/**
* @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();
};