diff -r 322d0feea350 -r 89ef5ed3c48b src/cm/media/js/lib/yui/yui_3.10.3/build/series-cartesian/series-cartesian.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cm/media/js/lib/yui/yui_3.10.3/build/series-cartesian/series-cartesian.js Tue Jul 16 14:29:46 2013 +0200 @@ -0,0 +1,1035 @@ +/* +YUI 3.10.3 (build 2fb5187) +Copyright 2013 Yahoo! Inc. All rights reserved. +Licensed under the BSD License. +http://yuilibrary.com/license/ +*/ + +YUI.add('series-cartesian', function (Y, NAME) { + +/** + * Provides functionality for creating a cartesian chart series. + * + * @module charts + * @submodule series-cartesian + */ +var Y_Lang = Y.Lang; + +/** + * An abstract class for creating series instances with horizontal and vertical axes. + * CartesianSeries provides the core functionality used by the following classes: + * + * + * @class CartesianSeries + * @extends SeriesBase + * @constructor + * @param {Object} config (optional) Configuration parameters. + * @submodule series-base + */ +Y.CartesianSeries = Y.Base.create("cartesianSeries", Y.SeriesBase, [], { + /** + * Storage for `xDisplayName` attribute. + * + * @property _xDisplayName + * @type String + * @private + */ + _xDisplayName: null, + + /** + * Storage for `yDisplayName` attribute. + * + * @property _yDisplayName + * @type String + * @private + */ + _yDisplayName: null, + + /** + * Th x-coordinate for the left edge of the series. + * + * @property _leftOrigin + * @type String + * @private + */ + _leftOrigin: null, + + /** + * The y-coordinate for the bottom edge of the series. + * + * @property _bottomOrigin + * @type String + * @private + */ + _bottomOrigin: null, + + /** + * Adds event listeners. + * + * @method addListeners + * @private + */ + addListeners: function() + { + var xAxis = this.get("xAxis"), + yAxis = this.get("yAxis"); + if(xAxis) + { + this._xDataReadyHandle = xAxis.after("dataReady", Y.bind(this._xDataChangeHandler, this)); + this._xDataUpdateHandle = xAxis.after("dataUpdate", Y.bind(this._xDataChangeHandler, this)); + } + if(yAxis) + { + this._yDataReadyHandle = yAxis.after("dataReady", Y.bind(this._yDataChangeHandler, this)); + this._yDataUpdateHandle = yAxis.after("dataUpdate", Y.bind(this._yDataChangeHandler, this)); + } + this._xAxisChangeHandle = this.after("xAxisChange", this._xAxisChangeHandler); + this._yAxisChangeHandle = this.after("yAxisChange", this._yAxisChangeHandler); + this._stylesChangeHandle = this.after("stylesChange", function() { + var axesReady = this._updateAxisBase(); + if(axesReady) + { + this.draw(); + } + }); + this._widthChangeHandle = this.after("widthChange", function() { + var axesReady = this._updateAxisBase(); + if(axesReady) + { + this.draw(); + } + }); + this._heightChangeHandle = this.after("heightChange", function() { + var axesReady = this._updateAxisBase(); + if(axesReady) + { + this.draw(); + } + }); + this._visibleChangeHandle = this.after("visibleChange", this._handleVisibleChange); + }, + + /** + * Event handler for the xAxisChange event. + * + * @method _xAxisChangeHandler + * @param {Object} e Event object. + * @private + */ + _xAxisChangeHandler: function() + { + var xAxis = this.get("xAxis"); + xAxis.after("dataReady", Y.bind(this._xDataChangeHandler, this)); + xAxis.after("dataUpdate", Y.bind(this._xDataChangeHandler, this)); + }, + + /** + * Event handler the yAxisChange event. + * + * @method _yAxisChangeHandler + * @param {Object} e Event object. + * @private + */ + _yAxisChangeHandler: function() + { + var yAxis = this.get("yAxis"); + yAxis.after("dataReady", Y.bind(this._yDataChangeHandler, this)); + yAxis.after("dataUpdate", Y.bind(this._yDataChangeHandler, this)); + }, + + /** + * Constant used to generate unique id. + * + * @property GUID + * @type String + * @private + */ + GUID: "yuicartesianseries", + + /** + * Event handler for xDataChange event. + * + * @method _xDataChangeHandler + * @param {Object} event Event object. + * @private + */ + _xDataChangeHandler: function() + { + var axesReady = this._updateAxisBase(); + if(axesReady) + { + this.draw(); + } + }, + + /** + * Event handler for yDataChange event. + * + * @method _yDataChangeHandler + * @param {Object} event Event object. + * @private + */ + _yDataChangeHandler: function() + { + var axesReady = this._updateAxisBase(); + if(axesReady) + { + this.draw(); + } + }, + + /** + * Checks to ensure that both xAxis and yAxis data are available. If so, set the `xData` and `yData` attributes + * and return `true`. Otherwise, return `false`. + * + * @method _updateAxisBase + * @return Boolean + * @private + */ + _updateAxisBase: function() + { + var xAxis = this.get("xAxis"), + yAxis = this.get("yAxis"), + xKey = this.get("xKey"), + yKey = this.get("yKey"), + yData, + xData, + xReady, + yReady, + ready; + if(!xAxis || !yAxis || !xKey || !yKey) + { + ready = false; + } + else + { + xData = xAxis.getDataByKey(xKey); + yData = yAxis.getDataByKey(yKey); + if(Y_Lang.isArray(xKey)) + { + xReady = (xData && Y.Object.size(xData) > 0) ? this._checkForDataByKey(xData, xKey) : false; + } + else + { + xReady = xData ? true : false; + } + if(Y_Lang.isArray(yKey)) + { + yReady = (yData && Y.Object.size(yData) > 0) ? this._checkForDataByKey(yData, yKey) : false; + } + else + { + yReady = yData ? true : false; + } + ready = xReady && yReady; + if(ready) + { + this.set("xData", xData); + this.set("yData", yData); + } + } + return ready; + }, + + /** + * Checks to see if all keys of a data object exist and contain data. + * + * @method _checkForDataByKey + * @param {Object} obj The object to check + * @param {Array} keys The keys to check + * @return Boolean + * @private + */ + _checkForDataByKey: function(obj, keys) + { + var i, + len = keys.length, + hasData = false; + for(i = 0; i < len; i = i + 1) + { + if(obj[keys[i]]) + { + hasData = true; + break; + } + } + return hasData; + }, + + /** + * Draws the series is the xAxis and yAxis data are both available. + * + * @method validate + * @private + */ + validate: function() + { + if((this.get("xData") && this.get("yData")) || this._updateAxisBase()) + { + this.draw(); + } + else + { + this.fire("drawingComplete"); + } + }, + + /** + * Calculates the coordinates for the series. + * + * @method setAreaData + * @protected + */ + setAreaData: function() + { + var w = this.get("width"), + h = this.get("height"), + xAxis = this.get("xAxis"), + yAxis = this.get("yAxis"), + xData = this._copyData(this.get("xData")), + yData = this._copyData(this.get("yData")), + direction = this.get("direction"), + dataLength = direction === "vertical" ? yData.length : xData.length, + xOffset = xAxis.getEdgeOffset(xAxis.getTotalMajorUnits(), w), + yOffset = yAxis.getEdgeOffset(yAxis.getTotalMajorUnits(), h), + padding = this.get("styles").padding, + leftPadding = padding.left, + topPadding = padding.top, + dataWidth = w - (leftPadding + padding.right + xOffset * 2), + dataHeight = h - (topPadding + padding.bottom + yOffset * 2), + xMax = xAxis.get("maximum"), + xMin = xAxis.get("minimum"), + yMax = yAxis.get("maximum"), + yMin = yAxis.get("minimum"), + xScaleFactor = dataWidth / (xMax - xMin), + yScaleFactor = dataHeight / (yMax - yMin), + graphic = this.get("graphic"), + xcoords, + ycoords; + graphic.set("width", w); + graphic.set("height", h); + //Assuming a vertical graph has a range/category for its vertical axis. + if(direction === "vertical") + { + yData = yData.reverse(); + } + this._leftOrigin = Math.round(((0 - xMin) * xScaleFactor) + leftPadding + xOffset); + this._bottomOrigin = Math.round((dataHeight + topPadding + yOffset)); + if(yMin < 0) + { + this._bottomOrigin = this._bottomOrigin - ((0 - yMin) * yScaleFactor); + } + xcoords = this._getXCoords(xData, xMin, dataWidth, xScaleFactor, xOffset, dataLength, leftPadding); + ycoords = this._getYCoords(yData, yMin, dataHeight, yScaleFactor, yOffset, dataLength, topPadding); + this.set("xcoords", xcoords); + this.set("ycoords", ycoords); + this._dataLength = dataLength; + this._setXMarkerPlane(xcoords, dataLength); + this._setYMarkerPlane(ycoords, dataLength); + }, + + /** + * Used to cache xData and yData in the setAreaData method. Returns a copy of an + * array if an array is received as the param and returns an object literal of + * array copies if an object literal is received as the param. + * + * @method _copyData + * @param {Array|Object} val The object or array to be copied. + * @return Array|Object + * @private + */ + _copyData: function(val) + { + var copy, + key; + if(Y_Lang.isArray(val)) + { + copy = val.concat(); + } + else + { + copy = {}; + for(key in val) + { + if(val.hasOwnProperty(key)) + { + copy[key] = val[key].concat(); + } + } + } + return copy; + }, + + /** + * Sets the marker plane for the series when the coords argument is an array. + * If the coords argument is an object literal no marker plane is set. + * + * @method _setXMarkerPlane + * @param {Array|Object} coords An array of x coordinates or an object literal + * containing key value pairs mapped to an array of coordinates. + * @param {Number} dataLength The length of data for the series. + * @private + */ + _setXMarkerPlane: function(coords, dataLength) + { + var i = 0, + xMarkerPlane = [], + xMarkerPlaneOffset = this.get("xMarkerPlaneOffset"), + nextX; + if(Y_Lang.isArray(coords)) + { + for(i = 0; i < dataLength; i = i + 1) + { + nextX = coords[i]; + xMarkerPlane.push({start:nextX - xMarkerPlaneOffset, end: nextX + xMarkerPlaneOffset}); + } + this.set("xMarkerPlane", xMarkerPlane); + } + }, + + /** + * Sets the marker plane for the series when the coords argument is an array. + * If the coords argument is an object literal no marker plane is set. + * + * @method _setYMarkerPlane + * @param {Array|Object} coords An array of y coordinates or an object literal + * containing key value pairs mapped to an array of coordinates. + * @param {Number} dataLength The length of data for the series. + * @private + */ + _setYMarkerPlane: function(coords, dataLength) + { + var i = 0, + yMarkerPlane = [], + yMarkerPlaneOffset = this.get("yMarkerPlaneOffset"), + nextY; + if(Y_Lang.isArray(coords)) + { + for(i = 0; i < dataLength; i = i + 1) + { + nextY = coords[i]; + yMarkerPlane.push({start:nextY - yMarkerPlaneOffset, end: nextY + yMarkerPlaneOffset}); + } + this.set("yMarkerPlane", yMarkerPlane); + } + }, + + /** + * Gets the x-coordinates for a series. Used by the setAreaData method. + * Returns an array when an array is received as the first argument. + * Returns an object literal when an object literal is received as the first argument. + * + * @method _getXCoords + * @param {Array|Object} xData An array of data values mapped to the x axis or an + * object literal containing key values pairs of data values mapped to the x axis. + * @param {Number} xMin The minimum value of the x axis. + * @param {Number} dataWidth The width used to calculate the x-coordinates. + * @param {Number} xScaleFactor The ratio used to calculate x-coordinates. + * @param {Number} xOffset The distance of the first and last x-coordinate from the + * beginning and end of the x-axis. + * @param {Number} dataLength The number of data points in the arrays. + * @param {Number} leftPadding The left padding of the series. + * @return Array|Object + * @private + */ + _getXCoords: function(xData, xMin, dataWidth, xScaleFactor, xOffset, dataLength, leftPadding) + { + var isNumber = Y_Lang.isNumber, + xcoords, + xValue, + nextX, + key, + i; + if(Y_Lang.isArray(xData)) + { + xcoords = []; + for (i = 0; i < dataLength; ++i) + { + xValue = parseFloat(xData[i]); + if(isNumber(xValue)) + { + nextX = (((xValue - xMin) * xScaleFactor) + leftPadding + xOffset); + } + else + { + nextX = NaN; + } + xcoords.push(nextX); + } + } + else + { + xcoords = {}; + for(key in xData) + { + if(xData.hasOwnProperty(key)) + { + xcoords[key] = this._getXCoords.apply( + this, + [xData[key], xMin, dataWidth, xScaleFactor, xOffset, dataLength, leftPadding] + ); + } + } + } + return xcoords; + }, + + /** + * Gets the y-coordinates for a series. Used by the setAreaData method. + * Returns an array when an array is received as the first argument. + * Returns an object literal when an object literal is received as the first argument. + * + * @method _getYCoords + * @param {Array|Object} yData An array of data values mapped to the y axis or an + * object literal containing key values pairs of data values mapped to the y axis. + * @param {Number} yMin The minimum value of the y axis. + * @param {Number} dataHeight The height used to calculate the y-coordinates. + * @param {Number} yScaleFactor The ratio used to calculate y-coordinates. + * @param {Number} yOffset The distance of the first and last y-coordinate from the beginning and end of the y-axis. + * @param {Number} dataLength The number of data points in the arrays. + * @param {Number} topPadding The top padding of the series. + * @return Array|Object + * @private + */ + _getYCoords: function(yData, yMin, dataHeight, yScaleFactor, yOffset, dataLength, topPadding) + { + var isNumber = Y_Lang.isNumber, + ycoords, + yValue, + nextY, + key, + i; + if(Y_Lang.isArray(yData)) + { + ycoords = []; + for (i = 0; i < dataLength; ++i) + { + yValue = parseFloat(yData[i]); + if(isNumber(yValue)) + { + nextY = ((dataHeight + topPadding + yOffset) - (yValue - yMin) * yScaleFactor); + } + else + { + nextY = NaN; + } + ycoords.push(nextY); + } + } + else + { + ycoords = {}; + for(key in yData) + { + if(yData.hasOwnProperty(key)) + { + ycoords[key] = this._getYCoords.apply( + this, + [yData[key], yMin, dataHeight, yScaleFactor, yOffset, dataLength, topPadding] + ); + } + } + } + return ycoords; + }, + + /** + * Finds the first valid index of an array coordinates. + * + * @method _getFirstValidIndex + * @param {Array} coords An array of x or y coordinates. + * @return Number + * @private + */ + _getFirstValidIndex: function(coords) + { + var coord, + i = -1, + limit = coords.length; + while(!Y_Lang.isNumber(coord) && i < limit) + { + i += 1; + coord = coords[i]; + } + return i; + }, + + /** + * Finds the last valid index of an array coordinates. + * + * @method _getLastValidIndex + * @param {Array} coords An array of x or y coordinates. + * @return Number + * @private + */ + _getLastValidIndex: function(coords) + { + var coord, + i = coords.length, + limit = -1; + while(!Y_Lang.isNumber(coord) && i > limit) + { + i -= 1; + coord = coords[i]; + } + return i; + }, + + /** + * Draws the series. + * + * @method draw + * @protected + */ + draw: function() + { + var w = this.get("width"), + h = this.get("height"), + xcoords, + ycoords; + if(this.get("rendered")) + { + if((isFinite(w) && isFinite(h) && w > 0 && h > 0) && + ((this.get("xData") && this.get("yData")) || + this._updateAxisBase())) + { + if(this._drawing) + { + this._callLater = true; + return; + } + this._drawing = true; + this._callLater = false; + this.setAreaData(); + xcoords = this.get("xcoords"); + ycoords = this.get("ycoords"); + if(xcoords && ycoords && xcoords.length > 0) + { + this.drawSeries(); + } + this._drawing = false; + if(this._callLater) + { + this.draw(); + } + else + { + this._toggleVisible(this.get("visible")); + this.fire("drawingComplete"); + } + } + } + }, + + /** + * Default value for plane offsets when the parent chart's `interactiveType` is `planar`. + * + * @property _defaultPlaneOffset + * @type Number + * @private + */ + _defaultPlaneOffset: 4, + + /** + * Destructor implementation for the CartesianSeries class. + * Calls destroy on all Graphic instances. + * + * @method destructor + * @protected + */ + destructor: function() + { + if(this.get("rendered")) + { + if(this._xDataReadyHandle) + { + this._xDataReadyHandle.detach(); + } + if(this._xDataUpdateHandle) + { + this._xDataUpdateHandle.detach(); + } + if(this._yDataReadyHandle) + { + this._yDataReadyHandle.detach(); + } + if(this._yDataUpdateHandle) + { + this._yDataUpdateHandle.detach(); + } + this._xAxisChangeHandle.detach(); + this._yAxisChangeHandle.detach(); + } + } + /** + * Event handle for the x-axis' dataReady event. + * + * @property _xDataReadyHandle + * @type {EventHandle} + * @private + */ + + /** + * Event handle for the x-axis dataUpdate event. + * + * @property _xDataUpdateHandle + * @type {EventHandle} + * @private + */ + + /** + * Event handle for the y-axis dataReady event. + * + * @property _yDataReadyHandle + * @type {EventHandle} + * @private + */ + + /** + * Event handle for the y-axis dataUpdate event. + * @property _yDataUpdateHandle + * @type {EventHandle} + * @private + */ + + /** + * Event handle for the xAxisChange event. + * @property _xAxisChangeHandle + * @type {EventHandle} + * @private + */ + + /** + * Event handle for the yAxisChange event. + * @property _yAxisChangeHandle + * @type {EventHandle} + * @private + */ + + /** + * Event handle for the stylesChange event. + * @property _stylesChangeHandle + * @type {EventHandle} + * @private + */ + + /** + * Event handle for the widthChange event. + * @property _widthChangeHandle + * @type {EventHandle} + * @private + */ + + /** + * Event handle for the heightChange event. + * @property _heightChangeHandle + * @type {EventHandle} + * @private + */ + + /** + * Event handle for the visibleChange event. + * @property _visibleChangeHandle + * @type {EventHandle} + * @private + */ +}, { + ATTRS: { + /** + * An array of all series of the same type used within a chart application. + * + * @attribute seriesTypeCollection + * @type Array + */ + seriesTypeCollection: {}, + + /** + * Name used for for displaying data related to the x-coordinate. + * + * @attribute xDisplayName + * @type String + */ + xDisplayName: { + getter: function() + { + return this._xDisplayName || this.get("xKey"); + }, + + setter: function(val) + { + this._xDisplayName = val.toString(); + return val; + } + }, + + /** + * Name used for for displaying data related to the y-coordinate. + * + * @attribute yDisplayName + * @type String + */ + yDisplayName: { + getter: function() + { + return this._yDisplayName || this.get("yKey"); + }, + + setter: function(val) + { + this._yDisplayName = val.toString(); + return val; + } + }, + + /** + * Name used for for displaying category data + * + * @attribute categoryDisplayName + * @type String + * @readOnly + */ + categoryDisplayName: { + lazyAdd: false, + + getter: function() + { + return this.get("direction") === "vertical" ? this.get("yDisplayName") : this.get("xDisplayName"); + }, + + setter: function(val) + { + if(this.get("direction") === "vertical") + { + this._yDisplayName = val; + } + else + { + this._xDisplayName = val; + } + return val; + } + }, + + /** + * Name used for for displaying value data + * + * @attribute valueDisplayName + * @type String + * @readOnly + */ + valueDisplayName: { + lazyAdd: false, + + getter: function() + { + return this.get("direction") === "vertical" ? this.get("xDisplayName") : this.get("yDisplayName"); + }, + + setter: function(val) + { + if(this.get("direction") === "vertical") + { + this._xDisplayName = val; + } + else + { + this._yDisplayName = val; + } + return val; + } + }, + + /** + * Read-only attribute indicating the type of series. + * + * @attribute type + * @type String + * @default cartesian + */ + type: { + value: "cartesian" + }, + + /** + * Order of this instance of this `type`. + * + * @attribute order + * @type Number + */ + order: {}, + + /** + * Order of the instance + * + * @attribute graphOrder + * @type Number + */ + graphOrder: {}, + + /** + * x coordinates for the series. + * + * @attribute xcoords + * @type Array + */ + xcoords: {}, + + /** + * y coordinates for the series + * + * @attribute ycoords + * @type Array + */ + ycoords: {}, + + /** + * Reference to the `Axis` instance used for assigning + * x-values to the graph. + * + * @attribute xAxis + * @type Axis + */ + xAxis: {}, + + /** + * Reference to the `Axis` instance used for assigning + * y-values to the graph. + * + * @attribute yAxis + * @type Axis + */ + yAxis: {}, + + /** + * Indicates which array to from the hash of value arrays in + * the x-axis `Axis` instance. + * + * @attribute xKey + * @type String + */ + xKey: { + setter: function(val) + { + if(Y_Lang.isArray(val)) + { + return val; + } + else + { + return val.toString(); + } + } + }, + + /** + * Indicates which array to from the hash of value arrays in + * the y-axis `Axis` instance. + * + * @attribute yKey + * @type String + */ + yKey: { + setter: function(val) + { + if(Y_Lang.isArray(val)) + { + return val; + } + else + { + return val.toString(); + } + } + }, + + /** + * Array of x values for the series. + * + * @attribute xData + * @type Array + */ + xData: {}, + + /** + * Array of y values for the series. + * + * @attribute yData + * @type Array + */ + yData: {}, + + /** + * Collection of area maps along the xAxis. Used to determine mouseover for multiple + * series. + * + * @attribute xMarkerPlane + * @type Array + */ + xMarkerPlane: {}, + + /** + * Collection of area maps along the yAxis. Used to determine mouseover for multiple + * series. + * + * @attribute yMarkerPlane + * @type Array + */ + yMarkerPlane: {}, + + /** + * Distance from a data coordinate to the left/right for setting a hotspot. + * + * @attribute xMarkerPlaneOffset + * @type Number + */ + xMarkerPlaneOffset: { + getter: function() { + var marker = this.get("styles").marker; + if(marker && marker.width && isFinite(marker.width)) + { + return marker.width * 0.5; + } + return this._defaultPlaneOffset; + } + }, + + /** + * Distance from a data coordinate to the top/bottom for setting a hotspot. + * + * @attribute yMarkerPlaneOffset + * @type Number + */ + yMarkerPlaneOffset: { + getter: function() { + var marker = this.get("styles").marker; + if(marker && marker.height && isFinite(marker.height)) + { + return marker.height * 0.5; + } + return this._defaultPlaneOffset; + } + }, + + /** + * Direction of the series + * + * @attribute direction + * @type String + */ + direction: { + value: "horizontal" + } + } +}); + + +}, '3.10.3', {"requires": ["series-base"]});