AutorÃa | Ultima modificación | Ver Log |
YUI.add('charts-base', function (Y, NAME) {/*** Provides functionality for creating charts.** @module charts* @submodule charts-base*/var CONFIG = Y.config,WINDOW = CONFIG.win,DOCUMENT = CONFIG.doc,Y_Lang = Y.Lang,IS_STRING = Y_Lang.isString,_getClassName = Y.ClassNameManager.getClassName,SERIES_MARKER = _getClassName("seriesmarker");/*** Gridlines draws gridlines on a Graph.** @class Gridlines* @constructor* @extends Base* @uses Renderer* @param {Object} config (optional) Configuration parameters.* @submodule charts-base*/Y.Gridlines = Y.Base.create("gridlines", Y.Base, [Y.Renderer], {/*** Reference to the `Path` element used for drawing Gridlines.** @property _path* @type Path* @private*/_path: null,/*** Removes the Gridlines.** @method remove* @private*/remove: function(){var path = this._path;if(path){path.destroy();}},/*** Draws the gridlines** @method draw* @protected*/draw: function(){if(this.get("axis") && this.get("graph")){this._drawGridlines();}},/*** Algorithm for drawing gridlines** @method _drawGridlines* @private*/_drawGridlines: function(){var path,axis = this.get("axis"),axisPosition = axis.get("position"),points,i = 0,l,direction = this.get("direction"),graph = this.get("graph"),w = graph.get("width"),h = graph.get("height"),line = this.get("styles").line,color = line.color,weight = line.weight,alpha = line.alpha,count = this.get("count"),length,lineFunction;if(isFinite(w) && isFinite(h) && w > 0 && h > 0){if(count && Y.Lang.isNumber(count)){points = this._getPoints(count, w, h);}else if(axisPosition !== "none" && axis && axis.get("tickPoints")){points = axis.get("tickPoints");}else{points = this._getPoints(axis.get("styles").majorUnit.count, w, h);}l = points.length;path = graph.get("gridlines");path.set("width", w);path.set("height", h);path.set("stroke", {weight: weight,color: color,opacity: alpha});if(direction === "vertical"){lineFunction = this._verticalLine;length = h;}else{lineFunction = this._horizontalLine;length = w;}for(i = 0; i < l; i = i + 1){lineFunction(path, points[i], length);}path.end();}},/*** Calculates the coordinates for the gridlines based on a count.** @method _getPoints* @param {Number} count Number of gridlines* @return Array* @private*/_getPoints: function(count, w, h){var i,points = [],multiplier,divisor = count - 1;for(i = 0; i < count; i = i + 1){multiplier = i/divisor;points[i] = {x: w * multiplier,y: h * multiplier};}return points;},/*** Algorithm for horizontal lines.** @method _horizontalLine* @param {Path} path Reference to path element* @param {Object} pt Coordinates corresponding to a major unit of an axis.* @param {Number} w Width of the Graph* @private*/_horizontalLine: function(path, pt, w){path.moveTo(0, pt.y);path.lineTo(w, pt.y);},/*** Algorithm for vertical lines.** @method _verticalLine* @param {Path} path Reference to path element* @param {Object} pt Coordinates corresponding to a major unit of an axis.* @param {Number} h Height of the Graph* @private*/_verticalLine: function(path, pt, h){path.moveTo(pt.x, 0);path.lineTo(pt.x, h);},/*** Gets the default value for the `styles` attribute. Overrides* base implementation.** @method _getDefaultStyles* @return Object* @protected*/_getDefaultStyles: function(){var defs = {line: {color:"#f0efe9",weight: 1,alpha: 1}};return defs;}},{ATTRS: {/*** Indicates the direction of the gridline.** @attribute direction* @type String*/direction: {},/*** Indicate the `Axis` in which to bind* the gridlines.** @attribute axis* @type Axis*/axis: {},/*** Indicates the `Graph` in which the gridlines* are drawn.** @attribute graph* @type Graph*/graph: {},/*** Indicates the number of gridlines to display. If no value is set, gridlines will equal the number of ticks in* the corresponding axis.** @attribute count* @type Number*/count: {}}});/*** Graph manages and contains series instances for a `CartesianChart`* instance.** @class Graph* @constructor* @extends Widget* @uses Renderer* @submodule charts-base*/Y.Graph = Y.Base.create("graph", Y.Widget, [Y.Renderer], {/*** @method bindUI* @private*/bindUI: function(){var bb = this.get("boundingBox");bb.setStyle("position", "absolute");this.after("widthChange", this._sizeChangeHandler);this.after("heightChange", this._sizeChangeHandler);this.after("stylesChange", this._updateStyles);this.after("groupMarkersChange", this._drawSeries);},/*** @method syncUI* @private*/syncUI: function(){var background,cb,bg,sc = this.get("seriesCollection"),series,i = 0,len = sc ? sc.length : 0,hgl = this.get("horizontalGridlines"),vgl = this.get("verticalGridlines");if(this.get("showBackground")){background = this.get("background");cb = this.get("contentBox");bg = this.get("styles").background;bg.stroke = bg.border;bg.stroke.opacity = bg.stroke.alpha;bg.fill.opacity = bg.fill.alpha;bg.width = this.get("width");bg.height = this.get("height");bg.type = bg.shape;background.set(bg);}for(; i < len; ++i){series = sc[i];if(series instanceof Y.SeriesBase){series.render();}}if(hgl && hgl instanceof Y.Gridlines){hgl.draw();}if(vgl && vgl instanceof Y.Gridlines){vgl.draw();}},/*** Object of arrays containing series mapped to a series type.** @property seriesTypes* @type Object* @private*/seriesTypes: null,/*** Returns a series instance based on an index.** @method getSeriesByIndex* @param {Number} val index of the series* @return CartesianSeries*/getSeriesByIndex: function(val){var col = this.get("seriesCollection"),series;if(col && col.length > val){series = col[val];}return series;},/*** Returns a series instance based on a key value.** @method getSeriesByKey* @param {String} val key value of the series* @return CartesianSeries*/getSeriesByKey: function(val){var obj = this._seriesDictionary,series;if(obj && obj.hasOwnProperty(val)){series = obj[val];}return series;},/*** Adds dispatcher to a `_dispatcher` used to* to ensure all series have redrawn before for firing event.** @method addDispatcher* @param {CartesianSeries} val series instance to add* @protected*/addDispatcher: function(val){if(!this._dispatchers){this._dispatchers = [];}this._dispatchers.push(val);},/*** Collection of series to be displayed in the graph.** @property _seriesCollection* @type Array* @private*/_seriesCollection: null,/*** Object containing key value pairs of `CartesianSeries` instances.** @property _seriesDictionary* @type Object* @private*/_seriesDictionary: null,/*** Parses series instances to be displayed in the graph.** @method _parseSeriesCollection* @param {Array} Collection of `CartesianSeries` instances or objects container `CartesianSeries` attributes values.* @private*/_parseSeriesCollection: function(val){if(!val){return;}var len = val.length,i = 0,series,seriesKey;this._seriesCollection = [];this._seriesDictionary = {};this.seriesTypes = [];for(; i < len; ++i){series = val[i];if(!(series instanceof Y.CartesianSeries) && !(series instanceof Y.PieSeries)){this._createSeries(series);continue;}this._addSeries(series);}len = this._seriesCollection.length;for(i = 0; i < len; ++i){series = this.get("seriesCollection")[i];seriesKey = series.get("direction") === "horizontal" ? "yKey" : "xKey";this._seriesDictionary[series.get(seriesKey)] = series;}},/*** Adds a series to the graph.** @method _addSeries* @param {CartesianSeries} series Series to add to the graph.* @private*/_addSeries: function(series){var type = series.get("type"),seriesCollection = this.get("seriesCollection"),graphSeriesLength = seriesCollection.length,seriesTypes = this.seriesTypes,typeSeriesCollection;if(!series.get("graph")){series.set("graph", this);}seriesCollection.push(series);if(!seriesTypes.hasOwnProperty(type)){this.seriesTypes[type] = [];}typeSeriesCollection = this.seriesTypes[type];series.set("graphOrder", graphSeriesLength);series.set("order", typeSeriesCollection.length);typeSeriesCollection.push(series);series.set("seriesTypeCollection", typeSeriesCollection);this.addDispatcher(series);series.after("drawingComplete", Y.bind(this._drawingCompleteHandler, this));this.fire("seriesAdded", series);},/*** Creates a `CartesianSeries` instance from an object containing attribute key value pairs. The key value pairs include* attributes for the specific series and a type value which defines the type of series to be used.** @method createSeries* @param {Object} seriesData Series attribute key value pairs.* @private*/_createSeries: function(seriesData){var type = seriesData.type,seriesCollection = this.get("seriesCollection"),seriesTypes = this.seriesTypes,typeSeriesCollection,SeriesClass,series;seriesData.graph = this;if(!seriesTypes.hasOwnProperty(type)){seriesTypes[type] = [];}typeSeriesCollection = seriesTypes[type];seriesData.graph = this;seriesData.order = typeSeriesCollection.length;seriesData.graphOrder = seriesCollection.length;SeriesClass = this._getSeries(seriesData.type);series = new SeriesClass(seriesData);this.addDispatcher(series);series.after("drawingComplete", Y.bind(this._drawingCompleteHandler, this));typeSeriesCollection.push(series);seriesCollection.push(series);series.set("seriesTypeCollection", typeSeriesCollection);if(this.get("rendered")){series.render();}},/*** String reference for pre-defined `Series` classes.** @property _seriesMap* @type Object* @private*/_seriesMap: {line : Y.LineSeries,column : Y.ColumnSeries,bar : Y.BarSeries,area : Y.AreaSeries,candlestick : Y.CandlestickSeries,ohlc : Y.OHLCSeries,stackedarea : Y.StackedAreaSeries,stackedline : Y.StackedLineSeries,stackedcolumn : Y.StackedColumnSeries,stackedbar : Y.StackedBarSeries,markerseries : Y.MarkerSeries,spline : Y.SplineSeries,areaspline : Y.AreaSplineSeries,stackedspline : Y.StackedSplineSeries,stackedareaspline : Y.StackedAreaSplineSeries,stackedmarkerseries : Y.StackedMarkerSeries,pie : Y.PieSeries,combo : Y.ComboSeries,stackedcombo : Y.StackedComboSeries,combospline : Y.ComboSplineSeries,stackedcombospline : Y.StackedComboSplineSeries},/*** Returns a specific `CartesianSeries` class based on key value from a look up table of a direct reference to a* class. When specifying a key value, the following options are available:** <table>* <tr><th>Key Value</th><th>Class</th></tr>* <tr><td>line</td><td>Y.LineSeries</td></tr>* <tr><td>column</td><td>Y.ColumnSeries</td></tr>* <tr><td>bar</td><td>Y.BarSeries</td></tr>* <tr><td>area</td><td>Y.AreaSeries</td></tr>* <tr><td>stackedarea</td><td>Y.StackedAreaSeries</td></tr>* <tr><td>stackedline</td><td>Y.StackedLineSeries</td></tr>* <tr><td>stackedcolumn</td><td>Y.StackedColumnSeries</td></tr>* <tr><td>stackedbar</td><td>Y.StackedBarSeries</td></tr>* <tr><td>markerseries</td><td>Y.MarkerSeries</td></tr>* <tr><td>spline</td><td>Y.SplineSeries</td></tr>* <tr><td>areaspline</td><td>Y.AreaSplineSeries</td></tr>* <tr><td>stackedspline</td><td>Y.StackedSplineSeries</td></tr>* <tr><td>stackedareaspline</td><td>Y.StackedAreaSplineSeries</td></tr>* <tr><td>stackedmarkerseries</td><td>Y.StackedMarkerSeries</td></tr>* <tr><td>pie</td><td>Y.PieSeries</td></tr>* <tr><td>combo</td><td>Y.ComboSeries</td></tr>* <tr><td>stackedcombo</td><td>Y.StackedComboSeries</td></tr>* <tr><td>combospline</td><td>Y.ComboSplineSeries</td></tr>* <tr><td>stackedcombospline</td><td>Y.StackedComboSplineSeries</td></tr>* </table>** When referencing a class directly, you can specify any of the above classes or any custom class that extends* `CartesianSeries` or `PieSeries`.** @method _getSeries* @param {String | Object} type Series type.* @return CartesianSeries* @private*/_getSeries: function(type){var seriesClass;if(Y_Lang.isString(type)){seriesClass = this._seriesMap[type];}else{seriesClass = type;}return seriesClass;},/*** Event handler for marker events.** @method _markerEventHandler* @param {Object} e Event object.* @private*/_markerEventHandler: function(e){var type = e.type,markerNode = e.currentTarget,strArr = markerNode.getAttribute("id").split("_"),series = this.getSeriesByIndex(strArr[1]),index = strArr[2];series.updateMarkerState(type, index);},/*** Collection of `CartesianSeries` instances to be redrawn.** @property _dispatchers* @type Array* @private*/_dispatchers: null,/*** Updates the `Graph` styles.** @method _updateStyles* @private*/_updateStyles: function(){var styles = this.get("styles").background,border = styles.border;border.opacity = border.alpha;styles.stroke = border;styles.fill.opacity = styles.fill.alpha;this.get("background").set(styles);this._sizeChangeHandler();},/*** Event handler for size changes.** @method _sizeChangeHandler* @param {Object} e Event object.* @private*/_sizeChangeHandler: function(){var hgl = this.get("horizontalGridlines"),vgl = this.get("verticalGridlines"),w = this.get("width"),h = this.get("height"),bg = this.get("styles").background,weight,background;if(bg && bg.border){weight = bg.border.weight || 0;}if(this.get("showBackground")){background = this.get("background");if(w && h){background.set("width", w);background.set("height", h);}}if(this._gridlines){this._gridlines.clear();}if(hgl && hgl instanceof Y.Gridlines){hgl.draw();}if(vgl && vgl instanceof Y.Gridlines){vgl.draw();}this._drawSeries();},/*** Draws each series.** @method _drawSeries* @private*/_drawSeries: function(){if(this._drawing){this._callLater = true;return;}var sc,i,len,graphic = this.get("graphic");graphic.set("autoDraw", false);graphic.set("width", this.get("width"));graphic.set("height", this.get("height"));this._callLater = false;this._drawing = true;sc = this.get("seriesCollection");i = 0;len = sc ? sc.length : 0;for(; i < len; ++i){sc[i].draw();if((!sc[i].get("xcoords") || !sc[i].get("ycoords")) && !sc[i] instanceof Y.PieSeries){this._callLater = true;break;}}this._drawing = false;if(this._callLater){this._drawSeries();}},/*** Event handler for series drawingComplete event.** @method _drawingCompleteHandler* @param {Object} e Event object.* @private*/_drawingCompleteHandler: function(e){var series = e.currentTarget,graphic,index = Y.Array.indexOf(this._dispatchers, series);if(index > -1){this._dispatchers.splice(index, 1);}if(this._dispatchers.length < 1){graphic = this.get("graphic");if(!graphic.get("autoDraw")){graphic._redraw();}this.fire("chartRendered");}},/*** Gets the default value for the `styles` attribute. Overrides* base implementation.** @method _getDefaultStyles* @return Object* @protected*/_getDefaultStyles: function(){var defs = {background: {shape: "rect",fill:{color:"#faf9f2"},border: {color:"#dad8c9",weight: 1}}};return defs;},/*** Destructor implementation Graph class. Removes all Graphic instances from the widget.** @method destructor* @protected*/destructor: function(){if(this._graphic){this._graphic.destroy();this._graphic = null;}if(this._background){this._background.get("graphic").destroy();this._background = null;}if(this._gridlines){this._gridlines.get("graphic").destroy();this._gridlines = null;}}}, {ATTRS: {/*** The x-coordinate for the graph.** @attribute x* @type Number* @protected*/x: {setter: function(val){this.get("boundingBox").setStyle("left", val + "px");return val;}},/*** The y-coordinate for the graph.** @attribute y* @type Number* @protected*/y: {setter: function(val){this.get("boundingBox").setStyle("top", val + "px");return val;}},/*** Reference to the chart instance using the graph.** @attribute chart* @type ChartBase* @readOnly*/chart: {getter: function() {var chart = this._state.chart || this;return chart;}},/*** Collection of series. When setting the `seriesCollection` the array can contain a combination of either* `CartesianSeries` instances or object literals with properties that will define a series.** @attribute seriesCollection* @type CartesianSeries*/seriesCollection: {getter: function(){return this._seriesCollection;},setter: function(val){this._parseSeriesCollection(val);return this._seriesCollection;}},/*** Indicates whether the `Graph` has a background.** @attribute showBackground* @type Boolean* @default true*/showBackground: {value: true},/*** Read-only hash lookup for all series on in the `Graph`.** @attribute seriesDictionary* @type Object* @readOnly*/seriesDictionary: {readOnly: true,getter: function(){return this._seriesDictionary;}},/*** Reference to the horizontal `Gridlines` instance.** @attribute horizontalGridlines* @type Gridlines* @default null*/horizontalGridlines: {value: null,setter: function(val){var cfg,key,gl = this.get("horizontalGridlines");if(gl && gl instanceof Y.Gridlines){gl.remove();}if(val instanceof Y.Gridlines){gl = val;val.set("graph", this);return val;}else if(val){cfg = {direction: "horizonal",graph: this};for(key in val){if(val.hasOwnProperty(key)){cfg[key] = val[key];}}gl = new Y.Gridlines(cfg);return gl;}}},/*** Reference to the vertical `Gridlines` instance.** @attribute verticalGridlines* @type Gridlines* @default null*/verticalGridlines: {value: null,setter: function(val){var cfg,key,gl = this.get("verticalGridlines");if(gl && gl instanceof Y.Gridlines){gl.remove();}if(val instanceof Y.Gridlines){gl = val;val.set("graph", this);return val;}else if(val){cfg = {direction: "vertical",graph: this};for(key in val){if(val.hasOwnProperty(key)){cfg[key] = val[key];}}gl = new Y.Gridlines(cfg);return gl;}}},/*** Reference to graphic instance used for the background.** @attribute background* @type Graphic* @readOnly*/background: {getter: function(){if(!this._background){this._backgroundGraphic = new Y.Graphic({render:this.get("contentBox")});this._backgroundGraphic.get("node").style.zIndex = 0;this._background = this._backgroundGraphic.addShape({type: "rect"});}return this._background;}},/*** Reference to graphic instance used for gridlines.** @attribute gridlines* @type Graphic* @readOnly*/gridlines: {readOnly: true,getter: function(){if(!this._gridlines){this._gridlinesGraphic = new Y.Graphic({render:this.get("contentBox")});this._gridlinesGraphic.get("node").style.zIndex = 1;this._gridlines = this._gridlinesGraphic.addShape({type: "path"});}return this._gridlines;}},/*** Reference to graphic instance used for series.** @attribute graphic* @type Graphic* @readOnly*/graphic: {readOnly: true,getter: function(){if(!this._graphic){this._graphic = new Y.Graphic({render:this.get("contentBox")});this._graphic.get("node").style.zIndex = 2;this._graphic.set("autoDraw", false);}return this._graphic;}},/*** Indicates whether or not markers for a series will be grouped and rendered in a single complex shape instance.** @attribute groupMarkers* @type Boolean*/groupMarkers: {value: false}/*** Style properties used for drawing a background. Below are the default values:* <dl>* <dt>background</dt><dd>An object containing the following values:* <dl>* <dt>fill</dt><dd>Defines the style properties for the fill. Contains the following values:* <dl>* <dt>color</dt><dd>Color of the fill. The default value is #faf9f2.</dd>* <dt>alpha</dt><dd>Number from 0 to 1 indicating the opacity of the background fill.* The default value is 1.</dd>* </dl>* </dd>* <dt>border</dt><dd>Defines the style properties for the border. Contains the following values:* <dl>* <dt>color</dt><dd>Color of the border. The default value is #dad8c9.</dd>* <dt>alpha</dt><dd>Number from 0 to 1 indicating the opacity of the background border.* The default value is 1.</dd>* <dt>weight</dt><dd>Number indicating the width of the border. The default value is 1.</dd>* </dl>* </dd>* </dl>* </dd>* </dl>** @attribute styles* @type Object*/}});/*** The ChartBase class is an abstract class used to create charts.** @class ChartBase* @constructor* @submodule charts-base*/function ChartBase() {}ChartBase.ATTRS = {/*** Data used to generate the chart.** @attribute dataProvider* @type Array*/dataProvider: {lazyAdd: false,valueFn: function(){var defDataProvider = [];if(!this._wereSeriesKeysExplicitlySet()){this.set("seriesKeys", this._buildSeriesKeys(defDataProvider), {src: "internal"});}return defDataProvider;},setter: function(val){var dataProvider = this._setDataValues(val);if(!this._wereSeriesKeysExplicitlySet()){this.set("seriesKeys", this._buildSeriesKeys(dataProvider), {src: "internal"});}return dataProvider;}},/*** A collection of keys that map to the series axes. If no keys are set,* they will be generated automatically depending on the data structure passed into* the chart.** @attribute seriesKeys* @type Array*/seriesKeys: {lazyAdd: false,setter: function(val){var opts = arguments[2];if(!val || (opts && opts.src && opts.src === "internal")){this._seriesKeysExplicitlySet = false;}else{this._seriesKeysExplicitlySet = true;}return val;}},/*** Sets the `aria-label` for the chart.** @attribute ariaLabel* @type String*/ariaLabel: {value: "Chart Application",setter: function(val){var cb = this.get("contentBox");if(cb){cb.setAttribute("aria-label", val);}return val;}},/*** Sets the aria description for the chart.** @attribute ariaDescription* @type String*/ariaDescription: {value: "Use the up and down keys to navigate between series. Use the left and right keys to navigate through items in a series.",setter: function(val){if(this._description){this._description.set("text", val);}return val;}},/*** Reference to the default tooltip available for the chart.* <p>Contains the following properties:</p>* <dl>* <dt>node</dt><dd>Reference to the actual dom node</dd>* <dt>showEvent</dt><dd>Event that should trigger the tooltip</dd>* <dt>hideEvent</dt><dd>Event that should trigger the removal of a tooltip (can be an event or an array of events)</dd>* <dt>styles</dt><dd>A hash of style properties that will be applied to the tooltip node</dd>* <dt>show</dt><dd>Indicates whether or not to show the tooltip</dd>* <dt>markerEventHandler</dt><dd>Displays and hides tooltip based on marker events</dd>* <dt>planarEventHandler</dt><dd>Displays and hides tooltip based on planar events</dd>* <dt>markerLabelFunction</dt><dd>Reference to the function used to format a marker event triggered tooltip's text.* The method contains the following arguments:* <dl>* <dt>categoryItem</dt><dd>An object containing the following:* <dl>* <dt>axis</dt><dd>The axis to which the category is bound.</dd>* <dt>displayName</dt><dd>The display name set to the category (defaults to key if not provided).</dd>* <dt>key</dt><dd>The key of the category.</dd>* <dt>value</dt><dd>The value of the category.</dd>* </dl>* </dd>* <dt>valueItem</dt><dd>An object containing the following:* <dl>* <dt>axis</dt><dd>The axis to which the item's series is bound.</dd>* <dt>displayName</dt><dd>The display name of the series. (defaults to key if not provided)</dd>* <dt>key</dt><dd>The key for the series.</dd>* <dt>value</dt><dd>The value for the series item.</dd>* </dl>* </dd>* <dt>itemIndex</dt><dd>The index of the item within the series.</dd>* <dt>series</dt><dd> The `CartesianSeries` instance of the item.</dd>* <dt>seriesIndex</dt><dd>The index of the series in the `seriesCollection`.</dd>* </dl>* The method returns an `HTMLElement` which is written into the DOM using `appendChild`. If you override this method and choose* to return an html string, you will also need to override the tooltip's `setTextFunction` method to accept an html string.* </dd>* <dt>planarLabelFunction</dt><dd>Reference to the function used to format a planar event triggered tooltip's text* <dl>* <dt>categoryAxis</dt><dd> `CategoryAxis` Reference to the categoryAxis of the chart.* <dt>valueItems</dt><dd>Array of objects for each series that has a data point in the coordinate plane of the event. Each* object contains the following data:* <dl>* <dt>axis</dt><dd>The value axis of the series.</dd>* <dt>key</dt><dd>The key for the series.</dd>* <dt>value</dt><dd>The value for the series item.</dd>* <dt>displayName</dt><dd>The display name of the series. (defaults to key if not provided)</dd>* </dl>* </dd>* <dt>index</dt><dd>The index of the item within its series.</dd>* <dt>seriesArray</dt><dd>Array of series instances for each value item.</dd>* <dt>seriesIndex</dt><dd>The index of the series in the `seriesCollection`.</dd>* </dl>* </dd>* </dl>* The method returns an `HTMLElement` which is written into the DOM using `appendChild`. If you override this method and choose* to return an html string, you will also need to override the tooltip's `setTextFunction` method to accept an html string.* </dd>* <dt>setTextFunction</dt><dd>Method that writes content returned from `planarLabelFunction` or `markerLabelFunction` into the* the tooltip node. Has the following signature:* <dl>* <dt>label</dt><dd>The `HTMLElement` that the content is to be added.</dd>* <dt>val</dt><dd>The content to be rendered into tooltip. This can be a `String` or `HTMLElement`. If an HTML string is used,* it will be rendered as a string.</dd>* </dl>* </dd>* </dl>* @attribute tooltip* @type Object*/tooltip: {valueFn: "_getTooltip",setter: function(val){return this._updateTooltip(val);}},/*** The key value used for the chart's category axis.** @attribute categoryKey* @type String* @default category*/categoryKey: {value: "category"},/*** Indicates the type of axis to use for the category axis.** <dl>* <dt>category</dt><dd>Specifies a `CategoryAxis`.</dd>* <dt>time</dt><dd>Specifies a `TimeAxis</dd>* </dl>** @attribute categoryType* @type String* @default category*/categoryType:{value:"category"},/*** Indicates the the type of interactions that will fire events.** <dl>* <dt>marker</dt><dd>Events will be broadcasted when the mouse interacts with individual markers.</dd>* <dt>planar</dt><dd>Events will be broadcasted when the mouse intersects the plane of any markers on the chart.</dd>* <dt>none</dt><dd>No events will be broadcasted.</dd>* </dl>** @attribute interactionType* @type String* @default marker*/interactionType: {value: "marker"},/*** Reference to all the axes in the chart.** @attribute axesCollection* @type Array*/axesCollection: {},/*** Reference to graph instance.** @attribute graph* @type Graph*/graph: {valueFn: "_getGraph"},/*** Indicates whether or not markers for a series will be grouped and rendered in a single complex shape instance.** @attribute groupMarkers* @type Boolean*/groupMarkers: {value: false}};ChartBase.prototype = {/*** Utility method to determine if `seriesKeys` was explicitly provided* (for example during construction, or set by the user), as opposed to* being derived from the dataProvider for example.** @method _wereSeriesKeysExplicitlySet* @private* @return boolean true if the `seriesKeys` attribute was explicitly set.*/_wereSeriesKeysExplicitlySet : function(){var seriesKeys = this.get("seriesKeys");return seriesKeys && this._seriesKeysExplicitlySet;},/*** Handles groupMarkers change event.** @method _groupMarkersChangeHandler* @param {Object} e Event object.* @private*/_groupMarkersChangeHandler: function(e){var graph = this.get("graph"),useGroupMarkers = e.newVal;if(graph){graph.set("groupMarkers", useGroupMarkers);}},/*** Handler for itemRendered event.** @method _itemRendered* @param {Object} e Event object.* @private*/_itemRendered: function(e){this._itemRenderQueue = this._itemRenderQueue.splice(1 + Y.Array.indexOf(this._itemRenderQueue, e.currentTarget), 1);if(this._itemRenderQueue.length < 1){this._redraw();}},/*** Default value function for the `Graph` attribute.** @method _getGraph* @return Graph* @private*/_getGraph: function(){var graph = new Y.Graph({chart:this,groupMarkers: this.get("groupMarkers")});graph.after("chartRendered", Y.bind(function() {this.fire("chartRendered");}, this));return graph;},/*** Returns a series instance by index or key value.** @method getSeries* @param val* @return CartesianSeries*/getSeries: function(val){var series = null,graph = this.get("graph");if(graph){if(Y_Lang.isNumber(val)){series = graph.getSeriesByIndex(val);}else{series = graph.getSeriesByKey(val);}}return series;},/*** Returns an `Axis` instance by key reference. If the axis was explicitly set through the `axes` attribute,* the key will be the same as the key used in the `axes` object. For default axes, the key for* the category axis is the value of the `categoryKey` (`category`). For the value axis, the default* key is `values`.** @method getAxisByKey* @param {String} val Key reference used to look up the axis.* @return Axis*/getAxisByKey: function(val){var axis,axes = this.get("axes");if(axes && axes.hasOwnProperty(val)){axis = axes[val];}return axis;},/*** Returns the category axis for the chart.** @method getCategoryAxis* @return Axis*/getCategoryAxis: function(){var axis,key = this.get("categoryKey"),axes = this.get("axes");if(axes.hasOwnProperty(key)){axis = axes[key];}return axis;},/*** Default direction of the chart.** @property _direction* @type String* @default horizontal* @private*/_direction: "horizontal",/*** Storage for the `dataProvider` attribute.** @property _dataProvider* @type Array* @private*/_dataProvider: null,/*** Setter method for `dataProvider` attribute.** @method _setDataValues* @param {Array} val Array to be set as `dataProvider`.* @return Array* @private*/_setDataValues: function(val){if(Y_Lang.isArray(val[0])){var hash,dp = [],cats = val[0],i = 0,l = cats.length,n,sl = val.length;for(; i < l; ++i){hash = {category:cats[i]};for(n = 1; n < sl; ++n){hash["series" + n] = val[n][i];}dp[i] = hash;}return dp;}return val;},/*** Storage for `seriesCollection` attribute.** @property _seriesCollection* @type Array* @private*/_seriesCollection: null,/*** Setter method for `seriesCollection` attribute.** @property _setSeriesCollection* @param {Array} val Array of either `CartesianSeries` instances or objects containing series attribute key value pairs.* @private*/_setSeriesCollection: function(val){this._seriesCollection = val;},/*** Helper method that returns the axis class that a key references.** @method _getAxisClass* @param {String} t The type of axis.* @return Axis* @private*/_getAxisClass: function(t){return this._axisClass[t];},/*** Key value pairs of axis types.** @property _axisClass* @type Object* @private*/_axisClass: {stacked: Y.StackedAxis,numeric: Y.NumericAxis,category: Y.CategoryAxis,time: Y.TimeAxis},/*** Collection of axes.** @property _axes* @type Array* @private*/_axes: null,/*** @method initializer* @private*/initializer: function(){this._itemRenderQueue = [];this._seriesIndex = -1;this._itemIndex = -1;this.after("dataProviderChange", this._dataProviderChangeHandler);},/*** @method renderUI* @private*/renderUI: function(){var tt = this.get("tooltip"),bb = this.get("boundingBox"),cb = this.get("contentBox");//move the position = absolute logic to a class filebb.setStyle("position", "absolute");cb.setStyle("position", "absolute");this._addAxes();this._addSeries();if(tt && tt.show){this._addTooltip();}this._setAriaElements(bb, cb);},/*** Creates an aria `live-region`, `aria-label` and `aria-describedby` for the Chart.** @method _setAriaElements* @param {Node} cb Reference to the Chart's `contentBox` attribute.* @private*/_setAriaElements: function(bb, cb){var description = this._getAriaOffscreenNode(),id = this.get("id") + "_description",liveRegion = this._getAriaOffscreenNode();cb.set("tabIndex", 0);cb.set("role", "img");cb.setAttribute("aria-label", this.get("ariaLabel"));cb.setAttribute("aria-describedby", id);description.set("id", id);description.set("tabIndex", -1);description.set("text", this.get("ariaDescription"));liveRegion.set("id", "live-region");liveRegion.set("aria-live", "polite");liveRegion.set("aria-atomic", "true");liveRegion.set("role", "status");bb.setAttribute("role", "application");bb.appendChild(description);bb.appendChild(liveRegion);this._description = description;this._liveRegion = liveRegion;},/*** Sets a node offscreen for use as aria-description or aria-live-regin.** @method _setOffscreen* @return Node* @private*/_getAriaOffscreenNode: function(){var node = Y.Node.create("<div></div>"),ie = Y.UA.ie,clipRect = (ie && ie < 8) ? "rect(1px 1px 1px 1px)" : "rect(1px, 1px, 1px, 1px)";node.setStyle("position", "absolute");node.setStyle("height", "1px");node.setStyle("width", "1px");node.setStyle("overflow", "hidden");node.setStyle("clip", clipRect);return node;},/*** @method syncUI* @private*/syncUI: function(){this._redraw();},/*** @method bindUI* @private*/bindUI: function(){this.after("tooltipChange", Y.bind(this._tooltipChangeHandler, this));this.after("widthChange", this._sizeChanged);this.after("heightChange", this._sizeChanged);this.after("groupMarkersChange", this._groupMarkersChangeHandler);var tt = this.get("tooltip"),hideEvent = "mouseout",showEvent = "mouseover",cb = this.get("contentBox"),interactionType = this.get("interactionType"),i = 0,len,markerClassName = "." + SERIES_MARKER,isTouch = ((WINDOW && ("ontouchstart" in WINDOW)) && !(Y.UA.chrome && Y.UA.chrome < 6));Y.on("keydown", Y.bind(function(e) {var key = e.keyCode,numKey = parseFloat(key),msg;if(numKey > 36 && numKey < 41){e.halt();msg = this._getAriaMessage(numKey);this._liveRegion.set("text", msg);}}, this), this.get("contentBox"));if(interactionType === "marker"){//if touch capabilities, toggle tooltip on touchend. otherwise, the tooltip attribute's hideEvent/showEvent types.hideEvent = tt.hideEvent;showEvent = tt.showEvent;if(isTouch){Y.delegate("touchend", Y.bind(this._markerEventDispatcher, this), cb, markerClassName);//hide active tooltip if the chart is touchedY.on("touchend", Y.bind(function(e) {//only halt the event if it originated from the chartif(cb.contains(e.target)){e.halt(true);}if(this._activeMarker){this._activeMarker = null;this.hideTooltip(e);}}, this));}else{Y.delegate("mouseenter", Y.bind(this._markerEventDispatcher, this), cb, markerClassName);Y.delegate("mousedown", Y.bind(this._markerEventDispatcher, this), cb, markerClassName);Y.delegate("mouseup", Y.bind(this._markerEventDispatcher, this), cb, markerClassName);Y.delegate("mouseleave", Y.bind(this._markerEventDispatcher, this), cb, markerClassName);Y.delegate("click", Y.bind(this._markerEventDispatcher, this), cb, markerClassName);Y.delegate("mousemove", Y.bind(this._positionTooltip, this), cb, markerClassName);}}else if(interactionType === "planar"){if(isTouch){this._overlay.on("touchend", Y.bind(this._planarEventDispatcher, this));}else{this._overlay.on("mousemove", Y.bind(this._planarEventDispatcher, this));this.on("mouseout", this.hideTooltip);}}if(tt){this.on("markerEvent:touchend", Y.bind(function(e) {var marker = e.series.get("markers")[e.index];if(this._activeMarker && marker === this._activeMarker){this._activeMarker = null;this.hideTooltip(e);}else{this._activeMarker = marker;tt.markerEventHandler.apply(this, [e]);}}, this));if(hideEvent && showEvent && hideEvent === showEvent){this.on(interactionType + "Event:" + hideEvent, this.toggleTooltip);}else{if(showEvent){this.on(interactionType + "Event:" + showEvent, tt[interactionType + "EventHandler"]);}if(hideEvent){if(Y_Lang.isArray(hideEvent)){len = hideEvent.length;for(; i < len; ++i){this.on(interactionType + "Event:" + hideEvent[i], this.hideTooltip);}}this.on(interactionType + "Event:" + hideEvent, this.hideTooltip);}}}},/*** Event handler for marker events.** @method _markerEventDispatcher* @param {Object} e Event object.* @private*/_markerEventDispatcher: function(e){var type = e.type,cb = this.get("contentBox"),markerNode = e.currentTarget,strArr = markerNode.getAttribute("id").split("_"),index = strArr.pop(),seriesIndex = strArr.pop(),series = this.getSeries(parseInt(seriesIndex, 10)),items = this.getSeriesItems(series, index),isTouch = e && e.hasOwnProperty("changedTouches"),pageX = isTouch ? e.changedTouches[0].pageX : e.pageX,pageY = isTouch ? e.changedTouches[0].pageY : e.pageY,x = pageX - cb.getX(),y = pageY - cb.getY();if(type === "mouseenter"){type = "mouseover";}else if(type === "mouseleave"){type = "mouseout";}series.updateMarkerState(type, index);e.halt();/*** Broadcasts when `interactionType` is set to `marker` and a series marker has received a mouseover event.*** @event markerEvent:mouseover* @preventable false* @param {EventFacade} e Event facade with the following additional* properties:* <dl>* <dt>categoryItem</dt><dd>Hash containing information about the category `Axis`.</dd>* <dt>valueItem</dt><dd>Hash containing information about the value `Axis`.</dd>* <dt>node</dt><dd>The dom node of the marker.</dd>* <dt>x</dt><dd>The x-coordinate of the mouse in relation to the Chart.</dd>* <dt>y</dt><dd>The y-coordinate of the mouse in relation to the Chart.</dd>* <dt>series</dt><dd>Reference to the series of the marker.</dd>* <dt>index</dt><dd>Index of the marker in the series.</dd>* <dt>seriesIndex</dt><dd>The `order` of the marker's series.</dd>* </dl>*//*** Broadcasts when `interactionType` is set to `marker` and a series marker has received a mouseout event.** @event markerEvent:mouseout* @preventable false* @param {EventFacade} e Event facade with the following additional* properties:* <dl>* <dt>categoryItem</dt><dd>Hash containing information about the category `Axis`.</dd>* <dt>valueItem</dt><dd>Hash containing information about the value `Axis`.</dd>* <dt>node</dt><dd>The dom node of the marker.</dd>* <dt>x</dt><dd>The x-coordinate of the mouse in relation to the Chart.</dd>* <dt>y</dt><dd>The y-coordinate of the mouse in relation to the Chart.</dd>* <dt>series</dt><dd>Reference to the series of the marker.</dd>* <dt>index</dt><dd>Index of the marker in the series.</dd>* <dt>seriesIndex</dt><dd>The `order` of the marker's series.</dd>* </dl>*//*** Broadcasts when `interactionType` is set to `marker` and a series marker has received a mousedown event.** @event markerEvent:mousedown* @preventable false* @param {EventFacade} e Event facade with the following additional* properties:* <dl>* <dt>categoryItem</dt><dd>Hash containing information about the category `Axis`.</dd>* <dt>valueItem</dt><dd>Hash containing information about the value `Axis`.</dd>* <dt>node</dt><dd>The dom node of the marker.</dd>* <dt>x</dt><dd>The x-coordinate of the mouse in relation to the Chart.</dd>* <dt>y</dt><dd>The y-coordinate of the mouse in relation to the Chart.</dd>* <dt>series</dt><dd>Reference to the series of the marker.</dd>* <dt>index</dt><dd>Index of the marker in the series.</dd>* <dt>seriesIndex</dt><dd>The `order` of the marker's series.</dd>* </dl>*//*** Broadcasts when `interactionType` is set to `marker` and a series marker has received a mouseup event.** @event markerEvent:mouseup* @preventable false* @param {EventFacade} e Event facade with the following additional* properties:* <dl>* <dt>categoryItem</dt><dd>Hash containing information about the category `Axis`.</dd>* <dt>valueItem</dt><dd>Hash containing information about the value `Axis`.</dd>* <dt>node</dt><dd>The dom node of the marker.</dd>* <dt>x</dt><dd>The x-coordinate of the mouse in relation to the Chart.</dd>* <dt>y</dt><dd>The y-coordinate of the mouse in relation to the Chart.</dd>* <dt>series</dt><dd>Reference to the series of the marker.</dd>* <dt>index</dt><dd>Index of the marker in the series.</dd>* <dt>seriesIndex</dt><dd>The `order` of the marker's series.</dd>* </dl>*//*** Broadcasts when `interactionType` is set to `marker` and a series marker has received a click event.** @event markerEvent:click* @preventable false* @param {EventFacade} e Event facade with the following additional* properties:* <dl>* <dt>categoryItem</dt><dd>Hash containing information about the category `Axis`.</dd>* <dt>valueItem</dt><dd>Hash containing information about the value `Axis`.</dd>* <dt>node</dt><dd>The dom node of the marker.</dd>* <dt>x</dt><dd>The x-coordinate of the mouse in relation to the Chart.</dd>* <dt>y</dt><dd>The y-coordinate of the mouse in relation to the Chart.</dd>* <dt>pageX</dt><dd>The x location of the event on the page (including scroll)</dd>* <dt>pageY</dt><dd>The y location of the event on the page (including scroll)</dd>* <dt>series</dt><dd>Reference to the series of the marker.</dd>* <dt>index</dt><dd>Index of the marker in the series.</dd>* <dt>seriesIndex</dt><dd>The `order` of the marker's series.</dd>* <dt>originEvent</dt><dd>Underlying dom event.</dd>* </dl>*/this.fire("markerEvent:" + type, {originEvent: e,pageX:pageX,pageY:pageY,categoryItem:items.category,valueItem:items.value,node:markerNode,x:x,y:y,series:series,index:index,seriesIndex:seriesIndex});},/*** Event handler for dataProviderChange.** @method _dataProviderChangeHandler* @param {Object} e Event object.* @private*/_dataProviderChangeHandler: function(e){var dataProvider = e.newVal,axes,i,axis;this._seriesIndex = -1;this._itemIndex = -1;if(this instanceof Y.CartesianChart){this.set("axes", this.get("axes"));this.set("seriesCollection", this.get("seriesCollection"));}axes = this.get("axes");if(axes){for(i in axes){if(axes.hasOwnProperty(i)){axis = axes[i];if(axis instanceof Y.Axis){if(axis.get("position") !== "none"){this._addToAxesRenderQueue(axis);}axis.set("dataProvider", dataProvider);}}}}},/*** Event listener for toggling the tooltip. If a tooltip is visible, hide it. If not, it* will create and show a tooltip based on the event object.** @method toggleTooltip* @param {Object} e Event object.*/toggleTooltip: function(e){var tt = this.get("tooltip");if(tt.visible){this.hideTooltip();}else{tt.markerEventHandler.apply(this, [e]);}},/*** Shows a tooltip** @method _showTooltip* @param {String} msg Message to dispaly in the tooltip.* @param {Number} x x-coordinate* @param {Number} y y-coordinate* @private*/_showTooltip: function(msg, x, y){var tt = this.get("tooltip"),node = tt.node;if(msg){tt.visible = true;tt.setTextFunction(node, msg);node.setStyle("top", y + "px");node.setStyle("left", x + "px");node.setStyle("visibility", "visible");}},/*** Positions the tooltip** @method _positionTooltip* @param {Object} e Event object.* @private*/_positionTooltip: function(e){var tt = this.get("tooltip"),node = tt.node,cb = this.get("contentBox"),x = (e.pageX + 10) - cb.getX(),y = (e.pageY + 10) - cb.getY();if(node){node.setStyle("left", x + "px");node.setStyle("top", y + "px");}},/*** Hides the default tooltip** @method hideTooltip*/hideTooltip: function(){var tt = this.get("tooltip"),node = tt.node;tt.visible = false;node.set("innerHTML", "");node.setStyle("left", -10000);node.setStyle("top", -10000);node.setStyle("visibility", "hidden");},/*** Adds a tooltip to the dom.** @method _addTooltip* @private*/_addTooltip: function(){var tt = this.get("tooltip"),id = this.get("id") + "_tooltip",cb = this.get("contentBox"),oldNode = DOCUMENT.getElementById(id);if(oldNode){cb.removeChild(oldNode);}tt.node.set("id", id);tt.node.setStyle("visibility", "hidden");cb.appendChild(tt.node);},/*** Updates the tooltip attribute.** @method _updateTooltip* @param {Object} val Object containing properties for the tooltip.* @return Object* @private*/_updateTooltip: function(val){var tt = this.get("tooltip") || this._getTooltip(),i,styles,node,props = {markerLabelFunction:"markerLabelFunction",planarLabelFunction:"planarLabelFunction",setTextFunction:"setTextFunction",showEvent:"showEvent",hideEvent:"hideEvent",markerEventHandler:"markerEventHandler",planarEventHandler:"planarEventHandler",show:"show"};if(Y_Lang.isObject(val)){styles = val.styles;if(val.node && tt.node){tt.node.destroy(true);node = Y.one(val.node);}else{node = tt.node;}if(styles){for(i in styles){if(styles.hasOwnProperty(i)){node.setStyle(i, styles[i]);}}}for(i in props){if(val.hasOwnProperty(i)){tt[i] = val[i];}}tt.node = node;}return tt;},/*** Default getter for `tooltip` attribute.** @method _getTooltip* @return Object* @private*/_getTooltip: function(){var node = DOCUMENT.createElement("div"),tooltipClass = _getClassName("chart-tooltip"),tt = {setTextFunction: this._setText,markerLabelFunction: this._tooltipLabelFunction,planarLabelFunction: this._planarLabelFunction,show: true,hideEvent: "mouseout",showEvent: "mouseover",markerEventHandler: function(e){var tt = this.get("tooltip"),msg = tt.markerLabelFunction.apply(this, [e.categoryItem, e.valueItem, e.index, e.series, e.seriesIndex]);this._showTooltip(msg, e.x + 10, e.y + 10);},planarEventHandler: function(e){var tt = this.get("tooltip"),msg ,categoryAxis = this.get("categoryAxis");msg = tt.planarLabelFunction.apply(this, [categoryAxis, e.valueItem, e.index, e.items, e.seriesIndex]);this._showTooltip(msg, e.x + 10, e.y + 10);}};node = Y.one(node);node.set("id", this.get("id") + "_tooltip");node.setStyle("fontSize", "85%");node.setStyle("opacity", "0.83");node.setStyle("position", "absolute");node.setStyle("paddingTop", "2px");node.setStyle("paddingRight", "5px");node.setStyle("paddingBottom", "4px");node.setStyle("paddingLeft", "2px");node.setStyle("backgroundColor", "#fff");node.setStyle("border", "1px solid #dbdccc");node.setStyle("pointerEvents", "none");node.setStyle("zIndex", 3);node.setStyle("whiteSpace", "noWrap");node.setStyle("visibility", "hidden");node.addClass(tooltipClass);tt.node = Y.one(node);return tt;},/*** Formats tooltip text when `interactionType` is `planar`.** @method _planarLabelFunction* @param {Axis} categoryAxis Reference to the categoryAxis of the chart.* @param {Array} valueItems Array of objects for each series that has a data point in the coordinate plane of the event.* Each object contains the following data:* <dl>* <dt>axis</dt><dd>The value axis of the series.</dd>* <dt>key</dt><dd>The key for the series.</dd>* <dt>value</dt><dd>The value for the series item.</dd>* <dt>displayName</dt><dd>The display name of the series. (defaults to key if not provided)</dd>* </dl>* @param {Number} index The index of the item within its series.* @param {Array} seriesArray Array of series instances for each value item.* @param {Number} seriesIndex The index of the series in the `seriesCollection`.* @return {HTMLElement}* @private*/_planarLabelFunction: function(categoryAxis, valueItems, index, seriesArray){var msg = DOCUMENT.createElement("div"),valueItem,i = 0,len = seriesArray.length,axis,categoryValue,seriesValue,series;if(categoryAxis){categoryValue = categoryAxis.get("labelFunction").apply(this,[categoryAxis.getKeyValueAt(this.get("categoryKey"), index), categoryAxis.get("labelFormat")]);if(!Y_Lang.isObject(categoryValue)){categoryValue = DOCUMENT.createTextNode(categoryValue);}msg.appendChild(categoryValue);}for(; i < len; ++i){series = seriesArray[i];if(series.get("visible")){valueItem = valueItems[i];axis = valueItem.axis;seriesValue = axis.get("labelFunction").apply(this,[axis.getKeyValueAt(valueItem.key, index), axis.get("labelFormat")]);msg.appendChild(DOCUMENT.createElement("br"));msg.appendChild(DOCUMENT.createTextNode(valueItem.displayName));msg.appendChild(DOCUMENT.createTextNode(": "));if(!Y_Lang.isObject(seriesValue)){seriesValue = DOCUMENT.createTextNode(seriesValue);}msg.appendChild(seriesValue);}}return msg;},/*** Formats tooltip text when `interactionType` is `marker`.** @method _tooltipLabelFunction* @param {Object} categoryItem An object containing the following:* <dl>* <dt>axis</dt><dd>The axis to which the category is bound.</dd>* <dt>displayName</dt><dd>The display name set to the category (defaults to key if not provided)</dd>* <dt>key</dt><dd>The key of the category.</dd>* <dt>value</dt><dd>The value of the category</dd>* </dl>* @param {Object} valueItem An object containing the following:* <dl>* <dt>axis</dt><dd>The axis to which the item's series is bound.</dd>* <dt>displayName</dt><dd>The display name of the series. (defaults to key if not provided)</dd>* <dt>key</dt><dd>The key for the series.</dd>* <dt>value</dt><dd>The value for the series item.</dd>* </dl>* @return {HTMLElement}* @private*/_tooltipLabelFunction: function(categoryItem, valueItem){var msg = DOCUMENT.createElement("div"),categoryValue = categoryItem.axis.get("labelFunction").apply(this,[categoryItem.value, categoryItem.axis.get("labelFormat")]),seriesValue = valueItem.axis.get("labelFunction").apply(this,[valueItem.value, valueItem.axis.get("labelFormat")]);msg.appendChild(DOCUMENT.createTextNode(categoryItem.displayName));msg.appendChild(DOCUMENT.createTextNode(": "));if(!Y_Lang.isObject(categoryValue)){categoryValue = DOCUMENT.createTextNode(categoryValue);}msg.appendChild(categoryValue);msg.appendChild(DOCUMENT.createElement("br"));msg.appendChild(DOCUMENT.createTextNode(valueItem.displayName));msg.appendChild(DOCUMENT.createTextNode(": "));if(!Y_Lang.isObject(seriesValue)){seriesValue = DOCUMENT.createTextNode(seriesValue);}msg.appendChild(seriesValue);return msg;},/*** Event handler for the tooltipChange.** @method _tooltipChangeHandler* @param {Object} e Event object.* @private*/_tooltipChangeHandler: function(){if(this.get("tooltip")){var tt = this.get("tooltip"),node = tt.node,show = tt.show,cb = this.get("contentBox");if(node && show){if(!cb.contains(node)){this._addTooltip();}}}},/*** Updates the content of text field. This method writes a value into a text field using* `appendChild`. If the value is a `String`, it is converted to a `TextNode` first.** @method _setText* @param label {HTMLElement} label to be updated* @param val {String} value with which to update the label* @private*/_setText: function(textField, val){textField.empty();if(Y_Lang.isNumber(val)){val = val + "";}else if(!val){val = "";}if(IS_STRING(val)){val = DOCUMENT.createTextNode(val);}textField.appendChild(val);},/*** Returns all the keys contained in a `dataProvider`.** @method _getAllKeys* @param {Array} dp Collection of objects to be parsed.* @return Object*/_getAllKeys: function(dp){var i = 0,len = dp.length,item,key,keys = {};for(; i < len; ++i){item = dp[i];for(key in item){if(item.hasOwnProperty(key)){keys[key] = true;}}}return keys;},/*** Constructs seriesKeys if not explicitly specified.** @method _buildSeriesKeys* @param {Array} dataProvider The dataProvider for the chart.* @return Array* @private*/_buildSeriesKeys: function(dataProvider){var allKeys,catKey = this.get("categoryKey"),keys = [],i;if(this._seriesKeysExplicitlySet){return this._seriesKeys;}allKeys = this._getAllKeys(dataProvider);for(i in allKeys){if(allKeys.hasOwnProperty(i) && i !== catKey){keys.push(i);}}return keys;}};Y.ChartBase = ChartBase;/*** The CartesianChart class creates a chart with horizontal and vertical axes.** @class CartesianChart* @extends ChartBase* @constructor* @submodule charts-base*/Y.CartesianChart = Y.Base.create("cartesianChart", Y.Widget, [Y.ChartBase, Y.Renderer], {/*** @method renderUI* @private*/renderUI: function(){var bb = this.get("boundingBox"),cb = this.get("contentBox"),tt = this.get("tooltip"),overlayClass = _getClassName("overlay");//move the position = absolute logic to a class filebb.setStyle("position", "absolute");cb.setStyle("position", "absolute");this._addAxes();this._addGridlines();this._addSeries();if(tt && tt.show){this._addTooltip();}if(this.get("interactionType") === "planar"){this._overlay = Y.Node.create("<div></div>");this._overlay.set("id", this.get("id") + "_overlay");this._overlay.setStyle("position", "absolute");this._overlay.setStyle("background", "#fff");this._overlay.setStyle("opacity", 0);this._overlay.addClass(overlayClass);this._overlay.setStyle("zIndex", 4);cb.append(this._overlay);}this._setAriaElements(bb, cb);this._redraw();},/*** When `interactionType` is set to `planar`, listens for mouse move events and fires `planarEvent:mouseover` or `planarEvent:mouseout`* depending on the position of the mouse in relation to data points on the `Chart`.** @method _planarEventDispatcher* @param {Object} e Event object.* @private*/_planarEventDispatcher: function(e){var graph = this.get("graph"),bb = this.get("boundingBox"),cb = graph.get("contentBox"),isTouch = e && e.hasOwnProperty("changedTouches"),pageX = isTouch ? e.changedTouches[0].pageX : e.pageX,pageY = isTouch ? e.changedTouches[0].pageY : e.pageY,posX = pageX - bb.getX(),posY = pageY - bb.getY(),offset = {x: pageX - cb.getX(),y: pageY - cb.getY()},sc = graph.get("seriesCollection"),series,i = 0,index,oldIndex = this._selectedIndex,item,items = [],categoryItems = [],valueItems = [],direction = this.get("direction"),hasMarkers,catAxis,valAxis,coord,//data columns and area data could be created on a graph levelmarkerPlane,len,coords;e.halt(true);if(direction === "horizontal"){catAxis = "x";valAxis = "y";}else{valAxis = "x";catAxis = "y";}coord = offset[catAxis];if(sc){len = sc.length;while(i < len && !markerPlane){if(sc[i]){markerPlane = sc[i].get(catAxis + "MarkerPlane");}i++;}}if(markerPlane){len = markerPlane.length;for(i = 0; i < len; ++i){if(coord <= markerPlane[i].end && coord >= markerPlane[i].start){index = i;break;}}len = sc.length;for(i = 0; i < len; ++i){series = sc[i];coords = series.get(valAxis + "coords");hasMarkers = series.get("markers");if(hasMarkers && !isNaN(oldIndex) && oldIndex > -1){series.updateMarkerState("mouseout", oldIndex);}if(coords && coords[index] > -1){if(hasMarkers && !isNaN(index) && index > -1){series.updateMarkerState("mouseover", index);}item = this.getSeriesItems(series, index);categoryItems.push(item.category);valueItems.push(item.value);items.push(series);}}this._selectedIndex = index;/*** Broadcasts when `interactionType` is set to `planar` and a series' marker plane has received a mouseover event.*** @event planarEvent:mouseover* @preventable false* @param {EventFacade} e Event facade with the following additional* properties:* <dl>* <dt>categoryItem</dt><dd>An array of hashes, each containing information about the category `Axis` of each marker* whose plane has been intersected.</dd>* <dt>valueItem</dt><dd>An array of hashes, each containing information about the value `Axis` of each marker whose* plane has been intersected.</dd>* <dt>x</dt><dd>The x-coordinate of the mouse in relation to the Chart.</dd>* <dt>y</dt><dd>The y-coordinate of the mouse in relation to the Chart.</dd>* <dt>pageX</dt><dd>The x location of the event on the page (including scroll)</dd>* <dt>pageY</dt><dd>The y location of the event on the page (including scroll)</dd>* <dt>items</dt><dd>An array including all the series which contain a marker whose plane has been intersected.</dd>* <dt>index</dt><dd>Index of the markers in their respective series.</dd>* <dt>originEvent</dt><dd>Underlying dom event.</dd>* </dl>*//*** Broadcasts when `interactionType` is set to `planar` and a series' marker plane has received a mouseout event.** @event planarEvent:mouseout* @preventable false* @param {EventFacade} e*/if(index > -1){this.fire("planarEvent:mouseover", {categoryItem:categoryItems,valueItem:valueItems,x:posX,y:posY,pageX:pageX,pageY:pageY,items:items,index:index,originEvent:e});}else{this.fire("planarEvent:mouseout");}}},/*** Indicates the default series type for the chart.** @property _type* @type {String}* @private*/_type: "combo",/*** Queue of axes instances that will be updated. This method is used internally to determine when all axes have been updated.** @property _itemRenderQueue* @type Array* @private*/_itemRenderQueue: null,/*** Adds an `Axis` instance to the `_itemRenderQueue`.** @method _addToAxesRenderQueue* @param {Axis} axis An `Axis` instance.* @private*/_addToAxesRenderQueue: function(axis){if(!this._itemRenderQueue){this._itemRenderQueue = [];}if(Y.Array.indexOf(this._itemRenderQueue, axis) < 0){this._itemRenderQueue.push(axis);}},/*** Adds axis instance to the appropriate array based on position** @method _addToAxesCollection* @param {String} position The position of the axis* @param {Axis} axis The `Axis` instance*/_addToAxesCollection: function(position, axis){var axesCollection = this.get(position + "AxesCollection");if(!axesCollection){axesCollection = [];this.set(position + "AxesCollection", axesCollection);}axesCollection.push(axis);},/*** Returns the default value for the `seriesCollection` attribute.** @method _getDefaultSeriesCollection* @param {Array} val Array containing either `CartesianSeries` instances or objects containing data to construct series instances.* @return Array* @private*/_getDefaultSeriesCollection: function(){var seriesCollection,dataProvider = this.get("dataProvider");if(dataProvider){seriesCollection = this._parseSeriesCollection();}return seriesCollection;},/*** Parses and returns a series collection from an object and default properties.** @method _parseSeriesCollection* @param {Object} val Object contain properties for series being set.* @return Object* @private*/_parseSeriesCollection: function(val){var dir = this.get("direction"),seriesStyles = this.get("styles").series,stylesAreArray = seriesStyles && Y_Lang.isArray(seriesStyles),stylesIndex,setStyles,globalStyles,sc = [],catAxis,valAxis,tempKeys = [],series,seriesKeys = this.get("seriesKeys").concat(),i,index,l,type = this.get("type"),key,catKey,seriesKey,graph,orphans = [],categoryKey = this.get("categoryKey"),showMarkers = this.get("showMarkers"),showAreaFill = this.get("showAreaFill"),showLines = this.get("showLines");val = val ? val.concat() : [];if(dir === "vertical"){catAxis = "yAxis";catKey = "yKey";valAxis = "xAxis";seriesKey = "xKey";}else{catAxis = "xAxis";catKey = "xKey";valAxis = "yAxis";seriesKey = "yKey";}l = val.length;while(val && val.length > 0){series = val.shift();key = this._getBaseAttribute(series, seriesKey);if(key){index = Y.Array.indexOf(seriesKeys, key);if(index > -1){seriesKeys.splice(index, 1);tempKeys.push(key);sc.push(series);}else{orphans.push(series);}}else{orphans.push(series);}}while(orphans.length > 0){series = orphans.shift();if(seriesKeys.length > 0){key = seriesKeys.shift();this._setBaseAttribute(series, seriesKey, key);tempKeys.push(key);sc.push(series);}else if(series instanceof Y.CartesianSeries){series.destroy(true);}}if(seriesKeys.length > 0){tempKeys = tempKeys.concat(seriesKeys);}l = tempKeys.length;for(i = 0; i < l; ++i){series = sc[i] || {type:type};if(series instanceof Y.CartesianSeries){this._parseSeriesAxes(series);}else{series[catKey] = series[catKey] || categoryKey;series[seriesKey] = series[seriesKey] || seriesKeys.shift();series[catAxis] = this._getCategoryAxis();series[valAxis] = this._getSeriesAxis(series[seriesKey]);series.type = series.type || type;series.direction = series.direction || dir;if(series.type === "combo" ||series.type === "stackedcombo" ||series.type === "combospline" ||series.type === "stackedcombospline"){if(showAreaFill !== null){series.showAreaFill = (series.showAreaFill !== null && series.showAreaFill !== undefined) ?series.showAreaFill : showAreaFill;}if(showMarkers !== null){series.showMarkers = (series.showMarkers !== null && series.showMarkers !== undefined) ? series.showMarkers : showMarkers;}if(showLines !== null){series.showLines = (series.showLines !== null && series.showLines !== undefined) ? series.showLines : showLines;}}if(seriesStyles){stylesIndex = stylesAreArray ? i : series[seriesKey];globalStyles = seriesStyles[stylesIndex];if(globalStyles){setStyles = series.styles;if(setStyles){series.styles = this._mergeStyles(setStyles, globalStyles);}else{series.styles = globalStyles;}}}sc[i] = series;}}if(sc){graph = this.get("graph");graph.set("seriesCollection", sc);sc = graph.get("seriesCollection");}return sc;},/*** Parse and sets the axes for a series instance.** @method _parseSeriesAxes* @param {CartesianSeries} series A `CartesianSeries` instance.* @private*/_parseSeriesAxes: function(series){var axes = this.get("axes"),xAxis = series.get("xAxis"),yAxis = series.get("yAxis"),YAxis = Y.Axis,axis;if(xAxis && !(xAxis instanceof YAxis) && Y_Lang.isString(xAxis) && axes.hasOwnProperty(xAxis)){axis = axes[xAxis];if(axis instanceof YAxis){series.set("xAxis", axis);}}if(yAxis && !(yAxis instanceof YAxis) && Y_Lang.isString(yAxis) && axes.hasOwnProperty(yAxis)){axis = axes[yAxis];if(axis instanceof YAxis){series.set("yAxis", axis);}}},/*** Returns the category axis instance for the chart.** @method _getCategoryAxis* @return Axis* @private*/_getCategoryAxis: function(){var axis,axes = this.get("axes"),categoryAxisName = this.get("categoryAxisName") || this.get("categoryKey");axis = axes[categoryAxisName];return axis;},/*** Returns the value axis for a series.** @method _getSeriesAxis* @param {String} key The key value used to determine the axis instance.* @return Axis* @private*/_getSeriesAxis:function(key, axisName){var axes = this.get("axes"),i,keys,axis;if(axes){if(axisName && axes.hasOwnProperty(axisName)){axis = axes[axisName];}else{for(i in axes){if(axes.hasOwnProperty(i)){keys = axes[i].get("keys");if(keys && keys.hasOwnProperty(key)){axis = axes[i];break;}}}}}return axis;},/*** Gets an attribute from an object, using a getter for Base objects and a property for object* literals. Used for determining attributes from series/axis references which can be an actual class instance* or a hash of properties that will be used to create a class instance.** @method _getBaseAttribute* @param {Object} item Object or instance in which the attribute resides.* @param {String} key Attribute whose value will be returned.* @return Object* @private*/_getBaseAttribute: function(item, key){if(item instanceof Y.Base){return item.get(key);}if(item.hasOwnProperty(key)){return item[key];}return null;},/*** Sets an attribute on an object, using a setter of Base objects and a property for object* literals. Used for setting attributes on a Base class, either directly or to be stored in an object literal* for use at instantiation.** @method _setBaseAttribute* @param {Object} item Object or instance in which the attribute resides.* @param {String} key Attribute whose value will be assigned.* @param {Object} value Value to be assigned to the attribute.* @private*/_setBaseAttribute: function(item, key, value){if(item instanceof Y.Base){item.set(key, value);}else{item[key] = value;}},/*** Creates `Axis` instances.** @method _setAxes* @param {Object} val Object containing `Axis` instances or objects in which to construct `Axis` instances.* @return Object* @private*/_setAxes: function(val){var hash = this._parseAxes(val),axes = {},axesAttrs = {edgeOffset: "edgeOffset",calculateEdgeOffset: "calculateEdgeOffset",position: "position",overlapGraph:"overlapGraph",labelValues: "labelValues",hideFirstMajorUnit: "hideFirstMajorUnit",hideLastMajorUnit: "hideLastMajorUnit",labelFunction:"labelFunction",labelFunctionScope:"labelFunctionScope",labelFormat:"labelFormat",appendLabelFunction: "appendLabelFunction",appendTitleFunction: "appendTitleFunction",maximum:"maximum",minimum:"minimum",roundingMethod:"roundingMethod",alwaysShowZero:"alwaysShowZero",scaleType: "scaleType",title:"title",width:"width",height:"height"},dp = this.get("dataProvider"),ai,i,pos,axis,axisPosition,dh,AxisClass,config,axesCollection;for(i in hash){if(hash.hasOwnProperty(i)){dh = hash[i];if(dh instanceof Y.Axis){axis = dh;}else{axis = null;config = {};config.dataProvider = dh.dataProvider || dp;config.keys = dh.keys;if(dh.hasOwnProperty("roundingUnit")){config.roundingUnit = dh.roundingUnit;}pos = dh.position;if(dh.styles){config.styles = dh.styles;}config.position = dh.position;for(ai in axesAttrs){if(axesAttrs.hasOwnProperty(ai) && dh.hasOwnProperty(ai)){config[ai] = dh[ai];}}//only check for existing axis if we constructed the default axes alreadyif(val){axis = this.getAxisByKey(i);}if(axis && axis instanceof Y.Axis){axisPosition = axis.get("position");if(pos !== axisPosition){if(axisPosition !== "none"){axesCollection = this.get(axisPosition + "AxesCollection");axesCollection.splice(Y.Array.indexOf(axesCollection, axis), 1);}if(pos !== "none"){this._addToAxesCollection(pos, axis);}}axis.setAttrs(config);}else{AxisClass = this._getAxisClass(dh.type);axis = new AxisClass(config);axis.after("axisRendered", Y.bind(this._itemRendered, this));}}if(axis){axesCollection = this.get(pos + "AxesCollection");if(axesCollection && Y.Array.indexOf(axesCollection, axis) > 0){axis.set("overlapGraph", false);}axes[i] = axis;}}}return axes;},/*** Adds axes to the chart.** @method _addAxes* @private*/_addAxes: function(){var axes = this.get("axes"),i,axis,pos,w = this.get("width"),h = this.get("height"),node = Y.Node.one(this._parentNode);if(!this._axesCollection){this._axesCollection = [];}for(i in axes){if(axes.hasOwnProperty(i)){axis = axes[i];if(axis instanceof Y.Axis){if(!w){this.set("width", node.get("offsetWidth"));w = this.get("width");}if(!h){this.set("height", node.get("offsetHeight"));h = this.get("height");}this._addToAxesRenderQueue(axis);pos = axis.get("position");if(!this.get(pos + "AxesCollection")){this.set(pos + "AxesCollection", [axis]);}else{this.get(pos + "AxesCollection").push(axis);}this._axesCollection.push(axis);if(axis.get("keys").hasOwnProperty(this.get("categoryKey"))){this.set("categoryAxis", axis);}axis.render(this.get("contentBox"));}}}},/*** Renders the Graph.** @method _addSeries* @private*/_addSeries: function(){var graph = this.get("graph");graph.render(this.get("contentBox"));},/*** Adds gridlines to the chart.** @method _addGridlines* @private*/_addGridlines: function(){var graph = this.get("graph"),hgl = this.get("horizontalGridlines"),vgl = this.get("verticalGridlines"),direction = this.get("direction"),leftAxesCollection = this.get("leftAxesCollection"),rightAxesCollection = this.get("rightAxesCollection"),bottomAxesCollection = this.get("bottomAxesCollection"),topAxesCollection = this.get("topAxesCollection"),seriesAxesCollection,catAxis = this.get("categoryAxis"),hAxis,vAxis;if(this._axesCollection){seriesAxesCollection = this._axesCollection.concat();seriesAxesCollection.splice(Y.Array.indexOf(seriesAxesCollection, catAxis), 1);}if(hgl){if(leftAxesCollection && leftAxesCollection[0]){hAxis = leftAxesCollection[0];}else if(rightAxesCollection && rightAxesCollection[0]){hAxis = rightAxesCollection[0];}else{hAxis = direction === "horizontal" ? catAxis : seriesAxesCollection[0];}if(!this._getBaseAttribute(hgl, "axis") && hAxis){this._setBaseAttribute(hgl, "axis", hAxis);}if(this._getBaseAttribute(hgl, "axis")){graph.set("horizontalGridlines", hgl);}}if(vgl){if(bottomAxesCollection && bottomAxesCollection[0]){vAxis = bottomAxesCollection[0];}else if (topAxesCollection && topAxesCollection[0]){vAxis = topAxesCollection[0];}else{vAxis = direction === "vertical" ? catAxis : seriesAxesCollection[0];}if(!this._getBaseAttribute(vgl, "axis") && vAxis){this._setBaseAttribute(vgl, "axis", vAxis);}if(this._getBaseAttribute(vgl, "axis")){graph.set("verticalGridlines", vgl);}}},/*** Default Function for the axes attribute.** @method _getDefaultAxes* @return Object* @private*/_getDefaultAxes: function(){var axes;if(this.get("dataProvider")){axes = this._parseAxes();}return axes;},/*** Generates and returns a key-indexed object containing `Axis` instances or objects used to create `Axis` instances.** @method _parseAxes* @param {Object} axes Object containing `Axis` instances or `Axis` attributes.* @return Object* @private*/_parseAxes: function(axes){var catKey = this.get("categoryKey"),axis,attr,keys,newAxes = {},claimedKeys = [],newKeys = [],categoryAxisName = this.get("categoryAxisName") || this.get("categoryKey"),valueAxisName = this.get("valueAxisName"),seriesKeys = this.get("seriesKeys").concat(),i,l,ii,ll,cIndex,direction = this.get("direction"),seriesPosition,categoryPosition,valueAxes = [],seriesAxis = this.get("stacked") ? "stacked" : "numeric";if(direction === "vertical"){seriesPosition = "bottom";categoryPosition = "left";}else{seriesPosition = "left";categoryPosition = "bottom";}if(axes){for(i in axes){if(axes.hasOwnProperty(i)){axis = axes[i];keys = this._getBaseAttribute(axis, "keys");attr = this._getBaseAttribute(axis, "type");if(attr === "time" || attr === "category"){categoryAxisName = i;this.set("categoryAxisName", i);if(Y_Lang.isArray(keys) && keys.length > 0){catKey = keys[0];this.set("categoryKey", catKey);}newAxes[i] = axis;}else if(i === categoryAxisName){newAxes[i] = axis;}else{newAxes[i] = axis;if(i !== valueAxisName && keys && Y_Lang.isArray(keys)){ll = keys.length;for(ii = 0; ii < ll; ++ii){claimedKeys.push(keys[ii]);}valueAxes.push(newAxes[i]);}if(!(this._getBaseAttribute(newAxes[i], "type"))){this._setBaseAttribute(newAxes[i], "type", seriesAxis);}if(!(this._getBaseAttribute(newAxes[i], "position"))){this._setBaseAttribute(newAxes[i],"position",this._getDefaultAxisPosition(newAxes[i], valueAxes, seriesPosition));}}}}}cIndex = Y.Array.indexOf(seriesKeys, catKey);if(cIndex > -1){seriesKeys.splice(cIndex, 1);}l = seriesKeys.length;for(i = 0; i < l; ++i){cIndex = Y.Array.indexOf(claimedKeys, seriesKeys[i]);if(cIndex > -1){newKeys = newKeys.concat(claimedKeys.splice(cIndex, 1));}}claimedKeys = newKeys.concat(claimedKeys);l = claimedKeys.length;for(i = 0; i < l; i = i + 1){cIndex = Y.Array.indexOf(seriesKeys, claimedKeys[i]);if(cIndex > -1){seriesKeys.splice(cIndex, 1);}}if(!newAxes.hasOwnProperty(categoryAxisName)){newAxes[categoryAxisName] = {};}if(!(this._getBaseAttribute(newAxes[categoryAxisName], "keys"))){this._setBaseAttribute(newAxes[categoryAxisName], "keys", [catKey]);}if(!(this._getBaseAttribute(newAxes[categoryAxisName], "position"))){this._setBaseAttribute(newAxes[categoryAxisName], "position", categoryPosition);}if(!(this._getBaseAttribute(newAxes[categoryAxisName], "type"))){this._setBaseAttribute(newAxes[categoryAxisName], "type", this.get("categoryType"));}if(!newAxes.hasOwnProperty(valueAxisName) && seriesKeys && seriesKeys.length > 0){newAxes[valueAxisName] = {keys:seriesKeys};valueAxes.push(newAxes[valueAxisName]);}if(claimedKeys.length > 0){if(seriesKeys.length > 0){seriesKeys = claimedKeys.concat(seriesKeys);}else{seriesKeys = claimedKeys;}}if(newAxes.hasOwnProperty(valueAxisName)){if(!(this._getBaseAttribute(newAxes[valueAxisName], "position"))){this._setBaseAttribute(newAxes[valueAxisName],"position",this._getDefaultAxisPosition(newAxes[valueAxisName], valueAxes, seriesPosition));}this._setBaseAttribute(newAxes[valueAxisName], "type", seriesAxis);this._setBaseAttribute(newAxes[valueAxisName], "keys", seriesKeys);}if(!this._wereSeriesKeysExplicitlySet()){this.set("seriesKeys", seriesKeys, {src: "internal"});}return newAxes;},/*** Determines the position of an axis when one is not specified.** @method _getDefaultAxisPosition* @param {Axis} axis `Axis` instance.* @param {Array} valueAxes Array of `Axis` instances.* @param {String} position Default position depending on the direction of the chart and type of axis.* @return String* @private*/_getDefaultAxisPosition: function(axis, valueAxes, position){var direction = this.get("direction"),i = Y.Array.indexOf(valueAxes, axis);if(valueAxes[i - 1] && valueAxes[i - 1].position){if(direction === "horizontal"){if(valueAxes[i - 1].position === "left"){position = "right";}else if(valueAxes[i - 1].position === "right"){position = "left";}}else{if (valueAxes[i -1].position === "bottom"){position = "top";}else{position = "bottom";}}}return position;},/*** Returns an object literal containing a categoryItem and a valueItem for a given series index. Below is the structure of each:** @method getSeriesItems* @param {CartesianSeries} series Reference to a series.* @param {Number} index Index of the specified item within a series.* @return Object An object literal containing the following:** <dl>* <dt>categoryItem</dt><dd>Object containing the following data related to the category axis of the series.* <dl>* <dt>axis</dt><dd>Reference to the category axis of the series.</dd>* <dt>key</dt><dd>Category key for the series.</dd>* <dt>value</dt><dd>Value on the axis corresponding to the series index.</dd>* </dl>* </dd>* <dt>valueItem</dt><dd>Object containing the following data related to the category axis of the series.* <dl>* <dt>axis</dt><dd>Reference to the value axis of the series.</dd>* <dt>key</dt><dd>Value key for the series.</dd>* <dt>value</dt><dd>Value on the axis corresponding to the series index.</dd>* </dl>* </dd>* </dl>*/getSeriesItems: function(series, index){var xAxis = series.get("xAxis"),yAxis = series.get("yAxis"),xKey = series.get("xKey"),yKey = series.get("yKey"),categoryItem,valueItem;if(this.get("direction") === "vertical"){categoryItem = {axis:yAxis,key:yKey,value:yAxis.getKeyValueAt(yKey, index)};valueItem = {axis:xAxis,key:xKey,value: xAxis.getKeyValueAt(xKey, index)};}else{valueItem = {axis:yAxis,key:yKey,value:yAxis.getKeyValueAt(yKey, index)};categoryItem = {axis:xAxis,key:xKey,value: xAxis.getKeyValueAt(xKey, index)};}categoryItem.displayName = series.get("categoryDisplayName");valueItem.displayName = series.get("valueDisplayName");categoryItem.value = categoryItem.axis.getKeyValueAt(categoryItem.key, index);valueItem.value = valueItem.axis.getKeyValueAt(valueItem.key, index);return {category:categoryItem, value:valueItem};},/*** Handler for sizeChanged event.** @method _sizeChanged* @param {Object} e Event object.* @private*/_sizeChanged: function(){if(this._axesCollection){var ac = this._axesCollection,i = 0,l = ac.length;for(; i < l; ++i){this._addToAxesRenderQueue(ac[i]);}this._redraw();}},/*** Returns the maximum distance in pixels that the extends outside the top bounds of all vertical axes.** @method _getTopOverflow* @param {Array} set1 Collection of axes to check.* @param {Array} set2 Seconf collection of axes to check.* @param {Number} width Width of the axes* @return Number* @private*/_getTopOverflow: function(set1, set2, height){var i = 0,len,overflow = 0,axis;if(set1){len = set1.length;for(; i < len; ++i){axis = set1[i];overflow = Math.max(overflow,Math.abs(axis.getMaxLabelBounds().top) - axis.getEdgeOffset(axis.get("styles").majorTicks.count, height));}}if(set2){i = 0;len = set2.length;for(; i < len; ++i){axis = set2[i];overflow = Math.max(overflow,Math.abs(axis.getMaxLabelBounds().top) - axis.getEdgeOffset(axis.get("styles").majorTicks.count, height));}}return overflow;},/*** Returns the maximum distance in pixels that the extends outside the right bounds of all horizontal axes.** @method _getRightOverflow* @param {Array} set1 Collection of axes to check.* @param {Array} set2 Seconf collection of axes to check.* @param {Number} width Width of the axes* @return Number* @private*/_getRightOverflow: function(set1, set2, width){var i = 0,len,overflow = 0,axis;if(set1){len = set1.length;for(; i < len; ++i){axis = set1[i];overflow = Math.max(overflow,axis.getMaxLabelBounds().right - axis.getEdgeOffset(axis.get("styles").majorTicks.count, width));}}if(set2){i = 0;len = set2.length;for(; i < len; ++i){axis = set2[i];overflow = Math.max(overflow,axis.getMaxLabelBounds().right - axis.getEdgeOffset(axis.get("styles").majorTicks.count, width));}}return overflow;},/*** Returns the maximum distance in pixels that the extends outside the left bounds of all horizontal axes.** @method _getLeftOverflow* @param {Array} set1 Collection of axes to check.* @param {Array} set2 Seconf collection of axes to check.* @param {Number} width Width of the axes* @return Number* @private*/_getLeftOverflow: function(set1, set2, width){var i = 0,len,overflow = 0,axis;if(set1){len = set1.length;for(; i < len; ++i){axis = set1[i];overflow = Math.max(overflow,Math.abs(axis.getMinLabelBounds().left) - axis.getEdgeOffset(axis.get("styles").majorTicks.count, width));}}if(set2){i = 0;len = set2.length;for(; i < len; ++i){axis = set2[i];overflow = Math.max(overflow,Math.abs(axis.getMinLabelBounds().left) - axis.getEdgeOffset(axis.get("styles").majorTicks.count, width));}}return overflow;},/*** Returns the maximum distance in pixels that the extends outside the bottom bounds of all vertical axes.** @method _getBottomOverflow* @param {Array} set1 Collection of axes to check.* @param {Array} set2 Seconf collection of axes to check.* @param {Number} height Height of the axes* @return Number* @private*/_getBottomOverflow: function(set1, set2, height){var i = 0,len,overflow = 0,axis;if(set1){len = set1.length;for(; i < len; ++i){axis = set1[i];overflow = Math.max(overflow,axis.getMinLabelBounds().bottom - axis.getEdgeOffset(axis.get("styles").majorTicks.count, height));}}if(set2){i = 0;len = set2.length;for(; i < len; ++i){axis = set2[i];overflow = Math.max(overflow,axis.getMinLabelBounds().bottom - axis.getEdgeOffset(axis.get("styles").majorTicks.count, height));}}return overflow;},/*** Redraws and position all the components of the chart instance.** @method _redraw* @private*/_redraw: function(){if(this._drawing){this._callLater = true;return;}this._drawing = true;this._callLater = false;var w = this.get("width"),h = this.get("height"),leftPaneWidth = 0,rightPaneWidth = 0,topPaneHeight = 0,bottomPaneHeight = 0,leftAxesCollection = this.get("leftAxesCollection"),rightAxesCollection = this.get("rightAxesCollection"),topAxesCollection = this.get("topAxesCollection"),bottomAxesCollection = this.get("bottomAxesCollection"),i = 0,l,axis,graphOverflow = "visible",graph = this.get("graph"),topOverflow,bottomOverflow,leftOverflow,rightOverflow,graphWidth,graphHeight,graphX,graphY,allowContentOverflow = this.get("allowContentOverflow"),diff,rightAxesXCoords,leftAxesXCoords,topAxesYCoords,bottomAxesYCoords,graphRect = {};if(leftAxesCollection){leftAxesXCoords = [];l = leftAxesCollection.length;for(i = l - 1; i > -1; --i){leftAxesXCoords.unshift(leftPaneWidth);leftPaneWidth += leftAxesCollection[i].get("width");}}if(rightAxesCollection){rightAxesXCoords = [];l = rightAxesCollection.length;i = 0;for(i = l - 1; i > -1; --i){rightPaneWidth += rightAxesCollection[i].get("width");rightAxesXCoords.unshift(w - rightPaneWidth);}}if(topAxesCollection){topAxesYCoords = [];l = topAxesCollection.length;for(i = l - 1; i > -1; --i){topAxesYCoords.unshift(topPaneHeight);topPaneHeight += topAxesCollection[i].get("height");}}if(bottomAxesCollection){bottomAxesYCoords = [];l = bottomAxesCollection.length;for(i = l - 1; i > -1; --i){bottomPaneHeight += bottomAxesCollection[i].get("height");bottomAxesYCoords.unshift(h - bottomPaneHeight);}}graphWidth = w - (leftPaneWidth + rightPaneWidth);graphHeight = h - (bottomPaneHeight + topPaneHeight);graphRect.left = leftPaneWidth;graphRect.top = topPaneHeight;graphRect.bottom = h - bottomPaneHeight;graphRect.right = w - rightPaneWidth;if(!allowContentOverflow){topOverflow = this._getTopOverflow(leftAxesCollection, rightAxesCollection);bottomOverflow = this._getBottomOverflow(leftAxesCollection, rightAxesCollection);leftOverflow = this._getLeftOverflow(bottomAxesCollection, topAxesCollection);rightOverflow = this._getRightOverflow(bottomAxesCollection, topAxesCollection);diff = topOverflow - topPaneHeight;if(diff > 0){graphRect.top = topOverflow;if(topAxesYCoords){i = 0;l = topAxesYCoords.length;for(; i < l; ++i){topAxesYCoords[i] += diff;}}}diff = bottomOverflow - bottomPaneHeight;if(diff > 0){graphRect.bottom = h - bottomOverflow;if(bottomAxesYCoords){i = 0;l = bottomAxesYCoords.length;for(; i < l; ++i){bottomAxesYCoords[i] -= diff;}}}diff = leftOverflow - leftPaneWidth;if(diff > 0){graphRect.left = leftOverflow;if(leftAxesXCoords){i = 0;l = leftAxesXCoords.length;for(; i < l; ++i){leftAxesXCoords[i] += diff;}}}diff = rightOverflow - rightPaneWidth;if(diff > 0){graphRect.right = w - rightOverflow;if(rightAxesXCoords){i = 0;l = rightAxesXCoords.length;for(; i < l; ++i){rightAxesXCoords[i] -= diff;}}}}graphWidth = graphRect.right - graphRect.left;graphHeight = graphRect.bottom - graphRect.top;graphX = graphRect.left;graphY = graphRect.top;if(topAxesCollection){l = topAxesCollection.length;i = 0;for(; i < l; i++){axis = topAxesCollection[i];if(axis.get("width") !== graphWidth){axis.set("width", graphWidth);}axis.get("boundingBox").setStyle("left", graphX + "px");axis.get("boundingBox").setStyle("top", topAxesYCoords[i] + "px");}if(axis._hasDataOverflow()){graphOverflow = "hidden";}}if(bottomAxesCollection){l = bottomAxesCollection.length;i = 0;for(; i < l; i++){axis = bottomAxesCollection[i];if(axis.get("width") !== graphWidth){axis.set("width", graphWidth);}axis.get("boundingBox").setStyle("left", graphX + "px");axis.get("boundingBox").setStyle("top", bottomAxesYCoords[i] + "px");}if(axis._hasDataOverflow()){graphOverflow = "hidden";}}if(leftAxesCollection){l = leftAxesCollection.length;i = 0;for(; i < l; ++i){axis = leftAxesCollection[i];axis.get("boundingBox").setStyle("top", graphY + "px");axis.get("boundingBox").setStyle("left", leftAxesXCoords[i] + "px");if(axis.get("height") !== graphHeight){axis.set("height", graphHeight);}}if(axis._hasDataOverflow()){graphOverflow = "hidden";}}if(rightAxesCollection){l = rightAxesCollection.length;i = 0;for(; i < l; ++i){axis = rightAxesCollection[i];axis.get("boundingBox").setStyle("top", graphY + "px");axis.get("boundingBox").setStyle("left", rightAxesXCoords[i] + "px");if(axis.get("height") !== graphHeight){axis.set("height", graphHeight);}}if(axis._hasDataOverflow()){graphOverflow = "hidden";}}this._drawing = false;if(this._callLater){this._redraw();return;}if(graph){graph.get("boundingBox").setStyle("left", graphX + "px");graph.get("boundingBox").setStyle("top", graphY + "px");graph.set("width", graphWidth);graph.set("height", graphHeight);graph.get("boundingBox").setStyle("overflow", graphOverflow);}if(this._overlay){this._overlay.setStyle("left", graphX + "px");this._overlay.setStyle("top", graphY + "px");this._overlay.setStyle("width", graphWidth + "px");this._overlay.setStyle("height", graphHeight + "px");}},/*** Destructor implementation for the CartesianChart class. Calls destroy on all axes, series and the Graph instance.* Removes the tooltip and overlay HTML elements.** @method destructor* @protected*/destructor: function(){var graph = this.get("graph"),i = 0,len,seriesCollection = this.get("seriesCollection"),axesCollection = this._axesCollection,tooltip = this.get("tooltip").node;if(this._description){this._description.empty();this._description.remove(true);}if(this._liveRegion){this._liveRegion.empty();this._liveRegion.remove(true);}len = seriesCollection ? seriesCollection.length : 0;for(; i < len; ++i){if(seriesCollection[i] instanceof Y.CartesianSeries){seriesCollection[i].destroy(true);}}len = axesCollection ? axesCollection.length : 0;for(i = 0; i < len; ++i){if(axesCollection[i] instanceof Y.Axis){axesCollection[i].destroy(true);}}if(graph){graph.destroy(true);}if(tooltip){tooltip.empty();tooltip.remove(true);}if(this._overlay){this._overlay.empty();this._overlay.remove(true);}},/*** Returns the appropriate message based on the key press.** @method _getAriaMessage* @param {Number} key The keycode that was pressed.* @return String*/_getAriaMessage: function(key){var msg = "",series,items,categoryItem,valueItem,seriesIndex = this._seriesIndex,itemIndex = this._itemIndex,seriesCollection = this.get("seriesCollection"),len = seriesCollection.length,dataLength;if(key % 2 === 0){if(len > 1){if(key === 38){seriesIndex = seriesIndex < 1 ? len - 1 : seriesIndex - 1;}else if(key === 40){seriesIndex = seriesIndex >= len - 1 ? 0 : seriesIndex + 1;}this._itemIndex = -1;}else{seriesIndex = 0;}this._seriesIndex = seriesIndex;series = this.getSeries(parseInt(seriesIndex, 10));msg = series.get("valueDisplayName") + " series.";}else{if(seriesIndex > -1){msg = "";series = this.getSeries(parseInt(seriesIndex, 10));}else{seriesIndex = 0;this._seriesIndex = seriesIndex;series = this.getSeries(parseInt(seriesIndex, 10));msg = series.get("valueDisplayName") + " series.";}dataLength = series._dataLength ? series._dataLength : 0;if(key === 37){itemIndex = itemIndex > 0 ? itemIndex - 1 : dataLength - 1;}else if(key === 39){itemIndex = itemIndex >= dataLength - 1 ? 0 : itemIndex + 1;}this._itemIndex = itemIndex;items = this.getSeriesItems(series, itemIndex);categoryItem = items.category;valueItem = items.value;if(categoryItem && valueItem && categoryItem.value && valueItem.value){msg += categoryItem.displayName +": " +categoryItem.axis.formatLabel.apply(this, [categoryItem.value, categoryItem.axis.get("labelFormat")]) +", ";msg += valueItem.displayName +": " +valueItem.axis.formatLabel.apply(this, [valueItem.value, valueItem.axis.get("labelFormat")]) +", ";}else{msg += "No data available.";}msg += (itemIndex + 1) + " of " + dataLength + ". ";}return msg;}}, {ATTRS: {/*** Indicates whether axis labels are allowed to overflow beyond the bounds of the chart's content box.** @attribute allowContentOverflow* @type Boolean*/allowContentOverflow: {value: false},/*** Style object for the axes.** @attribute axesStyles* @type Object* @private*/axesStyles: {lazyAdd: false,getter: function(){var axes = this.get("axes"),i,styles = this._axesStyles;if(axes){for(i in axes){if(axes.hasOwnProperty(i) && axes[i] instanceof Y.Axis){if(!styles){styles = {};}styles[i] = axes[i].get("styles");}}}return styles;},setter: function(val){var axes = this.get("axes"),i;for(i in val){if(val.hasOwnProperty(i) && axes.hasOwnProperty(i)){this._setBaseAttribute(axes[i], "styles", val[i]);}}return val;}},/*** Style object for the series** @attribute seriesStyles* @type Object* @private*/seriesStyles: {lazyAdd: false,getter: function(){var styles = this._seriesStyles,graph = this.get("graph"),dict,i;if(graph){dict = graph.get("seriesDictionary");if(dict){styles = {};for(i in dict){if(dict.hasOwnProperty(i)){styles[i] = dict[i].get("styles");}}}}return styles;},setter: function(val){var i,l,s;if(Y_Lang.isArray(val)){s = this.get("seriesCollection");i = 0;l = val.length;for(; i < l; ++i){this._setBaseAttribute(s[i], "styles", val[i]);}}else{for(i in val){if(val.hasOwnProperty(i)){s = this.getSeries(i);this._setBaseAttribute(s, "styles", val[i]);}}}return val;}},/*** Styles for the graph.** @attribute graphStyles* @type Object* @private*/graphStyles: {lazyAdd: false,getter: function(){var graph = this.get("graph");if(graph){return(graph.get("styles"));}return this._graphStyles;},setter: function(val){var graph = this.get("graph");this._setBaseAttribute(graph, "styles", val);return val;}},/*** Style properties for the chart. Contains a key indexed hash of the following:* <dl>* <dt>series</dt><dd>A key indexed hash containing references to the `styles` attribute for each series in the chart.* Specific style attributes vary depending on the series:* <ul>* <li><a href="AreaSeries.html#attr_styles">AreaSeries</a></li>* <li><a href="BarSeries.html#attr_styles">BarSeries</a></li>* <li><a href="ColumnSeries.html#attr_styles">ColumnSeries</a></li>* <li><a href="ComboSeries.html#attr_styles">ComboSeries</a></li>* <li><a href="LineSeries.html#attr_styles">LineSeries</a></li>* <li><a href="MarkerSeries.html#attr_styles">MarkerSeries</a></li>* <li><a href="SplineSeries.html#attr_styles">SplineSeries</a></li>* </ul>* </dd>* <dt>axes</dt><dd>A key indexed hash containing references to the `styles` attribute for each axes in the chart. Specific* style attributes can be found in the <a href="Axis.html#attr_styles">Axis</a> class.</dd>* <dt>graph</dt><dd>A reference to the `styles` attribute in the chart. Specific style attributes can be found in the* <a href="Graph.html#attr_styles">Graph</a> class.</dd>* </dl>** @attribute styles* @type Object*/styles: {lazyAdd: false,getter: function(){var styles = {axes: this.get("axesStyles"),series: this.get("seriesStyles"),graph: this.get("graphStyles")};return styles;},setter: function(val){if(val.hasOwnProperty("axes")){if(this.get("axesStyles")){this.set("axesStyles", val.axes);}else{this._axesStyles = val.axes;}}if(val.hasOwnProperty("series")){if(this.get("seriesStyles")){this.set("seriesStyles", val.series);}else{this._seriesStyles = val.series;}}if(val.hasOwnProperty("graph")){this.set("graphStyles", val.graph);}}},/*** Axes to appear in the chart. This can be a key indexed hash of axis instances or object literals* used to construct the appropriate axes.** @attribute axes* @type Object*/axes: {lazyAdd: false,valueFn: "_getDefaultAxes",setter: function(val){if(this.get("dataProvider")){val = this._setAxes(val);}return val;}},/*** Collection of series to appear on the chart. This can be an array of Series instances or object literals* used to construct the appropriate series.** @attribute seriesCollection* @type Array*/seriesCollection: {lazyAdd: false,valueFn: "_getDefaultSeriesCollection",setter: function(val){if(this.get("dataProvider")){return this._parseSeriesCollection(val);}return val;}},/*** Reference to the left-aligned axes for the chart.** @attribute leftAxesCollection* @type Array* @private*/leftAxesCollection: {},/*** Reference to the bottom-aligned axes for the chart.** @attribute bottomAxesCollection* @type Array* @private*/bottomAxesCollection: {},/*** Reference to the right-aligned axes for the chart.** @attribute rightAxesCollection* @type Array* @private*/rightAxesCollection: {},/*** Reference to the top-aligned axes for the chart.** @attribute topAxesCollection* @type Array* @private*/topAxesCollection: {},/*** Indicates whether or not the chart is stacked.** @attribute stacked* @type Boolean*/stacked: {value: false},/*** Direction of chart's category axis when there is no series collection specified. Charts can* be horizontal or vertical. When the chart type is column, the chart is horizontal.* When the chart type is bar, the chart is vertical.** @attribute direction* @type String*/direction: {getter: function(){var type = this.get("type");if(type === "bar"){return "vertical";}else if(type === "column"){return "horizontal";}return this._direction;},setter: function(val){this._direction = val;return this._direction;}},/*** Indicates whether or not an area is filled in a combo chart.** @attribute showAreaFill* @type Boolean*/showAreaFill: {},/*** Indicates whether to display markers in a combo chart.** @attribute showMarkers* @type Boolean*/showMarkers:{},/*** Indicates whether to display lines in a combo chart.** @attribute showLines* @type Boolean*/showLines:{},/*** Indicates the key value used to identify a category axis in the `axes` hash. If* not specified, the categoryKey attribute value will be used.** @attribute categoryAxisName* @type String*/categoryAxisName: {},/*** Indicates the key value used to identify a the series axis when an axis not generated.** @attribute valueAxisName* @type String*/valueAxisName: {value: "values"},/*** Reference to the horizontalGridlines for the chart.** @attribute horizontalGridlines* @type Gridlines*/horizontalGridlines: {getter: function(){var graph = this.get("graph");if(graph){return graph.get("horizontalGridlines");}return this._horizontalGridlines;},setter: function(val){var graph = this.get("graph");if(val && !Y_Lang.isObject(val)){val = {};}if(graph){graph.set("horizontalGridlines", val);}else{this._horizontalGridlines = val;}}},/*** Reference to the verticalGridlines for the chart.** @attribute verticalGridlines* @type Gridlines*/verticalGridlines: {getter: function(){var graph = this.get("graph");if(graph){return graph.get("verticalGridlines");}return this._verticalGridlines;},setter: function(val){var graph = this.get("graph");if(val && !Y_Lang.isObject(val)){val = {};}if(graph){graph.set("verticalGridlines", val);}else{this._verticalGridlines = val;}}},/*** Type of chart when there is no series collection specified.** @attribute type* @type String*/type: {getter: function(){if(this.get("stacked")){return "stacked" + this._type;}return this._type;},setter: function(val){if(this._type === "bar"){if(val !== "bar"){this.set("direction", "horizontal");}}else{if(val === "bar"){this.set("direction", "vertical");}}this._type = val;return this._type;}},/*** Reference to the category axis used by the chart.** @attribute categoryAxis* @type Axis*/categoryAxis:{}}});/*** The PieChart class creates a pie chart** @class PieChart* @extends ChartBase* @constructor* @submodule charts-base*/Y.PieChart = Y.Base.create("pieChart", Y.Widget, [Y.ChartBase], {/*** Calculates and returns a `seriesCollection`.** @method _getSeriesCollection* @return Array* @private*/_getSeriesCollection: function(){if(this._seriesCollection){return this._seriesCollection;}var axes = this.get("axes"),sc = [],seriesKeys,i = 0,l,type = this.get("type"),key,catAxis = "categoryAxis",catKey = "categoryKey",valAxis = "valueAxis",seriesKey = "valueKey";if(axes){seriesKeys = axes.values.get("keyCollection");key = axes.category.get("keyCollection")[0];l = seriesKeys.length;for(; i < l; ++i){sc[i] = {type:type};sc[i][catAxis] = "category";sc[i][valAxis] = "values";sc[i][catKey] = key;sc[i][seriesKey] = seriesKeys[i];}}this._seriesCollection = sc;return sc;},/*** Creates `Axis` instances.** @method _parseAxes* @param {Object} val Object containing `Axis` instances or objects in which to construct `Axis` instances.* @return Object* @private*/_parseAxes: function(hash){if(!this._axes){this._axes = {};}var i, pos, axis, dh, config, AxisClass,type = this.get("type"),w = this.get("width"),h = this.get("height"),node = Y.Node.one(this._parentNode);if(!w){this.set("width", node.get("offsetWidth"));w = this.get("width");}if(!h){this.set("height", node.get("offsetHeight"));h = this.get("height");}for(i in hash){if(hash.hasOwnProperty(i)){dh = hash[i];pos = type === "pie" ? "none" : dh.position;AxisClass = this._getAxisClass(dh.type);config = {dataProvider:this.get("dataProvider")};if(dh.hasOwnProperty("roundingUnit")){config.roundingUnit = dh.roundingUnit;}config.keys = dh.keys;config.width = w;config.height = h;config.position = pos;config.styles = dh.styles;axis = new AxisClass(config);axis.on("axisRendered", Y.bind(this._itemRendered, this));this._axes[i] = axis;}}},/*** Adds axes to the chart.** @method _addAxes* @private*/_addAxes: function(){var axes = this.get("axes"),i,axis,p;if(!axes){this.set("axes", this._getDefaultAxes());axes = this.get("axes");}if(!this._axesCollection){this._axesCollection = [];}for(i in axes){if(axes.hasOwnProperty(i)){axis = axes[i];p = axis.get("position");if(!this.get(p + "AxesCollection")){this.set(p + "AxesCollection", [axis]);}else{this.get(p + "AxesCollection").push(axis);}this._axesCollection.push(axis);}}},/*** Renders the Graph.** @method _addSeries* @private*/_addSeries: function(){var graph = this.get("graph"),seriesCollection = this.get("seriesCollection");this._parseSeriesAxes(seriesCollection);graph.set("showBackground", false);graph.set("width", this.get("width"));graph.set("height", this.get("height"));graph.set("seriesCollection", seriesCollection);this._seriesCollection = graph.get("seriesCollection");graph.render(this.get("contentBox"));},/*** Parse and sets the axes for the chart.** @method _parseSeriesAxes* @param {Array} c A collection `PieSeries` instance.* @private*/_parseSeriesAxes: function(c){var i = 0,len = c.length,s,axes = this.get("axes"),axis;for(; i < len; ++i){s = c[i];if(s){//If series is an actual series instance,//replace axes attribute string ids with axesif(s instanceof Y.PieSeries){axis = s.get("categoryAxis");if(axis && !(axis instanceof Y.Axis)){s.set("categoryAxis", axes[axis]);}axis = s.get("valueAxis");if(axis && !(axis instanceof Y.Axis)){s.set("valueAxis", axes[axis]);}continue;}s.categoryAxis = axes.category;s.valueAxis = axes.values;if(!s.type){s.type = this.get("type");}}}},/*** Generates and returns a key-indexed object containing `Axis` instances or objects used to create `Axis` instances.** @method _getDefaultAxes* @return Object* @private*/_getDefaultAxes: function(){var catKey = this.get("categoryKey"),seriesKeys = this.get("seriesKeys").concat(),seriesAxis = "numeric";return {values:{keys:seriesKeys,type:seriesAxis},category:{keys:[catKey],type:this.get("categoryType")}};},/*** Returns an object literal containing a categoryItem and a valueItem for a given series index.** @method getSeriesItem* @param series Reference to a series.* @param index Index of the specified item within a series.* @return Object*/getSeriesItems: function(series, index){var categoryItem = {axis: series.get("categoryAxis"),key: series.get("categoryKey"),displayName: series.get("categoryDisplayName")},valueItem = {axis: series.get("valueAxis"),key: series.get("valueKey"),displayName: series.get("valueDisplayName")};categoryItem.value = categoryItem.axis.getKeyValueAt(categoryItem.key, index);valueItem.value = valueItem.axis.getKeyValueAt(valueItem.key, index);return {category:categoryItem, value:valueItem};},/*** Handler for sizeChanged event.** @method _sizeChanged* @param {Object} e Event object.* @private*/_sizeChanged: function(){this._redraw();},/*** Redraws the chart instance.** @method _redraw* @private*/_redraw: function(){var graph = this.get("graph"),w = this.get("width"),h = this.get("height"),dimension;if(graph){dimension = Math.min(w, h);graph.set("width", dimension);graph.set("height", dimension);}},/*** Formats tooltip text for a pie chart.** @method _tooltipLabelFunction* @param {Object} categoryItem An object containing the following:* <dl>* <dt>axis</dt><dd>The axis to which the category is bound.</dd>* <dt>displayName</dt><dd>The display name set to the category (defaults to key if not provided)</dd>* <dt>key</dt><dd>The key of the category.</dd>* <dt>value</dt><dd>The value of the category</dd>* </dl>* @param {Object} valueItem An object containing the following:* <dl>* <dt>axis</dt><dd>The axis to which the item's series is bound.</dd>* <dt>displayName</dt><dd>The display name of the series. (defaults to key if not provided)</dd>* <dt>key</dt><dd>The key for the series.</dd>* <dt>value</dt><dd>The value for the series item.</dd>* </dl>* @param {Number} itemIndex The index of the item within the series.* @param {CartesianSeries} series The `PieSeries` instance of the item.* @return {HTMLElement}* @private*/_tooltipLabelFunction: function(categoryItem, valueItem, itemIndex, series){var msg = DOCUMENT.createElement("div"),total = series.getTotalValues(),pct = Math.round((valueItem.value / total) * 10000)/100;msg.appendChild(DOCUMENT.createTextNode(categoryItem.displayName +": " + categoryItem.axis.get("labelFunction").apply(this, [categoryItem.value, categoryItem.axis.get("labelFormat")])));msg.appendChild(DOCUMENT.createElement("br"));msg.appendChild(DOCUMENT.createTextNode(valueItem.displayName +": " + valueItem.axis.get("labelFunction").apply(this, [valueItem.value, valueItem.axis.get("labelFormat")])));msg.appendChild(DOCUMENT.createElement("br"));msg.appendChild(DOCUMENT.createTextNode(pct + "%"));return msg;},/*** Returns the appropriate message based on the key press.** @method _getAriaMessage* @param {Number} key The keycode that was pressed.* @return String*/_getAriaMessage: function(key){var msg = "",categoryItem,items,series,valueItem,seriesIndex = 0,itemIndex = this._itemIndex,len,total,pct,markers;series = this.getSeries(parseInt(seriesIndex, 10));markers = series.get("markers");len = markers && markers.length ? markers.length : 0;if(key === 37){itemIndex = itemIndex > 0 ? itemIndex - 1 : len - 1;}else if(key === 39){itemIndex = itemIndex >= len - 1 ? 0 : itemIndex + 1;}this._itemIndex = itemIndex;items = this.getSeriesItems(series, itemIndex);categoryItem = items.category;valueItem = items.value;total = series.getTotalValues();pct = Math.round((valueItem.value / total) * 10000)/100;if(categoryItem && valueItem){msg += categoryItem.displayName +": " +categoryItem.axis.formatLabel.apply(this, [categoryItem.value, categoryItem.axis.get("labelFormat")]) +", ";msg += valueItem.displayName +": " + valueItem.axis.formatLabel.apply(this, [valueItem.value, valueItem.axis.get("labelFormat")]) +", ";msg += "Percent of total " + valueItem.displayName + ": " + pct + "%,";}else{msg += "No data available,";}msg += (itemIndex + 1) + " of " + len + ". ";return msg;},/*** Destructor implementation for the PieChart class.** @method destructor* @protected*/destructor: function(){var series,axis,tooltip = this.get("tooltip"),tooltipNode = tooltip.node,graph = this.get("graph"),axesCollection = this._axesCollection,seriesCollection = this.get("seriesCollection");while(seriesCollection.length > 0){series = seriesCollection.shift();series.destroy(true);}while(axesCollection.length > 0){axis = axesCollection.shift();if(axis instanceof Y.Axis){axis.destroy(true);}}if(this._description){this._description.empty();this._description.remove(true);}if(this._liveRegion){this._liveRegion.empty();this._liveRegion.remove(true);}if(graph){graph.destroy(true);}if(tooltipNode){tooltipNode.empty();tooltipNode.remove(true);}}}, {ATTRS: {/*** Sets the aria description for the chart.** @attribute ariaDescription* @type String*/ariaDescription: {value: "Use the left and right keys to navigate through items.",setter: function(val){if(this._description){this._description.set("text", val);}return val;}},/*** Axes to appear in the chart.** @attribute axes* @type Object*/axes: {getter: function(){return this._axes;},setter: function(val){this._parseAxes(val);}},/*** Collection of series to appear on the chart. This can be an array of Series instances or object literals* used to describe a Series instance.** @attribute seriesCollection* @type Array*/seriesCollection: {lazyAdd: false,getter: function(){return this._getSeriesCollection();},setter: function(val){return this._setSeriesCollection(val);}},/*** Type of chart when there is no series collection specified.** @attribute type* @type String*/type: {value: "pie"}}});/*** The Chart class is the basic application used to create a chart.** @class Chart* @constructor* @submodule charts-base*/function Chart(cfg){if(cfg.type !== "pie"){return new Y.CartesianChart(cfg);}else{return new Y.PieChart(cfg);}}Y.Chart = Chart;}, '3.18.1', {"requires": ["dom","event-mouseenter","event-touch","graphics-group","axes","series-pie","series-line","series-marker","series-area","series-spline","series-column","series-bar","series-areaspline","series-combo","series-combospline","series-line-stacked","series-marker-stacked","series-area-stacked","series-spline-stacked","series-column-stacked","series-bar-stacked","series-areaspline-stacked","series-combo-stacked","series-combospline-stacked"]});