#

API Docs for: 3.10.3
Show: Inherited Protected Private Deprecated

# File: charts/js/PieChart.js

    /**
     * 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"
            }
        }
    });