Show:

File: ia\ui\TimeControl.js

/** 
 * A class for controlling time animations.
 *
 * @author J Clare
 * @class ia.TimeControl
 * @constructor
 * @param {String} id The id of the TimeControl.
 * @param {ia.DataGroup} dataGroup The this._dataGroup attached to the control.
 * @param {Function} callbackFunction Called when a selection is made. 
 */
ia.TimeControl = function(id, dataGroup, callbackFunction)
{		
	this.id = id;
	if (callbackFunction) this._callbackFunction = callbackFunction;
	this._dataGroup = dataGroup;

	this.delay = 1.5;

	// Is the animation this._playing.
	this._playing = false;

	// Div to contain play button.
	this.$playBtn = undefined;

	// The current geography id.
	this._currentGeographyId = undefined;

	// The current indicator id.
	this._currentIndicatorId = undefined;

	this.container  = $j("<div id='"+id+"-container' class='ia-time-control-scrollbox'>");
	this._scrollBox = new ia.ScrollBox(this.container);

	this.$table  = $j("<table class='ia-time-control-table'>");
	this.container.append(this.$table);

	var me = this;

	this._dataGroup.addEventListener(ia.DataEvent.GEOG_CHANGED, function(event)
	{
		me._stop();
		me._currentIndicatorId = event.indicator.id;
		me._currentGeographyId = event.indicator.geography.id;
		me._render(event.indicator);

		if (event.indicator.date !== undefined)
		{
			var fixedDate = event.indicator.date.replace(/'/g, "#quote#").replace(/"/g, "#double-quote#"); // Fix for quotations breaking ids.
			me.$table.find("td.ia-time-control-date-btn[id='"+fixedDate+"-btn']").addClass("ia-time-control-date-btn-active");
		}
	});

	this._dataGroup.addEventListener(ia.DataEvent.INDICATOR_CHANGED, function(event)
	{
		// Indicator has been changed outside control.
		if ((event.indicator.geography.id !== me._currentGeographyId) || (me._currentIndicatorId !== event.indicator.id))
		{
			me._stop();
			me._currentIndicatorId = event.indicator.id;
			me._currentGeographyId = event.indicator.geography.id;
			me._render(event.indicator);
		}
		else if (me._playing)
		{
			var t = setTimeout(function()
			{
				clearTimeout(t);
				if (me._playing)
				{
					// Load next date or stop animation if at the end.
					var dates = event.theme.getIndicatorDates(event.indicator.id);
					var index = dates.indexOf(event.indicator.date) + 1;
					if (index < dates.length)
						me._dataGroup.setData(event.geography.id, event.indicator.id, dates[index]);
					else
						me._stop();
				}

			}, me.delay * 1000);
		}

		me.$table.find("td.ia-time-control-date-btn").removeClass("ia-time-control-date-btn-active");

		if (event.indicator.date !== undefined)
		{
			var fixedDate = event.indicator.date.replace(/'/g, "#quote#").replace(/"/g, "#double-quote#"); // Fix for quotations breaking ids.
			me.$table.find("td.ia-time-control-date-btn[id='"+fixedDate+"-btn']").addClass("ia-time-control-date-btn-active");
		}
	});
};

/**
 * The container that holds the object.
 * 
 * @property container
 * @type JQUERY Element
 */
ia.TimeControl.prototype.container;

/**
 * The time delay in seconds between changing dates.
 * 
 * @property delay
 * @type Number
 * @default 1.5
 */
ia.TimeControl.prototype.delay;

/**
 * Plays the animation.
 *
 * @method _play
 * @private
 */
ia.TimeControl.prototype._play = function() 
{	
	if (!this._playing)
	{
		if (this._callbackFunction) this._callbackFunction.call(null, true);
		this._playing = true;
		this.$playBtn.removeClass("ia-time-control-btn-play");
		this.$playBtn.addClass("ia-time-control-btn-stop");

		// Load next date or first date if at the end.
		var dates = this._dataGroup.theme.getIndicatorDates(this._dataGroup.indicator.id);
		var index = dates.indexOf(this._dataGroup.indicator.date) + 1;
		if (index < dates.length) 
			this._dataGroup.setData(this._dataGroup.geography.id, this._dataGroup.indicator.id, dates[index]);
		else 
			this._dataGroup.setData(this._dataGroup.geography.id, this._dataGroup.indicator.id, dates[0]);
	}
	else this._stop();
};

/**
 * Stops the animation.
 *
 * @method _stop
 * @private
 */
ia.TimeControl.prototype._stop = function() 
{	
	if (this._callbackFunction) this._callbackFunction.call(null, false);
	this._playing = false;
	if (this.$playBtn)
	{
		this.$playBtn.removeClass("ia-time-control-btn-stop");
		this.$playBtn.addClass("ia-time-control-btn-play");
	}
};

/**
 * Moves to previous date.
 *
 * @method _back
 * @private
 */
ia.TimeControl.prototype._back = function() 
{	
	this._stop();

	// Load previous date or last date if at the start.
	var dates = this._dataGroup.theme.getIndicatorDates(this._dataGroup.indicator.id);
	var index = dates.indexOf(this._dataGroup.indicator.date) - 1;
	if (index > -1) 
		this._dataGroup.setData(this._dataGroup.geography.id, this._dataGroup.indicator.id, dates[index]);
	else 
		this._dataGroup.setData(this._dataGroup.geography.id, this._dataGroup.indicator.id, dates[dates.length-1]);
};

/**
 * Moves to next date.
 *
 * @method _next
 * @private
 */
ia.TimeControl.prototype._next = function() 
{			
	this._stop();

	// Load next date or first date if at the end.
	var dates = this._dataGroup.theme.getIndicatorDates(this._dataGroup.indicator.id);
	var index = dates.indexOf(this._dataGroup.indicator.date) + 1;
	if (index < dates.length) 
		this._dataGroup.setData(this._dataGroup.geography.id, this._dataGroup.indicator.id, dates[index]);
	else 
		this._dataGroup.setData(this._dataGroup.geography.id, this._dataGroup.indicator.id, dates[0]);
};

/**
 * Sets the data.
 *
 * @method setData
 */
ia.TimeControl.prototype.setData = function(indicator) 
{	
	this._stop();
	this._currentIndicatorId = indicator.id;
	this._currentGeographyId = indicator.geography.id;
	this._render(indicator);
	this.$table.find("td.ia-time-control-date-btn").removeClass("ia-time-control-date-btn-active");

	if (indicator.date !== undefined)
	{
		var fixedDate = indicator.date.replace(/'/g, "#quote#").replace(/"/g, "#double-quote#"); // Fix for quotations breaking ids.
		this.$table.find("td.ia-time-control-date-btn[id='"+fixedDate+"-btn']").addClass("ia-time-control-date-btn-active");
	}
};

/**
 * Renders the control.
 *
 * @method _render
 * @private
 */
ia.TimeControl.prototype._render = function(indicator) 
{	
	this.$table.empty();

	var dates = indicator.theme.getIndicatorDates(indicator.id);
	if (dates)
	{
		var me = this;

		$tr = $j("<tr>");
		this.$table.append($tr);

		this.$playBtn = $j("<td class='ia-list-item ia-time-control-btn ia-time-control-btn-play'>");
		$tr.append(this.$playBtn);
		this.$playBtn.bind(ia.CLICK_TYPE, function(e) 
		{
			e.stopPropagation();
			if (ia.IS_TOUCH_DEVICE) e.preventDefault();
			me._play();
		});

		var $backBtn = $j("<td class='ia-list-item ia-time-control-btn ia-time-control-btn-back'>");
		$tr.append($backBtn);
		$backBtn.bind(ia.CLICK_TYPE, function(e) 
		{
			e.stopPropagation();
			if (ia.IS_TOUCH_DEVICE) e.preventDefault();
			me._back();
		});

		var $forwardBtn = $j("<td class='ia-list-item ia-time-control-btn ia-time-control-btn-forward'>");
		$tr.append($forwardBtn);
		$forwardBtn.bind(ia.CLICK_TYPE, function(e) 
		{
			e.stopPropagation();
			if (ia.IS_TOUCH_DEVICE) e.preventDefault();
			me._next();
		});

		for (var i = 0; i < dates.length; i++) 
		{
			var date = dates[i]
			var fixedDate = date.replace(/'/g, "#quote#").replace(/"/g, "#double-quote#"); // Fix for quotations breaking ids.
			$dateBtn = $j("<td id='"+fixedDate+"-btn' class='ia-list-item ia-time-control-td ia-time-control-date-btn'>").html(date);
			$tr.append($dateBtn);

			(function() // Execute immediately
			{ 
				var geographyId = indicator.geography.id;
				var indicatorId = indicator.id;
				var dateStr = date;

				$dateBtn.bind(ia.CLICK_TYPE, function(e) 
				{
					e.stopPropagation();
					if (ia.IS_TOUCH_DEVICE) e.preventDefault();

					me._stop();
					me._dataGroup.setData(geographyId, indicatorId, dateStr);
				});
			})();
		}
	}
	this._scrollBox.refresh();
};