#

API Docs for: 3.10.3
Show: Inherited Protected Private Deprecated

# File: charts/js/AxisBase.js

    /**
     * The axis-base submodule contains functionality for the handling of axis data in a chart.
     *
     * @module charts
     * @submodule axis-base
     */
    /**
     * An abstract class that provides the core functionality used by the following classes:
     * <ul>
     *      <li>{{#crossLink "CategoryAxisBase"}}{{/crossLink}}</li>
     *      <li>{{#crossLink "NumericAxisBase"}}{{/crossLink}}</li>
     *      <li>{{#crossLink "StackedAxisBase"}}{{/crossLink}}</li>
     *      <li>{{#crossLink "TimeAxisBase"}}{{/crossLink}}</li>
     *      <li>{{#crossLink "CategoryAxis"}}{{/crossLink}}</li>
     *      <li>{{#crossLink "NumericAxis"}}{{/crossLink}}</li>
     *      <li>{{#crossLink "StackedAxis"}}{{/crossLink}}</li>
     *      <li>{{#crossLink "TimeAxis"}}{{/crossLink}}</li>
     *  </ul>
     *
     * @class AxisBase
     * @constructor
     * @extends Base
     * @uses Renderer
     * @param {Object} config (optional) Configuration parameters.
     * @submodule axis-base
     */
    Y.AxisBase = Y.Base.create("axisBase", Y.Base, [Y.Renderer], {
        /**
         * @method initializer
         * @private
         */
        initializer: function()
        {
            this.after("minimumChange", Y.bind(this._keyChangeHandler, this));
            this.after("maximumChange", Y.bind(this._keyChangeHandler, this));
            this.after("keysChange", this._keyChangeHandler);
            this.after("dataProviderChange", this._dataProviderChangeHandler);
        },

        /**
         * Handles changes to `dataProvider`.
         *
         * @method _dataProviderChangeHandler
         * @param {Object} e Event object.
         * @private
         */
        _dataProviderChangeHandler: function()
        {
            var keyCollection = this.get("keyCollection").concat(),
                keys = this.get("keys"),
                i;
            if(keys)
            {
                for(i in keys)
                {
                    if(keys.hasOwnProperty(i))
                    {
                        delete keys[i];
                    }
                }
            }
            if(keyCollection && keyCollection.length)
            {
                this.set("keys", keyCollection);
            }
        },

        /**
         * Calculates the maximum and minimum values for the `Data`.
         *
         * @method _updateMinAndMax
         * @private
         */
        _updateMinAndMax: function() {
        },

        /**
         * Constant used to generate unique id.
         *
         * @property GUID
         * @type String
         * @private
         */
        GUID: "yuibaseaxis",

        /**
         * Type of data used in `Axis`.
         *
         * @property _type
         * @type String
         * @readOnly
         * @private
         */
        _type: null,

        /**
         * Storage for `setMaximum` attribute.
         *
         * @property _setMaximum
         * @type Object
         * @private
         */
        _setMaximum: null,

        /**
         * Storage for `setMinimum` attribute.
         *
         * @property _setMinimum
         * @type Object
         * @private
         */
        _setMinimum: null,

        /**
         * Reference to data array.
         *
         * @property _data
         * @type Array
         * @private
         */
        _data: null,

        /**
         * Indicates whether the all data is up to date.
         *
         * @property _updateTotalDataFlag
         * @type Boolean
         * @private
         */
        _updateTotalDataFlag: true,

        /**
         * Storage for `dataReady` attribute.
         *
         * @property _dataReady
         * @type Boolean
         * @readOnly
         * @private
         */
        _dataReady: false,

        /**
         * Adds an array to the key hash.
         *
         * @method addKey
         * @param value Indicates what key to use in retrieving
         * the array.
         */
        addKey: function (value)
    	{
            this.set("keys", value);
    	},

        /**
         * Gets an array of values based on a key.
         *
         * @method _getKeyArray
         * @param {String} key Value key associated with the data array.
         * @param {Array} data Array in which the data resides.
         * @return Array
         * @private
         */
        _getKeyArray: function(key, data)
        {
            var i = 0,
                obj,
                keyArray = [],
                len = data.length;
            for(; i < len; ++i)
            {
                obj = data[i];
                keyArray[i] = obj[key];
            }
            return keyArray;
        },

        /**
         * Updates the total data array.
         *
         * @method _updateTotalData
         * @private
         */
        _updateTotalData: function()
        {
    		var keys = this.get("keys"),
                i;
            this._data = [];
            for(i in keys)
            {
                if(keys.hasOwnProperty(i))
                {
                    this._data = this._data.concat(keys[i]);
                }
            }
            this._updateTotalDataFlag = false;
        },

        /**
         * Removes an array from the key hash.
         *
         * @method removeKey
         * @param {String} value Indicates what key to use in removing from
         * the hash.
         */
        removeKey: function(value)
        {
            var keys = this.get("keys");
            if(keys.hasOwnProperty(value))
            {
                delete keys[value];
                this._keyChangeHandler();
            }
        },

        /**
         * Returns a value based of a key value and an index.
         *
         * @method getKeyValueAt
         * @param {String} key value used to look up the correct array
         * @param {Number} index within the array
         * @return Number
         */
        getKeyValueAt: function(key, index)
        {
            var value = NaN,
                keys = this.get("keys");
            if(keys[key] && Y_Lang.isNumber(parseFloat(keys[key][index])))
            {
                value = keys[key][index];
            }
            return parseFloat(value);
        },

        /**
         * Returns values based on key identifiers. When a string is passed as an argument, an array of values is returned.
         * When an array of keys is passed as an argument, an object literal with an array of values mapped to each key is
         * returned.
         *
         * @method getDataByKey
         * @param {String|Array} value value used to identify the array
         * @return Array|Object
         */
        getDataByKey: function (value)
        {
            var obj,
                i,
                len,
                key,
                keys = this.get("keys");
            if(Y_Lang.isArray(value))
            {
                obj = {};
                len = value.length;
                for(i = 0; i < len; i = i + 1)
                {
                    key = value[i];
                    if(keys[key])
                    {
                        obj[key] = this.getDataByKey(key);
                    }
                }
            }
            else if(keys[value])
            {
                obj = keys[value];
            }
            else
            {
                obj = null;
            }
            return obj;
        },

        /**
         * Returns the total number of majorUnits that will appear on an axis.
         *
         * @method getTotalMajorUnits
         * @return Number
         */
        getTotalMajorUnits: function()
        {
            var units,
                majorUnit = this.get("styles").majorUnit;
            units = majorUnit.count;
            return units;
        },

        /**
         * Gets the distance that the first and last ticks are offset from there respective
         * edges.
         *
         * @method getEdgeOffset
         * @param {Number} ct Number of ticks on the axis.
         * @param {Number} l Length (in pixels) of the axis.
         * @return Number
         */
        getEdgeOffset: function(ct, l)
        {
            var edgeOffset;
            if(this.get("calculateEdgeOffset")) {
                edgeOffset = (l/ct)/2;
            } else {
                edgeOffset = 0;
            }
            return edgeOffset;
        },

        /**
         * Updates the `Axis` after a change in keys.
         *
         * @method _keyChangeHandler
         * @param {Object} e Event object.
         * @private
         */
        _keyChangeHandler: function()
        {
            this._updateMinAndMax();
            this._updateTotalDataFlag = true;
            this.fire("dataUpdate");
        },

        /**
         * Gets the default value for the `styles` attribute. Overrides
         * base implementation.
         *
         * @method _getDefaultStyles
         * @return Object
         * @protected
         */
        _getDefaultStyles: function()
        {
            var axisstyles = {
                majorUnit: {
                    determinant:"count",
                    count:11,
                    distance:75
                }
            };
            return axisstyles;
        },

        /**
         * Getter method for maximum attribute.
         *
         * @method _maximumGetter
         * @return Number
         * @private
         */
        _maximumGetter: function ()
        {
            var max = this.get("dataMaximum"),
                min = this.get("minimum");
            //If all values are zero, force a range so that the Axis and related series
            //will still render.
            if(min === 0 && max === 0)
            {
                max = 10;
            }
            if(Y_Lang.isNumber(this._setMaximum))
            {
                max = this._setMaximum;
            }
            return parseFloat(max);
        },

        /**
         * Setter method for maximum attribute.
         *
         * @method _maximumSetter
         * @param {Object} value
         * @private
         */
        _maximumSetter: function (value)
        {
            this._setMaximum = parseFloat(value);
            return value;
        },

        /**
         * Getter method for minimum attribute.
         *
         * @method _minimumGetter
         * @return Number
         * @private
         */
        _minimumGetter: function ()
        {
            var min = this.get("dataMinimum");
            if(Y_Lang.isNumber(this._setMinimum))
            {
                min = this._setMinimum;
            }
            return parseFloat(min);
        },

        /**
         * Setter method for minimum attribute.
         *
         * @method _minimumSetter
         * @param {Object} value
         * @private
         */
        _minimumSetter: function(val)
        {
            this._setMinimum = parseFloat(val);
            return val;
        },

        /**
         * Indicates whether or not the maximum attribute has been explicitly set.
         *
         * @method _getSetMax
         * @return Boolean
         * @private
         */
        _getSetMax: function()
        {
            return Y_Lang.isNumber(this._setMaximum);
        },

        /**
         * Indicates whether or not the minimum attribute has been explicitly set.
         *
         * @method _getSetMin
         * @return Boolean
         * @private
         */
        _getSetMin: function()
        {
            return Y_Lang.isNumber(this._setMinimum);
        }
    }, {
        ATTRS: {
            /**
             * Determines whether and offset is automatically calculated for the edges of the axis.
             *
             * @attribute calculateEdgeOffset
             * @type Boolean
             */
            calculateEdgeOffset: {
                value: false
            },

            labelFunction: {
                valueFn: function() {
                    return this.formatLabel;
                }
            },

            /**
             * Hash of array identifed by a string value.
             *
             * @attribute keys
             * @type Object
             */
            keys: {
                value: {},

                setter: function(val)
                {
                    var keys = {},
                        i,
                        len,
                        data = this.get("dataProvider");
                    if(Y_Lang.isArray(val))
                    {
                        len = val.length;
                        for(i = 0; i < len; ++i)
                        {
                            keys[val[i]] = this._getKeyArray(val[i], data);
                        }

                    }
                    else if(Y_Lang.isString(val))
                    {
                        keys = this.get("keys");
                        keys[val] = this._getKeyArray(val, data);
                    }
                    else
                    {
                        for(i in val)
                        {
                            if(val.hasOwnProperty(i))
                            {
                                keys[i] = this._getKeyArray(i, data);
                            }
                        }
                    }
                    this._updateTotalDataFlag = true;
                    return keys;
                }
            },

            /**
             *Returns the type of axis data
             *  <dl>
             *      <dt>time</dt><dd>Manages time data</dd>
             *      <dt>stacked</dt><dd>Manages stacked numeric data</dd>
             *      <dt>numeric</dt><dd>Manages numeric data</dd>
             *      <dt>category</dt><dd>Manages categorical data</dd>
             *  </dl>
             *
             * @attribute type
             * @type String
             */
            type:
            {
                readOnly: true,

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

            /**
             * Instance of `ChartDataProvider` that the class uses
             * to build its own data.
             *
             * @attribute dataProvider
             * @type Array
             */
            dataProvider:{
                setter: function (value)
                {
                    return value;
                }
            },

            /**
             * The maximum value contained in the `data` array. Used for
             * `maximum` when `autoMax` is true.
             *
             * @attribute dataMaximum
             * @type Number
             */
            dataMaximum: {
                getter: function ()
                {
                    if(!Y_Lang.isNumber(this._dataMaximum))
                    {
                        this._updateMinAndMax();
                    }
                    return this._dataMaximum;
                }
            },

            /**
             * The maximum value that will appear on an axis.
             *
             * @attribute maximum
             * @type Number
             */
            maximum: {
                lazyAdd: false,

                getter: "_maximumGetter",

                setter: "_maximumSetter"
            },

            /**
             * The minimum value contained in the `data` array. Used for
             * `minimum` when `autoMin` is true.
             *
             * @attribute dataMinimum
             * @type Number
             */
            dataMinimum: {
                getter: function ()
                {
                    if(!Y_Lang.isNumber(this._dataMinimum))
                    {
                        this._updateMinAndMax();
                    }
                    return this._dataMinimum;
                }
            },

            /**
             * The minimum value that will appear on an axis.
             *
             * @attribute minimum
             * @type Number
             */
            minimum: {
                lazyAdd: false,

                getter: "_minimumGetter",

                setter: "_minimumSetter"
            },

            /**
             * Determines whether the maximum is calculated or explicitly
             * set by the user.
             *
             * @attribute setMax
             * @type Boolean
             */
            setMax: {
                readOnly: true,

                getter: "_getSetMax"
            },

            /**
             * Determines whether the minimum is calculated or explicitly
             * set by the user.
             *
             * @attribute setMin
             * @type Boolean
             */
            setMin: {
                readOnly: true,

                getter: "_getSetMin"
            },

            /**
             * Array of axis data
             *
             * @attribute data
             * @type Array
             */
            data: {
                getter: function ()
                {
                    if(!this._data || this._updateTotalDataFlag)
                    {
                        this._updateTotalData();
                    }
                    return this._data;
                }
            },

            /**
             * Array containing all the keys in the axis.

             * @attribute keyCollection
             * @type Array
             */
            keyCollection: {
                getter: function()
                {
                    var keys = this.get("keys"),
                        i,
                        col = [];
                    for(i in keys)
                    {
                        if(keys.hasOwnProperty(i))
                        {
                            col.push(i);
                        }
                    }
                    return col;
                },
                readOnly: true
            },

            /**
             * Object which should have by the labelFunction
             *
             * @attribute labelFunctionScope
             * @type Object
             */
            labelFunctionScope: {}
        }
    });