src/cm/media/js/lib/yui/yui_3.10.3/build/charts-base/charts-base.js
changeset 525 89ef5ed3c48b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cm/media/js/lib/yui/yui_3.10.3/build/charts-base/charts-base.js	Tue Jul 16 14:29:46 2013 +0200
@@ -0,0 +1,5119 @@
+/*
+YUI 3.10.3 (build 2fb5187)
+Copyright 2013 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+
+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._seriesKeysExplicitlySet)
+            {
+                this.set("seriesKeys", this._buildSeriesKeys(defDataProvider), {src: "internal"});
+            }
+            return defDataProvider;
+        },
+
+        setter: function(val)
+        {
+            var dataProvider = this._setDataValues(val);
+            if(!this._seriesKeysExplicitlySet)
+            {
+                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.setContent("");
+                this._description.appendChild(DOCUMENT.createTextNode(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 = {
+    /**
+     * 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 file
+        bb.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.appendChild(DOCUMENT.createTextNode(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.setContent("");
+                this._liveRegion.appendChild(DOCUMENT.createTextNode(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 touched
+                Y.on("touchend", Y.bind(function(e) {
+                    //only halt the event if it originated from the chart
+                    if(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;
+            node = Y.one(val.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 {String | HTML}
+     * @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 {String | HTML}
+     * @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.setContent("");
+        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"),
+            overlay,
+            overlayClass = _getClassName("overlay");
+        //move the position = absolute logic to a class file
+        bb.setStyle("position", "absolute");
+        cb.setStyle("position", "absolute");
+        this._addAxes();
+        this._addGridlines();
+        this._addSeries();
+        if(tt && tt.show)
+        {
+            this._addTooltip();
+        }
+        if(this.get("interactionType") === "planar")
+        {
+            overlay = DOCUMENT.createElement("div");
+            this.get("contentBox").appendChild(overlay);
+            this._overlay = Y.one(overlay);
+            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);
+        }
+        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 level
+            markerPlane,
+            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",
+                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 already
+                    if(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._seriesKeysExplicitlySet)
+        {
+            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 axes
+                if(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 {HTML}
+     * @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;
+    }
+}, {
+    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.setContent("");
+                    this._description.appendChild(DOCUMENT.createTextNode(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.10.3', {
+    "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"
+    ]
+});