Google Maps Hacking and Bookmarklets

Update: New version maps.6.js. Breaks at least onMapStateChanged handlers, now expects a function rather than an object—affects lat/long bookmarklet.

Update: There looks like a new version of Google Maps (maps.4.js—make that maps.5.js, someone's been busy--check out Part 13 for some rampant speculation :-) ) is on the scene. I haven't looked at what's changed—I've been too busy with the unauthorised Google Maps Standalone Mode.

Update:The latest version of Google Maps (maps.3.js) requires http://libgmail.sf.net/loadxml-0.0.4.js or later. The route following bookmarklets have not yet been updated to work with the latest Google Maps version.

Ah, the lure of all things Google...

I've been poking around in Google Maps
and had some success I thought others might be able to build on. I've
put this in a couple of places but thought I'd throw it here as well:

Part 1 : XML Handling

Okay, I've been playing around with sending requests to Gmaps via a Python proxy and manipulating the files returned on the fly.

If you save this book marklet and click on it when on any
(?--certainly the home page) Gmaps page it should move you to a
location in Vancouver, Canada.

By changing various values you can do some more
experimenting... For example, I have successfully added another
"location" tag with an id "B" and new coordinates. Also I changed the
marker image to be a random png from the Google site--but discovered
the image dimensions seem to be hard coded so it was distorted.

This should allow specifying things like a pan from one place to
another, and adding additional markers, via Javascript bookmarklets.
This approach is probably more practical than intercepting the XML/JS
retrieved from the server (which is still possible & could be
interesting).

It works best when you've zoomed in pretty closely. It has no error
checking so ensure you have actually got directions currently listed.
It takes no notice of the zoom level nor how many points there are in
the route, so it could take a long time if the route is long. Obviously
there are improvements that can be made along those lines.

I've tested this under FireFox 1.0 on Mac OS X, I'd be interested to know if it works successfully elsewhere.

This provides an example of how to create totally custom and arbitrarily placed markers--this could be used to highlight locations of interest along the route, for example, or display a UFO or armies of attacking mutants--or something. (Hmmm, the SimCity idea is starting to look possible--where's Godzilla when you need him? Hmmm, animated storys on Google Maps? :-) )

At present the existing shadow is used. Still need to investigate changing image size.

When prompted for the file to inject, enter: http://libgmail.sf.net/routefollow-0.0.1.jsNote: When you do this, you are allowing your browser to run completely arbitrary code in a context where it has more control over your browser than usual--specifically, it will run as if it was loaded from the current page. Make sure you understand the implications of this before you use the above bookmarklet.

You should now see "Go" and "Stop" links in the yellow bar near the top of the Google Maps page.

I have extended this technique to allow an automatically updating clock (with the data retrieved from a non-Google URL) proof-of-concept which lays the groundwork for some interesting possibilities...

Update: Okay, here's a much nicer implementation of the injection code that doesn't require the timeout hack. It relies on using a "load" event triggered when the inserted script element has loaded--handy really: (Inject External File Bookmarklet 2)

Part 6 : Big Brother is listening

The following bookmark hooks into the "state listener" functionality Gmaps helpfully provides in order to update a Lat/Long display whenever the map is moved (it does not rely on polling): (LatLong Autoupdate Bookmarklet)

Part 7 : Arbitrary XML upload via GUI

There's currently a few alternative approachs to this about (that'll teach me not to release early and often! :-) ) but here's my cross-browser UI-based implementation of loading an arbitrary Google Maps format XML file into Google Maps.

Using the "Inject External File Bookmarklet" from above (and after reading the associated warning) inject the following:

