# Yahoo! UI Library

### charts 3.3.0

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

    /**
     * The CartesianSeries class creates a chart with horizontal and vertical axes.
     *
     * @class CartesianSeries
     * @extends Base
     * @uses Renderer
     * @constructor
     */
    Y.CartesianSeries = Y.Base.create("cartesianSeries", Y.Base, [Y.Renderer], {
        /**
         * @private
         */
        _xDisplayName: null,

        /**
         * @private
         */
        _yDisplayName: null,

        /**
         * @private
         */
        _leftOrigin: null,

        /**
         * @private
         */
        _bottomOrigin: null,

        /**
         * @private
         */
        render: function()
        {
            this._setCanvas();
            this.addListeners();
            this.set("rendered", true);
            this.validate();
        },

        /**
         * @private
         */
        addListeners: function()
        {
            var xAxis = this.get("xAxis"),
                yAxis = this.get("yAxis");
            if(xAxis)
            {
                xAxis.after("dataReady", Y.bind(this._xDataChangeHandler, this));
                xAxis.after("dataUpdate", Y.bind(this._xDataChangeHandler, this));
            }
            if(yAxis)
            {
                yAxis.after("dataReady", Y.bind(this._yDataChangeHandler, this));
                yAxis.after("dataUpdate", Y.bind(this._yDataChangeHandler, this));
            }
            this.after("xAxisChange", this._xAxisChangeHandler);
            this.after("yAxisChange", this._yAxisChangeHandler);
            this.after("stylesChange", function(e) {
                var axesReady = this._updateAxisData();
                if(axesReady)
                {
                    this.draw();
                }
            });
            this.after("widthChange", function(e) {
                var axesReady = this._updateAxisData();
                if(axesReady)
                {
                    this.draw();
                }
            });
            this.after("heightChange", function(e) {
                var axesReady = this._updateAxisData();
                if(axesReady)
                {
                    this.draw();
                }
            });
            this.after("visibleChange", this._toggleVisible);
        },

        /**
         * @private
         */
        _xAxisChangeHandler: function(e)
        {
            var xAxis = this.get("xAxis");
            xAxis.after("dataReady", Y.bind(this._xDataChangeHandler, this));
            xAxis.after("dataUpdate", Y.bind(this._xDataChangeHandler, this));
        },

        /**
         * @private
         */
        _yAxisChangeHandler: function(e)
        {
            var yAxis = this.get("yAxis");
            yAxis.after("dataReady", Y.bind(this._yDataChangeHandler, this));
            yAxis.after("dataUpdate", Y.bind(this._yDataChangeHandler, this));
        },

        /**
         * @private
         */
        GUID: "yuicartesianseries",

        /**
         * @private (protected)
         */
        _xDataChangeHandler: function(event)
        {
            var axesReady = this._updateAxisData();
            if(axesReady)
            {
                this.draw();
            }
        },

        /**
         * @private (protected)
         */
        _yDataChangeHandler: function(event)
        {
            var axesReady = this._updateAxisData();
            if(axesReady)
            {
                this.draw();
            }
        },

        /**
         * @private
         */
        _updateAxisData: function()
        {
            var xAxis = this.get("xAxis"),
                yAxis = this.get("yAxis"),
                xKey = this.get("xKey"),
                yKey = this.get("yKey"),
                yData,
                xData;
            if(!xAxis || !yAxis || !xKey || !yKey)
            {
                return false;
            }
            xData = xAxis.getDataByKey(xKey);
            yData = yAxis.getDataByKey(yKey);
            if(!xData || !yData)
            {
                return false;
            }
            this.set("xData", xData.concat());
            this.set("yData", yData.concat());
            return true;
        },

        /**
         * @private
         */
        validate: function()
        {
            if((this.get("xData") && this.get("yData")) || this._updateAxisData())
            {
                this.draw();
            }
        },

        /**
         * @protected
         *
         * Creates a <code>Graphic</code> instance.
         *
         * @method _setCanvas
         */
        _setCanvas: function()
        {
            this.set("graphic", new Y.Graphic());
            this.get("graphic").render(this.get("graph").get("contentBox"));
        },

        /**
         * @protected
         *
         * Calculates the coordinates for the series.
         *
         * @method setAreaData
         */
        setAreaData: function()
        {
            var nextX, nextY,
                graph = this.get("graph"),
                w = graph.get("width"),
                h = graph.get("height"),
                xAxis = this.get("xAxis"),
                yAxis = this.get("yAxis"),
                xData = this.get("xData").concat(),
                yData = this.get("yData").concat(),
                xOffset = xAxis.getEdgeOffset(xData.length, w),
                yOffset = yAxis.getEdgeOffset(yData.length, h),
                padding = this.get("styles").padding,
    			leftPadding = padding.left,
    			topPadding = padding.top,
    			dataWidth = w - (leftPadding + padding.right + xOffset),
    			dataHeight = h - (topPadding + padding.bottom + yOffset),
    			xcoords = [],
    			ycoords = [],
    			xMax = xAxis.get("maximum"),
    			xMin = xAxis.get("minimum"),
    			yMax = yAxis.get("maximum"),
    			yMin = yAxis.get("minimum"),
                xScaleFactor = dataWidth / (xMax - xMin),
    			yScaleFactor = dataHeight / (yMax - yMin),
                dataLength,
                direction = this.get("direction"),
                i = 0,
                xMarkerPlane = [],
                yMarkerPlane = [],
                xMarkerPlaneOffset = this.get("xMarkerPlaneOffset"),
                yMarkerPlaneOffset = this.get("yMarkerPlaneOffset"),
                graphic = this.get("graphic");
            dataLength = xData.length;
            xOffset *= 0.5;
            yOffset *= 0.5;
            //Assuming a vertical graph has a range/category for its vertical axis.
            if(direction === "vertical")
            {
                yData = yData.reverse();
            }
            if(graphic)
            {
                graphic.setSize(w, h);
            }
            this._leftOrigin = Math.round(((0 - xMin) * xScaleFactor) + leftPadding + xOffset);
            this._bottomOrigin =  Math.round((dataHeight + topPadding + yOffset) - (0 - yMin) * yScaleFactor);
            for (; i < dataLength; ++i)
    		{
                nextX = Math.round((((xData[i] - xMin) * xScaleFactor) + leftPadding + xOffset));
    			nextY = Math.round(((dataHeight + topPadding + yOffset) - (yData[i] - yMin) * yScaleFactor));
                xcoords.push(nextX);
                ycoords.push(nextY);
                xMarkerPlane.push({start:nextX - xMarkerPlaneOffset, end: nextX + xMarkerPlaneOffset});
                yMarkerPlane.push({start:nextY - yMarkerPlaneOffset, end: nextY + yMarkerPlaneOffset});
            }
            this.set("xcoords", xcoords);
    		this.set("ycoords", ycoords);
            this.set("xMarkerPlane", xMarkerPlane);
            this.set("yMarkerPlane", yMarkerPlane);
        },

        /**
         * @protected
         *
         * Draws the series.
         *
         * @method draw
         */
        draw: function()
        {
            var graph = this.get("graph"),
                w = graph.get("width"),
                h = graph.get("height");

            if(this.get("rendered"))
            {
                if((isFinite(w) && isFinite(h) && w > 0 && h > 0) && ((this.get("xData") && this.get("yData")) || this._updateAxisData()))
                {
                    if(this._drawing)
                    {
                        this._callLater = true;
                        return;
                    }
                    this._drawing = true;
                    this._callLater = false;
                    this.setAreaData();
                    if(this.get("xcoords") && this.get("ycoords"))
                    {
                        this.drawSeries();
                    }
                    this._drawing = false;
                    if(this._callLater)
                    {
                        this.draw();
                    }
                    else
                    {
                        this._toggleVisible(this.get("visible"));
                        this.fire("drawingComplete");
                    }
                }
            }
        },

        /**
         * @private
         */
        _defaultPlaneOffset: 4,

        /**
         * @protected
         *
         * Gets the default value for the <code>styles</code> attribute. Overrides
         * base implementation.
         *
         * @method _getDefaultStyles
         * @return Object
         */
        _getDefaultStyles: function()
        {
            return {padding:{
                    top: 0,
                    left: 0,
                    right: 0,
                    bottom: 0
                }};
        },

        /**
         * @protected
         *
         * Collection of default colors used for lines in a series when not specified by user.
         *
         * @property _defaultLineColors
         * @type Array
         */
        _defaultLineColors:["#426ab3", "#d09b2c", "#000000", "#b82837", "#b384b5", "#ff7200", "#779de3", "#cbc8ba", "#7ed7a6", "#007a6c"],

        /**
         * @protected
         *
         * Collection of default colors used for marker fills in a series when not specified by user.
         *
         * @property _defaultFillColors
         * @type Array
         */
        _defaultFillColors:["#6084d0", "#eeb647", "#6c6b5f", "#d6484f", "#ce9ed1", "#ff9f3b", "#93b7ff", "#e0ddd0", "#94ecba", "#309687"],

        /**
         * @protected
         *
         * Collection of default colors used for marker borders in a series when not specified by user.
         *
         * @property _defaultBorderColors
         * @type Array
         */
        _defaultBorderColors:["#205096", "#b38206", "#000000", "#94001e", "#9d6fa0", "#e55b00", "#5e85c9", "#adab9e", "#6ac291", "#006457"],

        /**
         * @protected
         *
         * Collection of default colors used for area fills, histogram fills and pie fills in a series when not specified by user.
         *
         * @property _defaultSliceColors
         * @type Array
         */
        _defaultSliceColors: ["#66007f", "#a86f41", "#295454", "#996ab2", "#e8cdb7", "#90bdbd","#000000","#c3b8ca", "#968373", "#678585"],

        /**
         * @protected
         *
         * Parses a color based on a series order and type.
         *
         * @method _getDefaultColor
         * @param {Number} index Index indicating the series order.
         * @param {String} type Indicates which type of object needs the color.
         * @return String
         */
        _getDefaultColor: function(index, type)
        {
            var colors = {
                    line: this._defaultLineColors,
                    fill: this._defaultFillColors,
                    border: this._defaultBorderColors,
                    slice: this._defaultSliceColors
                },
                col = colors[type],
                l = col.length;
            index = index || 0;
            if(index >= l)
            {
                index = index % l;
            }
            type = type || "fill";
            return colors[type][index];
        },

        /**
         * @protected
         *
         * Shows/hides contents of the series.
         *
         * @method _toggleVisible
         */
        _toggleVisible: function(e)
        {
            var graphic = this.get("graphic"),
                markers = this.get("markers"),
                i = 0,
                len,
                visible = this.get("visible"),
                marker;
            if(graphic)
            {
                graphic.toggleVisible(visible);
            }
            if(markers)
            {
                len = markers.length;
                for(; i < len; ++i)
                {
                    marker = markers[i];
                    if(marker)
                    {
                        marker.toggleVisible(visible);
                    }
                }

            }
            if(this._lineGraphic)
            {
                this._lineGraphic.toggleVisible(visible);
            }
        }
    }, {
        ATTRS: {
            /**
             * Name used for for displaying data related to the x-coordinate.
             *
             * @attribute xDisplayName
             * @type String
             */
            xDisplayName: {
                getter: function()
                {
                    return this._xDisplayName || this.get("xKey");
                },

                setter: function(val)
                {
                    this._xDisplayName = val;
                    return val;
                }
            },

            /**
             * Name used for for displaying data related to the y-coordinate.
             *
             * @attribute yDisplayName
             * @type String
             */
            yDisplayName: {
                getter: function()
                {
                    return this._yDisplayName || this.get("yKey");
                },

                setter: function(val)
                {
                    this._yDisplayName = val;
                    return val;
                }
            },

            /**
             * Name used for for displaying category data
             *
             * @attribute categoryDisplayName
             * @type String
             */
            categoryDisplayName: {
                readOnly: true,

                getter: function()
                {
                    return this.get("direction") == "vertical" ? this.get("yDisplayName") : this.get("xDisplayName");
                }
            },

            /**
             * Name used for for displaying value data
             *
             * @attribute valueDisplayName
             * @type String
             */
            valueDisplayName: {
                readOnly: true,

                getter: function()
                {
                    return this.get("direction") == "vertical" ? this.get("xDisplayName") : this.get("yDisplayName");
                }
            },

            /**
             * Read-only attribute indicating the type of series.
             *
             * @attribute type
             * @type String
             * @default cartesian
             */
            type: {
                value: "cartesian"
            },

            /**
             * Order of this instance of this <code>type</code>.
             *
             * @attribute order
             * @type Number
             */
            order: {},

            /**
             * Order of the instance
             *
             * @attribute graphOrder
             * @type Number
             */
            graphOrder: {},

            /**
             * x coordinates for the series.
             *
             * @attribute xcoords
             * @type Array
             */
            xcoords: {},

            /**
             * y coordinates for the series
             *
             * @attribute ycoords
             * @type Array
             */
            ycoords: {},

            /**
             * Reference to the <code>Graph</code> in which the series is drawn into.
             *
             * @attribute graph
             * @type Graph
             */
            graph: {},

            /**
             * Reference to the <code>Axis</code> instance used for assigning
             * x-values to the graph.
             *
             * @attribute xAxis
             * @type Axis
             */
            xAxis: {},

            /**
             * Reference to the <code>Axis</code> instance used for assigning
             * y-values to the graph.
             *
             * @attribute yAxis
             * @type Axis
             */
            yAxis: {},

            /**
             * Indicates which array to from the hash of value arrays in
             * the x-axis <code>Axis</code> instance.
             *
             * @attribute xKey
             * @type String
             */
            xKey: {},

            /**
             * Indicates which array to from the hash of value arrays in
             * the y-axis <code>Axis</code> instance.
             *
             * @attribute yKey
             * @type String
             */
            yKey: {},

            /**
             * Array of x values for the series.
             *
             * @attribute xData
             * @type Array
             */
            xData: {},

            /**
             * Array of y values for the series.
             *
             * @attribute yData
             * @type Array
             */
            yData: {},

            /**
             * Indicates whether the Series has been through its initial set up.
             *
             * @attribute rendered
             * @type Boolean
             */
            rendered: {
                value: false
            },

            /*
             * Returns the width of the parent graph
             *
             * @attribute width
             * @type Number
             */
            width: {
                readOnly: true,

                getter: function()
                {
                    this.get("graph").get("width");
                }
            },

            /**
             * Returns the height of the parent graph
             *
             * @attribute height
             * @type Number
             */
            height: {
                readOnly: true,

                getter: function()
                {
                    this.get("graph").get("height");
                }
            },

            /**
             * Indicates whether to show the series
             *
             * @attribute visible
             * @type Boolean
             * @default true
             */
            visible: {
                value: true
            },

            /**
             * Collection of area maps along the xAxis. Used to determine mouseover for multiple
             * series.
             *
             * @attribute xMarkerPlane
             * @type Array
             */
            xMarkerPlane: {},

            /**
             * Collection of area maps along the yAxis. Used to determine mouseover for multiple
             * series.
             *
             * @attribute yMarkerPlane
             * @type Array
             */
            yMarkerPlane: {},

            /**
             * Distance from a data coordinate to the left/right for setting a hotspot.
             *
             * @attribute xMarkerPlaneOffset
             * @type Number
             */
            xMarkerPlaneOffset: {
                getter: function() {
                    var marker = this.get("styles").marker;
                    if(marker && marker.width && isFinite(marker.width))
                    {
                        return marker.width * 0.5;
                    }
                    return this._defaultPlaneOffset;
                }
            },

            /**
             * Distance from a data coordinate to the top/bottom for setting a hotspot.
             *
             * @attribute yMarkerPlaneOffset
             * @type Number
             */
            yMarkerPlaneOffset: {
                getter: function() {
                    var marker = this.get("styles").marker;
                    if(marker && marker.height && isFinite(marker.height))
                    {
                        return marker.height * 0.5;
                    }
                    return this._defaultPlaneOffset;
                }
            },

            /**
             * Direction of the series
             *
             * @attribute direction
             * @type String
             */
            direction: {
                value: "horizontal"
            }
        }
    });

Copyright © 2011 Yahoo! Inc. All rights reserved.