Show:

File: ia\factories\ComponentFactory.js

/** 
 * A Factory objects for building components.
 *
 * @author J Clare
 * @class ia.ComponentFactory
 * @constructor
 * @param {ia.Config} config The config.
 * @param {ia.Report} report The report.
 * @param {ia.DataGroup[]} dataGroups A list of associated datagroups.
 * @param {ia.InteractionGroup} interactionGroup The associated interaction group.
 * @param {ia.InteractionGroup} comparisonInteractionGroup The associated comparison interaction group.
 */
ia.ComponentFactory = function(config, report, componentGroups)
{
	this._config = config;
	this._report = report;
	this._componentGroups = componentGroups;
	this._dataGroups = [];
	this._factories = {};

	// Build the interaction groups.
	for (var i = 0; i < this._componentGroups.length; i++)
	{
		var g = componentGroups[i];
		this.buildInteractionGroups(report, g.dataGroup, g.interactionGroup, g.comparisonInteractionGroup);
		this._dataGroups[i] = g.dataGroup;
	}
};

/** 
 * Updates the component.
 * 
 * @method update
 * @param {String} id The id of the component.
 * @param {Function} callbackFunction Called on completion of function, with the component id as the parameter.
 */
ia.ComponentFactory.prototype.update = function(id, onComponentReady) 
{
	var factory = this._factories[id];
	if (factory !== undefined ) 
	{
		factory.update(function()
		{
			onComponentReady.call(null, id); // Return.
		});
	}
	else onComponentReady.call(null, id); // Return.
};

/** 
 * Renders the component.
 * 
 * @method render
 * @param {String} id The id of the component.
 * @param {Function} callbackFunction Called on completion of function, with the component id as the parameter.
 */
ia.ComponentFactory.prototype.render = function(id, onComponentReady) 
{
	var factory = this._factories[id];
	if (factory !== undefined ) 
	{
		factory.render(function()
		{
			onComponentReady.call(null, id); // Return.
		});
	}
	else onComponentReady.call(null, id); // Return.
};

/** 
 * Builds the component.
 * 
 * @method build
 * @param {String} id The id of the component.
 * @param {Function} callbackFunction Called on completion of function, with the component id as the parameter.
 */
ia.ComponentFactory.prototype.build = function(id, onComponentReady) 
{
	var me = this;
	var component = this._config.getComponent(id);
	if (component)
	{
		var suffix = this._getSuffix(id);
		var type = this._getType(id);

		// Get the correct component group.
		var index = suffix - 1;
		if (suffix === '') index = 0;
		var componentGroup = this._componentGroups[index];

		if (componentGroup !== undefined)
		{
			var factory;

			// Components that require single data group.
			if (type === "legend") 						factory = new ia.LegendFactory(component, this._report, componentGroup);
			else if (type === "featureLegend") 			factory = new ia.FeatureLegendFactory(component, this._report, componentGroup);
			else if (type === "areaBreakdownBarChart") 	factory = new ia.AreaBreakdownBarChartFactory(component, this._report, componentGroup);
			else if (type === "areaBreakdownLineChart") factory = new ia.AreaBreakdownLineChartFactory(component, this._report, componentGroup);
			else if (type === "areaBreakdownPieChart") 	factory = new ia.AreaBreakdownPieChartFactory(component, this._report, componentGroup);
			else if (type === "areaBreakdownPieLegend") factory = new ia.AreaBreakdownPieLegendFactory(component, this._report, componentGroup);
			else if (type === "barChart") 				factory = new ia.BarChartFactory(component, this._report, componentGroup);
			else if (type === "boxAndWhisker") 			factory = new ia.BoxAndWhiskerFactory(component, this._report, componentGroup);
			else if (type === "timeSeries") 			factory = new ia.TimeSeriesFactory(component, this._report, componentGroup);
			else if (type === "discreteTimeSeries") 	factory = new ia.DiscreteTimeSeriesFactory(component, this._report, componentGroup);
			else if (type === "stackedTimeSeries") 		factory = new ia.StackedTimeSeriesFactory(component, this._report, componentGroup);
			else if (type === "pyramidChart") 			factory = new ia.PyramidChartFactory(component, this._report, componentGroup);
			else if (type === "timeControl") 			factory = new ia.TimeControlFactory(component, this._report, componentGroup);
			else if (type === "featureCard") 			factory = new ia.FeatureCardFactory(component, this._report, componentGroup);
			else if (type === "metadata") 				factory = new ia.MetadataFactory(component, this._report, componentGroup);
			else if (type === "textbox") 				factory = new ia.TextBoxFactory(component, this._report, componentGroup);
			else if (type === "statsbox") 				factory = new ia.StatsBoxFactory(component, this._report, componentGroup);
			else if (type === "advancedPieChart") 		factory = new ia.AdvancedPieChartFactory(component, this._report, componentGroup);
			else if (type === "pieChart") 				factory = new ia.PieChartFactory(component, this._report, componentGroup);
			else if (type === "dataExplorer") 			factory = new ia.DataExplorerFactory(component, this._report, componentGroup);
			else if (type === "geogExplorer") 			factory = new ia.GeogExplorerFactory(component, this._report, componentGroup);
			else if (type === "filterExplorer") 		factory = new ia.FilterExplorerFactory(component, this._report, componentGroup);
			else if (type === "menuBar") 				factory = new ia.MenuBarFactory(component, this._report, componentGroup);
			else if (type === "spineChart") 			factory = new ia.AreaProfileFactory(component, this._report, componentGroup);
			else if (type === "map") 					factory = new ia.MapFactory(component, this._report, componentGroup);					
			// Components that require multiple data groups.
			else if (type === "scatterPlot") 			factory = new ia.ScatterPlotFactory(component, this._report, this._dataGroups, componentGroup.interactionGroup, componentGroup.comparisonInteractionGroup);
			else if (type === "table") 	
			{
				if (this._config.template === ia.DOUBLE_GEOG_REPORT
					|| this._config.template === ia.DOUBLE_BASELAYER_REPORT)		
				{
					var dGroup = this._dataGroups[index];
					factory = new ia.DataTableFactory(component, this._report, [dGroup], componentGroup.interactionGroup, componentGroup.comparisonInteractionGroup);
				}
				else factory = new ia.DataTableFactory(component, this._report, this._dataGroups, componentGroup.interactionGroup, componentGroup.comparisonInteractionGroup);
			}
			else if (type === "comparisonTable") 		
			{
				if (this._config.template === ia.DOUBLE_GEOG_REPORT
					|| this._config.template === ia.DOUBLE_BASELAYER_REPORT)		
				{
					var dGroup = this._dataGroups[index];
					factory = new ia.ComparisonTableFactory(component, this._report, [dGroup], componentGroup.interactionGroup, componentGroup.comparisonInteractionGroup);
				}
				else factory = new ia.ComparisonTableFactory(component, this._report, this._dataGroups, componentGroup.interactionGroup, componentGroup.comparisonInteractionGroup);
			}	
			else onComponentReady.call(null, id); // Return.

			if (factory !== undefined ) 
			{
				this._factories[component.id] = factory; // Add to factories hashtable.

				if (type === "map" && (this._config.template === ia.DOUBLE_BASELAYER_REPORT  // Special case for double base layer templates.
					|| this._config.template === ia.DOUBLE_BASELAYER_REPORT_NEW))
				{
					factory.build(function()
					{
						factory.update(function()
						{
							factory.render(function()
							{
								factory2 = new ia.MapFactory(undefined, me._report, me._componentGroups[1]); // Add second layer.
								factory2.build(function()
								{
									factory2.update(function()
									{
										factory2.render(function()
										{
				 							onComponentReady.call(null, id); // Return.
										});
									});
								});
							});
						});
					});
				}
				else
				{
					factory.build(function()
					{
						factory.update(function()
						{
							factory.render(function()
							{
	 							onComponentReady.call(null, id); // Return.
							});
						});
					});
				}
			}
		}
		else onComponentReady.call(null, id); // Return.
	}
	else onComponentReady.call(null, id); // Return.
};

