Source: maps/limbs/DirectionsController.js


/**
 * @class
 * Controls behaviour for showing directions to a central destination from various travel points (a.k.a a "how to find us" map).
 * 
 * The controller is configured with options for creating markers, limbs and directions.
 * 
 * Transport links (origins of travel to the destination) are then added using the addTransportLink method. Custom
 * travel options can be supplied to override the default options that were set via the constructor, allowing
 * each transport link to use a different icon, travel mode, etc.
 * 
 * @constructor
 * @param {lucid.maps.limbs.DirectionsControllerOptions} options  Options for the default behaviour of this controller.
 */
lucid.maps.limbs.DirectionsController = function( options )
{
	var map;
	var limbMarkerFactory;
	var directionsRenderer;
	
	
	// This initialise function is called at the end of the constructor.
	function init()
	{
		map = options.map;
		
		
		var markerOptions = { clickHandlerFactory: defaultClickHandlerFactory };
		if (typeof options.markerOptions !== "undefined")
		{
			lucid.maps.limbs.applyMarkerOptions( markerOptions, options.markerOptions );
		}

		var limbOptions = { syncClick: true };
		if (typeof options.limbOptions !== "undefined")
		{
			lucid.maps.limbs.applyLimbOptions( limbOptions, options.limbOptions );
		}

		var factoryOptions = { map: map,
		                       markerOptions: markerOptions,
		                       limbOptions: limbOptions };

		limbMarkerFactory = new lucid.maps.limbs.LimbMarkerFactory( factoryOptions );


		var directionsRendererOptions = { map: map,
		                                  hideRouteList: true,
		                                  routeIndex: 0,
		                                  draggable: false,
		                                  preserveViewport: false,
		                                  suppressMarkers: true,
		                                  suppressInfoWindows: true };

		directionsRenderer = new google.maps.DirectionsRenderer( directionsRendererOptions );
	}

	/**
	 * @param {lucid.maps.limbs.TransportLinkOptions} travelOptions  Options to override the default options passed into the factory's constructor.
	 * @returns {lucid.maps.limbs.Limb}  The LIMB that was created for the new travel point.
	 */
	this.addTransportLink = function( travelOptions )
	{
		var customisedMarkerOptions = (typeof travelOptions.markerOptions === "undefined") ? {} : travelOptions.markerOptions;
		var customisedLimbOptions = (typeof travelOptions.limbOptions === "undefined") ? {} : travelOptions.limbOptions;

		var limb = limbMarkerFactory.addCustomised( customisedMarkerOptions, customisedLimbOptions );
		var marker = limb.getTarget();

		// Build-up the directions options from the raw defaults, the factory defaults and the options passed into this function.
		// Attach those options to the marker so they can be accessed from the marker's click handler.
		marker.directionsOptions = { origin: marker.getPosition(),
		                             provideRouteAlternatives: false };
		if (typeof options.directionOptions !== "undefined")
		{
			lucid.maps.limbs.applyDirectionsOptions( marker.directionsOptions, options.directionOptions );
		}
		if (typeof travelOptions.directionOptions !== "undefined")
		{
			lucid.maps.limbs.applyDirectionsOptions( marker.directionsOptions, travelOptions.directionOptions );
		}

		return limb;
	};


	/**
	 * @param {google.maps.Marker} marker  The marker to create a click-handler for.
	 * @return {function}  A function that handles the click on that marker.
	 */
	function defaultClickHandlerFactory( marker )
	{
		return function()
		{
			// TODO Raise pre event
			
			hidePreviousRoute();
			
			zoomToRoute( marker.getPosition(), marker.directionsOptions.destination );
			
			new google.maps.DirectionsService().route( marker.directionsOptions, showRoute );
			
			// TODO Raise waiting event
		};
	}

	function hidePreviousRoute()
	{
		directionsRenderer.setMap( null );
	}

	function zoomToRoute( origin, destination )
	{
		var routeBounds = new google.maps.LatLngBounds();
		routeBounds = routeBounds.extend( origin );
		routeBounds = routeBounds.extend( destination );

		map.fitBounds( routeBounds );
	}

	function showRoute( directions, status )
	{
		if (status == google.maps.DirectionsStatus.OK)
		{
			directionsRenderer.setDirections( directions );
			directionsRenderer.setMap( map );
		}
		
		// TODO Raise post event
	}


	init();
};

/**
 * @type {object}
 * @property {google.maps.MarkerOptions} [markerOptions]  Settings for the travel-point marker.
 * @property {lucid.maps.limbs.LimbOptions} [limbOptions]  Settings for the travel-point LIMB.
 * @property {google.maps.DirectionsRequest} [directionOptions]  Settings for the directions/route from this travel-point to the destination.
 */
lucid.maps.limbs.TransportLinkOptions = {};

/**
 * @type {object}
 * @augments lucid.maps.limbs.TransportLinkOptions
 * @property {google.maps.Map} map  The map that will show the travel points and directions.
 */
lucid.maps.limbs.DirectionsControllerOptions = {};