File: ia\thematics\Thematic.js
/**
* The <code>ia.Thematic</code> class is used to
* classify data. The Theme contains two classifiers
* for classifying both numeric and non-numeric data.
*
* <p>The data is an associative array with the following format:</p>
* <p>["eh11"]{id:"eh11", name:"polwarth", value:2345, associate1:25}
* <br/>["eh12"]{id:"eh12", name:"morningside", value:4347, associate1:45}
* <br/>["eh13"]{id:"eh13", name:"merchiston", value:2496, associate1:25}</p>
*
* @author J Clare
* @class ia.Thematic
* @extends ia.EventDispatcher
* @constructor
* @param {AssociativeArray[]} data The data is an associative array with the following format:
* <br/>["eh11"]{id:"eh11", name:"polwarth", value:2345, associate1:25}
* <br/>["eh12"]{id:"eh12", name:"morningside", value:4347, associate1:45}
* <br/>["eh13"]{id:"eh13", name:"merchiston", value:2496, associate1:25}
*/
ia.Thematic = function(data)
{
ia.Thematic.baseConstructor.call(this);
this._data = new Object();
this._dataField = "value";
this._dataType = "numeric";
this._dataChanged = true;
this.symbol = ia.Shape.SQUARE;
this.noDataValue = "No Data";
this.numericClassifier = new ia.NumericClassifier();
this.categoricClassifier = new ia.CategoricClassifier();
if (data !== undefined) this.setData(data);
};
ia.extend(ia.EventDispatcher, ia.Thematic);
/**
* Constant indicating a continuous value classification.
*
* @static
* @final
* @property CONTINUOUS
* @type String
* @default "continuous"
*/
ia.Thematic.CONTINUOUS = "continuous";
/**
* Constant indicating an equal interval classification.
*
* @static
* @final
* @property EQUAL_INTERVAL
* @type String
* @default "equalInterval"
*/
ia.Thematic.EQUAL_INTERVAL = "equalInterval";
/**
* Constant indicating a quantile classification.
*
* @static
* @final
* @property QUANTILE
* @type String
* @default "quantile"
*/
ia.Thematic.QUANTILE = "quantile";
/**
* Constant indicating a natural breaks classification.
*
* @static
* @final
* @property NATURAL
* @type String
* @default "natural"
*/
ia.Thematic.NATURAL = "natural";
/**
* Constant indicating a standard deviation classification.
*
* @static
* @final
* @property STANDARD_DEVIATION
* @type String
* @default "standardDeviation"
*/
ia.Thematic.STANDARD_DEVIATION = "standardDeviation";
/**
* Specifies that the data for the thematic is numeric.
*
* @static
* @final
* @property NUMERIC
* @type String
* @default "numeric"
*/
ia.Thematic.NUMERIC = "numeric";
/**
* Specifies that the data for the thematic is categoric.
*
* @static
* @final
* @property CATEGORIC
* @type String
* @default "categoric"
*/
ia.Thematic.CATEGORIC = "categoric";
/**
* The symbol used for point data.
*
* @property symbol
* @type String
* @default ia.Shape.SQUARE
*/
ia.Thematic.prototype.symbol;
/**
* The no data value.
*
* @property noDataValue
* @type String
* @default "No Data"
*/
ia.Thematic.prototype.noDataValue;
/**
* The classifier used to handle numeric data.
*
* @property numericClassifier
* @type ia.NumericClassifier
*/
ia.Thematic.prototype.numericClassifier;
/**
* The classifier used to handle non-numeric data.
*
* @property categoricClassifier
* @type ia.CategoricClassifier
*/
ia.Thematic.prototype.categoricClassifier;
/**
* Gets the data for the theme.
*
* <p>The data is an associative array with the following format:<p>
* <p>["eh11"]{id:"eh11", name:"polwarth", value:2345, associate1:25}
* <br/>["eh12"]{id:"eh12", name:"morningside", value:4347, associate1:45}
* <br/>["eh13"]{id:"eh13", name:"merchiston", value:2496, associate1:25}</p>
*
* @method getData
* @return {AssociativeArray[]} The data.
*/
ia.Thematic.prototype.getData = function()
{
return this._data;
};
/**
* Sets the data for the theme.
*
* <p>The data is an associative array with the following format:<p>
* <p>["eh11"]{id:"eh11", name:"polwarth", value:2345, associate1:25}
* <br/>["eh12"]{id:"eh12", name:"morningside", value:4347, associate1:45}
* <br/>["eh13"]{id:"eh13", name:"merchiston", value:2496, associate1:25}</p>
*
* @method setData
* @param {AssociativeArray[]} data The data.
*/
ia.Thematic.prototype.setData = function(data)
{
this._data = data;
this._dataChanged = true;
};
/**
* Gets the field of the data provider that provides the values.
*
* @method getDataField
* @return {String} The data field.
*/
ia.Thematic.prototype.getDataField = function()
{
return this._dataField;
};
/**
* Sets the field of the data provider that provides the values.
*
* @method setDataField
* @param {String} dataField The data field.
*/
ia.Thematic.prototype.setDataField = function(dataField)
{
this._dataField = dataField;
this._dataChanged = true;
};
/**
* Gets the data type of the data provider.
*
* <p>Possible values include:
* <ul>
* <li><code>ia.Thematic.NUMERIC</code></li>
* <li><code>ia.Thematic.CATEGORIC</code></li>
* </ul>
* </p>
*
* @method getDataType
* @return {String} The data type.
*/
ia.Thematic.prototype.getDataType = function()
{
return this._dataType;
};
/**
* Sets the data type of the data provider.
*
* <p>Possible values include:
* <ul>
* <li><code>ia.Thematic.NUMERIC</code></li>
* <li><code>ia.Thematic.CATEGORIC</code></li>
* </ul>
* </p>
*
* @method setDataType
* @param {String} dataType The data type.
*/
ia.Thematic.prototype.setDataType = function(dataType)
{
this._dataType = dataType;
this._dataChanged = true;
};
/**
* An array of classes contained in the theme.
*
* @method getClasses
* @return {ia.LegendClass[]} The classes.
*/
ia.Thematic.prototype.getClasses = function()
{
return this.numericClassifier.getClasses().concat(this.categoricClassifier.getClasses());
};
/**
* Gets the legend class for the given value.
*
* @method getClass
* @param {Number|String} value The value.
* @return {ia.LegendClass} The legend class that contains the value.
*/
ia.Thematic.prototype.getClass = function(value)
{
var legendClass;
if (this._dataType === ia.Thematic.CATEGORIC)
{
legendClass = this.categoricClassifier.getClass(value);
}
else
{
if (ia.isNumber(value)) legendClass = this.numericClassifier.getClass(value);
else legendClass = this.categoricClassifier.getClass(value);
}
return legendClass;
};
/**
* Call this to commit any changes.
*
* @method commitChanges
*/
ia.Thematic.prototype.commitChanges = function()
{
if (this._dataChanged)
{
var nArray = new Array();
var cArray = new Array();
var dataItem;
var value;
for (var id in this._data)
{
dataItem = this._data[id];
value = dataItem[this._dataField];
if (this._dataType === ia.Thematic.CATEGORIC)
{
cArray.push(value);
}
else
{
if (ia.isNumber(value)) nArray.push(value);
else cArray.push(value);
}
}
this.numericClassifier.setData(nArray);
this.categoricClassifier.setData(cArray);
}
// Commit classifier changes
this.numericClassifier.commitChanges()
this.categoricClassifier.commitChanges()
// Now link ids to legend classes.
var legendClasses = this.getClasses();
var n = legendClasses.length;
var legendClass;
// Set symbol shape and index to legend class.
for (var i = 0; i < n; i++)
{
legendClass = legendClasses[i];
legendClass.symbol = this.symbol;
legendClass.index = i;
// Check for point with no data value.
if (legendClass.getLabel() === this.noDataValue
&& legendClass.symbol !== ia.Shape.LINE
&& legendClass.symbol !== ia.Shape.SQUARE)
{
legendClass.size = 0
}
}
// Add thematic information to data items.
for (var id in this._data)
{
dataItem = this._data[id];
value = dataItem[this._dataField];
for (var i = 0; i < n; i++)
{
legendClass = legendClasses[i];
if (legendClass.contains(value))
{
// Add thematic information to the data item.
dataItem.color = legendClass.color;
dataItem.symbolSize = legendClass.size;
dataItem.legendClass = legendClass;
// Add the data item to the list of items contained in the class
// This is useful for legends and pie charts
legendClass.items.push(dataItem);
break;
}
}
}
this.dispatchEvent(new ia.Event(ia.Event.THEME_CHANGED, this));
};