# Yahoo! UI Library

### charts 3.3.0

Yahoo! UI Library > charts > Graph.js (source view)
Search:
Filters Show Private Show Protected Show Deprecated

    /**
     * Graph manages and contains series instances for a <code>CartesianChart</code>
     * instance.
     *
     * @class Graph
     * @constructor
     * @extends Widget
     * @uses Renderer
     */
    Y.Graph = Y.Base.create("graph", Y.Widget, [Y.Renderer], {
        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);
        },

        /**
         * @private
         */
        syncUI: function()
        {
            if(this.get("showBackground"))
            {
                var graphic = new Y.Graphic(),
                    graphicNode,
                    cb = this.get("contentBox"),
                    bg = this.get("styles").background,
                    border = bg.border,
                    weight = border.weight || 0,
                    w = this.get("width"),
                    h = this.get("height");
                if(w)
                {
                    w += weight * 2;
                    bg.width = w;
                }
                if(h)
                {
                    h += weight * 2;
                    bg.height = h;
                }
                graphic.render(cb);
                this._background = graphic.getShape(bg);
                graphicNode = Y.one(graphic.node);
                graphicNode.setStyle("left", 0 - weight);
                graphicNode.setStyle("top", 0 - weight);
                graphicNode.setStyle("zIndex", -1);
            }
        },

        /**
         * @private
         */
        renderUI: function()
        {
            var sc = this.get("seriesCollection"),
                series,
                i = 0,
                len = sc.length,
                hgl = this.get("horizontalGridlines"),
                vgl = this.get("verticalGridlines");
            for(; i < len; ++i)
            {
                series = sc[i];
                if(series instanceof Y.CartesianSeries)
                {
                    series.render();
                }
            }
            if(hgl && hgl instanceof Y.Gridlines)
            {
                hgl.draw();
            }
            if(vgl && vgl instanceof Y.Gridlines)
            {
                vgl.draw();
            }
        },

        /**
         * @private
         * Hash of arrays containing series mapped to a series type.
         */
        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;
        },

        /**
         * @protected
         * Adds dispatcher to a <code>_dispatcher</code> used to
         * to ensure all series have redrawn before for firing event.
         *
         * @method addDispatcher
         * @param {CartesianSeries} val series instance to add
         */
        addDispatcher: function(val)
        {
            if(!this._dispatchers)
            {
                this._dispatchers = [];
            }
            this._dispatchers.push(val);
        },

        /**
         * @private
         * @description Collection of series to be displayed in the graph.
         */
        _seriesCollection: null,

        /**
         * @private
         */
        _seriesDictionary: null,

        /**
         * @private
         * Parses series instances to be displayed in the graph.
         */
        _parseSeriesCollection: function(val)
        {
            if(!val)
            {
                return;
            }
            var len = val.length,
                i = 0,
                series,
                seriesKey;
            if(!this.get("seriesCollection"))
            {
                this._seriesCollection = [];
            }
            if(!this._seriesDictionary)
            {
                this._seriesDictionary = {};
            }
            if(!this.seriesTypes)
            {
                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.get("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;
            }
        },

        /**
         * @private
         * Adds a series to the graph.
         */
        _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);
            this.addDispatcher(series);
            series.after("drawingComplete", Y.bind(this._drawingCompleteHandler, this));
            this.fire("seriesAdded", series);
        },

        /**
         * @private
         */
        _createSeries: function(seriesData)
        {
            var type = seriesData.type,
                seriesCollection = this.get("seriesCollection"),
                seriesTypes = this.seriesTypes,
                typeSeriesCollection,
                seriesType,
                series;
                seriesData.graph = this;
            if(!seriesTypes.hasOwnProperty(type))
            {
                seriesTypes[type] = [];
            }
            typeSeriesCollection = seriesTypes[type];
            seriesData.graph = this;
            seriesData.order = typeSeriesCollection.length;
            seriesData.graphOrder = seriesCollection.length;
            seriesType = this._getSeries(seriesData.type);
            series = new seriesType(seriesData);
            this.addDispatcher(series);
            series.after("drawingComplete", Y.bind(this._drawingCompleteHandler, this));
            typeSeriesCollection.push(series);
            seriesCollection.push(series);
        },

        /**
         * @private
         */
        _getSeries: function(type)
        {
            var seriesClass;
            switch(type)
            {
                case "line" :
                    seriesClass = Y.LineSeries;
                break;
                case "column" :
                    seriesClass = Y.ColumnSeries;
                break;
                case "bar" :
                    seriesClass = Y.BarSeries;
                break;
                case "area" :
                    seriesClass = Y.AreaSeries;
                break;
                case "candlestick" :
                    seriesClass = Y.CandlestickSeries;
                break;
                case "ohlc" :
                    seriesClass = Y.OHLCSeries;
                break;
                case "stackedarea" :
                    seriesClass = Y.StackedAreaSeries;
                break;
                case "stackedline" :
                    seriesClass = Y.StackedLineSeries;
                break;
                case "stackedcolumn" :
                    seriesClass = Y.StackedColumnSeries;
                break;
                case "stackedbar" :
                    seriesClass = Y.StackedBarSeries;
                break;
                case "markerseries" :
                    seriesClass = Y.MarkerSeries;
                break;
                case "spline" :
                    seriesClass = Y.SplineSeries;
                break;
                case "areaspline" :
                    seriesClass = Y.AreaSplineSeries;
                break;
                case "stackedspline" :
                    seriesClass = Y.StackedSplineSeries;
                break;
                case "stackedareaspline" :
                    seriesClass = Y.StackedAreaSplineSeries;
                break;
                case "stackedmarkerseries" :
                    seriesClass = Y.StackedMarkerSeries;
                break;
                case "pie" :
                    seriesClass = Y.PieSeries;
                break;
                case "combo" :
                    seriesClass = Y.ComboSeries;
                break;
                case "stackedcombo" :
                    seriesClass = Y.StackedComboSeries;
                break;
                case "combospline" :
                    seriesClass = Y.ComboSplineSeries;
                break;
                case "stackedcombospline" :
                    seriesClass = Y.StackedComboSplineSeries;
                break;
                default:
                    seriesClass = Y.CartesianSeries;
                break;
            }
            return seriesClass;
        },

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

        /**
         * @private
         */
        _dispatchers: null,

        /**
         * @private
         */
        _updateStyles: function()
        {
            this._background.update(this.get("styles").background);
            this._sizeChangeHandler();
        },

        /**
         * @private
         */
        _sizeChangeHandler: function(e)
        {
            var hgl = this.get("horizontalGridlines"),
                vgl = this.get("verticalGridlines"),
                w = this.get("width"),
                h = this.get("height"),
                graphicNode,
                x = 0,
                y = 0,
                bg = this.get("styles").background,
                weight;
            if(bg && bg.border)
            {
                weight = bg.border.weight || 0;
            }
            if(this._background)
            {
                graphicNode = Y.one(this._background.parentNode);
                if(w && h)
                {
                    if(weight)
                    {
                        w += weight * 2;
                        h += weight * 2;
                        x -= weight;
                        y -= weight;
                    }
                    graphicNode.setStyle("width", w);
                    graphicNode.setStyle("height", h);
                    graphicNode.setStyle("left", x);
                    graphicNode.setStyle("top", y);
                    this._background.update({width:w, height:h});
                }
            }
            if(hgl && hgl instanceof Y.Gridlines)
            {
                hgl.draw();
            }
            if(vgl && vgl instanceof Y.Gridlines)
            {
                vgl.draw();
            }
            this._drawSeries();
        },

        /**
         * @private
         */
        _drawSeries: function()
        {
            if(this._drawing)
            {
                this._callLater = true;
                return;
            }
            this._callLater = false;
            this._drawing = true;
            var sc = this.get("seriesCollection"),
                i = 0,
                len = sc.length;
            for(; i < len; ++i)
            {
                sc[i].draw();
                if(!sc[i].get("xcoords") || !sc[i].get("ycoords"))
                {
                    this._callLater = true;
                    break;
                }
            }
            this._drawing = false;
            if(this._callLater)
            {
                this._drawSeries();
            }
        },

        /**
         * @private
         */
        _drawingCompleteHandler: function(e)
        {
            var series = e.currentTarget,
                index = Y.Array.indexOf(this._dispatchers, series);
            if(index > -1)
            {
                this._dispatchers.splice(index, 1);
            }
            if(this._dispatchers.length < 1)
            {
                this.fire("chartRendered");
            }
        },

        /**
         * @protected
         *
         * Gets the default value for the <code>styles</code> attribute. Overrides
         * base implementation.
         *
         * @method _getDefaultStyles
         * @return Object
         */
        _getDefaultStyles: function()
        {
            var defs = {
                background: {
                    shape: "rect",
                    fill:{
                        color:"#faf9f2"
                    },
                    border: {
                        color:"#dad8c9",
                        weight: 1
                    }
                }
            };
            return defs;
        }
    }, {
        ATTRS: {
            /**
             * Collection of series. When setting the <code>seriesCollection</code> the array can contain a combination of either
             * <code>CartesianSeries</code> 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 <code>Graph</code> has a background.
             *
             * @attribute showBackground
             * @type Boolean
             * @default true
             */
            showBackground: {
                value: true
            },

            /**
             * Read-only hash lookup for all series on in the <code>Graph</code>.
             *
             * @attribute seriesDictionary
             * @type Object
             */
            seriesDictionary: {
                readOnly: true,

                getter: function()
                {
                    return this._seriesDictionary;
                }
            },

            /**
             * Reference to the horizontal <code>Gridlines</code> instance.
             *
             * @attribute horizontalGridlines
             * @type Gridlines
             * @default null
             */
            horizontalGridlines: {
                value: null,

                setter: function(val)
                {
                    var gl = this.get("horizontalGridlines");
                    if(gl && gl instanceof Y.Gridlines)
                    {
                        gl.remove();
                    }
                    if(val instanceof Y.Gridlines)
                    {
                        gl = val;
                        val.set("graph", this);
                        val.render();
                        return val;
                    }
                    else if(val && val.axis)
                    {
                        gl = new Y.Gridlines({direction:"horizontal", axis:val.axis, graph:this, styles:val.styles});
                        gl.render();
                        return gl;
                    }
                }
            },

            /**
             * Reference to the vertical <code>Gridlines</code> instance.
             *
             * @attribute verticalGridlines
             * @type Gridlines
             * @default null
             */
            verticalGridlines: {
                value: null,

                setter: function(val)
                {
                    var gl = this.get("verticalGridlines");
                    if(gl && gl instanceof Y.Gridlines)
                    {
                        gl.remove();
                    }
                    if(val instanceof Y.Gridlines)
                    {
                        gl = val;
                        val.set("graph", this);
                        val.render();
                        return val;
                    }
                    else if(val && val.axis)
                    {
                        gl = new Y.Gridlines({direction:"vertical", axis:val.axis, graph:this, styles:val.styles});
                        gl.render();
                        return gl;
                    }
                }
            }

            /**
             * Style properties used for drawing a background. Below are the default values:
             *  <dl>
             *      <dt>fill</dt><dd>A hash containing 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>A hash containing 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>
             *
             * @attribute styles
             * @type Object
             */
        }
    });

Copyright © 2011 Yahoo! Inc. All rights reserved.