Source: maps/limbs/LimbFactory.js


/**
 * @class
 * A factory class for generating LIMBs.
 * This class provides a slight performance gain by refreshing multiple LIMBs within a single event handler when the map moves.
 * This also provides convenience methods for hiding/showing LIMBs as and when the map is hidden or shown.
 * 
 * @constructor
 * @param {google.maps.Map} map  The map that is displaying the LIMBs.
 * @param {lucid.maps.limbs.LimbOptions} [defaultOptions]  Default settings for each LIMB being created by this factory.
 */
lucid.maps.limbs.LimbFactory = function( map, defaultOptions )
{
	var limbs;
	var hidden;
	
	
	// This initialise function is called at the end of the constructor.
	function init()
	{
		limbs = [];
		hidden = false;
		
		google.maps.event.addListener( map, "bounds_changed", handleMapMove );
	}
	
	/* NOTE:
		Desktop browsers trigger the "bounds_changed" event while the map is being panned.
		Mobile browsers wait until the pan is complete. This makes the LIMBs 'sticky'.
		A continuous refresh (using an interval) was trialled but map.getBounds function
		always returns the bounds from when the drag started, not it's current location.
	 */
	
	
	function handleMapMove()
	{
		refresh();
	}
	
	function refresh()
	{
		//var startTimestamp = new Date();
		
		var layout = ( (typeof defaultOptions !== "undefined") && (typeof defaultOptions.layout !== "undefined") )? defaultOptions.layout : null;
		
		if (layout)
			layout.init();
		
		for (var i=0; i<limbs.length; i++)
		{
			limbs[i].refresh();
		}
		
		if (layout)
			layout.complete();
		
		//var duration = new Date().getTime() - startTimestamp.getTime();
		//console.log( "No layout took " + duration + "ms" );
	}
	
	/**
	 * Get this factory to manage a LIMB.
	 * The LIMB should have its "independent" property set to false.
	 * If you don't have an instance of a LIMB, use the create method to create and add a new LIMB object.
	 * 
	 * @param {lucid.maps.limbs.Limb} limb  The LIMB to be managed by this factory.
	 */
	this.add = function( limb )
	{
		limbs[limbs.length] = limb;
	};
	
	/**
	 * Create a new LIMB and manage it.
	 * 
	 * @param {lucid.maps.limbs.LimbOptions|google.maps.Marker} markerOrOptions  Settings for the LIMB to be created. These settings will override the defaultOptions passed into the constructor.
	 *                                                                           Or the Marker to be tracked by the LIMB.
	 * @return {lucid.maps.limbs.Limb}  The LIMB that has been created.
	 */
	this.create = function( markerOrOptions )
	{
		var limbOptions = {};
		
		// Copy across the default options.
		if (typeof defaultOptions !== "undefined")
		{
			lucid.maps.limbs.applyLimbOptions( limbOptions, defaultOptions );
		}
		
		// Override the defaults with options specific to this LIMB.
		if (markerOrOptions.constructor == (new google.maps.Marker()).constructor)
		{
			limbOptions.target = markerOrOptions;
		}
		else
		{
			lucid.maps.limbs.applyLimbOptions( limbOptions, markerOrOptions );
		}
		
		// This class overrides two options with fixed values.
		limbOptions.hidden = hidden;
		limbOptions.independent = false;
		
		var limb = new lucid.maps.limbs.Limb( limbOptions );
		
		this.add( limb );
		
		return limb;
	};
	
	/**
	 * Temporarily hide the labels.
	 * This does not remove the LIMBs and targets, it just takes them off display.
	 * Call this if you hide the map element.
	 */
	this.hide = function()
	{
		hidden = true;
		
		for (var i=0; i<limbs.length; i++)
		{
			limbs[i].hide();
		}
	};
	
	/**
	 * Re-display the labels after being hidden with a call to 'hide'.
	 */
	this.show = function()
	{
		hidden = false;
		
		for (var i=0; i<limbs.length; i++)
		{
			limbs[i].show();
		}
	};
	
	/**
	 * Remove all LIMBs from this collection.
	 * The LIMB will still exist, it just won't be managed by this container anymore.
	 */
	this.removeAll = function()
	{
		limbs = [];
	};
	
	/**
	 * Destroy all the LIMBs in this collection.
	 * The LIMB will be removed from the page.
	 */
	this.destroyAll = function()
	{
		for (var i=0; i<limbs.length; i++)
		{
			limbs[i].destroy();
			limbs[i] = null;
		}
		limbs = [];
	};
	
	
	init();
};