/** 
 * Builds a all components in the config.
 * 
 * @method buildComponent
 * @param {Function} onComponentsReady Gets called when the build is complete.
 */
ia.ComponentFactory.prototype.buildComponents = function(onComponentsReady) 
{
	var me = this;
	var components = me._config.getComponents();
	var noComponents = components.length;
	var index = 0;

	// Could be dodgy using a loop here, but its faster and each component
	// doesnt rely on the other being complete so probably ok.
	function onComponentReady(componentId)
	{
		index++;
		if (index === noComponents) onComponentsReady.call(null); 		// Return
	}

	for (var i = 0; i < noComponents; i++)
	{
		me.build(components[i].id, onComponentReady)
	}

	/* This is slightly slower but potentially more robust.
	function onComponentReady(componentId)
	{
		index++;
		if (index === noComponents) onComponentsReady.call(null); 		// Return
		else me.buildComponent(components[index].id, onComponentReady); // Build next component.
	}
	me.buildComponent(components[0].id, onComponentReady); 				// Build first component.
	*/
};

/** 
 * Extracts the suffix from the component id.
 * 
 * @method _getSuffix
 * @param {String} id The id of the component.
 * @return {String} The suffix.
 * @private
 */
ia.ComponentFactory.prototype._getSuffix = function(id) 
{
	// Extract the suffix from the id.
	var suffix = id.slice(-1);
	if (!ia.isNumber(suffix)) suffix = "";

	// An underscore represents an extra version of a component eg 'barChart_2' or 'barChart2_2'.
	// The first number represents the data group the component is associated with.
	// The second number is simply to make the id unique.
	// This has been added so we can eventually add in multiple versions of components.
	if (id.indexOf("_") !== -1)
	{
		suffix = id.slice(-3).charAt(0);
		if (!ia.isNumber(suffix)) suffix = "";
	}

	return suffix;
};

/** 
 * Extracts the type from the component id.
 * 
 * @method _getType
 * @param {String} id The id of the component.
 * @return {String} The type.
 * @private
 */
ia.ComponentFactory.prototype._getType = function(id) 
{
	var type = id;

	// Extract the suffix from the id.
	var suffix = id.slice(-1);
	if (ia.isNumber(suffix)) type = type.substring(0,type.length-1);

	// An underscore represents an extra version of a component eg 'barChart_2' or 'barChart2_2'.
	// The first number represents the data group the component is associated with.
	// The second number is simply to make the id unique.
	// This has been added so we can eventually add in multiple versions of components.
	if (id.indexOf("_") !== -1)
	{
		type = id;
		suffix = id.slice(-3).charAt(0);
		if (ia.isNumber(suffix)) type = type.substring(0,type.length-3);
		else type = type.substring(0,type.length-2)
	}

	return type;
};