UNPKG

yuidoc-asp

Version:

YUIDoc, YUI's JavaScript Documentation engine tweaked to work with VB/VBScript comments.

840 lines (780 loc) 22.6 kB
/** * The CartesianSeries class creates a chart with horizontal and vertical axes. * * @module charts * @class CartesianSeries * @extends Base * @uses Renderer * @constructor */ Y.CartesianSeries = Y.Base.create("cartesianSeries", Y.Base, [Y.Renderer], { /** * 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, /** * @method render * @private */ render: function() { this._setCanvas(); this.addListeners(); this.set("rendered", true); this.validate(); }, /** * Adds event listeners. * * @method addListeners * @private */ addListeners: function() { var xAxis = this.get("xAxis"), yAxis = this.get("yAxis"); if(xAxis) { xAxis.after("dataReady", Y.bind(this._xDataChangeHandler, this)); xAxis.after("dataUpdate", Y.bind(this._xDataChangeHandler, this)); } if(yAxis) { yAxis.after("dataReady", Y.bind(this._yDataChangeHandler, this)); yAxis.after("dataUpdate", Y.bind(this._yDataChangeHandler, this)); } this.after("xAxisChange", this._xAxisChangeHandler); this.after("yAxisChange", this._yAxisChangeHandler); this.after("stylesChange", function(e) { var axesReady = this._updateAxisData(); if(axesReady) { this.draw(); } }); this.after("widthChange", function(e) { var axesReady = this._updateAxisData(); if(axesReady) { this.draw(); } }); this.after("heightChange", function(e) { var axesReady = this._updateAxisData(); if(axesReady) { this.draw(); } }); this.after("visibleChange", this._handleVisibleChange); }, /** * Event handler for the xAxisChange event. * * @method _xAxisChangeHandler * @param {Object} e Event object. * @private */ _xAxisChangeHandler: function(e) { 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(e) { 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(event) { var axesReady = this._updateAxisData(); if(axesReady) { this.draw(); } }, /** * Event handler for yDataChange event. * * @method _yDataChangeHandler * @param {Object} event Event object. * @private */ _yDataChangeHandler: function(event) { var axesReady = this._updateAxisData(); 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 _updateAxisData * @return Boolean * @private */ _updateAxisData: function() { var xAxis = this.get("xAxis"), yAxis = this.get("yAxis"), xKey = this.get("xKey"), yKey = this.get("yKey"), yData, xData; if(!xAxis || !yAxis || !xKey || !yKey) { return false; } xData = xAxis.getDataByKey(xKey); yData = yAxis.getDataByKey(yKey); if(!xData || !yData) { return false; } this.set("xData", xData.concat()); this.set("yData", yData.concat()); return true; }, /** * 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._updateAxisData()) { this.draw(); } else { this.fire("drawingComplete"); } }, /** * Creates a `Graphic` instance. * * @method _setCanvas * @protected */ _setCanvas: function() { var graph = this.get("graph"), graphic = graph.get("graphic"); this.set("graphic", graphic); }, /** * Calculates the coordinates for the series. * * @method setAreaData * @protected */ setAreaData: function() { var isNumber = Y_Lang.isNumber, nextX, nextY, graph = this.get("graph"), w = graph.get("width"), h = graph.get("height"), xAxis = this.get("xAxis"), yAxis = this.get("yAxis"), xData = this.get("xData").concat(), yData = this.get("yData").concat(), xValue, yValue, xOffset = xAxis.getEdgeOffset(xData.length, w), yOffset = yAxis.getEdgeOffset(yData.length, h), padding = this.get("styles").padding, leftPadding = padding.left, topPadding = padding.top, dataWidth = w - (leftPadding + padding.right + xOffset), dataHeight = h - (topPadding + padding.bottom + yOffset), xcoords = [], ycoords = [], xMax = xAxis.get("maximum"), xMin = xAxis.get("minimum"), yMax = yAxis.get("maximum"), yMin = yAxis.get("minimum"), xScaleFactor = dataWidth / (xMax - xMin), yScaleFactor = dataHeight / (yMax - yMin), dataLength, direction = this.get("direction"), i = 0, xMarkerPlane = [], yMarkerPlane = [], xMarkerPlaneOffset = this.get("xMarkerPlaneOffset"), yMarkerPlaneOffset = this.get("yMarkerPlaneOffset"), graphic = this.get("graphic"); graphic.set("width", w); graphic.set("height", h); dataLength = xData.length; xOffset *= 0.5; yOffset *= 0.5; //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)); for (; i < dataLength; ++i) { xValue = parseFloat(xData[i]); yValue = parseFloat(yData[i]); if(isNumber(xValue)) { nextX = Math.round((((xValue - xMin) * xScaleFactor) + leftPadding + xOffset)); } else { nextX = NaN; } if(isNumber(yValue)) { nextY = Math.round(((dataHeight + topPadding + yOffset) - (yValue - yMin) * yScaleFactor)); } else { nextY = NaN; } xcoords.push(nextX); ycoords.push(nextY); xMarkerPlane.push({start:nextX - xMarkerPlaneOffset, end: nextX + xMarkerPlaneOffset}); yMarkerPlane.push({start:nextY - yMarkerPlaneOffset, end: nextY + yMarkerPlaneOffset}); } this.set("xcoords", xcoords); this.set("ycoords", ycoords); this.set("xMarkerPlane", xMarkerPlane); this.set("yMarkerPlane", yMarkerPlane); this._dataLength = dataLength; }, /** * Draws the series. * * @method draw * @protected */ draw: function() { var graph = this.get("graph"), w = graph.get("width"), h = graph.get("height"); if(this.get("rendered")) { if((isFinite(w) && isFinite(h) && w > 0 && h > 0) && ((this.get("xData") && this.get("yData")) || this._updateAxisData())) { if(this._drawing) { this._callLater = true; return; } this._drawing = true; this._callLater = false; this.setAreaData(); if(this.get("xcoords") && this.get("ycoords")) { 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, /** * Gets the default value for the `styles` attribute. Overrides * base implementation. * * @method _getDefaultStyles * @return Object * @protected */ _getDefaultStyles: function() { return {padding:{ top: 0, left: 0, right: 0, bottom: 0 }}; }, /** * Collection of default colors used for lines in a series when not specified by user. * * @property _defaultLineColors * @type Array * @protected */ _defaultLineColors:["#426ab3", "#d09b2c", "#000000", "#b82837", "#b384b5", "#ff7200", "#779de3", "#cbc8ba", "#7ed7a6", "#007a6c"], /** * Collection of default colors used for marker fills in a series when not specified by user. * * @property _defaultFillColors * @type Array * @protected */ _defaultFillColors:["#6084d0", "#eeb647", "#6c6b5f", "#d6484f", "#ce9ed1", "#ff9f3b", "#93b7ff", "#e0ddd0", "#94ecba", "#309687"], /** * Collection of default colors used for marker borders in a series when not specified by user. * * @property _defaultBorderColors * @type Array * @protected */ _defaultBorderColors:["#205096", "#b38206", "#000000", "#94001e", "#9d6fa0", "#e55b00", "#5e85c9", "#adab9e", "#6ac291", "#006457"], /** * Collection of default colors used for area fills, histogram fills and pie fills in a series when not specified by user. * * @property _defaultSliceColors * @type Array * @protected */ _defaultSliceColors: ["#66007f", "#a86f41", "#295454", "#996ab2", "#e8cdb7", "#90bdbd","#000000","#c3b8ca", "#968373", "#678585"], /** * Parses a color based on a series order and type. * * @method _getDefaultColor * @param {Number} index Index indicating the series order. * @param {String} type Indicates which type of object needs the color. * @return String * @protected */ _getDefaultColor: function(index, type) { var colors = { line: this._defaultLineColors, fill: this._defaultFillColors, border: this._defaultBorderColors, slice: this._defaultSliceColors }, col = colors[type], l = col.length; index = index || 0; if(index >= l) { index = index % l; } type = type || "fill"; return colors[type][index]; }, /** * Shows/hides contents of the series. * * @method _handleVisibleChange * @param {Object} e Event object. * @protected */ _handleVisibleChange: function(e) { this._toggleVisible(this.get("visible")); }, /** * Returns the sum of all values for the series. * * @method getTotalValues * @return Number */ getTotalValues: function() { var total = this.get("valueAxis").getTotalByKey(this.get("valueKey")); return total; }, /** * Destructor implementation for the CartesianSeries class. Calls destroy on all Graphic instances. * * @method destructor * @protected */ destructor: function() { if(this._path) { this._path.destroy(); } if(this._lineGraphic) { this._lineGraphic.destroy(); this._lineGraphic = null; } if(this.get("graphic")) { this.get("graphic").destroy(); } } }, { ATTRS: { /** * 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: { readOnly: true, getter: function() { return this.get("direction") == "vertical" ? this.get("yDisplayName") : this.get("xDisplayName"); } }, /** * Name used for for displaying value data * * @attribute valueDisplayName * @type String * @readOnly */ valueDisplayName: { readOnly: true, getter: function() { return this.get("direction") == "vertical" ? this.get("xDisplayName") : this.get("yDisplayName"); } }, /** * 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 `Chart` application. * * @attribute chart * @type ChartBase * @readOnly */ chart: { readOnly: true, getter: function() { return this.get("graph").get("chart"); } }, /** * Reference to the `Graph` in which the series is drawn into. * * @attribute graph * @type Graph */ graph: {}, /** * 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) { 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) { 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: {}, /** * Indicates whether the Series has been through its initial set up. * * @attribute rendered * @type Boolean */ rendered: { value: false }, /* * Returns the width of the parent graph * * @attribute width * @type Number */ width: { readOnly: true, getter: function() { this.get("graph").get("width"); } }, /** * Returns the height of the parent graph * * @attribute height * @type Number */ height: { readOnly: true, getter: function() { this.get("graph").get("height"); } }, /** * Indicates whether to show the series * * @attribute visible * @type Boolean * @default true */ visible: { value: true }, /** * 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" }, /** * Indicates whether or not markers for a series will be grouped and rendered in a single complex shape instance. * * @attribute groupMarkers * @type Boolean */ groupMarkers: { getter: function() { if(this._groupMarkers === undefined) { return this.get("graph").get("groupMarkers"); } else { return this._groupMarkers; } }, setter: function(val) { this._groupMarkers = val; return val; } } } });