/**
* @class
* Manages {lucid.maps.limbs.Limb}s for a set of markers.
* This class will create the google.maps.Marker instance on the map as well as the associated LIMB.
* An info-box can optionally be associated with the factory, which displays information about the marker.
*
* @constructor
* @param {lucid.maps.limbs.LimbMarkerFactoryOptions} options The factory options.
*/
lucid.maps.limbs.LimbMarkerFactory = function( options )
{
var markers;
var limbs;
// This initialise function is called at the end of the constructor.
function init()
{
var defaultLimbOptions = (typeof options.limbOptions !== "undefined") ? options.limbOptions : {};
markers = [];
limbs = new lucid.maps.limbs.LimbFactory( options.map, defaultLimbOptions );
}
/**
* Remove all markers and LIMBs created by this manager.
*/
this.removeAll = function()
{
for (var i=0; i<markers.length; i++)
{
if (typeof options.infoBox !== "undefined")
options.infoBox.remove( markers[i] );
markers[i].setMap( null );
markers[i] = null;
}
markers = [];
limbs.destroyAll();
};
/**
* Add a new marker and a LIMB to the map.
* The map instance and label styling are set in the options passed into the manager's constructor.
*
* @param {google.maps.LatLng} position The location to be marked.
* @param {string} title The name/title of the location. Used as the title of the marker created on the map.
* @return {lucid.maps.limbs.Limb} The limb that has been created.
*/
this.add = function( position, title )
{
var customMarkerOptions = { position: position,
title: title };
var customLimbOptions = {};
return this.addCustomised( customMarkerOptions, customLimbOptions );
};
/**
* Add a new marker and a LIMB to the map.
* NB: The map and label styling are set in the options passed into the manager's constructor.
*
* @param {google.maps.MarkerOptions} customisedMarkerOptions Selected settings of the marker to be overriden from the options passed into the constructor.
* @param {lucid.maps.limbs.LimbOptions} customisedLimbOptions Selected settings of the LIMB to be overriden from the options passed into the constructor.
* @return {lucid.maps.limbs.Limb} The limb that has been created.
*/
this.addCustomised = function( customisedMarkerOptions, customisedLimbOptions )
{
// Create the marker, taking into account the default marker options set into this instance
// and the custom marker options in the function call.
var markerOptions = {};
lucid.maps.limbs.applyMarkerOptions( markerOptions, options.markerOptions );
lucid.maps.limbs.applyMarkerOptions( markerOptions, customisedMarkerOptions );
markerOptions.map = options.map;
var marker = new google.maps.Marker( markerOptions );
if (typeof options.infoBox !== "undefined")
{
options.infoBox.add( marker );
}
if (typeof markerOptions.clickHandlerFactory === "function")
{
google.maps.event.addListener( marker, "click", markerOptions.clickHandlerFactory( marker ) );
}
markers[markers.length] = marker;
customisedLimbOptions.target = marker;
return limbs.create( customisedLimbOptions );
};
/**
* Zoom and pan the map so that all markers are in view.
* You can optionally specify additional locations to be included in the map view by setting LatLng in the options parameter.
*
* @param {object} zoomOptions
* @param {google.maps.LatLng[]} [zoomOptions.additionalLocations] Locations, in addition to the markers, which should be kept in view when the map view is changed.
*/
this.zoomToAll = function( zoomOptions )
{
var locations = [];
for (var i=0; i<markers.length; i++)
{
locations[locations.length] = markers[i].getPosition();
}
if (zoomOptions.additionalLocations)
{
for (var i=0; i<zoomOptions.additionalLocations.length; i++)
{
locations[locations.length] = zoomOptions.additionalLocations[i];
}
}
if (locations.length > 0)
{
var bounds = new google.maps.LatLngBounds( locations[0], locations[0] );
for (var i=0; i<locations.length; i++)
{
bounds = bounds.extend( locations[i] );
}
options.map.fitBounds( bounds );
}
};
/**
* Temporarily hide the labels.
* This does not remove the LIMBs and markers, it just takes them off display.
* Call this if you hide the map element.
*/
this.hide = function()
{
limbs.hide();
// NB: The markers are part of the map and should be hidden by hiding the map element.
};
/**
* Re-display the labels after being hidden with a call to 'hide'.
*/
this.show = function()
{
limbs.show();
// NB: The markers are part of the map and should be shown by showing the map element.
};
/**
* Destroy this instance and any associated resources.
* This method should be called when the instance is no longer required.
*/
this.destroy = function()
{
this.removeAll();
};
/**
* @return {number} The total number of places being labelled (includes any labels currently being hidden).
*/
this.getNumberOfMarkers = function()
{
return markers.length;
};
init();
};
/**
* @type {object}
* @property {google.maps.Map} map The map the markers and LIMBs are to be associated with.
* @property {google.maps.MarkerOptions} markerOptions The settings for the marker shown on the map for these labels.
* The LimbMarkerFactory will ignore the position property. This will be set when the places are added with a call to addPlaces.
* @property {lucid.maps.limbs.LimbOptions} [limbOptions] The settings for the LIMB shown on the map for these labels.
* The LimbMarkerFactory will ignore the marker property. This will be set to the place's marker.
* The LimbMarkerFactory will ignore the independent property. This will always be false.
* If undefined the LIMB will take its styling from the marker.
* @property {lucid.maps.limbs.InfoBox} [infoBox] The class that displays an info box when the user clicks on the label.
* Leave undefined if no info box should appear.
*/
lucid.maps.limbs.LimbMarkerFactoryOptions = {};
/**
* Copy google.maps.MarkerOptions from one instance to another.
* Only the settings defined in the 'optionsToApply' object will be copied onto the 'options' object.
*
* @param {google.maps.MarkerOptions} options The target instance.
* @param {google.maps.MarkerOptions} optionsToApply Options that take precedence and should be copied into the target object.
*/
lucid.maps.limbs.applyMarkerOptions = function( options, optionsToApply )
{
if (typeof optionsToApply.anchorPoint !== "undefined")
options.anchorPoint = optionsToApply.anchorPoint;
if (typeof optionsToApply.animation !== "undefined")
options.animation = optionsToApply.animation;
if (typeof optionsToApply.clickable !== "undefined")
options.clickable = optionsToApply.clickable;
if (typeof optionsToApply.crossOnDrag !== "undefined")
options.crossOnDrag = optionsToApply.crossOnDrag;
if (typeof optionsToApply.cursor !== "undefined")
options.cursor = optionsToApply.cursor;
if (typeof optionsToApply.draggable !== "undefined")
options.draggable = optionsToApply.draggable;
if (typeof optionsToApply.flat !== "undefined")
options.flat = optionsToApply.flat;
if (typeof optionsToApply.icon !== "undefined")
options.icon = optionsToApply.icon;
if (typeof optionsToApply.map !== "undefined")
options.map = optionsToApply.map;
if (typeof optionsToApply.optimized !== "undefined")
options.optimized = optionsToApply.optimized;
if (typeof optionsToApply.position !== "undefined")
options.position = optionsToApply.position;
if (typeof optionsToApply.raiseOnDrag !== "undefined")
options.raiseOnDrag = optionsToApply.raiseOnDrag;
if (typeof optionsToApply.shadow !== "undefined")
options.shadow = optionsToApply.shadow;
if (typeof optionsToApply.shape !== "undefined")
options.shape = optionsToApply.shape;
if (typeof optionsToApply.title !== "undefined")
options.title = optionsToApply.title;
if (typeof optionsToApply.visible !== "undefined")
options.visible = optionsToApply.visible;
if (typeof optionsToApply.zIndex !== "undefined")
options.zIndex = optionsToApply.zIndex;
if (typeof optionsToApply.clickHandlerFactory !== "undefined")
options.clickHandlerFactory = optionsToApply.clickHandlerFactory;
};
/* TODO Move these 'apply' functions into a separate JS file. */
/**
* Copy google.maps.DirectionsRequest from one instance to another.
* Only the settings defined in the 'optionsToApply' object will be copied onto the 'options' object.
*
* @param {google.maps.DirectionsRequest} options The target instance.
* @param {google.maps.DirectionsRequest} optionsToApply Options that take precedence and should be copied into the target object.
*/
lucid.maps.limbs.applyDirectionsOptions = function( options, optionsToApply )
{
if (typeof optionsToApply.avoidHighways !== "undefined")
options.avoidHighways = optionsToApply.avoidHighways;
if (typeof optionsToApply.avoidTolls !== "undefined")
options.avoidTolls = optionsToApply.avoidTolls;
if (typeof optionsToApply.destination !== "undefined")
options.destination = optionsToApply.destination;
if (typeof optionsToApply.durationInTraffic !== "undefined")
options.durationInTraffic = optionsToApply.durationInTraffic;
if (typeof optionsToApply.optimizeWaypoints !== "undefined")
options.optimizeWaypoints = optionsToApply.optimizeWaypoints;
if (typeof optionsToApply.origin !== "undefined")
options.origin = optionsToApply.origin;
if (typeof optionsToApply.provideRouteAlternatives !== "undefined")
options.provideRouteAlternatives = optionsToApply.provideRouteAlternatives;
if (typeof optionsToApply.region !== "undefined")
options.region = optionsToApply.region;
if (typeof optionsToApply.transitOptions !== "undefined")
options.transitOptions = optionsToApply.transitOptions;
if (typeof optionsToApply.travelMode !== "undefined")
options.travelMode = optionsToApply.travelMode;
if (typeof optionsToApply.unitSystem !== "undefined")
options.unitSystem = optionsToApply.unitSystem;
if (typeof optionsToApply.waypoints !== "undefined")
options.waypoints = optionsToApply.waypoints;
};