/**
* @namespace WPGMZA
* @module Map
* @requires WPGMZA.EventDispatcher
*/
(function($) {
/**
* Constructor
* @param element to contain map
*/
WPGMZA.Map = function(element, options)
{
var self = this;
WPGMZA.assertInstanceOf(this, "Map");
WPGMZA.EventDispatcher.call(this);
if(!(element instanceof HTMLElement))
throw new Error("Argument must be a HTMLElement");
this.id = element.getAttribute("data-map-id");
if(!/\d+/.test(this.id))
throw new Error("Map ID must be an integer");
WPGMZA.maps.push(this);
this.element = element;
this.element.wpgmzaMap = this;
this.engineElement = element;
this.markers = [];
this.polygons = [];
this.polylines = [];
this.circles = [];
this.loadSettings();
}
WPGMZA.Map.prototype = Object.create(WPGMZA.EventDispatcher.prototype);
WPGMZA.Map.prototype.constructor = WPGMZA.Map;
WPGMZA.Map.getConstructor = function()
{
switch(WPGMZA.settings.engine)
{
case "google-maps":
if(WPGMZA.isProVersion())
return WPGMZA.GoogleProMap;
return WPGMZA.GoogleMap;
break;
default:
if(WPGMZA.isProVersion())
return WPGMZA.OLProMap;
return WPGMZA.OLMap;
break;
}
}
WPGMZA.Map.createInstance = function(element, options)
{
var constructor = WPGMZA.Map.getConstructor();
return new constructor(element, options);
}
/**
* Loads the maps settings and sets some defaults
* @return void
*/
WPGMZA.Map.prototype.loadSettings = function()
{
var settings = new WPGMZA.MapSettings(this.element);
this.settings = $.extend({}, WPGMZA.settings, settings);
}
/**
* Sets options in bulk on map
* @return void
*/
WPGMZA.Map.prototype.setOptions = function(options)
{
for(var name in options)
this.settings[name] = options[name];
}
/**
* Gets the distance between two latLngs in kilometers
* NB: Static function
* @return number
*/
var earthRadiusMeters = 6371;
var piTimes360 = Math.PI / 360;
function deg2rad(deg) {
return deg * (Math.PI/180)
};
/**
* This gets the distance in kilometers between two latitude / longitude points
* TODO: Move this to the distance class, or the LatLng class
* @return void
*/
WPGMZA.Map.getGeographicDistance = function(lat1, lon1, lat2, lon2)
{
var dLat = deg2rad(lat2-lat1);
var dLon = deg2rad(lon2-lon1);
var a =
Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
Math.sin(dLon/2) * Math.sin(dLon/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = earthRadiusMeters * c; // Distance in km
return d;
}
WPGMZA.Map.prototype.setCenter = function(latLng)
{
if(!("lat" in latLng && "lng" in latLng))
throw new Error("Argument is not an object with lat and lng");
}
/**
* Sets the dimensions of the map
* @return void
*/
WPGMZA.Map.prototype.setDimensions = function(width, height)
{
$(this.element).css({
width: width
});
$(this.engineElement).css({
width: "100%",
height: height
});
}
/**
* Adds the specified marker to this map
* @return void
*/
WPGMZA.Map.prototype.addMarker = function(marker)
{
if(!(marker instanceof WPGMZA.Marker))
throw new Error("Argument must be an instance of WPGMZA.Marker");
marker.map = this;
marker.parent = this;
this.markers.push(marker);
this.dispatchEvent({type: "markeradded", marker: marker});
marker.dispatchEvent({type: "added"});
}
/**
* Removes the specified marker from this map
* @return void
*/
WPGMZA.Map.prototype.removeMarker = function(marker)
{
if(!(marker instanceof WPGMZA.Marker))
throw new Error("Argument must be an instance of WPGMZA.Marker");
if(marker.map !== this)
throw new Error("Wrong map error");
marker.map = null;
marker.parent = null;
this.markers.splice(this.markers.indexOf(marker), 1);
this.dispatchEvent({type: "markerremoved", marker: marker});
marker.dispatchEvent({type: "removed"});
}
WPGMZA.Map.prototype.getMarkerByID = function(id)
{
for(var i = 0; i < this.markers.length; i++)
{
if(this.markers[i].id == id)
return this.markers[i];
}
return null;
}
WPGMZA.Map.prototype.removeMarkerByID = function(id)
{
var marker = this.getMarkerByID(id);
if(!marker)
return;
this.removeMarker(marker);
}
/**
* Adds the specified polygon to this map
* @return void
*/
WPGMZA.Map.prototype.addPolygon = function(polygon)
{
if(!(polygon instanceof WPGMZA.Polygon))
throw new Error("Argument must be an instance of WPGMZA.Polygon");
polygon.map = this;
this.polygons.push(polygon);
this.dispatchEvent({type: "polygonadded", polygon: polygon});
}
/**
* Removes the specified polygon from this map
* @return void
*/
WPGMZA.Map.prototype.deletePolygon = function(polygon)
{
if(!(polygon instanceof WPGMZA.Polygon))
throw new Error("Argument must be an instance of WPGMZA.Polygon");
if(polygon.map !== this)
throw new Error("Wrong map error");
polygon.map = null;
this.polygons.splice(this.polygons.indexOf(polygon), 1);
this.dispatchEvent({type: "polygonremoved", polygon: polygon});
}
WPGMZA.Map.prototype.getPolygonByID = function(id)
{
for(var i = 0; i < this.polygons.length; i++)
{
if(this.polygons[i].id == id)
return this.polygons[i];
}
return null;
}
WPGMZA.Map.prototype.deletePolygonByID = function(id)
{
var polygon = this.getPolygonByID(id);
if(!polygon)
return;
this.deletePolygon(polygon);
}
/**
* Gets a polyline by ID
* @return void
*/
WPGMZA.Map.prototype.getPolylineByID = function(id)
{
for(var i = 0; i < this.polylines.length; i++)
{
if(this.polylines[i].id == id)
return this.polylines[i];
}
return null;
}
/**
* Adds the specified polyline to this map
* @return void
*/
WPGMZA.Map.prototype.addPolyline = function(polyline)
{
if(!(polyline instanceof WPGMZA.Polyline))
throw new Error("Argument must be an instance of WPGMZA.Polyline");
polyline.map = this;
this.polylines.push(polyline);
this.dispatchEvent({type: "polylineadded", polyline: polyline});
}
/**
* Removes the specified polyline from this map
* @return void
*/
WPGMZA.Map.prototype.deletePolyline = function(polyline)
{
if(!(polyline instanceof WPGMZA.Polyline))
throw new Error("Argument must be an instance of WPGMZA.Polyline");
if(polyline.map !== this)
throw new Error("Wrong map error");
polyline.map = null;
this.polylines.splice(this.polylines.indexOf(polyline), 1);
this.dispatchEvent({type: "polylineremoved", polyline: polyline});
}
WPGMZA.Map.prototype.getPolylineByID = function(id)
{
for(var i = 0; i < this.polylines.length; i++)
{
if(this.polylines[i].id == id)
return this.polylines[i];
}
return null;
}
WPGMZA.Map.prototype.deletePolylineByID = function(id)
{
var polyline = this.getPolylineByID(id);
if(!polyline)
return;
this.deletePolyline(polyline);
}
/**
* Adds the specified circle to this map
* @return void
*/
WPGMZA.Map.prototype.addCircle = function(circle)
{
if(!(circle instanceof WPGMZA.Circle))
throw new Error("Argument must be an instance of WPGMZA.Circle");
circle.map = this;
this.circles.push(circle);
this.dispatchEvent({type: "circleadded", circle: circle});
}
/**
* Removes the specified circle from this map
* @return void
*/
WPGMZA.Map.prototype.removeCircle = function(circle)
{
if(!(circle instanceof WPGMZA.Circle))
throw new Error("Argument must be an instance of WPGMZA.Circle");
if(circle.map !== this)
throw new Error("Wrong map error");
circle.map = null;
this.circles.splice(this.circles.indexOf(circle), 1);
this.dispatchEvent({type: "circleremoved", circle: circle});
}
WPGMZA.Map.prototype.getCircleByID = function(id)
{
for(var i = 0; i < this.circles.length; i++)
{
if(this.circles[i].id == id)
return this.circles[i];
}
return null;
}
WPGMZA.Map.prototype.deleteCircleByID = function(id)
{
var circle = this.getCircleByID(id);
if(!circle)
return;
this.deleteCircle(circle);
}
/**
* Nudges the map viewport by the given pixel coordinates
* @return void
*/
WPGMZA.Map.prototype.nudge = function(x, y)
{
var pixels = this.latLngToPixels(this.getCenter());
pixels.x += parseFloat(x);
pixels.y += parseFloat(y);
if(isNaN(pixels.x) || isNaN(pixels.y))
throw new Error("Invalid coordinates supplied");
var latLng = this.pixelsToLatLng(pixels);
this.setCenter(latLng);
}
/**
* Triggered when the window resizes
* @return void
*/
WPGMZA.Map.prototype.onWindowResize = function(event)
{
}
/**
* Listener for when the engine map div is resized
* @return void
*/
WPGMZA.Map.prototype.onElementResized = function(event)
{
}
WPGMZA.Map.prototype.onBoundsChanged = function(event)
{
// Native events
this.trigger("boundschanged");
$(this.element).trigger("boundschanged.wpgmza");
// Google / legacy compatibility events
this.trigger("bounds_changed");
$(this.element).trigger("bounds_changed");
}
WPGMZA.Map.prototype.onIdle = function(event)
{
$(this.element).trigger("idle");
$(this.element).trigger("idle.wpgmza");
}
/*$(document).ready(function() {
function createMaps()
{
// TODO: Test that this works for maps off screen (which borks google)
$(".wpgmza-map").each(function(index, el) {
if(!el.wpgmzaMap)
{
WPGMZA.runCatchableTask(function() {
WPGMZA.Map.createInstance(el);
}, el);
}
});
}
createMaps();
// Call again each second to load AJAX maps
setInterval(createMaps, 1000);
});*/
})(jQuery);