This will add a text input box and "Upload" button. Supply any URL pointing to an XML file in the Google Maps format and it will use it. (There's a ten second delay before display at present to allow for retrieval time, which is rough but hopefully does the job until I improve it.)

Of course, I don't really know squat about XSL so I'm sure more impressive things are possible...

How's it done? Well, I essentially implemented an extended XmlHttpRequest object that allows off-domain file retrieval and got Gmaps to use that instead of the normal one. (I just hand off same-domain calls to the usual object and use script tag injection to handle the off-domain calls.)

The code's a mess but it works for me under Firefox. There's some XML parsing code I found somewhere which probably won't work under IE at the moment.

Part 9 : Real time information display

This is the beginning of an investigation into display of (near) real time information on Google Maps with the addition of custom content and appearance.

(The source page updates every 60 seconds, we don't currently auto-upload, so you have to do that manually.)

The information used for this research is from the Seattle Fire Department's Real Time 911 information page. A script parse911.cgi retrieves the page on request then currently performs a Google Maps search on the first ten (most recent) locations listed and aggregates the results. It also trys to locate the viewing area so all markers can be seen at once--this isn't perfect at the moment, however. It seems the data retrieved for any particular location is not always accurate, so bear that in mind if you think you see your dog's house burning down.

There's additional information available at the site such as the incident type, and the number and type of vehicles present--which suggests some interesting possibilities... :-)

Update: Upload http://stuff.rancidbacon.com/parse911-0.2.0.cgi to see both custom XML and XSL files in action (still requires a manual refresh at present). Also, see the end of Part 11 for a tip for helping with custom XSL development.

Part 10 : Google Maps Classes and Functions Reference

Part 11 : Beta be more robust

The recent change to maps.3.js broke a few pieces of code on this page so I've been thinking of how to make things a bit more robust. For reasons of compression and/or obfuscation Gmaps mostly uses one or two letter identifiers for functions, classes and variables in its JavaScript code. In order to make these hacks more robust against code changes I've developed a utility function to determine the current identifier for a particular function or class.

By adapting the technique used to update the generation of the Classes and Functions Reference in Part 10 we seek to identify a unique signature for a desired function or class and use that rather than the actual identifier used in any specific code version. This is all enabled by JavaScript's introspection capabilities.

Consider the XmlHttpRequestFactory whose create method needs to be replaced to enable off-domain file retrieval. In maps.2.js it was called Yd but it is known more colloquially as cg in maps.3.js:

By comparing the two versions and other definitions in the scripts we can determine that if we have a function declaration with a create method that in turn contains the text XMLHttpRequest we can be reasonably certain it refers to XmlHttpRequestFactory. All we need is a helper to find it for us automatically. Hey, here's one now (this example is from http://libgmail.sf.net/loadxml-0.0.5.js):

In general the first argument will be "function" or "object", the second argument will be a method name or blank if the target is only a function and the third argument will be a code snippet. This approach is probably too verbose for bookmarks--even when compressed--but it seems viable for longer scripts.

Tip: The object referred to by _Xslt includes a cache for the XSL style-sheets used to format the pop-up and side panels. The caching functionality can be unwanted when developing or debugging style-sheets so use the following to clear the cache and force a reload from the URL:

_Xslt.cache_ = new Object()

Introspection references

For details on how functions are part of the global JavaScript namespace and this can be accessed as an array to retrieve the definitions consult these JavaScript introspection references:

Oh yeah, I just have to say again: the JavaScript Shell Bookmarklet is fantastic.

Part 12 : Whoops, how did that happen..?

Okay, this is just a screenshot at the moment, but here it is:

The above is a screenshot of a web page with an iframe that contains a page from another domain which is showing a totally interactive Gmaps view with custom data and stylesheets. This is a proof-of-concept for a "service" that could be supplied the URL of a data file and style-sheet and display the interactive map.

There are no bookmarklets or other browser hacks involved and the original Gmaps maps.3.js Javascript file is used unmodified.

Part 13 : An unofficial official Gmaps API?

I've just noticed something kinda interesting in the last two updates (4 & 5) to the Google Maps Javascript files (maps.X.js) and thought I'd indulge in some idle speculation. (Incidentally, it appears the "Local" search option uses a different Javascript file http://www.google.com/mapfiles/maps.local.1.js.)