mxn.register('google', { Mapstraction: { init: function(element,api) { var me = this; if (GMap2) { if (GBrowserIsCompatible()) { this.maps[api] = new GMap2(element); GEvent.addListener(this.maps[api], 'click', function(marker,location) { if ( marker && marker.mapstraction_marker ) { marker.mapstraction_marker.click.fire(); } else if ( location ) { me.click.fire({'location': new mxn.LatLonPoint(location.y, location.x)}); } // If the user puts their own Google markers directly on the map // then there is no location and this event should not fire. if ( location ) { me.clickHandler(location.y,location.x,location,me); } }); GEvent.addListener(this.maps[api], 'moveend', function() { me.moveendHandler(me); me.endPan.fire(); }); GEvent.addListener(this.maps[api], 'zoomend', function() { me.changeZoom.fire(); }); this.loaded[api] = true; me.load.fire(); } else { alert('browser not compatible with Google Maps'); } } else { alert(api + ' map script not imported'); } }, applyOptions: function(){ var map = this.maps[this.api]; if(this.options.enableScrollWheelZoom){ map.enableContinuousZoom(); map.enableScrollWheelZoom(); } if (this.options.enableDragging) { map.enableDragging(); } else { map.disableDragging(); } }, resizeTo: function(width, height){ this.currentElement.style.width = width; this.currentElement.style.height = height; this.maps[this.api].checkResize(); }, addControls: function( args ) { var map = this.maps[this.api]; // remove old controls if (this.controls) { while ((ctl = this.controls.pop())) { // Google specific method map.removeControl(ctl); } } else { this.controls = []; } c = this.controls; // Google has a combined zoom and pan control. if (args.zoom || args.pan) { if (args.zoom == 'large'){ this.addLargeControls(); } else { this.addSmallControls(); } } if (args.scale) { this.controls.unshift(new GScaleControl()); map.addControl(this.controls[0]); this.addControlsArgs.scale = true; } if (args.overview) { c.unshift(new GOverviewMapControl()); map.addControl(c[0]); this.addControlsArgs.overview = true; } if (args.map_type) { this.addMapTypeControls(); } }, addSmallControls: function() { var map = this.maps[this.api]; this.controls.unshift(new GSmallMapControl()); map.addControl(this.controls[0]); this.addControlsArgs.zoom = 'small'; this.addControlsArgs.pan = true; }, addLargeControls: function() { var map = this.maps[this.api]; this.controls.unshift(new GLargeMapControl()); map.addControl(this.controls[0]); this.addControlsArgs.zoom = 'large'; this.addControlsArgs.pan = true; }, addMapTypeControls: function() { var map = this.maps[this.api]; this.controls.unshift(new GMapTypeControl()); map.addControl(this.controls[0]); this.addControlsArgs.map_type = true; }, setCenterAndZoom: function(point, zoom) { var map = this.maps[this.api]; var pt = point.toProprietary(this.api); map.setCenter(pt, zoom); }, addMarker: function(marker, old) { var map = this.maps[this.api]; var gpin = marker.toProprietary(this.api); map.addOverlay(gpin); GEvent.addListener(gpin, 'infowindowopen', function() { marker.openInfoBubble.fire(); }); GEvent.addListener(gpin, 'infowindowclose', function() { marker.closeInfoBubble.fire(); }); return gpin; }, removeMarker: function(marker) { var map = this.maps[this.api]; map.removeOverlay(marker.proprietary_marker); }, removeAllMarkers: function() { var map = this.maps[this.api]; // FIXME: got a feeling this doesn't only delete markers map.clearOverlays(); }, declutterMarkers: function(opts) { throw 'Not implemented'; }, addPolyline: function(polyline, old) { var map = this.maps[this.api]; gpolyline = polyline.toProprietary(this.api); map.addOverlay(gpolyline); return gpolyline; }, removePolyline: function(polyline) { var map = this.maps[this.api]; map.removeOverlay(polyline.proprietary_polyline); }, getCenter: function() { var map = this.maps[this.api]; var pt = map.getCenter(); var point = new mxn.LatLonPoint(pt.lat(),pt.lng()); return point; }, setCenter: function(point, options) { var map = this.maps[this.api]; var pt = point.toProprietary(this.api); if(options && options.pan) { map.panTo(pt); } else { map.setCenter(pt); } }, setZoom: function(zoom) { var map = this.maps[this.api]; map.setZoom(zoom); }, getZoom: function() { var map = this.maps[this.api]; return map.getZoom(); }, getZoomLevelForBoundingBox: function( bbox ) { var map = this.maps[this.api]; // NE and SW points from the bounding box. var ne = bbox.getNorthEast(); var sw = bbox.getSouthWest(); var gbox = new GLatLngBounds( sw.toProprietary(this.api), ne.toProprietary(this.api) ); var zoom = map.getBoundsZoomLevel( gbox ); return zoom; }, setMapType: function(type) { var map = this.maps[this.api]; switch(type) { case mxn.Mapstraction.ROAD: map.setMapType(G_NORMAL_MAP); break; case mxn.Mapstraction.SATELLITE: map.setMapType(G_SATELLITE_MAP); break; case mxn.Mapstraction.HYBRID: map.setMapType(G_HYBRID_MAP); break; default: map.setMapType(type || G_NORMAL_MAP); } }, getMapType: function() { var map = this.maps[this.api]; var type = map.getCurrentMapType(); switch(type) { case G_NORMAL_MAP: return mxn.Mapstraction.ROAD; case G_SATELLITE_MAP: return mxn.Mapstraction.SATELLITE; case G_HYBRID_MAP: return mxn.Mapstraction.HYBRID; default: return null; } }, getBounds: function () { var map = this.maps[this.api]; var ne, sw, nw, se; var gbox = map.getBounds(); sw = gbox.getSouthWest(); ne = gbox.getNorthEast(); return new mxn.BoundingBox(sw.lat(), sw.lng(), ne.lat(), ne.lng()); }, setBounds: function(bounds){ var map = this.maps[this.api]; var sw = bounds.getSouthWest(); var ne = bounds.getNorthEast(); var gbounds = new GLatLngBounds(new GLatLng(sw.lat,sw.lon),new GLatLng(ne.lat,ne.lon)); map.setCenter(gbounds.getCenter(), map.getBoundsZoomLevel(gbounds)); }, addImageOverlay: function(id, src, opacity, west, south, east, north, oContext) { var map = this.maps[this.api]; map.getPane(G_MAP_MAP_PANE).appendChild(oContext.imgElm); this.setImageOpacity(id, opacity); this.setImagePosition(id); GEvent.bind(map, "zoomend", this, function() { this.setImagePosition(id); }); GEvent.bind(map, "moveend", this, function() { this.setImagePosition(id); }); }, setImagePosition: function(id, oContext) { var map = this.maps[this.api]; var topLeftPoint; var bottomRightPoint; topLeftPoint = map.fromLatLngToDivPixel( new GLatLng(oContext.latLng.top, oContext.latLng.left) ); bottomRightPoint = map.fromLatLngToDivPixel( new GLatLng(oContext.latLng.bottom, oContext.latLng.right) ); oContext.pixels.top = topLeftPoint.y; oContext.pixels.left = topLeftPoint.x; oContext.pixels.bottom = bottomRightPoint.y; oContext.pixels.right = bottomRightPoint.x; }, addOverlay: function(url, autoCenterAndZoom) { var map = this.maps[this.api]; var geoXML = new GGeoXml(url); map.addOverlay(geoXML, function() { if(autoCenterAndZoom) { geoXML.gotoDefaultViewport(map); } }); }, addTileLayer: function(tile_url, opacity, copyright_text, min_zoom, max_zoom, map_type) { var copyright = new GCopyright(1, new GLatLngBounds(new GLatLng(-90,-180), new GLatLng(90,180)), 0, "copyleft"); var copyrightCollection = new GCopyrightCollection(copyright_text); copyrightCollection.addCopyright(copyright); var tilelayers = []; tilelayers[0] = new GTileLayer(copyrightCollection, min_zoom, max_zoom); tilelayers[0].isPng = function() { return true; }; tilelayers[0].getOpacity = function() { return opacity; }; tilelayers[0].getTileUrl = function (a, b) { url = tile_url; url = url.replace(/\{Z\}/g,b); url = url.replace(/\{X\}/g,a.x); url = url.replace(/\{Y\}/g,a.y); return url; }; if(map_type) { var tileLayerOverlay = new GMapType(tilelayers, new GMercatorProjection(19), copyright_text, { errorMessage:"More "+copyright_text+" tiles coming soon" }); this.maps[this.api].addMapType(tileLayerOverlay); } else { tileLayerOverlay = new GTileLayerOverlay(tilelayers[0]); this.maps[this.api].addOverlay(tileLayerOverlay); } this.tileLayers.push( [tile_url, tileLayerOverlay, true] ); return tileLayerOverlay; }, toggleTileLayer: function(tile_url) { for (var f=0; f