Show:

File: ia\factories\PyramidChartFactory.js

/** 
 * Factory for creating pyramid charts.
 *
 * @author J Clare
 * @class ia.PyramidChartFactory
 * @param {ia.ComponentConfig} config The component config.
 * @param {ia.Report} report The report object.
 * @param {Object} componentGroup  Hash table containing the Data and  Interaction Groups that the component belongs to:
 * {dataGroup:ia.DataGroup, interactionGroup:ia.InteractionGroup, comparisonInteractionGroup:ia.InteractionGroup}.
 */
ia.PyramidChartFactory = function(config, report, componentGroup)
{
	var me = this;

	// Data and Interaction groups that the components belongs to.
	var interactionGroup = componentGroup.interactionGroup;
	var dataGroup = componentGroup.dataGroup;
	var comparisonInteractionGroup = componentGroup.comparisonInteractionGroup;

	// Event handlers.

	// This code executes every time a geography has changed.
	dataGroup.addEventListener(ia.DataEvent.GEOG_CHANGED, function(event)
	{
		updateGeography();
		me.render();
	});

	// This code executes every time the data groups data has changed.
	dataGroup.addEventListener(ia.DataEvent.DATA_CHANGED, function(event)
	{
		me.update();
		me.render();
	});

	// This code executes every time the selection has changed.
	interactionGroup.addEventListener(ia.InteractionEvent.SELECTION_CHANGED, function(event)
	{
		var selectedFeatures = interactionGroup.getSelection();
		if (selectedFeatures.length > 0) 
		{
			var id = selectedFeatures[0];
			var pData = dataGroup.geography.getProfileData([id]);
			for (var i = 0; i < mLayers.length; i++)
			{
				mLayers[i].setData(pData.themes[0].indicators); // Males.
				fLayers[i].setData(pData.themes[1].indicators); // Females.
			}
		}
		else
		{
			for (var i = 0; i < mLayers.length; i++)
			{
				mLayers[i].setData({}); // Males.
				fLayers[i].setData({}); // Females.
			}
		}
		me.render();
	});

	// This code executes every time the comparison selection has changed.
	comparisonInteractionGroup.addEventListener(ia.InteractionEvent.SELECTION_CHANGED, function(event) 
	{
		me.update();
		me.render();
	});

	// Components.

	// Panel.
	var panel = report.getWidget(config.id); 
	panel.exportFunction = function() {if (chart.isVisible) chart.exportData(report.config.getProperty("saveImageText"));}; 

	// Chart.
	var legendConfig;
	var legend;

	var chart;

	var mLayers;
	var mLayer;
	var mComparisonLayer;

	var fLayers;
	var fLayer;
	var fComparisonLayer

	/** 
	 * Builds the component.
	 *
	 * @method build
 	 * @param {Function} callbackFunction Called on completion of function, with the component id as the parameter.
	 */
	this.build = function(callbackFunction)
	{
		// Empty panel.
		panel.content.empty();

		// Legend.
		legendConfig = report.config.getComponent("pyramidLegend"+dataGroup.suffix);
		if (legendConfig)
		{
			legend = new ia.ProfileLegend(legendConfig.id);
			if (legendConfig.getProperty("layout")) legend.layout = legendConfig.getProperty("layout");

			var legendPanel = report.getWidget(legendConfig.id);
			legendPanel.append(legend.container);
			report.addComponent(legendConfig.id, legend);
		}

		// chart.
		chart = new ia.PyramidChart(config.id);
		chart.formatter = report.locale.formatter;
		panel.append(chart.container);

		// Arrays to hold the layers.
		fLayers = [];
		mLayers = [];

		// Male layer.
		mLayer = new ia.PyramidLayer();
		mLayer.setVisible(true);
		mLayer.interactive = true;
		mLayer.highlightColor = report.highlightColor;
		mLayer.selectionColor = report.selectionColor;

		// Set styles after layer added to chart otherwise it gets override by the ia-chart-item style.
		chart.addLayer(mLayer);
		mLayers[mLayers.length] = mLayer;

		// Female layer.
		fLayer = new ia.PyramidLayer();
		fLayer.gender = "female";
		fLayer.setVisible(true);
		fLayer.interactive = true;
		fLayer.highlightColor = report.highlightColor;
		fLayer.selectionColor = report.selectionColor;

		// Set styles after layer added to chart otherwise it gets override by the ia-chart-item style.
		chart.addLayer(fLayer);
		fLayers[fLayers.length] = fLayer;

		// Male Comparison layer.
		mComparisonLayer = new ia.ComparisonPyramidLayer();
		mComparisonLayer.setVisible(true);
		mComparisonLayer.interactive = true;
		mComparisonLayer.thematic = dataGroup.comparisonThematic;
		mComparisonLayer.highlightColor = report.highlightColor;
		mComparisonLayer.selectionColor = report.selectionColor;

		chart.addLayer(mComparisonLayer);
		comparisonInteractionGroup.addComponent(mComparisonLayer);

		// Female Comparison layer.
		fComparisonLayer = new ia.ComparisonPyramidLayer();
		fComparisonLayer.gender = "female";
		fComparisonLayer.setVisible(true);
		fComparisonLayer.interactive = true;
		fComparisonLayer.thematic = dataGroup.comparisonThematic;
		fComparisonLayer.highlightColor = report.highlightColor;
		fComparisonLayer.selectionColor = report.selectionColor;
		chart.addLayer(fComparisonLayer);
		comparisonInteractionGroup.addComponent(fComparisonLayer);

		var legendClasses = [];
		var label = config.getProperty("femaleLabel")
		var legendClass = new ia.CategoricClass(label);
		legendClass.color = config.getProperty("femaleColor");
		legendClass.symbol = ia.Shape.SQUARE;
		legendClass.size = 12;
		legendClass.value = label;
		legendClasses[legendClasses.length] = legendClass;

		var legendClass = new ia.CategoricClass(config.getProperty("maleLabel"));
		var label = config.getProperty("maleLabel")
		var legendClass = new ia.CategoricClass(label);
		legendClass.color = config.getProperty("maleColor");
		legendClass.symbol = ia.Shape.SQUARE;
		legendClass.size = 12;
		legendClass.value = label;
		legendClasses[legendClasses.length] = legendClass;

		// Associate Layers.
		for (var i = 1; i <= 3; i++) 
		{
			if (config.getProperty("line_value_"+i) !== undefined)
			{
				var dataField = config.getProperty("line_value_"+i);
				var color = config.getProperty("line_color_"+i);
				var label = config.getProperty("line_label_"+i);

				// Male Associate layer.
				var mAssociateLayer = new ia.ComparisonPyramidLayer();
				mAssociateLayer.dataField = dataField;
				mAssociateLayer.setVisible(true);
				mAssociateLayer.interactive = true;
				mAssociateLayer.displayAll = true;
				mAssociateLayer.tip = config.getProperty("tip");
				mAssociateLayer.highlightColor = report.highlightColor;
				chart.addLayer(mAssociateLayer);
				mAssociateLayer.style.strokeStyle = color;

				// Female Associate layer.
				var fAssociateLayer = new ia.ComparisonPyramidLayer();
				fAssociateLayer.gender = "female";
				fAssociateLayer.dataField = dataField;
				fAssociateLayer.setVisible(true);
				fAssociateLayer.interactive = true;
				fAssociateLayer.tip = config.getProperty("tip");
				fAssociateLayer.displayAll = true;
				fAssociateLayer.highlightColor = report.highlightColor;
				chart.addLayer(fAssociateLayer);
				fAssociateLayer.style.strokeStyle = color;

				fLayers[fLayers.length] = fAssociateLayer;
				mLayers[mLayers.length] = mAssociateLayer;

				// For pyramid key.
				var legendClass = new ia.CategoricClass(label);
				legendClass.color = color;
				legendClass.symbol = ia.Shape.HORIZONTAL_LINE;
				legendClass.size = 12;
				legendClass.value = label;
				legendClasses[legendClasses.length] = legendClass;
			}
		}

		if (report.url.params["select"+dataGroup.suffix]) // select=_00CE,_00CF,_00DA
		{
			var arr = report.url.params["select"+dataGroup.suffix].toString().split(",");
			var id = arr[arr.length-1];
			var pData = dataGroup.geography.getProfileData([id]);
			for (var i = 0; i < mLayers.length; i++)
			{
				mLayers[i].setData(pData.themes[0].indicators); // Males.
				fLayers[i].setData(pData.themes[1].indicators); // Females.
			}
		}

		// Associated legend created in above code.
		if (legend) 
		{
			legend.legendClasses = legendClasses;
			legend.render();
		}

		report.addComponent(config.id, chart);
	
		updateGeography(); 			
				
		// Wait till charts ready before returning.
		chart.addEventListener(ia.Event.MAP_READY, function() 
		{
			if (callbackFunction !== undefined) callbackFunction.call(null, config.id);
		});
	};

	/** 
	 * Updates the component.
	 *
	 * @method update
 	 * @param {Function} callbackFunction Called on completion of function, with the component id as the parameter.
	 */
	this.update = function(callbackFunction)
	{
		chart.orientation = "horizontal";
		chart.drawBarsFromZero = config.getProperty("drawBarsFromZero");
		chart.showYAxisLabels = config.getProperty("showYAxisLabels"); 

		mLayer.dataField = config.getProperty("data") || "value";
		mLayer.tip = config.getProperty("tip");
		mLayer.style.fillStyle = ia.Color.toRGBA(config.getProperty("maleColor"), 0.8);
		mLayer.style.strokeStyle = config.getProperty("maleColor");

		fLayer.dataField = config.getProperty("data") || "value";
		fLayer.tip = config.getProperty("tip");
		fLayer.style.fillStyle = ia.Color.toRGBA(config.getProperty("femaleColor"), 0.8);
		fLayer.style.strokeStyle = config.getProperty("femaleColor"); 

		mComparisonLayer.dataField = config.getProperty("data") || "value";
		mComparisonLayer.displayAll = config.getProperty("showComparison");
		mComparisonLayer.tip = config.getProperty("tip");

		fComparisonLayer.dataField = config.getProperty("data") || "value";
		fComparisonLayer.tip = config.getProperty("tip");
		fComparisonLayer.displayAll = config.getProperty("showComparison");

		var indicator = dataGroup.indicator;

		// Check for custom fixed values.
		var fixedMaxValue = indicator.getProperty(config.getProperty("maxChartValue"));
		if (fixedMaxValue)
		{
			chart.useTightLabels = true;
			chart.fixedMaxValue = fixedMaxValue;
		}
		else
		{
			// If theres no custom values then check for config.xml fixed values.
			if (config.getProperty("useFixedValues"))
			{
				chart.useTightLabels = true;
				chart.fixedMaxValue = config.getProperty("fixedMaxValue");
			}
			else chart.useTightLabels = config.getProperty("useTightLabels");
		}
		
		// Axis titles.
		var xTitle = config.getProperty("xAxisTitle");
		if (xTitle) chart.xAxisTitle = report.textSubstitution.formatMessage(xTitle);
		var yTitle = config.getProperty("yAxisTitle");
		if (yTitle) chart.yAxisTitle = report.textSubstitution.formatMessage(yTitle);

		// Data.
		var themes = dataGroup.geography.getThemes();
		var mTheme = themes[0];
		chart.yAxisLabels = mTheme.getIndicatorNames().reverse();
		chart.date = indicator.date;

		if (callbackFunction !== undefined) callbackFunction.call(null, config.id);
	};

	/** 
	 * Renders the component.
	 *
	 * @method render
 	 * @param {Function} callbackFunction Called on completion of function, with the component id as the parameter.
	 */
	this.render = function(callbackFunction)
	{
		chart.render();
		
		if (callbackFunction !== undefined) callbackFunction.call(null, config.id);
	};

	// Update the data when the geography changes.
	function updateGeography()
	{
		var geography = dataGroup.geography;
		chart.geography = geography;
		var comparisonFeatures = geography.getComparisonFeatures();
		var comparisonFeatureIds = [];
		for (var i = 0; i < comparisonFeatures.length; i++)  
		{ 
			comparisonFeatureIds.push(comparisonFeatures[i].id)
		}

		var pData = geography.getProfileData(comparisonFeatureIds);
		mComparisonLayer.setData(pData.themes[0].indicators); // Males.
		fComparisonLayer.setData(pData.themes[1].indicators); // Females.
	};
};