/**
* @namespace WPGMZA
* @module GoogleMap
* @requires WPGMZA.Map
* @pro-requires WPGMZA.ProMap
*/
(function($) {
var Parent;
/**
* Constructor
* @param element to contain the map
*/
WPGMZA.GoogleMap = function(element, options)
{
var self = this;
if(!window.google)
throw new Error("Google API not loaded - " + wpgmza_api_not_enqueued_reason);
Parent.call(this, element, options);
this.loadGoogleMap();
if(options)
this.setOptions(options);
google.maps.event.addListener(this.googleMap, "click", function(event) {
self.dispatchEvent("click");
});
google.maps.event.addListener(this.googleMap, "rightclick", function(event) {
var wpgmzaEvent = new WPGMZA.Event("rightclick");
wpgmzaEvent.latLng = {
lat: event.latLng.lat(),
lng: event.latLng.lng()
};
self.dispatchEvent(wpgmzaEvent);
});
google.maps.event.addListener(this.googleMap, "dragend", function(event) {
self.dispatchEvent("dragend");
});
google.maps.event.addListener(this.googleMap, "zoom_changed", function(event) {
self.dispatchEvent("zoom_changed");
self.dispatchEvent("zoomchanged");
});
// Idle event
google.maps.event.addListener(this.googleMap, "idle", function(event) {
self.onIdle(event);
});
// Dispatch event
if(!WPGMZA.isProVersion())
{
this.dispatchEvent("created");
WPGMZA.events.dispatchEvent({type: "mapcreated", map: this});
}
}
// If we're running the Pro version, inherit from ProMap, otherwise, inherit from Map
if(WPGMZA.isProVersion())
{
Parent = WPGMZA.ProMap;
WPGMZA.GoogleMap.prototype = Object.create(WPGMZA.ProMap.prototype);
}
else
{
Parent = WPGMZA.Map;
WPGMZA.GoogleMap.prototype = Object.create(WPGMZA.Map.prototype);
}
WPGMZA.GoogleMap.prototype.constructor = WPGMZA.GoogleMap;
/**
* Creates the Google Maps map
* @return void
*/
WPGMZA.GoogleMap.prototype.loadGoogleMap = function()
{
var self = this;
var options = this.settings.toGoogleMapsOptions();
this.googleMap = new google.maps.Map(this.engineElement, options);
google.maps.event.addListener(this.googleMap, "bounds_changed", function() {
self.onBoundsChanged();
});
if(this.settings.bicycle)
this.enableBicycleLayer(true);
if(this.settings.traffic)
this.enableTrafficLayer(true);
if(this.settings.transport)
this.enablePublicTransportLayer(true);
this.showPointsOfInterest(this.settings.show_points_of_interest);
// Move the loading wheel into the map element (it has to live outside in the HTML file because it'll be overwritten by Google otherwise)
$(this.engineElement).append($(this.element).find(".wpgmza-loader"));
}
WPGMZA.GoogleMap.prototype.setOptions = function(options)
{
Parent.prototype.setOptions.call(this, options);
this.googleMap.setOptions(this.settings.toGoogleMapsOptions());
var clone = $.extend({}, options);
if(clone.center instanceof WPGMZA.LatLng || typeof clone.center == "object")
clone.center = {
lat: parseFloat(clone.center.lat),
lng: parseFloat(clone.center.lng)
};
this.googleMap.setOptions(clone);
}
/**
* Adds the specified marker to this map
* @return void
*/
WPGMZA.GoogleMap.prototype.addMarker = function(marker)
{
marker.googleMarker.setMap(this.googleMap);
Parent.prototype.addMarker.call(this, marker);
}
/**
* Removes the specified marker from this map
* @return void
*/
WPGMZA.GoogleMap.prototype.removeMarker = function(marker)
{
marker.googleMarker.setMap(null);
Parent.prototype.removeMarker.call(this, marker);
}
/**
* Adds the specified polygon to this map
* @return void
*/
WPGMZA.GoogleMap.prototype.addPolygon = function(polygon)
{
polygon.googlePolygon.setMap(this.googleMap);
Parent.prototype.addPolygon.call(this, polygon);
}
/**
* Removes the specified polygon from this map
* @return void
*/
WPGMZA.GoogleMap.prototype.removePolygon = function(polygon)
{
polygon.googlePolygon.setMap(null);
Parent.prototype.removePolygon.call(this, polygon);
}
/**
* Adds the specified polyline to this map
* @return void
*/
WPGMZA.GoogleMap.prototype.addPolyline = function(polyline)
{
polyline.googlePolyline.setMap(this.googleMap);
Parent.prototype.addPolyline.call(this, polyline);
}
/**
* Removes the specified polygon from this map
* @return void
*/
WPGMZA.GoogleMap.prototype.removePolyline = function(polyline)
{
polyline.googlePolyline.setMap(null);
Parent.prototype.removePolyline.call(this, polyline);
}
WPGMZA.GoogleMap.prototype.addCircle = function(circle)
{
circle.googleCircle.setMap(this.googleMap);
Parent.prototype.addCircle.call(this, circle);
}
WPGMZA.GoogleMap.prototype.removeCircle = function(circle)
{
circle.googleCircle.setMap(null);
Parent.prototype.removeCircle.call(this, circle);
}
/**
* Delegate for google maps getCenter
* @return void
*/
WPGMZA.GoogleMap.prototype.getCenter = function()
{
var latLng = this.googleMap.getCenter();
return {
lat: latLng.lat(),
lng: latLng.lng()
};
}
/**
* Delegate for google maps setCenter
* @return void
*/
WPGMZA.GoogleMap.prototype.setCenter = function(latLng)
{
WPGMZA.Map.prototype.setCenter.call(this, latLng);
if(latLng instanceof WPGMZA.LatLng)
this.googleMap.setCenter({
lat: latLng.lat,
lng: latLng.lng
});
else
this.googleMap.setCenter(latLng);
}
/**
* Delegate for google maps setPan
* @return void
*/
WPGMZA.GoogleMap.prototype.panTo = function(latLng)
{
if(latLng instanceof WPGMZA.LatLng)
this.googleMap.panTo({
lat: latLng.lat,
lng: latLng.lng
});
else
this.googleMap.panTo(latLng);
}
/**
* Delegate for google maps getCenter
* @return void
*/
WPGMZA.GoogleMap.prototype.getZoom = function()
{
return this.googleMap.getZoom();
}
/**
* Delegate for google maps getZoom
* @return void
*/
WPGMZA.GoogleMap.prototype.setZoom = function(value)
{
return this.googleMap.setZoom(value);
}
/**
* Gets the bounds
* @return object
*/
WPGMZA.GoogleMap.prototype.getBounds = function()
{
var bounds = this.googleMap.getBounds();
var northEast = bounds.getNorthEast();
var southWest = bounds.getSouthWest();
return {
topLeft: {
lat: northEast.lat(),
lng: southWest.lng()
},
bottomRight: {
lat: southWest.lat(),
lng: northEast.lng()
}
};
}
/**
* Fit to given boundaries
* @return void
*/
WPGMZA.GoogleMap.prototype.fitBounds = function(southWest, northEast)
{
if(southWest instanceof WPGMZA.LatLng)
southWest = {lat: southWest.lat, lng: southWest.lng};
if(northEast instanceof WPGMZA.LatLng)
northEast = {lat: northEast.lat, lng: northEast.lng};
this.googleMap.fitBounds(southWest, northEast);
}
/**
* Fit the map boundaries to visible markers
* @return void
*/
WPGMZA.GoogleMap.prototype.fitBoundsToVisibleMarkers = function()
{
var bounds = new google.maps.LatLngBounds();
for(var i = 0; i < this.markers.length; i++)
{
if(markers[i].getVisible())
bounds.extend(markers[i].getPosition());
}
this.googleMap.fitBounds(bounds);
}
/**
* Enables / disables the bicycle layer
* @param enable boolean, enable or not
* @return void
*/
WPGMZA.GoogleMap.prototype.enableBicycleLayer = function(enable)
{
if(!this.bicycleLayer)
this.bicycleLayer = new google.maps.BicyclingLayer();
this.bicycleLayer.setMap(
enable ? this.googleMap : null
);
}
/**
* Enables / disables the bicycle layer
* @param enable boolean, enable or not
* @return void
*/
WPGMZA.GoogleMap.prototype.enableTrafficLayer = function(enable)
{
if(!this.trafficLayer)
this.trafficLayer = new google.maps.TrafficLayer();
this.trafficLayer.setMap(
enable ? this.googleMap : null
);
}
/**
* Enables / disables the bicycle layer
* @param enable boolean, enable or not
* @return void
*/
WPGMZA.GoogleMap.prototype.enablePublicTransportLayer = function(enable)
{
if(!this.publicTransportLayer)
this.publicTransportLayer = new google.maps.TransitLayer();
this.publicTransportLayer.setMap(
enable ? this.googleMap : null
);
}
/**
* Shows / hides points of interest
* @param show boolean, enable or not
* @return void
*/
WPGMZA.GoogleMap.prototype.showPointsOfInterest = function(show)
{
// TODO: This will bug the front end because there is textarea with theme data
var text = $("textarea[name='theme_data']").val();
if(!text)
return;
var styles = JSON.parse(text);
styles.push({
featureType: "poi",
stylers: [
{
visibility: (show ? "on" : "off")
}
]
});
this.googleMap.setOptions({styles: styles});
}
/**
* Gets the min zoom of the map
* @return int
*/
WPGMZA.GoogleMap.prototype.getMinZoom = function()
{
return parseInt(this.settings.min_zoom);
}
/**
* Sets the min zoom of the map
* @return void
*/
WPGMZA.GoogleMap.prototype.setMinZoom = function(value)
{
this.googleMap.setOptions({
minZoom: value,
maxZoom: this.getMaxZoom()
});
}
/**
* Gets the min zoom of the map
* @return int
*/
WPGMZA.GoogleMap.prototype.getMaxZoom = function()
{
return parseInt(this.settings.max_zoom);
}
/**
* Sets the min zoom of the map
* @return void
*/
WPGMZA.GoogleMap.prototype.setMaxZoom = function(value)
{
this.googleMap.setOptions({
minZoom: this.getMinZoom(),
maxZoom: value
});
}
WPGMZA.GoogleMap.prototype.latLngToPixels = function(latLng)
{
var map = this.googleMap;
var nativeLatLng = new google.maps.LatLng({
lat: parseFloat(latLng.lat),
lng: parseFloat(latLng.lng)
});
var topRight = map.getProjection().fromLatLngToPoint(map.getBounds().getNorthEast());
var bottomLeft = map.getProjection().fromLatLngToPoint(map.getBounds().getSouthWest());
var scale = Math.pow(2, map.getZoom());
var worldPoint = map.getProjection().fromLatLngToPoint(nativeLatLng);
return {
x: (worldPoint.x - bottomLeft.x) * scale,
y: (worldPoint.y - topRight.y) * scale
};
}
WPGMZA.GoogleMap.prototype.pixelsToLatLng = function(x, y)
{
if(y == undefined)
{
if("x" in x && "y" in x)
{
y = x.y;
x = x.x;
}
else
console.warn("Y coordinate undefined in pixelsToLatLng (did you mean to pass 2 arguments?)");
}
var map = this.googleMap;
var topRight = map.getProjection().fromLatLngToPoint(map.getBounds().getNorthEast());
var bottomLeft = map.getProjection().fromLatLngToPoint(map.getBounds().getSouthWest());
var scale = Math.pow(2, map.getZoom());
var worldPoint = new google.maps.Point(x / scale + bottomLeft.x, y / scale + topRight.y);
var latLng = map.getProjection().fromPointToLatLng(worldPoint);
return {
lat: latLng.lat(),
lng: latLng.lng()
};
}
/**
* Handle the map element resizing
* @return void
*/
WPGMZA.GoogleMap.prototype.onElementResized = function(event)
{
if(!this.googleMap)
return;
google.maps.event.trigger(this.googleMap, "resize");
}
})(jQuery);