
(function (factory) {
    if (typeof module === 'object' && typeof module.exports !== "undefined") {
        module.exports = factory;
    } else {
        factory(FusionCharts);
    }
}(function (FusionCharts) {

/**
 * @private
 * @module fusioncharts.renderer.javascript.legend-gradient
 */

FusionCharts.register('module', ['private', 'modules.renderer.js-gradientlegend', function() {
    var global = this,
        lib = global.hcLib,
        pluckNumber = lib.pluckNumber,
        pluck = lib.pluck,
        toRaphaelColor = lib.toRaphaelColor,
        graphics = lib.graphics,
        dehashify = lib.dehashify,
        hashify = lib.hashify,
        convertColor = graphics.convertColor,
        RGBtoHex = graphics.RGBtoHex,
        HEXtoRGB = graphics.HEXtoRGB,
        getLightColor = graphics.getLightColor,
        getValidColor = graphics.getValidColor,
        compositionKeys = {},
        isIE = lib.isIE,
        TRACKER_FILL = 'rgba(192,192,192,' + (isIE ? 0.002 : 0.000001) + ')',
        legendManager,
        DEF_COLOR = lib.COLOR_BLACK,
        FORMER_SLIDER_INDEX = false,
        LATER_SLIDER_INDEX = true,
        PERCENT_STR = '%',
        COMMA_STR = ',',
        hasOwnProp = ({}).hasOwnProperty,
        M = 'M',
        L = 'L',
        animType = 'easeIn',
        componentPoolFactory,
        universalPool = {};

    // Utility functions

    /*
     * Recursively merges two objects.
     * Source is object from where the properties will be copied and sink is destination object where the props are to
     * be copied. If the property is already present in sink, it wont copy the property.
     *
     * Example:                         After merging the sink will be changed and returned
     * src = {      | sink = {      |   sink = {
     *  a: 1,       |   b: 33,      |       a: 1,
     *  b: 2,       |   c: 44,      |       b: 33,
     *  obj1: {     |   obj2: {     |       c: 44,
     *      m: 1,   |       w: 11,  |       obj1: {
     *      n: 2    |       x: 22   |           m: 1,
     *  },          | }             |           n: 2
     *  obj2: {     |               |       },
     *      x: 1,   |               |       obj2: {
     *      y: 2,   |               |           w: 11,
     *      z: 3    |               |           x: 22,
     *  }           |               |           y: 2,
     * }            |               |           z: 3
     *              |               |       }
     *              |               |   }
     *
     * @param: source {Object} - The object from where the props are to be copied
     * @param: sink {Object} - The object where the props are to be merged
     * @return {Object} - The reference to the sink object which was passed
     */
    function merge (source, sink) {
        (function rec (source, sink) {
            var sourceVal,
                prop;

            for (prop in source) {
                // Iterates for every property in souce
                if (!hasOwnProp.call(source, prop)) {
                    // Igoners if the property does not belong to the object directly, it might resides on the prototype
                    // chain
                    continue;
                }

                sourceVal = source[prop];
                if (sink[prop] === undefined) {
                    // Assigns the value / ref if the value of the same property is undefined (it's not checked whether
                    // the key is directly or indirectly present on the object) in the sink.
                    sink[prop] = sourceVal;
                } else if (typeof sourceVal === 'object' && typeof sourceVal !== null) {
                    // If the value is another object recursively perform the merging.

                    // @todo check if the value is function, array etc. If it happens this will execute unpredictively,
                    // Its not implmented because it would more condition.
                    rec(sourceVal, sink[prop]);
                }
            }
        })(source, sink);

        return sink;
    }

    /*
     * Takes care of sanity checking of the color to some extent.
     * If no color is passed, ie called as getValidHexColor() it returns the default color. If incorrect color is passed
     * it returns false.
     *
     * @param code {String} - color code in string
     * @return {String | Boolean} - false if invalid color is passed, otherwise the same color or default color if no
     *                              no color is passed
     */
    function getValidHexColor (code) {
        var color = code ? code : DEF_COLOR;

        return getValidColor(color) || DEF_COLOR;
    }

    /*
     * Returns the opposite LIGHT color of a color. If the color is alraedy light, wont get much difference.
     *
     * @param code {String} - color code in string
     * @return {String} - Lightest (approx) color code of the color sent
     */
    function getOppositeColor (code) {
        return getLightColor(code, 1);
    }

    function getColorBetween(range1, range2, value) {
        /*jshint newcap: false */
        var value1 = range1.value,
            code1 = range1.code,
            rgb1 = HEXtoRGB(code1),
            value2 = range2.value,
            code2 = range2.code,
            rgb2 = HEXtoRGB(code2),
            diff,
            rgb;

        diff = value2 - value1;

        rgb = [
            Math.round(rgb1[0] + (((rgb2[0] - rgb1[0]) / diff) * (value - value1))),
            Math.round(rgb1[1] + (((rgb2[1] - rgb1[1]) / diff) * (value - value1))),
            Math.round(rgb1[2] + (((rgb2[2] - rgb1[2]) / diff) * (value - value1)))
        ];

        return RGBtoHex(rgb);
        /*jshint newcap: true */
    }

    function normalizeFontSizeAppend(obj) {
        var fontSize = obj.fontSize + '',
            normalizeFontSize;

        if (!fontSize) { return obj; }

        normalizeFontSize = fontSize.replace(/(\d+)(px)*/, '$1px');
        obj.fontSize = normalizeFontSize;

        return obj;
    }

    function isInvalid(arg){
        if (arg === undefined || typeof arg === 'undefined' || arg === null) {
            return true;
        } else if (arg !== arg) {
            return true;
        }

        return false;
    }

    compositionKeys.CAPTION = 'CAPTION';
    compositionKeys.LEGEND_BODY = 'LEGEND_BODY';
    compositionKeys.AXIS_LABEL = 'LEGEND_LABEL';
    compositionKeys.LEGEND_AXIS = 'LEGEND_AXIS';
    compositionKeys.RANGE = 'RANGE';
    compositionKeys.AXIS_VALUE = 'AXIS_VALUE';

    legendManager = (function () {
        var layers,
            components,
            chart,
            defaultConf = {},
            config;

        defaultConf.legendCarpetConf = {
            spreadFactor : 0.85,
            allowDrag: false,
            captionAlignment: 'center',
            padding: {
                v: 3,
                h: 3
            },
            style : {
                'fill' : '#e4d9c1',
                'stroke' : '#c4b89d'
            }
        };

        defaultConf.legendCaptionConf = {
            spreadFactor: 0.2,
            padding: {
                v: 2,
                h: 2
            },
            style : {
                fill: '#786B50',
                fontFamily: 'sans-serif',
                fontSize: '12px',
                fontWeight: 'bold',
                fontStyle: 'normal'
            },
            bound: {
                style: {
                    stroke: 'none'
                }
            }
        };

        defaultConf.legendBodyConf = {
            spreadFactor: 0.8,
            padding: {
                v: 2,
                h: 2
            },
            bound: {
                style: {
                    stroke: 'none'
                }
            }
        };

        defaultConf.legendAxisConf = {
            legendAxisHeight: 11,
            spreadFactor: 0.4,
            padding: {
                v: 1,
                h: 1
            },
            style : {
                stroke: 'none',
                'stroke-opacity': 0,
                'stroke-width': 1
            },
            line: {
                grooveLength: 3,
                offset: 8,
                style: {
                    stroke: 'rgba(255, 255, 255, 0.65)',
                    'stroke-width': 1.5
                }
            },
            shadow : {
                style : {
                    stroke : 'none',
                    fill : toRaphaelColor({
                        FCcolor: {
                            alpha : '25,0,0',
                            angle : 360,
                            color : '000000,FFFFFF,FFFFFF',
                            ratio : '0,30,40'
                        }
                    })
                }
            },
            bound: {
                style: {
                    stroke: 'none'
                }
            }
        };

        defaultConf.sliderGroupConf = {
            showTooltip: 1,
            outerCircle : {
                rFactor: 1.4,
                style: {
                    fill: TRACKER_FILL,
                    stroke: '#757575',
                    'stroke-width': 3
                }
            },
            innerCircle : {
                rFactor: 0.65,
                style: {
                    fill: TRACKER_FILL,
                    stroke: '#FFFFFF'
                }
            }
        };

        defaultConf.axisTextItemConf = {
            spreadFactor: 0.3,
            padding: {
                v: 1,
                h: 1
            },
            style : {
                fill: '#786B50',
                fontFamily: 'sans-serif',
                fontSize: '12px',
                fontWeight: 'normal',
                fontStyle: 'normal'
            }
        };

        function normalizePreprocessedData (confArr) {
            var numberFormatter = components.numberFormatter,
                index,
                length,
                rawVal;

            for (index = 0, length = confArr.length; index < length; index++) {
                rawVal = confArr[index].maxvalue;

                if (!rawVal) {
                    continue;
                }

                confArr[index].maxvalue = numberFormatter.getCleanValue(rawVal);
            }
        }

        return {
            init : function (options) {
                chart = options.chart;
                layers = chart.graphics;
                components = chart.components;
            },

            setConf : function (conf) {
                config = conf;
            },

            legacyDataParser : function (data, extremes) {
                var colormanagerConf = {},
                    numberFormatter = components.numberFormatter,
                    colorConfArr,
                    colorConf,
                    startColor,
                    endColor,
                    index,
                    validColor,
                    length,
                    colorRange,
                    value,
                    dispValue,
                    mapByPercent,
                    isMaxValPresent,
                    obj;

                if (!data) {
                    return false;
                }

                colormanagerConf.mapByPercent = mapByPercent = !!(pluckNumber(data.mapbypercent, 0));
                colorConfArr = data.color || [];

                if (data.minvalue === undefined) {
                    data.minvalue = extremes.min !== undefined ? (mapByPercent ? 0 : extremes.min) : 0;
                }

                if (data.maxvalue === undefined) {
                    data.maxvalue = extremes.max !== undefined ? (mapByPercent ? 100 : extremes.max) : 100;
                }

                isMaxValPresent = false;
                for (index = 0, length = colorConfArr.length; index < length; index++) {
                    if (colorConfArr[index].maxvalue) {
                        isMaxValPresent = true;
                        break;
                    }
                }

                if (!isMaxValPresent) {
                    colorConfArr = [];
                }

                startColor = data.code;

                colorRange = colormanagerConf.colorRange = [];
                colormanagerConf.gradient = !!pluckNumber(data.gradient, 1);

                // If no additional color array is provided as part of generating the gradient, creates the start and
                // end value to create the gradient
                if (!colorConfArr.length) {
                    if (startColor) {
                        // If start color is mentioned, create a gradient starting from default color to the mentioned
                        // color
                        endColor = getValidHexColor(startColor);
                        startColor = getValidHexColor();
                    } else {
                        // If no color is mentioned, create a gradient of two opposite color
                        startColor = getValidHexColor();
                        endColor = getOppositeColor(startColor);
                    }

                    colorConfArr.push({
                        code: endColor,
                        maxvalue: data.maxvalue,
                        label: undefined
                    });

                } else {
                    startColor = getValidHexColor(startColor);
                }

                normalizePreprocessedData(colorConfArr);

                colorConfArr = colorConfArr.sort(function (m, n) {
                    return m.maxvalue - n.maxvalue;
                });

                value = dispValue = data.minvalue && numberFormatter.getCleanValue(data.minvalue);
                dispValue = (value !== undefined || value !== null) && (mapByPercent ? value + PERCENT_STR :
                    numberFormatter.legendValue(value));
                colorRange.push({
                    code: dehashify(startColor),
                    value: value,
                    displayValue: dispValue,
                    label: data.startlabel
                });

                for (index = 0, length = colorConfArr.length; index < length; index++) {
                    colorConf = colorConfArr[index];
                    validColor = getValidHexColor(colorConf.code || colorConf.color);

                    value = dispValue = colorConf.maxvalue;

                    if(isNaN(parseInt(value, 10))) { continue; }

                    dispValue = (value !== undefined || value !== null) && (mapByPercent ? value + PERCENT_STR :
                        numberFormatter.legendValue(value));

                    colorRange.push(obj = new Object({
                        code: dehashify(validColor),
                        value: value,
                        displayValue: dispValue,
                        label: colorConf.label || colorConf.displayvalue
                    }));
                }

                colorRange[colorRange.length - 1].label = data.endlabel || colorConf.label;

                return colormanagerConf;

            },

            getDefaultConf: function (key) {
                return defaultConf[key];
            }
        };
    })();

    componentPoolFactory = function (chart) {
        var chartId = chart.chartInstance.id,
            pool = universalPool[chartId] || (universalPool[chartId] = {});


        return (function () {
            var elemTypes,
                actions = {},
                paper;

            elemTypes = {
                KEY_RECT : 'rect',
                KEY_TEXT : 'text',
                KEY_GROUP: 'group',
                KEY_CIRCLE: 'circle',
                KEY_PATH: 'path'
            };

            actions[elemTypes.KEY_RECT] = function (group) {
                return paper.rect(group);
            };

            actions[elemTypes.KEY_TEXT] = function (attr, group) {
                return paper.text(attr, group);
            };

            actions[elemTypes.KEY_GROUP] = function (groupName, parentGroup) {
                return paper.group(groupName, parentGroup);
            };

            actions[elemTypes.KEY_CIRCLE] = function (group) {
                return paper.circle(group);
            };

            actions[elemTypes.KEY_PATH] = function (pathStr, group) {
                return paper.path(pathStr, group);
            };

            function _hideRecursive () {
                var keyLevel1,
                    keyLevel2,
                    objLevel1,
                    val,
                    index, length;

                for (keyLevel1 in pool) {
                    objLevel1 = pool[keyLevel1];

                    for (keyLevel2 in objLevel1) {
                        val = objLevel1[keyLevel2];

                        if (val instanceof Array) {
                            for (index = 0, length = val.length; index < length; index++) {
                                val[index] && val[index].hide();
                            }
                        } else {
                            val.hide();
                        }
                    }
                }
            }

            return {
                init: function (renderer) {
                    paper = renderer;

                    _hideRecursive();
                },

                emptyPool: function () {
                    pool = universalPool[chartId] = {};
                },

                getChart: function () {
                    return chart;
                },

                getComponent: function (id, elemType, storeTillReCall) {
                    var idSpecificPool = pool[id],
                        multiInstance,
                        instance,
                        inst,
                        instanceRetrieved = 0;


                    if (!idSpecificPool) {
                        idSpecificPool = pool[id] = {};
                    }

                    instance = idSpecificPool[elemType];

                    if ((instance && !(instance instanceof Array)) ||
                        (instance instanceof Array && instance.length > 0)) {
                        return function () {
                            if (storeTillReCall) {
                                inst = instance[instanceRetrieved++];
                                if (inst) {
                                    return inst.show();
                                } else {
                                    return instance[instanceRetrieved] = actions[elemType].apply(this, arguments);
                                }
                            }

                            return instance.show();
                        };
                    }

                    return function () {
                        if (storeTillReCall) {
                            multiInstance = idSpecificPool[elemType] || (idSpecificPool[elemType] = []);
                            instance = actions[elemType].apply(this, arguments);
                            multiInstance.push(instance);

                            return instance.show();
                        }

                        return idSpecificPool[elemType] = actions[elemType].apply(this, arguments);
                    };

                },

                hideAll: function () {
                    _hideRecursive();
                },

                getKeys: function () {
                    return elemTypes;
                }
            };
        })();
    };

    function LegendBase (carpet, componentPool) {
        this.carpet = carpet;
        this._componentPool = componentPool;
    }

    LegendBase.prototype.constructor = LegendBase;

    LegendBase.prototype.draw = function (options) {
        options.componentPool = this._componentPool;
        return this.carpet.draw(options);
    };

    LegendBase.prototype.getLogicalSpace = function (options, recalculate) {
        options.componentPool = this._componentPool;
        return this.carpet.getLogicalSpace(options, recalculate);
    };

    LegendBase.prototype.dispose = function () {
        this.carpet && this.carpet.group && this.carpet.group.remove();
        this._componentPool.emptyPool();
    };

    function LegendCarpet (conf) {
        this.conf = conf;
        this._id = 'GL_CARPET';

        // Save the components which are the building block of the whole legend. Like: The background rect,
        // text, slider, color axis etc.
        this.compositionsByCategory = {};
        this.node = undefined;
        this.group = undefined;
        this._lSpace = undefined;
        this.autoRecalculate = false;
        this.groupName = 'fc-gradient-legend';
        this.moveInstructions = {};
    }

    LegendCarpet.prototype.constructor = LegendCarpet;

    LegendCarpet.prototype.addCompositions = function (instance, category) {
        this.compositionsByCategory[category] = instance;
    };

    LegendCarpet.prototype.getBoundingBox = function (options) {
        var conf = this.conf,
            spreadFactor = conf.spreadFactor,
            refSide = options.refSide,
            alignment = options.alignment,
            refOffset = options.refOffset,
            x = options.x,
            y = options.y,
            lWidth;


        lWidth = conf.width = refSide * spreadFactor;

        if (alignment && (x === undefined || x === null)) {
            x = ((refOffset + refSide) / 2) - lWidth / 2;
        }

        return {
            width: lWidth,
            height: options.maxOtherSide,
            x: x,
            y: y
        };
    };

    LegendCarpet.prototype.getPostCalcDecisions = function (bBox, componentsArea) {
        var conf = this.conf,
            padding = conf.padding,
            cat,
            totalHeightTaken = 0;

        for (cat in componentsArea) {
            totalHeightTaken += componentsArea[cat].height || 0;
        }

        bBox.height = totalHeightTaken + 2 * padding.v;
    };

    LegendCarpet.prototype.getLogicalSpace = function (options, recalculate) {
        var lSpace = this._lSpace,
            conf = this.conf,
            padding = conf.padding,
            compositionsByCategory = this.compositionsByCategory,
            composition,
            bBox,
            effectivePlotArea,
            compositionLSPace,
            compositionHeight = 0,
            componentsArea = { },
            category,
            compositionPlotArea,
            autoRecalculate,
            heightNotUsed = 0;

        if (lSpace && !recalculate) {
            lSpace.isImpure = true;
            // If logical space has already been calculated and recalculate flag is on, return without recalculating.
            return lSpace;
        } else {
            autoRecalculate = false;
        }

        lSpace = this._lSpace = bBox = this.getBoundingBox(options);

        if (isInvalid(lSpace.x) || isInvalid(lSpace.y) || isInvalid(lSpace.height) || isInvalid(lSpace.width)) {
            this.autoRecalculate = true;
        }

        // Copy the props
        effectivePlotArea = merge(bBox, {});

        // The logical rect inside which the composition are drawn
        effectivePlotArea.height -= 2 * padding.v;
        effectivePlotArea.width -= 2 * padding.h;
        effectivePlotArea.x += padding.h;
        effectivePlotArea.y += padding.v;

        for (category in compositionsByCategory) {
            composition = compositionsByCategory[category];

            compositionPlotArea = merge(effectivePlotArea, {});
            compositionPlotArea.y += compositionHeight;
            compositionHeight = effectivePlotArea.height * composition.conf.spreadFactor;
            compositionPlotArea.height = compositionHeight + heightNotUsed;

            compositionLSPace = composition.getLogicalSpace(merge(compositionPlotArea, {}), options, recalculate);

            heightNotUsed = compositionPlotArea.height - compositionLSPace.height;

            componentsArea[category] = compositionLSPace;

            compositionHeight = compositionLSPace.height;
        }

        this.getPostCalcDecisions(bBox, componentsArea);

        this._lSpace = bBox;
        return bBox;
    };

    LegendCarpet.prototype.setupDragging = function () {
        var group = this. group,
            dx = 0,
            dy = 0,
            idx = 0,
            idy = 0;

        group.css({cursor: 'move'});
        group.drag(function (_dx, _dy) {
            dx = _dx;
            dy = _dy;
            group.attr({
                transform: 't' + (idx + dx) + ',' + (idy + dy)
            });
        }, function () {
            idx += dx;
            idy += dy;
        }, function () { });
    };

    LegendCarpet.prototype.draw = function (options) {
        var conf = this.conf,
            compositionsByCategory = this.compositionsByCategory,
            paper = options.paper,
            parentGroup = options.parentGroup,
            componentPool = options.componentPool,
            chart = componentPool.getChart(),
            group,
            node,
            category,
            composition,
            lSpace,
            compositionRes,
            animDuration = chart.get('config', 'animationObj').duration,
            instanceFn,
            keys = componentPool.getKeys();

        this.getLogicalSpace(options, this.autoRecalculate);
        lSpace = this._lSpace;

        instanceFn = componentPool.getComponent(this._id, keys.KEY_GROUP);
        this.group = group = instanceFn(this.groupName, parentGroup);

        group.attr({
            opacity: 0
        });

        group.animate({
            opacity: 1
        }, animDuration, animType);

        // The main rect outside all the composition
        instanceFn = componentPool.getComponent(this._id, keys.KEY_RECT);
        this.node = node = instanceFn(group).attr(lSpace).css(conf.style);

        for (category in compositionsByCategory) {
            composition = compositionsByCategory[category];

            compositionRes = composition.draw(conf.captionAlignment, lSpace, {
                colorRange: options.colorRange,
                numberFormatter: options.numberFormatter,
                paper: paper,
                parentLayer: group,
                smartLabel: options.smartLabel,
                moveInstructions : this.moveInstructions[category],
                componentPool: options.componentPool
            });
        }

        conf.allowDrag && this.setupDragging();
        return this.node;
    };


    function VerticalLegendCarpet () {
        LegendCarpet.apply(this, arguments);
    }

    VerticalLegendCarpet.prototype = Object.create(LegendCarpet.prototype);
    VerticalLegendCarpet.prototype.constructor = VerticalLegendCarpet;

    VerticalLegendCarpet.prototype.getBoundingBox = function (options) {
        var conf = this.conf,
            spreadFactor = conf.spreadFactor,
            refSide = options.refSide,
            alignment = options.alignment,
            refOffset = options.refOffset,
            x = options.x,
            y = options.y,
            lHeight;


        lHeight = conf.height = refSide * spreadFactor;

        if (alignment && (y === undefined || y === null)) {
            y = ((refOffset + refSide) / 2) - lHeight / 2;
        }

        return {
            width: options.maxOtherSide,
            height: lHeight,
            x: x,
            y: y
        };
    };

    VerticalLegendCarpet.prototype.getPostCalcDecisions = function (bBox, componentsArea) {
        var conf = this.conf,
            padding = conf.padding,
            maxWidth = Number.NEGATIVE_INFINITY,
            width,
            cat,
            move = this.moveInstructions,
            diff;

        LegendCarpet.prototype.getPostCalcDecisions.apply(this, arguments);

        for (cat in componentsArea) {
            width = componentsArea[cat].width;
            maxWidth = maxWidth < width ? width : maxWidth;
        }

        bBox.width = maxWidth + 2 * padding.h;

        for (cat in componentsArea) {
            width = componentsArea[cat].width;
            if (diff = maxWidth - width) {
                move[cat] = 't' + diff / 2 + ',0';
            }
        }
    };

    function LegendCaption (text, conf) {
        this.rawText = text;
        this.conf = conf;
        this._id = 'GL_CAPTION';

        this.node = undefined;
        this.bound = undefined;
        this._lSpace = undefined;
    }

    LegendCaption.prototype.constructor = LegendCaption;

    LegendCaption.LEFT = {
        x: function (smartText, boundingBox) {
            return boundingBox.x + smartText.width / 2 + 2;
        }
    };

    LegendCaption.RIGHT = {
        x: function (smartText, boundingBox) {
            return boundingBox.x + boundingBox.width - smartText.width / 2 - 2;
        }
    };

    LegendCaption.CENTER = {
        x: function (smartText, boundingBox) {
            return boundingBox.x + (boundingBox.width / 2);
        }
    };

    LegendCaption.prototype.getLogicalSpace = function (bBox, options, recalculate) {
        var conf = this.conf,
            padding = conf.padding,
            lSpace = this._lSpace,
            text = this.rawText,
            componentPool = options.componentPool,
            chart = componentPool.getChart(),
            smartLabel,
            effectivePlotArea,
            smartText,
            copyOfStyle;

        if (lSpace && !recalculate) {
            lSpace.isImpure = true;
            // If logical space has already been calculated and recalculate flag is on, return without recalculating.
            return lSpace;
        }

        lSpace = this._lSpace = {
            bound: {
                height: 0,
                width: 0
            },

            node: {
                logicArea: undefined,
                smartText: undefined
            }
        };

        smartLabel = options.smartLabel;

        if (!text) {
            return lSpace.bound;
        }

        effectivePlotArea = merge(bBox, {});

        // The logical rect inside which the composition are drawn
        effectivePlotArea.height -= 2 * padding.v;
        effectivePlotArea.width -= 2 * padding.h;
        effectivePlotArea.x += padding.h;
        effectivePlotArea.y += padding.v;

        smartLabel.useEllipsesOnOverflow(chart.config.useEllipsesWhenOverflow);
        copyOfStyle = merge(this.conf.style, {});
        normalizeFontSizeAppend(copyOfStyle);

        smartLabel.setStyle(this._metaStyle = copyOfStyle);
        smartText = smartLabel.getSmartText(text, effectivePlotArea.width, effectivePlotArea.height);

        effectivePlotArea.height = smartText.height;
        effectivePlotArea.width = smartText.width;

        bBox.height = smartText.height + 2 * padding.v;
        bBox.width = smartText.width + 2 * padding.h;

        lSpace.node.smartText = smartText;
        lSpace.node.logicArea = effectivePlotArea;
        lSpace.bound = bBox;

        return bBox;
    };

    LegendCaption.prototype.draw = function () {
        var conf = this.conf,
            smartLabel,
            paper,
            layer,
            boundAttr = conf.bound || {},
            group,
            bound,
            instanceFn,
            boundingArea,
            lSpace,
            normalizedX,
            x,
            bBox,
            options,
            node,
            componentPool,
            keys;

        if (arguments.length >= 3) {
            x = arguments[0];
            bBox = arguments[1];
            options = arguments[2];
        } else if (arguments.length >= 2){
            x = arguments[0];
            options = arguments[1];
        }

        smartLabel = options.smartLabel;
        paper = options.paper;
        layer = options.parentLayer;
        componentPool = options.componentPool;
        keys = componentPool.getKeys();

        // Separate group for caption and the bounding rect
        instanceFn = componentPool.getComponent(this._id, keys.KEY_GROUP);
        this.group = group = instanceFn('legend-caption', layer).css(conf.style);

        //group = paper.group('legend-caption', layer);

        this.getLogicalSpace(bBox, options);
        lSpace = this._lSpace;

        node = lSpace.node;
        boundingArea = lSpace.bound;

        // Bounding rect
        instanceFn = componentPool.getComponent(this._id, keys.KEY_RECT);
        this.bound = bound = instanceFn(group).attr(boundingArea).css(boundAttr.style);
        //bound = this.bound = paper.rect(boundingArea, group).css(boundAttr.style);

        normalizedX = typeof x === 'string' ? LegendCaption[x.toUpperCase()].x(node.smartText, bBox || node.logicArea)
            : x;

        instanceFn = componentPool.getComponent(this._id, keys.KEY_TEXT);
        this.node = instanceFn({ }, group).attr({
                text: node.smartText.text,
                x: normalizedX,
                y: node.logicArea.y + (node.smartText.height / 2),
                lineHeight: this._metaStyle.lineHeight,
                fill: conf.style.fill
            });

        return {
            group: group,
            bound: bound,
            node: this.node
        };
    };



    function LegendBody (colorRange, conf, childTextConf) {
        this.colorRange = colorRange;
        this.conf = conf;
        this.childTextConf = childTextConf;
        this._id = 'GL_BODY';

        this.bound = undefined;
        this.compositionsByCategory = {};
        this._lSpace = undefined;
    }

    // Space calculation order
    LegendBody.SC_STACK = [
        compositionKeys.AXIS_LABEL,
        compositionKeys.LEGEND_AXIS,
        compositionKeys.AXIS_VALUE
    ];

    LegendBody.DARW_STACK = [
        compositionKeys.AXIS_VALUE,
        compositionKeys.LEGEND_AXIS,
        compositionKeys.AXIS_LABEL
    ];

    LegendBody.prototype.constructor = LegendBody;

    LegendBody.prototype.addCompositions = function (instance, category) {
        this.compositionsByCategory[category] = instance;
    };

    LegendBody.prototype.getCompositionPlotAreaFor = function (effectivePlotArea) {
        var plotArea;

        plotArea = merge(effectivePlotArea, {});

        return function (compositionAreaOffset, sf) {
            compositionAreaOffset = compositionAreaOffset || {};

            plotArea.y += compositionAreaOffset.height || 0;
            plotArea.height = effectivePlotArea.height * sf;

            return plotArea;
        };
    };

    LegendBody.prototype.getSpaceTaken = function (spaceObj) {
        return spaceObj.height;
    };

    LegendBody.prototype.updateEffectivePlotArea = function (bBox, effectivePlotArea, val) {
        var conf = this.conf,
            padding = conf.padding;

        effectivePlotArea.height = val;
        bBox.height = val + 2 * padding.v;
    };

    LegendBody.prototype.getLogicalSpace = function (bBox, options, recalculate) {
        var lSpace = this._lSpace,
            conf = this.conf,
            padding = conf.padding,
            compositionsByCategory = this.compositionsByCategory,
            composition,
            compositionPlotArea,
            compositionAreaOffset,
            effectivePlotArea,
            getCompositionPlotArea,
            spaceTaken = 0,
            index,
            length;

        if (lSpace && !recalculate) {
            lSpace.isImpure = true;
            // If logical space has already been calculated and recalculate flag is on, return without recalculating.
            return lSpace;
        }

        lSpace = this._lSpace = {
            bound: {
                height: 0,
                width: 0
            },

            node: {
                logicArea: undefined
            }
        };

        effectivePlotArea = merge(bBox, {});

        // The logical rect inside which the composition are drawn
        effectivePlotArea.height -= 2 * padding.v;
        effectivePlotArea.width -= 2 * padding.h;
        effectivePlotArea.x += padding.h;
        effectivePlotArea.y += padding.v;

        getCompositionPlotArea = this.getCompositionPlotAreaFor(effectivePlotArea);

        options.colorRange = this.colorRange;

        for (index = 0, length = LegendBody.SC_STACK.length; index < length; index++) {
            if (!(composition = compositionsByCategory[LegendBody.SC_STACK[index]])) {
                continue;
            }

            compositionPlotArea = getCompositionPlotArea(compositionAreaOffset, composition.conf.spreadFactor);
            compositionAreaOffset = composition.getLogicalSpace(merge(compositionPlotArea, {}), options, recalculate);

            spaceTaken += this.getSpaceTaken(compositionAreaOffset);
        }

        this.updateEffectivePlotArea(bBox, effectivePlotArea, spaceTaken);

        lSpace.node.logicArea = effectivePlotArea;
        lSpace.bound = bBox;

        return bBox;
    };

    LegendBody.prototype.draw = function () {
        var childTextConf = this.childTextConf,
            conf = this.conf,
            boundStyle = conf.bound.style || {},
            compositionsByCategory = this.compositionsByCategory,
            paper,
            layer,
            bound,
            colorRange,
            composition,
            legendBodyGroup,
            bBox,
            componentPool,
            lSpace,
            x,
            options,
            index,
            length,
            instanceFn,
            keys;


        if (arguments.length >= 3) {
            x = arguments[0];
            bBox = arguments[1];
            options = arguments[2];
        } else if (arguments.length >= 2){
            x = arguments[0];
            options = arguments[1];
        }

        paper = options.paper;
        layer = options.parentLayer;
        colorRange = options.colorRange;
        componentPool = options.componentPool;
        keys = componentPool.getKeys();

        this.getLogicalSpace(bBox, options);
        lSpace = this._lSpace;
        // debugger
        instanceFn = componentPool.getComponent(this._id, keys.KEY_GROUP);
        legendBodyGroup = instanceFn('legend-body', layer).attr({
            transform: 't0,0'
        }).css(childTextConf.style);
        //legendBodyGroup = paper.group('legend-body', layer);

        instanceFn = componentPool.getComponent(this._id, keys.KEY_RECT);
        this.bound = bound = instanceFn(legendBodyGroup).attr(lSpace.bound).css(boundStyle);
        //bound = this.bound = paper.rect(lSpace.bound, legendBodyGroup).css(boundStyle);


        options.colorRange = this.colorRange;
        options.parentLayer = legendBodyGroup;
        for (index = 0, length = LegendBody.DARW_STACK.length; index < length; index++) {
            if (!(composition = compositionsByCategory[LegendBody.DARW_STACK[index]])) {
                continue;
            }

            composition.draw(options);
        }

        if (options.moveInstructions) {
            legendBodyGroup.attr({
                transform: options.moveInstructions
            });
        }

        return {
            bound: bound,
            group: legendBodyGroup
        };
    };

    function VerticalLegendBody () {
        LegendBody.apply(this, arguments);
    }

    VerticalLegendBody.prototype = Object.create(LegendBody.prototype);
    VerticalLegendBody.prototype.constructor = VerticalLegendBody;

    VerticalLegendBody.prototype.getCompositionPlotAreaFor = function (effectivePlotArea) {
        var plotArea;

        plotArea = merge(effectivePlotArea, {});

        return function (compositionAreaOffset, sf) {
            compositionAreaOffset = compositionAreaOffset || {};

            plotArea.x += compositionAreaOffset.width || 0;
            plotArea.width = effectivePlotArea.width * sf;

            return plotArea;
        };
    };

    VerticalLegendBody.prototype.updateEffectivePlotArea = function (bBox, effectivePlotArea, val) {
        var conf = this.conf,
            padding = conf.padding;

        effectivePlotArea.width = val;
        bBox.width = val + 2 * padding.h;
    };

    VerticalLegendBody.prototype.getSpaceTaken = function (spaceObj) {
        return spaceObj.width;
    };

    function LegendLabels(conf) {
        this.conf = conf;
        this._id = 'GL_LABELS';
    }

    LegendLabels.prototype.constructor = LegendLabels;

    LegendLabels.prototype.getEffectivePlotArea = function (area) {
        var conf = this.conf,
            padding = conf.padding;

        // The logical rect inside which the composition are drawn
        area.height -= 2 * padding.v;
        area.width -= 2 * padding.h;
        area.x += padding.h;
        area.y += padding.v;
        this.node = [];

        return area;
    };

    LegendLabels.prototype.getLogicalSpace = function (bBox, options, recalculate) {
        var lSpace = this._lSpace,
            conf = this.conf,
            padding = conf.padding,
            cRange,
            smartLabel,
            crDataObj,
            index,
            length,
            labelHeights = [],
            leftBound,
            rightBound,
            plotArea,
            label,
            valueRatio,
            stop,
            zerothStop,
            lsTexts,
            maxHeight,
            effectivePlotArea,
            testSmartLabel,
            noOfLabels = 0,
            nextRefPoint,
            currPoint,
            leftStop,
            smartText,
            ni,
            copyOfStyle,
            componentPool = options.componentPool,
            chart = componentPool.getChart(),
            normalizedDataArr = [];

        if (lSpace && !recalculate) {
            lSpace.isImpure = true;
            // If logical space has already been calculated and recalculate flag is on, return without recalculating.
            return lSpace;
        }

        cRange = options.colorRange;
        smartLabel = options.smartLabel;
        valueRatio = cRange.getCumulativeValueRatio();
        crDataObj = cRange.colorRange;

        lSpace = this._lSpace = {
            bound: {
                height: 0,
                width: 0
            },

            node: {
                logicArea: undefined,
                smartTexts: []
            }
        };

        lsTexts = lSpace.node.smartTexts;

        plotArea = merge(bBox, {});

        // The logical rect inside which the composition are drawn
        effectivePlotArea = this.getEffectivePlotArea(plotArea);

        smartLabel.useEllipsesOnOverflow(chart.config.useEllipsesWhenOverflow);
        copyOfStyle = merge(conf.style, {});
        normalizeFontSizeAppend(this._metaStyle = copyOfStyle);

        smartLabel.setStyle(copyOfStyle);
        testSmartLabel = smartLabel.getSmartText('W');

        for (index = 0, length = crDataObj.length; index < length; index++) {
            label = crDataObj[index].label;

            if (!label) {
                lsTexts[index] = undefined;
                continue;
            }

            noOfLabels++;
            normalizedDataArr.push({
                oriIndex: index,
                label: label
            });
        }

        length = normalizedDataArr.length;

        if (length === 0) {
            return {
                height: 0,
                width: 0
            };
        }

        if (length > 1) {
            stop = ((valueRatio[normalizedDataArr[length - 1].oriIndex] -
                valueRatio[normalizedDataArr[0].oriIndex]) / 2) * effectivePlotArea.width / 100;
        } else {
            stop = Math.max(valueRatio[normalizedDataArr[0].oriIndex], 100 -
                valueRatio[normalizedDataArr[0].oriIndex]) / 2 * effectivePlotArea.width / 100;
        }

        zerothStop = stop;

        // first scale Label
        smartText = smartLabel.getSmartText(normalizedDataArr[0].label, zerothStop, effectivePlotArea.height);
        smartText.x = valueRatio[normalizedDataArr[0].oriIndex] * effectivePlotArea.width / 100;
        leftBound = smartText.x + smartText.width;
        labelHeights.push(smartText.height);
        lsTexts[normalizedDataArr[0].oriIndex] = smartText;

        //last scale label
        smartText = smartLabel.getSmartText(normalizedDataArr[length - 1].label,
            zerothStop, effectivePlotArea.height);
        smartText.x = valueRatio[normalizedDataArr[length - 1].oriIndex] * effectivePlotArea.width / 100;
        rightBound = smartText.x - smartText.width;
        labelHeights.push(smartText.height);
        lsTexts[normalizedDataArr[length - 1].oriIndex] = smartText;

        leftStop = leftBound;
        for (index = 1; index < length - 1; index++) {
            label = normalizedDataArr[index].label;
            ni = normalizedDataArr[index].oriIndex;

            smartText = undefined;

            nextRefPoint = index + 1 === length - 1 ? rightBound : valueRatio[normalizedDataArr[index + 1].oriIndex] *
                effectivePlotArea.width / 100;

            currPoint = valueRatio[normalizedDataArr[index].oriIndex] * effectivePlotArea.width / 100;

            stop = Math.min(currPoint - leftStop, nextRefPoint - currPoint);

            if (stop > 2 * testSmartLabel.width) {
                smartText = smartLabel.getSmartText(label, stop, effectivePlotArea.height);
                smartText.x = valueRatio[ni] * effectivePlotArea.width / 100;

                leftStop = stop;
                labelHeights.push(smartText.height);
            }

            lsTexts[normalizedDataArr[index].oriIndex] = smartText;
        }

        maxHeight = Math.max.apply(Math, labelHeights);

        effectivePlotArea.height = maxHeight;
        bBox.height = maxHeight + 2 * padding.v;

        lSpace.node.logicArea = effectivePlotArea;
        lSpace.bound = bBox;

        return bBox;
    };

    LegendLabels.prototype.draw = function () {
        var paper,
            layer,
            bound,
            conf = this.conf,
            boundStyle = conf.bound && conf.bound.style || {
                stroke: 'none'
            },
            cRange,
            componentPool,
            legendLabelsGroup,
            bBox,
            smartText,
            lSpace,
            crDataObj,
            valueRatio,
            options,
            index,
            logicArea,
            lsTexts,
            length,
            pos = {},
            instanceFn,
            keys;


        if (arguments.length >= 2) {
            bBox = arguments[0];
            options = arguments[1];
        } else if (arguments.length >= 1){
            options = arguments[0];
        }

        paper = options.paper;
        layer = options.parentLayer;
        cRange = options.colorRange;
        valueRatio = cRange.getCumulativeValueRatio();
        crDataObj = cRange.colorRange;
        componentPool = options.componentPool;
        keys = componentPool.getKeys();

        this.getLogicalSpace(bBox, options);
        lSpace = this._lSpace;
        logicArea = lSpace.node.logicArea;
        lsTexts = lSpace.node.smartTexts;

        instanceFn = componentPool.getComponent(this._id, keys.KEY_GROUP);
        legendLabelsGroup = instanceFn('legend-labels', layer);

        instanceFn = componentPool.getComponent(this._id, keys.KEY_RECT);
        this.bound = bound = instanceFn(legendLabelsGroup).attr(lSpace.bound).css(boundStyle);

        // legendLabelsGroup.transform('R0');


        instanceFn = componentPool.getComponent(this._id, keys.KEY_TEXT, true);
        for (index = 0, length = lsTexts.length; index < length; index++) {
            smartText = lsTexts[index];

            if (!smartText) {
                continue;
            }

            pos.y = logicArea.y + smartText.height / 2;

            if (index === length - 1) {
                pos.x = logicArea.x + smartText.x - smartText.width / 2;
            } else if (index){
                pos.x = logicArea.x + smartText.x;
            } else {
                pos.x = logicArea.x + smartText.x + smartText.width / 2;
            }

            this.node.push(instanceFn({}, legendLabelsGroup).attr({
                text: smartText.text,
                x: pos.x,
                y: pos.y,
                lineHeight: this._metaStyle.lineHeight,
                fill: conf.style.fill
            }).transform('R0'));
        }

        return {
            group: legendLabelsGroup,
            bound: bound,
            node: this.node
        };
    };

    function VerticalLegendLabels () {
        LegendLabels.apply(this, arguments);
    }

    VerticalLegendLabels.prototype = Object.create(LegendLabels.prototype);
    VerticalLegendLabels.prototype.constructor = VerticalLegendLabels;

    VerticalLegendLabels.prototype.getLogicalSpace = function (bBox, options, recalculate) {
        var lSpace = this._lSpace,
            conf = this.conf,
            padding = conf.padding,
            cRange,
            smartLabel,
            crDataObj,
            index,
            length,
            labelHeights = [],
            leftBound,
            rightBound,
            plotArea,
            label,
            valueRatio,
            stop,
            zerothStop,
            lsTexts,
            maxHeight,
            effectivePlotArea,
            testSmartLabel,
            noOfLabels = 0,
            nextRefPoint,
            currPoint,
            leftStop,
            smartText,
            ni,
            copyOfStyle,
            componentPool = options.componentPool,
            chart = componentPool.getChart(),
            normalizedDataArr = [];

        if (lSpace && !recalculate) {
            lSpace.isImpure = true;
            // If logical space has already been calculated and recalculate flag is on, return without recalculating.
            return lSpace;
        }

        cRange = options.colorRange;
        smartLabel = options.smartLabel;
        valueRatio = cRange.getCumulativeValueRatio();
        crDataObj = cRange.colorRange;

        lSpace = this._lSpace = {
            bound: {
                height: 0,
                width: 0
            },

            node: {
                logicArea: undefined,
                smartTexts: []
            }
        };

        lsTexts = lSpace.node.smartTexts;

        plotArea = merge(bBox, {});

        // The logical rect inside which the composition are drawn
        effectivePlotArea = this.getEffectivePlotArea(plotArea);

        smartLabel.useEllipsesOnOverflow(chart.config.useEllipsesWhenOverflow);
        copyOfStyle = merge(conf.style, {});
        normalizeFontSizeAppend(this._metaStyle = copyOfStyle);

        smartLabel.setStyle(copyOfStyle);
        testSmartLabel = smartLabel.getSmartText('W');

        for (index = 0, length = crDataObj.length; index < length; index++) {
            label = crDataObj[index].label;

            if (!label) {
                lsTexts[index] = undefined;
                continue;
            }

            noOfLabels++;
            normalizedDataArr.push({
                oriIndex: index,
                label: label
            });
        }

        length = normalizedDataArr.length;

        if (length === 0) {
            return {
                height: 0,
                width: 0
            };
        }

        if (length > 1) {
            stop = ((valueRatio[normalizedDataArr[length - 1].oriIndex] -
                valueRatio[normalizedDataArr[0].oriIndex]) / 2) * effectivePlotArea.height / 100;
        } else {
            stop = Math.max(valueRatio[normalizedDataArr[0].oriIndex], 100 -
                valueRatio[normalizedDataArr[0].oriIndex]) / 2 * effectivePlotArea.height / 100;
        }

        zerothStop = stop;

        // first scale Label
        smartText = smartLabel.getSmartText(normalizedDataArr[0].label, zerothStop, effectivePlotArea.width);
        smartText.y = valueRatio[normalizedDataArr[0].oriIndex] * effectivePlotArea.height / 100;
        leftBound = smartText.y + smartText.width;
        labelHeights.push(smartText.height);
        lsTexts[normalizedDataArr[0].oriIndex] = smartText;

        //last scale label
        smartText = smartLabel.getSmartText(normalizedDataArr[length - 1].label, zerothStop, effectivePlotArea.width);
        smartText.y = valueRatio[normalizedDataArr[length - 1].oriIndex] * effectivePlotArea.height / 100;
        rightBound = smartText.y - smartText.width;
        labelHeights.push(smartText.height);
        lsTexts[normalizedDataArr[length - 1].oriIndex] = smartText;

        leftStop = leftBound;
        for (index = 1; index < length - 1; index++) {
            label = normalizedDataArr[index].label;
            ni = normalizedDataArr[index].oriIndex;

            smartText = undefined;

            nextRefPoint = index + 1 === length - 1 ? rightBound : valueRatio[normalizedDataArr[index + 1].oriIndex] *
                effectivePlotArea.height / 100;

            currPoint = valueRatio[normalizedDataArr[index].oriIndex] * effectivePlotArea.height / 100;

            stop = Math.min(currPoint - leftStop, nextRefPoint - currPoint);

            if (stop > 2 * testSmartLabel.width) {
                smartText = smartLabel.getSmartText(label, stop, effectivePlotArea.width);
                smartText.y = valueRatio[ni] * effectivePlotArea.height / 100;

                leftStop = stop;
                labelHeights.push(smartText.height);
            }

            lsTexts[normalizedDataArr[index].oriIndex] = smartText;
        }

        maxHeight = Math.max.apply(Math, labelHeights);

        effectivePlotArea.width = maxHeight;
        bBox.width = maxHeight + 2 * padding.v;

        lSpace.node.logicArea = effectivePlotArea;
        lSpace.bound = bBox;

        return bBox;
    };

    VerticalLegendLabels.prototype.draw = function () {
        var paper,
            layer,
            bound,
            conf = this.conf,
            boundStyle = conf.bound && conf.bound.style || {
                stroke: 'none'
            },
            cRange,
            componentPool,
            legendLabelsGroup,
            bBox,
            smartText,
            lSpace,
            crDataObj,
            valueRatio,
            options,
            index,
            logicArea,
            lsTexts,
            length,
            pos = {},
            instanceFn,
            keys;


        if (arguments.length >= 2) {
            bBox = arguments[0];
            options = arguments[1];
        } else if (arguments.length >= 1){
            options = arguments[0];
        }

        paper = options.paper;
        layer = options.parentLayer;
        cRange = options.colorRange;
        valueRatio = cRange.getCumulativeValueRatio();
        crDataObj = cRange.colorRange;
        componentPool = options.componentPool;
        keys = componentPool.getKeys();

        this.getLogicalSpace(bBox, options);
        lSpace = this._lSpace;
        logicArea = lSpace.node.logicArea;
        lsTexts = lSpace.node.smartTexts;

        instanceFn = componentPool.getComponent(this._id, keys.KEY_GROUP);
        legendLabelsGroup = instanceFn('legend-labels', layer);

        instanceFn = componentPool.getComponent(this._id, keys.KEY_RECT);
        this.bound = bound = instanceFn(legendLabelsGroup).attr(lSpace.bound).css(boundStyle);

        instanceFn = componentPool.getComponent(this._id, keys.KEY_TEXT, true);
        for (index = 0, length = lsTexts.length; index < length; index++) {
            smartText = lsTexts[index];

            if (!smartText) {
                continue;
            }

            pos.x = logicArea.x + smartText.height / 2;

            if (index === length - 1) {
                pos.y = logicArea.y + smartText.y - smartText.width / 2;
            } else if (index){
                pos.y = logicArea.y + smartText.y;
            } else {
                pos.y = logicArea.y + smartText.y + smartText.width / 2;
            }

            this.node.push(instanceFn({}, legendLabelsGroup).attr({
                text: smartText.text,
                x: pos.x,
                y: pos.y,
                lineHeight: this._metaStyle.lineHeight,
                fill: conf.style.fill
            }).transform('R270,' + pos.x + ',' + pos.y));
        }

        return {
            group: legendLabelsGroup,
            bound: bound,
            node: this.node
        };
    };




    function LegendValues () {
        LegendLabels.apply(this, arguments);
        this._id = 'GL_VALUES';
    }

    LegendValues.prototype = Object.create(LegendLabels.prototype);
    LegendValues.prototype.constructor = LegendValues;

    LegendValues.prototype.getLogicalSpace = function (bBox, options, recalculate) {
        var lSpace = this._lSpace,
            conf = this.conf,
            padding = conf.padding,
            componentPool = options.componentPool,
            chart = componentPool.getChart(),
            cRange,
            smartLabel,
            crDataObj,
            smartText,
            index,
            length,
            valueRatio,
            stop,
            nextRefPoint,
            currPoint,
            zerothStop,
            labelHeights = [],
            leftBound,
            leftStop,
            rightBound,
            maxHeight,
            effectivePlotArea,
            val,
            dispValue,
            testSmartLabel,
            copyOfStyle,
            lsTexts;

        if (lSpace && !recalculate) {
            lSpace.isImpure = true;
            // If logical space has already been calculated and recalculate flag is on, return without recalculating.
            return lSpace;
        }

        cRange = options.colorRange;
        smartLabel = options.smartLabel;
        crDataObj = cRange.colorRange;
        valueRatio = cRange.getCumulativeValueRatio();

        lSpace = this._lSpace = {
            bound: {
                height: 0,
                width: 0
            },

            node: {
                logicArea: undefined,
                smartTexts: []
            }
        };

        lsTexts = lSpace.node.smartTexts;
        effectivePlotArea = merge(bBox, {});

        // The logical rect inside which the composition are drawn
        effectivePlotArea.height -= 2 * padding.v;
        effectivePlotArea.width -= 2 * padding.h;
        effectivePlotArea.x += padding.h;
        effectivePlotArea.y += padding.v;

        smartLabel.useEllipsesOnOverflow(chart.config.useEllipsesWhenOverflow);
        copyOfStyle = merge(conf.style, {});
        normalizeFontSizeAppend(this._metaStyle = copyOfStyle);

        smartLabel.setStyle(copyOfStyle);
        testSmartLabel = smartLabel.getSmartText('W');

        length = crDataObj.length;
        zerothStop = stop = ((valueRatio[length - 1] - valueRatio[0]) / 2) * effectivePlotArea.width / 100;

        // first scale Label
        dispValue = crDataObj[0].displayValue;
        smartText = smartLabel.getSmartText((typeof dispValue !== 'string' && dispValue !== undefined) &&
            dispValue.toString() || dispValue, zerothStop, effectivePlotArea.height);
        smartText.x = valueRatio[0] * effectivePlotArea.width / 100;
        leftBound = smartText.x + smartText.width;
        labelHeights.push(smartText.height);
        lsTexts[0] = smartText;

        //last scale label
        smartText = smartLabel.getSmartText(crDataObj[length - 1].displayValue,
            zerothStop, effectivePlotArea.height);
        smartText.x = valueRatio[length - 1] * effectivePlotArea.width / 100;
        rightBound = smartText.x - smartText.width;
        labelHeights.push(smartText.height);
        lsTexts[length - 1] = smartText;

        leftStop = leftBound;
        for (index = 1; index < length - 1; index++) {
            smartText = undefined;

            val = crDataObj[index].displayValue;

            nextRefPoint = index + 1 === length - 1 ? rightBound : valueRatio[index + 1] *
                effectivePlotArea.width / 100;
            currPoint = valueRatio[index] * effectivePlotArea.width / 100;

            stop = Math.min(currPoint - leftStop, nextRefPoint - currPoint);

            if (stop > 1.5 * testSmartLabel.width) {
                smartText = smartLabel.getSmartText(val, 2 * stop, effectivePlotArea.height);
                smartText.x = valueRatio[index] * effectivePlotArea.width / 100;
                leftStop = stop;
                labelHeights.push(smartText.height);
            }

            lsTexts[index] = smartText;
        }

        maxHeight = Math.max.apply(Math, labelHeights);

        effectivePlotArea.height = maxHeight;
        bBox.height = maxHeight + 2 * padding.v;

        lSpace.node.logicArea = effectivePlotArea;
        lSpace.bound = bBox;

        return bBox;
    };

    LegendValues.prototype.draw = function () {
        var conf = this.conf,
            boundStyle = conf.bound && conf.bound.style || {
                stroke: 'none'
            },
            keys,
            pos = {},
            paper,
            layer,
            bound,
            legendValuesGroup,
            componentPool,
            bBox,
            lSpace,
            smartLabel,
            logicArea,
            options,
            cRange,
            valueRatio,
            index,
            length,
            smartTexts,
            smartText,
            instanceFn,
            numberFormatter;


        if (arguments.length >= 2) {
            bBox = arguments[0];
            options = arguments[1];
        } else if (arguments.length >= 1){
            options = arguments[0];
        }

        paper = options.paper;
        layer = options.parentLayer;
        smartLabel = options.smartLabel,
        cRange = options.colorRange;
        numberFormatter = options.numberFormatter,
        valueRatio = cRange.getCumulativeValueRatio();
        componentPool = options.componentPool;
        keys = componentPool.getKeys();

        this.getLogicalSpace(bBox, options);
        lSpace = this._lSpace;
        logicArea = lSpace.node.logicArea;
        smartTexts = lSpace.node.smartTexts;

        instanceFn = componentPool.getComponent(this._id, keys.KEY_GROUP);
        legendValuesGroup = instanceFn('legend-values', layer);

        instanceFn = componentPool.getComponent(this._id, keys.KEY_RECT);
        this.bound = bound = instanceFn(legendValuesGroup).attr(lSpace.bound).css(boundStyle);

        instanceFn = componentPool.getComponent(this._id, keys.KEY_TEXT, true);
        for (index = 0, length = valueRatio.length; index < length; index++) {
            smartText = smartTexts[index];

            if (!smartText) {
                continue;
            }

            pos.y = logicArea.y + smartText.height / 2;

            if (index === length - 1) {
                pos.x = logicArea.x + smartText.x - smartText.width / 2;
            } else if (index){
                pos.x = logicArea.x + smartText.x;
            } else {
                pos.x = logicArea.x + smartText.x + smartText.width / 2;
            }

            instanceFn({}, legendValuesGroup).attr({
                text: smartText.text,
                x: pos.x,
                y: pos.y,
                lineHeight: this._metaStyle.lineHeight,
                fill: conf.style.fill
            });

        }

        return {
            group: legendValuesGroup,
            bound: bound
        };
    };


    function VerticalLegendValues () {
        LegendValues.apply(this, arguments);
        this._id = 'GL_VALUES';
    }

    VerticalLegendValues.prototype = Object.create(LegendValues.prototype);
    VerticalLegendValues.prototype.constructor = VerticalLegendValues;

    VerticalLegendValues.prototype.getLogicalSpace = function (bBox, options, recalculate) {
        var lSpace = this._lSpace,
            conf = this.conf,
            padding = conf.padding,
            componentPool = options.componentPool,
            chart = componentPool.getChart(),
            cRange,
            smartLabel,
            crDataObj,
            smartText,
            index,
            length,
            valueRatio,
            stop,
            nextRefPoint,
            currPoint,
            effectivePlotArea,
            zerothStop,
            labelWidths = [],
            topBound,
            topStop,
            maxWidth,
            bottomBound,
            val,
            copyOfStyle,
            testSmartLabel,
            lsTexts;

        if (lSpace && !recalculate) {
            lSpace.isImpure = true;
            // If logical space has already been calculated and recalculate flag is on, return without recalculating.
            return lSpace;
        }

        cRange = options.colorRange;
        smartLabel = options.smartLabel;
        crDataObj = cRange.colorRange;
        valueRatio = cRange.getCumulativeValueRatio();

        lSpace = this._lSpace = {
            bound: {
                height: 0,
                width: 0
            },

            node: {
                logicArea: undefined,
                smartTexts: []
            }
        };

        lsTexts = lSpace.node.smartTexts;
        effectivePlotArea = merge(bBox, {});

        // The logical rect inside which the composition are drawn
        effectivePlotArea.height -= 2 * padding.v;
        effectivePlotArea.width -= 2 * padding.h;
        effectivePlotArea.x += padding.h;
        effectivePlotArea.y += padding.v;

        smartLabel.useEllipsesOnOverflow(chart.config.useEllipsesWhenOverflow);
        copyOfStyle = merge(conf.style, {});
        normalizeFontSizeAppend(copyOfStyle);

        smartLabel.setStyle(this._metaStyle = copyOfStyle);
        testSmartLabel = smartLabel.getSmartText('W');

        length = crDataObj.length;
        zerothStop = stop = ((valueRatio[length - 1] - valueRatio[0]) / 2) * effectivePlotArea.height / 100;

        // first scale Label
        smartText = smartLabel.getSmartText(crDataObj[0].displayValue,
                    effectivePlotArea.width, zerothStop);
        smartText.y = valueRatio[0] * effectivePlotArea.height / 100;
        topBound = smartText.y + smartText.width;
        labelWidths.push(smartText.width);
        lsTexts[0] = smartText;

        //last scale label
        smartText = smartLabel.getSmartText(crDataObj[length - 1].displayValue,
            effectivePlotArea.width, zerothStop);
        smartText.y = valueRatio[length - 1] * effectivePlotArea.height / 100;
        bottomBound = smartText.y - smartText.height;
        labelWidths.push(smartText.width);
        lsTexts[length - 1] = smartText;

        topStop = topBound;
        for (index = 1; index < length - 1; index++) {
            smartText = undefined;

            val = crDataObj[index].displayValue;

            nextRefPoint = index + 1 === length - 1 ? bottomBound : valueRatio[index + 1] *
                effectivePlotArea.height / 100;
            currPoint = valueRatio[index] * effectivePlotArea.height / 100;

            stop = Math.min(currPoint - topStop, nextRefPoint - currPoint);

            if (stop > 2 * testSmartLabel.height) {
                smartText = smartLabel.getSmartText(val, effectivePlotArea.width, 2 * stop);
                smartText.y = valueRatio[index] * effectivePlotArea.height / 100;

                topStop = stop;
                labelWidths.push(smartText.width);
            }

            lsTexts[index] = smartText;
        }

        maxWidth = Math.max.apply(Math, labelWidths);

        effectivePlotArea.width = maxWidth;
        bBox.width = maxWidth + 2 * padding.h;

        lSpace.node.logicArea = effectivePlotArea;
        lSpace.bound = bBox;

        return bBox;
    };

    VerticalLegendValues.prototype.draw = function () {
        var paper,
            layer,
            bound,
            conf = this.conf,
            boundStyle = conf.bound && conf.bound.style || {
                stroke: 'none'
            },
            legendValuesGroup,
            bBox,
            lSpace,
            smartLabel,
            logicArea,
            options,
            cRange,
            valueRatio,
            smartTexts,
            smartText,
            index,
            length,
            pos = {},
            componentPool,
            instanceFn,
            keys;


        if (arguments.length >= 2) {
            bBox = arguments[0];
            options = arguments[1];
        } else if (arguments.length >= 1){
            options = arguments[0];
        }

        paper = options.paper;
        layer = options.parentLayer;
        smartLabel = options.smartLabel,
        cRange = options.colorRange;
        valueRatio = cRange.getCumulativeValueRatio();
        componentPool = options.componentPool;
        keys = componentPool.getKeys();

        this.getLogicalSpace(bBox, options);
        lSpace = this._lSpace;
        logicArea = lSpace.node.logicArea;
        smartTexts = lSpace.node.smartTexts;

        instanceFn = componentPool.getComponent(this._id, keys.KEY_GROUP);
        legendValuesGroup = instanceFn('legend-values', layer);

        instanceFn = componentPool.getComponent(this._id, keys.KEY_RECT);
        this.bound = bound = instanceFn(legendValuesGroup).attr(lSpace.bound).css(boundStyle);

        instanceFn = componentPool.getComponent(this._id, keys.KEY_TEXT, true);
        for (index = 0, length = valueRatio.length; index < length; index++) {
            smartText = smartTexts[index];

            if (!smartText) {
                continue;
            }

            pos.x = logicArea.x + smartText.width / 2;

            if (index === length - 1) {
                pos.y = logicArea.y + smartText.y - smartText.height / 2;
            } else if (index){
                pos.y = logicArea.y + smartText.y;
            } else {
                pos.y = logicArea.y + smartText.y + smartText.height / 2;
            }

            instanceFn({ }, legendValuesGroup).attr({
                text: smartText.text,
                x: pos.x,
                y: pos.y,
                lineHeight: this._metaStyle.lineHeight,
                fill: conf.style.fill
            });

        }

        return {
            group: legendValuesGroup,
            bound: bound
        };
    };

    function LegendAxis (conf) {
        this.conf = conf;
        this._id = 'FL_AXIS';

        this.node = undefined;
        this.shadow = undefined;
        this.markerLine = undefined;
        this.compositionsByCategory = {};
    }

    LegendAxis.prototype.constructor = LegendAxis;

    LegendAxis.prototype.addCompositions = function (instance, category) {
        this.compositionsByCategory[category] = instance;
    };

    LegendAxis.prototype.getLogicalSpace = function (bBox, options, recalculate) {
        var lSpace = this._lSpace,
            conf = this.conf,
            padding = conf.padding,
            heightTakenLower,
            heightTakenUpper,
            heightTaken,
            axisThickness = conf.legendAxisHeight,
            compositionsByCategory = this.compositionsByCategory,
            sliderG,
            effectivePlotArea,
            slider,
            sliderSpace,
            sliderExtraDiam = 0;

        if (lSpace && !recalculate) {
            lSpace.isImpure = true;
            // If logical space has already been calculated and recalculate flag is on, return without recalculating.
            return lSpace;
        }

        lSpace = this._lSpace = {
            bound: {
                height: 0,
                width: 0
            },

            node: {
                logicArea: undefined
            }
        };

        effectivePlotArea = merge(bBox, {});

        // The logical rect inside which the composition are drawn
        effectivePlotArea.height -= 2 * padding.v;
        effectivePlotArea.width -= 2 * padding.h;
        effectivePlotArea.x += padding.h;
        effectivePlotArea.y += padding.v;

        heightTakenLower = (axisThickness / 2) + conf.line.offset;
        heightTakenUpper = axisThickness / 2;

        sliderG = compositionsByCategory[compositionKeys.RANGE];
        if (sliderG) {
            slider = sliderG.sliders[false];
            sliderSpace = slider.conf.outerCircle.rFactor * axisThickness;
            heightTakenUpper += sliderExtraDiam = Math.max(sliderSpace / 2 - axisThickness / 2, 0);
        }

        // @todo Change the height and width of bBox
        effectivePlotArea.y += sliderExtraDiam;
        effectivePlotArea.height = heightTaken = heightTakenUpper + heightTakenLower + sliderExtraDiam;
        bBox.height = heightTaken + 2 * padding.v;

        lSpace.node.logicArea = effectivePlotArea;
        lSpace.bound = bBox;

        return bBox;
    };

    LegendAxis.prototype.getDrawableAxisArea = function (parentBoundingRect) {
        var conf = this.conf,
            x = parentBoundingRect.x,
            y = parentBoundingRect.y,
            width = parentBoundingRect.width,
            height = conf.legendAxisHeight,
            r = conf.legendAxisHeight / 2;

        return {
            x: x,
            y: y,
            width: width,
            height: height,
            r: r
        };
    };

    LegendAxis.prototype.preDrawingRangeParam = function (drawableArea) {
        var y = drawableArea.y + (drawableArea.height / 2),
            calculationBase = drawableArea.height;

        return {
            y: y,
            calculationBase: calculationBase,
            rangeStart: drawableArea.x,
            rangeEnd: drawableArea.x + drawableArea.width,
            prop: 'y'
        };
    };

    LegendAxis.prototype.getScaleMarkerPathStr = function (oriAxisRect, valueRatio) {
        var axisRect = merge(oriAxisRect, {}),
            conf = this.conf,
            lineAttr = conf.line,
            index,
            length,
            ratio,
            covered,
            markerStartY,
            tickStr = '',
            lineStr = '';

        axisRect.x += axisRect.r;
        axisRect.width -= 2 * axisRect.r;
        markerStartY = axisRect.y + axisRect.height;

        for (index = 0, length = valueRatio.length; index < length; index++) {
            ratio = valueRatio[index];
            covered = axisRect.x + (ratio * axisRect.width / 100);

            tickStr += M + (covered) + COMMA_STR + (markerStartY - lineAttr.grooveLength) +
                L + (covered) + COMMA_STR + (markerStartY + lineAttr.offset);
        }

        lineStr += M + (axisRect.x) + COMMA_STR + (markerStartY + lineAttr.offset) +
            L + (axisRect.x + axisRect.width) + COMMA_STR + (markerStartY + lineAttr.offset);

        return tickStr + lineStr;
    };

    LegendAxis.prototype.getColorGradient = function (colorRange) {
        return {
            axis: colorRange.getBoxFill(),
            shadow: toRaphaelColor({
                FCcolor: {
                    alpha : '25,0,0',
                    angle : 90,
                    color : '000000,FFFFFF,FFFFFF',
                    ratio : '0,30,40'
                }
            })
        };
    };

    LegendAxis.prototype.draw = function () {
        var paper,
            layer,
            bound,
            conf = this.conf,
            boundAttr = conf.bound || {},
            lineAttr = conf.line,
            boundStyle = boundAttr.style || {},
            node,
            bBox,
            category,
            compositionsByCategory = this.compositionsByCategory,
            cRange,
            valueRatio,
            composition,
            compositionMes,
            legendAxisGroup,
            rangeParams,
            grad,
            oriAxisRect,
            lSpace,
            options,
            instanceFn,
            keys,
            componentPool,
            scaleLine;


        if (arguments.length >= 2) {
            bBox = arguments[0];
            options = arguments[1];
        } else if (arguments.length >= 1){
            options = arguments[0];
        }

        paper = options.paper;
        layer = options.parentLayer;
        cRange = options.colorRange;
        valueRatio = cRange.getCumulativeValueRatio();
        componentPool = options.componentPool;
        keys = componentPool.getKeys();


        this.getLogicalSpace(bBox, options);
        lSpace = this._lSpace;

        instanceFn = componentPool.getComponent(this._id, keys.KEY_GROUP);
        legendAxisGroup = instanceFn('legend-axis', layer);
        //legendAxisGroup = paper.group('legend-axis', layer);

        instanceFn = componentPool.getComponent(this._id, keys.KEY_RECT, true);

        this.bound = bound = instanceFn(legendAxisGroup).attr(lSpace.bound).css(boundStyle);
        //bound = this.bound = paper.rect(lSpace.bound, legendAxisGroup).css(boundStyle);

        oriAxisRect = this.getDrawableAxisArea(lSpace.node.logicArea);
        grad = this.getColorGradient(cRange);
        conf.style.fill = grad.axis;
        conf.shadow.style.fill = grad.shadow;

        // node = this.node = paper.rect(oriAxisRect, legendAxisGroup).css(conf.style);
        // this.shadow = paper.rect(oriAxisRect, legendAxisGroup).css(conf.shadow.style);
        node = this.node = instanceFn(legendAxisGroup).attr(oriAxisRect).css(conf.style);
        this.shadow = instanceFn(legendAxisGroup).attr(oriAxisRect).css(conf.shadow.style);

        scaleLine = this.getScaleMarkerPathStr(oriAxisRect, valueRatio);
        instanceFn = componentPool.getComponent(this._id, keys.KEY_PATH);
        instanceFn('M0,0', legendAxisGroup)
            .attr({ path: scaleLine }).css(lineAttr.style);

        for (category in compositionsByCategory) {
            composition = compositionsByCategory[category];

            switch (category) {
                case compositionKeys.RANGE:
                    rangeParams = this.preDrawingRangeParam(oriAxisRect);

                    options[rangeParams.prop] = rangeParams[rangeParams.prop];
                    options.key = rangeParams.prop;
                    options.rCalcBase = rangeParams.calculationBase;
                    options.parentLayer = legendAxisGroup;

                    compositionMes = composition.draw(rangeParams.rangeStart,rangeParams.rangeEnd, options);
            }
        }
    };

    function VerticalLegendAxis () {
        LegendAxis.apply(this, arguments);
    }

    VerticalLegendAxis.prototype = Object.create(LegendAxis.prototype);
    VerticalLegendAxis.prototype.constructor = VerticalLegendAxis;

    VerticalLegendAxis.prototype.getLogicalSpace = function (bBox, options, recalculate) {
        var lSpace = this._lSpace,
            conf = this.conf,
            padding = conf.padding,
            widthTakenLower,
            widthTakenUpper,
            widthTaken,
            axisThickness = conf.legendAxisHeight,
            compositionsByCategory = this.compositionsByCategory,
            sliderG,
            slider,
            effectivePlotArea,
            sliderSpace,
            sliderExtraDiam = 0;

        if (lSpace && !recalculate) {
            lSpace.isImpure = true;
            // If logical space has already been calculated and recalculate flag is on, return without recalculating.
            return lSpace;
        }

        lSpace = this._lSpace = {
            bound: {
                height: 0,
                width: 0
            },

            node: {
                logicArea: undefined
            }
        };

        effectivePlotArea = merge(bBox, {});

        // The logical rect inside which the composition are drawn
        effectivePlotArea.height -= 2 * padding.v;
        effectivePlotArea.width -= 2 * padding.h;
        effectivePlotArea.x += padding.h;
        effectivePlotArea.y += padding.v;

        widthTakenLower = (axisThickness / 2) + conf.line.offset;
        widthTakenUpper = axisThickness / 2;

        sliderG = compositionsByCategory[compositionKeys.RANGE];
        if (sliderG) {
            slider = sliderG.sliders[false];
            sliderSpace = slider.conf.outerCircle.rFactor * axisThickness;
            widthTakenUpper += sliderExtraDiam = Math.max(sliderSpace / 2 - axisThickness / 2, 0);
        }

        effectivePlotArea.x += sliderExtraDiam;
        effectivePlotArea.width = widthTaken = widthTakenUpper + widthTakenLower + sliderExtraDiam;
        bBox.width = widthTaken + 2 * padding.v;

        lSpace.node.logicArea = effectivePlotArea;
        lSpace.bound = bBox;

        return bBox;
    };

    VerticalLegendAxis.prototype.getDrawableAxisArea = function (parentBoundingRect) {
        var conf = this.conf;

        return {
            x: parentBoundingRect.x,
            y: parentBoundingRect.y,
            width: conf.legendAxisHeight,
            height: parentBoundingRect.height,
            r: conf.legendAxisHeight / 2
        };
    };

    VerticalLegendAxis.prototype.getScaleMarkerPathStr = function (oriAxisRect, valueRatio) {
        var axisRect = merge(oriAxisRect, {}),
            conf = this.conf,
            lineAttr = conf.line,
            index,
            ratio,
            length,
            markerStartX,
            covered,
            tickStr = '',
            lineStr = '';

        axisRect.y += axisRect.r;
        axisRect.height -= 2 * axisRect.r;
        markerStartX = axisRect.x + axisRect.width;

        for (index = 0, length = valueRatio.length; index < length; index++) {
            ratio = valueRatio[index];
            covered = axisRect.y + (ratio * axisRect.height / 100);

            tickStr += M + (markerStartX - lineAttr.grooveLength) + COMMA_STR + (covered) +
                L + (markerStartX + lineAttr.offset) + COMMA_STR + (covered);
        }

        lineStr += M + (markerStartX + lineAttr.offset) + COMMA_STR + (axisRect.y) +
            L + (markerStartX + lineAttr.offset) + COMMA_STR + (axisRect.y + axisRect.height);

        return tickStr + lineStr;
    };

    VerticalLegendAxis.prototype.getColorGradient = function (colorRange) {
        return {
            axis: colorRange.getBoxFill(true),
            shadow: toRaphaelColor({
                FCcolor: {
                    alpha : '25,0,0',
                    angle : 360,
                    color : '000000,FFFFFF,FFFFFF',
                    ratio : '0,30,40'
                }
            })
        };
    };

    VerticalLegendAxis.prototype.preDrawingRangeParam = function (drawableArea) {
        var x = drawableArea.x + (drawableArea.width / 2),
            calculationBase = drawableArea.width;

        return {
            x: x,
            calculationBase: calculationBase,
            rangeStart: drawableArea.y,
            rangeEnd: drawableArea.y + drawableArea.height,
            prop: 'x'
        };
    };

    function SliderGroup (conf) {
        var sliderConf = conf,
            options = {};

        this._id = 'GL_SG1';
        this.conf = conf;

        options.conf = sliderConf;

        this.extremes = [];
        this.sliders = {};

        options.sliderGroup = this;
        this.valueRange = [];
        this.callbacks = [];

        this.sliders[FORMER_SLIDER_INDEX] = new Slider(FORMER_SLIDER_INDEX, options, this._id +
                    '_' + (+FORMER_SLIDER_INDEX));
        this.sliders[LATER_SLIDER_INDEX] = new Slider(LATER_SLIDER_INDEX, options, this._id +
                    '_' + (+LATER_SLIDER_INDEX));
    }

    SliderGroup.prototype.constructor = SliderGroup;


    SliderGroup.prototype.initRange = function (slider, updatedRange) {
        var sliderIndex = slider.sliderIndex;

        this.extremes[+sliderIndex] = updatedRange;
    };

    SliderGroup.prototype.updateRange = function (slider, updatedRange) {
        var sliderIndex = slider.sliderIndex,
            sliders = this.sliders,
            s = sliders[!sliderIndex];

        s.updateSwingRange(sliderIndex, updatedRange);
    };

    SliderGroup.prototype.reset = function () {
        var options = {};

        options.conf = this.conf;
        options.sliderGroup = this;

        // @todo do it from a more generalized way
        this.sliders[FORMER_SLIDER_INDEX] = new Slider(FORMER_SLIDER_INDEX, options, this._id +
                    '_' + (+FORMER_SLIDER_INDEX));
        this.sliders[LATER_SLIDER_INDEX] = new Slider(LATER_SLIDER_INDEX, options, this._id +
                    '_' + (+LATER_SLIDER_INDEX));

        this.draw.apply(this, this._drawParams);
    };

    SliderGroup.prototype.clearListeners = function () {
        this.callbacks.length = 0;
    };

    SliderGroup.prototype.draw = function (rangeStart, rangeEnd, options) {
        var sliders = this.sliders,
            lSlider = sliders[FORMER_SLIDER_INDEX],
            rSlider = sliders[LATER_SLIDER_INDEX],
            cRange = options.colorRange,
            colorRange = cRange.colorRange,
            componentPool = options.componentPool,
            chart = this._fcChart = componentPool.getChart(),
            oneSliderMes;

        this.getValueFormPixel = function (valueStart, valueEnd, pixelStart, pixelEnd) {
            var unit = (valueEnd - valueStart) / (pixelEnd - pixelStart);

            this.getValueFormPixel = function (pixel) {
                return valueStart + (unit * pixel);
            };
        };

        this.updateWhenInMove = function (numberFormatter, mapByPercent) {
            this.updateWhenInMove = function (slider, val) {
                var extremes = this.extremes,
                    sliderIndex = slider.sliderIndex,
                    nVal,
                    value;

                if (sliderIndex) {
                    nVal = extremes[1] - extremes[0] + val;
                } else {
                    nVal = val;
                }

                value = this.getValueFormPixel(nVal);

                if (!mapByPercent) {
                    value = numberFormatter.legendValue(value);
                } else {
                    value = parseFloat(value).toFixed(2) + PERCENT_STR;
                }

                return value;
            };
        };

        this._drawParams = [rangeStart, rangeEnd, options];
        this.updateWhenInMove(chart.components.numberFormatter, cRange.mapByPercent);

        oneSliderMes = lSlider.draw(rangeStart, colorRange[0].displayValue, options[options.key], options);
        oneSliderMes = rSlider.draw(rangeEnd, colorRange[colorRange.length - 1].displayValue, options[options.key],
                options);

        lSlider.swing = this.extremes.slice(0);
        rSlider.swing = this.extremes.slice(0);

        this.getValueFormPixel(colorRange[0].value, colorRange[colorRange.length - 1].value,
                                this.extremes[0], this.extremes[1]);

        return oneSliderMes;
    };

    SliderGroup.prototype.registerListener = function (fn, context, params) {
        this.callbacks.push({
            fn: fn,
            context: context,
            params: params || []
        });
    };

    SliderGroup.prototype.updateWhenInRest = function (slider, val) {
        var sliders = this.sliders,
            extremes = this.extremes,
            sliderIndex = slider.sliderIndex,
            lValue,
            rValue,
            cIndex,
            cLength,
            callbacks = this.callbacks,
            cb,
            params;

        if (sliderIndex) {
            lValue = sliders[!sliderIndex].currPos;
            rValue = extremes[1] - extremes[0] + val;
        } else {
            lValue = val;
            rValue = extremes[1] - extremes[0] + sliders[!sliderIndex].currPos;
        }

        for (cIndex = 0, cLength = callbacks.length; cIndex < cLength; cIndex++) {
            cb = callbacks[cIndex];
            params = cb.params.slice(0);
            params.unshift(this.getValueFormPixel(rValue));
            params.unshift(this.getValueFormPixel(lValue));
            cb.fn.apply(cb.context, params);
        }
    };

    SliderGroup.prototype.dragStarted = function (self) {
        var sliders = this.sliders,
            extremes = this.extremes,
            conf = self.conf,
            chart = this._fcChart;

        global.raiseEvent ('legendpointerdragstart', {
            pointerIndex: +self.sliderIndex,
            pointers: [{
                value: this.getValueFormPixel(sliders[false].currPos)
            }, {
                value: this.getValueFormPixel(extremes[1] - extremes[0] + sliders[true].currPos)
            }],
            legendPointerHeight: conf.outerRadius,
            legendPointerWidth: conf.innerRadius,
            outerRadius: conf.outerRadius,
            innerRadius: conf.innerRadius
        }, chart.chartInstance, [chart.id]);
    };


    SliderGroup.prototype.dragCompleted = function (self, isDragged, newVal) {
        var sliders = this.sliders,
            extremes = this.extremes,
            conf = self.conf,
            minValue = this.getValueFormPixel(sliders[false].currPos),
            maxValue = this.getValueFormPixel(extremes[1] - extremes[0] + sliders[true].currPos),
            chart = this._fcChart,
            newMinValue,
            newMaxValue;

        if (!self.sliderIndex) {
            newMinValue = this.getValueFormPixel(newVal);
            newMaxValue = maxValue;
        } else {
            newMinValue = minValue;
            newMaxValue = this.getValueFormPixel(extremes[1] - extremes[0] + newVal);
        }

        if (isDragged) {
            global.raiseEvent ('legendrangeupdated', {
                previousMinValue: minValue,
                previousMaxValue: maxValue,
                minValue: newMinValue,
                maxValue: newMaxValue
            }, chart.chartInstance, [chart.id]);
        }

        global.raiseEvent ('legendpointerdragstop', {
            pointerIndex: +self.sliderIndex,
            pointers: [{
                value: minValue
            }, {
                value: maxValue
            }],
            legendPointerHeight: conf.outerRadius,
            legendPointerWidth: conf.innerRadius,
            outerRadius: conf.outerRadius,
            innerRadius: conf.innerRadius
        }, chart.chartInstance, [chart.id]);
    };

    function Slider (sliderIndex, options, id) {
        this.conf = options.conf;
        this.sliderIndex = sliderIndex;
        this.rangeGroup = options.sliderGroup;
        this._id = id;

        this.node = undefined;
        this.tracker = undefined;
        this.currPos = 0;
        this.swing = [];
    }

    Slider.prototype.constructor = Slider;

    Slider.prototype.updateSwingRange = function (index, value) {
        this.swing[+index] = value;
    };

    // @todo: Who should be responsible for reset, range or individual slider
    // Slider.prototype.reset = function () {
    //     var node = this.node,
    //         tracker = this.tracker,
    //         conf = this.conf,
    //         dragAPI;

    //     if (!node) {
    //         return;
    //     }

    //     node.attr({
    //         transform: 't0,0'
    //     });

    //     this.currPos = 0;
    //     this.swing = [];

    // };

    Slider.prototype.draw = function (rangeStart, scaleVal, position, options) {
        var layer = options.parentLayer,
            conf = this.conf,
            ocConf = conf.outerCircle,
            icConf = conf.innerCircle,
            ocRadius = Math.ceil((ocConf.rFactor * options.rCalcBase ) / 2),
            icRadius = Math.ceil((icConf.rFactor * options.rCalcBase ) / 2),
            icThickness = ocRadius - icRadius,
            group,
            rangeGroup = this.rangeGroup,
            sliderIndex = this.sliderIndex,
            dragAPI,
            strokeWidthOffset,
            x,
            y,
            tracker,
            instanceFn,
            iniRange,
            componentPool = options.componentPool,
            keys = componentPool.getKeys();

        conf.outerRadius = ocRadius;
        conf.innerRadius = icRadius;

        this._scaleVal = scaleVal;

        icConf.style['stroke-width'] = icThickness;
        strokeWidthOffset = Math.ceil(ocConf.style['stroke-width'] / 2);
        icRadius += strokeWidthOffset;

        instanceFn = componentPool.getComponent(this._id, keys.KEY_GROUP);
        group = this.node = instanceFn('fc-gl-slider', layer).attr({
            'cursor' : 'pointer',
            'transform': 't0,0'
        });


        if (options.key === 'x') {
            x = position;
            y = rangeStart;
            y += sliderIndex ? -(icRadius) : +icRadius;
            iniRange = y;
        } else {
            x = rangeStart;
            y = position;
            x += sliderIndex ? -(icRadius) : +icRadius;
            iniRange = x;
        }

        rangeGroup.initRange(this, iniRange);

        instanceFn = componentPool.getComponent(this._id, keys.KEY_CIRCLE, true);
        instanceFn(group).attr({
            cx: x,
            cy: y,
            r: ocRadius
        }).css(ocConf.style);
        instanceFn(group).attr({
            cx: x,
            cy: y,
            r: icRadius
        }).css(icConf.style);

        tracker = this.tracker = instanceFn(group).attr({
            cx: x,
            cy: y,
            r: ocRadius + 5,
            ishot: true,
            fill: TRACKER_FILL,
            stroke: 0,
            cursor: 'pointer'
        }).trackTooltip(conf.showTooltip ? true : false).tooltip(scaleVal, null, null, true);

        this._dragAPI = dragAPI = this.getDragAPI(options.key === 'x');

        tracker.undrag();
        tracker.drag(dragAPI.dragging, dragAPI.dragStart, dragAPI.dragEnd);

        return {
            translateAscending: ocRadius + strokeWidthOffset
        };
    };

    Slider.prototype.getDragAPI = function (verticalDragging) {
        var self = this,
            node = self.node,
            index = self.sliderIndex,
            range = self.rangeGroup,
            swing,
            lastDisplacement,
            timeoutId,
            innerRadius = self.conf.innerRadius,
            spaceSaved = innerRadius,
            isDragged;

        return {
            dragging : function () {
                var left,
                    right,
                    d,
                    event;

                event = arguments[4];
                event.stopPropagation();
                event.preventDefault();

                if (verticalDragging) {
                    d = arguments[1];
                } else {
                    d = arguments[0];
                }

                if (index) {
                    left = swing[0] - swing[1] + spaceSaved;
                    right = 0;
                } else {
                    left = 0;
                    right = swing[1] - swing[0] - spaceSaved;
                }

                if ((self.currPos + d) < left || (self.currPos + d) > right) {
                    return;
                }

                node.attr({
                    transform : verticalDragging ? 't0,' + (self.currPos + d) :
                            't' + (self.currPos + d) + ',' + 0
                });

                lastDisplacement = d;

                timeoutId && clearTimeout(timeoutId);
                timeoutId = setTimeout(function () {
                    range.updateWhenInRest(self, self.currPos + d);
                }, 100);

                self.tracker.tooltip(range.updateWhenInMove(self, self.currPos + d), null, null, true);
                isDragged = true;

                return true;
            },

            dragStart : function (x, y, event) {
                event.stopPropagation();
                event.preventDefault();

                node.attr({
                    transform : verticalDragging ? 't0,' + self.currPos :
                            't' + self.currPos + ',' + 0
                });

                swing = swing || self.swing;

                isDragged = false;

                range.dragStarted(self);
            },

            dragEnd : function () {
                var newPos;
                range.dragCompleted(self, isDragged, self.currPos + lastDisplacement);

                if (!isDragged) {
                    return;
                }

                timeoutId && clearTimeout(timeoutId);
                timeoutId = setTimeout(function () {
                    range.updateWhenInRest(self, self.currPos);
                }, 100);

                self.currPos += lastDisplacement;
                newPos = swing[+index] + self.currPos;
                range.updateRange(self, newPos);
            }
        };
    };


    function ColorRange (data, options, chart) {
        var numberFormatter = chart.components.numberFormatter,
            index,
            length,
            range,
            min,
            max,
            minRange,
            maxRange,
            minValue,
            maxValue,
            mapByPercent;

        this.data = data;
        this.options = options || {};
        mapByPercent = this.mapByPercent = !!data.mapByPercent;
        this.appender = '';

        min = this.mapByPercent ? 0 : options.min;
        max = this.mapByPercent ? 100 :  options.max;

        if (data.colorRange.length === 2) {
            minRange = data.colorRange[0];
            maxRange = data.colorRange[1];

            minValue = minRange.value = isInvalid(minRange.value) ? min : minRange.value;
            maxValue = maxRange.value = isInvalid(maxRange.value) ? max : maxRange.value;

            if (minValue === maxValue) {
                minValue = minRange.value = min;
                maxValue = maxRange.value = max;
            }

            minRange.displayValue = mapByPercent ? minValue + PERCENT_STR :  numberFormatter.legendValue(minValue);
            maxRange.displayValue = mapByPercent ? maxValue + PERCENT_STR :  numberFormatter.legendValue(maxValue);
        }

        if ((isInvalid(min) && isInvalid(minRange.value)) || (isInvalid(max) && isInvalid(minRange.value)) ||
            !data.gradient) {
            this._preparationGoneWrong = true;
        } else {
            this._preparationGoneWrong = false;
        }

        range = this.colorRange = data.colorRange.sort(function (m, n) { return m.value - n.value; });
        this.valueRatio = undefined;
        this.values = [];

        for (index = 0, length = range.length; index < length; index++) {
            this.values.push(range[index].value);
        }
    }

    ColorRange.prototype.constructor = ColorRange;

    ColorRange.prototype.getValueRatio = function () {
        var colorRange = this.colorRange,
            currentRange,
            index,
            length = colorRange.length,
            ratio = this.valueRatio,
            maxValue = colorRange[length - 1].value,
            minValue = colorRange[0].value,
            range = maxValue - minValue,
            itemValuePercent,
            lastValue = 0;

        if (ratio) {
            return ratio;
        }

        ratio = this.valueRatio = [];
        for (index = 0; index < length; index++) {
            currentRange = colorRange[index];
            itemValuePercent = (currentRange.value - minValue) / range;

            ratio.push((itemValuePercent - lastValue) * 100);
            lastValue = itemValuePercent;
        }

        return ratio;
    };

    ColorRange.prototype.getCumulativeValueRatio = function () {
        var colorRange = this.colorRange,
            currentRange,
            index,
            length = colorRange.length,
            firstValue = colorRange[0].value,
            lastValue = colorRange[length - 1].value,
            ratio = [];

        for (index = 0; index < length; index++) {
            currentRange = colorRange[index];
            ratio.push((currentRange.value - firstValue) / (lastValue - firstValue) * 100);
        }
        return ratio;
    };

    ColorRange.prototype.getBoxFill = function (isVertical) {
        var colorRange = this.colorRange,
            currentRange,
            index,
            length = colorRange.length,
            color = [],
            raphColorArg,
            angle;

        angle = isVertical ? 90 : 0;

        for (index = 0; index < length; index++) {
            currentRange = colorRange[index];
            color.push(currentRange.code);
        }

        raphColorArg = {
            FCcolor: {
                alpha: '100,100,100',
                angle: angle,
                color: color.join(COMMA_STR),
                ratio: this.getValueRatio().join(COMMA_STR)
            }
        };

        return toRaphaelColor(raphColorArg);
    };

    ColorRange.prototype.getColorByValue = function (nVal) {
        var valueArr = this.values,
            colorRange = this.colorRange,
            length,
            index,
            rangeOutSideColor,
            color;

        if (nVal === undefined || nVal === null) {
            return;
        }

        for (index = 0, length = valueArr.length; index < length; index++) {
            if (nVal === valueArr[index]) {
                color = colorRange[index].code;
                break;
            } else if (!index && nVal < valueArr[index]) {
                rangeOutSideColor = true;
                break;
            } else if (index === length - 1 && nVal > valueArr[index]) {
                rangeOutSideColor = true;
                break;
            }else if (nVal > valueArr[index] && nVal < valueArr[index + 1]) {
                color = getColorBetween(colorRange[index], colorRange[index + 1], nVal);
                break;
            }
        }

        if (rangeOutSideColor) {
            return;
        }

        return color;
    };


    function GradientLegend () {
        LegendBase.apply(this, arguments);
    }

    GradientLegend.prototype = Object.create(LegendBase.prototype);
    GradientLegend.prototype.constructor = GradientLegend;

    FusionCharts.register('component', ['gradientLegend', 'gradientLegend', {
        pIndex: 1,

        enabled: false,
        /*
         * Initializes the component.
         * Calling this would create instance of colorRange. Which can be used to access the api of the same.
         * Configure is called when the second level of init is called. The second level is explained below.
         *
         *
         * Example use
         * legend = new (FusionCharts.register('component',['gradientLegend', 'gradientLegend']))();
         *
         * 1st level - fn = legend.init({chart: chart});
         * 2nd level - fn({min: 100, max: 1000, maxOtherSide: 150});
         *
         * Or putting it together -  legend.init({chart: chart, dataExtremes: {min: 100, max: 1000, maxOtherSide: 150}})
         * colorRange = legend.colorRange
         *
         *
         * @param options {Object} - A simple key value pair needed for init.
         * {
         *      chart: chartInstance,
         *      dataExtremes: optional data extreme of the datasets in the form
         *          {
         *              max: maximum value,
         *              min: minimum value,
         *              maxOtherSide: Optional maximum other side measurement. This takes the maximum allowed height for
         *                  a horizontal legend and width for vertical legend.
         *          },
         * }
         *
         * @return {Function | undefined} - If the dataExtremes are provided return undefined, else returns a function
         *                                  where it is to be fed.
         */
        init: function (options) {
            var componentAPI = this,
                iapi = options.chart,
                dataExtremes,
                cr,
                nData,
                fcChart;

            /*
             * Performs 2nd level of initialization.
             * Injects the colorRange in the API object.
             *
             * @param de {Object} - A simple key value pair needed for 2nd level of init. See the above dataExtremes obj
             */
            function continueInit (de) {
                // Extracts raw FC Chart data and parse it to prepare data for colorRange. This kind of acts like a
                // adapter.
                componentAPI.data = options.chart.jsonData.colorrange;
                nData = componentAPI.nData = legendManager.legacyDataParser(componentAPI.data, de);

                if (!nData) {
                    // If no valid data is present, sets a flag not to draw the legend . This will be read by subsequent
                    // calls.
                    componentAPI._dontPlot = true;
                    return;
                }

                // Starts prepaeparing the drawOptions object which is needed during the final drawing and space
                // management.
                componentAPI.drawOptions = {
                    smartLabel: iapi.linkedItems.smartLabel,
                    colorRange: (componentAPI.colorRange = cr = new ColorRange(nData, de, fcChart)),
                    maxOtherSide: de.maxOtherSide
                };

                componentAPI._dontPlot = false;
                cr && cr._preparationGoneWrong && (componentAPI._dontPlot = true);

                componentAPI._recalculateLogicalSpace = true;

                // Parse all the legend releted attrs.
                componentAPI._configure();
            }

            // Initiates the legend manager by providing the access to the chart object.
            legendManager.init(options);

            // Saves the reference of chart for internal use, in case
            fcChart = componentAPI._chart = options.chart;
            componentAPI._cpool = componentPoolFactory(fcChart);

            if (!(dataExtremes = options.dataExtremes)) {
                // If the dataExtremes is not provided, return the function for 2nd level of init
                return continueInit;
            }

            // If provided perform the 2nd level of init internally by giving the feel to the user that init happened
            // in one single shot
            continueInit(dataExtremes);
        },

        /*
         * Parses all the FC attributes for gradient legend
         */
        _configure: function () {
            var componentAPI = this,
                chart = componentAPI._chart,
                chartAttrs = chart.jsonData.chart,
                conf = componentAPI.conf = {},
                outCanvasBaseFont = chartAttrs.outcnvbasefont,
                outCanvasBaseFontSize = chartAttrs.outcnvbasefontsize,
                outCanvasBaseFontColor = chartAttrs.outcnvbasefontcolor,
                labelStyle = chart.config.dataLabelStyle,
                fColor,
                fFamily,
                fSize,
                fWeight,
                cfColor,
                cfFamily,
                cfSize,
                cfWeight,
                axisBorderColor,
                axisBorderAlpha;

            conf.caption = pluck(chartAttrs.legendcaption);
            conf.legendPosition = pluck(chartAttrs.legendposition, 'bottom').toLowerCase();
            conf.showLegend = pluckNumber(chartAttrs.showlegend, 1);
            conf.interactiveLegend = pluckNumber(chartAttrs.interactivelegend, 1);
            conf.showLegendLabels = pluckNumber(chartAttrs.showlegendlabels, 1);

            fColor = chartAttrs.legenditemfontcolor || outCanvasBaseFontColor;
            fFamily = chartAttrs.legenditemfont || outCanvasBaseFont;
            fSize = chartAttrs.legenditemfontsize || outCanvasBaseFontSize;
            fWeight = pluckNumber(chartAttrs.legenditemfontbold, 0);

            cfColor = chartAttrs.legendcaptionfontcolor || outCanvasBaseFontColor;
            cfFamily = chartAttrs.legendcaptionfont || outCanvasBaseFont;
            cfSize = chartAttrs.legendcaptionfontsize || outCanvasBaseFontSize;
            cfWeight = pluckNumber(chartAttrs.legendcaptionfontbold, 1);

            axisBorderColor = chartAttrs.legendaxisbordercolor ?
                hashify(dehashify(chartAttrs.legendaxisbordercolor)) : undefined;

            axisBorderAlpha = axisBorderColor ? pluckNumber(chartAttrs.legendaxisborderalpha, 100) / 100 :
                undefined;

            // We do this like this so that, it becomes easy to override the default configuartion. The default conf was
            // created in this format.
            conf.axisTextItemConf = {
                style: {
                    fill: fColor ? convertColor(pluck(fColor)) : labelStyle.color,
                    fontFamily: fFamily ? pluck(fFamily) : labelStyle.fontFamily,
                    fontSize: fSize ? pluckNumber(fSize) : labelStyle.fontSize.match(/\d+/)[0],
                    fontWeight: fWeight ? 'bold' : labelStyle.fontWeight
                }
            };

            conf.legendCaptionConf = {
                style : {
                    fill: cfColor ? convertColor(pluck(cfColor)) : labelStyle.color,
                    fontFamily: cfFamily ? pluck(cfFamily) : labelStyle.fontFamily,
                    fontSize: cfSize ? pluckNumber(cfSize) : labelStyle.fontSize.match(/\d+/)[0],
                    fontWeight: cfWeight ? 'bold' : labelStyle.fontWeight,
                    fontStyle: 'normal'
                }
            };

            conf.legendAxisConf = {
                legendAxisHeight: 11,
                style : {
                    stroke: axisBorderColor,
                    'stroke-opacity': axisBorderAlpha
                },
                line: {
                    style: {
                        stroke: convertColor(pluck(chartAttrs.legendscalelinecolor, 'FFF8E9'),
                            pluckNumber(chartAttrs.legendscalelinealpha, 100)),
                        'stroke-width': pluckNumber(chartAttrs.legendscalelinethickness)
                    }
                }
            };

            conf.sliderGroupConf = {
                showTooltip: pluckNumber(chartAttrs.showtooltip, 1),
                outerCircle : {
                    rFactor: pluckNumber(chartAttrs.sliderdiameterfactor),
                    style: {
                        stroke: convertColor(pluck(chartAttrs.legendpointerbordercolor, '757575'),
                            pluckNumber(chartAttrs.legendpointerborderalpha, 100))
                    }
                },
                innerCircle : {
                    rFactor: pluckNumber(chartAttrs.sliderholediameterfactor),
                    style: {
                        stroke: convertColor(pluck(chartAttrs.legendpointercolor, 'FFFFFF'),
                            pluckNumber(chartAttrs.legendpointeralpha, 100))
                    }
                }
            };

            conf.legendCarpetConf = {
                spreadFactor : pluckNumber(chartAttrs.legendspreadfactor),
                allowDrag: !!pluckNumber(chartAttrs.legendallowdrag, 0),
                captionAlignment: pluck(chartAttrs.legendcaptionalignment, 'center'),
                style : {
                    'fill' : convertColor(pluck(chartAttrs.legendbgcolor, 'e4d9c1'),
                            pluckNumber(chartAttrs.legendbgalpha, 100)),
                    'stroke' : convertColor(pluck(chartAttrs.legendbordercolor, 'c4b89d'),
                            pluckNumber(chartAttrs.legendborderalpha, 100)),
                    'stroke-width': pluckNumber(chartAttrs.legendborderthickness, 1)
                }
            };
        },

        /*
         * This takes care of the instance creation of various component based on attrs. Dependency injection /
         * component injection is managed from here.
         * This is not meant to be called from outside. This gets called internally.
         */
        postConfigureInit : function () {
            var componentAPI = this,
                conf = componentAPI.conf,
                caption,
                carpet,
                axis,
                sGroup,
                gl,
                ovrdConf,
                ovrdTextConf,
                body,
                labels,
                values;

            // Container for the component instances.
            componentAPI.elem = {};

            // The details of the various components and their relationship is written at the top.

            if (conf.caption) {
                // If caption is present, create a instance of the same
                ovrdConf = merge(legendManager.getDefaultConf('legendCaptionConf'), conf.legendCaptionConf);
                caption = new LegendCaption(conf.caption, ovrdConf);
            }

            if (conf.interactiveLegend) {
                // If interactiveLegend is attr is present, creates the sliders of the legend.

                // Override the default conf with the user given one.
                ovrdConf = merge(legendManager.getDefaultConf('sliderGroupConf'), conf.sliderGroupConf);
                componentAPI.elem.sGroup = sGroup = new SliderGroup(ovrdConf);
                componentAPI.listeners && componentAPI.listeners.length > 0 &&
                    sGroup.registerListener.apply(sGroup, componentAPI.listeners);
            }

            ovrdConf = merge(legendManager.getDefaultConf('legendCarpetConf'), conf.legendCarpetConf);

            if (conf.legendPosition === 'bottom') {
                // If the legend to be placed at bottom

                // The reference side would be width and will be covered the complete canvasWidth.
                // The max of other side is given by maxOtherSide.
                // The margin is taken from canvasLeft
                componentAPI.drawOptions.refSideKey = 'canvasWidth';
                componentAPI.drawOptions.refOffsetKey = 'canvasLeft';

                // Creates a horizontal capet, axis, labels and values component
                carpet = new LegendCarpet(ovrdConf);

                ovrdTextConf = merge(legendManager.getDefaultConf('axisTextItemConf'), conf.axisTextItemConf);

                body = new LegendBody(componentAPI.drawOptions.colorRange,
                    legendManager.getDefaultConf('legendBodyConf'), ovrdTextConf);

                axis = new LegendAxis(merge(legendManager.getDefaultConf('legendAxisConf'), conf.legendAxisConf));

                conf.showLegendLabels && (labels = new LegendLabels(ovrdTextConf));
                values = new LegendValues(ovrdTextConf);
            } else {
                // If the legend to be placed at bottom

                // The reference side would be height and will be covered the complete canvasWidth.
                // The max of other side is given by maxOtherSide.
                // The margin is taken from canvasTop
                componentAPI.drawOptions.refSideKey = 'canvasHeight';
                componentAPI.drawOptions.refOffsetKey = 'canvasTop';

                ovrdTextConf = merge(legendManager.getDefaultConf('axisTextItemConf'), conf.axisTextItemConf);

                carpet = new VerticalLegendCarpet(ovrdConf);
                body = new VerticalLegendBody(componentAPI.drawOptions.colorRange,
                    legendManager.getDefaultConf('legendBodyConf'), ovrdTextConf);

                axis = new VerticalLegendAxis(merge(legendManager.getDefaultConf('legendAxisConf'),
                    conf.legendAxisConf));

                conf.showLegendLabels && (labels = new VerticalLegendLabels(ovrdTextConf));
                values = new VerticalLegendValues(ovrdTextConf);
            }

            // If the slider group is defined, inject as component. Slider group is component of axis.
            sGroup && axis.addCompositions(sGroup, compositionKeys.RANGE);

            // Adds component to the body if available
            labels && body.addCompositions(labels, compositionKeys.AXIS_LABEL);
            body.addCompositions(axis, compositionKeys.LEGEND_AXIS);
            body.addCompositions(values, compositionKeys.AXIS_VALUE);

            // Adds the body and the caption to the carpet
            caption && carpet.addCompositions(caption, compositionKeys.CAPTION);
            carpet.addCompositions(body, compositionKeys.LEGEND_BODY);

            // Finally creates the gradient legend.
            componentAPI.elem.gl = gl = new GradientLegend(carpet, componentAPI._cpool);
        },

        notifyWhenUpdate: function (fn, context, params) {
            var componentAPI = this,
                rGroup;

            rGroup = componentAPI.elem && componentAPI.elem.sGroup;
            if (rGroup) {
                rGroup.registerListener(fn, context, params);
            } else {
                componentAPI.listeners = [fn, context, params];
            }
        },

        dispose: function () {
            var componentAPI = this;

            componentAPI.elem && componentAPI.elem.gl && componentAPI.elem.gl.dispose();
            componentAPI.elem = {};
        },

        getLogicalSpace: function (maxOtherSide) {
            var componentAPI = this,
                conf = componentAPI.conf,
                zeroArea = {
                    height: 0,
                    width: 0
                },
                drawOptions = componentAPI.drawOptions,
                refSideKey,
                chart = componentAPI._chart,
                refOffsetKey;

            // @todo redundancy in calculating the reference side. Make it from a organized procedure call.
            if (!componentAPI._recalculateLogicalSpace) {
                refSideKey = drawOptions.refSideKey;
                refOffsetKey = drawOptions.refOffsetKey;

                componentAPI.drawOptions.refSide = chart.config[refSideKey];
                componentAPI.drawOptions.refOffset = chart.config[refOffsetKey];

                (componentAPI._logicalArea = componentAPI.elem.gl.getLogicalSpace(componentAPI.drawOptions, true));
                return componentAPI._logicalArea || zeroArea;
            }

            if (componentAPI._dontPlot) {
                return zeroArea;
            }

            componentAPI._recalculateLogicalSpace = false;
            componentAPI.postConfigureInit();

            if (!conf.showLegend) {
                return zeroArea;
            }

            refSideKey = drawOptions.refSideKey;
            refOffsetKey = drawOptions.refOffsetKey;

            componentAPI.drawOptions.refSide = chart.config[refSideKey];
            componentAPI.drawOptions.refOffset = chart.config[refOffsetKey];

            componentAPI.drawOptions.maxOtherSide = maxOtherSide || componentAPI.drawOptions.maxOtherSide;
            return componentAPI.elem.gl &&
                (componentAPI._logicalArea = componentAPI.elem.gl.getLogicalSpace(componentAPI.drawOptions, true));
        },

        resetLegend: function() {
            var componentAPI = this,
                rGroup;

            rGroup = componentAPI.elem && componentAPI.elem.sGroup;
            if (rGroup) {
                rGroup.reset();
            }
        },

        clearListeners: function () {
            var componentAPI = this,
                rGroup;

            rGroup = componentAPI.elem && componentAPI.elem.sGroup;
            if (rGroup) {
                rGroup.clearListeners();
            }
        },

        draw: function (x, y, options) {
            var componentAPI = this,
                conf = componentAPI.conf,
                measurement,
                node;

            if (componentAPI._dontPlot) {
                return;
            }

            componentAPI._cpool.init(options.paper);

            if (!conf.showLegend) {
                componentAPI.enabled  = false;
                return;
            }

            componentAPI.drawOptions.paper = options.paper;
            componentAPI.drawOptions.parentGroup = options.parentGroup;
            componentAPI.drawOptions.x = x;
            componentAPI.drawOptions.y = y;
            componentAPI.drawOptions.maxOtherSide = componentAPI.drawOptions.maxOtherSide || options.maxOtherSide;

            node = componentAPI.elem.gl.draw(componentAPI.drawOptions);
            measurement = node.getBBox();

            conf.xPos = measurement.x;
            conf.yPos = measurement.y;
            conf.height = measurement.height;
            conf.width = measurement.width;

            componentAPI.enabled = true;
        }

    }]);
}]);

/**!
 * @license FusionCharts JavaScript Library
 * Copyright FusionCharts Technologies LLP
 * License Information at <http://www.fusioncharts.com/license>
 *
 * @version 3.12.0
 */
/**
 * @private
 * @module fusioncharts.renderer.javascript.msstepline
 */
FusionCharts.register('module', ['private', 'modules.renderer.js-msstepline', function() {
    var global = this,
        lib = global.hcLib,
        win = global.window,
        creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname),
        COMPONENT = 'component',
        DATASET = 'dataset',
        chartAPI = lib.chartAPI,
        pluckNumber = lib.pluckNumber,
        pluck = lib.pluck,
        Image = win.Image,
        preDefStr = lib.preDefStr,
        schedular = lib.schedular,
        LINE = preDefStr.line,
        toRaphaelColor = lib.toRaphaelColor,
        getFirstValue = lib.getFirstValue,
        configStr = preDefStr.configStr,
        animationObjStr = preDefStr.animationObjStr,
        dataLabelStr = preDefStr.dataLabelStr,
        BLANKSTRING = lib.BLANKSTRING,
        hiddenStr = preDefStr.hiddenStr,
        SETROLLOVERATTR = 'setRolloverAttr',
        SETROLLOUTATTR = 'setRolloutAttr',
        math = Math,
        mathMax = math.max,
        hasTouch = lib.hasTouch,
        TOUCH_THRESHOLD_PIXELS = lib.TOUCH_THRESHOLD_PIXELS,
        CLICK_THRESHOLD_PIXELS = lib.CLICK_THRESHOLD_PIXELS,
        HTP = hasTouch ? TOUCH_THRESHOLD_PIXELS : CLICK_THRESHOLD_PIXELS,
        M = 'M',
        H = 'H',
        V = 'V',
        ROUND = preDefStr.ROUND,
        miterStr = preDefStr.miterStr,
        UNDEFINED,
        NORMALSTRING = 'normal';

    chartAPI('msstepline', {
        friendlyName: 'Multi-series Step Line Chart',
        standaloneInit: true,
        creditLabel: creditLabel,
        defaultDatasetType: 'msstepline',
        defaultPlotShadow: 1,
        applicableDSList: {'msstepline': true}
    }, chartAPI.mscartesian, {
        drawverticaljoins: 1,
        useforwardsteps: 1,
        zeroplanethickness: 1,
        zeroplanealpha: 40,
        showzeroplaneontop: 0,
        enablemousetracking: true
    }, chartAPI.areabase);

    FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-group-msstepline',
        function () {
            var COMPONENT = 'component',
                DATASET_GROUP = 'datasetGroup';

            FusionCharts.register(COMPONENT, [DATASET_GROUP, 'msstepline', {
            },'line']);
        }
    ]);

    FusionCharts.register(COMPONENT, [DATASET, 'MSStepLine', {
        type: 'msstepline',
        _addLegend: function () {
            var dataset = this,
                chart = dataset.chart,
                conf = dataset.config,
                legend = chart.components.legend,
                drawAnchors = pluckNumber(conf.drawanchors, 1),
                config = {
                    enabled: conf.includeinlegend,
                    type : LINE,
                    /* In case of scatter (a child chartAPI of line),
                    line is drawn in legend only when drawLine is set
                    to true. */
                    drawLine: pluck(conf.drawLine, true),
                    fillColor : toRaphaelColor({
                        color: conf.anchorbgcolor,
                        alpha: conf.anchorbgalpha
                    }),
                    strokeColor: toRaphaelColor({
                        color: conf.anchorbordercolor,
                        alpha: '100'
                    }),
                    rawFillColor: conf.anchorbgcolor,
                    rawStrokeColor: conf.anchorbordercolor,
                    anchorSide: drawAnchors ? conf.anchorsides : 0,
                    strokeWidth: conf.anchorborderthickness,
                    label : getFirstValue(dataset.JSONData.seriesname),
                    lineWidth: conf.linethickness
                };
            dataset.legendItemId = legend.addItems(dataset, dataset.legendInteractivity, config);
        },
        draw: function () {// retrive requitrd objects
            var dataSet = this,
                JSONData = dataSet.JSONData,
                chart = dataSet.chart,
                jobList = chart.getJobList(),
                chartComponents = chart.components,
                conf = dataSet.config,
                datasetIndex = dataSet.index || dataSet.positionIndex,
                chartConfig = chart.config,
                len,
                i,
                paper = chartComponents.paper,
                xAxis = chartComponents.xAxis[0],
                yAxis = dataSet.yAxis,
                xPos,
                yPos,
                layers = chart.graphics,
                dataLabelsLayer = layers.datalabelsGroup,
                toolText,
                label,
                setElement,
                hotElement,
                setLink,
                setValue,
                eventArgs,
                displayValue,
                dataStore = dataSet.components.data,
                dataObj,
                setRolloutAttr,
                setRolloverAttr,
                removeDataArr = dataSet.components.removeDataArr || [],
                removeDataArrLen = removeDataArr.length,
                lineThickness = conf.linethickness,
                container = dataSet.graphics.container,
                connectNullData = chartConfig.connectnulldata,
                group = layers.datasetGroup,
                hoverEffects,
                shadow = conf.shadow,
                anchorShadow,
                dataLabelContainer = dataSet.graphics.dataLabelContainer,
                anchorProps = {},
                imgRef,
                symbol,
                config,
                animationObj = chart.get(configStr, animationObjStr),
                dummyAnimElem = animationObj.dummyObj,
                dummyAnimObj = animationObj.animObj,
                animationDuration = animationObj.duration,
                pool = dataSet.components.pool || [],
                showValue,
                pathAttr,
                EVENTARGS = 'eventArgs',
                /*
                    Called when transpose animation is completed
                    for hiding the dataset
                */
                animCallBack = function() {
                    if (dataSet.visible === false && (dataSet._conatinerHidden === false ||
                            dataSet._conatinerHidden=== undefined)) {
                        container.lineGroup.hide();
                        container.lineShadowGroup.hide();
                        container.anchorShadowGroup.hide();
                        container.anchorGroup.hide();
                        dataLabelContainer && dataLabelContainer.hide();
                        dataSet._conatinerHidden = true;
                    }
                },
                /*
                    Called when the initial animation compeletes
                    for showing the dataset
                */
                initAnimCallBack = function () {
                    group.lineConnector.attr({
                        'clip-rect': null
                    });
                    // fix for ie11
                    group.lineConnector.node && group.lineConnector.node.removeAttribute('clip-path');
                    if (dataSet.visible !== false) {
                        container.lineShadowGroup.show();
                        container.anchorShadowGroup.show();
                        container.anchorGroup.show();
                        dataLabelContainer && dataLabelContainer.show();
                    }
                    // animCompleteFn();
                },
                animFlag = true,
                setTooltext,
                connector,
                dashStyle,
                yBase = yAxis.getAxisBase(),
                yBasePos = yAxis.yBasePos = yAxis.getAxisPosition(yBase),
                clipConf = chartComponents.canvas.config.clip,
                clipCanvasInit = clipConf['clip-canvas-init'].slice(0),
                clipCanvas = clipConf['clip-canvas'].slice(0),
                lineDashStyle = conf.lineDashStyle,
                lineColorObj = {
                    color: conf.linecolor,
                    alpha: conf.alpha
                },
                setColor,
                setDashStyle,
                lineSegmentChange,
                colorObj,
                linePath = [],
                lscthash,
                lineDrawing = 0,
                mainLinePath = [],
                lastYPos = null,
                lastXPos,
                lastMoveCommand = [],
                initialAnimation = false,
                connectorShadow,
                MAX_MITER_LINEJOIN = 2,
                cosmeticAttrs,
                lineElement = dataSet.graphics.lineElement,
                visible = dataSet.visible,
                drawVerticalJoins = conf.drawverticaljoins,
                useForwardSteps = conf.useforwardsteps,
                labelElement,
                imageElement,
                polypath,
                animType = animationObj.animType,
                isNewElem,
                noOfImages = 0,
                catLabel,
                halfStep = chart.config.stepatmiddle ? xAxis.getPVR() * 0.5 : 0,
                radius,
                borderThickness,
                topAnchorPos,
                bottomAnchorPos,
                canvasTop = chartConfig.canvasTop,
                canvasBottom = chartConfig.canvasBottom;

            conf.imagesLoaded = 0;
            /*
             * Creating lineConnector group and appending it to dataset layer if not created
             * Lineconnector group has the anchorgroups of all datasets
             */
            group.lineConnector = group.lineConnector ||
                paper.group('line-connector', group);
            // Create dataset container if not created
            if (!container) {
                container = dataSet.graphics.container = {
                    lineShadowGroup: paper.group('connector-shadow', group.lineConnector),
                    anchorShadowGroup: paper.group('anchor-shadow', group.lineConnector),
                    lineGroup: paper.group(LINE, group.lineConnector),
                    anchorGroup: paper.group('anchors', group.lineConnector)
                };
                if (!visible) {
                    container.lineShadowGroup.hide();
                    container.anchorShadowGroup.hide();
                    container.lineGroup.hide();
                    container.anchorGroup.hide();
                }

            }

            if (!dataStore) {
                dataStore = dataSet.components.data = [];
            }

            if (!dataLabelContainer) {
                dataLabelContainer = dataSet.graphics.dataLabelContainer = dataSet.graphics.dataLabelContainer ||
                    paper.group(dataLabelStr, dataLabelsLayer);
                if (!visible) {
                    dataLabelContainer.hide();
                }
            }

            if (visible) {
                container.lineShadowGroup.show();
                container.anchorShadowGroup.show();
                container.lineGroup.show();
                container.anchorGroup.show();
                dataLabelContainer.show();
            }
            len = xAxis.getCategoryLen();
            //create plot elements
            for (i=0; i<len; i++) {
                dataObj = dataStore[i];
                if (!dataObj) {
                    continue;
                }
                config = dataObj.config;
                setValue = config.setValue;
                setLink  = config.setLink;
                setTooltext = config.setLevelTooltext;
                showValue = config.showValue;
                anchorProps = config.anchorProps;
                symbol = anchorProps.symbol;
                anchorShadow = anchorProps.shadow;
                displayValue = config.displayValue;
                setElement = dataObj.graphics.element;
                imageElement = dataObj.graphics.image;
                hotElement = dataObj.graphics.hotElement;
                labelElement = dataObj.graphics.label;
                // Creating the data object if not created
                if (!dataObj) {
                    dataObj = dataStore[i] = {
                        graphics : {}
                    };
                }
                // If value is null
                if (setValue === null) {
                    lastMoveCommand.length = 0;
                    if (!connectNullData) {
                        lastYPos = null;
                    }
                    setElement && setElement.hide();
                    imageElement && imageElement.hide();
                    labelElement && labelElement.hide();
                    hotElement && hotElement.hide();
                }
                else {
                    // Storing the color Object of this data
                    colorObj = {
                        color: config.color,
                        alpha: config.alpha
                    };
                    dashStyle = config.dashStyle;
                    xPos = xAxis.getAxisPosition(i);
                    // On hiding a dataset the y position of the hidden dataset is set to yBasePos
                    if (!dataSet.visible && animationDuration) {
                        yPos = yBasePos;
                    }
                    else {
                        yPos = yAxis.getAxisPosition(setValue);
                    }
                    hoverEffects = config.hoverEffects;
                    anchorProps.isAnchorHoverRadius = hoverEffects.anchorRadius;

                    radius = anchorProps.radius;
                    borderThickness = anchorProps.borderThickness;

                    topAnchorPos = yPos - radius - (borderThickness / 2);
                    bottomAnchorPos = yPos + radius + (borderThickness / 2);

                    topAnchorPos < canvasTop && (chartConfig.toleranceTop = mathMax(chartConfig.toleranceTop || 0,
                        canvasTop - topAnchorPos));
                    bottomAnchorPos > canvasBottom && (chartConfig.toleranceBottom = mathMax(
                        chartConfig.toleranceBottom || 0, bottomAnchorPos - canvasBottom));

                    label = config.label;
                    catLabel = xAxis.getLabel(i);

                    if (!chartConfig.showtooltip) {
                        toolText = BLANKSTRING;
                    }
                    else {
                        toolText = config.toolText + (setTooltext ? BLANKSTRING : config.toolTipValue);
                    }

                    config.finalTooltext = toolText;

                    eventArgs = config.eventArgs || (config.eventArgs = {});
                    // Storing the event arguments
                    eventArgs.index = i;
                    eventArgs.link = setLink;
                    eventArgs.value = setValue;
                    eventArgs.displayValue = displayValue;
                    eventArgs.categoryLabel = catLabel;
                    eventArgs.toolText = toolText;
                    eventArgs.id = conf.userID;
                    eventArgs.datasetIndex = datasetIndex;
                    eventArgs.datasetName = JSONData.seriesname;
                    eventArgs.visible = visible;

                    isNewElem = false;
                    // If imageurl is present
                    if (anchorProps.imageUrl) {
                        config.anchorImageLoaded = false;
                        dataObj._xPos = xPos;
                        dataObj._yPos = yPos;
                        imgRef = new Image();
                        imgRef.onload = this._onAnchorImageLoad(dataSet, i, eventArgs, xPos, yPos);
                        imgRef.onerror = this._onErrorSetter(dataSet, i);
                        imgRef.src = anchorProps.imageUrl;
                        noOfImages++;
                    }
                    else {
                        imageElement && imageElement.hide();
                        polypath = [symbol[1] || 2, xPos, yPos,
                            anchorProps.radius, anchorProps.startAngle, anchorProps.dip];
                        cosmeticAttrs = {
                            fill: toRaphaelColor({
                                color: anchorProps.bgColor,
                                alpha: anchorProps.bgAlpha
                            }),
                            stroke: toRaphaelColor({
                                color: anchorProps.borderColor,
                                alpha: anchorProps.borderAlpha
                            }),
                            'stroke-width': anchorProps.borderThickness,
                            visibility: !anchorProps.radius ? hiddenStr : visible
                        };
                        // Create anchor element if not created
                        if (!setElement) {
                            if (pool.element && pool.element.length) {
                                setElement = dataObj.graphics.element = pool.element.shift();
                            }
                            else {
                                isNewElem = true;
                                setElement = dataObj.graphics.element = paper.polypath(container.anchorGroup);
                                setElement.attr({
                                    polypath: polypath
                                });
                            }
                        }

                        setElement.show().animateWith(dummyAnimElem, dummyAnimObj, {
                            polypath: polypath
                        }, animationDuration, animType,  animFlag && animCallBack);

                        setElement.attr(cosmeticAttrs)
                        .shadow(anchorShadow, container.anchorShadowGroup)
                        .data('hoverEnabled', hoverEffects.enabled)
                        .data(EVENTARGS,eventArgs);
                        animFlag = false;
                    }

                    connector = dataObj.graphics.connector;
                    if (hoverEffects.enabled) {
                        setRolloverAttr = {
                            polypath: [hoverEffects.anchorSides || 2,
                                        xPos, yPos,
                                        hoverEffects.anchorRadius,
                                        hoverEffects.startAngle,
                                        hoverEffects.dip
                                    ],
                            fill: toRaphaelColor({
                                color: hoverEffects.anchorColor,
                                alpha: hoverEffects.anchorBgAlpha
                            }),
                            stroke: toRaphaelColor({
                                color: hoverEffects.anchorBorderColor,
                                alpha: hoverEffects.anchorBorderAlpha
                            }),
                            'stroke-width': hoverEffects.anchorBorderThickness
                        };
                        setRolloutAttr = {
                            polypath: [anchorProps.sides, xPos, yPos,
                                        anchorProps.radius, anchorProps.startAngle, 0
                                    ],
                            fill: toRaphaelColor({
                                color: anchorProps.bgColor,
                                alpha: anchorProps.bgAlpha
                            }),
                            stroke: toRaphaelColor({
                                color: anchorProps.borderColor,
                                alpha: anchorProps.borderAlpha
                            }),
                            'stroke-width': anchorProps.borderThickness
                        };
                        setElement && setElement
                        .data('anchorRadius', anchorProps.radius)
                        .data('anchorHoverRadius', hoverEffects.anchorRadius)
                        .data('hoverEnabled', hoverEffects.enabled)
                        .data(SETROLLOVERATTR, setRolloverAttr)
                        .data(SETROLLOUTATTR, setRolloutAttr)
                        .data(EVENTARGS,eventArgs);
                    }

                    config.trackerConfig || (config.trackerConfig = {});

                    config.trackerConfig.trackerRadius = mathMax(anchorProps.radius,
                        hoverEffects && hoverEffects.anchorRadius || 0, HTP) +
                        ((anchorProps.borderThickness || 0) / 2);
                    // // anchor Radius of hot element is set to maximum of hover radius and anchor radius
                    // anchorRadius = mathMax(anchorProps.radius,
                    //     hoverEffects &&
                    //     hoverEffects.anchorRadius || 0, HTP);

                    /*
                        if colorObj and dash style of this data is different from
                        the previous data then a new line segment is to be created
                    */
                    lineSegmentChange = (lscthash !== [
                        toRaphaelColor(colorObj || lineColorObj),
                        dashStyle || lineDashStyle
                    ].join(':'));
                    // If the y position of the last value is not null
                    if (lastYPos !== null) {
                        if (lastMoveCommand.length) {
                            linePath = linePath.concat(lastMoveCommand);
                            lastMoveCommand.length = 0;
                        }
                        // move to the starting position of the line segment
                        if (!linePath.join(BLANKSTRING)) {
                            linePath.push(M, lastXPos, lastYPos);
                        }
                        if (useForwardSteps) {
                            linePath.push(H, xPos - halfStep);
                            if (drawVerticalJoins) {
                                linePath.push(V, yPos);
                            }
                            else {
                                linePath.push(M, xPos - halfStep, yPos);
                            }
                            if (halfStep) {
                                linePath.push(H, xPos);
                            }
                        }
                        else {
                            if (drawVerticalJoins) {
                                linePath.push(V, yPos);
                            }
                            else {
                                linePath.push(M, lastXPos, yPos);
                            }
                            linePath.push(H, xPos);
                        }
                        // If a new line segment is to be created
                        if (lineSegmentChange) {
                            // If a connector path is to drawn
                            if (!lineDrawing) {
                                if (!connector) {
                                    connector = dataObj.graphics.connector = paper.path(linePath,
                                        container.lineGroup);
                                    initialAnimation = true;
                                }

                                connector.animateWith(dummyAnimElem, dummyAnimObj, {
                                    path: linePath
                                }, animationDuration, animType, animFlag && animCallBack);

                                connector.attr({
                                    'stroke-dasharray': setDashStyle,
                                    'stroke-width': lineThickness,
                                    'stroke': setColor,
                                    'stroke-linecap': ROUND,
                                    'stroke-linejoin': lineThickness >
                                        MAX_MITER_LINEJOIN ? ROUND : miterStr
                                })
                                .shadow(connectorShadow, container.lineShadowGroup);
                                animFlag = false;

                            }
                            // Else appending the path to main Line path
                            else {
                                mainLinePath = mainLinePath.concat(linePath);
                            }
                            linePath = [];
                        }
                        // Hide the unused disjoint lines and push it to pool for reusing it next time when new
                        // disjoint lines will be drawn
                        if (!lineSegmentChange) {
                            if (connector) {
                                connector.hide();
                            }
                        }
                    } else {
                        // Pushing the x  y position of move command to lastMoveCommand array
                        lastMoveCommand.push(M, xPos, yPos);
                    }
                    // Storing the xPos and yPos of this data for next iterations
                    lastXPos = xPos;
                    lastYPos = yPos;
                    setColor = toRaphaelColor(colorObj || lineColorObj);
                    if (colorObj) {
                        connectorShadow = {
                            opacity: colorObj && colorObj.alpha/100
                        };
                    }
                    else {
                        connectorShadow = shadow;
                    }
                    setDashStyle = dashStyle || lineDashStyle;
                    /*If color,alpha or dashed is not defined for this data
                    then line drawing is set to 1 so the path of this data is
                    appended to mainLinePath and not the connector path
                    */
                    if (pluck(config.color, config.alpha, config.dashed) === UNDEFINED) {
                        lineDrawing = 1;
                    }
                    else {
                        lineDrawing = 0;
                    }
                    lscthash = [setColor, setDashStyle].join(':');
                    /*Storing the x position and y position in dataObject for future reference
                    For example - when drawing labels we need this xPos and yPos
                    */
                    dataObj._xPos = xPos;
                    dataObj._yPos = yPos;

                    !anchorProps.imageUrl && this.drawLabel(i);
                }
            }

            conf.noOfImages = conf.totalImages = noOfImages;

            if (noOfImages === 0) {
                jobList.labelDrawID.push(schedular.addJob(dataSet.drawLabel, dataSet, [],
                    lib.priorityList.label));
            }


            if (linePath.length) {
                mainLinePath = mainLinePath.concat(linePath);
            }
            pathAttr = {
                path: mainLinePath
            };
            cosmeticAttrs = {
                'stroke-dasharray': lineDashStyle,
                'stroke-width': lineThickness,
                'stroke': toRaphaelColor(lineColorObj),
                'stroke-linecap': ROUND,
                /*  for lines even with thickness as 2 we need to have round line join
                    otherwise the line join may look like exceeding the correct position
                */
                'stroke-linejoin': lineThickness >= MAX_MITER_LINEJOIN ? ROUND : miterStr
            };
            if (!lineElement) {
                lineElement = dataSet.graphics.lineElement = paper.path({
                    path: mainLinePath
                }, container.lineGroup);
                initialAnimation = true;
            }

            lineElement.show().animateWith(dummyAnimElem, dummyAnimObj,
                pathAttr, animationDuration, animType, animFlag && animCallBack);

            lineElement.attr(cosmeticAttrs)
                .shadow(shadow, container.lineShadowGroup);
            animFlag = false;

            if (animationDuration && visible && initialAnimation) {
                container.anchorGroup.hide();
                container.lineShadowGroup.hide();
                container.anchorShadowGroup.hide();
                dataLabelContainer.hide();
                group.lineConnector.attr({
                    'clip-rect': clipCanvasInit
                })
                .animateWith(dummyAnimElem, dummyAnimObj, {
                    'clip-rect': clipCanvas
                }, animationDuration, NORMALSTRING, initAnimCallBack);
            }
            for (i = 0; i < removeDataArrLen; i++) {
                dataSet._removeDataVisuals(removeDataArr.shift());
            }
            dataSet.drawn = true;
        }
    }, LINE, {
        drawverticaljoins : undefined,
        useforwardsteps : undefined
    }]);
}]);

/**!
 * @license FusionCharts JavaScript Library
 * Copyright FusionCharts Technologies LLP
 * License Information at <http://www.fusioncharts.com/license>
 *
 * @version 3.12.0
 */
/**
 * @private
 * @module fusioncharts.renderer.javascript.powercharts
 * @requires fusioncharts.renderer.javascript.msstepline
 * @requires fusioncharts.renderer.javascript.legend-gradient
 * @requires fusioncharts.renderer.javascript.js-component-toolbox
 * @export fusioncharts.powercharts.js
 */
FusionCharts.register('module', ['private', 'modules.renderer.js-powercharts',
	function() {
		// Adding FC_ChartUpdated event to eventList
        // for dragCharts
        var global = this,
            lib = global.hcLib,
            R = lib.Raphael,
            pluckNumber = lib.pluckNumber,
            math = Math,
            mathSin = math.sin,
            mathCos = math.cos,
            mathPI = math.PI,
            deg2rad = mathPI / 180,
            M = 'M',
            L = 'L',
            Z = 'Z',
            A = 'A',
            getArcPath = function(cX, cY, startX, startY, endX, endY, rX, rY, isClockWise, isLargeArc) {
                return [A, rX, rY, 0, isLargeArc, isClockWise, endX, endY];
            };

        lib.eventList.chartupdated = 'FC_ChartUpdated';
        lib.eventList.dataposted = 'FC_DataPosted';
        lib.eventList.dataposterror = 'FC_DataPostError';
        lib.eventList.datarestored = 'FC_DataRestored';

        // Add custom symbol to Raphael
        R.addSymbol({
            resizeIcon: function(x, y, radius) {
                var
                LINE_GAP = pluckNumber(radius, 15) / 3,
                    LINE_DIS = 3,
                    paths = [],
                    i;

                if (LINE_GAP < 0) {
                    LINE_GAP = -LINE_GAP;
                    radius = -radius;
                    x += radius - LINE_GAP / 2;
                    y += radius - LINE_GAP / 2;
                }

                for (i = 3; i > 0; i -= 1) {
                    paths.push(M, x - LINE_GAP * i, y - LINE_DIS,
                        L, x - LINE_DIS, y - LINE_GAP * i);
                }
                return paths;
            },
            closeIcon: function(x, y, r) {
                var
                icoX = x,
                    icoY = y,
                    rad = r * 1.3,
                    startAngle = 43 * deg2rad,
                    // to prevent cos and sin of start and end from becoming
                    // equal on 360 arcs
                    endAngle = 48 * deg2rad,
                    startX = icoX + rad * mathCos(startAngle),
                    startY = icoY + rad * mathSin(startAngle),
                    endX = icoX + rad * mathCos(endAngle),
                    endY = icoY + rad * mathSin(endAngle),
                    paths,
                    r1 = 0.71 * (r - 2), //(r - 2) * 0.5,
                    r2 = 0.71 * (r - 2), //(r - 2) * 0.87,

                    arcPath = getArcPath(icoX, icoY, startX, startY, endX,
                        endY, rad, rad, 0, 1);

                paths = [M, startX, startY];
                paths = paths.concat(arcPath);
                paths = paths.concat([
                    M, x + r1, y - r2,
                    L, x - r1, y + r2,
                    M, x - r1, y - r2,
                    L, x + r1, y + r2
                ]);

                return paths;
            },
            configureIcon: function(x, y, r) {
                r = r - 1;
                var k = 0.5,
                    l = 0.25,
                    r1 = r * 0.71,
                    r2 = (r + 2) * 0.71,
                    x1 = x - r,
                    y1 = y - r,
                    x2 = x + r,
                    y2 = y + r,
                    x3 = x + k,
                    y3 = y + k,
                    x4 = x - k,
                    y4 = y - k,

                    x5 = x1 - 2,
                    y5 = y1 - 2,
                    x6 = x2 + 2,
                    y6 = y2 + 2,
                    x7 = x + r1,
                    y7 = y + r1,
                    x8 = x - r1,
                    y8 = y - r1,
                    x9 = x + r2,
                    y9 = y + r2,
                    x10 = x - r2,
                    y10 = y - r2,
                    paths;

                paths = [M, x1, y3, L, x5, y3, x5, y4, x1, y4,
                    x8 - l, y8 + l, x10 - l, y10 + l, x10 + l, y10 - l, x8 + l, y8 - l,
                    x4, y1, x4, y5, x3, y5, x3, y1,
                    x7 - l, y8 - l, x9 - l, y10 - l, x9 + l, y10 + l, x7 + l, y8 + l,
                    x2, y4, x6, y4, x6, y3, x2, y3,
                    x7 + l, y7 - l, x9 + l, y9 - l, x9 - l, y9 + l, x7 - l, y7 + l,
                    x3, y2, x3, y6, x4, y6, x4, y2,
                    x8 + l, y7 + l, x10 + l, y9 + l, x10 - l, y9 - l, x8 - l, y7 - l, Z
                ];
                return paths;
            },
            axisIcon: function(x, y, r) {
                r = r - 1;
                var r1 = r * 0.33,
                    r2 = r / 2,
                    x1 = x - r,
                    y1 = y - r,
                    x2 = x + r2,
                    y2 = y + r,
                    x3 = x - r2,
                    y3 = y + r1,
                    y4 = y - r1,
                    paths;

                paths = [M, x1, y1, L, x2, y1, x2, y2, x1, y2, M, x3, y3, L, x2, y3,
                    M, x3, y4, L, x2, y4
                ];
                return paths;
            },
            loggerIcon: function(x, y, r) {
                r = r - 1;
                x = x - r;
                y = y - r;
                var r2 = r * 2,
                    x1 = x + r2,
                    x2 = x + 2,
                    x3 = x1 - 2,
                    y1 = y + 2,
                    y2 = y1 + r,
                    y3 = y2 + 2,
                    paths;

                paths = [M, x, y, L, x1, y, x1, y1, x3, y1, x3, y2, x1, y2, x1, y3,
                    x, y3, x, y2, x2, y2, x2, y1, x, y1, x, y
                ];
                return paths;
            }
        });

        global.addEventListener('rendered', function(event) {
            var chartObj = event.sender,
                state = chartObj.__state,
                iapi = chartObj.jsVars && chartObj.jsVars.instanceAPI;
            if (chartObj.disposed) {
                return;
            }
            if (!state.listenersAdded && iapi && typeof iapi.getCollatedData === 'function') {
                chartObj.addEventListener(['chartupdated', 'dataupdated', 'rendered'], function(event) {
                    delete event.sender.__state.hasStaleData;
                });
                state.listenersAdded = true;
            }
        });
	}
]);

/* jshint ignore: start */
FusionCharts.register ('module', ['private', 'modules.renderer.js-spline', function () {
    var global = this,
        lib = global.hcLib,
        win = global.window,
        math = Math,
        mathRound = math.round,
        creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
        chartAPI = lib.chartAPI;

    chartAPI('spline', {
        friendlyName: 'Spline Chart',
        standaloneInit: true,
        singleseries: true,
        creditLabel: creditLabel,
        defaultDatasetType: 'msspline',
        defaultPlotShadow: 1,
        applicableDSList: {'spline': true},
        /**
         * getSplineExtremities is called to get back the maximum and minimum y values of the vertical envelope
         * of a spline. The data may contain null data values, to be tackled based on the connectNullData setting.
         * For connectNullData = 0, the curve splits into separate spline curves, to be tackled via recursivion,
         * as below. The parameters index and limits are left blank for the initial call to this method, used only
         * for recursion, tackled from within the method.
         */
        getSplineExtremities: function (data, chartWidth, connectNullData, index, limits) {
            // array to hold the pertinent data only, required for gradients' calculations
            var arrKnot = [],
                validValueFound = false,
                u = index || 0,
                chart = this;

            limits = limits || { max: Number.MIN_VALUE, min: Number.MAX_VALUE };

            // populating arrKnot with pertinent data by iterating and checking
            for (; u < data.length; ++u) {

                // checking for if the first valid data value is found
                if (!validValueFound) {
                    // if data value is valid
                    if (!isNaN (data[u].config.setValue) && data[u].config.setValue !== null) {
                        validValueFound = true;
                    // just ingore the null/invalid data value, for the first valid data value is yet to be found
                    } else {
                        continue;
                    }
                    // reach this position if the first valid data value is found for this data value itself
                    arrKnot.push ( {
                        index : u,
                        y : data[u].config.setValue
                    });
                // if valid first data value is already found
                } else {
                    // for invalid data value
                    if (isNaN (data[u].config.setValue) || data[u].config.setValue === null) {
                        if (connectNullData) {
                            // just ignore the data
                            continue;
                        } else {
                            // split here, to end the curve and start a new curve
                            break;
                        }
                    } else {
                        arrKnot.push ( {
                            index : u,
                            y : data[u].config.setValue
                        });
                    }
                }
            }
            // spline curve is possible for a set of plots with more than 2 points
            if (arrKnot.length > 2) {
                // Examine the spline curve to find the min-max vertically
                chart.evalSplineExtremities (arrKnot, chartWidth, limits);
            }
            //
            // recursion is required for the case of a series splitted into multiple subset of points due to
            // existence of null data entries in the series
            if (u < data.length && !connectNullData) {
                chart.getSplineExtremities (data, chartWidth, connectNullData, u, limits);
            }
            return limits;
        },
        /**
         *
         * evalSplineExtremities is called to evaluate the vertical extremities of the bounding box of the spline.
         */
        evalSplineExtremities: function (arrKnot, chartWidth, limits) {
            // object to store gradients at spline plots
            var objGrad = { },
                chart = this,
                u, i, t, calcValue, delX;

            // Below, each gradient is initialised to zero
            for (i = 0; i < arrKnot.length; ++ i) {
                // getting the original index for this data
                t = arrKnot[i].index;
                // initialised to zero
                objGrad ['D' + t] = 0;
            }

            // The following iteration is a mathematical purpose - iterative method of approximation with faster
            // convergence. The more the number of iteration, more precise are the approximate solutions.
            for (u = 0; u < 10; ++ u) {
                // iteration for convergence towards actual solutions
                for (i = 0; i < arrKnot.length; ++ i) {
                    if (i === 0) {
                        calcValue = (3 * (arrKnot [i + 1].y - arrKnot[i].y) -
                            objGrad ['D' + arrKnot[i + 1].index]) / 2;
                    } else if (i === arrKnot.length - 1) {
                        calcValue = (3 * (arrKnot[i].y - arrKnot[i - 1].y) -
                            objGrad ['D' + arrKnot[i - 1].index]) / 2;
                    } else {
                        calcValue = (3 * (arrKnot[i + 1].y - arrKnot[i - 1].y) -
                            objGrad ['D' + arrKnot[i + 1].index] - objGrad ['D' + arrKnot[i - 1].index]) / 4;
                    }
                    // gradient value updated in repository for use in subsequent loop/turn for faster convergence
                    objGrad ['D' + arrKnot[i].index] = calcValue;
                }
            }

            // Since, canvas width is not ready as yet, chart width is used instead to get as close as possible to
            // the required x-interval between two consecutive spline plots
            delX = mathRound (chartWidth / (arrKnot.length - 1));

            // each spline constitutes of a number of smaller curves, each joining two consecutive pioints.
            for (i = 1; i < arrKnot.length; ++ i) {
                // find the max-min y-values for the bounding box of the unit curve
                chart.getSegmentExtremities (i, arrKnot, objGrad, limits, delX);
            }
        },

        /**
         * getSegmentExtremities method is aclled to process unit curves constituting a spline
         * and evaluate the vertical limits of the curve.
         */
        getSegmentExtremities: function (index, data, objGradientStore, limits, delX) {
            // storing the reference of the repository of coordinates of the points
            var arrKnot = data,
                i = index,
                j = 0,
                slope1, slope2, a1, a2, a3, a4, maxY, minY, k, n, t, y1;

            // slopes of the curve at the two extremes of the spline
            slope1 = objGradientStore ['D' + arrKnot[j].index];
            slope2 = objGradientStore ['D' + arrKnot[i].index];
            // calculating the four coefficients characterising the cubic polynomial
            a1 = arrKnot[j].y;
            a2 = slope1;
            a3 = 3 * (arrKnot[i].y - arrKnot[j].y) - 2 * slope1 - slope2;
            a4 = 2 * (arrKnot[j].y - arrKnot[i].y) + slope1 + slope2;

            maxY = limits.max;
            minY = limits.min;

            for (k = 0, n = delX; k <= n; k++) {
                t = k / n;
                y1 = a1 + a2 * t + a3 * t * t + a4 * t * t * t;

                if (y1 < minY) {
                    minY = y1;
                }

                if (y1 > maxY) {
                    maxY = y1;
                }
            }

            limits.max = maxY;
            limits.min = minY;
        }
    }, chartAPI.sscartesian, {
        minimizetendency: 0,
        zeroplanethickness: 1,
        zeroplanealpha: 40,
        showzeroplaneontop: 0,
        enablemousetracking: true
    }, chartAPI.areabase);

}]);

FusionCharts.register ('module', ['private', 'modules.renderer.js-splinearea', function () {
    var global = this,
        lib = global.hcLib,
        win = global.window,
        HUNDREDSTRING = lib.HUNDREDSTRING,
        creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
        chartAPI = lib.chartAPI;

    chartAPI('splinearea', {
        friendlyName: 'Spline Area Chart',
        standaloneInit: true,
        hasLegend: false,
        singleseries: true,
        creditLabel: creditLabel,
        defaultDatasetType: 'mssplinearea',
        defaultPlotShadow: 0
    }, chartAPI.spline, {
        anchoralpha: HUNDREDSTRING,
        minimizetendency: 0,
        enablemousetracking: true
    }, chartAPI.areabase);

}]);

FusionCharts.register ('module', ['private', 'modules.renderer.js-msspline', function () {
    var global = this,
        lib = global.hcLib,
        win = global.window,
        creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
        chartAPI = lib.chartAPI;

    chartAPI('msspline', {
        standaloneInit: true,
        friendlyName: 'Multi-series Spline  Chart',
        creditLabel: creditLabel,
        defaultDatasetType : 'msspline',
        applicableDSList: {'msspline': true},
        defaultPlotShadow: 1,
        getSplineExtremities: chartAPI.spline.getSplineExtremities,
        evalSplineExtremities: chartAPI.spline.evalSplineExtremities,
        getSegmentExtremities: chartAPI.spline.getSegmentExtremities
    }, chartAPI.mscartesian, {
        minimizetendency: 0,
        zeroplanethickness: 1,
        zeroplanealpha: 40,
        showzeroplaneontop: 0,
        enablemousetracking: true
    }, chartAPI.areabase);

}]);

FusionCharts.register ('module', ['private', 'modules.renderer.js-mssplinearea', function () {
    var global = this,
        lib = global.hcLib,
        win = global.window,
        creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
        chartAPI = lib.chartAPI;

    chartAPI('mssplinearea', {
        friendlyName: 'Multi-series Spline Area Chart',
        standaloneInit: true,
        creditLabel: creditLabel,
        defaultDatasetType: 'mssplinearea',
        defaultPlotShadow: 0
    }, chartAPI.msspline, {
        minimizetendency: 0,
        enablemousetracking: true
    }, chartAPI.areabase);
}]);

FusionCharts.register ('module', ['private', 'modules.renderer.js-mssplinedy', function () {
    var global = this,
        lib = global.hcLib,
        win = global.window,
        creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
        chartAPI = lib.chartAPI;

    chartAPI('mssplinedy', {
        friendlyName: 'Multi-series Dual Y-Axis Spline Chart',
        standaloneInit: true,
        creditLabel: creditLabel,
        isDual: true,
        defaultDatasetType : 'msspline',
        applicableDSList: {'msspline': true},
        getSplineExtremities: chartAPI.spline.getSplineExtremities,
        evalSplineExtremities: chartAPI.spline.evalSplineExtremities,
        getSegmentExtremities: chartAPI.spline.getSegmentExtremities
    }, chartAPI.msdybasecartesian, {
        minimizetendency: 0,
        zeroplanethickness: 1,
        zeroplanealpha: 40,
        showzeroplaneontop: 0
    }, chartAPI.msspline);

}]);

FusionCharts.register ('module', ['private', 'modules.renderer.js-multiaxisline', function () {
    var global = this,
        lib = global.hcLib,
        win = global.window,
        pluck = lib.pluck,
        pluckNumber = lib.pluckNumber,
        preDefStr = lib.preDefStr,
        sStr = preDefStr.sStr,
        COMPONENT = 'component',
        BLANKSTRING = lib.BLANKSTRING,
        parseUnsafeString = lib.parseUnsafeString,
        DATASET = 'dataset',
        UNDEFINED,
        DATASET_GROUP = 'datasetGroup',
        defaultFontStr = preDefStr.defaultFontStr,
        pluckFontSize = lib.pluckFontSize, // To get the valid font size (filters negative values)
        divLineAlphaStr = preDefStr.divLineAlphaStr,
        divLineAlpha3DStr = preDefStr.divLineAlpha3DStr,
        componentDispose = lib.componentDispose,
        chartPaletteStr = lib.chartPaletteStr = {
            chart2D: {
                bgColor : 'bgColor',
                bgAlpha : 'bgAlpha',
                bgAngle : 'bgAngle',
                bgRatio : 'bgRatio',
                canvasBgColor : 'canvasBgColor',
                canvasBaseColor : 'canvasBaseColor',
                divLineColor : 'divLineColor',
                legendBgColor : 'legendBgColor',
                legendBorderColor : 'legendBorderColor',
                toolTipbgColor : 'toolTipbgColor',
                toolTipBorderColor : 'toolTipBorderColor',
                baseFontColor : 'baseFontColor',
                anchorBgColor : 'anchorBgColor'
            },
            chart3D : {
                bgColor : 'bgColor3D',
                bgAlpha : 'bgAlpha3D',
                bgAngle : 'bgAngle3D',
                bgRatio : 'bgRatio3D',
                canvasBgColor : 'canvasBgColor3D',
                canvasBaseColor : 'canvasBaseColor3D',
                divLineColor : 'divLineColor3D',
                divLineAlpha : divLineAlpha3DStr,
                legendBgColor : 'legendBgColor3D',
                legendBorderColor : 'legendBorderColor3D',
                toolTipbgColor : 'toolTipbgColor3D',
                toolTipBorderColor : 'toolTipBorderColor3D',
                baseFontColor : 'baseFontColor3D',
                anchorBgColor : 'anchorBgColor3D'
            }
        },
        AXIS = 'axis',
        creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
        colorStrings = preDefStr.colors,
        convertColor = lib.graphics.convertColor,
        extend2 = lib.extend2, //old: jarendererExtend / margecolone
        altVGridColorStr = preDefStr.altVGridColorStr,
        configStr = preDefStr.configStr,
        animationObjStr = preDefStr.animationObjStr,
        isIE = lib.isIE,
        TRACKER_FILL = 'rgba(192,192,192,' + (isIE ? 0.002 : 0.000001) + ')', // invisible but clickable
        COMMA = ',',
        toRaphaelColor = lib.toRaphaelColor,
        hasTouch = lib.hasTouch,
        math = Math,
        mathMax = math.max,
        mathMin = math.min,
        POSITION_BOTTOM = preDefStr.POSITION_BOTTOM,
        COLOR_000000 = colorStrings.c000000,
        altVGridAlphaStr = preDefStr.altVGridAlphaStr,
        chartAPI = lib.chartAPI;

    chartAPI('multiaxisline', {
        friendlyName: 'Multi-axis Line Chart',
        standaloneInit: true,
        creditLabel: creditLabel,
        defaultDatasetType: 'multiaxisline',
        defaultPlotShadow: 1,
        axisPaddingLeft: 0,
        axisPaddingRight: 0,
        applicableDSList: { LINE: true },
        _createDatasets : function () {
            var iapi = this,
                components = iapi.components,
                chartConfig = iapi.config,
                //graphics = iapi.graphics,
                //datasetGroup = graphics.datasetGroup,
                dataObj = iapi.jsonData,
                dataset = dataObj.axis,
                length,
                i,
                j,
                diff,
                subDataset,
                datasetStore,
                datasetStoreLen,
                curDatasetStoreLen = 0,
                datasetObj,
                subDatasetLen,
                defaultSeriesType = iapi.defaultDatasetType,
                applicableDSList = iapi.applicableDSList,
                legend = components.legend,
                legendItems = legend.components.items || [],
                GroupManager,
                dsType,
                DsClass,
                DsGroupClass,
                datasetJSON,
                isStacked = iapi.config.isstacked,
                groupManagerName,
                parentyaxis,
                dsCount = { },
                count = 0,
                axisDataSetMap,
                JSONData,
                prevDataLength,
                currDataLength;

            if (!dataset) {
                iapi.setChartMessage();
                return;
            }
            length = dataset.length;
            iapi.config.categories = dataObj.categories && dataObj.categories[0].category;

            datasetStore = components.dataset  || (components.dataset = []);
            datasetStoreLen = datasetStore.length;
            axisDataSetMap = chartConfig.axisDataSetMap = [];
            for (i=0; i<length; i++) {

                subDataset = dataset[i].dataset;
                axisDataSetMap[i] = [];
                if (!subDataset) {
                    continue;
                }
                subDatasetLen = subDataset.length;
                curDatasetStoreLen += subDatasetLen;
                for (j = 0; j < subDatasetLen; j++) {
                    datasetJSON = subDataset[j];
                    datasetJSON.seriesname &&  (datasetJSON.seriesname = parseUnsafeString(datasetJSON.seriesname));
                    parentyaxis = datasetJSON.parentyaxis || BLANKSTRING;
                    if (iapi.isDual && parentyaxis.toLowerCase () === sStr) {
                        dsType = pluck (datasetJSON.renderas, iapi.sDefaultDatasetType);
                    }
                    else {
                        dsType = pluck (datasetJSON.renderas, defaultSeriesType);
                    }
                    dsType = dsType && dsType.toLowerCase ();
                    if (!applicableDSList[dsType]) {
                        dsType = defaultSeriesType;
                    }

                    /// get the DsClass
                    DsClass = FusionCharts.get(COMPONENT, [DATASET, dsType]);
                    if (DsClass) {
                        if (dsCount[dsType] === UNDEFINED) {
                            dsCount[dsType] = 0;
                        }
                        else {
                            dsCount[dsType]++;
                        }
                        groupManagerName = 'datasetGroup_' + dsType;
                        // get the ds group class
                        DsGroupClass = FusionCharts.register(COMPONENT, [DATASET_GROUP, dsType]);
                        GroupManager = components[groupManagerName];
                        if (DsGroupClass && !GroupManager) {
                            GroupManager = components[groupManagerName] = new DsGroupClass ();
                            GroupManager.chart = iapi;
                            GroupManager.init ();
                            // groupManager.init (components, graphics);
                            // groupManager.dataSetsLen = length;
                        }

                        // If the dataset does not exists.
                        if (!datasetStore[count]) {
                            // create the dataset Object
                            datasetObj = new DsClass ();
                            datasetStore.push (datasetObj);
                            datasetObj.chart = iapi;
                            datasetObj.index = i;
                            // set axis index to refer the right axis
                            datasetObj.axisIndex = i;
                            axisDataSetMap[i].push(count);
                            count += 1;
                            // add to group manager
                            GroupManager && (isStacked ? GroupManager.addDataSet (datasetObj, 0, dsCount[dsType]) :
                                GroupManager.addDataSet (datasetObj, dsCount[dsType], 0));
                            datasetObj.init (datasetJSON);
                        }
                        // If the dataset exists incase the chart is updated using setChartData() method.
                        else {
                            datasetObj = datasetStore[count];
                            JSONData = datasetObj.JSONData;
                            prevDataLength = JSONData.data ? JSONData.data.length : 0;
                            currDataLength = datasetJSON.data ? datasetJSON.data.length : 0;
                            // Removing data plots if the number of current data plots
                            // is more than the existing ones.
                            if (prevDataLength > currDataLength) {
                                datasetObj.removeData(currDataLength - 1, prevDataLength - currDataLength, false);
                            }
                            datasetObj.JSONData = datasetJSON;
                            datasetObj.index = i;
                            datasetObj.axisIndex = i;
                            datasetObj.configure();
                            // set axis index to refer the right axis
                            axisDataSetMap[i].push(count);
                            count += 1;
                        }
                    }
                }
            }
            // When the number of datasets entered vis setChartData is less than the existing dataset then
            // dispose the extra datasets.
            if (datasetStoreLen > curDatasetStoreLen) {
                diff = datasetStoreLen - curDatasetStoreLen;

                for (j = curDatasetStoreLen; j < datasetStoreLen; j ++ ) {
                    componentDispose.call(datasetStore[j]);
                }
                datasetStore.splice(curDatasetStoreLen, diff);

                legendItems.splice(curDatasetStoreLen, diff);
            }
        },
        _createAxes : function () {
            var iapi = this,
                components = iapi.components,
                CartesianAxis = FusionCharts.register (COMPONENT, [AXIS, 'cartesian']),
                xAxis;

            components.yAxis = [];
            components.xAxis = [];
            components.xAxis[0] = xAxis = new CartesianAxis ();
            xAxis.chart = iapi;
            xAxis.init ();
            // set the chart categories
            iapi._setCategories ();
        },
        _feedAxesRawData : function () {
            var iapi = this,
                components = iapi.components,
                chartConfig = iapi.config,
                colorM = components.colorManager,
                numberFormatter = components.numberFormatter,
                dataObj = iapi.jsonData,
                chartAttrs = dataObj.chart,
                xAxisConf,
                yAxisConf,
                is3d = iapi.is3d,
                palleteString = is3d ? chartPaletteStr.chart3D : chartPaletteStr.chart2D,
                CartesianAxis = FusionCharts.register (COMPONENT, [AXIS, 'cartesian']),
                yAxis,
                xAxis,
                axes,
                i,
                len,
                isOpposit,
                axisJson,
                plotColor,
                leftAxes,
                rightAxes,
                axesMap,
                axisHEXColor,
                axisColor,
                gridLineWidth,
                tickWidth,
                axisLineThickness,
                showAxis,
                checkBoxChecked = false,
                count = 0,
                j,
                jlen;


            xAxisConf = {
                outCanfontFamily: pluck (chartAttrs.outcnvbasefont, chartAttrs.basefont, defaultFontStr),
                outCanfontSize:  pluckFontSize (chartAttrs.outcnvbasefontsize, chartAttrs.basefontsize, 10),
                outCancolor: pluck (chartAttrs.outcnvbasefontcolor, chartAttrs.basefontcolor,
                    colorM.getColor (palleteString.baseFontColor)).replace (/^#? ([a-f0-9]+)/ig, '#$1'),
                axisNamePadding: chartAttrs.xaxisnamepadding,
                axisValuePadding: chartAttrs.labelpadding,
                axisNameFont: chartAttrs.xaxisnamefont,
                axisNameFontSize: chartAttrs.xaxisnamefontsize,
                axisNameFontColor: chartAttrs.xaxisnamefontcolor,
                axisNameFontBold: chartAttrs.xaxisnamefontbold,
                axisNameFontItalic: chartAttrs.xaxisnamefontitalic,
                axisNameBgColor: chartAttrs.xaxisnamebgcolor,
                axisNameBorderColor: chartAttrs.xaxisnamebordercolor,
                axisNameAlpha: chartAttrs.xaxisnamealpha,
                axisNameFontAlpha: chartAttrs.xaxisnamefontalpha,
                axisNameBgAlpha: chartAttrs.xaxisnamebgalpha,
                axisNameBorderAlpha: chartAttrs.xaxisnameborderalpha,
                axisNameBorderPadding: chartAttrs.xaxisnameborderpadding,
                axisNameBorderRadius: chartAttrs.xaxisnameborderradius,
                axisNameBorderThickness: chartAttrs.xaxisnameborderthickness,
                axisNameBorderDashed: chartAttrs.xaxisnameborderdashed,
                axisNameBorderDashLen: chartAttrs.xaxisnameborderdashlen,
                axisNameBorderDashGap: chartAttrs.xaxisnameborderdashgap,
                useEllipsesWhenOverflow: chartAttrs.useellipseswhenoverflow,
                divLineColor: pluck (chartAttrs.vdivlinecolor, chartAttrs.divlinecolor,
                    colorM.getColor (palleteString.divLineColor)),
                divLineAlpha: pluck (chartAttrs.vdivlinealpha, chartAttrs.divlinealpha,
                    is3d ? colorM.getColor(divLineAlpha3DStr) : colorM.getColor (divLineAlphaStr)),
                divLineThickness: pluckNumber (chartAttrs.vdivlinethickness, chartAttrs.divlinethickness, 1),
                divLineIsDashed: Boolean (pluckNumber (chartAttrs.vdivlinedashed, chartAttrs.vdivlineisdashed,
                    chartAttrs.divlinedashed, chartAttrs.divlineisdashed, 0)),
                divLineDashLen: pluckNumber (chartAttrs.vdivlinedashlen, chartAttrs.divlinedashlen, 4),
                divLineDashGap: pluckNumber (chartAttrs.vdivlinedashgap, chartAttrs.divlinedashgap, 2),
                showAlternateGridColor: pluckNumber (chartAttrs.showalternatevgridcolor, 0),
                alternateGridColor: pluck (chartAttrs.alternatevgridcolor, colorM.getColor (altVGridColorStr)),
                alternateGridAlpha: pluck (chartAttrs.alternatevgridalpha, colorM.getColor (altVGridAlphaStr)),
                numDivLines: chartAttrs.numvdivlines,
                labelFont: chartAttrs.labelfont,
                labelFontSize: chartAttrs.labelfontsize,
                labelFontColor: chartAttrs.labelfontcolor,
                labelFontBold : chartAttrs.labelfontbold,
                labelFontItalic : chartAttrs.labelfontitalic,
                labelFontAlpha: chartAttrs.labelalpha,
                maxLabelHeight : chartAttrs.maxlabelheight,
                axisName: chartAttrs.xaxisname,
                axisMinValue: chartAttrs.xaxisminvalue,
                axisMaxValue: chartAttrs.xaxismaxvalue,
                setAdaptiveMin: chartAttrs.setadaptivexmin,
                adjustDiv: chartAttrs.adjustvdiv,
                labelDisplay: chartAttrs.labeldisplay,
                showLabels: chartAttrs.showlabels,
                rotateLabels: chartAttrs.rotatelabels,
                slantLabel: pluckNumber (chartAttrs.slantlabels, chartAttrs.slantlabel),
                labelStep: pluckNumber (chartAttrs.labelstep, chartAttrs.xaxisvaluesstep),
                showAxisValues: pluckNumber (chartAttrs.showxaxisvalues,  chartAttrs.showxaxisvalue),
                showLimits: chartAttrs.showvlimits,
                showDivLineValues: pluckNumber (chartAttrs.showvdivlinevalues, chartAttrs.showvdivlinevalues),
                showZeroPlane: chartAttrs.showvzeroplane,
                zeroPlaneColor: chartAttrs.vzeroplanecolor,
                zeroPlaneThickness: chartAttrs.vzeroplanethickness,
                zeroPlaneAlpha: chartAttrs.vzeroplanealpha,
                showZeroPlaneValue: chartAttrs.showvzeroplanevalue,
                trendlineColor: chartAttrs.trendlinecolor,
                trendlineToolText: chartAttrs.trendlinetooltext,
                trendlineThickness: chartAttrs.trendlinethickness,
                trendlineAlpha: chartAttrs.trendlinealpha,
                showTrendlinesOnTop: chartAttrs.showtrendlinesontop,
                showAxisLine: pluckNumber (chartAttrs.showxaxisline, chartAttrs.showaxislines,
                    chartAttrs.drawAxisLines, 0),
                axisLineThickness: pluckNumber (chartAttrs.xaxislinethickness, chartAttrs.axislinethickness, 1),
                axisLineAlpha: pluckNumber (chartAttrs.xaxislinealpha, chartAttrs.axislinealpha, 100),
                axisLineColor: pluck (chartAttrs.xaxislinecolor, chartAttrs.axislinecolor, COLOR_000000)
            };
            yAxisConf = {
                outCanfontFamily: pluck (chartAttrs.outcnvbasefont, chartAttrs.basefont, defaultFontStr),
                outCanfontSize:  pluckFontSize (chartAttrs.outcnvbasefontsize, chartAttrs.basefontsize, 10),
                outCancolor: pluck (chartAttrs.outcnvbasefontcolor, chartAttrs.basefontcolor,
                    colorM.getColor (palleteString.baseFontColor)).replace (/^#? ([a-f0-9]+)/ig, '#$1'),
                useEllipsesWhenOverflow: chartAttrs.useellipseswhenoverflow,
                showAlternateGridColor: 0,
                axisNameFont: chartAttrs.yaxisnamefont,
                axisNameFontSize: chartAttrs.yaxisnamefontsize,
                axisNameFontColor: chartAttrs.yaxisnamefontcolor,
                axisNameFontBold: chartAttrs.yaxisnamefontbold,
                axisNameFontItalic: chartAttrs.yaxisnamefontitalic,
                axisNameBgColor: chartAttrs.yaxisnamebgcolor,
                axisNameBorderColor: chartAttrs.yaxisnamebordercolor,
                axisNameAlpha: chartAttrs.yaxisnamealpha,
                axisNameFontAlpha: chartAttrs.yaxisnamefontalpha,
                axisNameBgAlpha: chartAttrs.yaxisnamebgalpha,
                axisNameBorderAlpha: chartAttrs.yaxisnameborderalpha,
                axisNameBorderPadding: chartAttrs.yaxisnameborderpadding,
                axisNameBorderRadius: chartAttrs.yaxisnameborderradius,
                axisNameBorderThickness: chartAttrs.yaxisnameborderthickness,
                axisNameBorderDashed: chartAttrs.yaxisnameborderdashed,
                axisNameBorderDashLen: chartAttrs.yaxisnameborderdashlen,
                axisNameBorderDashGap: chartAttrs.yaxisnameborderdashgap
            };
            // xAxisConf.vtrendlines = dataObj.vtrendlines;
            // yAxisConf.trendlines = dataObj.trendlines;
            xAxis = components.xAxis[0];
            xAxis.setCommonConfigArr (xAxisConf, false, false, false);
            xAxis.configure();
            chartConfig.axesArr = {
                leftAxes : [],
                rightAxes : [],
                axesMap : [],
                checkBox : [],
                leftSideSelected : false
            };
            leftAxes = chartConfig.axesArr.leftAxes = [];
            rightAxes = chartConfig.axesArr.rightAxes = [];
            axesMap = chartConfig.axesArr.axesMap = [];
            axes = dataObj.axis || [];
            for (i = 0, len = axes.length; i < len; i += 1) {
                if (!components.yAxis[i]) {
                    yAxis = components.yAxis[i] = new CartesianAxis ();
                    yAxis.chart = iapi;
                    yAxis.init ();
                } else {
                    yAxis = components.yAxis[i];
                }
                axisJson = axes[i];
                checkBoxChecked = false;
                for (j = 0, jlen = axisJson.dataset ? axisJson.dataset.length : 0; j < jlen; j += 1) {
                    if(Number(axisJson.dataset[j].visible) !== 0 ) {
                        checkBoxChecked = true;
                    }
                }
                showAxis = pluckNumber(axisJson.showaxis, 1);
                plotColor = colorM.getPlotColor(i);
                axisHEXColor = pluck(axisJson.color, chartAttrs.axiscolor,
                        plotColor);
                axisColor = convertColor(axisHEXColor, 100);
                gridLineWidth = pluckNumber(axisJson.divlinethickness,
                        chartAttrs.divlinethickness, 1);
                tickWidth = pluckNumber(axisJson.tickwidth, chartAttrs.axistickwidth, 2);
                axisLineThickness = pluckNumber(axisJson.axislinethickness, chartAttrs.axislinethickness, 2);
                isOpposit = !(pluckNumber(axisJson.axisonleft,1));
                if (isOpposit) {
                    axesMap.push({'side' : 'r', 'index' : rightAxes.length, showAxis : showAxis,
                        checkBoxChecked : checkBoxChecked});
                    rightAxes.push({'index' : i, showAxis : showAxis,
                        checkBoxChecked : checkBoxChecked});
                } else {
                    if (showAxis) {
                        chartConfig.axesArr.leftSideSelected = true;
                    }
                    axesMap.push({'side' : 'l', 'index' : leftAxes.length, showAxis : showAxis,
                        checkBoxChecked : checkBoxChecked});
                    leftAxes.push({'index' : i, showAxis : showAxis,
                        checkBoxChecked : checkBoxChecked});
                }
                //add axis configuration
                yAxisConf.labelStep = pluckNumber(axisJson.yaxisvaluesstep, axisJson.yaxisvaluestep,
                    chartAttrs.yaxisvaluesstep, chartAttrs.yaxisvaluestep);
                yAxisConf.axisMaxValue = axisJson.maxvalue;
                //yAxisConf.tickWidth = tickWidth;
                yAxisConf.axisMinValue = axisJson.minvalue;
                yAxisConf.setAdaptiveMin = pluckNumber(axisJson.setadaptiveymin, chartAttrs.setadaptiveymin);
                yAxisConf.numDivLines = pluckNumber(axisJson.numdivlines, chartAttrs.numdivlines, 4);
                yAxisConf.adjustDiv = pluckNumber(axisJson.adjustdiv, chartAttrs.adjustdiv);
                yAxisConf.showAxisValues = pluckNumber(axisJson.showyaxisvalues,
                    axisJson.showyaxisvalue, chartAttrs.showyaxisvalues, chartAttrs.showyaxisvalue, 1);
                yAxisConf.showLimits = pluckNumber(axisJson.showlimits, chartAttrs.showyaxislimits,
                    chartAttrs.showlimits, yAxisConf.showAxisValues);
                yAxisConf.showDivLineValues = pluckNumber(axisJson.showdivlinevalue,
                    chartAttrs.showdivlinevalues, axisJson.showdivlinevalues,
                    yAxisConf.showAxisValues);
                yAxisConf.showZeroPlane = pluckNumber(axisJson.showzeroplane, chartAttrs.showzeroplane);
                yAxisConf.showZeroPlaneValue = pluckNumber(axisJson.showzeroplanevalue,
                    chartAttrs.showzeroplanevalue);
                yAxisConf.zeroPlaneColor = axisJson.zeroplanecolor;
                yAxisConf.zeroPlaneThickness = pluckNumber(axisJson.zeroplanethickness, axisJson.divlinethickness,
                    chartConfig.zeroplanethickness, 2),
                yAxisConf.zeroPlaneAlpha = pluckNumber(axisJson.zeroplanealpha, axisJson.divlinealpha,
                    chartConfig.zeroplanealpha),
                yAxisConf.showZeroPlaneOnTop  = chartConfig.showzeroplaneontop,
                yAxisConf.divLineColor = pluck(axisJson.divlinecolor, axisHEXColor);
                yAxisConf.divLineAlpha = pluckNumber(axisJson.divlinealpha, chartAttrs.divlinealpha,
                                colorM.getColor(divLineAlphaStr), 100);
                yAxisConf.divLineThickness = gridLineWidth;
                yAxisConf.divLineIsDashed = Boolean (pluckNumber(axisJson.divlinedashed, axisJson.divlineisdashed,
                            chartAttrs.divlinedashed, chartAttrs.divlineisdashed, 0));
                yAxisConf.divLineDashLen = pluckNumber(axisJson.divlinedashlen,
                                chartAttrs.divlinedashlen, 4);
                yAxisConf.divLineDashGap = pluckNumber(axisJson.divlinedashgap,
                                chartAttrs.divlinedashgap, 2);

                yAxisConf.showAxisLine = 1;
                yAxisConf.axisLineThickness = axisLineThickness;
                yAxisConf.axisLineAlpha = 100;
                yAxisConf.axisLineColor = axisHEXColor;
                yAxisConf.tickLength = tickWidth;
                yAxisConf.tickColor = axisHEXColor;
                yAxisConf.tickAlpha = 100;
                yAxisConf.tickWidth = axisLineThickness;
                yAxisConf.axisName = axisJson.title;
                yAxisConf.rotateAxisName = 1;
                yAxis.setCommonConfigArr ((extend2({},yAxisConf)), true, false, isOpposit);
                yAxis.configure();
                numberFormatter.parseMLAxisConf(axisJson, i);
                if (pluckNumber(axisJson.showaxis) === 0) {
                    yAxis.hide();
                    yAxis.setAxisConfig({
                        axisIndex : i,
                        drawAxisLineWRTCanvas : false,
                        drawLabels : false,
                        drawPlotlines : false,
                        drawAxisLine : false,
                        drawPlotBands : false,
                        drawAxisName : false,
                        drawTrendLines : false,
                        drawTrendLabels : false,
                        drawTick : false,
                        drawTickMinor : false
                    });
                } else {
                    yAxis.show();
                    yAxis.setAxisConfig({
                        axisIndex : i,
                        drawAxisLineWRTCanvas : false,
                        drawLabels : true,
                        drawPlotlines : true,
                        drawAxisLine : true,
                        drawPlotBands : true,
                        drawAxisName : true,
                        drawTrendLines : true,
                        drawTrendLabels : true,
                        drawTick : true,
                        drawTickMinor : true
                    });
                }
                count += 1;
            }
            for (i = count, len = components.yAxis.length; i < len; i += 1) {
                components.yAxis[i].hide();
            }
        },
        _setAxisLimits: function () {
            var iapi = this,
                components = iapi.components,
                chartConfig = iapi.config,
                axis = chartConfig.axisDataSetMap,
                dataset = components.dataset,
                yAxis = components.yAxis,
                length = axis.length,
                i,
                infMin = -Infinity,
                infMax = +Infinity,
                max = infMin,
                min = infMax,
                j,
                len,
                maxminObj;

            for (i=0; i<length; i += 1) {
                for (j = 0, len = axis[i].length; j < len; j += 1) {
                    maxminObj = dataset[axis[i][j]].getDataLimits ();
                    max = mathMax (max, maxminObj.max);
                    min = mathMin (min, maxminObj.min);
                }
                if(min === Infinity) {
                    min = 0;
                }
                if(max === -Infinity) {
                    max = min + 1;
                }
                yAxis[i].setDataLimit (max, min);
                max = infMin;
                min = infMax;
            }

            // for (groupManager in groupManagerObj) {
            //     yAxisIndex = groupManagerObj[groupManager].yAxisIndex;
            //     maxminObj = groupManagerObj[groupManager].getDataLimits ();
            //     max = mathMax (max, maxminObj.max);
            //     min = mathMin (min, maxminObj.min);
            //     sYMax = mathMax (sYMax, maxminObj.sYMax);
            //     sYMin = mathMin (sYMin, maxminObj.sYMin);
            // }
            // if (syncAxisLimits) {
            //     actualMax = mathMax (max, sYMax);
            //     actualMin = mathMin (min, sYMin);
            //     yAxis[0].setDataLimit (actualMax, actualMin);
            //     yAxis[1].setDataLimit (actualMax, actualMin);
            // }
            // else {
            //     max = getSafeValue (max);
            //     min = getSafeValue (min);
            //     sYMax = getSafeValue (sYMax);
            //     sYMin = getSafeValue (sYMin);
            //     yAxis[0].setDataLimit (max, min);
            //     yAxis[1].setDataLimit (sYMax, sYMin);
            // }

            // // will give the divline of the active axis
            // divLineCount = yAxis[0].getDivLineCount ();
            // // // setting the inactive axis to forcefully have the same divlines
            // yAxis[1].setAxisConfig ( {
            //     numDivLines : divLineCount,
            //     adjustDiv : 0
            // });
            // if ((xMax !== infMin) || (xMin !== infMax)) {
            //     xAxis[0].config.xaxisrange = {
            //         max : xMax,
            //         min : xMin
            //     };
            //     xAxis[0].setDataLimit (xMax, xMin);
            // }
        },
        _spaceManager: function () {
            // todo marge _allocateSpace and _spacemanager
            var spaceForActionBar,
                actionBarSpace,
                availableWidth,
                availableHeight,
                iapi = this,
                config = iapi.config,
                axesArr = config.axesArr,
                components = iapi.components,
                legendPosition = config.legendPosition,
                axis = config.axisDataSetMap,
                xAxis = components.xAxis,
                yAxis = components.yAxis,
                hasLegend = iapi.hasLegend,
                xDepth = config.xDepth,
                yDepth = config.yDepth,
                legend = components.legend,
                canvasBaseDepth = config.canvasBaseDepth,
                canvasBasePadding = config.canvasBasePadding,
                axesPadding = config.axesPadding,
                shift = 0,
                rightPadding = 0,
                leftPadding = 0,
                length = axis.length,
                i,
                yAxisSpaceUsed,
                axesMap,
                leftAxes,
                rightAxes,
                allotedSpace,
                mappedAxis,
                is3d = iapi.is3D,
                chartAttrs = iapi.jsonData.chart,
                showBorder = pluckNumber (chartAttrs.showborder, is3d ? 0 : 1),
                canvasBorderWidth = components.canvas.config.canvasBorderWidth,
                chartBorderWidth =
                    config.borderWidth = showBorder ? pluckNumber (chartAttrs.borderthickness, 1) : 0,
                canvasMarginTop = config.canvasMarginTop,
                canvasMarginBottom = config.canvasMarginBottom,
                canvasMarginLeft = config.canvasMarginLeft,
                canvasMarginRight = config.canvasMarginRight,
                minCanvasHeight = config.minCanvasHeight,
                minCanvasWidth = config.minCanvasWidth,
                height = config.height,
                width = config.width,
                diff,
                heightAdjust = false,
                widthAdjust = false,
                top,
                bottom,
                left,
                right,
                currentCanvasHeight,
                currentCanvasWidth,
                origCanvasTopMargin = config.origCanvasTopMargin,
                origCanvasBottomMargin = config.origCanvasBottomMargin,
                origCanvasLeftMargin = config.origCanvasLeftMargin,
                origCanvasRightMargin = config.origCanvasRightMargin,
                sum;
            //****** Manage space
            iapi._allocateSpace ( {
                top : chartBorderWidth,
                bottom : chartBorderWidth,
                left : chartBorderWidth,
                right : chartBorderWidth
            });

            iapi._allocateSpace ( {
                left : config.canvasMarginLeft,
                right : config.canvasMarginRight
            });
            //****** Manage space
            axesMap = axesArr.axesMap;
            leftAxes = axesArr.leftAxes;
            rightAxes = axesArr.rightAxes;
            if (legendPosition === 'right') {
                allotedSpace = config.canvasWidth * 0.3;
            }
            else {
                allotedSpace = config.canvasHeight * 0.3;
            }
            //No space is allocated for legend drawing in single series charts
            ((hasLegend !== false) && xAxis) && iapi._allocateSpace
                (legend._manageLegendPosition (allotedSpace));

            for (i=0; i<length; i += 1) {
                if (axesMap[i].showaxis === 0) {
                    continue;
                }
                availableWidth = config.canvasWidth * 0.7;
                yAxisSpaceUsed = yAxis[i].placeAxis (availableWidth);
                yAxis[i] && iapi._allocateSpace (yAxisSpaceUsed);
                mappedAxis = axesMap[i];
                if (mappedAxis.side === 'r') {
                    rightAxes[mappedAxis.index].width = yAxisSpaceUsed.right;
                    rightPadding += axesPadding;
                } else {
                    leftAxes[mappedAxis.index].width = yAxisSpaceUsed.left;
                    leftPadding += axesPadding;
                }
            }
            spaceForActionBar = config.availableHeight * 0.225;
            actionBarSpace = iapi._manageActionBarSpace && iapi._manageActionBarSpace(spaceForActionBar) || {};
            iapi._allocateSpace(actionBarSpace);

            availableHeight = (legendPosition === POSITION_BOTTOM) ? config.canvasHeight * 0.6 :
                config.canvasWidth * 0.6;
            iapi._manageChartMenuBar(availableHeight);
            availableWidth = config.canvasWidth * 0.7;
            if (availableWidth > (rightPadding + leftPadding)) {
                iapi._allocateSpace ({
                    'left' : leftPadding,
                    'right' : rightPadding
                });
            }
            availableHeight = config.canvasHeight * 0.6;
            xAxis[0] && iapi._allocateSpace (xAxis[0].placeAxis (availableHeight));
            // alocate the space for datasets
            availableHeight = config.canvasHeight * 0.325;
            iapi._getDSspace && iapi._allocateSpace (iapi._getDSspace (availableHeight));

            if (yDepth) {
                iapi._allocateSpace ( {
                    bottom : yDepth
                });
                shift = xDepth + canvasBasePadding + canvasBaseDepth;
            }

            iapi._allocateSpace ( {
                top : canvasBorderWidth,
                bottom : canvasBorderWidth,
                left : canvasBorderWidth,
                right : canvasBorderWidth
            });
            // Allocate space for canvas margin only if the margin is less than the margin entered by the user.
            top = canvasMarginTop > config.canvasTop ? (canvasMarginTop - config.canvasTop) : 0;
            bottom = canvasMarginBottom > (height - config.canvasBottom) ?
                (canvasMarginBottom + config.canvasBottom - height) : 0;
            left = canvasMarginLeft > config.canvasLeft ? (canvasMarginLeft - config.canvasLeft) : 0;
            right = canvasMarginRight > (width - config.canvasRight) ?
                (canvasMarginRight + config.canvasRight - width) : 0;

            iapi._allocateSpace ( {
                top : top,
                bottom : bottom,
                left : left,
                right : right
            });
            // Forcing canvas height to its minimum
            if (heightAdjust) {
                sum = origCanvasTopMargin + origCanvasBottomMargin;
                currentCanvasHeight = config.canvasHeight;
                if (currentCanvasHeight > minCanvasHeight) {
                    diff = currentCanvasHeight - minCanvasHeight;
                    top = diff * origCanvasTopMargin / sum;
                    bottom = diff * origCanvasBottomMargin / sum;
                }
                iapi._allocateSpace ( {
                    top : top,
                    bottom : bottom
                });
            }

            // Forcing canvas width to its minimum
            if (widthAdjust) {
                sum = origCanvasLeftMargin + origCanvasRightMargin;
                currentCanvasWidth = config.canvasWidth;
                if (currentCanvasWidth > minCanvasWidth) {
                    diff = currentCanvasWidth - minCanvasWidth;
                    left = diff * origCanvasLeftMargin / sum;
                    right = diff * origCanvasRightMargin / sum;
                }
                iapi._allocateSpace ( {
                    left : left,
                    right : right
                });
            }

            config.actualCanvasMarginTop = top;
            config.actualCanvasMarginLeft = left;
            config.actualCanvasMarginRight = right;
            config.actualCanvasMarginBottom = bottom;
        },
        _postSpaceManagement : function () {
            var iapi = this,
                config = iapi.config,
                components = iapi.components,
                xAxis = components.xAxis && components.xAxis[0],
                legend = components.legend,
                xDepth = config.xDepth,
                canvasConfig = components.canvas.config,
                canvasBorderWidth = canvasConfig.canvasBorderWidth,
                canvasPadding = canvasConfig.canvasPadding,
                canvasPaddingLeft = canvasConfig.canvasPaddingLeft,
                canvasPaddingRight = canvasConfig.canvasPaddingRight;

            xAxis && xAxis.setAxisDimention ( {
                x : config.canvasLeft + (xDepth || 0) + mathMax(canvasPaddingLeft, canvasPadding),
                y : config.canvasBottom + (config.shift || 0) + canvasBorderWidth,
                opposite : config.canvasTop - canvasBorderWidth,
                axisLength : config.canvasWidth - (xDepth || 0) - mathMax(canvasPaddingLeft, canvasPadding) -
                                mathMax(canvasPaddingRight, canvasPadding)
            });

            xAxis && xAxis.shiftLabels (-xDepth, 0);
            legend.postSpaceManager();
        },
        _resuffelAxis : function () {
            var data = this.data('axisDetails'),
                iapi = data.iapi,
                config = iapi.config,
                axesArr = config.axesArr,
                prevAxis,
                axesMap,
                leftAxes,
                rightAxes,
                swapIndex,
                i,
                swapFromIndex;

            axesMap = axesArr.axesMap;
            leftAxes = axesArr.leftAxes;
            rightAxes = axesArr.rightAxes;
            if (data.position === 'l') {

                for (i = leftAxes.length - 1; i > data.index; i--) {
                    if (leftAxes[i].showAxis) {
                        swapIndex = i;
                        swapFromIndex = data.index;
                        break;
                    }
                }
                if (swapIndex !== undefined) {
                    prevAxis = extend2({},leftAxes[swapFromIndex]);
                    leftAxes[swapFromIndex] = extend2({}, leftAxes[swapIndex]);
                    leftAxes[swapIndex] = extend2({}, prevAxis);
                }
                if (axesArr.leftSideSelected && swapIndex === undefined) {
                    return;
                }
                axesArr.leftSideSelected = true;
            } else {
                for (i = 0; i < data.index; i++) {
                    if (rightAxes[i].showAxis) {
                        swapIndex = i;
                        swapFromIndex = data.index;
                        break;
                    }
                }
                if (swapIndex !== undefined) {
                    prevAxis = extend2({},rightAxes[swapFromIndex]);
                    rightAxes[swapFromIndex] = extend2({}, rightAxes[swapIndex]);
                    rightAxes[swapIndex] = extend2({}, prevAxis);
                }
                if (!axesArr.leftSideSelected && swapIndex === undefined) {
                    return;
                }
                axesArr.leftSideSelected = false;
            }
            iapi._drawAxis(true);
        },
        _dolegendInteraction : function () {
            var iapi = arguments[1],
                checkbox = this,
                axisIndex = arguments[0],
                dataSets = iapi.components.dataset,
                legend = iapi.components.legend,
                i;

            if (checkbox.checked) {
                for (i in dataSets) {
                    if(dataSets.hasOwnProperty(i)) {
                        if (!dataSets[i].visible && dataSets[i].axisIndex === axisIndex) {
                            dataSets[i].show();
                        }
                    }
                }
            } else {
                for (i in dataSets) {
                    if(dataSets.hasOwnProperty(i)) {
                        if (dataSets[i].visible && dataSets[i].axisIndex === axisIndex) {
                            dataSets[i].hide();
                        }
                    }
                }
            }
            legend.drawLegend();
        },
        _drawAxis : function (onlyY) {
            var iapi = this,
                config = iapi.config,
                axesArr = config.axesArr,
                components = iapi.components,
                yAxis = components.yAxis || [],
                xAxis = components.xAxis || [],
                paper = components.paper,
                allowAxisShift = config.allowAxisShift,
                allowSelection = config.allowSelection,
                axisHotElement = iapi.graphics.axisHotElement || [],
                trackerContainer = iapi.graphics.trackerContainer,
                checkBoxContainer = iapi.graphics.buttonGroup,
                canvasConfig = components.canvas.config,
                canvasBorderWidth = canvasConfig.canvasBorderWidth,
                canvasPaddingTop = canvasConfig.canvasPaddingTop,
                canvasPaddingBottom = canvasConfig.canvasPaddingBottom,
                axesPadding = config.axesPadding,
                tb = this.components.tb,
                leftPadding = 0,
                rightPadding = 0,
                counter = 0,
                x,
                y,
                height,
                width,
                eventI,
                eventLen,
                axesMap,
                leftAxes,
                rightAxes,
                i,
                length,
                axis,
                attr,
                hotElement,
                toolBox,
                toolBoxAPI,
                CheckboxSymbol,
                axisNamePadding,
                animationDuration,
                transposeAnimDuration,
                animType,
                axisIndex,
                checkboxes,
                checkbox,
                transposeX,
                transposeY,
                checkboxTopPadding = 4,
                isSelectedDrawn = false,
                cbIdCount = 0,
                animObj,
                dummyObj;

            animationDuration = iapi.get(configStr, animationObjStr);
            animObj = animationDuration.animObj;
            dummyObj = animationDuration.dummyObj;
            transposeAnimDuration = animationDuration.transposeAnimDuration;
            animType = animationDuration.animType;
            toolBox = components.tb || (components.tb =
                new (FusionCharts.register(COMPONENT, ['toolbox', 'toolbox']))());
            toolBox.init({
                iAPI: iapi,
                graphics: iapi.graphics,
                chart: iapi,
                components: components
            });
            toolBoxAPI = components.toolBoxAPI;
            CheckboxSymbol = toolBoxAPI.CheckboxSymbol;
            axesMap = axesArr.axesMap;
            leftAxes = axesArr.leftAxes;
            rightAxes = axesArr.rightAxes;
            checkboxes = axesArr.checkBox;
            for (i in checkboxes) {
                if (checkboxes.hasOwnProperty(i)) {
                    checkboxes[i].checkbox.hide();
                }
            }
            attr = {
                cursor: 'col-resize',
                stroke: TRACKER_FILL,
                fill: TRACKER_FILL,
                ishot: true,
                visibility: true
            };
            for (length = i = leftAxes.length - 1; i >= 0; i -= 1) {
                if (leftAxes[i].showAxis === 0) {
                    continue;
                }
                x = config.canvasLeft - canvasBorderWidth - leftPadding - axesPadding;
                y = config.canvasTop + canvasPaddingTop;
                height = config.canvasHeight - canvasPaddingTop - canvasPaddingBottom;
                width = leftAxes[i].width;
                axisIndex = leftAxes[i].index;
                axis = yAxis[axisIndex];
                axis.setAxisDimention ( {
                    x : x,
                    y : y,
                    opposite : config.canvasRight + canvasBorderWidth,
                    axisLength : height
                });
                leftPadding += width + axesPadding;
                if (!isSelectedDrawn && axesArr.leftSideSelected) {
                    axis.setAxisConfig({
                        'isActive' : true,
                        'axisNameAlignCanvas' : true,
                        'drawAxisNameFromBottom' : true
                    });
                    isSelectedDrawn = true;
                } else {
                    axis.setAxisConfig({
                        'isActive' : false,
                        'axisNameAlignCanvas' : true,
                        'drawAxisNameFromBottom' : true
                    });
                }

                if (allowSelection) {
                    if (!checkboxes[axisIndex]) {
                        checkbox = checkboxes[axisIndex] = {};
                        checkbox.checkbox = new CheckboxSymbol(BLANKSTRING, true, cbIdCount++, tb.pId);
                        checkbox.checkbox.conf = toolBox.getDefaultConfiguration();

                        checkbox.checkbox.attachEventHandlers({
                            click : {
                                fn : iapi._dolegendInteraction,
                                args : [axisIndex, iapi]
                            }
                        });

                        checkbox.checkbox.draw(x - width, y + height + checkboxTopPadding, {
                            parentLayer: checkBoxContainer
                        });
                        checkbox.checkboxPrePos = {
                            x : x - width,
                            y : y + height + checkboxTopPadding
                        };
                    } else {
                        checkbox = checkboxes[axisIndex];
                        transposeX = (x - width) - (checkboxes[axisIndex].checkboxPrePos.x);
                        transposeY = (y + height + checkboxTopPadding) - (checkboxes[axisIndex].checkboxPrePos.y);
                        checkbox.checkbox.show();
                        checkbox.checkbox.attachEventHandlers({
                            click : {
                                fn : iapi._dolegendInteraction,
                                args : [axisIndex, iapi]
                            }
                        });
                        if (transposeAnimDuration) {
                            checkbox.checkbox.node.animateWith(dummyObj, animObj,
                                {transform: 't'+transposeX+COMMA+transposeY},
                                transposeAnimDuration, animType);
                        } else {
                            checkbox.checkbox.node.attr({transform: 't'+transposeX+COMMA+transposeY});
                        }
                    }
                    checkbox.checkbox.node.attr({
                        stroke : toRaphaelColor({
                            color: config.checkBoxColor,
                            alpha: 100
                        })
                    });

                    checkbox.checkbox.node.attr({
                        'stroke-width' : [1, 2]
                    });
                    if (config.axisConfigured) {
                        if (leftAxes[i].checkBoxChecked) {
                            checkbox.checkbox.check();
                        } else {
                            checkbox.checkbox.uncheck();
                        }
                    }
                }

                if (allowAxisShift) {
                    attr.x = x - width;
                    attr.y = y;
                    attr.width = width;
                    attr.height = height;
                    // Creating the hot element if not created
                    if (axisHotElement[counter]) {
                        hotElement = axisHotElement[counter].attr(attr);
                        hotElement.show();
                        // remove the events from the elements
                        for (eventI = 0, eventLen = hotElement.events.length; eventI < eventLen; eventI++ ) {
                            hotElement.events[eventI].unbind();
                            hotElement.events.splice(eventI, 1);
                            eventLen -= 1;
                        }
                    }
                    else {
                        hotElement = axisHotElement[counter] = paper.rect(attr, trackerContainer);
                    }

                    hotElement
                    .data('axisDetails', {
                        iapi : iapi,
                        position : 'l',
                        index : i
                    });
                    if (hasTouch) {
                        hotElement.touchstart(iapi._resuffelAxis);
                    } else {
                        hotElement.mousedown(iapi._resuffelAxis);
                    }

                    counter += 1;
                }

            }
            for (i = 0, length = rightAxes.length; i < length; i += 1 ) {
                if (rightAxes[i].showAxis === 0) {
                    continue;
                }
                axisIndex = rightAxes[i].index;
                axis = yAxis[axisIndex];
                x = config.canvasRight + canvasBorderWidth + rightPadding + axesPadding;
                y = config.canvasTop + canvasPaddingTop;
                height = config.canvasHeight - canvasPaddingTop - canvasPaddingBottom;
                width = rightAxes[i].width;
                axis.setAxisDimention ( {
                    x : x,
                    y : y,
                    opposite : config.canvasLeft - canvasBorderWidth,
                    axisLength : height
                });
                rightPadding += rightAxes[i].width + axesPadding;
                if (!isSelectedDrawn && !axesArr.leftSideSelected) {
                    axis.setAxisConfig({
                        'isActive' : true,
                        'axisNameAlignCanvas' : true,
                        'drawAxisNameFromBottom' : true
                    });
                    isSelectedDrawn = true;
                } else {
                    axis.setAxisConfig({
                        'isActive' : false,
                        'axisNameAlignCanvas' : true,
                        'drawAxisNameFromBottom' : true
                    });
                }
                axisNamePadding = axis.getAxisConfig('axisNamePadding');
                if (allowSelection) {
                    if (!checkboxes[axisIndex]) {
                        checkbox = checkboxes[axisIndex] = {};
                        checkbox.checkbox = new CheckboxSymbol(BLANKSTRING, true, cbIdCount++, tb.pId);
                        checkbox.checkbox.conf = toolBox.getDefaultConfiguration();
                        checkbox.checkbox.attachEventHandlers({
                            click : {
                                fn : iapi._dolegendInteraction,
                                args : [axisIndex, iapi]
                            }
                        });
                        checkbox.checkbox.draw(x + axisNamePadding, y + height + checkboxTopPadding, {
                            parentLayer: checkBoxContainer
                        });
                        checkbox.checkboxPrePos = {
                            x : x - width,
                            y : y + height + checkboxTopPadding
                        };
                    } else {
                        checkbox = checkboxes[axisIndex];
                        transposeX = (x - width) - (checkbox.checkboxPrePos.x);
                        transposeY = (y + height + checkboxTopPadding) - (checkbox.checkboxPrePos.y);
                        checkbox.checkbox.show();
                        checkbox.checkbox.attachEventHandlers({
                            click : {
                                fn : iapi._dolegendInteraction,
                                args : [axisIndex, iapi]
                            }
                        });
                        if (transposeAnimDuration) {
                            checkbox.checkbox.node.animateWith(dummyObj, animObj,
                                {transform: 't'+transposeX+COMMA+transposeY},
                                transposeAnimDuration, animType);
                        } else {
                            checkbox.checkbox.node.attr({transform: 't'+transposeX+COMMA+transposeY});
                        }
                    }
                    checkbox.checkbox.node.attr({
                        stroke : toRaphaelColor({
                            color: config.checkBoxColor,
                            alpha: 100
                        })
                    });

                    checkbox.checkbox.node.attr({
                        'stroke-width' : [1, 2]
                    });
                    if (config.axisConfigured) {
                        if (rightAxes[i].checkBoxChecked) {
                            checkbox.checkbox.check();
                        } else {
                            checkbox.checkbox.uncheck();
                        }
                    }
                }
                if (allowAxisShift) {
                    attr.x = x;
                    attr.y = y;
                    attr.width = width;
                    attr.height = height;
                    // Creating the hot element if not created
                    if (axisHotElement[counter]) {
                        hotElement = axisHotElement[counter].attr(attr);
                        hotElement.show();
                        // remove the events from the elements
                        for (eventI = 0, eventLen = hotElement.events.length; eventI < eventLen; eventI++ ) {
                            hotElement.events[eventI].unbind();
                            hotElement.events.splice(eventI, 1);
                            eventLen -= 1;
                        }
                    }
                    else {
                        hotElement = axisHotElement[counter] = paper.rect(attr, trackerContainer);
                    }
                    hotElement
                    .data('axisDetails', {
                        iapi : iapi,
                        position : 'r',
                        index : i
                    });
                    if (hasTouch) {
                        hotElement.touchstart(iapi._resuffelAxis);
                    } else {
                        hotElement.mousedown(iapi._resuffelAxis);
                    }

                    counter += 1;
                }
            }
            iapi.graphics.axisHotElement = axisHotElement;
            for (i = counter, length = axisHotElement.length; i < length; i += 1) {
                axisHotElement[i].hide();
            }
            if (!onlyY) {
                for (i = 0, length = xAxis.length; i < length; i++) {
                    xAxis[i].draw ();
                }
            }
            for (i = 0, length = yAxis.length; i < length; i++) {
                yAxis[i].draw ();
            }
            config.axisConfigured = false;
        }

    }, chartAPI.mscartesian, {
        enablemousetracking: true
    }, chartAPI.areabase);

}]);

FusionCharts.register ('module', ['private', 'modules.renderer.js-inversemsline', function () {
    var global = this,
      lib = global.hcLib,
      win = global.window,
      creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
      chartAPI = lib.chartAPI,
      preDefStr = lib.preDefStr,
      LINE = preDefStr.line;

    chartAPI('inversemsline', {
        friendlyName: 'Inverted Y-Axis Multi-series Line Chart',
        standaloneInit: true,
        creditLabel: creditLabel,
        defaultDatasetType: LINE,
        defaultPlotShadow: 1,
        applicableDSList: {LINE: true}
    }, chartAPI.msinversecartesian, {
        zeroplanethickness: 1,
        zeroplanealpha: 40,
        showzeroplaneontop: 0,
        enablemousetracking: true
    }, chartAPI.areabase);
}]);

FusionCharts.register ('module', ['private', 'modules.renderer.js-inversemsarea', function () {
    var global = this,
      lib = global.hcLib,
      win = global.window,
      creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
      chartAPI = lib.chartAPI;

    chartAPI('inversemsarea', {
        friendlyName: 'Inverted Y-Axis Multi-series Area Chart',
        standaloneInit: true,
        creditLabel: creditLabel,
        defaultDatasetType: 'area',
        applicableDSList: {'area': true}
    }, chartAPI.msinversecartesian, {
        enablemousetracking: true
    }, chartAPI.areabase);

}]);

FusionCharts.register ('module', ['private', 'modules.renderer.js-inversemscolumn2d', function () {
    var global = this,
      lib = global.hcLib,
      win = global.window,
      creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
      chartAPI = lib.chartAPI,
      preDefStr = lib.preDefStr,
      COLUMN = preDefStr.column;

    chartAPI('inversemscolumn2d', {
        friendlyName: 'Inverted Y-Axis Multi-series Column Chart',
        standaloneInit: true,
        creditLabel: creditLabel,
        defaultDatasetType: COLUMN,
        applicableDSList: {COLUMN: true},
        isInverse : true
    }, chartAPI.msinversecartesian, {
        enablemousetracking: true
    });

}]);

FusionCharts.register ('module', ['private', 'modules.renderer.js-logmsline', function () {
    var global = this,
      lib = global.hcLib,
      win = global.window,
      preDefStr = lib.preDefStr,
      LINE = preDefStr.line,
      creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
      chartAPI = lib.chartAPI;

    chartAPI('logmsline', {
        standaloneInit: true,
        friendlyName: 'Multi-series Line Chart',
        creditLabel: creditLabel,
        defaultDatasetType : LINE,
        defaultPlotShadow: 1,
        applicableDSList: {LINE: true}
    }, chartAPI.mslog, {
        zeroplanethickness: 1,
        enablemousetracking: true,
        zeroplanealpha: 40,
        showzeroplaneontop: 0
    }, chartAPI.areabase);
}]);

FusionCharts.register ('module', ['private', 'modules.renderer.js-logmscolumn2d', function () {
    var global = this,
      lib = global.hcLib,
      win = global.window,
      preDefStr = lib.preDefStr,
      COLUMN = preDefStr.column,
      creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
      chartAPI = lib.chartAPI;
    chartAPI('logmscolumn2d', {
        friendlyName: 'Multi-series Log Column Chart',
        standaloneInit: true,
        creditLabel: creditLabel,
        defaultDatasetType: COLUMN,
        applicableDSList: {COLUMN: true}
    }, chartAPI.mslog, {
        enablemousetracking: true
    });
}]);

FusionCharts.register ('module', ['private', 'modules.renderer.js-logstackedcolumn2d', function () {
    var global = this,
      lib = global.hcLib,
      win = global.window,
      creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
      chartAPI = lib.chartAPI;

    chartAPI('logstackedcolumn2d', {
        friendlyName: 'Stacked Log Column Chart',
        standaloneInit: true,
        creditLabel: creditLabel
    }, chartAPI.logmscolumn2d, {
        isstacked: true
    });
}]);

FusionCharts.register ('module', ['private', 'modules.renderer.js-errorbar2d', function () {
    var global = this,
        lib = global.hcLib,
        win = global.window,
        creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
        chartAPI = lib.chartAPI;

    chartAPI('errorbar2d', {
        friendlyName: 'Error Bar Chart',
        standaloneInit: true,
        creditLabel: creditLabel,
        showValues: 0,
        isErrorChart: true,
        fireGroupEvent: true,
        hasLegend: true,
        defaultDatasetType : 'errorbar2d',
        applicableDSList: {'errorbar2d': true},
        eiMethods : { }
    }, chartAPI.mscartesian, {
        enablemousetracking: true
    });

}]);

FusionCharts.register ('module', ['private', 'modules.renderer.js-errorline', function () {
    var global = this,
        lib = global.hcLib,
        win = global.window,
        creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
        chartAPI = lib.chartAPI;

    chartAPI('errorline', {
        friendlyName: 'Error Line Chart',
        useErrorGroup: true,
        isErrorChart: true,
        fireGroupEvent: true,
        creditLabel: creditLabel,
        defaultPlotShadow: 1,
        axisPaddingLeft: 0,
        axisPaddingRight: 0,
        canvasPaddingModifiers: ['anchor', 'errorbar'],
        defaultDatasetType : 'errorline',
        applicableDSList: {'errorline': true}
    }, chartAPI.mscartesian, {
        zeroplanethickness: 1,
        zeroplanealpha: 40,
        showzeroplaneontop: 0,
        enablemousetracking: true
    }, chartAPI.areabase);
}]);

FusionCharts.register('module', ['private', 'modules.renderer.js-errorscatter', function () {
    var global = this,
        lib = global.hcLib,
        chartAPI = lib.chartAPI,
        win = global.window,
        creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname);

    chartAPI('errorscatter', {
        friendlyName: 'Error Scatter Chart',
        isXY: true,
        standaloneInit: true,
        creditLabel: creditLabel,
        defaultDatasetType: 'errorscatter',
        applicableDSList: {'errorscatter': true},
        defaultZeroPlaneHighlighted: false,
        useErrorGroup: true,
        isErrorChart: true,
        fireGroupEvent: true,
        initAnimation: true
    }, chartAPI.scatterBase, {
        enablemousetracking: true
    });
}]);

FusionCharts.register('module', ['private', 'modules.renderer.js-waterfall2d', function () {
    var global = this,
        lib = global.hcLib,
        chartAPI = lib.chartAPI,
        win = global.window,
        creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname),
        each = lib.each,
        TRUE_STRING = 'true',
        ONE_STRING = '1';

    //In the new architechture, changing the rendererId and setting a flag true for singleSeries.
    chartAPI('waterfall2d', {
        standaloneInit: true,
        friendlyName: 'Waterfall Chart',
        creditLabel: creditLabel,
        defaultDatasetType : 'Waterfall2D',
        applicableDSList: {
            'Waterfall2D': true
        },
        singleseries: true,
        hasLegend: false,
        /*
         * Seggregates the original data to data and vline.
         * @param data: Original data used for seggregation.
         * @return Object: JSON data to be used further by the child components, e.g. dataSet.
        */
        _dataSegregator: function (data) {
            var dataOnlyArr = [],
                catOnlyArr = [];

            each (data, function (data, i) {
                if (!(data.vline === TRUE_STRING || data.vline === true || data.vline === 1 ||
                    data.vline === ONE_STRING)) {
                    dataOnlyArr.push (data);
                }
                else {
                    catOnlyArr.push({
                        index: i,
                        data: data
                    });
                }
            });
            return {
                data: dataOnlyArr,
                catData: catOnlyArr
            };
        }
    }, chartAPI.sscartesian, {
        enablemousetracking: true
    });
}]);

FusionCharts.register('module', ['private', 'modules.renderer.js-multilevelpie', function () {
    var global = this,
        lib = global.hcLib,
        chartAPI = lib.chartAPI,
        win = global.window,
        creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname),
        parseUnsafeString = lib.parseUnsafeString,
        BLANKSTRING = lib.BLANKSTRING,
        preDefStr = lib.preDefStr,
        sStr = preDefStr.sStr,
        pluck = lib.pluck,
        COMPONENT = 'component',
        DATASET = 'dataset',
        UNDEFINED;

    /////////////// MultiLevelPie ///////////
    ///function to add mspie data
    chartAPI('multilevelpie', {
        standaloneInit: true,
        friendlyName: 'Multi-level Pie Chart',
        creditLabel: creditLabel,
        defaultDatasetType : 'multiLevelPie',
        applicableDSList: {
            'multiLevelPie': true
        },
        is3d: true,
        //disable legend
        hasLegend: false,
        hasCanvas: false,
        _createDatasets : function () {
            var iapi = this,
                components = iapi.components,
                //graphics = iapi.graphics,
                //datasetGroup = graphics.datasetGroup,
                dataObj = iapi.jsonData,
                dataset = dataObj.dataset || [],
                length = dataset.length,
                i,
                //j,
                //subDataset,
                datasetStore,
                datasetObj,
                //subDatasetLen,
                defaultSeriesType = iapi.defaultDatasetType,
                applicableDSList = iapi.applicableDSList,
                dsType,
                DsClass,
                datasetJSON,
                parentyaxis,
                categories = [],
                catLength,
                dsCount = {};

            categories = (iapi.config.categories = dataObj.category || []);
            catLength = categories.length;

            if(!length && catLength){
                dataset = categories;
                length = catLength;
            }
            // if the data has no categories in them.
            if (!catLength) {
                iapi.setChartMessage();
            }
            datasetStore = components.dataset  || (components.dataset = []);

            for(i = 0; i < length; i += 1) {

                datasetJSON = dataset[i];
                datasetJSON.seriesname &&  (datasetJSON.seriesname = parseUnsafeString(datasetJSON.seriesname));
                parentyaxis = datasetJSON.parentyaxis || BLANKSTRING;
                if (parentyaxis.toLowerCase() === sStr) {
                    dsType = pluck(datasetJSON.renderas, iapi.sDefaultDatasetType);
                }
                else {
                    dsType = pluck(datasetJSON.renderas, defaultSeriesType);
                }
                dsType = dsType && dsType.toLowerCase();
                if (!applicableDSList[dsType]) {
                    dsType = defaultSeriesType;
                }

                /// get the DsClass
                DsClass = FusionCharts.get(COMPONENT, [DATASET, dsType]);
                if (DsClass) {
                    if (dsCount[dsType] === UNDEFINED) {
                        dsCount[dsType] = 0;
                    }
                    else {
                        dsCount[dsType]++;
                    }
                    // If the dataset does not exists.
                    if (!datasetStore[0]) {
                        // create the dataset Object
                        datasetObj = new DsClass ();
                        datasetStore.push (datasetObj);
                        datasetObj.chart = iapi;
                        datasetObj.index = i;
                    }
                    else {
                        datasetObj = datasetStore[0];
                        datasetObj.JSONData = datasetJSON;
                    }
                    datasetObj.init (dataset);
                }
            }
        },
        _spaceManager: function () {
            var availableHeight,
                iapi = this,
                config = iapi.config;
            //****** Manage space
            iapi._allocateSpace(iapi._manageActionBarSpace &&
                iapi._manageActionBarSpace(config.availableHeight * 0.225) || {});
            availableHeight = config.canvasHeight * 0.7;
            // a space manager that manages the space for the tools as well as the captions.
            iapi._manageChartMenuBar(availableHeight);
        }
    }, chartAPI.guageBase);
}]);

FusionCharts.register('module', ['private', 'modules.renderer.js-radar', function () {
    var global = this,
        lib = global.hcLib,
        chartAPI = lib.chartAPI,
        win = global.window,
        creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname);

    /*--/ Chart Api for Radar /--*/
    chartAPI('radar', {
        friendlyName: 'Radar Chart',
        standaloneInit: true,
        creditLabel: creditLabel,
        defaultDatasetType : 'radar',
        applicableDSList: {'radar': true},
        hasLegend: true,
        areaAlpha: 50,
        defaultPlotShadow: 0,
        _postSpaceManagement : function () {
            var iapi = this,
                components = iapi.components,
                config = iapi.config,
                yAxis = components.yAxis && components.yAxis[0],
                legend = components.legend;

            yAxis.setAxisDimention ( {
                x : config.canvasLeft + config.canvasWidth/2,
                y : config.canvasTop,
                axisLength : config.canvasHeight/2
            });
            legend.postSpaceManager();
        },
        _mouseEvtHandler: function (e) {
            return chartAPI.dragbase._mouseEvtHandler.call(this, e);
        }

    }, chartAPI.mspolar, {
        radarradius: 0,
        radarborderthickness: 2,
        showvalues: 0,
        plotfillalpha: 50,
        enablemousetracking: true
    }, chartAPI.areabase);
}]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dragbase', function () {
    var global = this,
        lib = global.hcLib,
        win = global.window,
        doc = win.document,
        preDefStr = lib.preDefStr,
        colorStrings = preDefStr.colors,
        COLOR_FFFFFF = colorStrings.FFFFFF,
        ZEROSTRING = lib.ZEROSTRING,
        UNDERSCORE = preDefStr.UNDERSCORE,
        BLANK = lib.BLANKSTRING,
        BLANKSTRING = lib.BLANKSTRING,
        //add the tools thats are requared
        pluck = lib.pluck,
        getValidValue = lib.getValidValue,
        pluckNumber = lib.pluckNumber,
        extend2 = lib.extend2,
        hasSVG = lib.hasSVG,
        isIE = lib.isIE,
        dropHash = lib.regex.dropHash,
        HASHSTRING = lib.HASHSTRING,
        NONE = 'none',
        PXSTRING = 'px',
        schedular = lib.schedular,
        priorityList = lib.priorityList,
        extend = function(a, b) {
            var n;
            if (!a) {
                a = {};
            }
            for (n in b) {
                a[n] = b[n];
            }
            return a;
        },
        MOUSEOUT = 'mouseout',
        MOUSEMOVE = 'mousemove',
        COMPONENT = 'component',
        addEvent = lib.addEvent,
        removeEvent = lib.removeEvent,
        PX = PXSTRING,
        math = Math,
        mathMin = math.min,
        mathMax = math.max,
        hasTouch = lib.hasTouch,
        convertColor = lib.graphics.convertColor,
        chartAPI = lib.chartAPI,
        xssEncode = global.xssEncode,
        createElement = lib.createElement;

    chartAPI('dragbase', {
        configure: function () {
            var iapi = this,
                jsonData = iapi.jsonData,
                chartAttr = jsonData.chart,
                fontSize,
                chartConfig;
            iapi.base.base.configure.call(this);
            chartConfig = iapi.config;
            chartConfig.formAction = getValidValue(chartAttr.formaction);

            if (chartAttr.submitdataasxml === ZEROSTRING && !chartAttr.formdataformat) {
                chartAttr.formdataformat = global.dataFormats.CSV;
            }

            chartConfig.formDataFormat = pluck(chartAttr.formdataformat,
                global.dataFormats.XML);
            chartConfig.formTarget = pluck(chartAttr.formtarget, '_self');
            chartConfig.formMethod = pluck(chartAttr.formmethod, 'POST');
            chartConfig.submitFormAsAjax = pluckNumber(chartAttr.submitformusingajax, 1);
            chartConfig.restoreBtnTitle = pluck(chartAttr.restorebtntitle, 'Restore');
            chartConfig.submitBtnTitle = pluck(chartAttr.formbtntitle, 'Submit');

            // Form Button
            chartConfig.showFormBtn = pluckNumber(chartAttr.showformbtn, 1) && chartConfig.formAction;
            chartConfig.showRestoreBtn = pluckNumber(chartAttr.showrestorebtn, 1);
            chartConfig.formBtnTitle = pluck(chartAttr.formbtntitle, 'Submit');
            chartConfig.formBtnBorderColor = pluck(chartAttr.formbtnbordercolor, 'CBCBCB');
            chartConfig.formBtnBgColor = pluck(chartAttr.formbtnbgcolor, COLOR_FFFFFF);
            chartConfig.btnPadding = pluckNumber(chartAttr.btnpadding, 7); //2 px more for better presentation
            chartConfig.btnSpacing = pluckNumber(chartAttr.btnspacing, 5);
            chartConfig.formBtnStyle = {
                fontSize: chartConfig.style.outCanfontSize,
                fontFamily: chartConfig.style.outCanfontFamily,
                fontWeight: 'bold'
            };
            chartConfig.formBtnLabelFill = chartConfig.style.outCancolor;
            if (chartAttr.btntextcolor) {
                chartConfig.formBtnLabelFill = chartAttr.btntextcolor.replace(dropHash, HASHSTRING);
            }
            if ((fontSize = pluckNumber(chartAttr.btnfontsize)) >= 0) {
                chartConfig.formBtnStyle.fontSize = fontSize + PX;
            }
            chartConfig.restoreBtnWidth = pluckNumber(chartAttr.restorebtnwidth, 0);
            chartConfig.formBtnWidth = pluckNumber(chartAttr.formbtnwidth, 0);
            // Restore Button configuration
            chartConfig.restoreBtnBorderColor = pluck(chartAttr.restorebtnbordercolor,
                chartConfig.formBtnBorderColor);
            chartConfig.restoreBtnBgColor = pluck(chartAttr.restorebtnbgcolor,
                chartConfig.formBtnBgColor);
            chartConfig.restoreBtnStyle = {
                fontSize: chartConfig.formBtnStyle.fontSize,
                fontFamily: chartConfig.formBtnStyle.fontFamily,
                fontWeight: 'bold'
            };
            chartConfig.restoreBtnLabelFill = chartConfig.formBtnLabelFill;
            if (chartAttr.toolbary || chartAttr.toolbarx) {
                chartConfig.spaceHardCoded = true;
            }
            else {
                delete chartConfig.spaceHardCoded;
            }
        },
        _createToolBox: function () {
            var chart = this,
                toolBox = chart.components.tb || (chart.components.tb =
                    new (FusionCharts.register(COMPONENT, ['toolbox', 'toolbox']))()),
            toolBoxAPI, conf, SymbolStore, ComponentGroup, HorizontalToolbar,
            components = chart.components,
            buttonGroup,
            submitBtn,
            toolConf,
            toolbox,
            Symbol,
            restoreBtn,
            SmartLabel = chart.linkedItems.smartLabel,
            chartConf = chart.config,
            SymbolWithContext,
            showRestoreBtn = chartConf.showRestoreBtn,
            formAction = chartConf.formAction,
            restoreBtnTitle = chartConf.restoreBtnTitle,
            submitBtnTitle = chartConf.submitBtnTitle,
            formBtnStyle = chartConf.formBtnStyle,
            restoreBtnStyle = chartConf.restoreBtnStyle,
            restoreBtnWidth = chartConf.restoreBtnWidth,
            restoreBtnBgColor = chartConf.restoreBtnBgColor,
            restoreBtnBorderColor = chartConf.restoreBtnBorderColor,
            formBtnBgColor = chartConf.formBtnBgColor,
            formBtnBorderColor = chartConf.formBtnBorderColor,
            restoreBtnLabelFill = chartConf.restoreBtnLabelFill,
            formBtnLabelFill = chartConf.formBtnLabelFill,
            btnSpacing = chartConf.btnSpacing,
            padding = chartConf.btnPadding,
            formBtnWidth = chartConf.formBtnWidth,
            formBtnHeight,
            restoreBtnHeight,
            chartMenuBar = components.chartMenuBar,
            dimensions,
            actionBar = components.actionBar,
            pId;
             /* Do not reconfigure the toolbox if its already drawn.
             This flag is set falsy on each time configurations
            are updated. */
            if (chartMenuBar && chartMenuBar.drawn || actionBar && actionBar.drawn) {
                return;
            }
            pId = toolBox.init({
                graphics: chart.graphics || (chart.graphics = {}),
                chart: chart,
                components: chart.components
            });

            toolBox.pId = pId;

            toolBoxAPI = components.toolBoxAPI = toolBox.getAPIInstances(toolBox.ALIGNMENT_HORIZONTAL);
            SymbolStore = toolBoxAPI.SymbolStore;
            ComponentGroup = toolBoxAPI.ComponentGroup;
            HorizontalToolbar = toolBoxAPI.Toolbar;
            Symbol = toolBoxAPI.Symbol;
            SymbolWithContext = toolBoxAPI.SymbolWithContext;
            toolConf = toolBox.getDefaultConfiguration();
            conf = toolBox.getDefaultConfiguration();
            restoreBtn = new Symbol(restoreBtnTitle, true, (toolBox.idCount = toolBox.idCount || 0,
                toolBox.idCount++), toolBox.pId);
            submitBtn = new Symbol(submitBtnTitle, true, toolBox.idCount++, toolBox.pId);

            chartAPI.mscartesian._createToolBox.call(chart);

            if (chartConf.spaceHardCoded) {
                // preference is given to the chartMenuBar, if not exist, its the action bar.
                actionBar = components.actionBar = components.chartMenuBar || components.actionBar;
            }
            if (!(actionBar = components.actionBar)) {
                toolbox = new HorizontalToolbar(toolBox.idCount++, toolBox.pId);
                actionBar = (components.actionBar = toolbox);
            }

            chart.addConfigureOptions && chart.addConfigureOptions();

            buttonGroup = new ComponentGroup(toolBox.idCount++, toolBox.pId);
            SmartLabel.useEllipsesOnOverflow(chartConf.useEllipsesWhenOverflow);
            SmartLabel.setStyle(restoreBtnStyle);
            dimensions = SmartLabel.getOriSize(restoreBtnTitle);
            restoreBtnWidth = mathMax(dimensions.width, restoreBtnWidth);
            restoreBtnHeight = dimensions.height;
            SmartLabel.setStyle(formBtnStyle);
            dimensions = SmartLabel.getOriSize(submitBtnTitle);
            formBtnWidth = mathMax(formBtnWidth, dimensions.width);
            formBtnHeight = dimensions.height;
            restoreBtn.conf.width = restoreBtnWidth + padding;
            submitBtn.conf.width = formBtnWidth + padding;
            restoreBtn.conf.stroke = convertColor(restoreBtnBorderColor, 100);
            restoreBtn.conf.height = restoreBtnHeight + padding;
            submitBtn.conf.height = formBtnHeight + padding;
            submitBtn.conf.fill = convertColor(formBtnBgColor, 100);
            submitBtn.conf.labelFill = convertColor(formBtnLabelFill, 100);
            restoreBtn.conf.fill = convertColor(restoreBtnBgColor, 100);
            restoreBtn.conf.labelFill = convertColor(restoreBtnLabelFill, 100);
            submitBtn.conf.stroke = convertColor(formBtnBorderColor, 100);
            submitBtn.conf.btnTextStyle.fontSize = formBtnStyle.fontSize;
            restoreBtn.conf.btnTextStyle.fontSize = restoreBtnStyle.fontSize;
            conf.spacing = btnSpacing;
            buttonGroup.setConfiguaration({
                buttons : conf,
                group : {
                    fill : convertColor(COLOR_FFFFFF, 0),
                    borderThickness : 0
                }
            });
            if (showRestoreBtn) {
                buttonGroup.addSymbol(restoreBtn);
                // Restore Button
                restoreBtn.attachEventHandlers({
                    click: function () {
                        chart.restoreData();
                    }
                });
            }

            if (formAction) {
                buttonGroup.addSymbol(submitBtn);
                submitBtn.attachEventHandlers({
                    click: function () {
                        chart.submitData(global);
                    }
                });
            }
            // The restore and Submit buttons should always be placed in the bottom.
            buttonGroup.btnConfig.vAlign = 'b';

            actionBar.addComponent(buttonGroup);
            actionBar.toolbarConfig.fill = convertColor('EBEBEB', 0);
            actionBar.toolbarConfig.borderThickness = 0;
        },
        addConfigureOptions: function () {
            var chart = this,
                chartMenuTools = chart.chartMenuTools,
                components = chart.components,
                actionBar = components.actionBar,
                chartMenuBar = components.chartMenuBar,
                componentGroup = (chartMenuBar || actionBar).componentGroups[0],
                symbolList = componentGroup.symbolList[0],
                sListRef = symbolList.getListRefernce(),
                chartAttr = chart.jsonData.chart,
                allowAxisChange = pluckNumber(chartAttr.allowaxischange, 1),
                setChartTools = chartMenuTools.set,
                configureTools = [
                {
                    'Increase Upper Limit' : {
                        handler: function () {
                            var yAxis = chart.components.yAxis[0],
                                axisRange = yAxis.config.axisRange,
                                max = axisRange.max,
                                tickInterval = axisRange.tickInterval;
                            chart.changeUpperLimits(max + tickInterval);
                        },
                        action: 'click'
                    }
                },
                {
                    'Increase Lower Limit': {
                        handler: function () {
                            var yAxis = chart.components.yAxis[0],
                                axisRange = yAxis.config.axisRange,
                                min = axisRange.min,
                                tickInterval = axisRange.tickInterval;
                            chart.changeLowerLimits(min + tickInterval);
                        },
                        action: 'click'
                    }
                },
                {
                    'Decrease Upper Limit': {
                        handler: function () {
                            var yAxis = chart.components.yAxis[0],
                                axisRange = yAxis.config.axisRange,
                                max = axisRange.max,
                                tickInterval = axisRange.tickInterval;
                            chart.changeUpperLimits(max - tickInterval);
                        },
                        action: 'click'
                    }
                },
                {
                    'Decrease Lower Limit': {
                        handler: function () {
                            var yAxis = chart.components.yAxis[0],
                                axisRange = yAxis.config.axisRange,
                                min = axisRange.min,
                                tickInterval = axisRange.tickInterval;
                            chart.changeLowerLimits(min - tickInterval);
                        },
                        action: 'click'
                    }
                }
            ];
            if (allowAxisChange) {
                setChartTools(configureTools);
                sListRef.appendAsList(configureTools);
            }

        },
        drawAxisUpdateUI: function() {
            var chart = this,
                chartGraphics = chart.graphics,
                yAxis = chart.components.yAxis[0],
                axisRange = yAxis.config.axisRange,
                axisLabels = yAxis.getAxisConfig('extremeLabels') || [],
                chartConf = chart.config,
                min = axisRange.min,
                max = axisRange.max,
                maxLabel = axisLabels.lastLabel.graphic,
                minLabel = axisLabels.firstLabel.graphic,
                container = chart.linkedItems.container,
                inCanvasStyle = chart.config.style.inCanvasStyle || {},
                inputStyle = extend({
                    outline: NONE, // prevent chrome outlining
                    '-webkit-appearance': NONE, // disable ios background
                    filter: 'alpha(opacity=0)', // IE opacity
                    position: 'absolute',
                    background: 'transparent',
                    border: '1px solid #cccccc',
                    textAlign: 'right',
                    top: 0,
                    left: 0,
                    width: 50,
                    zIndex: 20,
                    opacity: 0,
                    borderRadius: 0,
                    display: 'block'
                }, inCanvasStyle),
                hashify = lib.hashify,
                poi = {
                    max: {
                        label: maxLabel,
                        value: max
                    },
                    min: {
                        label: minLabel,
                        value: min
                    }
                },
                poiObj,
                label,
                value,
                oldValue,
                box,
                isMaxLabel,
                inputElement,
                showRangeError,
                inputWidth,
                inputLeft,
                item,
                doAxisUpdate = function(value, oldvalue, isMax) {
                    var success;
                    // do not update if value has not changed
                    if (value === oldvalue + BLANKSTRING) {
                        return null;
                    }

                    success = isMax ?
                        chart.changeUpperLimits(Number(value), true) :
                        chart.changeLowerLimits(Number(value), true);

                    if (!success && showRangeError) {
                        chart.showMessage('Sorry! Not enough range gap to modify axis limit to ' +
                            (Number(value) || ZEROSTRING) +
                            '.<br />Please modify the data values to be within range.<br />&nbsp;<br />' +
                            '(click anywhere on the chart to close this message)', true);
                    }

                    return success;
                },
                onFocus = function (){
                    var ele = this,
                        inCanvasStyle = chart.config.style.inCanvasStyle || {},
                        styleObj = {
                            opacity: 1,
                            filter: 'alpha(opacity=100)', // IE opacity
                            color: inCanvasStyle.color
                        },
                        item;

                    if (styleObj.color) {
                        styleObj.color = hashify(styleObj.color);
                    }
                    ele.value = ele.dataValue;

                    for (item in styleObj) {
                        ele.style[item] = styleObj[item];
                    }

                    ele.justFocussed = true;
                    ele.hasFocus = true;
                    ele.axisLabel && ele.axisLabel.hide();
                    if (!chart.graphics.hiddenAxisLabels) {
                        chart.graphics.hiddenAxisLabels = [];
                    }
                    chart.graphics.hiddenAxisLabels.push(ele.axisLabel);
                },
                onMouseUp = (function () {
                    return function() {


                        var ele = this;
                        if (ele.justFocussed) {

                            ele.justFocussed = false;
                            if (!hasTouch) {
                                setTimeout(function() {
                                    ele.select();
                                }, 0);
                            }
                        }
                    };
                })(),
                onBlur = function () {
                    var ele = this,
                        newValue = ele.value,
                        oldValue = ele.oldValue,
                        isMaxLabel = ele.isMaxLabel,
                        success = doAxisUpdate(newValue, oldValue,
                            isMaxLabel);

                    if (success !== true) {
                        ele.style.opacity = 0;
                        ele.style.filter = 'alpha(opacity=0)';
                         // IE opacity
                        ele.axisLabel && ele.axisLabel.show();
                    }

                    if (isIE) {
                        // To call the actual blur on the element in case of IE
                        doc.getElementsByTagName('body')[0].focus &&
                        doc.getElementsByTagName('body')[0].focus();
                    }

                    ele.justFocussed = false;
                    ele.hasFocus = false;
                },
                onKeyUp = function (e) {
                    var ele = this,
                        keyCode = e.originalEvent.keyCode,
                        newValue = ele.value,
                        oldValue = ele.oldValue,
                        isMaxLabel = ele.isMaxLabel,
                        success;

                    if (keyCode === 13) {
                        success = doAxisUpdate(newValue, oldValue,
                            isMaxLabel);
                        if (success === false) {
                            ele.style.color = '#dd0000';
                        }
                        else {
                            lib.dem.fire(ele, 'blur', e);
                        }
                    } else if (keyCode === 27) {
                        ele.value = oldValue;
                        lib.dem.fire(ele, 'blur', e);
                    }
                },
                defaultAction = function (inputElement) {
                    return function(e) {
                        if (inputElement.parentNode) {
                            lib.dem.fire(inputElement, 'blur', e);
                        }
                    };
                },
                destroyFn = function (inputElement, defaultAction) {
                    return function() {
                        removeEvent(chart, 'defaultprevented', defaultAction);
                        inputElement.parentNode.removeChild(inputElement);

                    };
                },
                defaultActionIE = function (inputElement) {
                    return function(e) {
                        if (e.srcElement !== inputElement && inputElement.hasFocus) {
                            lib.dem.fire(inputElement, 'blur', e);
                        }
                    };
                },
                destroyFnIE = function (inputElement, defaultAction) {
                    return function() {
                        removeEvent(container, 'mousedown', defaultAction);
                        inputElement.parentNode.removeChild(inputElement);
                    };
                },
                defActionFn,
                defActionFnIE,
                prop;

            for (prop in poi) {
                poiObj = poi[prop];
                label = poiObj.label;
                value = poiObj.value;
                oldValue = (poiObj.oldValue = value);
                box = label && label.getBBox();
                isMaxLabel = prop === 'max' ? true : false;

                if (!chartGraphics.inputElements) {
                    chartGraphics.inputElements = {};
                }
                inputElement = chartGraphics.inputElements[prop];

                // Take precaution to ensure that we do not do any computation
                // in case chart is destroyed.
                if (!(box && label)) {
                    if (inputElement) {
                        inputElement.style.display = 'none';
                    }
                    continue;
                }

                // Decide the width and position of inputbox.
                inputWidth = box.x + box.width - chartConf.marginLeft;
                inputLeft = chartConf.canvasLeft - inputWidth - (hasSVG ? 4 : 5);

                extend(inputStyle, {
                    top: (box.y + (hasSVG ? -1 : 0)) + PX,
                    left: inputLeft + PX,
                    width: inputWidth + PX
                });

                if (!inputElement) {
                    // Create the input-box element and provide its initial attrs
                    // and styling.
                    inputElement = chartGraphics.inputElements[prop] = createElement(
                        'input', {
                            type: 'text',
                            value: value,
                            name: value || BLANKSTRING
                        }, container, true);

                    // Add events to make the textboxes visible on focus and hide
                    // when not.
                    lib.dem.listen(inputElement, ['focus', 'mouseup', 'blur', 'keyup'], [
                        onFocus,
                        onMouseUp,
                        onBlur,
                        onKeyUp
                    ]);

                    // Mark it for no event prevention
                    inputElement.setAttribute('isOverlay', 'true');

                    // When out of textbox is clicked, we need to emulate blur event.
                    // This is because the container grabs the mousedown event for
                    // better UX.
                    if (hasSVG) {
                        addEvent(container, 'defaultprevented', defActionFn = defaultAction(inputElement));
                        // cleanup
                        addEvent(container, 'destroy', destroyFn(inputElement, defActionFn));
                    } else {
                        addEvent(container, 'mousedown', defActionFnIE = defaultActionIE(inputElement));
                        // cleanup
                        addEvent(container, 'destroy', destroyFnIE(inputElement, defActionFnIE));
                    }

                }
                inputElement.dataValue = value;
                if (inputStyle.color) {
                    inputStyle.color = hashify(inputStyle.color);
                }
                for (item in inputStyle) {
                    inputElement.style[item] = inputStyle[item];
                }
                inputElement.value = value;
                inputElement.oldValue = value;
                inputElement.name = value || BLANKSTRING;
                inputElement.axisLabel = label;
                inputElement.isMaxLabel = isMaxLabel;
            }
        },
        changeUpperLimits: function (upperLimit) {
            var chart = this,
                components = chart.components,
                yAxis = components.yAxis[0],
                axisRange = yAxis.config.axisRange,
                min = axisRange.min,
                yAxisMax = axisRange.max,
                config = chart.config,
                maxValue = config.yMax,
                limitchanged = false,
                hiddenAxisLabels = chart.graphics.hiddenAxisLabels || [],
                len = hiddenAxisLabels.length,
                i,
                label,
                max;

            if ((upperLimit !== undefined) && upperLimit > maxValue && upperLimit !== yAxisMax) {
                max = upperLimit;
                limitchanged = true;
            }
            else {
                max = maxValue > yAxisMax ? maxValue : yAxisMax;
            }

            if (limitchanged) {
                yAxis.setAxisConfig({
                    axisMaxValue : max,
                    axisMinValue : min,
                    showUpperLimit: true
                });
                yAxis.setDataLimit(max, min);
                chart._manageSpace();
                chart._postSpaceManagement();
                chart._drawCanvas();
                chart.chartMenuBar && chart._drawChartMenuBar();
                chart._manageCaptionPosition();
                chart._drawCanvas();
                //iapi._drawCaption ();
                components.caption && components.caption.draw();

                chart.drawLegend();

                chart.drawActionBar && chart.drawActionBar();

                // Show hidden axis labels
                for (i = 0; i < len; i++) {
                    label = hiddenAxisLabels[i];
                    label.show();
                }

                chart._drawAxis && chart._drawAxis();
                chart._drawDataset ();
                chart.drawAxisUpdateUI();
            }
            return limitchanged;
        },
        changeLowerLimits: function (lowerLimit) {
            var chart = this,
                components = chart.components,
                yAxis = components.yAxis[0],
                axisRange = yAxis.config.axisRange,
                minValue = chart.config.yMin,
                max = axisRange.max,
                min,
                limitchanged = false,
                hiddenAxisLabels = chart.graphics.hiddenAxisLabels || [],
                len = hiddenAxisLabels.length,
                i,
                label,
                yMin = axisRange.min;
            if ((lowerLimit !== undefined) && lowerLimit < minValue && lowerLimit !== yMin) {
                min = lowerLimit;
                limitchanged = true;
            } else {
                lowerLimit = minValue < yMin ? minValue : yMin;
            }
            if (limitchanged) {
                yAxis.setAxisConfig({
                    axisMaxValue : max,
                    axisMinValue : lowerLimit
                });
                yAxis.setDataLimit(max, min);
                chart._manageSpace();
                chart._postSpaceManagement();
                chart._drawCanvas();
                chart.chartMenuBar && chart._drawChartMenuBar();
                chart._manageCaptionPosition();
                chart._drawCanvas();
                //iapi._drawCaption ();
                components.caption && components.caption.draw();

                chart.drawLegend();

                chart.drawActionBar && chart.drawActionBar();

                // Show hidden axis labels
                for (i = 0; i < len; i++) {
                    label = hiddenAxisLabels[i];
                    label.show();
                }

                chart._drawAxis && chart._drawAxis();
                chart._drawDataset ();
                chart.drawAxisUpdateUI();
            }
            return limitchanged;
        },
        eiMethods: {
            getDataWithId: function () {
                var vars = this.jsVars,
                    iapi = vars.instanceAPI,
                    dataObj = iapi.getJSONData(),
                    returnObj = [
                        [BLANK]
                    ],
                    datasets = dataObj.dataset,
                    catArr = (dataObj.categories && dataObj.categories[0] &&
                        dataObj.categories[0].category),
                    i = (datasets && datasets.length) || 0,
                    vLinePassed = 0,
                    setArr,
                    catName,
                    catObj,
                    set,
                    DS,
                    item,
                    dsID,
                    id,
                    j,
                    ln;

                while (i--) {
                    DS = datasets[i];
                    if (DS) {
                        returnObj[0][i + 1] = DS.id || DS.seriesname;
                        dsID = DS.id || (i + 1);
                        set = DS.data;
                        ln = (set && set.length) || 0;
                        for (j = 0; j < ln; j += 1) {
                            item = j + 1;
                            if (!returnObj[item]) {
                                catObj = (catArr && catArr[j + vLinePassed]) || {};
                                while (catObj.vline) {
                                    vLinePassed += 1;
                                    catObj = catArr[j + vLinePassed] || {};
                                }
                                catName = catObj.label || catObj.name || BLANK;
                                returnObj[item] = [catName];
                            }
                            setArr = returnObj[item];
                            id = set[j].id || (item + UNDERSCORE + dsID);
                            setArr[i + 1] = [id, Number(set[j].value)];
                        }
                    }
                }

                return returnObj;
            },
            getData: function(format) {
                // create a two dimensional array as given in the docs
                var vars = this.jsVars,
                    iapi = vars.instanceAPI,
                    dataObj = iapi.getJSONData(),
                    returnObj = [
                        [BLANK]
                    ],
                    datasets = dataObj.dataset,
                    catArr = (dataObj.categories && dataObj.categories[0] &&
                        dataObj.categories[0].category),
                    i = (datasets && datasets.length) || 0,
                    vLinePassed = 0,
                    catObj,
                    setArr,
                    catName,
                    set,
                    item,
                    ln,
                    j;

                // When a format is provided
                if (format) {
                    // no transcoding needed for json
                    if (/^json$/ig.test(format)) {
                        returnObj = dataObj;
                    } else {
                        returnObj = global.core.transcodeData.call(iapi.chartInstance, dataObj,
                            'json', format);
                    }
                }
                // if no format has been specified, return data as 2d array.
                else {
                    while (i--) {
                        set = datasets[i];
                        if (set) {
                            returnObj[0][i + 1] = datasets[i].seriesname;

                            set = datasets[i] && datasets[i].data;
                            ln = (set && set.length) || 0;
                            for (j = 0; j < ln; j += 1) {
                                item = j + 1;
                                if (!returnObj[item]) {
                                    catObj = (catArr && catArr[j + vLinePassed]) || {};
                                    while (catObj.vline) {
                                        vLinePassed += 1;
                                        catObj = catArr[j + vLinePassed] || {};
                                    }
                                    catName = catObj.label || catObj.name || BLANK;
                                    returnObj[item] = [catName];
                                }
                                setArr = returnObj[item];
                                setArr[i + 1] = Number(set[j].value);
                            }
                        }
                    }
                }

                return returnObj;
            },
            setUpperLimit: function (limit, callback) {
                var iapi = this.apiInstance,
                    list = iapi.getJobList(),
                    output,
                    asyncRender = iapi.chartInstance.args.asyncRender;

                if (callback || asyncRender) {
                    list.eiMethods.push(schedular.addJob(function(){
                        output = iapi.changeUpperLimits(limit);
                        if (typeof callback === 'function') {
                            callback(output);
                        }
                    }, iapi, [], priorityList.postRender));
                }
                else {
                    return iapi.changeUpperLimits(limit);
                }
            },
            setLowerLimit: function (limit, callback) {
                var iapi = this.apiInstance,
                    list = iapi.getJobList(),
                    output,
                    asyncRender = iapi.chartInstance.args.asyncRender;

                if (callback || asyncRender) {
                    list.eiMethods.push(schedular.addJob(function(){
                        output = iapi.changeLowerLimits(limit);
                        if (typeof callback === 'function') {
                            callback(output);
                        }
                    }, iapi, [], priorityList.postRender));
                }
                else {
                    return iapi.changeLowerLimits(limit);
                }
            },
            getLowerLimit: function (callback) {
                var iapi = this.apiInstance,
                    components = iapi.components,
                    yAxis = components.yAxis && components.yAxis[0],
                    list = iapi.getJobList();

                if (yAxis) {
                    if (callback) {
                        list.eiMethods.push(schedular.addJob(function () {
                            callback(yAxis.config.axisRange.min);
                        }, iapi, [], priorityList.postRender));
                    }
                    else {
                        return yAxis.config.axisRange.min;
                    }
                }

            },
            getUpperLimit: function (callback) {
                var iapi = this.apiInstance,
                    components = iapi.components,
                    yAxis = components.yAxis && components.yAxis[0],
                    list = iapi.getJobList();

                if (yAxis) {
                    if (callback) {
                        list.eiMethods.push(schedular.addJob(function () {
                            callback(yAxis.config.axisRange.max);
                        }, iapi, [], priorityList.postRender));
                    }
                    else {
                        return yAxis.config.axisRange.max;
                    }
                }
            }
        },
        restoreData: function () {
            var chart = this,
                components = chart.components,
                yAxis = components.yAxis[0],
                datasets = components.dataset,
                legend = components.legend,
                len = datasets.length,
                dataset,
                hiddenAxisLabels = chart.graphics.hiddenAxisLabels || [],
                label,
                i;

            chart.config.isDataRestored = true;
            for (i = 0; i < len; i++) {
                dataset = datasets[i];
                dataset.configure();
            }
            yAxis.setAxisConfig({
                axisMaxValue : undefined,
                axisMinValue : undefined
            });
            chart._setAxisLimits();

            len = hiddenAxisLabels.length;
            for (i = 0; i < len; i++) {
                label = hiddenAxisLabels[i];
                label.show();
            }
            chart._drawAxis();
            chart._drawDataset();
            legend._drawPointLegendItem();
            chart.drawAxisUpdateUI();
            delete chart.config.isDataRestored;
            lib.raiseEvent('dataRestored', {}, chart.chartInstance, [chart.chartInstance.id]);
        },
        submitData: function (global) {
            var chart = this,
                iapi = chart.chartInstance,
                ajaxObj = new global.ajax(),
                chartConf = chart.config,
                json = global.dataFormats.JSON,
                csv = global.dataFormats.CSV,
                xml = global.dataFormats.XML,
                url = chartConf.formAction,
                chartInstance = chart.chartInstance,
                submitAsAjax = chartConf.submitFormAsAjax,
                requestType,
                data,
                paramObj,
                tempSpan,
                formEle;

            if (chartConf.formDataFormat === json) {
                requestType = json;
                data = JSON.stringify(chart.getJSONData());
            } else if (chart.formDataFormat === csv) {
                requestType = csv;
                data = iapi.getCSVString && iapi.getCSVString();
                if (data === undefined) {
                    data = global.core.transcodeData(chart.getJSONData(), json, csv);
                }
            } else {
                requestType = xml;
                data = global.core.transcodeData(chart.getJSONData(), json, xml);
            }

            // cancel data submit function added in event options
            /**
             * For interative charts like `Select Scatter`, `DragNode`, `Dragable Column2D ` and etc., data
             * points value can be selected for `Scatter Chart` and values can be changed for dragable charts by
             * clicking and dragging the data points whose data point values can be sent to an URL by ajax POST.
             * This is the first event raised when `Submit` button is clicked where the current chart data is
             * about to be sent to the set URL.
             *
             * @event FusionCharts#beforeDataSubmit
             * @group chart-powercharts
             *
             * @param {string} data - Contains the XML string with complete chart data at it's current state.
             *
             */
            global.raiseEvent('beforeDataSubmit', {
                data: data
            }, chartInstance, undefined, function() {
                // After the collation is done, we have to submit the data using
                // ajax or form submit method.
                if (!submitAsAjax) {
                    // Create a hidden form with data inside it.
                    tempSpan = win.document.createElement('span');
                    tempSpan.innerHTML = '<form style="display:none" action="' +
                        url + '" method="' + chartConf.formMethod + '" target="' + chartConf.formTarget +
                        '"> <input type="hidden" name="strXML" value="' +
                        xssEncode(data) + '"><input type="hidden" name="dataFormat" value="' +
                        requestType.toUpperCase() + '" /></form>';

                    formEle = tempSpan.removeChild(tempSpan.firstChild);

                    // Append the form to body and then submit it.
                    win.document.body.appendChild(formEle);
                    formEle.submit && formEle.submit();
                    // cleanup
                    formEle.parentNode.removeChild(formEle);
                    tempSpan = formEle = null;
                }
                else {
                    ajaxObj.onError = function(response, wrapper, ajaxData, url) {
                    /**
                     * For interative charts like `Select Scatter`, `DragNode`, `Dragable Column2D ` and etc.,
                     * data points value can be selected for `Scatter Chart` and values can be changed for
                     * dragable charts by clicking and dragging the data points whose data point values can be
                     * sent to an URL by ajax POST. This event is raised if there is an ajax error in sending
                     * the chart XML data.
                     *
                     * @event FusionCharts#dataSubmitError
                     * @group chart-powercharts
                     *
                     * @param {string} data - Contains the XML string with complete chart data.
                     * @param {number} httpStatus - Tells the status code of the ajax POST request
                     * @param {string} statusText - Contains the ajax error message.
                     * @param {string} url - URL to which the data is sent as ajax POST request.
                     * @param {object} xhrObject - XMLHttpRequest object which takes care of sending the XML
                     * chart data. In case of error, this object won't be defined.
                     */
                        lib.raiseEvent('dataSubmitError', {
                            xhrObject: wrapper.xhr,
                            url: url,
                            statusText: response,
                            httpStatus: (wrapper.xhr && wrapper.xhr.status) ?
                                wrapper.xhr.status : -1,
                            data: data
                        }, chartInstance, [chartInstance.id, response, wrapper.xhr && wrapper.xhr.status]);
                    };

                    ajaxObj.onSuccess = function(response, wrapper, ajaxData, url) {
                    /**
                     * For interative charts like `Select Scatter`, `DragNode`, `Dragable Column2D ` and etc.,
                     * data points value can be selected for `Scatter Chart` and values can be changed for
                     * dragable charts by clicking and dragging the data points whose data point values can be
                     * sent to an URL by ajax POST. This event is raised when the ajax POST request is
                     * successfully completed.
                     *
                     * @event FusionCharts#dataSubmitted
                     * @group chart-powercharts
                     *
                     * @param {string} data - Contains the XML string with complete chart data.
                     * @param {string} reponse - Contains the reponse returned by the web server to which the
                     * HTTP POST request was submitted.
                     * @param {string} url - URL to which the data is sent as HTTP POST request.
                     * @param {object} xhrObject - XMLHttpRequest object which takes care of sending the XML
                     * chart data
                     */
                        lib.raiseEvent('dataSubmitted', {
                            xhrObject: ajaxObj,
                            response: response,
                            url: url,
                            data: data
                        }, chartInstance, [chartInstance.id, response]);
                    };

                    paramObj = {};
                    paramObj['str' + requestType.toUpperCase()] = data;

                    if (ajaxObj.open) {
                        ajaxObj.abort();
                    }
                    ajaxObj.post(url, paramObj);
                }
            }, function() {
                /**
                 * For interative charts like `Select Scatter`, `DragNode`, `Dragable Column2D ` and etc.,
                 * data points value can be selected for `Scatter Chart` and values can be changed for
                 * dragable charts by clicking and dragging the data points whose data point values can be
                 * sent to an URL by ajax POST. This event is raised when `preventDefault()` method is called
                 * from the `eventObject` of FusionCharts#beforeDataSubmit event.
                 *
                 * @event FusionCharts#dataSubmitCancelled
                 * @group chart-powercharts
                 *
                 * @param {string} data - Contains the XML string with complete chart data.
                 * @param {number} httpStatus - Tells the status code of the ajax POST request
                 * @param {string} statusText - Contains the ajax error message.
                 * @param {string} url - URL to which the data is sent as ajax POST request.
                 * @param {object} xhrObject - XMLHttpRequest object which takes care of sending the XML
                 * chart data. In case of error, this object won't be defined.
                 * @example
                 * FusionCharts.addEventListener('beforeDataSubmit', function(eventObject, parameterObject) {
                 *   eventObject.preventDefault();
                 * }
                 */
                global.raiseEvent('dataSubmitCancelled', {
                    data: data
                }, chartInstance);
            });
        },
        getJSONData: function () {
            var chart = this,
                defaultDatasetType = chart.defaultDatasetType && chart.defaultDatasetType.toLowerCase(),
                chartComponents = chart.components,
                groupManager = chartComponents['datasetGroup_' + defaultDatasetType],
                datasets = chartComponents.dataset,
                rawDatasets = chart.jsonData.dataset,
                rawDataset,
                rawObj = chart.jsonData,
                len = datasets.length,
                datasetsArr = [],
                jsonObj,
                dataObj,
                dataset,
                i;
            if (groupManager && groupManager.getJSONData) {
                datasetsArr = groupManager.getJSONData();
            }
            else {
                for (i = 0; i < len; i++) {
                    dataset = datasets[i];
                    dataObj = dataset.getJSONData();
                    rawDataset = rawDatasets[i] || {};
                    delete rawDataset.data;
                    datasetsArr.push(extend2(rawDataset, dataObj));
                }
            }
            jsonObj = extend2({}, rawObj);
            jsonObj.dataset = datasetsArr;
            return jsonObj;
        },
        _setDataLimits: function () {
            var chart = this,
                datasets = chart.components.dataset,
                config = chart.config,
                yMax = -Infinity,
                yMin = +Infinity,
                dataset,
                limits,
                len,
                i;
            len = datasets.length;
            for (i = 0; i < len; i++) {
                dataset = datasets[i];
                limits = dataset.getDataLimits();
                yMax = mathMax(yMax, limits.max);
                yMin = mathMin(yMin, limits.min);
            }
            config.yMax = yMax;
            config.yMin = yMin;
        },
        _mouseEvtHandler: function (e) {
            var chart = this,
                data = e.data,
                mouseTracker = data.mouseTracker,
                oriEvent = e.originalEvent,
                chartConfig = chart.config,
                canvasLeft = chartConfig.canvasLeft,
                canvasRight = chartConfig.canvasRight,
                canvasBottom = chartConfig.canvasBottom,
                canvasTop = chartConfig.canvasTop,
                datasets = chartConfig.datasetOrder || chart.components.dataset,
                coordinate = lib.getMouseCoordinate(chart.linkedItems.container, oriEvent, chart),
                chartX = coordinate.chartX,
                chartY = coordinate.chartY,
                dataset,
                hoveredInfo,
                pointFound = false,
                i = datasets.length,
                j,
                l,
                derivedEvensInfo,
                _lastDatasetIndex = mouseTracker._lastDatasetIndex,
                _lastPointIndex = mouseTracker._lastPointIndex,
                dragStart,
                eventType,
                tolerance = chartConfig.dragTolerance || 0;

            (_lastPointIndex !== undefined) &&
                (dragStart = datasets[_lastDatasetIndex].components.data[_lastPointIndex].config.dragStart);

            // @todo we have to implement this for charts with more than one canvas like candle stick
            // if inside the canvas
            if (!dragStart && chartX > canvasLeft - tolerance && chartX < canvasRight + tolerance &&
                        chartY > canvasTop - tolerance && chartY < canvasBottom + tolerance ||
                                                        !dragStart && chart.config.plotOverFlow) {

                // @todo make sure the datasets are as per their z-order
                while (i-- && !pointFound) {
                    dataset = datasets[i];
                    if (dataset && dataset.visible) {
                        hoveredInfo = dataset._getHoveredPlot && dataset._getHoveredPlot(chartX, chartY);
                        if (hoveredInfo && hoveredInfo.hovered) {
                            pointFound = true;
                            hoveredInfo.datasetIndex = i;
                            derivedEvensInfo = mouseTracker._getMouseEvents(e, hoveredInfo.datasetIndex,
                                hoveredInfo.pointIndex);
                        }
                    }
                }
            }

            //for drag event
            if(dragStart && _lastDatasetIndex !== undefined) {
                eventType = (e.type === MOUSEOUT) ? MOUSEMOVE : e.type;
                datasets[_lastDatasetIndex] && datasets[_lastDatasetIndex]._firePlotEvent &&
                        datasets[_lastDatasetIndex]._firePlotEvent(eventType, _lastPointIndex, e);
            }
            // @todo instead of sending event names, create a event object of that type and send it
            // fire out on last hovered plot
            if (!dragStart && (!pointFound || (derivedEvensInfo && derivedEvensInfo.fireOut)) &&
                        _lastDatasetIndex !== undefined) {
                // delete stored last ds details
                delete mouseTracker._lastDatasetIndex;
                delete mouseTracker._lastPointIndex;

                datasets[_lastDatasetIndex] && datasets[_lastDatasetIndex]._firePlotEvent &&
                    datasets[_lastDatasetIndex]._firePlotEvent(MOUSEOUT, _lastPointIndex, e);

                // @todo scope to have sticky tracked tooltip
            }
            // fire remaining events
            if (pointFound) {
                l = derivedEvensInfo.events && derivedEvensInfo.events.length;
                // store the index of the hovered DS and plot
                mouseTracker._lastDatasetIndex = hoveredInfo.datasetIndex;
                _lastPointIndex = mouseTracker._lastPointIndex = hoveredInfo.pointIndex;
                for (j = 0; j < l; j += 1) {
                    dataset && dataset._firePlotEvent && dataset._firePlotEvent(derivedEvensInfo.events[j],
                        _lastPointIndex, e);
                }
            }
        }
    }, chartAPI.mscartesian);
}]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dragnode', function () {
    var global = this,
        lib = global.hcLib,
        win = global.window,
        ZEROSTRING = lib.ZEROSTRING,
        //add the tools thats are requared
        pluck = lib.pluck,
        getValidValue = lib.getValidValue,
        pluckNumber = lib.pluckNumber,
        extend2 = lib.extend2,
        COMPONENT = 'component',
        componentDispose = lib.componentDispose,
        math = Math,
        mathMin = math.min,
        mathMax = math.max,
        creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname),
        chartAPI = lib.chartAPI,
        DATASET = 'dataset',
        DATASET_GROUP = 'datasetGroup',
        UNDEFINED;


    chartAPI('dragnode', {
        friendlyName: 'Dragable Node Chart',
        standaloneInit: true,
        fireGroupEvent: true,
        hasLegend: true,
        numVDivLines: 0,
        numDivLines: 0,
        showLimits: 0,
        setadaptivexmin: 1,
        showdivlinevalues: 0,
        showzeroplane: 0,
        showyaxisvalues: 0,
        dontShowLegendByDefault: true,
        creditLabel: creditLabel,
        //showvlimits: 0,
        defaultDatasetType: 'dragnode',
        configure: function () {
            var iapi = this,
                jsonData = iapi.jsonData,
                chartAttr = jsonData.chart,
                config;
            chartAPI.dragbase.configure.call(this);
            config = iapi.config;
            config.formAction = getValidValue(chartAttr.formaction);

            if (chartAttr.submitdataasxml === ZEROSTRING && !chartAttr.formdataformat) {
                chartAttr.formdataformat = global.dataFormats.CSV;
            }

            config.formDataFormat = pluck(chartAttr.formdataformat,
                global.dataFormats.XML);
            config.formTarget = pluck(chartAttr.formtarget, '_self');
            config.formMethod = pluck(chartAttr.formmethod, 'POST');
            config.submitFormAsAjax = pluckNumber(chartAttr.submitformusingajax, 1);
            config.viewMode = pluckNumber(chartAttr.viewmode, 0);
        },
        _createDatasets : function () {
            var iapi = this,
                config = iapi.config,
                components = iapi.components,
                dataObj = iapi.jsonData,
                dataset = dataObj.dataset,
                connectorSet = dataObj.connectors,
                labelSet = dataObj.labels && dataObj.labels.label || [],
                datasetlen = dataset && dataset.length,
                connLength =  connectorSet && connectorSet.length,
                labelsLength = labelSet && labelSet.length || [],
                legend = components.legend,
                i,
                datasetStore,
                datasetObj,
                GroupManager,
                DsGroupClass,
                datasetJSON,
                Dragnode,
                connectorObj,
                connectors,
                ConnectorClass,
                DragLabelClass,
                labelObj,
                prevDataLength,
                currDataLength,
                count = 0,
                JSONData,
                datasetMap = config.datasetMap || (config.datasetMap = {
                    connectors : [],
                    dragnode : [],
                    labels : []
                }),
                dsTypeRef,
                dsRef,
                tempMap = {
                    connectors : [],
                    dragnode : [],
                    labels : []
                },
                length,
                j,
                dsCount = {},
                dsType,
                groupManagerName = 'datasetGroup_dragnode';

            if (!dataset) {
                iapi.setChartMessage();
                return;
            }

            iapi.config.categories = dataObj.categories && dataObj.categories[0].category;

            datasetStore = components.dataset = [];
            // get the ds group class
            DsGroupClass = FusionCharts.register(COMPONENT, [DATASET_GROUP, 'dragnode']);
            GroupManager = components[groupManagerName];
            if (DsGroupClass && !GroupManager) {
                GroupManager = components[groupManagerName] = new DsGroupClass();
                GroupManager.chart = iapi;
                GroupManager.init();
            }
            Dragnode = FusionCharts.get(COMPONENT, [DATASET, 'Dragnode']);
            ConnectorClass = FusionCharts.get(COMPONENT, [DATASET, 'Connector']);
            DragLabelClass = FusionCharts.get(COMPONENT, [DATASET, 'DragableLabels']);
            for(i = 0; i < datasetlen; i++) {
                dsType = 'dragnode';
                dsTypeRef = datasetMap[dsType];
                dsRef = dsTypeRef[0];
                if (dsCount[dsType] === UNDEFINED) {
                    dsCount[dsType] = 0;
                }
                else {
                    dsCount[dsType]++;
                }
                if (!dsRef) {
                    datasetJSON = dataset[i];
                    datasetObj = new Dragnode();
                    datasetObj.chart = iapi;
                    tempMap[dsType].push(datasetObj);
                    datasetStore.push(datasetObj);
                    datasetObj.chart = iapi;
                    datasetObj.index = i;
                    datasetObj.init(datasetJSON);
                    GroupManager.addDataset(datasetObj, i);
                }
                else {

                    datasetJSON = dataset[i];
                    JSONData = (dsRef.components && dsRef.components.data) || [];
                    tempMap[dsType].push(dsRef);
                    datasetStore.push (dsRef);
                    prevDataLength = JSONData.length;
                    currDataLength = datasetJSON && datasetJSON.data && datasetJSON.data.length || 0;
                    // Removing data plots if the number of current data plots is more than the existing ones.
                    if (prevDataLength > currDataLength) {
                        dsRef.removeData(currDataLength - 1,
                            prevDataLength - currDataLength);
                    }
                    dsRef.JSONData = datasetJSON;
                    dsRef.configure();
                    dsTypeRef.shift();
                }
                count++;
            }
            for (i = 0; i < connLength; i++) {
                dsType = 'connectors';
                connectors = connectorSet[i];
                dsTypeRef = datasetMap[dsType];
                dsRef = dsTypeRef[0];
                if (dsCount[dsType] === UNDEFINED) {
                    dsCount[dsType] = 0;
                }
                else {
                    dsCount[dsType]++;
                }
                if (!dsRef) {
                    connectorObj = new ConnectorClass();
                    connectorObj.chart = iapi;
                    connectorObj.index = i;
                    tempMap[dsType].push(connectorObj);
                    datasetStore.push(connectorObj);
                    connectorObj.init(connectors);
                    GroupManager.addConnectors(connectorObj, i);
                }
                else {
                    JSONData = (dsRef.components && dsRef.components.data) || [];
                    prevDataLength = JSONData.length;
                    currDataLength = connectors.connector && connectors.connector.length || 0;
                    tempMap[dsType].push(dsRef);
                    datasetStore.push (dsRef);
                    // Removing data plots if the number of current data plots is more than the existing ones.
                    if (prevDataLength > currDataLength) {
                        dsRef.removeData(currDataLength - 1,
                            prevDataLength - currDataLength);
                    }
                    dsRef.JSONData = connectors;
                    dsRef.configure();
                    dsTypeRef.shift();
                }
                count++;
            }

            dsType = 'labels';
            dsTypeRef = datasetMap[dsType];
            dsRef = dsTypeRef[0];
            if (dsCount[dsType] === UNDEFINED) {
                dsCount[dsType] = 0;
            }
            else {
                dsCount[dsType]++;
            }
            if (!dsRef) {
                labelObj = new DragLabelClass();
                labelObj.chart = iapi;
                tempMap[dsType].push(labelObj);
                datasetStore.push(labelObj);
                labelObj.init(labelSet);
                GroupManager.addLabels(labelObj, 0);
            }
            else {
                JSONData = dsRef.JSONData;
                prevDataLength = JSONData.length;
                currDataLength = labelsLength;
                tempMap[dsType].push(dsRef);
                datasetStore.push (dsRef);
                // Removing data plots if the number of current data plots is more than the existing ones.
                if (prevDataLength > currDataLength) {
                    dsRef.removeData(currDataLength - 1,
                        prevDataLength - currDataLength);
                }
                dsRef.JSONData = labelSet;
                dsRef.configure();
                dsTypeRef.shift();
            }

            iapi.config._datasetUpdated = true;
            // Removing unused datasets if any
            for (dataset in datasetMap) {
                dsTypeRef  = datasetMap[dataset];
                length = dsTypeRef.length;
                count = dsCount[dataset] || -1;
                if (length) {
                    for (j = 0; j < length; j++) {
                        if (dataset === 'dragnode') {

                            GroupManager.removeNodeDataset(count);
                            GroupManager._clearConnectors();
                            legend.removeItem(dsTypeRef[j].legendItemId);
                        }
                        else if (dataset === 'connectors') {
                            GroupManager.removeConnectorSet(count);
                        }
                        else {
                            GroupManager.removeLabelSet(count);
                        }
                        componentDispose.call(dsTypeRef[j]);
                        count +=1;
                    }
                }
            }
            config.datasetMap = tempMap;
        },
        addConfigureOptions: function () {
            var chart = this,
                chartMenuTools = chart.chartMenuTools,
                components = chart.components,
                actionBar = components.actionBar,
                chartMenuBar =components.chartMenuBar,
                manager = chart.components['datasetGroup_' + chart.defaultDatasetType],
                componentGroup = (chartMenuBar || actionBar).componentGroups[0],
                symbolList = componentGroup.symbolList[0],
                sListRef = symbolList.getListRefernce(),
                setChartTools = chartMenuTools.set,
                viewMode = chart.config.viewMode,
                configureTools = [
                    {
                        'Add Node' : {
                            handler: function () {
                                manager.showNodeAddUI();
                            },
                            action: 'click'
                        }
                    },
                    {
                        'Add Connector': {
                            handler: function () {
                                manager.showConnectorAddUI(manager.chart, {

                                });
                            },
                            action: 'click'
                        }
                    },
                    {
                        'Add Label': {
                            handler: function () {
                                manager.showLabelUpdateUI(manager.chart, {

                                });
                            },
                            action: 'click'
                        }
                    }
                ];
            setChartTools(configureTools);
            !viewMode && sListRef.appendAsList(configureTools);
        },
        // _createAxes: function () {
        //     var iapi = this,
        //         chartAttr = iapi.jsonData.chart,
        //         yAxis;
        //     chartAPI.mscartesian._createAxes.call(iapi);
        //     yAxis = iapi.components.yAxis[0];
        //     yAxis.setAxisConfig({
        //         showZeroPlane: pluckNumber(chartAttr.showzeroplane, 0),
        //         showZeroPlaneValue: pluckNumber(chartAttr.showzeroplanevalue, 1),
        //         showDivLineValues: pluckNumber(chartAttr.showdivlinevalues, 0)
        //     });
        // },
        _redrawDragNode: function (eventArgs, sourceEvent) {
            var manager = this,
                chart = manager.chart;
            manager.draw();
            lib.raiseEvent('chartUpdated', extend2({
                sourceEvent: sourceEvent
            }, eventArgs), chart.chartInstance, [chart.chartInstance.id]);

        },
        addNode: function (dataObj) {
            var chart = this,
                datasets = chart.components.dataset,
                datasetId = dataObj.datasetId,
                len = datasets.length,
                dataset,
                groupManager,
                eventArgs,
                index,
                idFound,
                id,
                i,
                sourceEvent = 'nodeAdded',
                dataStore;

            for (i = 0; i < len; i++) {
                dataset = datasets[i] || {};
                id = dataset.config && dataset.config.id;
                if (id !== UNDEFINED) {
                    id = id.toString();
                }
                if (id === datasetId) {
                    idFound = true;
                    break;
                }
            }
            if (dataset && idFound) {
                groupManager = dataset.groupManager,
                dataStore = dataset.components.data;
                dataObj.add = true;
                // This is the index of the new data
                index = dataStore.length;
                eventArgs = {
                    index: index, // to be deprecated
                    dataIndex: index,
                    link: dataObj.link,
                    y: dataObj.y,
                    x: dataObj.x,
                    shape: dataObj.shape,
                    width: dataObj.width,
                    height: dataObj.height,
                    radius: dataObj.radius,
                    sides: dataObj.sides,
                    label: dataObj.name,
                    toolText: dataObj.tooltext,
                    id: dataObj.id,
                    datasetIndex: dataset.index,
                    datasetName: dataset.JSONData.seriesname,
                    sourceType: 'dataplot'
                };

                dataset._setConfigure(index, dataObj);
                chart._redrawDragNode.call(groupManager, eventArgs, sourceEvent);
                /**
                 * In `DragNode` charts, data points are represented as nodes whose
                 * properties like location(x,y), shape, dimensions and color can be added dynamically to
                 * the chart. Chart can contain any number of datasets and an index number is assigned to
                 * each dataset based upon order of dataset creation. This event is raised when a node is
                 * added by clicking on the menu button located at the left side bottom of the chart by
                 * default but can the menu button location can be changed.
                 *
                 * This event is only applicable to DragNode chart.
                 *
                 * @event FusionCharts#nodeAdded
                 * @group chart-powercharts:dragnode
                 *
                 * @param {number} datasetIndex - Index of the dataset to which the newly added
                 * node belongs to.
                 * @param {string} datasetName - Name of the dataset to which the node was added. Name of
                 * the dataset can be defined by the attribute `seriesName` for `dataset` tag in the chart
                 * data.
                 * @param {number} dataIndex - Index of the newly added node.
                 *
                 * @param {number} height - Height of the shape represented by the newly added node.
                 * @param {string} id - ID of the newly added node which can be set using `id` attribute
                 * for `set` tag.
                 *
                 * @param {string} label - Text displayed inside the shape of the newly added node.
                 * @param {string} link - URL associated with the newly added node.
                 * @param {number} radius - Radius of the circumcirle for the shape of the
                 * newly added node.
                 * @param {string} shape - Shape of the newly added node.
                 * @param {number} sides - Depending on the shape of the node it is the
                 * number of sides of the polygon. If it is a circle it will have 0 sides.
                 * @param {string} toolText - Text that is displayed over the shape of the
                 * newly added node.
                 * @param {number} width - Width of the shape of the newly added node.
                 * @param {number} x - X Co-ordinate of the newly added node in reference with
                 * the canvas / axis.
                 * @param {number} y - Y Co-ordinate of the newly added node in reference with
                 * the canvas / axis.
                 */
                global.raiseEvent(sourceEvent, eventArgs, chart.chartInstance);
            }

        },
        updateNode: function (updateObj) {
            var chart = this,
                groupManager = chart.components['datasetGroup_' + chart.defaultDatasetType],
                datasets = groupManager.datasets,
                len = datasets.length,
                dataLen,
                idFound,
                dataset,
                dataObj,
                i,
                dataStore,
                eventArgs,
                sourceEvent = 'nodeupdated',
                j;
            updateObj.update = true;
            for (i = 0; i < len; i++) {
                dataset = datasets[i].dataset;
                dataStore = dataset.components.data || [];
                dataLen = dataStore.length;
                for (j = 0; j < dataLen; j++) {
                    dataObj = dataStore[j];
                    if (dataObj.config.id === updateObj.id) {
                        idFound = true;
                        break;
                    }
                }
            }

            if (dataset && idFound) {
                eventArgs = {
                    index: j, // to be deprecated
                    dataIndex: j,
                    link: updateObj.link,
                    y: updateObj.y,
                    x: updateObj.x,
                    shape: updateObj.shape,
                    width: updateObj.width,
                    height: updateObj.height,
                    radius: updateObj.radius,
                    sides: updateObj.sides,
                    label: updateObj.name,
                    toolText: updateObj.tooltext,
                    id: updateObj.id,
                    datasetIndex: dataset.index,
                    datasetName: dataset.JSONData.seriesname,
                    sourceType: 'dataplot'
                };
                dataset._setConfigure(j, updateObj);
                chart._redrawDragNode.call(groupManager, eventArgs, sourceEvent);
                global.raiseEvent(sourceEvent, eventArgs, chart.chartInstance);
            }

        },

        deleteNode: function (id) {
            var chart = this,
                groupManager = chart.components['datasetGroup_' + chart.defaultDatasetType],
                nodes = groupManager.nodes,
                node = nodes[id],
                dataset,
                dataStore,
                startConnectors,
                endConnectors,
                i,
                graphics,
                connector,
                dataObj,
                prop,
                len,
                eventArgs,
                config,
                idFound,
                sourceEvent = 'nodedeleted',
                removeElements = function (graphics) {
                    for (var i in graphics) {
                        graphics[i].remove();
                    }
                };
            if (node) {
                dataset = node.dataset;
                dataStore = dataset.components.data;
                startConnectors = node.config.startConnectors;
                endConnectors = node.config.endConnectors;
                len = dataStore.length;
                for (i = 0; i < len; i++) {
                    dataObj = dataStore[i];
                    if (dataObj.config.id === id) {
                        idFound = true;
                        break;
                    }
                }

                if (idFound === true) {
                    graphics = dataObj.graphics;
                    removeElements(graphics);
                    for (prop in startConnectors) {
                        connector = startConnectors[prop] || {};
                        graphics = connector.graphics;
                        removeElements(graphics);
                        delete connector.graphics;
                        connector.removed = true;
                    }
                    for (prop in endConnectors) {
                        connector = endConnectors[prop] || {};
                        graphics = connector.graphics;
                        removeElements(graphics);
                        delete connector.graphics;
                        connector.removed = true;
                    }
                    delete nodes[id];
                    dataObj.removed = true;
                    config = dataObj.config || {};
                    eventArgs = {
                        index: i,
                        dataIndex: i,
                        link: config.link,
                        y: config.y,
                        x: config.x,
                        shape: config.shape,
                        width: config.width,
                        height: config.height,
                        radius: config.radius,
                        sides: config.sides,
                        label: config.displayValue,
                        toolText: config.toolText,
                        id: config.id,
                        datasetIndex: i,
                        datasetName: dataset.JSONData.seriesname,
                        sourceType: 'dataplot'
                    };
                    lib.raiseEvent('chartUpdated', extend2({
                        sourceEvent: sourceEvent
                    }, eventArgs), chart.chartInstance, [chart.chartInstance.id]);
                    global.raiseEvent(sourceEvent, eventArgs, chart.chartInstance);
                }
            }

        },
        addConnector: function (connectorObj) {
            var chart = this,
                groupManager = chart.components['datasetGroup_' + chart.defaultDatasetType],
                connectorSets = groupManager.connectorSet,
                connectors = connectorSets[0].connectors,
                data = connectors.components.data,
                sourceEvent = 'connectoradded',
                eventArgs,
                length = data.length;
            connectorObj.add = true;
            connectors._setConfigure(length, connectorObj);
            eventArgs = {
                arrowAtEnd: Boolean(connectorObj.arrowAtEnd),
                arrowAtStart: Boolean(connectorObj.arrowAtStart),
                fromNodeId: connectorObj.from,
                id: connectorObj.id,
                label: connectorObj.label,
                link: connectorObj.connectorLink,
                sourceType: 'connector',
                toNodeId: connectorObj.to
            };
            chart._redrawDragNode.call(groupManager, eventArgs, sourceEvent);
            global.raiseEvent(sourceEvent, eventArgs, chart.chartInstance);
        },
        editConnector: function (connectorObj) {
            var chart = this,
                groupManager = chart.components['datasetGroup_' + chart.defaultDatasetType],
                from = connectorObj.from,
                to = connectorObj.to,
                connectorSets = groupManager.connectorSet,
                i,
                conLen,
                data,
                dataObj,
                fromId,
                toId,
                j,
                idFound,
                connectors,
                config,
                eventArgs,
                sourceEvent = 'connectorupdated',
                len = connectorSets.length;
            for (i = 0; i < len; i++) {
                connectors = connectorSets[i].connectors;
                data = connectors && connectors.components.data || [];
                conLen = data.length;
                for (j = 0; j < conLen; j++) {
                    dataObj = data[j];
                    config = dataObj.config;
                    fromId = config.from;
                    toId = config.to;
                    if (fromId === from && toId === to) {
                        idFound = true;
                        break;
                    }
                }
            }
            connectorObj.update = true;
            if (idFound) {
                connectors._setConfigure(j, connectorObj);
                eventArgs = {
                    arrowAtEnd: Boolean(connectorObj.arrowatend),
                    arrowAtStart: Boolean(connectorObj.arrowatstart),
                    fromNodeId: connectorObj.from,
                    id: connectorObj.id,
                    label: connectorObj.label,
                    link: connectorObj.link,
                    sourceType: 'connector',
                    toNodeId: connectorObj.to
                };
                chart._redrawDragNode.call(groupManager, eventArgs, sourceEvent);
                global.raiseEvent(sourceEvent, eventArgs, chart.chartInstance);
            }


        },
        deleteConnector: function (config) {
            var chart = this,
                groupManager = chart.components['datasetGroup_' + chart.defaultDatasetType],
                from = config.from,
                to = config.to,
                connectorSets = groupManager.connectorSet,
                i,
                j,
                dataObj,
                dataStore,
                dataLen,
                connFound = false,
                connectors,
                eventArgs,
                connConfig,
                len = connectorSets.length,
                sourceEvent = 'connectordeleted',
                removeElements = function (graphics) {
                    var prop;
                    for (prop in graphics) {
                        graphics[prop].remove();
                    }
                };

            for (i = 0; i < len; i++) {
                connectors = connectorSets[i].connectors;
                dataStore = connectors.components.data;
                dataLen = dataStore.length;
                for (j = 0; j < dataLen; j++) {
                    dataObj = dataStore[j];
                    if (dataObj.config.from === from && dataObj.config.to === to) {
                        connFound = true;
                        break;
                    }
                }
            }
            if (connFound) {
                connConfig = dataObj.config || {};
                eventArgs = {
                    arrowAtEnd: connConfig.arrowAtEnd,
                    arrowAtStart: connConfig.arrowAtStart,
                    fromNodeId: connConfig.from,
                    id: connConfig.id,
                    label: connConfig.label,
                    link: connConfig.connectorLink,
                    sourceType: 'connector',
                    toNodeId: connConfig.to
                };
                removeElements(dataObj.graphics);
                delete dataObj.graphics;
                // Mark data object as removed
                dataObj.removed = true;
                lib.raiseEvent('chartUpdated', extend2({
                    sourceEvent: sourceEvent
                }, eventArgs), chart.chartInstance, [chart.chartInstance.id]);
                global.raiseEvent(sourceEvent, eventArgs, chart.chartInstance);
            }

        },
        addLabel: function (labelObj) {
            var chart = this,
                manager = chart.components['datasetGroup_' + chart.defaultDatasetType],
                labelSet = manager.labelSet,
                DragLabelClass = FusionCharts.get(COMPONENT, [DATASET, 'DragableLabels']),
                labelDS,
                dataStore,
                sourceEvent = 'labeladded',
                eventArgs,
                len;
            labelObj.add = true;
            if (!labelSet.length) {
                labelDS = new DragLabelClass();
                labelDS.chart = chart;
                labelDS.init([labelObj]);
                manager.addLabels(labelDS, 0);
            }
            else {
                labelDS = manager.labelSet[0].labels,
                dataStore = labelDS.components.data,
                len = dataStore.length;
                labelDS._setConfigure(len, labelObj);
            }

            eventArgs = {
                text: labelObj.text,
                x: labelObj.x,
                y: labelObj.y,
                allowdrag: labelObj.allowdrag,
                sourceType: 'labelnode',
                link: labelObj.link
            };

            chart._redrawDragNode.call(manager, eventArgs, sourceEvent);

            global.raiseEvent(sourceEvent, eventArgs, chart.chartInstance);
            labelObj.add = true;
        },
        deleteLabel: function (index) {
            var chart = this,
                manager = chart.components['datasetGroup_' + chart.defaultDatasetType],
                labels = manager.labelSet[0].labels,
                dataStore = labels.components.data,
                labelObj = dataStore[index],
                labelElement,
                eventArgs,
                sourceEvent = 'labeldeleted';

            labelElement = labelObj.graphics.element;

            if (labelElement) {
                eventArgs = labelElement.data('eventArgs');
                labelElement.remove();
                delete labelObj.graphics;
            }
            lib.raiseEvent('chartUpdated', extend2({
                sourceEvent: sourceEvent
            }, eventArgs), chart.chartInstance, [chart.chartInstance.id]);

            global.raiseEvent(sourceEvent, eventArgs, chart.chartInstance);
            labelObj.removed = true;
        },
        restoreData: function () {
            var chart = this,
                manager = chart.components['datasetGroup_' + chart.defaultDatasetType],
                datasets = manager.datasets,
                legend = chart.components.legend,
                connectors = manager.connectorSet,
                i,
                dataset,
                dataStore,
                dataObj,
                graphics,
                labelObj,
                labelSet = manager.labelSet,
                removeElements = function (dataStore) {
                    var j,
                        ele;
                    for (j = 0; j < dataStore.length; j++) {
                        dataObj = dataStore[j];
                        delete dataObj.removed;
                        if (dataObj.config.add) {
                            graphics = dataStore[j].graphics;
                            for (ele in graphics) {
                                graphics[ele].remove();
                            }
                        }

                    }
                };
            for (i = 0; i < datasets.length; i++) {
                dataset = datasets[i].dataset;
                dataStore = dataset.components.data;
                removeElements(dataStore);
                dataset.drawn = false;
                dataset.configure();
            }
            for (i = 0; i < connectors.length; i++) {
                dataset = connectors[i].connectors;
                dataStore = dataset.components.data;
                removeElements(dataStore);
                dataset.drawn = false;
                dataset.configure();
            }
            if (labelSet.length) {
                labelObj = labelSet[0].labels;
                dataStore = labelObj.components.data;
                removeElements(dataStore);
                labelObj.configure();
            }
            chart._setAxisLimits();
            chart._drawAxis();
            chart._drawDataset();
            legend._drawPointLegendItem();
            lib.raiseEvent('dataRestored', {}, chart.chartInstance, [chart.chartInstance.id]);
        },
        getJSONData: function () {
            var chart = this,
                defaultDatasetType = chart.defaultDatasetType && chart.defaultDatasetType.toLowerCase(),
                chartComponents = chart.components,
                groupManager = chartComponents['datasetGroup_' + defaultDatasetType],
                datasets = chartComponents.dataset,
                rawObj = chart.jsonData,
                len = datasets.length,
                datasetsArr = [],
                jsonObj,
                dataObj,
                dataset,
                i;
            if (groupManager) {
                datasetsArr = groupManager.getJSONData();
            }
            else {
                for (i = 0; i < len; i++) {
                    dataset = datasets[i];
                    dataObj = dataset.getJSONData();
                    datasetsArr.push(dataObj);
                }
            }
            jsonObj = extend2({}, rawObj);
            jsonObj.dataset = datasetsArr.dataset;
            jsonObj.connectors = datasetsArr.connectors;
            jsonObj.labels = datasetsArr.labels;
            return jsonObj;
        },
        _setCategories: function () {
            var iapi = this,
            components = iapi.components,
            dataObj = iapi.jsonData,
            xAxis = components.xAxis,
            categories = dataObj.categories && dataObj.categories[0].category || [],
            catLen = categories.length,
            catArr = [],
            i,
            catObj;

            for (i = 0; i < catLen; i++) {
                catObj = categories[i] || {};
                if (catObj.x !== UNDEFINED) {
                    catArr.push(catObj);
                }
            }

            xAxis && xAxis[0].setCategory(catArr);
        },
        _drawDataset : function () {
            var iapi = this,
                components = iapi.components,
                defaultDatasetType = iapi.defaultDatasetType,
                managerName = 'datasetGroup_' + defaultDatasetType,
                groupManagerObj = components[managerName];
            groupManagerObj && groupManagerObj.draw();
        },
        _setAxisLimits : function () {
            var iapi = this,
                components = iapi.components,
                dataObj = iapi.jsonData,
                categories = dataObj.categories && dataObj.categories[0].category || [],
                category,
                catX,
                dataset = components.dataset,
                yAxis = components.yAxis,
                xAxis = components.xAxis,
                currentDataset,
                length = dataset.length,
                i,
                infMin = -Infinity,
                infMax = +Infinity,
                max = infMin,
                min = infMax,
                xMin = infMax,
                xMax = infMin,
                maxminObj,
                groupManager,
                xMaxValue,
                xMinValue,
                groupManagerObj = { },
                noManager = [],
                getMaxMin = function (maxminObj) {
                    xMaxValue = pluck(maxminObj.xMax, infMin);
                    xMinValue = pluck(maxminObj.xMin, infMax);
                    max = mathMax (max, maxminObj.max);
                    min = mathMin (min, maxminObj.min);
                    xMax = mathMax (xMax, xMaxValue);
                    xMin = mathMin (xMin, xMinValue);

                };

            for (i=0; i<length; i++) {
                currentDataset = dataset[i];
                groupManager = currentDataset.groupManager;
                if (groupManager) {
                    groupManagerObj[currentDataset.type] = groupManager;
                }
                else {
                    noManager.push (currentDataset);
                }
            }

            for (groupManager in groupManagerObj) {
                maxminObj = groupManagerObj[groupManager].getDataLimits ();
                getMaxMin (maxminObj);
            }

            length =noManager.length;
            for (i=0; i<length; i++) {
                maxminObj = noManager[i].getDataLimits ();
                getMaxMin (maxminObj);
            }

            (max === -Infinity) && (max = 0);
            (min === +Infinity) && (min = 0);
            iapi.config.yMax = max;
            iapi.config.yMin = min;
            yAxis[0].setAxisConfig ( {
                isPercent : iapi.isStacked ? iapi.config.stack100Percent : 0
            });
            yAxis[0].setDataLimit (max, min);
            if ((xMax !== infMin) || (xMin !== infMax)) {

                for (i = 0, length = categories.length; i < length; i++) {
                    category = categories[i];
                    if (catX = category.x) {
                        if (catX < xMin) {
                            xMin = catX;
                        }
                        if (catX > xMax) {
                            xMax = catX;
                        }
                    }
                }
                xAxis[0].setDataLimit (xMax, xMin);
            }
        }
    }, chartAPI.dragbase);

}]);

FusionCharts.register ('module', ['private', 'modules.renderer.js-dragarea', function () {
    var global = this,
        lib = global.hcLib,
        win = global.window,
        HUNDREDSTRING = lib.HUNDREDSTRING,
        creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
        chartAPI = lib.chartAPI;

    /////////////// DragArea ///////////
    chartAPI('dragarea', {
        friendlyName: 'Dragable Area Chart',
        standaloneInit: true,
        creditLabel: creditLabel,
        defaultDatasetType: 'dragarea',
        decimals: 2,
        applicableDSList: {'dragarea': true}
    }, chartAPI.dragbase, {
        anchoralpha: HUNDREDSTRING,
        enablemousetracking : true,
        isDrag : true
    }, chartAPI.areabase);

}]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dragline', function () {
    var global = this,
        lib = global.hcLib,
        chartAPI = lib.chartAPI,
        win = global.window,
        creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname);
            /////////////// DragLine ///////////
    chartAPI('dragline', {
        friendlyName: 'Dragable Line Chart',
        standaloneInit: true,
        creditLabel: creditLabel,
        decimals: 2,
        defaultDatasetType: 'dragline',
        applicableDSList: {'dragline': true},
        defaultPlotShadow: 1
    }, chartAPI.dragbase, {
        zeroplanethickness: 1,
        zeroplanealpha: 40,
        showzeroplaneontop: 0,
        enablemousetracking : true,
        isDrag : true
    }, chartAPI.areabase);

}]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dragcolumn2d', function () {
    var global = this,
        lib = global.hcLib,
        chartAPI = lib.chartAPI,
        win = global.window,
        creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname);

    /////////////// DragArea ///////////
    chartAPI('dragcolumn2d', {
        friendlyName: 'Dragable Column Chart',
        standaloneInit: true,
        creditLabel: creditLabel,
        decimals: 2,
        defaultDatasetType: 'DragColumn',
        applicableDSList: {'dragcolumn': true}
    }, chartAPI.dragbase, {
        enablemousetracking: true,
        isDrag : true
    });
}]);

FusionCharts.register ('module', ['private', 'modules.renderer.js-selectscatter', function () {
    var global = this,
        lib = global.hcLib,
        win = global.window,
        creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
        getValidValue = lib.getValidValue,
        COMMA = ',',
        extend2 = lib.extend2, //old: jarendererExtend / margecolone
        toRaphaelColor = lib.toRaphaelColor,
        preDefStr = lib.preDefStr,
        isIE = lib.isIE,
        hasSVG = lib.hasSVG,
        t = 't',
        docMode8 = win.document.documentMode === 8,
        BLANKSTRING = lib.BLANKSTRING,
        ROUND = preDefStr.ROUND,
        POINTER = 'pointer',
        math = Math,
        mathMin = math.min,
        mathMax = math.max,
        mathAbs = math.abs,
        xssEncode = global.xssEncode,
        hiddenStr = preDefStr.hiddenStr,
        HIDDEN = hiddenStr,
        visibleStr = preDefStr.visibleStr,
        VISIBLE = docMode8 ? visibleStr : BLANKSTRING,
        configStr = preDefStr.configStr,
        TRACKER_FILL = 'rgba(192,192,192,' + (isIE ? 0.002 : 0.000001) + ')', // invisible but clickable
        chartAPI = lib.chartAPI;

    chartAPI('selectscatter', {
        isXY: true,
        hasLegend: true,
        applicableDSList: {
            'selectScatter': true
        },
        friendlyName: 'Dragable Scatter Chart',
        standaloneInit: true,
        creditLabel: creditLabel,
        defaultDatasetType: 'selectScatter',
        defaultZeroPlaneHighlighted: false,
        configure: chartAPI.dragbase.configure,
        _createToolBox: chartAPI.dragbase._createToolBox,
        _manageActionBarSpace: chartAPI.dragbase._manageActionBarSpace,
        drawActionBar: chartAPI.dragbase.drawActionBar,
        getData: function(format) {
            // create a two dimensional array as given in the docs
            var iapi = this,
                dataObj = iapi.getCollatedData(),
                returnObj = [],
                datasets = dataObj.dataset,
                length = (datasets && datasets.length) || 0,
                index = 0,
                NULLSTR = 'null',
                dsInd = 0,
                setLen,
                set,
                j;


            // When a format is provided
            if (format) {
                // no transcoding needed for json
                if (/^json$/ig.test(format)) {
                    returnObj = dataObj;
                } else if (/^csv$/ig.test(format)) {
                    returnObj = iapi.getCSVString();
                } else {
                    returnObj = global.core.transcodeData(dataObj,
                        'json', format);
                }
            }
            // if no format has been specified, return data as 2d array.
            else {
                //while (length--) {
                for (; index < length; index += 1) {
                    set = datasets[index];
                    if (set) {
                        set = datasets[index] && datasets[index].data;
                        j = setLen = (set && set.length) || 0;
                        j && (returnObj[dsInd] || (returnObj[dsInd] = [getValidValue(datasets[index].id,
                            NULLSTR)]));
                        while (j--) {
                            returnObj[dsInd][j + 1] = getValidValue(set[j].id, NULLSTR);
                        }

                        setLen && (dsInd += 1);
                    }
                }
            }
            return returnObj;
        },

        getCSVString: function() {
            var chart = this,
                dataObj = chart.getData(),
                i = dataObj.length;

            while (i--) {
                dataObj[i] = dataObj[i].join(COMMA);
            }

            return dataObj.join('|');
        },
        getCollatedData: function() {
            var api = this,
                chartInstance = api.chartInstance,
                dataset = api.components.dataset,
                selectedArr = api.config._selectEleArr,
                len = selectedArr && selectedArr.length,
                origChartData = extend2({}, chartInstance.getChartData(global.dataFormats.JSON)),
                origDataSets = origChartData.dataset,
                xPos,
                yPos,
                oriDataArr,
                selectionBoxObj,
                lenDS,
                setObj,
                dataLen,
                startX,
                endX,
                startY,
                endY,
                selectedData = [];

            while (len--) {
                selectionBoxObj = selectedArr[len];
                if (!selectionBoxObj) {
                    continue;
                }
                startX = selectionBoxObj.startX;
                endX = selectionBoxObj.endX;
                startY = selectionBoxObj.startY;
                endY = selectionBoxObj.endY;
                lenDS = origDataSets.length;

                while (lenDS--) {
                    if (!dataset[lenDS].visible) {
                        continue;
                    }
                    selectedData[lenDS] || (selectedData[lenDS] = {
                        data: []
                    });
                    oriDataArr = origDataSets[lenDS].data;
                    dataLen = oriDataArr && oriDataArr.length;
                    while (dataLen--) {
                        setObj = oriDataArr[dataLen];
                        xPos = setObj.x;
                        yPos = setObj.y;
                        if (xPos > startX && xPos < endX &&
                            yPos < startY && yPos > endY) {
                            selectedData[lenDS].data[dataLen] = true;
                        }
                    }
                }
            }

            lenDS = origDataSets.length;
            while (lenDS--) {
                oriDataArr = origDataSets[lenDS].data;
                dataLen = oriDataArr && oriDataArr.length;
                while (dataLen--) {
                    if (!(selectedData[lenDS] && selectedData[lenDS].data[dataLen])) {
                        oriDataArr.splice(dataLen, 1);
                    }
                }
            }

            //state.hasStaleData = false;
            return (api.updatedDataObj = origChartData);
        },

        createSelectionBox: function(event) {
            var chart = event.chart,
                chartComponents = chart.components,
                paper = chartComponents.paper,
                chartConfig = chart.config,
                yAxis = chartComponents.yAxis && chartComponents.yAxis[0],
                xAxis = chartComponents.xAxis && chartComponents.xAxis[0],
                x = event.selectionLeft,
                y = event.selectionTop,
                width = event.selectionWidth,
                height = event.selectionHeight,
                x2 = x + width,
                y2 = y + height,
                TRACKER_WIDTH = 12,
                TRACKER_HALF_WIDTH = TRACKER_WIDTH * 0.5,
                trackerRadius = 12,
                resizeInnerSymbolColor = '#999999',
                resizeOuterSymbolColor = '#777777',
                closeButtonRadius = 6,
                cornerSymbolRadius = 15,
                isSmall = width > cornerSymbolRadius &&
                    height > cornerSymbolRadius,
                selectEleObj = {
                    resizeEleRadius: cornerSymbolRadius,
                    canvasTop: chartConfig.canvasTop,
                    canvasRight: chartConfig.canvasLeft + chartConfig.canvasWidth,
                    canvasLeft: chartConfig.canvasLeft,
                    canvasBottom: chartConfig.canvasTop + chartConfig.canvasHeight
                },
                trackerG = chart.graphics.trackerGroup,
                selectEleArr = chartConfig._selectEleArr || (chartConfig._selectEleArr = []),
                selectBoxG;

            //var TRACKER_FILL = 'rgba(255,0,0,0.3)';

            selectEleObj.index = selectEleArr.length;
            selectEleObj.id = 'SELECT_' + selectEleObj.index;

            selectEleObj.selectBoxG = selectBoxG = paper.group('selection-box',
                trackerG).toFront();

            // Drawing the main box element
            selectEleObj.selectBoxTracker = paper.rect(x, y, width, height, selectBoxG)
                .attr({
                    'stroke-width': 1,
                    stroke: toRaphaelColor(chartConfig.selectBorderColor),
                    ishot: true,
                    fill: chartConfig.selectFillColor
                })
                .css({
                    cursor: 'move'
                });
            selectEleObj.selectBoxTracker.data(configStr, {
                position: 6, // MOVE
                selectEleObj: selectEleObj,
                xChange: true,
                yChange: true
            });

            // Draw top tracker element
            selectEleObj.topTracker = paper.rect(x, y -
                TRACKER_HALF_WIDTH, width, TRACKER_WIDTH, selectBoxG)
                .attr({
                    'stroke-width': 0,
                    ishot: true,
                    fill: TRACKER_FILL
                })
                .css('cursor', hasSVG && 'ns-resize' || 'n-resize');
            selectEleObj.topTracker.data(configStr, {
                position: 1, // TOP
                selectEleObj: selectEleObj,
                yChange: true
            });

            // Draw right tracker element
            selectEleObj.rightTracker = paper.rect(x + width -
                TRACKER_HALF_WIDTH, y, TRACKER_WIDTH, height, selectBoxG)
                .attr({
                    'stroke-width': 0,
                    ishot: true,
                    fill: TRACKER_FILL
                })
                .css('cursor', hasSVG && 'ew-resize' || 'w-resize');
            selectEleObj.rightTracker.data(configStr, {
                position: 2, // RIGHT
                selectEleObj: selectEleObj,
                xChange: true
            });

            // Draw bottom tracker element
            selectEleObj.bottomTracker = paper.rect(x, y + height -
                TRACKER_HALF_WIDTH, width, TRACKER_WIDTH, selectBoxG)
                .attr({
                    'stroke-width': 0,
                    ishot: true,
                    fill: TRACKER_FILL
                })
                .css('cursor', hasSVG && 'ns-resize' || 'n-resize');
            selectEleObj.bottomTracker.data(configStr, {
                position: 3, // BOTTOM
                selectEleObj: selectEleObj,
                yChange: true
            });

            // Draw left tracker element
            selectEleObj.leftTracker = paper.rect(x - TRACKER_HALF_WIDTH, y,
                TRACKER_WIDTH, height, selectBoxG)
                .attr({
                    'stroke-width': 0,
                    ishot: true,
                    fill: TRACKER_FILL
                })
                .css('cursor', hasSVG && 'ew-resize' || 'e-resize');
            selectEleObj.leftTracker.data(configStr, {
                position: 4, // LEFT
                selectEleObj: selectEleObj,
                xChange: true
            });

            selectEleObj.cornerInnerSymbol = paper.symbol('resizeIcon', 0, 0,
                cornerSymbolRadius, selectBoxG)
                .attr({
                    transform: t + x2 + COMMA + y2,
                    'stroke-width': 1,
                    visibility: isSmall ? VISIBLE : HIDDEN,
                    ishot: true,
                    stroke: resizeInnerSymbolColor
                });

            selectEleObj.cornerOuterSymbol = paper.symbol('resizeIcon', 0, 0, -cornerSymbolRadius * 0.8, selectBoxG)
                .attr({
                    transform: t + x2 + COMMA + y2,
                    strokeWidth: 1,
                    visibility: !isSmall ? VISIBLE : HIDDEN,
                    ishot: true,
                    stroke: resizeOuterSymbolColor
                });

            selectEleObj.resizeTracker = paper.circle(x2, y2, trackerRadius, selectBoxG)
                .attr({
                    'stroke-width': 1,
                    stroke: TRACKER_FILL,
                    ishot: true,
                    fill: TRACKER_FILL
                })
                .css('cursor', hasSVG && 'nwse-resize' || 'nw-resize');
            selectEleObj.resizeTracker.data(configStr, {
                position: 5, // Corner
                selectEleObj: selectEleObj,
                yChange: true,
                xChange: true
            });

            selectEleObj.closeButton = paper.symbol('closeIcon', 0, 0, closeButtonRadius, selectBoxG)
                .attr({
                    transform: 't' + x2 + COMMA + y,
                    'stroke-width': 2,
                    stroke: chartConfig.selectionCancelButtonBorderColor,
                    fill: chartConfig.selectionCancelButtonFillColor,
                    'stroke-linecap': ROUND,
                    ishot: true,
                    'stroke-linejoin': ROUND
                })
                .css({
                    cursor: POINTER,
                    _cursor: 'hand'
                })
                .click(function() { // Delete the selection
                    chart.deleteSelection(this, chart);
                });
            selectEleObj.closeButton.data(configStr, {
                index: selectEleObj.index
            });

            selectEleObj.chart = chart;
            selectEleObj.startX = xAxis.getValue(x - chartConfig.canvasLeft);
            selectEleObj.startY = yAxis.getValue(y - chartConfig.canvasTop);
            selectEleObj.endX = xAxis.getValue(x2 - chartConfig.canvasLeft);
            selectEleObj.endY = yAxis.getValue(y2 - chartConfig.canvasTop);
            selectEleObj.isVisible = true;

            selectEleArr.push(selectEleObj);
            chart.bindDragEvent(selectEleObj);
        },

        _deleteAllSelection : function () {
            var chart = this,
                selectEleArr = chart.config._selectEleArr,
                selectEleObj,
                selectEleItem,
                items,
                items1;

            for (items in selectEleArr) {
                if (selectEleArr.hasOwnProperty(items)) {
                    selectEleObj = selectEleArr[items];
                    for (items1 in selectEleObj) {
                        if (selectEleObj.hasOwnProperty(items1)) {
                            selectEleItem = selectEleObj[items1];
                            selectEleItem.remove && selectEleItem.remove();
                            delete selectEleObj[items1];
                        }
                    }
                    delete selectEleArr[items];
                }
            }

        },

        deleteSelection: function(ele, chart) {
            var index = ele.data(configStr).index,
                chartComponents = chart.components,
                selectEleArr = chart.config._selectEleArr,
                selectEleObj = selectEleArr[index],
                selectT = selectEleObj.selectBoxTracker,
                selectEleItem,
                items,
                bBox,
                eventArgs;
            bBox = selectT.getBBox();
            eventArgs = {
                selectionLeft: bBox.x,
                selectionTop: bBox.y,
                selectionWidth: bBox.width,
                selectionHeight: bBox.height,
                startXValue: chartComponents.xAxis[0].getAxisPosition(bBox.x, 1),
                startYValue: chartComponents.yAxis[0].getAxisPosition(bBox.y, 1),
                endXValue: chartComponents.xAxis[0].getAxisPosition(bBox.x + bBox.width, 1),
                endYValue: chartComponents.yAxis[0].getAxisPosition(bBox.y + bBox.height, 1),
                data: chart.getCollatedData(),
                id: selectEleObj.id
            };

            for (items in selectEleObj) {
                if (selectEleObj.hasOwnProperty(items)) {
                    selectEleItem = selectEleObj[items];
                    selectEleItem.remove && selectEleItem.remove();
                    delete selectEleObj[items];
                }
            }
            delete selectEleArr[index];
            /**
             * This event is raised when the selection of a SelectScatter chart is removed. This happens when one
             * clicks the close button on a selection that one has made on the chart.
             *
             * @event FusionCharts#selectionRemoved
             * @group chart-powercharts:selectscatter
             *
             * @param {object} data - This returns the subset of data that was selected.
             */
            global.raiseEvent('selectionRemoved', eventArgs, chart.chartInstance);
        },

        bindDragEvent: function(selectEleObj) {
            var chart = this,
                //logic = chart.logic,
                item;
            for (item in selectEleObj) {
                /Tracker/.test(item) && selectEleObj[item].drag(chart.move,
                    chart.start, chart.up);
            }
        },

        start: function() {
            var ele = this,
                data = ele.data(configStr),
                selectEleObj = data.selectEleObj,

                topT = selectEleObj.topTracker,
                rightT = selectEleObj.rightTracker,
                bottomT = selectEleObj.bottomTracker,
                leftT = selectEleObj.leftTracker,
                resizeT = selectEleObj.resizeTracker,

                topTData = topT.data(configStr),
                rightTData = rightT.data(configStr),
                bottomTData = bottomT.data(configStr),
                leftTData = leftT.data(configStr),
                resizeTData = resizeT.data(configStr),
                selectTData = selectEleObj.selectBoxTracker.data(configStr),
                bBox = selectEleObj.selectBoxTracker.getBBox();

            topTData.ox = bBox.x;
            topTData.oy = bBox.y;

            rightTData.ox = bBox.x2;
            rightTData.oy = bBox.y;

            bottomTData.ox = bBox.x;
            bottomTData.oy = bBox.y2;

            leftTData.ox = bBox.x;
            leftTData.oy = bBox.y;

            topTData.ox = bBox.x;
            topTData.oy = bBox.y;

            resizeTData.ox = bBox.x2;
            resizeTData.oy = bBox.y2;

            selectTData.ox = bBox.x;
            selectTData.oy = bBox.y;
            selectTData.ow = bBox.width;
            selectTData.oh = bBox.height;
            selectTData.ox2 = bBox.x2;
            selectTData.oy2 = bBox.y2;
            // on click take the selection box on top.
            selectEleObj.selectBoxG.toFront();

            topT.hide();
            rightT.hide();
            bottomT.hide();
            leftT.hide();
            resizeT.hide();
            ele.show();
        },

        move: function(dx, dy) {
            var ele = this,
                data = ele.data(configStr),
                selectEleObj = data.selectEleObj,
                chart = selectEleObj.chart,
                chartConfig = chart.config,
                chartComponents = chart.components,
                topT = selectEleObj.topTracker,
                rightT = selectEleObj.rightTracker,
                bottomT = selectEleObj.bottomTracker,
                leftT = selectEleObj.leftTracker,
                resizeT = selectEleObj.resizeTracker,
                selectT = selectEleObj.selectBoxTracker,
                canvasLeft = selectEleObj.canvasLeft,
                canvasRight = selectEleObj.canvasRight,
                canvasTop = selectEleObj.canvasTop,
                canvasBottom = selectEleObj.canvasBottom,
                HALF_T_WID = -6,
                selectTData = selectT.data(configStr),
                attrib = {},
                bBox,
                eventArgs,
                x,
                y;

            dx = data.xChange ? dx : 0;
            dy = data.yChange ? dy : 0;

            x = dx + data.ox;
            y = dy + data.oy;

            x = mathMin(canvasRight - (data.ow || 0), mathMax(x, canvasLeft));
            y = mathMin(canvasBottom - (data.oh || 0), mathMax(y, canvasTop));


            switch (data.position) {
            case 1: // TOP
                attrib.y = mathMin(selectTData.oy2, y);
                attrib.height = mathAbs(selectTData.oy2 - y) || 1;
                topT.attr({
                    y: y + HALF_T_WID
                });
                break;
            case 2: // Right
                attrib.x = mathMin(selectTData.ox, x);
                attrib.width = mathAbs(selectTData.ox - x) || 1;
                rightT.attr({
                    x: x + HALF_T_WID
                });
                break;
            case 3: // Bottom
                attrib.y = mathMin(selectTData.oy, y);
                attrib.height = mathAbs(selectTData.oy - y) || 1;
                bottomT.attr({
                    y: y + HALF_T_WID
                });
                break;
            case 4: // Left
                attrib.x = mathMin(selectTData.ox2, x);
                attrib.width = mathAbs(selectTData.ox2 - x) || 1;
                leftT.attr({
                    x: x + HALF_T_WID
                });
                break;
            case 5: // Corner
                attrib.x = mathMin(selectTData.ox, x);
                attrib.width = mathAbs(selectTData.ox - x) || 1;
                attrib.y = mathMin(selectTData.oy, y);
                attrib.height = mathAbs(selectTData.oy - y) || 1;
                resizeT.attr({
                    cx: x,
                    cy: y
                });
                break;
            default:
                attrib.x = x;
                attrib.y = y;
                break;
            }

            if (!ele.data('dragStarted')) {
                bBox = selectT.getBBox();

                eventArgs = {
                    selectionLeft: bBox.x,
                    selectionTop: bBox.y,
                    selectionWidth: bBox.width,
                    selectionHeight: bBox.height,
                    startXValue: chartComponents.xAxis[0].getValue(bBox.x - chartConfig.canvasLeft),
                    startYValue: chartComponents.yAxis[0].getValue(bBox.y - chartConfig.canvasTop),
                    endXValue: chartComponents.xAxis[0].getValue(bBox.x + bBox.width - chartConfig.canvasLeft),
                    endYValue: chartComponents.yAxis[0].getValue(bBox.y + bBox.height - chartConfig.canvasTop),
                    id: selectEleObj.id
                };

                global.raiseEvent('BeforeSelectionUpdate', eventArgs, chart.chartInstance);
                ele.data('dragStarted', 1);
            }

            selectT.animate(attrib);

            if (selectEleObj.isVisible) {
                selectEleObj.closeButton.hide();
                selectEleObj.cornerInnerSymbol.hide();
                selectEleObj.cornerOuterSymbol.hide();
                selectEleObj.isVisible = false;
            }
        },

        up: function() {
            var ele = this,
                data = ele.data(configStr),
                selectEleObj = data.selectEleObj,
                chart = selectEleObj.chart,
                chartComponents = chart.components,
                chartConfig = chart.config,
                xAxis = chartComponents.xAxis && chartComponents.xAxis[0],
                yAxis = chartComponents.yAxis && chartComponents.yAxis[0],
                topT = selectEleObj.topTracker,
                rightT = selectEleObj.rightTracker,
                bottomT = selectEleObj.bottomTracker,
                leftT = selectEleObj.leftTracker,
                resizeT = selectEleObj.resizeTracker,
                selectT = selectEleObj.selectBoxTracker,
                RESIZE_T_RADIUS = 15,
                HALF_T_WID = -6,
                bBox,
                eventArgs;

            // using setTimeout to fix for the issue #RED-476.
            setTimeout(function() {
                bBox = selectT.getBBox(),

                selectEleObj.startX = xAxis.getValue(bBox.x - chartConfig.canvasLeft);
                selectEleObj.startY = yAxis.getValue(bBox.y - chartConfig.canvasTop);
                selectEleObj.endX = xAxis.getValue(bBox.x2 - chartConfig.canvasLeft);
                selectEleObj.endY = yAxis.getValue(bBox.y2 - chartConfig.canvasTop);

                topT.attr({
                    x: bBox.x,
                    y: bBox.y + HALF_T_WID,
                    width: bBox.width
                });
                rightT.attr({
                    x: bBox.x2 + HALF_T_WID,
                    y: bBox.y,
                    height: bBox.height
                });
                bottomT.attr({
                    x: bBox.x,
                    y: bBox.y2 + HALF_T_WID,
                    width: bBox.width
                });
                leftT.attr({
                    x: bBox.x + HALF_T_WID,
                    y: bBox.y,
                    height: bBox.height
                });
                resizeT.attr({
                    cx: bBox.x2,
                    cy: bBox.y2
                });

                selectEleObj.closeButton.transform(t + bBox.x2 + COMMA + bBox.y);
                selectEleObj.cornerInnerSymbol.transform(t + bBox.x2 + COMMA + bBox.y2);
                selectEleObj.cornerOuterSymbol.transform(t + bBox.x2 + COMMA + bBox.y2);
                selectEleObj.closeButton.show();
                if (bBox.width < RESIZE_T_RADIUS || bBox.height < RESIZE_T_RADIUS) {
                    selectEleObj.cornerInnerSymbol.hide();
                    selectEleObj.cornerOuterSymbol.show();
                } else {
                    selectEleObj.cornerInnerSymbol.show();
                    selectEleObj.cornerOuterSymbol.hide();
                }
                selectEleObj.isVisible = true;

                topT.show();
                rightT.show();
                bottomT.show();
                leftT.show();
                resizeT.show();

                if (ele.data('dragStarted')) {
                    eventArgs = {
                        selectionLeft: bBox.x,
                        selectionTop: bBox.y,
                        selectionWidth: bBox.width,
                        selectionHeight: bBox.height,
                        startXValue: chartComponents.xAxis[0].getValue(bBox.x - chartConfig.canvasLeft),
                        startYValue: chartComponents.yAxis[0].getValue(bBox.y - chartConfig.canvasTop),
                        endXValue: chartComponents.xAxis[0].getValue(bBox.x + bBox.width - chartConfig.canvasLeft),
                        endYValue: chartComponents.yAxis[0].getValue(bBox.y + bBox.height - chartConfig.canvasTop),
                        data: chart.getCollatedData(),
                        id: selectEleObj.id
                    };
                    global.raiseEvent('SelectionUpdated', eventArgs, chart.chartInstance);
                    ele.data('dragStarted', 0);
                }

            }, 100);
        },

        restoreData: function () {
            var chart = this,
                datasets = chart.components.dataset,
                i;

            chart._deleteAllSelection();
            for (i = 0; i < datasets.length; i++) {
                datasets[i].draw();

            }
            lib.raiseEvent('dataRestored', {}, chart.chartInstance, [chart.chartInstance.id]);
            return true;
        },

        submitData: function () {
            var chart = this,
                iapi = chart.chartInstance,
                ajaxObj = new global.ajax(),
                chartConf = chart.config,
                json = global.dataFormats.JSON,
                csv = global.dataFormats.CSV,
                xml = global.dataFormats.XML,
                url = chartConf.formAction || '',
                submitAsAjax = chartConf.submitFormAsAjax,
                requestType,
                data,
                paramObj,
                tempSpan,
                formEle;

            if (chartConf.formDataFormat === json) {
                requestType = json;
                data = JSON.stringify(chart.getCollatedData());
            } else if (chart.formDataFormat === csv) {
                requestType = csv;
                data = iapi.getCSVString && iapi.getCSVString();
                if (data === undefined) {
                    data = global.core.transcodeData(chart.getCollatedData(), json, csv);
                }
            } else {
                requestType = xml;
                data = global.core.transcodeData(chart.getCollatedData(), json, xml);
            }

            // cancel data submit function added in event options
            /**
             * For interative charts like `Select Scatter`, `DragNode`, `Dragable Column2D ` and etc., data
             * points value can be selected for `Scatter Chart` and values can be changed for dragable charts by
             * clicking and dragging the data points whose data point values can be sent to an URL by ajax POST.
             * This is the first event raised when `Submit` button is clicked where the current chart data is
             * about to be sent to the set URL.
             *
             * @event FusionCharts#beforeDataSubmit
             * @group chart-powercharts
             *
             * @param {string} data - Contains the XML string with complete chart data at it's current state.
             *
             */
            global.raiseEvent('beforeDataSubmit', {
                data: data
            }, iapi, undefined, function() {
                // After the collation is done, we have to submit the data using
                // ajax or form submit method.
                if (!submitAsAjax) {
                    // Create a hidden form with data inside it.
                    tempSpan = win.document.createElement('span');
                    tempSpan.innerHTML = '<form style="display:none" action="' +
                        url + '" method="' + chartConf.formMethod + '" target="' + chartConf.formTarget +
                        '"> <input type="hidden" name="strXML" value="' +
                        xssEncode(data) + '"><input type="hidden" name="dataFormat" value="' +
                        requestType.toUpperCase() + '" /></form>';

                    formEle = tempSpan.removeChild(tempSpan.firstChild);

                    // Append the form to body and then submit it.
                    win.document.body.appendChild(formEle);
                    formEle.submit && formEle.submit();
                    // cleanup
                    formEle.parentNode.removeChild(formEle);
                    tempSpan = formEle = null;
                }
                else {
                    ajaxObj.onError = function(response, wrapper, ajaxData, url) {
                    /**
                     * For interative charts like `Select Scatter`, `DragNode`, `Dragable Column2D ` and etc.,
                     * data points value can be selected for `Scatter Chart` and values can be changed for
                     * dragable charts by clicking and dragging the data points whose data point values can be
                     * sent to an URL by ajax POST. This event is raised if there is an ajax error in sending
                     * the chart XML data.
                     *
                     * @event FusionCharts#dataSubmitError
                     * @group chart-powercharts
                     *
                     * @param {string} data - Contains the XML string with complete chart data.
                     * @param {number} httpStatus - Tells the status code of the ajax POST request
                     * @param {string} statusText - Contains the ajax error message.
                     * @param {string} url - URL to which the data is sent as ajax POST request.
                     * @param {object} xhrObject - XMLHttpRequest object which takes care of sending the XML
                     * chart data. In case of error, this object won't be defined.
                     */
                        lib.raiseEvent('dataSubmitError', {
                            xhrObject: wrapper.xhr,
                            url: url,
                            statusText: response,
                            httpStatus: (wrapper.xhr && wrapper.xhr.status) ?
                                wrapper.xhr.status : -1,
                            data: data
                        }, iapi, [iapi.id, response, wrapper.xhr && wrapper.xhr.status]);
                    };

                    ajaxObj.onSuccess = function(response, wrapper, ajaxData, url) {
                    /**
                     * For interative charts like `Select Scatter`, `DragNode`, `Dragable Column2D ` and etc.,
                     * data points value can be selected for `Scatter Chart` and values can be changed for
                     * dragable charts by clicking and dragging the data points whose data point values can be
                     * sent to an URL by ajax POST. This event is raised when the ajax POST request is
                     * successfully completed.
                     *
                     * @event FusionCharts#dataSubmitted
                     * @group chart-powercharts
                     *
                     * @param {string} data - Contains the XML string with complete chart data.
                     * @param {string} reponse - Contains the reponse returned by the web server to which the
                     * HTTP POST request was submitted.
                     * @param {string} url - URL to which the data is sent as HTTP POST request.
                     * @param {object} xhrObject - XMLHttpRequest object which takes care of sending the XML
                     * chart data
                     */
                        lib.raiseEvent('dataSubmitted', {
                            xhrObject: ajaxObj,
                            response: response,
                            url: url,
                            data: data
                        }, iapi, [iapi.id, response]);
                    };

                    paramObj = {};
                    paramObj['str' + requestType.toUpperCase()] = data;

                    if (ajaxObj.open) {
                        ajaxObj.abort();
                    }
                    ajaxObj.post(url, paramObj);
                }
            }, function() {
                /**
                 * For interative charts like `Select Scatter`, `DragNode`, `Dragable Column2D ` and etc.,
                 * data points value can be selected for `Scatter Chart` and values can be changed for
                 * dragable charts by clicking and dragging the data points whose data point values can be
                 * sent to an URL by ajax POST. This event is raised when `preventDefault()` method is called
                 * from the `eventObject` of FusionCharts#beforeDataSubmit event.
                 *
                 * @event FusionCharts#dataSubmitCancelled
                 * @group chart-powercharts
                 *
                 * @param {string} data - Contains the XML string with complete chart data.
                 * @param {number} httpStatus - Tells the status code of the ajax POST request
                 * @param {string} statusText - Contains the ajax error message.
                 * @param {string} url - URL to which the data is sent as ajax POST request.
                 * @param {object} xhrObject - XMLHttpRequest object which takes care of sending the XML
                 * chart data. In case of error, this object won't be defined.
                 * @example
                 * FusionCharts.addEventListener('beforeDataSubmit', function(eventObject, parameterObject) {
                 *   eventObject.preventDefault();
                 * }
                 */
                global.raiseEvent('dataSubmitCancelled', {
                    data: data
                }, iapi);
            });
        },

        _postSpaceManagement: function () {
            var iapi = this;

            chartAPI('mscartesian')._postSpaceManagement.call(iapi);
            iapi._deleteAllSelection();
        },

        eiMethods : {
            getData: function(format) {
                var apiInstance = this.apiInstance;
                return apiInstance && apiInstance.getData(format);
            },
            restoreData: function() {
                var apiInstance = this.apiInstance;
                return apiInstance && apiInstance.restoreData();
            },
            submitData: function() {
                var apiInstance = this.apiInstance;
                return apiInstance && apiInstance.submitData();
            }
        }

    }, chartAPI.scatterBase, {
        enablemousetracking: true,
        allowreversexaxis: true
    });

}]);

FusionCharts.register ('module', ['private', 'modules.renderer.js-candlestick', function () {
    var global = this,
        lib = global.hcLib,
        win = global.window,
        creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
        chartAPI = lib.chartAPI,
        pluck = lib.pluck,
        convertColor = lib.graphics.convertColor,
        preDefStr = lib.preDefStr,
        altHGridColorStr = preDefStr.altHGridColorStr,
        altHGridAlphaStr = preDefStr.altHGridAlphaStr,
        parseUnsafeString = lib.parseUnsafeString,
        COLUMN = preDefStr.column,
        COMPONENT = 'component',
        DATASET = 'dataset',
        UNDEFINED,
        componentDispose = lib.componentDispose,
        VOLUME = preDefStr.volume,
        POSITION_RIGHT = lib.POSITION_RIGHT,
        math = Math,
        mathMax = math.max,
        mathRound = math.round,
        POSITION_BOTTOM = preDefStr.POSITION_BOTTOM,
        configStr = preDefStr.configStr,
        animationObjStr = preDefStr.animationObjStr,
        MAX_MITER_LINEJOIN = 2,
        ROUND = preDefStr.ROUND,
        miterStr = preDefStr.miterStr,
        NONE = 'none',
        toRaphaelColor = lib.toRaphaelColor,
        AXIS = 'axis',
        divLineAlpha3DStr = preDefStr.divLineAlpha3DStr,
        defaultFontStr = preDefStr.defaultFontStr,
        pluckFontSize = lib.pluckFontSize, // To get the valid font size (filters negative values)
        divLineAlphaStr = preDefStr.divLineAlphaStr,
        altVGridColorStr = preDefStr.altVGridColorStr,
        altVGridAlphaStr = preDefStr.altVGridAlphaStr,
        colorStrings = preDefStr.colors,
        mathMin = math.min,
        COLOR_000000 = colorStrings.c000000,
        BLANKSTRING = lib.BLANKSTRING,
        chartPaletteStr = lib.chartPaletteStr = {
            chart2D: {
                bgColor : 'bgColor',
                bgAlpha : 'bgAlpha',
                bgAngle : 'bgAngle',
                bgRatio : 'bgRatio',
                canvasBgColor : 'canvasBgColor',
                canvasBaseColor : 'canvasBaseColor',
                divLineColor : 'divLineColor',
                legendBgColor : 'legendBgColor',
                legendBorderColor : 'legendBorderColor',
                toolTipbgColor : 'toolTipbgColor',
                toolTipBorderColor : 'toolTipBorderColor',
                baseFontColor : 'baseFontColor',
                anchorBgColor : 'anchorBgColor'
            },
            chart3D : {
                bgColor : 'bgColor3D',
                bgAlpha : 'bgAlpha3D',
                bgAngle : 'bgAngle3D',
                bgRatio : 'bgRatio3D',
                canvasBgColor : 'canvasBgColor3D',
                canvasBaseColor : 'canvasBaseColor3D',
                divLineColor : 'divLineColor3D',
                divLineAlpha : divLineAlpha3DStr,
                legendBgColor : 'legendBgColor3D',
                legendBorderColor : 'legendBorderColor3D',
                toolTipbgColor : 'toolTipbgColor3D',
                toolTipBorderColor : 'toolTipBorderColor3D',
                baseFontColor : 'baseFontColor3D',
                anchorBgColor : 'anchorBgColor3D'
            }
        },
        extend2 = lib.extend2, //old: jarendererExtend / margecolone
        pluckNumber = lib.pluckNumber;

    chartAPI('candlestick', {
        friendlyName: 'Candlestick Chart',
        standaloneInit: true,
        creditLabel: creditLabel,
        paletteIndex: 3,
        defaultDatasetType: 'candlestick',
        hasLegend: true,
        applicableDSList: {'candlestick': true},
        canvasborderthickness: 1,
        hasInteractiveLegend: false,
        init: function (container, dataObj, chartobj, callBack) {
            var iapi = this,
                components;

            // chartAttrs = dataObj.chart = (dataObj.chart || dataObj.graph ||
            //         // dataObj.map || { });
            iapi.jsonData = dataObj;
            components = iapi.components = iapi.components || (iapi.components = {});

            components.canvasVolume = components.canvasVolume || (components.canvasVolume = {
                graphics: {},
                config: {}
            });

            chartAPI.mscartesian.init.call(iapi, container, dataObj, chartobj, callBack);

        },
        configure: function () {
            var iapi = this,
                config,
                volumeHeightPercent,
                canvasConfig,
                colorM = iapi.components.colorManager,
                vCanvasConf,
                chartAttrs = iapi.jsonData.chart,
                components = iapi.components;
            iapi.base.configure.call(this);
            config = iapi.config;
            canvasConfig = components.canvas.config;
            config.showVolumeChart = pluckNumber(chartAttrs.showvolumechart, 1);
            volumeHeightPercent = pluckNumber(chartAttrs.volumeheightpercent, 40);
            config.volumeHeightPercent = volumeHeightPercent < 20 ? 20 : (volumeHeightPercent > 80 ? 80 :
                    volumeHeightPercent);
            config.canvasBorderWidth = pluckNumber(chartAttrs.canvasborderthickness, 1);
            config.rollOverBandColor = convertColor(
                pluck(chartAttrs.rolloverbandcolor, colorM.getColor(altHGridColorStr)),
                pluck(chartAttrs.rolloverbandalpha, colorM.getColor(altHGridAlphaStr)));
            vCanvasConf = components.canvasVolume.config;
            extend2(vCanvasConf, canvasConfig);
        },
        _createDatasets : function () {
            var iapi = this,
                config = iapi.config,
                components = iapi.components,
                //graphics = iapi.graphics,
                //datasetGroup = graphics.datasetGroup,
                dataObj = iapi.jsonData,
                chartAttr = dataObj.chart,
                dataset = dataObj.dataset,
                trendset = dataObj.trendset || [],
                showVolumeChart = iapi.config.showVolumeChart,
                length = dataset && dataset.length,
                i,
                datasetStore,
                datasetObj,
                defaultSeriesType = iapi.defaultDatasetType,
                plotType = pluck(parseUnsafeString(chartAttr.plotpriceas), COLUMN),
                dsType,
                DsClass,
                datasetJSON,
                JSONData,
                prevDataLength,
                currDataLength,
                count = 0,
                // map,line,area,column, stores the index of the various dataplots in combinational charts.
                datasetMap = config.datasetMap || (config.datasetMap = {
                    trendset : [],
                    candlestick : []
                }),
                dsTypeRef,
                dsRef,
                dsCount = {},
                tempMap = {
                    trendset: [],
                    candlestick : []
                },
                datasetComp,
                j,
                vYAxis,
                legend = components.legend,
                obj;

            if (!dataset) {
                iapi.setChartMessage();
                return;
            }

            iapi.config.categories = dataObj.categories && dataObj.categories[0].category;

            datasetStore = components.dataset = [];

            for(i = 0, length = dataset.length; i < length; i++) {

                datasetJSON = dataset[i];
                datasetJSON.seriesname &&  (datasetJSON.seriesname = parseUnsafeString(datasetJSON.seriesname));
                dsType = pluck(datasetJSON.renderas, defaultSeriesType);
                dsType = dsType && dsType.toLowerCase();
                /// get the DsClass
                DsClass = FusionCharts.get(COMPONENT, [DATASET, dsType]);
                dsTypeRef = datasetMap[dsType];
                dsRef = dsTypeRef[0];

                if (DsClass) {
                    if (dsCount[dsType] === UNDEFINED) {
                        dsCount[dsType] = 0;
                    }
                    else {
                        dsCount[dsType]++;
                    }
                    // create the dataset Object
                    if (!dsRef) {
                        datasetObj = new DsClass();
                        datasetStore.push(datasetObj);
                        tempMap[dsType].push(datasetObj);
                        datasetObj.chart = iapi;
                        datasetObj.index = count;
                        datasetObj.init(datasetJSON);
                    }
                    else {
                        datasetComp = dsRef;
                        dsRef.index = i;
                        if (plotType !== datasetComp.config.plotType) {
                            componentDispose.call(datasetComp);
                            datasetObj = datasetStore[count] = new DsClass();
                            datasetObj.chart = iapi;
                            datasetObj.index = count;
                            datasetObj.init(datasetJSON);
                            dsRef = datasetObj;
                        }
                        else {
                            JSONData = dsRef.JSONData;
                            prevDataLength = JSONData && JSONData.data && JSONData.data.length;
                            currDataLength = datasetJSON.data && datasetJSON.data.length;
                            // Removing data plots if the number of
                            // current data plots is more than the existing ones.
                            if (prevDataLength > currDataLength) {
                                dsRef.removeData(currDataLength - 1,
                                    prevDataLength - currDataLength, false);
                            }
                            dsRef.JSONData = datasetJSON;
                        }
                        dsRef.configure();
                        tempMap[dsType].push(dsRef);
                        datasetStore.push (dsRef);
                        dsTypeRef.shift();
                    }
                }
                count++;

                vYAxis = components.yAxis && components.yAxis[1];
                if (showVolumeChart && iapi.config.drawVolume) {
                    vYAxis && vYAxis.show();
                    if (DsClass) {
                        if (dsCount[dsType] === UNDEFINED) {
                            dsCount[dsType] = 0;
                        }
                        else {
                            dsCount[dsType]++;
                        }
                        dsTypeRef = datasetMap[dsType];
                        dsRef = dsTypeRef[0];
                        if (!dsRef) {
                            datasetObj = new DsClass();
                            datasetObj.chart = iapi;
                            datasetStore.push(datasetObj);
                            tempMap[dsType].push(datasetObj);
                            datasetObj.init(datasetJSON, VOLUME);
                        }
                        else {
                            JSONData = dsRef.JSONData;
                            prevDataLength = JSONData && JSONData.data && JSONData.data.length;
                            currDataLength = datasetJSON.data && datasetJSON.data.length;
                            // Removing data plots if the number of current
                            // data plots is more than the existing ones.
                            if (prevDataLength > currDataLength) {
                                dsRef.removeData(currDataLength - 1,
                                    prevDataLength - currDataLength, false);
                            }
                            dsRef.JSONData = datasetJSON;
                            dsRef.configure();
                            datasetStore.push (dsRef);
                            tempMap[dsType].push(dsRef);
                            dsTypeRef.shift();
                        }
                    }
                    count++;
                }
                else {
                    vYAxis && vYAxis.hide();
                }
                if (iapi.config.drawVolume && showVolumeChart) {
                    showVolumeChart = iapi.config.showVolumeChart = 1;
                }
                else {
                    showVolumeChart = iapi.config.showVolumeChart = 0;
                }
            }
            for (i = 0,length = trendset.length; i < length; i++) {
                datasetJSON = trendset[i];
                dsType = 'trendset';
                dsTypeRef = datasetMap[dsType];
                dsRef = dsTypeRef[0];
                if (dsCount[dsType] === UNDEFINED) {
                    dsCount[dsType] = 0;
                }
                else {
                    dsCount[dsType]++;
                }
                if (!dsRef) {
                    DsClass = FusionCharts.get(COMPONENT, [DATASET, dsType]);
                    obj = new DsClass();
                    datasetStore.push(obj);
                    tempMap[dsType].push(obj);
                    obj.chart = iapi;
                    obj.index = count;
                    obj.init(datasetJSON);
                }
                else {
                    JSONData = dsRef.JSONData;
                    prevDataLength = JSONData && JSONData.data && JSONData.data.length;
                    currDataLength = datasetJSON.data && datasetJSON.data.length;
                    tempMap[dsType].push(dsRef);
                    datasetStore.push (dsRef);
                    dsRef.index = count;
                    // Removing data plots if the number of current data plots is more than the existing ones.
                    if (prevDataLength > currDataLength) {
                        dsRef.removeData(currDataLength - 1,
                            prevDataLength - currDataLength, false);
                    }
                    dsRef.JSONData = datasetJSON;
                    dsRef.configure();

                    dsTypeRef.shift();
                }
                count++;
            }

            // Removing unused datasets if any
            for (dataset in datasetMap) {
                dsTypeRef  = datasetMap[dataset];
                length = dsTypeRef.length;
                count = dsCount[dataset] || -1;
                if (length) {
                    for (j = 0; j < length; j++) {
                        legend.removeItem(dsTypeRef[j].legendItemId);
                        componentDispose.call(dsTypeRef[j]);
                    }
                }
            }

            config.datasetMap = tempMap;

        },
        _spaceManager: function () {
            // todo marge _allocateSpace and _spacemanager
            var spaceForActionBar,
                actionBarSpace,
                availableWidth,
                availableHeight,
                iapi = this,
                config = iapi.config,
                components = iapi.components,
                legendPosition = config.legendPosition,
                xAxis = components.xAxis && components.xAxis[0],
                vxAxis = components.xAxis && components.xAxis[1],
                yAxis = components.yAxis && components.yAxis[0],
                yAxis2 = components.yAxis && components.yAxis[1],
                hasLegend = iapi.hasLegend,
                legend = components.legend,
                canvasHeight,
                xAxisDimensions,
                showVolumeChart = iapi.config.showVolumeChart,
                volumeHeightPercent = showVolumeChart ? config.volumeHeightPercent : 0,
                canvasConfig = components.canvas.config,
                vCanvasConfig = components.canvasVolume.config,
                vCanvasY,
                padding = 6,
                canvasY,
                xAxis2dimensions,
                yAxisDim,
                vYAxisDim,
                width = config.width,
                height = config.height,
                actualYDim = {},
                allottedSpace,
                chartBorderWidth = config.chartBorderWidth,
                canvasBorderWidth = components.canvas.config.canvasBorderWidth,
                minCanvasHeight = config.minCanvasHeight,
                minCanvasWidth = config.minCanvasWidth,
                canvasMarginLeft = config.canvasMarginLeft,
                canvasMarginRight = config.canvasMarginRight,
                canvasMarginTop = config.canvasMarginTop,
                canvasMarginBottom = config.canvasMarginBottom,
                diff,
                currentCanvasHeight,
                currentCanvasWidth,
                heightAdjust,
                origCanvasTopMargin = config.origCanvasTopMargin,
                origCanvasBottomMargin = config.origCanvasBottomMargin,
                origCanvasLeftMargin = config.origCanvasLeftMargin,
                origCanvasRightMargin = config.origCanvasRightMargin,
                left,
                right,
                top,
                bottom,

                widthAdjust,
                sum;
            // Manage space

            iapi._allocateSpace ( {
                top : chartBorderWidth,
                bottom : chartBorderWidth,
                left : chartBorderWidth,
                right : chartBorderWidth
            });

            // iapi._allocateSpace ( {
            //     left : config.canvasMarginLeft,
            //     right : config.canvasMarginRight
            // });

            spaceForActionBar = config.availableHeight * 0.225;
            actionBarSpace = iapi._manageActionBarSpace && iapi._manageActionBarSpace(spaceForActionBar) ||
                {};
            iapi._allocateSpace(actionBarSpace);

            if (legendPosition === POSITION_RIGHT) {
                allottedSpace = config.canvasWidth * 0.225;
            }
            else {
                allottedSpace = config.canvasHeight * 0.3;
            }
            ((hasLegend !== false) && xAxis) &&
                iapi._allocateSpace(legend._manageLegendPosition(allottedSpace));
            availableWidth = config.canvasWidth * 0.7;
            yAxisDim = yAxis.placeAxis(availableWidth);
            vYAxisDim = showVolumeChart ? yAxis2.placeAxis(availableWidth) : {};
            actualYDim.left = mathMax(yAxisDim.left, vYAxisDim.left || 0);
            actualYDim.right = mathMax(yAxisDim.right, vYAxisDim.right || 0);
            iapi._allocateSpace(actualYDim);

            // Check for minimun canvas width for applying canvas left and right margin.
            if (minCanvasWidth > width - canvasMarginLeft - canvasMarginRight) {
                widthAdjust = true;
                diff = config.canvasWidth - minCanvasWidth;
                sum = canvasMarginLeft + canvasMarginRight;
                canvasMarginLeft = config.canvasMarginLeft = diff * canvasMarginLeft / sum;
                canvasMarginRight = config.canvasMarginRight = diff * canvasMarginRight / sum;
            }

            // Calculating the left and right canvas margin.
            left = canvasMarginLeft > config.canvasLeft ? (canvasMarginLeft - config.canvasLeft) : 0;
            right = canvasMarginRight > (width - config.canvasRight) ? (canvasMarginRight +
                config.canvasRight - width) : 0;

            iapi._allocateSpace ( {
                left : left,
                right : right
            });

            // Forcing canvas width to its minimum
            if (widthAdjust) {
                sum = origCanvasLeftMargin + origCanvasRightMargin;
                currentCanvasWidth = config.canvasWidth;
                if (currentCanvasWidth > minCanvasWidth) {
                    diff = currentCanvasWidth - minCanvasWidth;
                    left = diff * origCanvasLeftMargin / sum;
                    right = diff * origCanvasRightMargin / sum;
                }
                iapi._allocateSpace ( {
                    left : left,
                    right : right
                });
            }

            availableHeight = config.canvasHeight * 0.225;

            availableHeight = (legendPosition === POSITION_BOTTOM) ? config.canvasHeight * 0.6 :
                config.canvasWidth * 0.6;
            // a space manager that manages the space for the tools as well as the captions.
            iapi._manageChartMenuBar(availableHeight);

            iapi._allocateSpace ( {
                top : config.canvasMarginTop,
                bottom : config.canvasMarginBottom
            });

            availableHeight = config.canvasHeight * 0.3;
            xAxisDimensions = xAxis.placeAxis(availableHeight);
            xAxis && iapi._allocateSpace(xAxisDimensions);
            xAxisDimensions.bottom += padding;
            canvasConfig.intermediarySpace = xAxisDimensions.bottom;
            if (showVolumeChart) {
                xAxis2dimensions = vxAxis.placeAxis(availableHeight);
                iapi._allocateSpace(xAxis2dimensions);
            }
            iapi._allocateSpace({
                top : canvasBorderWidth,
                bottom : canvasBorderWidth * 2,
                left : canvasBorderWidth,
                right : canvasBorderWidth
            });

            // Check for minimum canvas height for applying top and bottom margin.
            if (minCanvasHeight > height - canvasMarginTop - canvasMarginBottom) {
                heightAdjust = true;
                diff = config.canvasHeight - minCanvasHeight;
                sum = canvasMarginTop + canvasMarginBottom;
                canvasMarginTop = config.canvasMarginTop = diff * canvasMarginTop / sum;
                canvasMarginBottom = config.canvasMarginBottom = diff * canvasMarginBottom / sum;
            }

            // Allocate space for canvas margin only if the margin is less than the margin entered by the user.
            top = canvasMarginTop > config.canvasTop ? (canvasMarginTop - config.canvasTop) : 0;
            bottom = canvasMarginBottom > (height - config.canvasBottom) ? (canvasMarginBottom +
                config.canvasBottom - height) : 0;

            iapi._allocateSpace ( {
                top : top,
                bottom : bottom
            });

            // Forcing canvas height to its minimum
            if (heightAdjust) {
                sum = origCanvasTopMargin + origCanvasBottomMargin;
                currentCanvasHeight = config.canvasHeight;
                if (currentCanvasHeight > minCanvasHeight) {
                    diff = currentCanvasHeight - minCanvasHeight;
                    top = diff * origCanvasTopMargin / sum;
                    bottom = diff * origCanvasBottomMargin / sum;
                }
                iapi._allocateSpace ( {
                    top : top,
                    bottom : bottom
                });
            }
            canvasHeight = config.canvasHeight;
            canvasConfig.canvasHeight = mathRound((100 - volumeHeightPercent)/100 * canvasHeight);
            vCanvasConfig.canvasHeight = ((volumeHeightPercent/100) * canvasHeight);

            canvasConfig.canvasTop = config.canvasTop;
            canvasConfig.canvasLeft = config.canvasLeft;
            canvasConfig.canvasBottom = canvasConfig.canvasTop + canvasConfig.canvasHeight;
            canvasConfig.canvasWidth = config.canvasWidth;
            canvasConfig.canvasRight = config.canvasRight;
            vCanvasConfig.canvasTop = canvasConfig.canvasBottom + xAxisDimensions.bottom +
                (canvasBorderWidth * 2);
            vCanvasConfig.canvasLeft = config.canvasLeft;
            vCanvasConfig.canvasBottom = vCanvasConfig.canvasTop + vCanvasConfig.canvasHeight +
                (canvasBorderWidth * 2);
            vCanvasConfig.canvasRight = config.canvasRight;
            vCanvasConfig.canvasWidth = config.canvasWidth;

            canvasY = config.canvasTop + canvasConfig.canvasHeight + canvasBorderWidth;
            vCanvasY = config.canvasTop + canvasConfig.canvasHeight + xAxisDimensions.bottom +
                (canvasBorderWidth * 2);
            canvasConfig.canvasY = canvasY;
            vCanvasConfig.canvasY = vCanvasY;
        },
        _postSpaceManagement : function () {
            var iapi = this,
                components = iapi.components,
                showVolumeChart = iapi.config.showVolumeChart,
                xAxis = components.xAxis && components.xAxis[0],
                yAxis = components.yAxis && components.yAxis[0],
                vxAxis = components.xAxis && components.xAxis[1],
                vyAxis = components.yAxis && components.yAxis[1],
                canvasConfig = components.canvas.config,
                legend = components.legend,
                vCanvasConfig = components.canvasVolume.config,
                canvasBorderWidth = canvasConfig.canvasBorderWidth;

            xAxis && xAxis.setAxisDimention({
                x : canvasConfig.canvasLeft,
                y : canvasConfig.canvasY,
                opposite : canvasConfig.canvasTop - canvasBorderWidth,
                axisLength : canvasConfig.canvasWidth
            });
            yAxis && yAxis.setAxisDimention({
                x : canvasConfig.canvasLeft - canvasBorderWidth,
                y : canvasConfig.canvasTop,
                opposite : canvasConfig.canvasRight + canvasBorderWidth,
                axisLength : canvasConfig.canvasHeight
            });

            if (showVolumeChart) {
                vxAxis && vxAxis.setAxisDimention({
                    x : canvasConfig.canvasLeft,
                    y : vCanvasConfig.canvasBottom,
                    opposite : vCanvasConfig.canvasTop - canvasBorderWidth,
                    axisLength : canvasConfig.canvasWidth
                });
                vyAxis && vyAxis.setAxisDimention({
                    x : canvasConfig.canvasLeft - canvasBorderWidth,
                    y : vCanvasConfig.canvasY,
                    opposite : vCanvasConfig.canvasRight + canvasBorderWidth,
                    axisLength : vCanvasConfig.canvasHeight
                });
                vxAxis && vxAxis.setCanvas(vCanvasConfig);
                vyAxis && vyAxis.setCanvas(vCanvasConfig);
            }
            xAxis.setCanvas(canvasConfig);
            yAxis.setCanvas(canvasConfig);
            legend.postSpaceManager();
        },
        _drawCanvas: function () {
            var iapi = this,
                components = iapi.components,
                chartGraphics = iapi.graphics,
                paper = components.paper,
                canvas = components.canvas,
                topCanvas = components.canvas.config,
                clip = topCanvas.clip || (topCanvas.clip = []),
                volumeCanvas = components.canvasVolume.config,
                graphics = canvas.graphics,
                vCanvasGraphics = components.canvasVolume.graphics,
                config = canvas.config,
                topCanvasElement = graphics.topCanvas,
                topCanvasBorderElement = graphics.topCanvasBorderElement,
                volumeCanvasElement = vCanvasGraphics.volumeCanvas,
                canvasLeft = topCanvas.canvasLeft,
                canvasTop = topCanvas.canvasTop,
                canvasWidth = topCanvas.canvasWidth,
                canvasHeight = topCanvas.canvasHeight,
                vCanvasTop = volumeCanvas.canvasTop,
                vCanvasHeight = volumeCanvas.canvasHeight,
                canvasGroup = chartGraphics.canvasGroup,
                canvasBorderRadius = config.canvasBorderRadius,
                canvasBorderWidth = config.canvasBorderWidth,
                borderWHlf = canvasBorderWidth * 0.5,
                canvasBorderColor = config.canvasBorderColor,
                animationObj = iapi.get(configStr, animationObjStr),
                dummyAnimElem = animationObj.dummyObj,
                dummyAnimObj = animationObj.animObj,
                animType = animationObj.animType,
                transposeAnimDuration = animationObj.transposeAnimDuration,
                canvasBgColor,
                attr1,
                attr2,
                topBorderAttr,
                showVolumeChart = iapi.config.showVolumeChart,
                shadow = config.shadow,
                shadowOnCanvasFill = config.shadowOnCanvasFill;

            canvasBgColor = config.canBGColor;
            // Upper canvas border attributes
            topBorderAttr = {
                x: canvasLeft - borderWHlf,
                y: canvasTop - borderWHlf,
                width: canvasWidth + canvasBorderWidth,
                height: canvasHeight + canvasBorderWidth,
                r: canvasBorderRadius,
                'stroke-width': canvasBorderWidth,
                stroke: canvasBorderColor,
                'stroke-linejoin': canvasBorderWidth > MAX_MITER_LINEJOIN ? ROUND : miterStr
            };

            if (!topCanvasBorderElement) {
                topCanvasBorderElement = graphics.topCanvasBorderElement = paper.rect(topBorderAttr, canvasGroup)
                .shadow(shadow);
            }
            else {
                if (transposeAnimDuration) {
                    topCanvasBorderElement.animateWith(dummyAnimElem, dummyAnimObj, {
                        x: canvasLeft - borderWHlf,
                        y: canvasTop - borderWHlf,
                        width: canvasWidth + canvasBorderWidth,
                        height: canvasHeight + canvasBorderWidth,
                        r: canvasBorderRadius
                    }, transposeAnimDuration, animType);
                }
                else {
                    topCanvasBorderElement.attr(topBorderAttr);
                }
            }

            topCanvasBorderElement.attr({
                'stroke-width': canvasBorderWidth,
                stroke: canvasBorderColor,
                'stroke-linejoin': canvasBorderWidth > MAX_MITER_LINEJOIN ? ROUND : miterStr
            });
            clip['clip-canvas'] = [
                mathMax (0, canvasLeft),
                mathMax (0, canvasTop),
                mathMax (1, canvasWidth),
                mathMax (1, canvasHeight)
            ];
            clip['clip-canvas-init'] = [
                mathMax (0, canvasLeft),
                mathMax (0, canvasTop),
                1,
                mathMax (1, canvasHeight)
            ];

            if (!topCanvasElement) {
                graphics.topCanvas = topCanvasElement = paper.rect(canvasGroup);
                topCanvasElement.attr({
                    x: canvasLeft,
                    y: canvasTop,
                    width: canvasWidth,
                    height: canvasHeight
                })
                .shadow(shadowOnCanvasFill);
            }
            else {
                if (transposeAnimDuration) {
                    topCanvasElement.animate({
                        x: canvasLeft,
                        y: canvasTop,
                        width: canvasWidth,
                        height: canvasHeight
                    }, transposeAnimDuration, animType)
                    .attr({
                        r: canvasBorderRadius
                    });
                }
                else {
                    topCanvasElement.attr(attr1);
                }
            }

            topCanvasElement.animateWith(dummyAnimElem, dummyAnimObj, {
                x: canvasLeft,
                y: canvasTop,
                width: canvasWidth,
                height: canvasHeight
            }, transposeAnimDuration, animType);

            topCanvasElement.attr({
                r: canvasBorderRadius,
                'stroke-width': 0,
                'stroke': NONE,
                fill: toRaphaelColor(canvasBgColor)
            });

            if (showVolumeChart) {

                attr2 = {
                    x: canvasLeft - borderWHlf,
                    y: vCanvasTop - borderWHlf - 1,
                    width: canvasWidth + canvasBorderWidth,
                    height: vCanvasHeight + canvasBorderWidth
                };

                if (!volumeCanvasElement) {
                    vCanvasGraphics.volumeCanvas = volumeCanvasElement = paper.rect(canvasGroup)
                        .attr(attr2)
                        .shadow(shadowOnCanvasFill)
                        .crisp();
                }

                volumeCanvasElement.show().animateWith(dummyAnimElem, dummyAnimObj, attr2,
                    transposeAnimDuration, animType).attr({
                        r: canvasBorderRadius,
                        fill: toRaphaelColor(canvasBgColor),
                        'stroke-width': canvasBorderWidth,
                        stroke: canvasBorderColor,
                        'stroke-linejoin': canvasBorderWidth > 2 ?
                            ROUND : miterStr,
                        'shape-rendering': 'crisp'
                    });
            }
            else {
                volumeCanvasElement && volumeCanvasElement.hide();
            }

        },
        _createAxes: function () {
            var iapi = this,
                components = iapi.components,
                yAxis1,
                CartesianAxis = FusionCharts.register(COMPONENT, [AXIS, 'cartesian']),
                showVolumeChart = iapi.config.showVolumeChart,
                yAxis,
                xAxis,
                vxAxis;

            components.yAxis = [];
            components.xAxis = [];
            components.yAxis[0] = yAxis = new CartesianAxis();
            components.yAxis[1] = yAxis1 = new CartesianAxis();

            components.xAxis[0] = xAxis = new CartesianAxis();
            yAxis.chart = iapi;
            yAxis1.chart = iapi;
            xAxis.chart = iapi;
            if (showVolumeChart) {
                components.xAxis[1] = vxAxis = new CartesianAxis();
                vxAxis.chart = iapi;
                vxAxis.init();
            }

            yAxis.init();
            yAxis1.init();

            xAxis.init();
            // set the chart categories
            iapi._setCategories();
        },
        _feedAxesRawData: function () {
            var iapi = this,
                components = iapi.components,
                colorM = components.colorManager,
                dataObj = iapi.jsonData,
                chartAttrs = dataObj.chart,
                xAxisConf,
                yAxis1,
                yAxisConf,
                vYAxisConf,
                is3d = iapi.is3d,
                palleteString = is3d ? chartPaletteStr.chart3D : chartPaletteStr.chart2D,
                CartesianAxis = FusionCharts.register(COMPONENT, [AXIS, 'cartesian']),
                yAxis,
                xAxis,
                showVolumeChart = iapi.config.showVolumeChart,
                vxAxis,
                vxAxisConf;
            xAxisConf = {
                outCanfontFamily: pluck(chartAttrs.outcnvbasefont, chartAttrs.basefont, defaultFontStr),
                outCanfontSize:  pluckFontSize(chartAttrs.outcnvbasefontsize, chartAttrs.basefontsize, 10),
                outCancolor: pluck(chartAttrs.outcnvbasefontcolor, chartAttrs.basefontcolor,
                    colorM.getColor(palleteString.baseFontColor)).replace(/^#?([a-f0-9]+)/ig, '#$1'),
                axisNamePadding: chartAttrs.xaxisnamepadding,
                axisValuePadding: chartAttrs.labelpadding,
                axisNameFont: chartAttrs.xaxisnamefont,
                axisNameFontSize: chartAttrs.xaxisnamefontsize,
                axisNameFontColor: chartAttrs.xaxisnamefontcolor,
                axisNameFontBold: chartAttrs.xaxisnamefontbold,
                axisNameFontItalic: chartAttrs.xaxisnamefontitalic,
                axisNameBgColor: chartAttrs.xaxisnamebgcolor,
                axisNameBorderColor: chartAttrs.xaxisnamebordercolor,
                axisNameAlpha: chartAttrs.xaxisnamealpha,
                axisNameFontAlpha: chartAttrs.xaxisnamefontalpha,
                axisNameBgAlpha: chartAttrs.xaxisnamebgalpha,
                axisNameBorderAlpha: chartAttrs.xaxisnameborderalpha,
                axisNameBorderPadding: chartAttrs.xaxisnameborderpadding,
                axisNameBorderRadius: chartAttrs.xaxisnameborderradius,
                axisNameBorderThickness: chartAttrs.xaxisnameborderthickness,
                axisNameBorderDashed: chartAttrs.xaxisnameborderdashed,
                axisNameBorderDashLen: chartAttrs.xaxisnameborderdashlen,
                axisNameBorderDashGap: chartAttrs.xaxisnameborderdashgap,
                useEllipsesWhenOverflow: chartAttrs.useellipseswhenoverflow,
                divLineColor: pluck (chartAttrs.vdivlinecolor, chartAttrs.divlinecolor,
                    colorM.getColor (palleteString.divLineColor)),
                divLineAlpha: pluck (chartAttrs.vdivlinealpha, chartAttrs.divlinealpha,
                    is3d ? colorM.getColor(divLineAlpha3DStr) : colorM.getColor (divLineAlphaStr)),
                divLineThickness: pluckNumber (chartAttrs.vdivlinethickness, chartAttrs.divlinethickness, 1),
                divLineIsDashed: Boolean (pluckNumber (chartAttrs.vdivlinedashed, chartAttrs.vdivlineisdashed,
                    chartAttrs.divlinedashed, chartAttrs.divlineisdashed, 0)),
                divLineDashLen: pluckNumber (chartAttrs.vdivlinedashlen, chartAttrs.divlinedashlen, 4),
                divLineDashGap: pluckNumber (chartAttrs.vdivlinedashgap, chartAttrs.divlinedashgap, 2),
                showAlternateGridColor: pluckNumber(chartAttrs.showalternatevgridcolor, 0),
                alternateGridColor: pluck(chartAttrs.alternatevgridcolor, colorM.getColor(altVGridColorStr)),
                alternateGridAlpha: pluck(chartAttrs.alternatevgridalpha, colorM.getColor(altVGridAlphaStr)),
                numDivLines: chartAttrs.numvdivlines,
                labelFont: chartAttrs.labelfont,
                labelFontSize: chartAttrs.labelfontsize,
                labelFontColor: chartAttrs.labelfontcolor,
                labelFontAlpha: chartAttrs.labelalpha,
                labelFontBold : chartAttrs.labelfontbold,
                labelFontItalic : chartAttrs.labelfontitalic,
                axisName: chartAttrs.xaxisname,
                axisMinValue: chartAttrs.xaxisminvalue,
                axisMaxValue: chartAttrs.xaxismaxvalue,
                setAdaptiveMin: chartAttrs.setadaptivexmin,
                adjustDiv: chartAttrs.adjustvdiv,
                labelDisplay: chartAttrs.labeldisplay,
                showLabels: chartAttrs.showlabels,
                rotateLabels: chartAttrs.rotatelabels,
                slantLabel: pluckNumber(chartAttrs.slantlabels, chartAttrs.slantlabel),
                labelStep: pluckNumber(chartAttrs.labelstep, chartAttrs.xaxisvaluesstep),
                showAxisValues: pluckNumber(chartAttrs.showxaxisvalues,  chartAttrs.showxaxisvalue),
                showLimits: chartAttrs.showvlimits,
                showDivLineValues: pluckNumber(chartAttrs.showvdivlinevalues, chartAttrs.showvdivlinevalues),
                showZeroPlane: chartAttrs.showvzeroplane,
                zeroPlaneColor: chartAttrs.vzeroplanecolor,
                zeroPlaneThickness: chartAttrs.vzeroplanethickness,
                zeroPlaneAlpha: chartAttrs.vzeroplanealpha,
                showZeroPlaneValue: chartAttrs.showvzeroplanevalue,
                trendlineColor: chartAttrs.trendlinecolor,
                trendlineToolText: chartAttrs.trendlinetooltext,
                trendlineThickness: chartAttrs.trendlinethickness,
                trendlineAlpha: chartAttrs.trendlinealpha,
                showTrendlinesOnTop: chartAttrs.showtrendlinesontop,
                showAxisLine: pluckNumber(chartAttrs.showxaxisline, chartAttrs.showaxislines,
                    chartAttrs.drawAxisLines, 0),
                axisLineThickness: pluckNumber(chartAttrs.xaxislinethickness, chartAttrs.axislinethickness, 1),
                axisLineAlpha: pluckNumber(chartAttrs.xaxislinealpha, chartAttrs.axislinealpha, 100),
                axisLineColor: pluck(chartAttrs.xaxislinecolor, chartAttrs.axislinecolor, COLOR_000000)
            };
            vxAxisConf = {
                outCanfontFamily: pluck(chartAttrs.outcnvbasefont, chartAttrs.basefont, defaultFontStr),
                outCanfontSize:  pluckFontSize(chartAttrs.outcnvbasefontsize, chartAttrs.basefontsize, 10),
                outCancolor: pluck(chartAttrs.outcnvbasefontcolor, chartAttrs.basefontcolor,
                    colorM.getColor(palleteString.baseFontColor)).replace(/^#?([a-f0-9]+)/ig, '#$1'),
                axisNamePadding: chartAttrs.xaxisnamepadding,
                axisValuePadding: chartAttrs.labelpadding,
                axisNameFont: chartAttrs.xaxisnamefont,
                axisNameFontSize: chartAttrs.xaxisnamefontsize,
                axisNameFontColor: chartAttrs.xaxisnamefontcolor,
                axisNameFontBold: chartAttrs.xaxisnamefontbold,
                axisNameFontItalic: chartAttrs.xaxisnamefontitalic,
                axisNameBgColor: chartAttrs.xaxisnamebgcolor,
                axisNameBorderColor: chartAttrs.xaxisnamebordercolor,
                axisNameAlpha: chartAttrs.xaxisnamealpha,
                axisNameFontAlpha: chartAttrs.xaxisnamefontalpha,
                axisNameBgAlpha: chartAttrs.xaxisnamebgalpha,
                axisNameBorderAlpha: chartAttrs.xaxisnameborderalpha,
                axisNameBorderPadding: chartAttrs.xaxisnameborderpadding,
                axisNameBorderRadius: chartAttrs.xaxisnameborderradius,
                axisNameBorderThickness: chartAttrs.xaxisnameborderthickness,
                axisNameBorderDashed: chartAttrs.xaxisnameborderdashed,
                axisNameBorderDashLen: chartAttrs.xaxisnameborderdashlen,
                axisNameBorderDashGap: chartAttrs.xaxisnameborderdashgap,
                useEllipsesWhenOverflow: chartAttrs.useellipseswhenoverflow,
                divLineColor: pluck(chartAttrs.vdivlinecolor, colorM.getColor(palleteString.divLineColor)),
                divLineAlpha: pluck(chartAttrs.vdivlinealpha, colorM.getColor(divLineAlphaStr)),
                divLineThickness: pluckNumber(chartAttrs.vdivlinethickness, 1),
                divLineIsDashed: Boolean(pluckNumber(chartAttrs.vdivlinedashed, chartAttrs.vdivlineisdashed, 0)),
                divLineDashLen: pluckNumber(chartAttrs.vdivlinedashlen, 4),
                divLineDashGap: pluckNumber(chartAttrs.vdivlinedashgap, 2),
                showAlternateGridColor: pluckNumber(chartAttrs.showalternatevgridcolor, 0),
                alternateGridColor: pluck(chartAttrs.alternatevgridcolor, colorM.getColor(altVGridColorStr)),
                alternateGridAlpha: pluck(chartAttrs.alternatevgridalpha, colorM.getColor(altVGridAlphaStr)),
                numDivLines: chartAttrs.numvdivlines,
                labelFont: chartAttrs.labelfont,
                labelFontSize: chartAttrs.labelfontsize,
                labelFontColor: chartAttrs.labelfontcolor,
                labelFontAlpha: chartAttrs.labelalpha,
                labelFontBold : chartAttrs.labelfontbold,
                labelFontItalic : chartAttrs.labelfontitalic,
                axisName: chartAttrs.xaxisname,
                axisMinValue: chartAttrs.xaxisminvalue,
                axisMaxValue: chartAttrs.xaxismaxvalue,
                setAdaptiveMin: chartAttrs.setadaptivexmin,
                adjustDiv: chartAttrs.adjustvdiv,
                labelDisplay: chartAttrs.labeldisplay,
                showLabels: 1,
                rotateLabels: chartAttrs.rotatelabels,
                slantLabel: pluckNumber(chartAttrs.slantlabels, chartAttrs.slantlabel),
                labelStep: pluckNumber(chartAttrs.labelstep, chartAttrs.xaxisvaluesstep),
                showAxisValues: pluckNumber(chartAttrs.showxaxisvalues,  chartAttrs.showxaxisvalue),
                showLimits: chartAttrs.showvlimits,
                showDivLineValues: pluckNumber(chartAttrs.showvdivlinevalues, chartAttrs.showvdivlinevalues),
                showZeroPlane: chartAttrs.showvzeroplane,
                zeroPlaneColor: chartAttrs.vzeroplanecolor,
                zeroPlaneThickness: chartAttrs.vzeroplanethickness,
                zeroPlaneAlpha: chartAttrs.vzeroplanealpha,
                showZeroPlaneValue: chartAttrs.showvzeroplanevalue,
                trendlineColor: chartAttrs.trendlinecolor,
                trendlineToolText: chartAttrs.trendlinetooltext,
                trendlineThickness: chartAttrs.trendinethickness,
                trendlineAlpha: chartAttrs.trendlinealpha,
                showTrendlinesOnTop: chartAttrs.showtrendlinesontop,
                showAxisLine: pluckNumber(chartAttrs.showxaxisline, chartAttrs.showaxislines,
                    chartAttrs.drawAxisLines, 0),
                axisLineThickness: pluckNumber(chartAttrs.xaxislinethickness, chartAttrs.axislinethickness, 1),
                axisLineAlpha: pluckNumber(chartAttrs.xaxislinealpha, chartAttrs.axislinealpha, 100),
                axisLineColor: pluck(chartAttrs.xaxislinecolor, chartAttrs.axislinecolor, COLOR_000000)
            };
            yAxisConf = {
                outCanfontFamily: pluck(chartAttrs.outcnvbasefont, chartAttrs.basefont, defaultFontStr),
                outCanfontSize:  pluckFontSize(chartAttrs.outcnvbasefontsize, chartAttrs.basefontsize, 10),
                outCancolor: pluck(chartAttrs.outcnvbasefontcolor, chartAttrs.basefontcolor,
                    colorM.getColor(palleteString.baseFontColor)).replace(/^#?([a-f0-9]+)/ig, '#$1'),
                axisNamePadding: chartAttrs.yaxisnamepadding,
                axisValuePadding: chartAttrs.yaxisvaluespadding,
                axisNameFont: chartAttrs.pyaxisnamefont,
                axisNameFontSize: chartAttrs.pyaxisnamefontsize,
                axisNameFontColor: chartAttrs.pyaxisnamefontcolor,
                axisNameFontBold: chartAttrs.pyaxisnamefontbold,
                axisNameFontItalic: chartAttrs.pyaxisnamefontitalic,
                axisNameBgColor: chartAttrs.pyaxisnamebgcolor,
                axisNameBorderColor: chartAttrs.pyaxisnamebordercolor,
                axisNameAlpha: chartAttrs.pyaxisnamealpha,
                axisNameFontAlpha: chartAttrs.pyaxisnamefontalpha,
                axisNameBgAlpha: chartAttrs.pyaxisnamebgalpha,
                axisNameBorderAlpha: chartAttrs.pyaxisnameborderalpha,
                axisNameBorderPadding: chartAttrs.pyaxisnameborderpadding,
                axisNameBorderRadius: chartAttrs.pyaxisnameborderradius,
                axisNameBorderThickness: chartAttrs.pyaxisnameborderthickness,
                axisNameBorderDashed: chartAttrs.pyaxisnameborderdashed,
                axisNameBorderDashLen: chartAttrs.pyaxisnameborderdashlen,
                axisNameBorderDashGap: chartAttrs.pyaxisnameborderdashgap,
                axisNameWidth: chartAttrs.yaxisnamewidth,
                useEllipsesWhenOverflow: chartAttrs.useellipseswhenoverflow,
                rotateAxisName: pluckNumber(chartAttrs.rotateyaxisname, 1),
                axisName: chartAttrs.pyaxisname,
                divLineColor: pluck(chartAttrs.divlinecolor, colorM.getColor(palleteString.divLineColor)),
                divLineAlpha: pluck(chartAttrs.divlinealpha, colorM.getColor(divLineAlphaStr)),
                divLineThickness: pluckNumber(chartAttrs.divlinethickness, 1),
                divLineIsDashed: Boolean(pluckNumber(chartAttrs.divlinedashed, chartAttrs.divlineisdashed, 1)),
                divLineDashLen: pluckNumber(chartAttrs.divlinedashlen, 4),
                divLineDashGap: pluckNumber(chartAttrs.divlinedashgap, 2),
                showAlternateGridColor: pluckNumber(chartAttrs.showalternatehgridcolor, 1),
                alternateGridColor: pluck(chartAttrs.alternatehgridcolor, colorM.getColor(altHGridColorStr)),
                alternateGridAlpha: pluck(chartAttrs.alternatehgridalpha, colorM.getColor(altHGridAlphaStr)),
                numDivLines: pluckNumber(chartAttrs.numpdivlines, 5),
                axisMinValue: chartAttrs.pyaxisminvalue,
                axisMaxValue: chartAttrs.pyaxismaxvalue,
                setAdaptiveMin: pluckNumber(chartAttrs.setadaptiveymin, 1),
                adjustDiv: chartAttrs.adjustdiv,
                labelStep: chartAttrs.yaxisvaluesstep,
                showAxisValues: pluckNumber(chartAttrs.showyaxisvalues, chartAttrs.showyaxisvalue),
                showLimits: pluckNumber(chartAttrs.showyaxislimits, chartAttrs.showlimits, iapi.showLimits),
                showDivLineValues: pluckNumber(chartAttrs.showdivlinevalues, chartAttrs.showdivlinevalue),
                showZeroPlane: chartAttrs.showzeroplane,
                zeroPlaneColor: chartAttrs.zeroplanecolor,
                zeroPlaneThickness: chartAttrs.zeroplanethickness,
                zeroPlaneAlpha: chartAttrs.zeroplanealpha,
                showZeroPlaneValue: chartAttrs.showzeroplanevalue,
                trendlineColor: chartAttrs.trendlinecolor,
                trendlineToolText: chartAttrs.trendlinetooltext,
                trendlineThickness: chartAttrs.trendlinethickness,
                trendlineAlpha: chartAttrs.trendlinealpha,
                showTrendlinesOnTop: chartAttrs.showtrendlinesontop,
                showAxisLine: pluckNumber(chartAttrs.showyaxisline, chartAttrs.showaxislines,
                    chartAttrs.drawAxisLines, 0),
                axisLineThickness: pluckNumber(chartAttrs.yaxislinethickness, chartAttrs.axislinethickness, 1),
                axisLineAlpha: pluckNumber(chartAttrs.yaxislinealpha, chartAttrs.axislinealpha, 100),
                axisLineColor: pluck(chartAttrs.yaxislinecolor, chartAttrs.axislinecolor, COLOR_000000)
            };
            vYAxisConf = {
                outCanfontFamily: pluck(chartAttrs.outcnvbasefont, chartAttrs.basefont, defaultFontStr),
                outCanfontSize:  pluckFontSize(chartAttrs.outcnvbasefontsize, chartAttrs.basefontsize, 10),
                outCancolor: pluck(chartAttrs.outcnvbasefontcolor, chartAttrs.basefontcolor,
                    colorM.getColor(palleteString.baseFontColor)).replace(/^#?([a-f0-9]+)/ig, '#$1'),
                axisNamePadding: chartAttrs.yaxisnamepadding,
                axisValuePadding: chartAttrs.yaxisvaluespadding,
                axisNameFont: chartAttrs.vyaxisnamefont,
                axisNameFontSize: chartAttrs.vyaxisnamefontsize,
                axisNameFontColor: chartAttrs.vyaxisnamefontcolor,
                axisNameFontBold: chartAttrs.vyaxisnamefontbold,
                axisNameFontItalic: chartAttrs.vyaxisnamefontitalic,
                axisNameBgColor: chartAttrs.vyaxisnamebgcolor,
                axisNameBorderColor: chartAttrs.vyaxisnamebordercolor,
                axisNameAlpha: chartAttrs.vyaxisnamealpha,
                axisNameFontAlpha: chartAttrs.vyaxisnamefontalpha,
                axisNameBgAlpha: chartAttrs.vyaxisnamebgalpha,
                axisNameBorderAlpha: chartAttrs.vyaxisnameborderalpha,
                axisNameBorderPadding: chartAttrs.vyaxisnameborderpadding,
                axisNameBorderRadius: chartAttrs.vyaxisnameborderradius,
                axisNameBorderThickness: chartAttrs.vyaxisnameborderthickness,
                axisNameBorderDashed: chartAttrs.vyaxisnameborderdashed,
                axisNameBorderDashLen: chartAttrs.vyaxisnameborderdashlen,
                axisNameBorderDashGap: chartAttrs.vyaxisnameborderdashgap,
                axisNameWidth: chartAttrs.yaxisnamewidth,
                useEllipsesWhenOverflow: chartAttrs.useellipseswhenoverflow,
                rotateAxisName: pluckNumber(chartAttrs.rotateyaxisname, 1),
                axisName: chartAttrs.vyaxisname,
                divLineColor: pluck(chartAttrs.divlinecolor, colorM.getColor(palleteString.divLineColor)),
                divLineAlpha: pluck(chartAttrs.divlinealpha, colorM.getColor(divLineAlphaStr)),
                divLineThickness: pluckNumber(chartAttrs.divlinethickness, 1),
                divLineIsDashed: Boolean(pluckNumber(chartAttrs.divlinedashed, chartAttrs.divlineisdashed, 1)),
                divLineDashLen: pluckNumber(chartAttrs.divlinedashlen, 4),
                divLineDashGap: pluckNumber(chartAttrs.divlinedashgap, 2),
                showAlternateGridColor: pluckNumber(chartAttrs.showalternatehgridcolor, 1),
                alternateGridColor: pluck(chartAttrs.alternatehgridcolor, colorM.getColor(altHGridColorStr)),
                alternateGridAlpha: pluck(chartAttrs.alternatehgridalpha, colorM.getColor(altHGridAlphaStr)),
                numDivLines: chartAttrs.numdivlines,
                // @todo have to change the y axis max and min value afterwards when percentage axis is ready
                axisMinValue: chartAttrs.vyaxisminvalue,
                axisMaxValue: chartAttrs.vyaxismaxvalue,
                setAdaptiveMin: chartAttrs.setadaptiveymin,
                adjustDiv: chartAttrs.adjustdiv,
                labelStep: chartAttrs.yaxisvaluesstep,
                showAxisValues: pluckNumber(chartAttrs.showyaxisvalues, chartAttrs.showyaxisvalue),
                showLimits: pluckNumber(chartAttrs.showsecondarylimits, chartAttrs.showlimits),
                showDivLineValues: pluckNumber(chartAttrs.showdivlinevalues, chartAttrs.showdivlinevalue),
                showZeroPlane: chartAttrs.showzeroplane,
                zeroPlaneColor: chartAttrs.zeroplanecolor,
                zeroPlaneThickness: chartAttrs.zeroplanethickness,
                zeroPlaneAlpha: chartAttrs.zeroplanealpha,
                showZeroPlaneValue: chartAttrs.showzeroplanevalue,
                trendlineColor: chartAttrs.trendlinecolor,
                trendlineToolText: chartAttrs.trendlinetooltext,
                trendlineThickness: chartAttrs.trendlinethickness,
                trendlineAlpha: chartAttrs.trendlinealpha,
                showTrendlinesOnTop: chartAttrs.showtrendlinesontop,
                showAxisLine: pluckNumber(chartAttrs.showyaxisline, chartAttrs.showaxislines,
                    chartAttrs.drawAxisLines, 0),
                axisLineThickness: pluckNumber(chartAttrs.yaxislinethickness, chartAttrs.axislinethickness, 1),
                axisLineAlpha: pluckNumber(chartAttrs.yaxislinealpha, chartAttrs.axislinealpha, 100),
                axisLineColor: pluck(chartAttrs.yaxislinecolor, chartAttrs.axislinecolor, COLOR_000000)
            };
            xAxisConf.vtrendlines = dataObj.vtrendlines;
            vxAxisConf.vtrendlines = dataObj.vtrendlines;
            yAxisConf.trendlines = dataObj.trendlines;
            yAxis = components.yAxis[0];
            yAxis1 = components.yAxis[1];

            xAxis = components.xAxis[0];


            yAxis.setCommonConfigArr(yAxisConf, true, false, false);
            yAxis.configure();
            yAxis1.setCommonConfigArr(vYAxisConf, true, false, false);
            yAxis1.configure();
            yAxis.setAxisConfig({
                drawLabelsOpposit : 1,
                axisNameAlignCanvas : 1,
                relativeAxis : yAxis1
            });
            yAxis1.setAxisConfig({
                drawLabelsOpposit : 1,
                axisNameAlignCanvas : 1,
                uniqueClassName : 1,
                relativeAxis : yAxis
            });

            xAxis.setCommonConfigArr(xAxisConf, false, false, false);
            xAxis.configure();
            xAxis.setAxisConfig({
                drawTrendLabels: showVolumeChart ? false : true
            });
            if (showVolumeChart) {
                if (!components.xAxis[1]) {
                    vxAxis = components.xAxis[1] = new CartesianAxis();
                    vxAxis.chart = iapi;
                    vxAxis.init();
                } else {
                    components.xAxis[1].show();
                }
                vxAxis = components.xAxis[1];
                vxAxis.setCommonConfigArr(vxAxisConf, false, false, false);
                vxAxis.configure();
                vxAxis.setAxisConfig({
                    drawLabels : false,
                    drawPlotlines : true,
                    drawPlotBands : false,
                    drawAxisName : false,
                    drawTrendLines : true,
                    drawOnlyCategoryLine : true,
                    uniqueClassName : 1
                });
            } else {
                if (components.xAxis[1]) {
                    components.xAxis[1].hide();
                }
            }
        },
        _setCategories: function() {

            var iapi = this,
                components = iapi.components,
                dataObj = iapi.jsonData,
                xAxis = components.xAxis,
                categories = dataObj.categories && dataObj.categories[0].category || [],
                xAxisCatArr = [],
                catObj,
                i;
            for (i = 0; i < categories.length; i++) {
                catObj = extend2({}, categories[i]);
                catObj.label = BLANKSTRING;
                xAxisCatArr.push(catObj);
            }
            xAxis[0].setAxisPadding(0.5, 0.5);
            xAxis[0].setCategory(categories);
            xAxis[1] && xAxis[1].setAxisPadding(0.5, 0.5);
            xAxis[1] && xAxis[1].setCategory(xAxisCatArr);
        },
        _setAxisLimits: function () {
            var iapi = this,
                    components = iapi.components,
                    dataset = components.dataset,
                    yAxis = components.yAxis,
                    xAxis = components.xAxis,
                    currentDataset,
                    length = dataset.length,
                    i,
                    infMin = -Infinity,
                    infMax = +Infinity,
                    max = infMin,
                    min = infMax,
                    vMax = infMin,
                    vMin = infMax,
                    xMin = infMax,
                    xMax = infMin,
                    maxminObj,
                    groupManager,
                    trendMinMaxObj,
                    yAxisIndex = 0,
                    groupManagerObj = {},
                    getMaxMin = function (maxminObj) {
                        if (yAxisIndex === 1) {
                            vMax = mathMax(vMax, maxminObj.max);
                            vMin = mathMin(vMin, maxminObj.min);
                        }
                        else {
                            max = mathMax(max, maxminObj.max);
                            min = mathMin(min, maxminObj.min);
                        }

                        xMax = mathMax(xMax, maxminObj.xMax || infMin);
                        xMin = mathMin(xMin, maxminObj.xMin || infMax);

                    };

            for (i=0; i<length; i++) {
                currentDataset = dataset[i];
                groupManager = currentDataset.groupManager;
                yAxisIndex =  currentDataset.config.parentYAxis;
                if (groupManager) {
                    groupManagerObj[currentDataset.type] = groupManager;
                    groupManagerObj[currentDataset.type].yAxisIndex = yAxisIndex;
                }
                else {
                    maxminObj = currentDataset.getDataLimits();
                    getMaxMin(maxminObj);
                }
            }

            for (groupManager in groupManagerObj) {
                yAxisIndex = groupManagerObj[groupManager].yAxisIndex;
                maxminObj = groupManagerObj[groupManager].getDataLimits();
                max = mathMax(max, maxminObj.max);
                min = mathMin(min, maxminObj.min);
            }
            trendMinMaxObj = iapi._getTrendLineMinMax('h');
            max = mathMax (max, trendMinMaxObj.max);
            min = mathMin (min, trendMinMaxObj.min);
            yAxis[0].setDataLimit(max, min);
            yAxis[1].setDataLimit(vMax, vMin);
            if ((xMax !== infMin) || (xMin !== infMax)) {
                xAxis[0].setAxisRange({
                    min: xMin - 0.5,
                    max: xMax + 0.5,
                    tickInterval: 1
                });
                xAxis[1] && xAxis[1].setAxisRange({
                    min: xMin - 0.5,
                    max: xMax + 0.5,
                    tickInterval: 1
                });
                // xAxis[0].setDataLimit(xMax, xMin);
            }
        },
        isDual: true
    }, chartAPI.mscartesian, {
        enablemousetracking: true,
        iscandlestick: true
    });

}]);

FusionCharts.register('module', ['private', 'modules.renderer.js-kagi', function () {
    var global = this,
        lib = global.hcLib,
        chartAPI = lib.chartAPI,
        win = global.window,
        math = Math,
        mathMin = math.min,
        mathMax = math.max,
        pluck = lib.pluck,
        pluckNumber = lib.pluckNumber,
        toPrecision = lib.toPrecision,
        creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname);

    //The chartAPI for the kagi chart.
    //It is a single series chart hence ingerited from sscartesian(Single series chart).
    chartAPI('kagi', {
        standaloneInit: true,
        friendlyName: 'Kagi Chart',
        creditLabel: creditLabel,
        defaultDatasetType : 'kagi',
        applicableDSList: {
            'kagi': true
        },
        singleseries: true,
        hasLegend: false,
        _postSpaceManagement : function () {
            var iapi = this,
                config = iapi.config,
                components = iapi.components,
                xAxis = components.xAxis && components.xAxis[0],
                yAxis = components.yAxis && components.yAxis[0],
                canvasConfig = components.canvas.config,
                canvasBorderWidth = canvasConfig.canvasBorderWidth,
                canvasPadding = canvasConfig.canvasPadding || 15,
                canvasPaddingTop = canvasConfig.canvasPaddingTop,
                canvasPaddingBottom = canvasConfig.canvasPaddingBottom,
                chartAttrs = iapi.jsonData.chart,
                dataset = components.dataset,
                series = dataset[0].config,
                shiftCount = series && series.shiftCount,
                min = pluckNumber(xAxis.getAxisConfig('axisMinValue'), 0),
                max = pluckNumber(xAxis.getAxisConfig('axisMaxValue'), shiftCount - 1),
                canvasWidth = iapi.config.canvasWidth,
                //plot area will not be less then 10 px
                leftPixelPad = mathMin(pluckNumber(chartAttrs.canvaspadding, 0), (canvasWidth / 2) - 10),
                rightPixelPad = leftPixelPad,
                // The maximum horizontal shift in percentage of the
                // available canvas width
                maxHShiftPercent = pluckNumber(chartAttrs.maxhshiftpercent, 10),
                effectiveCanvasWidth = canvasWidth - canvasPadding * 2,
                xShiftLength;

            yAxis && yAxis.setAxisDimention ( {
                x : config.canvasLeft - canvasBorderWidth,
                y : config.canvasTop + canvasPaddingTop,
                opposite : config.canvasRight + canvasBorderWidth,
                axisLength : config.canvasHeight - canvasPaddingTop - canvasPaddingBottom
            });

            iapi._setPosition();
            if (series) {
                // maxHShiftPercent can not be < 0
                maxHShiftPercent = maxHShiftPercent <= 0 ?
                    10 : maxHShiftPercent;
                xShiftLength = series.xShiftLength =
                    mathMin(effectiveCanvasWidth / shiftCount,
                        maxHShiftPercent * effectiveCanvasWidth / 100);
                leftPixelPad = canvasPadding + xShiftLength / 2;
                rightPixelPad = canvasWidth - ((xShiftLength *
                    // handling single value rendering issue in Kagi
                    mathMax((shiftCount - 1), 1)) + leftPixelPad);
                // Fix for Kagi chart single value rendering issue
                // If there is a single value, we use xAxis max value
                // as 1 not as 0
                max = mathMax(max, 1);
            }

            // function for adjusting value padding depending upon data and axis labels.
            iapi._adjustCanvasPadding();
            xAxis && xAxis.setAxisDimention ( {
                x: iapi.config.canvasLeft + canvasPadding + (xShiftLength/2),
                axisLength: xShiftLength * (max - min),
                y : config.canvasBottom + (config.shift || 0) + canvasBorderWidth,
                opposite : config.canvasTop - canvasBorderWidth
            });
        },
        _setPosition: function () {
            var i,
                point,
                yValue,
                config,
                isRally,
                lastHigh,
                lastLow,
                isRallyInitialised,
                lastPoint,
                iapi = this,
                components = iapi.components,
                dataObj = iapi.jsonData,
                dataSet = components.dataset[0],
                categories = dataObj.data || (dataSet && dataSet[0] && dataSet[0].data),
                setDataArr = dataSet.components.data,
                dataSetLen = setDataArr && setDataArr.length,
                yAxis = components.yAxis[0],
                xValue = 0,
                plotX = xValue,
                catArr = [];
            //create plot elements
            for (i=0; i<dataSetLen; i++) {

                point = setDataArr[i].config;
                yValue = point.setValue;

                dataObj = setDataArr[i];
                config = dataObj.config;

                // Creating the data object if not created
                if (!dataObj) {
                    dataObj = setDataArr[i] = {
                        graphics : {}
                    };
                }
                if (!point.isDefined) {
                    yValue = point.plotValue;
                }

                // Getting appropiate value for the current plot point.
                yValue = pluck(point.plotValue, yValue);

                // Set the y position.
                point.plotY = toPrecision(yAxis.getAxisPosition(point.setValue), 2);

                // Store value textbox y position.
                point.graphY = toPrecision(yAxis.getAxisPosition(yValue), 2);

                // Abscissa of the point on the kagi line.
                point.plotX = plotX;
                // If there is a horizontal shift, then abscissa of the kagi
                // line and as such all points on it shifts to the right by a
                // slab more.
                if (point.isShift) {
                    xValue += 1;
                    plotX = xValue;
                    categories && catArr.push(categories[i]);
                }
                else if (i === (dataSetLen - 1)){
                    categories && catArr.push(categories[i]);
                }

                if (i) {
                    lastPoint = setDataArr[i - 1].config;

                    // Getting the previously bundled up properties in local
                    // variables.
                    isRally = point && point.objParams && point.objParams.isRally;
                    lastHigh = point && point.objParams && point.objParams.lastHigh;
                    lastLow = point && point.objParams && point.objParams.lastLow;
                    isRallyInitialised = point && point.objParams &&
                        point.objParams.isRallyInitialised;

                    // To find if there is a change in trend towards the current
                    // plot.
                    if (lastPoint && isRallyInitialised &&
                        lastPoint.isRally !== point.isRally) {

                        // Setting in this.data for the plot, to be used for.
                        // Setting the color/thickness the graph segments.
                        point.isChanged = true;

                        // To get the pixel position of the transtion point and
                        // storing in data point for the plot.
                        point.ty = toPrecision(yAxis.getAxisPosition((isRally ?
                            lastHigh : lastLow)), 2);
                    } else {
                        // Setting in this.data for the plot.
                        point.isChanged = false;
                    }
                }
            }
            //end of previous translation
        },
        _setAxisLimits : function () {
            var iapi = this,
                components = iapi.components,
                dataset = components.dataset,
                yAxis = components.yAxis,
                xAxis = components.xAxis,
                currentDataset,
                length = dataset.length,
                i,
                infMin = -Infinity,
                infMax = +Infinity,
                max = infMin,
                min = infMax,
                xMin = infMax,
                xMax = infMin,
                maxminObj,
                groupManager,
                groupManagerObj = { },
                noManager = [],
                getMaxMin = function (maxminObj) {
                    max = mathMax (max, maxminObj.max);
                    min = mathMin (min, maxminObj.min);
                    xMax = mathMax (xMax, maxminObj.xMax || infMin);
                    xMin = mathMin (xMin, maxminObj.xMin || infMax);

                };

            for (i=0; i<length; i++) {
                currentDataset = dataset[i];
                groupManager = currentDataset.groupManager;
                if (groupManager) {
                    groupManagerObj[currentDataset.type] = groupManager;
                }
                else {
                    noManager.push (currentDataset);
                }
            }

            for (groupManager in groupManagerObj) {
                maxminObj = groupManagerObj[groupManager].getDataLimits ();
                getMaxMin (maxminObj);
            }

            length =noManager.length;
            for (i=0; i<length; i++) {
                maxminObj = noManager[i].getDataLimits ();
                getMaxMin (maxminObj);
            }
            getMaxMin(iapi._getTrendLineMinMax('h'));
            (max === -Infinity) && (max = 0);
            (min === +Infinity) && (min = 0);
            iapi.config.yMax = max;
            iapi.config.yMin = min;
            yAxis[0].setAxisConfig({
                setAdaptiveMin: true
            });
            yAxis[0].setDataLimit (max, min);
            if ((xMax !== infMin) || (xMin !== infMax)) {
                xAxis[0].config.xaxisrange = {
                    max : xMax,
                    min : xMin
                };
                xAxis[0].setDataLimit (xMax, xMin);
            }
        }
    }, chartAPI.waterfall2d, {
        enablemousetracking: true
    }, chartAPI.areabase);
}]);

FusionCharts.register('module', ['private', 'modules.renderer.js-boxandwhisker2d', function () {
    var global = this,
        lib = global.hcLib,
        chartAPI = lib.chartAPI,
        win = global.window,
        pluck = lib.pluck,
        parseUnsafeString = lib.parseUnsafeString,
        BLANK = lib.BLANKSTRING,
        BLANKSTRING = lib.BLANKSTRING,
        preDefStr = lib.preDefStr,
        sStr = preDefStr.sStr,
        componentDispose = lib.componentDispose,
        HUNDREDSTRING = lib.HUNDREDSTRING,
        COMPONENT = 'component',
        DATASET = 'dataset',
        DATASET_GROUP = 'datasetGroup',
        UNDEFINED,
        BoxAndWhiskerStatisticalCalc,
        setAttribDefs = lib.setAttribDefs,
        attrTypeNum = lib.attrTypeNum,
        creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname),
        math = Math,
        mathRound = math.round,
        mathAbs = math.abs,
        mathCeil = math.ceil,
        mathFloor = math.floor,
        mathSqrt = math.sqrt,
        mathPow = math.pow,
        defined = function(obj) {
            return obj !== UNDEFINED && obj !== null;
        };

    // boxAndWhisker statistical Methods
    lib.BoxAndWhiskerStatisticalCalc =
        BoxAndWhiskerStatisticalCalc = function(method, numberFormatter, dataSeparator) {
            this.nf = numberFormatter;
            this.dataSeparator = dataSeparator;
            this.method = (method || BLANK).toLowerCase().replace(/\s/g, BLANKSTRING);
        };

    BoxAndWhiskerStatisticalCalc.prototype = {
        setArray: function(value) {
            var nf = this.nf,
                dataSeparator = this.dataSeparator,
                sum = 0,
                len,
                dataArr;
            !value && (value = BLANK);
            // First we make an arry form the comma-separated value.
            // and then we sort and store the data array in dataArr
            //  for further calculation.
            dataArr = value.replace(/\s/g, BLANK).split(dataSeparator);
            // Parse the values using NumberFormatter getCleanValue
            len = this.dataLength = dataArr && dataArr.length;

            while (len--) {
                sum += dataArr[len] = nf.getCleanValue(dataArr[len]);
            }

            // Now sort the data in ascending order
            dataArr && dataArr.sort(function(a, b) {
                return a - b;
            });

            this.values = dataArr;
            // Calculate and store the Mean
            this.mean = sum / this.dataLength;
            this.getFrequencies();
        },

        getQuartiles: function() {
            var values = this.values,
                len = this.dataLength,
                isOdd = len % 2,
                q1Pos,
                q1LowPos,
                q3Pos,
                q3LowPos,
                q1Val,
                q3Val;

            switch (this.method) {
            case 'tukey':
                if (isOdd) {
                    // Q1 = n + 3 / 4 And Q3 = 3N + 1 / 4
                    q1Pos = (len + 3) / 4;
                    q3Pos = ((len * 3) + 1) / 4;
                } else {
                    // Q1 = n + 2 / 4 And Q3 = 3N + 2 / 4
                    q1Pos = (len + 2) / 4;
                    q3Pos = ((len * 3) + 2) / 4;
                }
                break;
            case 'mooremccabe':
                if (isOdd) {
                    // Q1 = n + 1 / 4 And Q3 = 3N + 3 / 4
                    q1Pos = (len + 1) / 4;
                    q3Pos = q1Pos * 3;
                } else {
                    // Q1 = n + 2 / 4 And Q3 = 3N + 2 / 4
                    q1Pos = (len + 2) / 4;
                    q3Pos = ((len * 3) + 2) / 4;
                }
                break;
            case 'freundperles':
                // Q1 = n + 3 / 4 And Q3 = 3N + 1 / 4
                q1Pos = (len + 3) / 4;
                q3Pos = ((len * 3) + 1) / 4;
                break;
            case 'mendenhallsincich':
                // Q1 = [n + 1 / 4] And [Q3 = 3N + 3 / 4]
                q1Pos = mathRound((len + 1) / 4);
                q3Pos = mathRound(q1Pos * 3);
                break;
            default:
                // Q1 = n + 1 / 4 And Q3 = 3N + 3 / 4
                q1Pos = (len + 1) / 4;
                q3Pos = q1Pos * 3;
                break;
            }

            q1Pos -= 1;
            q3Pos -= 1;
            q1LowPos = mathFloor(q1Pos);
            q3LowPos = mathFloor(q3Pos);

            q1Val = q1Pos - q1LowPos ? values[q1LowPos] +
                ((values[mathCeil(q1Pos)] - values[q1LowPos]) *
                (q1Pos - q1LowPos)) : values[q1Pos];
            q3Val = q3Pos - q3LowPos ? values[q3LowPos] +
                ((values[mathCeil(q3Pos)] - values[q3LowPos]) *
                (q3Pos - q3LowPos)) : values[q3Pos];

            return this.quartiles = {
                q1: q1Val,
                q3: q3Val
            };
        },

        // return min and max values from the data array.
        getMinMax: function() {
            var values = this.values;
            return {
                min: values[0],
                max: values[this.dataLength - 1]
            };
        },

        // calculate and returns the mean value
        getMean: function() {
            return this.mean;
        },

        // calculate the MeanDeviation
        getMD: function() {
            var mean = this.mean,
                freq = this.frequencies,
                freqLen = freq.length,
                freqObj,
                sum = 0;

            while (freqLen--) {
                freqObj = freq[freqLen];
                sum += freqObj.frequency * mathAbs(freqObj.value - mean);
            }
            return sum / this.dataLength;
        },

        // calculate the standard deviation
        getSD: function() {
            var mean = this.mean,
                values = this.values,
                i = this.dataLength,
                len = i,
                sum = 0;

            while (i--) {
                sum += mathPow(values[i] - mean, 2);
            }

            return mathSqrt(sum) / len;
        },

        // calculate the quartile deviation
        getQD: function() {
            return (this.quartiles.q3 - this.quartiles.q1) * 0.5;
        },

        // calculate the frequencies and sum of the values
        getFrequencies: function() {
            var frequenciesArr = [],
                len = this.dataLength,
                values = this.values,
                sum = 0,
                value,
                freqObj,
                index;

            for (index = 0; index < len; index += 1) {
                sum += value = values[index];
                if (defined(frequenciesArr[index])) {
                    frequenciesArr[index].frequency += 1;
                } else {
                    freqObj = {};
                    freqObj.value = value;
                    freqObj.frequency = 1;
                    frequenciesArr[index] = freqObj;
                }
            }
            this.sum = sum;
            this.frequencies = frequenciesArr;
        },

        getMedian: function() {
            var len = this.dataLength,
                midVal = len * 0.5,
                values = this.values;

            return len % 2 === 0 ? (values[midVal] + values[midVal - 1]) / 2 :
                values[mathFloor(midVal)];
        }
    };

    BoxAndWhiskerStatisticalCalc.prototype.constructor = BoxAndWhiskerStatisticalCalc;

    /******************************************************************************
     * Raphael Renderer Extension
     ******************************************************************************/

    setAttribDefs && setAttribDefs({
        whiskerslimitswidthratio: {
            type: attrTypeNum,
            pAttr: 'whiskerslimitswidthratio'
        },
        outliersupperrangeratio: {
            type: attrTypeNum,
            pAttr: 'outliersupperrangeratio'
        },
        outlierslowerrangeratio: {
            type: attrTypeNum,
            pAttr: 'outlierslowerrangeratio'
        },
        showalloutliers: {
            type: attrTypeNum,
            pAttr: 'showalloutliers'
        },
        showmean: {
            type: attrTypeNum,
            pAttr: 'showmean'
        },
        showsd: {
            type: attrTypeNum,
            pAttr: 'showsd'
        },
        showmd: {
            type: attrTypeNum,
            pAttr: 'showmd'
        },
        showqd: {
            type: attrTypeNum,
            pAttr: 'showqd'
        },
        showminvalues: {
            type: attrTypeNum,
            pAttr: 'showminvalues'
        },
        showmaxvalues: {
            type: attrTypeNum,
            pAttr: 'showmaxvalues'
        },
        showq1values: {
            type: attrTypeNum,
            pAttr: 'showq1values'
        },
        showq3values: {
            type: attrTypeNum,
            pAttr: 'showq3values'
        },
        showmedianvalues: {
            type: attrTypeNum,
            pAttr: 'showmedianvalues'
        }
    });

    chartAPI('boxandwhisker2d', {
        friendlyName: 'Box and Whisker Chart',
        standaloneInit: true,
        creditLabel: creditLabel,
        chart: chartAPI.errorbar2d.chart,
        drawErrorValue: chartAPI.errorbar2d.drawErrorValue,
        decimals: 2,
        maxColWidth: +Infinity,
        useErrorAnimation: 1,
        avoidCrispError: 0,
        tooltipsepchar: ': ',
        defaultDatasetType: 'boxandwhisker2d',
        applicableDSList: {'boxandwhisker2d': true},
        hasSubDataset: true,
        fireGroupEvent: true,
        fireInitialAnimation: true,
        drawTracker: true,
        _drawDataset : function () {
            var iapi = this,
                dataset = iapi.components.dataset,
                currentDataset,
                length = dataset.length,
                i,
                j,
                len,
                groupManager,
                groupManagerObj = {};

            for (i=0; i<length; i++) {
                currentDataset = dataset[i];
                groupManager = currentDataset.groupManager;
                groupManagerObj[currentDataset.type] = groupManager;
            }

            for (groupManager in groupManagerObj) {
                groupManagerObj[groupManager].draw();
            }

            dataset.flag = true;

            for (i=0; i<length; i++) {
                dataset[i].components.mean && dataset[i].components.mean.draw();
                dataset[i].components.sd && dataset[i].components.sd.draw();
                dataset[i].components.md && dataset[i].components.md.draw();
                dataset[i].components.qd && dataset[i].components.qd.draw();

                len = dataset[i].config.maxNumberOfOutliers || dataset[i].components.outliers.length;

                for (j = 0; j < len; j++) {

                    if (!dataset[i].config.showOutliersLegend) {
                        dataset[i].components.outliers[j].visible = false;
                    }
                    // else {
                    //     outliersVisible = dataset[i].components.outliers.visible;
                    //     dataset[i].components.outliers[j].visible =
                    //         (outliersVisible === UNDEFINED || outliersVisible) ? true : false;
                    // }
                    dataset[i].components.outliers && dataset[i].components.outliers[j].draw();
                }
            }
        },
        _createDatasets : function () {
            var iapi = this,
                components = iapi.components,
                xAxis = components.xAxis[0],
                dataObj = iapi.jsonData,
                dataset = dataObj.dataset,
                length = dataset && dataset.length,
                i,
                j,
                datasetStore,
                datasetStoreLen,
                datasetObj,
                defaultSeriesType = iapi.defaultDatasetType,
                applicableDSList = iapi.applicableDSList,
                legend = iapi.components.legend,
                legendItems = legend.components.items || [],
                GroupManager,
                dsType,
                DsClass,
                DsGroupClass,
                datasetJSON,
                isStacked = iapi.isStacked,
                groupManagerName,
                parentyaxis,
                prevData,
                prevDataLength,
                currDataLength,
                groupManagers = [],
                isRealTime = iapi.isRealTime,
                diff,
                catLen = iapi.config.catLen,
                currCatLen,
                DataDiff,
                catDiff,
                startIndex,
                dsCount = { };

            if (!dataset) {
                iapi.setChartMessage();
            }

            iapi.config.categories = dataObj.categories && dataObj.categories[0].category;

            datasetStore = components.dataset  || (components.dataset = []);
            datasetStoreLen = datasetStore.length;

            legend.emptyItems(0, legendItems.length);

            for (i=0; i<length; i++) {
                datasetJSON = dataset[i];

                datasetJSON.seriesname &&  (datasetJSON.seriesname = parseUnsafeString(datasetJSON.seriesname));

                parentyaxis = datasetJSON.parentyaxis || BLANKSTRING;
                if (iapi.isDual && parentyaxis.toLowerCase () === sStr) {
                    dsType = pluck (datasetJSON.renderas, iapi.sDefaultDatasetType);
                }
                else {
                    dsType = pluck (datasetJSON.renderas, defaultSeriesType);
                }
                dsType = dsType && dsType.toLowerCase ();
                if (!applicableDSList[dsType]) {
                    dsType = defaultSeriesType;
                }

                /// get the DsClass
                DsClass = FusionCharts.get(COMPONENT, [DATASET, dsType]);
                if (DsClass) {
                    if (dsCount[dsType] === UNDEFINED) {
                        dsCount[dsType] = 0;
                    }
                    else {
                        dsCount[dsType]++;
                    }
                    groupManagerName = 'datasetGroup_' + dsType;
                    // get the ds group class
                    DsGroupClass = FusionCharts.register(COMPONENT, [DATASET_GROUP, dsType]);
                    GroupManager = components[groupManagerName];
                    GroupManager && groupManagers.push(GroupManager);
                    if (DsGroupClass && !GroupManager) {
                        GroupManager = components[groupManagerName] = new DsGroupClass ();
                        GroupManager.chart = iapi;
                        GroupManager.init ();
                    }

                    // If the dataset does not exists.
                    if (!(datasetObj = datasetStore[i])) {
                        // create the dataset Object
                        datasetObj = new DsClass ();
                        datasetStore.push (datasetObj);
                        datasetObj.chart = iapi;
                        datasetObj.index = i;
                        // add to group manager
                        GroupManager && (isStacked ? GroupManager.addDataSet (datasetObj, 0, dsCount[dsType]) :
                            GroupManager.addDataSet (datasetObj, dsCount[dsType], 0));
                        datasetObj.init (datasetJSON);
                    }
                    // If the dataset exists incase the chart is updated using setChartData() method.
                    else {
                        currCatLen = xAxis.getCategoryLen();
                        catDiff = catLen - currCatLen;

                        prevData = isRealTime ?  datasetObj.components : datasetObj.JSONData;
                        prevDataLength = (prevData.data && prevData.data.length) || 0;
                        currDataLength = (datasetJSON.data && datasetJSON.data.length) || 0;

                        DataDiff = prevDataLength - currDataLength;

                        if (catDiff > DataDiff) {
                            diff = catDiff;
                            startIndex = currCatLen;
                        }
                        else {
                            diff = DataDiff;
                            startIndex = currDataLength;
                        }
                        // Removing data plots if the number of current data plots is more than the existing ones.
                        if (diff > 0) {
                            datasetObj.removeData(startIndex, diff, false);
                        }
                        datasetStore[i].JSONData = datasetJSON;
                        datasetStore[i].configure();
                        datasetStore[i]._deleteGridImages && datasetStore[i]._deleteGridImages();
                    }
                }
            }

            // When the number of datasets entered vis setChartData is less than the existing dataset
            // then dispose the extra datasets.
            if (datasetStoreLen > length) {
                diff = datasetStoreLen - length;
                GroupManager && isStacked && GroupManager.removeDataSet(0, i, diff);

                for (j = i, length = diff + i; j < length; j ++ ) {
                    GroupManager && !isStacked && GroupManager.removeDataSet(i, 0, 1);
                    legend.removeItem(datasetStore[j].legendItemId);
                    componentDispose.call(datasetStore[j]);
                }
                datasetStore.splice(i, diff);
            }
            iapi.config.catLen = xAxis.getCategoryLen();
        }

    }, chartAPI.mscartesian, {
        showplotborder: 1,
        plotborderdashlen: 5,
        plotborderdashgap: 4,
        plotfillalpha: HUNDREDSTRING,
        useroundedges: 0,
        plotborderthickness: 1,
        showvalues: 1,
        valuepadding: 2,
        showtooltip: 1,
        maxcolwidth: 50,
        rotatevalues: 0,
        use3dlighting: 1,
        whiskerslimitswidthratio: 40,
        outliersupperrangeratio: 0,
        outlierslowerrangeratio: 0,
        showalloutliers: 0,
        showmean: 0,
        showsd: 0,
        showmd: 0,
        showqd: 0,
        showminvalues: 1,
        showmaxvalues: 1,
        showq1values: 0,
        showq3values: 0,
        showmedianvalues: 1
    });
}]);

FusionCharts.register('module', ['private', 'modules.renderer.js-heatmap', function () {
    var global = this,
        lib = global.hcLib,
        chartAPI = lib.chartAPI,
        win = global.window,
        COMPONENT = 'component',
        AXIS = 'axis',
        pluckFontSize = lib.pluckFontSize,
        pluck = lib.pluck,
        pluckNumber = lib.pluckNumber,
        preDefStr = lib.preDefStr,
        defaultFontStr = preDefStr.defaultFontStr,
        divLineAlpha3DStr = preDefStr.divLineAlpha3DStr,
        divLineAlphaStr = preDefStr.divLineAlphaStr,
        altVGridColorStr = preDefStr.altVGridColorStr,
        altVGridAlphaStr = preDefStr.altVGridAlphaStr,
        altHGridColorStr = preDefStr.altHGridColorStr,
        altHGridAlphaStr = preDefStr.altHGridAlphaStr,
        colorStrings = preDefStr.colors,
        COLOR_000000 = colorStrings.c000000,
        UNDEFINED,
        creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname);

    chartAPI('heatmap', {
        friendlyName: 'Heatmap Chart',
        standaloneInit: true,
        creditLabel: creditLabel,
        //defaultSeriesType: 'heatmap',
        hasLegend: true,
        tooltipsepchar: ': ',
        tooltipConstraint: 'chart',
        defaultDatasetType : 'heatmap',
        applicableDSList: {'heatmap': true},
        isSingleSeries: true,
        hasGradientLegend: true,
        _createAxes : function() {
            var iapi = this,
                components = iapi.components,
                CartesianAxis = FusionCharts.register(COMPONENT, [AXIS, 'cartesian']),
                yAxis,
                xAxis;


            components.yAxis = [];
            components.xAxis = [];
            components.yAxis[0] = yAxis = new CartesianAxis();
            components.xAxis[0] = xAxis = new CartesianAxis();
            yAxis.chart = iapi;
            xAxis.chart = iapi;

            yAxis.init();
            xAxis.init();

        },

        _postSpaceManagement : function () {
            var iapi = this,
                config = iapi.config,
                placeAxisLabelsOnTop = config.placeAxisLabelsOnTop,
                components = iapi.components,
                xAxis = components.xAxis && components.xAxis[0],
                yAxis = components.yAxis && components.yAxis[0],
                legend = components.legend,
                xDepth = config.xDepth,
                canvasConfig = components.canvas.config,
                canvasBorderWidth = canvasConfig.canvasBorderWidth;

            xAxis && xAxis.setAxisDimention ( {
                x : config.canvasLeft,
                y : placeAxisLabelsOnTop ? (config.canvasTop + (config.shift || 0) - canvasBorderWidth) :
                    (config.canvasBottom + (config.shift || 0) + canvasBorderWidth),
                opposite : config.canvasTop - canvasBorderWidth,
                axisLength : config.canvasWidth
            });
            yAxis && yAxis.setAxisDimention ( {
                x : config.canvasLeft - canvasBorderWidth,
                y : config.canvasTop,
                opposite : config.canvasRight + canvasBorderWidth,
                axisLength : config.canvasHeight
            });

            xAxis && xAxis.shiftLabels (-xDepth, 0);
            legend.postSpaceManager();
            // Setting the number of columns to be displayed based on numdisplaysets.
            iapi.config.realtimeEnabled && iapi._setRealTimeCategories && iapi._setRealTimeCategories ();
            // function for adjusting value padding depending upon data and axis labels.
            iapi._adjustCanvasPadding();
        },

        _adjustCanvasPadding : function () {
        },

        _feedAxesRawData : function() {
            var iapi = this,
                components = iapi.components,
                colorM = components.colorManager,
                dataObj = iapi.jsonData,
                chartAttrs = dataObj.chart,
                xAxisConf,
                yAxisConf,
                is3d = iapi.is3d,
                chartPaletteStr = lib.chartPaletteStr,
                palleteString = is3d ? chartPaletteStr.chart3D : chartPaletteStr.chart2D,
                yAxis,
                xAxis;


            xAxisConf = {
                outCanfontFamily: pluck(chartAttrs.outcnvbasefont, chartAttrs.basefont, defaultFontStr),
                outCanfontSize:  pluckFontSize(chartAttrs.outcnvbasefontsize, chartAttrs.basefontsize, 10),
                outCancolor: pluck(chartAttrs.outcnvbasefontcolor, chartAttrs.basefontcolor,
                    colorM.getColor(palleteString.baseFontColor)).replace(/^#?([a-f0-9]+)/ig, '#$1'),
                axisNamePadding: chartAttrs.xaxisnamepadding,
                axisValuePadding: chartAttrs.labelpadding,
                axisNameFont: chartAttrs.xaxisnamefont,
                axisNameFontSize: chartAttrs.xaxisnamefontsize,
                axisNameFontColor: chartAttrs.xaxisnamefontcolor,
                axisNameFontBold: chartAttrs.xaxisnamefontbold,
                axisNameFontItalic: chartAttrs.xaxisnamefontitalic,
                axisNameBgColor: chartAttrs.xaxisnamebgcolor,
                axisNameBorderColor: chartAttrs.xaxisnamebordercolor,
                axisNameAlpha: chartAttrs.xaxisnamealpha,
                axisNameFontAlpha: chartAttrs.xaxisnamefontalpha,
                axisNameBgAlpha: chartAttrs.xaxisnamebgalpha,
                axisNameBorderAlpha: chartAttrs.xaxisnameborderalpha,
                axisNameBorderPadding: chartAttrs.xaxisnameborderpadding,
                axisNameBorderRadius: chartAttrs.xaxisnameborderradius,
                axisNameBorderThickness: chartAttrs.xaxisnameborderthickness,
                axisNameBorderDashed: chartAttrs.xaxisnameborderdashed,
                axisNameBorderDashLen: chartAttrs.xaxisnameborderdashlen,
                axisNameBorderDashGap: chartAttrs.xaxisnameborderdashgap,
                useEllipsesWhenOverflow: chartAttrs.useellipseswhenoverflow,
                divLineColor: pluck (chartAttrs.vdivlinecolor, chartAttrs.divlinecolor,
                    colorM.getColor (palleteString.divLineColor)),
                divLineAlpha: pluck (chartAttrs.vdivlinealpha, chartAttrs.divlinealpha,
                    is3d ? colorM.getColor(divLineAlpha3DStr) : colorM.getColor (divLineAlphaStr)),
                divLineThickness: pluckNumber (chartAttrs.vdivlinethickness, chartAttrs.divlinethickness, 1),
                divLineIsDashed: Boolean (pluckNumber (chartAttrs.vdivlinedashed, chartAttrs.vdivlineisdashed,
                    chartAttrs.divlinedashed, chartAttrs.divlineisdashed, 0)),
                divLineDashLen: pluckNumber (chartAttrs.vdivlinedashlen, chartAttrs.divlinedashlen, 4),
                divLineDashGap: pluckNumber (chartAttrs.vdivlinedashgap, chartAttrs.divlinedashgap, 2),
                showAlternateGridColor: pluckNumber(chartAttrs.showalternatevgridcolor, 0),
                alternateGridColor: pluck(chartAttrs.alternatevgridcolor, colorM.getColor(altVGridColorStr)),
                alternateGridAlpha: pluck(chartAttrs.alternatevgridalpha, colorM.getColor(altVGridAlphaStr)),
                numDivLines: chartAttrs.numvdivlines,
                labelFont: chartAttrs.labelfont,
                labelFontSize: chartAttrs.labelfontsize,
                labelFontColor: chartAttrs.labelfontcolor,
                labelFontAlpha: chartAttrs.labelalpha,
                labelFontBold : chartAttrs.labelfontbold,
                labelFontItalic : chartAttrs.labelfontitalic,
                axisName: chartAttrs.xaxisname,
                axisMinValue: chartAttrs.xaxisminvalue,
                axisMaxValue: chartAttrs.xaxismaxvalue,
                setAdaptiveMin: chartAttrs.setadaptivexmin,
                adjustDiv: chartAttrs.adjustvdiv,
                labelDisplay: chartAttrs.labeldisplay,
                showLabels: pluckNumber(chartAttrs.showxaxislabels, chartAttrs.showlabels),
                rotateLabels: chartAttrs.rotatexaxislabels,
                slantLabel: pluckNumber(chartAttrs.slantlabels, chartAttrs.slantlabel),
                labelStep: pluckNumber(chartAttrs.labelstep, chartAttrs.xaxisvaluesstep),
                showAxisValues: pluckNumber(chartAttrs.showxaxisvalues,  chartAttrs.showxaxisvalue),
                maxLabelHeight : chartAttrs.maxlabelheight,
                // showLimits: chartAttrs.showvlimits,
                // showDivLineValues: pluckNumber(chartAttrs.showvdivlinevalues, chartAttrs.showvdivlinevalues),
                showZeroPlane: chartAttrs.showvzeroplane,
                zeroPlaneColor: chartAttrs.vzeroplanecolor,
                zeroPlaneThickness: chartAttrs.vzeroplanethickness,
                zeroPlaneAlpha: chartAttrs.vzeroplanealpha,
                showZeroPlaneValue: chartAttrs.showvzeroplanevalue,
                trendlineColor: chartAttrs.trendlinecolor,
                trendlineToolText: chartAttrs.trendlinetooltext,
                trendlineThickness: chartAttrs.trendlinethickness,
                trendlineAlpha: chartAttrs.trendlinealpha,
                showTrendlinesOnTop: chartAttrs.showtrendlinesontop,
                showAxisLine: pluckNumber(chartAttrs.showxaxisline, chartAttrs.showaxislines,
                    chartAttrs.drawAxisLines, 0),
                axisLineThickness: pluckNumber(chartAttrs.xaxislinethickness, chartAttrs.axislinethickness, 1),
                axisLineAlpha: pluckNumber(chartAttrs.xaxislinealpha, chartAttrs.axislinealpha, 100),
                axisLineColor: pluck(chartAttrs.xaxislinecolor, chartAttrs.axislinecolor, COLOR_000000)
            };
            yAxisConf = {
                outCanfontFamily: pluck(chartAttrs.outcnvbasefont, chartAttrs.basefont, defaultFontStr),
                outCanfontSize:  pluckFontSize(chartAttrs.outcnvbasefontsize, chartAttrs.basefontsize, 10),
                outCancolor: pluck(chartAttrs.outcnvbasefontcolor, chartAttrs.basefontcolor,
                    colorM.getColor(palleteString.baseFontColor)).replace(/^#?([a-f0-9]+)/ig, '#$1'),
                axisNamePadding: chartAttrs.yaxisnamepadding,
                axisValuePadding: chartAttrs.yaxisvaluespadding,
                axisNameFont: chartAttrs.yaxisnamefont,
                axisNameFontSize: chartAttrs.yaxisnamefontsize,
                axisNameFontColor: chartAttrs.yaxisnamefontcolor,
                axisNameFontBold: chartAttrs.yaxisnamefontbold,
                axisNameFontItalic: chartAttrs.yaxisnamefontitalic,
                axisNameBgColor: chartAttrs.yaxisnamebgcolor,
                axisNameBorderColor: chartAttrs.yaxisnamebordercolor,
                axisNameAlpha: chartAttrs.yaxisnamealpha,
                axisNameFontAlpha: chartAttrs.yaxisnamefontalpha,
                axisNameBgAlpha: chartAttrs.yaxisnamebgalpha,
                axisNameBorderAlpha: chartAttrs.yaxisnameborderalpha,
                axisNameBorderPadding: chartAttrs.yaxisnameborderpadding,
                axisNameBorderRadius: chartAttrs.yaxisnameborderradius,
                axisNameBorderThickness: chartAttrs.yaxisnameborderthickness,
                axisNameBorderDashed: chartAttrs.yaxisnameborderdashed,
                axisNameBorderDashLen: chartAttrs.yaxisnameborderdashlen,
                axisNameBorderDashGap: chartAttrs.yaxisnameborderdashgap,
                axisNameWidth: chartAttrs.yaxisnamewidth,
                useEllipsesWhenOverflow: chartAttrs.useellipseswhenoverflow,
                rotateAxisName: pluckNumber(chartAttrs.rotateyaxisname, 1),
                axisName: chartAttrs.yaxisname,
                showAlternateGridColor: pluckNumber(chartAttrs.showalternatehgridcolor, 1),
                alternateGridColor: pluck(chartAttrs.alternatehgridcolor, colorM.getColor(altHGridColorStr)),
                alternateGridAlpha: pluck(chartAttrs.alternatehgridalpha, colorM.getColor(altHGridAlphaStr)),
                numDivLines: chartAttrs.numdivlines,
                axisMinValue: chartAttrs.yaxisminvalue,
                axisMaxValue: chartAttrs.yaxismaxvalue,
                setAdaptiveMin: chartAttrs.setadaptiveymin,
                adjustDiv: chartAttrs.adjustdiv,
                labelStep: chartAttrs.yaxisvaluesstep,
                showLabels: pluckNumber(chartAttrs.showyaxislabels, chartAttrs.showlabels),
                maxLabelWidthPercent : chartAttrs.maxlabelwidthpercent,
                showAxisValues: pluckNumber(chartAttrs.showyaxisvalues, chartAttrs.showyaxisvalue),
                divLineColor: pluck(chartAttrs.hdivlinecolor, colorM.getColor(palleteString.divLineColor)),
                divLineAlpha: pluck(chartAttrs.hdivlinealpha, colorM.getColor(divLineAlphaStr)),
                divLineThickness: pluckNumber(chartAttrs.hdivlinethickness, 1),
                divLineIsDashed: Boolean(pluckNumber(chartAttrs.hdivlinedashed, chartAttrs.hdivlineisdashed, 0)),
                divLineDashLen: pluckNumber(chartAttrs.hdivlinedashlen, 4),
                divLineDashGap: pluckNumber(chartAttrs.hdivlinedashgap, 2),
                // showLimits: chartAttrs.showlimits,
                // showDivLineValues: pluckNumber(chartAttrs.showdivlinevalues, chartAttrs.showdivlinevalue),
                showZeroPlane: chartAttrs.showzeroplane,
                zeroPlaneColor: chartAttrs.zeroplanecolor,
                zeroPlaneThickness: chartAttrs.zeroplanethickness,
                zeroPlaneAlpha: chartAttrs.zeroplanealpha,
                showZeroPlaneValue: chartAttrs.showzeroplanevalue,
                trendlineColor: chartAttrs.trendlinecolor,
                trendlineToolText: chartAttrs.trendlinetooltext,
                trendlineThickness: chartAttrs.trendlinethickness,
                trendlineAlpha: chartAttrs.trendlinealpha,
                showTrendlinesOnTop: chartAttrs.showtrendlinesontop,
                showAxisLine: pluckNumber(chartAttrs.showyaxisline, chartAttrs.showaxislines,
                    chartAttrs.drawAxisLines, 0),
                axisLineThickness: pluckNumber(chartAttrs.yaxislinethickness, chartAttrs.axislinethickness, 1),
                axisLineAlpha: pluckNumber(chartAttrs.yaxislinealpha, chartAttrs.axislinealpha, 100),
                axisLineColor: pluck(chartAttrs.yaxislinecolor, chartAttrs.axislinecolor, COLOR_000000)
            };
            xAxisConf.vtrendlines = dataObj.vtrendlines;
            yAxisConf.trendlines = dataObj.trendlines;
            yAxis = components.yAxis[0];
            xAxis = components.xAxis[0];

            yAxis.setCommonConfigArr(yAxisConf, true, true, false);
            xAxis.setCommonConfigArr(xAxisConf, false, false, iapi.config.placeAxisLabelsOnTop ? true : false);
            yAxis.configure();
            xAxis.configure();

            // set the chart categories
            iapi._setCategories();

        },

        _setAxisLimits : function () {

        },

        _setCategories: function() {

            var iapi = this,
                components = iapi.components,
                dataObj = iapi.jsonData,
                xAxis = components.xAxis,
                yAxis = components.yAxis,
                len = dataObj.dataset && dataObj.dataset[0].data && dataObj.dataset[0].data.length,
                i,
                columnObj,
                rowObj,
                columns,
                rows,
                columnArr = [],
                rowArr = [],
                columnFlag,
                rowFlag,
                j;

            if (!dataObj.columns || !dataObj.rows) {
                dataObj.columns = {};
                dataObj.columns.column = columns = [];

                dataObj.rows = {};
                dataObj.rows.row = rows = [];

                for (i = 0; i < len; i++) {
                    columnFlag = true;
                    rowFlag = true;

                    for (j=0; j<columns.length; j++) {
                        if (dataObj.dataset[0].data[i].columnid == columns[j].id) {
                            columnFlag = false;
                        }
                    }
                    if (columnFlag) {
                        columnObj = {
                            id : dataObj.dataset[0].data[i].columnid,
                            label: dataObj.dataset[0].data[i].columnid
                        };
                        dataObj.columns.column.push(columnObj);
                    }

                    for (j=0; j<rows.length; j++) {
                        if (dataObj.dataset[0].data[i].rowid == rows[j].id) {
                            rowFlag = false;
                        }
                    }
                    if (rowFlag) {
                        rowObj = {
                            id : dataObj.dataset[0].data[i].rowid,
                            label: dataObj.dataset[0].data[i].rowid
                        };
                        dataObj.rows.row.push(rowObj);
                    }
                }
            }

            columns = dataObj.columns.column;
            rows = dataObj.rows.row;

            for (i = 0; i < (columns && columns.length); i++) {
                columns[i].label = pluck(columns[i].label, columns[i].name, columns[i].id);
                (columns[i].label !== UNDEFINED) && columnArr.push(columns[i]);
            }
            dataObj.columns.column = columnArr;

            for (i = 0; i < (rows && rows.length); i++) {
                rows[i].label = pluck(rows[i].label, rows[i].name, rows[i].id);
                (rows[i].label !== UNDEFINED) && rowArr.push(rows[i]);
            }
            dataObj.rows.row = rowArr;

            dataObj.columns && xAxis[0].setAxisPadding(0.5, 0.5);
            dataObj.columns && xAxis[0].setCategory(dataObj.columns.column);

            dataObj.columns && yAxis[0].setAxisPadding(0.5, 0.5);
            dataObj.rows && yAxis[0].setCategory(dataObj.rows.row);

            xAxis[0].setAxisConfig({
                categoryNumDivLines : dataObj.columns.column.length - 1,
                categoryDivLinesFromZero : 0,
                showAlternateGridColor : 0
            });

            yAxis[0].setAxisConfig({
                categoryNumDivLines : dataObj.rows.row.length - 1,
                categoryDivLinesFromZero : 0,
                showAlternateGridColor : 0
            });

        }

    }, chartAPI.mscartesian, {
        enablemousetracking: true
    });
}]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-errorbar2d',
    function () {
        var global = this,
            lib = global.hcLib,
            //strings
            preDefStr = lib.preDefStr,
            colorStrings = preDefStr.colors,
            COLOR_FFFFFF = colorStrings.FFFFFF,
            COLOR_AAAAAA = colorStrings.AAAAAA,

            configStr = preDefStr.configStr,
            animationObjStr = preDefStr.animationObjStr,
            columnStr = preDefStr.columnStr,
            shadowStr = preDefStr.shadowStr,
            errorBarStr = preDefStr.errorBarStr,
            errorShadowStr = preDefStr.errorShadowStr,
            miterStr = preDefStr.miterStr,
            visibleStr = preDefStr.visibleStr,
            visiblilityStr = preDefStr.visiblilityStr,
            ROUND = preDefStr.ROUND,
            PERCENTAGESTRING = preDefStr.PERCENTAGESTRING,
            pStr = preDefStr.pStr,
            sStr = preDefStr.sStr,
            BLANKSTRING = lib.BLANKSTRING,
            parseTooltext = lib.parseTooltext,
            //add the tools thats are requared
            pluck = lib.pluck,
            getValidValue = lib.getValidValue,
            pluckNumber = lib.pluckNumber,
            getFirstValue = lib.getFirstValue,
            toRaphaelColor = lib.toRaphaelColor,
            isIE = lib.isIE,
            UNDEFINED,
            NONE = 'none',
            ROLLOVER = 'DataPlotRollOver',
            ROLLOUT = 'DataPlotRollOut',
            COMMASPACE = lib.COMMASPACE,
            showHoverEffectStr = preDefStr.showHoverEffectStr,
            SETROLLOVERATTR = preDefStr.setRolloverAttrStr,
            SETROLLOUTATTR = preDefStr.setRolloutAttrStr,
            DEFAULT_CURSOR = 'default',

            PLOTBORDERCOLOR = 'plotBorderColor',
            PLOTGRADIENTCOLOR = 'plotGradientColor',
            SHOWSHADOW = 'showShadow',
            POINTER = 'pointer',
            EVENTARGS = 'eventArgs',
            GROUPID = 'groupId',
            COMPONENT = 'component',
            DATASET = 'dataset',
            TRACKER_FILL = 'rgba(192,192,192,' + (isIE ? 0.002 : 0.000001) + ')', // invisible but clickable
            TOUCH_THRESHOLD_PIXELS = lib.TOUCH_THRESHOLD_PIXELS,
            CLICK_THRESHOLD_PIXELS = lib.CLICK_THRESHOLD_PIXELS,
            M = 'M',
            H = 'H',
            V = 'V',
            COMMA = ',',
            math = Math,
            mathRound = math.round,
            mathMin = math.min,
            mathMax = math.max,
            mathAbs = math.abs,
            hasTouch = lib.hasTouch,
            // hot/tracker threshold in pixels
            HTP = hasTouch ? TOUCH_THRESHOLD_PIXELS :
                CLICK_THRESHOLD_PIXELS,
            // getColumnColor = lib.graphics.getColumnColor,
            getFirstColor = lib.getFirstColor,
            // pluckColor = lib.pluckColor,
            getFirstAlpha = lib.getFirstAlpha,
            getLightColor = lib.graphics.getLightColor,
            convertColor = lib.graphics.convertColor,
            HUNDREDSTRING = lib.HUNDREDSTRING,
            // COMMASPACE = lib.COMMASPACE,
            plotEventHandler = lib.plotEventHandler;

        FusionCharts.register(COMPONENT, [DATASET, 'ErrorBar2D', {
            /*
             * Function for parsing all the attributes and value given by the user at chart,dataset and set level.
             * This function is called once from the init() function of the Column class.
             */
            configure : function () {
                var dataSet = this,
                    chart = dataSet.chart,
                    //logic = chart.logic,
                    conf = dataSet.config,
                    //fcJSON = dataSet.fcJSON,
                    JSONData = dataSet.JSONData,
                    setDataArr = JSONData.data,
                    setDataLen = setDataArr && setDataArr.length,
                    categories = chart.config.categories,
                    catLen = categories && categories.length,
                    len = mathMin(catLen, setDataLen),
                    chartAttr = chart.jsonData.chart,
                    colorM = chart.components.colorManager,
                    index = dataSet.index || dataSet.positionIndex,
                    showplotborder,
                    plotColor = colorM.getPlotColor(index),
                    plotBorderDash = pluckNumber(JSONData.dashed, chartAttr.plotborderdashed),
                    usePlotGradientColor = pluckNumber(chartAttr.useplotgradientcolor, 1),
                    showTooltip,
                    parseUnsafeString = lib.parseUnsafeString,
                    yAxisName = parseUnsafeString(chartAttr.yaxisname),
                    xAxisName = parseUnsafeString(chartAttr.xaxisname),
                    tooltipSepChar = parseUnsafeString(pluck(chartAttr.tooltipsepchar, COMMASPACE)),
                    seriesNameInTooltip = pluckNumber(chartAttr.seriesnameintooltip, 1),
                    parseTooltext = lib.parseTooltext,
                    formatedVal,
                    parserConfig,
                    setTooltext,
                    seriesname,
                    macroIndices,
                    tempPlotfillAngle,
                    toolText,
                    plotDashLen,
                    plotDashGap,
                    plotBorderThickness,
                    isRoundEdges,
                    showHoverEffect,
                    plotfillAngle,
                    plotFillAlpha,
                    plotRadius,
                    plotFillRatio,
                    plotgradientcolor,
                    plotBorderAlpha,
                    plotBorderColor,
                    plotBorderDashStyle,
                    initailPlotBorderDashStyle,
                    setData,
                    setValue,
                    dataObj,
                    config,
                    label,
                    colorArr,
                    hoverColor,
                    hoverAlpha,
                    hoverGradientColor,
                    hoverRatio,
                    hoverAngle,
                    hoverBorderColor,
                    hoverBorderAlpha,
                    hoverBorderThickness,
                    hoverBorderDashed,
                    hoverBorderDashGap,
                    hoverBorderDashLen,
                    hoverDashStyle,
                    hoverColorArr,
                    getDashStyle = lib.getDashStyle,
                    dataStore = dataSet.components.data,
                    numberFormatter = chart.components.numberFormatter,
                    toolTipValue,
                    setDisplayValue,
                    definedGroupPadding,
                    isBar = chart.isBar,
                    is3D = chart.is3D,
                    isStacked = chart.isStacked,
                    stack100Percent,
                    enableAnimation,
                    parentYAxis,
                    setDataDashed,
                    setDataPlotDashLen,
                    setDataPlotDashGap,

                    setErrorValue,
                    errorDataValue,
                    errorPercentValue,
                    errorInPercent,
                    i,
                    includeInLegend,
                    reflowData = /*logic.chartInstance.jsVars._reflowData*/ {},
                    reflowDataObj = reflowData.dataObj || (reflowData.dataObj = {}),
                    reflowChartObj = reflowDataObj.chart || (reflowDataObj.chart = {});

                conf.legendSymbolColor = plotColor;
                showplotborder = conf.showplotborder = pluckNumber(chartAttr.showplotborder, is3D ? 0 : 1);
                conf.plotDashLen = plotDashLen = pluckNumber(chartAttr.plotborderdashlen, 5);
                conf.plotDashGap = plotDashGap = pluckNumber(chartAttr.plotborderdashgap, 4);
                conf.plotfillAngle = plotfillAngle =  pluckNumber(360 - chartAttr.plotfillangle, (isBar ? 180 : 90));
                conf.plotFillAlpha =  plotFillAlpha = pluck(JSONData.alpha, chartAttr.plotfillalpha, HUNDREDSTRING);
                conf.plotColor = plotColor = pluck(JSONData.color, plotColor);
                conf.legendSymbolColor = conf.plotColor;
                conf.isRoundEdges = isRoundEdges = pluckNumber(chartAttr.useroundedges,0);
                conf.plotRadius = plotRadius = pluckNumber(chartAttr.useRoundEdges, conf.isRoundEdges ? 1 : 0);
                conf.plotFillRatio = plotFillRatio = pluck(JSONData.ratio, chartAttr.plotfillratio);
                conf.plotgradientcolor = plotgradientcolor = lib.getDefinedColor(chartAttr.plotgradientcolor,
                    colorM.getColor(PLOTGRADIENTCOLOR));
                !usePlotGradientColor && (plotgradientcolor = BLANKSTRING);
                conf.plotBorderAlpha = plotBorderAlpha = showplotborder ? pluck(chartAttr.plotborderalpha,
                    plotFillAlpha, HUNDREDSTRING): 0;
                conf.plotBorderColor = plotBorderColor = pluck(chartAttr.plotbordercolor,
                    is3D ? COLOR_FFFFFF : colorM.getColor(PLOTBORDERCOLOR));
                conf.plotBorderThickness = plotBorderThickness = pluckNumber(chartAttr.plotborderthickness, 1);
                conf.plotBorderDashStyle = initailPlotBorderDashStyle = plotBorderDash ?
                            getDashStyle(plotDashLen, plotDashGap, plotBorderThickness) : NONE;
                conf.showValues = pluckNumber(JSONData.showvalues, chartAttr.showvalues, 1);
                conf.valuePadding = pluckNumber(chartAttr.valuepadding, 2);
                conf.enableAnimation = enableAnimation = pluckNumber(chartAttr.animation,
                    chartAttr.defaultanimation, 1);
                conf.animation = !enableAnimation ? false : {
                    duration: pluckNumber(chartAttr.animationduration, 1) * 1000
                };
                reflowChartObj.transposeAnimation = conf.transposeAnimation =
                    pluckNumber(chartAttr.transposeanimation, reflowChartObj.transposeAnimation, enableAnimation);
                conf.transposeAnimDuration = pluckNumber(chartAttr.transposeanimduration, 0.2) * 1000;

                conf.showShadow = (isRoundEdges || is3D) ? pluckNumber(chartAttr.showshadow, 1) :
                    pluckNumber(chartAttr.showshadow, colorM.getColor(SHOWSHADOW));
                conf.showHoverEffect = showHoverEffect = pluckNumber(chartAttr.plothovereffect,
                    chartAttr.showhovereffect, UNDEFINED);
                conf.showTooltip = showTooltip = pluckNumber(chartAttr.showtooltip, 1);
                conf.stack100Percent = stack100Percent =
                    pluckNumber(chart.stack100percent ,chartAttr.stack100percent, 0);
                conf.definedGroupPadding = definedGroupPadding = mathMax(pluckNumber(chartAttr.plotspacepercent), 0);
                conf.plotSpacePercent = mathMax(pluckNumber(chartAttr.plotspacepercent, 20) % 100, 0);
                conf.maxColWidth = pluckNumber(isBar ? chartAttr.maxbarheight : chartAttr.maxcolwidth, 50);
                conf.showPercentValues = pluckNumber(chartAttr.showpercentvalues, (isStacked && stack100Percent) ?
                    1 : 0);
                conf.showPercentInToolTip = pluckNumber(chartAttr.showpercentintooltip,
                    (isStacked && stack100Percent) ? 1 : 0);
                conf.plotPaddingPercent = pluckNumber(chartAttr.plotpaddingpercent),
                conf.rotateValues = pluckNumber(chartAttr.rotatevalues) ? 270 : 0;
                conf.placeValuesInside = pluckNumber(chartAttr.placevaluesinside, 0);
                conf.includeInLegend = pluckNumber(JSONData.includeinlegend, 1);

                conf.errorInPercent = errorInPercent = pluckNumber(JSONData.errorinpercent, chartAttr.errorinpercent);

                conf.cumulativeValueOnErrorBar =
                    pluckNumber(JSONData.cumulativevalueonerrorbar, chartAttr.cumulativevalueonerrorbar, 1);
                // conf.zeroPlaneColor = chart.options.chart.zeroPlaneColor;
                // conf.zeroPlaneBorderColor = chart.options.chart.zeroPlaneBorderColor;
                // conf.zeroPlaneShowBorder = chart.options.chart.zeroPlaneShowBorder;

                conf.use3DLighting = pluckNumber(chartAttr.use3dlighting, 1);
                conf.parentYAxis = parentYAxis = pluck(JSONData.parentyaxis && JSONData.parentyaxis.toLowerCase(),
                    pStr) === sStr ? 1 : 0 ;
                if (!dataStore) {
                    dataStore = dataSet.components.data = [];
                }

                // Parsing the attributes and values at set level.
                for (i = 0; i < len; i++) {
                    setData = setDataArr && setDataArr[i];
                    dataObj = dataStore[i];
                    config = dataObj && dataObj.config;

                    if (!dataObj) {
                        dataObj = dataStore[i] = {
                            graphics : {}
                        };
                    }

                    if (!dataObj.config) {
                        config = dataStore[i].config = {};

                    }
                    config.showValue = pluckNumber(setData.showvalue, conf.showValues);
                    config.setValue = setValue = numberFormatter.getCleanValue(setData.value);
                    config.setLink  = pluck(setData.link);
                    config.toolTipValue = toolTipValue = numberFormatter.dataLabels(setValue, parentYAxis);
                    config.setDisplayValue = setDisplayValue = parseUnsafeString(setData.displayvalue);
                    config.displayValue = pluck(setDisplayValue, toolTipValue);
                    setDataDashed = pluckNumber(setData.dashed);
                    setDataPlotDashLen = pluckNumber(setData.dashlen, plotDashLen);
                    setDataPlotDashGap = plotDashGap = pluckNumber(setData.dashgap, plotDashGap);

                    config.plotBorderDashStyle = plotBorderDashStyle =  setDataDashed === 1 ?
                        getDashStyle(setDataPlotDashLen, setDataPlotDashGap, plotBorderThickness) :
                            (setDataDashed === 0 ? NONE : initailPlotBorderDashStyle);
                    plotColor = pluck(setData.color, conf.plotColor);
                    plotFillAlpha = pluck(setData.alpha, conf.plotFillAlpha);

                    // Setting the angle for plot fill for negative data
                    if (setValue < 0 && !isRoundEdges) {

                        tempPlotfillAngle = plotfillAngle;
                        plotfillAngle = isBar ? 180 - plotfillAngle : 360 - plotfillAngle;
                    }

                    // Setting the color Array to be applied to the bar/column.
                    config.colorArr = colorArr = lib.graphics.getColumnColor (
                            plotColor + COMMA + plotgradientcolor,
                            plotFillAlpha,
                            plotFillRatio,
                            plotfillAngle,
                            isRoundEdges,
                            plotBorderColor,
                            plotBorderAlpha.toString(),
                            (isBar ? 1 : 0),
                            (is3D ? true : false)
                            );

                    config.label = label =
                        getValidValue(parseUnsafeString(pluck (categories[i].tooltext, categories[i].label)));

                    // Parsing the hover effects only if showhovereffect is not 0.
                    if (showHoverEffect !== 0) {

                        hoverColor = pluck(setData.hovercolor, JSONData.hovercolor, chartAttr.plotfillhovercolor,
                            chartAttr.columnhovercolor, plotColor);
                        hoverAlpha = pluck(setData.hoveralpha, JSONData.hoveralpha,
                            chartAttr.plotfillhoveralpha, chartAttr.columnhoveralpha, plotFillAlpha);
                        hoverGradientColor = pluck(setData.hovergradientcolor,
                            JSONData.hovergradientcolor, chartAttr.plothovergradientcolor, plotgradientcolor);
                        !hoverGradientColor && (hoverGradientColor = BLANKSTRING);
                        hoverRatio = pluck(setData.hoverratio,
                            JSONData.hoverratio, chartAttr.plothoverratio, plotFillRatio);
                        hoverAngle = pluckNumber(360 - setData.hoverangle,
                            360 - JSONData.hoverangle, 360 - chartAttr.plothoverangle, plotfillAngle);
                        hoverBorderColor = pluck(setData.borderhovercolor,
                            JSONData.borderhovercolor, chartAttr.plotborderhovercolor, plotBorderColor);
                        hoverBorderAlpha = pluck(setData.borderhoveralpha,
                            JSONData.borderhoveralpha, chartAttr.plotborderhoveralpha,
                            chartAttr.plotfillhoveralpha, plotBorderAlpha, plotFillAlpha);
                        hoverBorderThickness = pluckNumber(setData.borderhoverthickness,
                            JSONData.borderhoverthickness, chartAttr.plotborderhoverthickness, plotBorderThickness);
                        hoverBorderDashed = pluckNumber(setData.borderhoverdashed,
                            JSONData.borderhoverdashed, chartAttr.plotborderhoverdashed);
                        hoverBorderDashGap = pluckNumber(setData.borderhoverdashgap,
                            JSONData.borderhoverdashgap, chartAttr.plotborderhoverdashgap, plotDashLen);
                        hoverBorderDashLen = pluckNumber(setData.borderhoverdashlen,
                            JSONData.borderhoverdashlen, chartAttr.plotborderhoverdashlen, plotDashGap);
                        hoverDashStyle = hoverBorderDashed ?
                            getDashStyle(hoverBorderDashLen, hoverBorderDashGap, hoverBorderThickness) :
                                plotBorderDashStyle;

                        /* If no hover effects are explicitly defined and
                         * showHoverEffect is not 0 then hoverColor is set.
                         */
                        if (showHoverEffect == 1 && hoverColor === plotColor) {
                            hoverColor = getLightColor(hoverColor, 70);
                        }

                        // setting the hover color array which is always applied except when showHoverEffect is not 0.
                        hoverColorArr = lib.graphics.getColumnColor (
                            hoverColor + COMMA + hoverGradientColor,
                            hoverAlpha,
                            hoverRatio,
                            hoverAngle,
                            isRoundEdges,
                            hoverBorderColor,
                            hoverBorderAlpha.toString(),
                            (isBar ? 1 : 0),
                            (is3D ? true : false)
                            ),

                        config.setRolloutAttr = {
                            fill: !is3D ? toRaphaelColor(colorArr[0])
                                    : [toRaphaelColor(colorArr[0]), !conf.use3DLighting],
                            stroke: showplotborder && toRaphaelColor(colorArr[1]),
                            'stroke-width': plotBorderThickness,
                            'stroke-dasharray': plotBorderDashStyle
                        };
                        config.setRolloverAttr = {
                            fill: !is3D ? toRaphaelColor(hoverColorArr[0])
                                    : [toRaphaelColor(hoverColorArr[0]), !conf.use3DLighting],
                            stroke: showplotborder && toRaphaelColor(hoverColorArr[1]),
                            'stroke-width': hoverBorderThickness,
                            'stroke-dasharray': hoverDashStyle
                        };
                    }

                    formatedVal = config.toolTipValue;

                    // Parsing tooltext against various configurations provided by the user.
                    setTooltext = getValidValue(parseUnsafeString(pluck(setData.tooltext,
                        JSONData.plottooltext, chartAttr.plottooltext)));

                    config.setErrorValue = setErrorValue = numberFormatter.getCleanValue(setData.errorvalue);
                    config.errorInPercent = pluckNumber(setData.errorinpercent, errorInPercent, 0);

                    config.errorInPercent &&
                    (config.setErrorValue = setErrorValue = pluckNumber(((setErrorValue / 100) * setValue).toFixed(2)));

                    config.cumulativeValueOnErrorBar =
                        pluckNumber(setData.cumulativevalueonerrorbar, conf.cumulativeValueOnErrorBar, 1);

                    config.positiveErrorValue =
                        numberFormatter.getCleanValue(pluckNumber(setData.positiveerrorvalue, setData.errorvalue));

                    (config.errorInPercent && config.positiveErrorValue) &&
                    (config.positiveErrorValue = pluckNumber(((config.positiveErrorValue / 100) *
                        setValue).toFixed(2)));

                    config.positiveCumulativeErrorValue = setValue +
                        pluckNumber(config.positiveErrorValue, config.setErrorValue);

                    config.negativeErrorValue =
                        numberFormatter.getCleanValue(pluckNumber(setData.negativeerrorvalue, setData.errorvalue));

                    (config.errorInPercent && config.negativeErrorValue) &&
                    (config.negativeErrorValue = pluckNumber(((config.negativeErrorValue / 100) *
                        setValue).toFixed(2)));

                    config.negativeCumulativeErrorValue = setValue -
                        pluckNumber(config.negativeErrorValue, config.setErrorValue);

                    config.errorToolTipValue = errorDataValue = numberFormatter.dataLabels(setErrorValue, parentYAxis);


                    config.negativeErrorToolTipValue =
                        numberFormatter.dataLabels(config.negativeErrorValue, parentYAxis);

                    config.negativeCumulativeErrorTooltipValue =
                        numberFormatter.dataLabels(config.negativeCumulativeErrorValue, parentYAxis);

                    config.positiveErrorToolTipValue =
                        numberFormatter.dataLabels(config.positiveErrorValue, parentYAxis);

                    config.positiveCumulativeErrorTooltipValue =
                        numberFormatter.dataLabels(config.positiveCumulativeErrorValue, parentYAxis);

                    config.errorPercentValue = errorPercentValue =
                        (mathRound(((setErrorValue / setValue) * HUNDREDSTRING) * HUNDREDSTRING) /
                        HUNDREDSTRING) + PERCENTAGESTRING;

                    if (!showTooltip) {
                        toolText = false;
                    }
                    else {
                        if (formatedVal === null) {
                            toolText = false;
                        }
                        else if (setTooltext !== undefined) {
                            macroIndices = [1,2,3,4,5,6,7,99,100,101,102,120,121];
                            parserConfig = {
                                yaxisName: yAxisName,
                                xaxisName: xAxisName ,
                                formattedValue : formatedVal,
                                errorValue: setErrorValue,
                                errorDataValue: errorDataValue,
                                errorPercentValue: errorPercentValue,
                                errorPercentDataValue: errorPercentValue,
                                positiveErrorValue: config.positiveErrorToolTipValue,
                                negativeErrorValue: config.negativeErrorToolTipValue,
                                label : label
                            };
                            toolText = parseTooltext(setTooltext, macroIndices,
                                parserConfig, setData, chartAttr, JSONData);
                        }
                        else {
                            if (seriesNameInTooltip) {
                                seriesname = getFirstValue(JSONData && JSONData.seriesname);
                            }
                            toolText = seriesname ? seriesname + tooltipSepChar : BLANKSTRING;
                            toolText += label ? label + tooltipSepChar : BLANKSTRING;
                        }
                    }
                    config.toolText = toolText;
                    config.setTooltext = toolText;
                    tempPlotfillAngle && (plotfillAngle = tempPlotfillAngle);
                }
                includeInLegend = dataSet.config.includeInLegend;
                (chart.hasLegend !== false) && includeInLegend && dataSet._addLegend();
                dataSet.ErrorValueConfigure();
            },

            ErrorValueConfigure: function() {
                var dataSet = this,
                    chart = dataSet.chart,
                    conf = dataSet.config,
                    //fcJSON = dataSet.fcJSON,
                    JSONData = dataSet.JSONData,
                    setDataArr = JSONData.data,
                    setDataLen = setDataArr && setDataArr.length,
                    categories = chart.config.categories,
                    catLen = categories && categories.length,
                    len = mathMin(catLen, setDataLen),
                    chartAttr = chart.jsonData.chart,
                    parseUnsafeString = lib.parseUnsafeString,
                    setData,
                    dataObj,
                    config,
                    dataStore = dataSet.components.data,
                    yAxisName = parseUnsafeString(chartAttr.yaxisname),
                    xAxisName = parseUnsafeString(chartAttr.xaxisname),
                    toolText,
                    seriesNameInTooltip = pluckNumber(chartAttr.seriesnameintooltip, 1),
                    seriesname,
                    tooltipSepChar = parseUnsafeString(pluck(chartAttr.tooltipsepchar, COMMASPACE)),
                    macroIndices,
                    parserConfig,
                    toolTipValue,
                    errorBarAlpha,
                    setErrorValue,
                    formatedVal,
                    setTooltext,
                    errorBarShadow,
                    maxValue = -Infinity,
                    minValue = Infinity,
                    setValue,
                    errorValue,
                    notHalfErrorBar,
                    maxErrorValue,
                    minErrorValue,
                    halfErrorBar,
                    positiveErrorValue,
                    negativeErrorValue,
                    cumulativeValueOnErrorBar,
                    positiveCumulativeErrorTooltext,
                    negativeCumulativeErrorTooltext,
                    getTooltext = function(setTooltext) {
                        var toolText;

                        if (!conf.showTooltip) {
                            toolText = false;
                        }
                        else {
                            if (formatedVal === null) {
                                toolText = false;
                            }
                            else if (setTooltext !== undefined) {
                                macroIndices = [1,2,3,4,5,6,7,99,100,101,102,120,121];
                                parserConfig = {
                                    yaxisName: yAxisName,
                                    xaxisName: xAxisName ,
                                    formattedValue : config.toolTipValue,
                                    errorValue: setErrorValue,
                                    errorDataValue: config.errorToolTipValue,
                                    errorPercentValue: config.errorPercentValue,
                                    errorPercentDataValue: config.errorPercentValue,
                                    positiveErrorValue: config.positiveErrorToolTipValue,
                                    negativeErrorValue: config.negativeErrorToolTipValue,
                                    label : config.label
                                };
                                toolText = parseTooltext(setTooltext, macroIndices,
                                    parserConfig, setData, chartAttr, JSONData);
                            }
                            else {
                                if (seriesNameInTooltip) {
                                    seriesname = getFirstValue(JSONData && JSONData.seriesname);
                                }
                                toolText = seriesname ? seriesname + tooltipSepChar : BLANKSTRING;
                                toolText += config.label ? config.label + tooltipSepChar : BLANKSTRING;
                            }
                        }
                        return toolText;
                    },
                    positiveErrorToolText,
                    negativeErrorToolText,
                    i;

                conf.showValues = pluckNumber(JSONData.showvalues, chartAttr.showvalues, 0);
                conf.errorBarShadow = errorBarShadow = pluckNumber(chartAttr.errorbarshadow, chartAttr.showshadow, 1);
                conf.ignoreEmptyDatasets = pluckNumber(JSONData.ignoreemptydatasets, 0);
                halfErrorBar = pluckNumber(chartAttr.halferrorbar, 1);
                conf.notHalfErrorBar = notHalfErrorBar = !pluckNumber(chartAttr.halferrorbar, 1);

                errorBarAlpha = getFirstAlpha(pluck(
                        JSONData.errorbaralpha, chartAttr.errorbaralpha, conf.plotFillAlpha));
                conf.errorBarWidthPercent = pluckNumber(
                    JSONData.errorbarwidthpercent, chartAttr.errorbarwidthpercent, 70);
                conf.errorBarColor = convertColor(getFirstColor(
                    pluck(JSONData.errorbarcolor, chartAttr.errorbarcolor,
                        COLOR_AAAAAA)), errorBarAlpha);
                conf.errorBarThickness = pluckNumber(
                    JSONData.errorbarthickness, chartAttr.errorbarthickness, 1);
                conf.shadowOpacity = errorBarShadow ? (errorBarAlpha / 250) : 0;



                for (i = 0; i < len; i++) {
                    setData = setDataArr && setDataArr[i];
                    dataObj = dataStore[i];
                    config = dataObj && dataObj.config;
                    positiveErrorToolText = UNDEFINED;
                    negativeErrorToolText = UNDEFINED;

                    if (pluckNumber(setData.value) === UNDEFINED) {
                        continue;
                    }

                    if (!dataObj) {
                        dataObj = dataStore[i] = {
                            graphics : {}
                        };
                    }

                    if (!dataObj.config) {
                        config = dataStore[i].config = {};

                    }

                    cumulativeValueOnErrorBar = config.cumulativeValueOnErrorBar;

                    config.notHalfErrorBar = conf.notHalfErrorBar;
                    config.halfErrorBar = halfErrorBar;

                    setValue = config.setValue;
                    config.showValue = pluckNumber(setData.showvalue, conf.showValues);
                    config.hasErrorValue = pluckNumber(setData.errorvalue) !== UNDEFINED ? 1 : 0;
                    setErrorValue = config.setErrorValue;

                    errorValue = config.errorValue = setErrorValue;

                    toolTipValue = config.errorToolTipValue;

                    formatedVal = toolTipValue;

                    setTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
                        JSONData.errorplottooltext, chartAttr.errorplottooltext,
                        formatedVal)));

                    toolText = getTooltext(setTooltext);

                    positiveErrorToolText = negativeErrorToolText = undefined;

                    setTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
                        JSONData.errorplottooltext, chartAttr.errorplottooltext,
                        config.positiveErrorToolTipValue)));

                    (setTooltext && config.positiveErrorToolTipValue) &&
                        (positiveErrorToolText = getTooltext(setTooltext));

                    setTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
                        JSONData.errorplottooltext, chartAttr.errorplottooltext,
                        config.negativeErrorToolTipValue)));

                    (setTooltext && config.negativeErrorToolTipValue) &&
                        (negativeErrorToolText = getTooltext(setTooltext));

                    if (cumulativeValueOnErrorBar) {
                        setTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
                            JSONData.errorplottooltext, chartAttr.errorplottooltext,
                                config.positiveCumulativeErrorTooltipValue)));

                        (setTooltext && config.positiveCumulativeErrorTooltipValue) &&
                            (positiveCumulativeErrorTooltext = getTooltext(setTooltext));

                        setTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
                            JSONData.errorplottooltext, chartAttr.errorplottooltext,
                                config.negativeCumulativeErrorTooltipValue)));

                        (setTooltext && config.negativeCumulativeErrorTooltipValue) &&
                            (negativeCumulativeErrorTooltext = getTooltext(setTooltext));
                    }

                    positiveErrorValue = config.positiveErrorValue;

                    negativeErrorValue = config.negativeErrorValue;

                    if (setData.positiveerrorvalue || setData.negativeerrorvalue) {
                        config.halfErrorBar = 0;
                        config.notHalfErrorBar = true;
                    }

                    maxErrorValue = setValue + (positiveErrorValue !== null ? positiveErrorValue : setErrorValue);
                    minErrorValue = setValue - (config.halfErrorBar ? 0 :
                        ((negativeErrorValue < 0 && setValue < 0) ? 0 :
                        (negativeErrorValue != null ? negativeErrorValue : setErrorValue)));

                    maxValue = mathMax(maxValue, maxErrorValue, minErrorValue);
                    minValue = mathMin(minValue, maxErrorValue, minErrorValue);

                    config.errorValueArr = [];

                    (config.positiveErrorValue === null) && (config.positiveErrorValue = undefined);
                    errorValue = -config.positiveErrorValue;
                    config.errorValueArr.push({
                        errorValue: errorValue,
                        tooltext: cumulativeValueOnErrorBar ? positiveCumulativeErrorTooltext :
                            (positiveErrorToolText || toolText),
                        errorEdgeBar : true
                    });

                    config.errorValueArr.push({
                        errorValue: errorValue,
                        tooltext: positiveErrorToolText || toolText
                    });

                    if (config.notHalfErrorBar) {
                        errorValue = config.negativeErrorValue;
                        config.errorValueArr.push({
                            errorValue: errorValue,
                            tooltext: cumulativeValueOnErrorBar ? negativeCumulativeErrorTooltext :
                                (negativeErrorToolText || toolText),
                            errorEdgeBar : true
                        });
                        config.errorValueArr.push({
                            errorValue: errorValue,
                            tooltext: negativeErrorToolText || toolText
                        });
                    }
                }
                conf.maxValue = maxValue;
                conf.minValue = minValue;
            },
            /*
             * Function for initializing the column class object.
             * This function is called once.
             * @param {object} chart - The default FutionCharts chart object.
             * @param {number} datasetIndex - The postion index of a dataset.
             * @param {number} stackIndex - The stack index of a dataset.
             */
            init : function(datasetJSON) {
                var dataSet = this,
                    chart = dataSet.chart,
                    components = chart.components,
                    visible,
                    isDual = chart.isDual,
                    //todo
                    yAxis = isDual ? components.yAxis[dataSet.yAxis || 0] : components.yAxis[0];



                if (!datasetJSON) {
                    return false;
                }
                dataSet.JSONData = datasetJSON;
                dataSet.yAxis = yAxis;
                dataSet.chartGraphics = chart.chartGraphics;
                dataSet.components = {
                };

                dataSet.graphics = {
                };

                // defined(stackIndex) ? (dataSet.JSONData = dataJSONarr[datasetIndex].dataset[stackIndex]):
                //         (dataSet.JSONData = dataJSONarr[datasetIndex]);
                dataSet.visible = visible = pluckNumber(dataSet.JSONData.visible,
                    !Number(dataSet.JSONData.initiallyhidden), 1) === 1;
                dataSet.configure();
            },

            /*
             * Function for drawing 2D columns.
             * This function is called every time for each dataset when they are initially drawn or shown/hidden from
             * the drawGraph() function.
             */
            draw: function () {
                var dataSet = this,
                    JSONData = dataSet.JSONData,
                    chartAttr = dataSet.chart.jsonData.chart,
                    conf = dataSet.config,
                    groupManager = dataSet.groupManager,
                    datasetIndex = dataSet.index,
                    categories = dataSet.chart.config.categories,
                    setDataArr = JSONData.data,
                    len,
                    setData,
                    attr,
                    i,
                    visible = dataSet.visible,
                    chart = dataSet.chart,
                    //jobList = chart.getJobList(),
                    paper = chart.components.paper,
                    xAxis = chart.components.xAxis[0],
                    yAxis = chart.components.yAxis[0],
                    parentContainer = chart.graphics.columnGroup,
                    isStacked = false,
                    xPos,
                    yPos,
                    crispBox,
                    parseUnsafeString = lib.parseUnsafeString,
                    getValidValue = lib.getValidValue,
                    R = lib.Raphael,
                    showTooltip = conf.showTooltip,
                    xAxisZeroPos = xAxis.getAxisPosition(0),
                    xAxisFirstPos = xAxis.getAxisPosition(1),
                    groupMaxWidth = conf.groupMaxWidth = xAxisFirstPos - xAxisZeroPos,
                    definedGroupPadding = conf.definedGroupPadding,
                    plotSpacePercent = conf.plotSpacePercent,
                    groupPadding = plotSpacePercent / 200,
                    numOfColumns = 1,
                    positionValue = groupManager.getDataSetPosition(dataSet),
                    stackSumValue = groupManager.stackSumValue[dataSet.positionIndex],
                    manageClip = groupManager.manageClip,
                    maxColWidth = conf.maxColWidth,

                    animationObj = chart.get(configStr, animationObjStr),
                    animType = animationObj.animType,
                    animObj = animationObj.animObj,
                    dummyObj = animationObj.dummyObj,
                    animationDuration = animationObj.duration,

                    // Calculating the net width occupied by bars for each category
                    groupNetWidth = (1 - definedGroupPadding * 0.01) * groupMaxWidth || mathMin(
                        groupMaxWidth * (1 - groupPadding * 2),
                        maxColWidth * numOfColumns
                    ),
                    initialColumnWidth = pluckNumber(positionValue.columnWidth, (groupNetWidth / numOfColumns)),
                    columnWidth,
                    xPosOffset = positionValue.xPosOffset || 0,
                    hiddenDatasetHeight = positionValue.height,
                    height,
                    toolText,
                    dataStore = dataSet.components.data,
                    dataObj,
                    setTooltext,
                    setElement,
                    // hotElement,
                    setLink,
                    setValue,
                    // eventArgs,
                    displayValue,
                    groupId,
                    config,
                    setRolloutAttr = {},
                    setRolloverAttr = {},

                    yAxisMaxmin = yAxis.getLimit(),
                    yMax = yAxisMaxmin.max,
                    yMin = yAxisMaxmin.min,

                    isPositiveNegative = yMax > 0 && yMin < 0,
                    isPositive,
                    yBase = yAxis.getAxisBase(),
                    yBasePos = yAxis.yBasePos = yAxis.getAxisPosition(yBase),
                    previousY,
                    previousYPos,
                    heightBase = 0,
                    showShadow = conf.showShadow,
                    plotBorderThickness = conf.plotBorderThickness,
                    plotRadius = conf.plotRadius,
                    container = dataSet.graphics.container,
                    dataLabelContainer = dataSet.graphics.dataLabelContainer,
                    shadowContainer = dataSet.graphics.shadowContainer,
                    errorGroupContainer = dataSet.graphics.errorGroupContainer,
                    errorShadowContainer = dataSet.graphics.errorShadowContainer,
                    colorArr,
                    plotBorderDashStyle,
                    animFlag = true,
                    drawDataLabel = false,
                    drawSumLabel = false,
                    drawErrorBar = false,
                    isNewElement,
                    removeDataArr = dataSet.components.removeDataArr || [],
                    removeDataArrLen = removeDataArr.length,
                    pool = dataSet.components.pool || [],
                    //showHoverEffect = conf.showHoverEffect,
                    chartConfig = chart.config,
                    showHoverEffect = chartConfig.plothovereffect,
                    trackerConfig,
                    //Fired at the end of transpose animation.
                    animCallBack = function() {
                        /*
                         * It enters the if condition if the dataset is not visible that is the legend is clicked to
                         * hide the dataset. Also it is executed only once for each dataset though it is called by
                         * every plot of each dataset but the _conatinerHidden flag restricts multiple execution of the
                         * if condition.
                         */
                        if (dataSet.visible === false && (dataSet._conatinerHidden === false ||
                                dataSet._conatinerHidden=== undefined)) {
                            container.hide();
                            shadowContainer.hide();
                            dataLabelContainer && dataLabelContainer.hide();
                            errorGroupContainer && errorGroupContainer.hide();
                            errorShadowContainer && errorShadowContainer.hide();
                            dataSet._conatinerHidden = true;
                        }
                    },
                    //animCompleteFn = chart.getAnimationCompleteFn(),

                    //Fired initially after the chart is rendered.
                    initAnimCallBack = function() {
                        dataSet.drawLabel();
                        dataSet.drawErrorValue();
                        //groupManager.drawSumValueFlag && groupManager.drawSumValue();
                        //animCompleteFn();
                    };

                /*
                 * Creating a container group for the graphic element of column plots if
                 * not present and attaching it to its parent group.
                 */
                if (!container) {
                    container = dataSet.graphics.container =
                        paper.group(columnStr, parentContainer).trackTooltip(true);

                    // Clipping the group so that the plots do not come out of the canvas area when given thick border.
                    // if (!container.attrs['clip-rect'] && !isScroll) {
                    //     container.attr({
                    //         'clip-rect': elements['clip-canvas']
                    //     });
                    // }
                    if (visible) {
                        container.show();
                    }
                    else {
                        container.hide();
                    }
                }

                //chart.addCSSDefinition('.fusioncharts-datalabels .fusioncharts-label', labelCSS);

                /*
                 * Creating the shadow element container group for each plots if not present
                 * and attaching it its parent group.
                 */
                if (!shadowContainer) {
                    // Always sending the shadow group to the back of the plots group.
                    shadowContainer = dataSet.graphics.shadowContainer =
                        paper.group(shadowStr, parentContainer).toBack();
                    // Clipping the group so that the shadow do not come out of the canvas area when given thick border.
                    // if (!shadowContainer.attrs['clip-rect'] && !isScroll) {
                    //     shadowContainer.attr({
                    //         'clip-rect': elements['clip-canvas']
                    //     });
                    // }
                    if (!visible) {
                        shadowContainer.hide();
                    }

                }

                len = xAxis.getCategoryLen();

                // Create plot elements.
                for (i = 0; i < len; i++) {
                    setData = setDataArr && setDataArr[i];
                    dataObj = dataStore[i];
                    if (!dataObj) {
                        continue;
                    }
                    trackerConfig = dataObj.trackerConfig = {};
                    config = dataObj && dataObj.config;
                    setValue = config && config.setValue;
                    isNewElement = false;

                    // If plot value is found "null", continue the loop to next iteration.
                    if (dataObj === undefined || setValue === undefined || setValue === null) {
                        continue;
                    }

                    isPositive = setValue >= 0;
                    setLink  = config.setLink;
                    colorArr = config.colorArr;

                    // Creating the data structure if not present for storing the graphics elements.
                    if (!dataObj.graphics) {
                        dataStore[i].graphics = {};

                    }

                    displayValue = config.displayValue;

                    previousY = isPositive ? config.previousPositiveY : config.previousNegativeY;

                    setTooltext = getValidValue(parseUnsafeString(pluck(setData.tooltext,
                            JSONData.plottooltext, chartAttr.plottooltext)));

                    /*
                     * If it is a stacked chart then the display value, tooltext value and data plots
                     * (if stack 100percent is active) is recalculated.
                     */
                    if (isStacked) {
                        previousY = dataSet._parseValues(i, previousY, stackSumValue[i], setTooltext);
                        setValue = config.value;
                    }

                    // Getting the previous yposition of the plot and calculating the current yposition of the plot.
                    previousYPos = yAxis.getAxisPosition( previousY|| yBase);
                    xPos = xAxis.getAxisPosition(i) + xPosOffset;

                    /*
                     * Check for setting the height of the datasets which are hidden. If the datasets are hidden then
                     * the height is set to 0 and ypos is set to the ypos of the previous plot.
                     */
                    if (hiddenDatasetHeight !== 0) {
                        yPos = yAxis.getAxisPosition(setValue + ( previousY || 0));
                        height = mathAbs(previousYPos - yPos);
                    }
                    else {
                        height = 0;
                        yPos = previousYPos;
                    }
                    yPos = mathMin(yPos,previousYPos);

                    // Fix for making the bottom border invisible for the plots.
                    if (!isPositiveNegative && manageClip && visible && plotBorderThickness > 0) {
                        height += plotBorderThickness;
                        groupManager.manageClip = false;
                    }

                    //todo- remove _ to make it public
                    dataObj._oriXPos = xPos;
                    dataObj._oriYPos = yPos;
                    dataObj._oriHeight = height;
                    dataObj._oriWidth = initialColumnWidth;

                    // Crisping the dataplots based on some condition determined by the column group manager.
                    if (groupManager.isCrisp) {
                        crispBox = R.crispBound(xPos, yPos, initialColumnWidth, height, plotBorderThickness);
                        xPos = crispBox.x;
                        yPos = crispBox.y;
                        columnWidth = crispBox.width;
                        height = crispBox.height;
                    }
                    else {
                        columnWidth = initialColumnWidth;
                    }

                    // Setting the final tooltext.
                    toolText = config.finalTooltext = (config.toolText !== false) && (config.toolText +
                        (setTooltext ? '' : config.toolTipValue));
                    plotBorderDashStyle = config.plotBorderDashStyle;

                    // Setting the event arguments.
                    trackerConfig.eventArgs = {
                        index: i,
                        link: setLink,
                        value: setValue,
                        cursor: setLink ? POINTER : BLANKSTRING,
                        displayValue: displayValue,
                        categoryLabel: categories[i].label,
                        toolText: !toolText ? '' : toolText,
                        id: BLANKSTRING,
                        datasetIndex: datasetIndex,
                        datasetName: JSONData.seriesname,
                        visible: visible
                    };

                    setRolloutAttr = config.setRolloutAttr;
                    setRolloverAttr = config.setRolloverAttr;

                    /*
                     * If animation is inactive then ybase position and heightBase of the plots is set to the final
                     * values.
                     */
                    if (!animationDuration) {
                        yBasePos = yPos;
                        heightBase = height;
                    }

                    // Setting the attributes for plot drawing.
                    attr = {
                        x: xPos,
                        y: yBasePos,
                        width: columnWidth,
                        height: heightBase || 1,
                        r: plotRadius,
                        ishot: !showTooltip,
                        fill: toRaphaelColor(colorArr[0]),
                        stroke: toRaphaelColor(colorArr[1]),
                        'stroke-width': plotBorderThickness,
                        'stroke-dasharray': plotBorderDashStyle,
                        'stroke-linejoin': miterStr,
                        'visibility': visible
                    };

                    //todo- remove _ to make it public
                    dataObj._xPos = xPos;
                    dataObj._yPos = yPos;
                    dataObj._height = height;
                    dataObj._width = columnWidth;

                    /*
                     * If the data plots are not present then they are created, else only attributes are set for the
                     * existing plots.
                     */
                    if (!dataObj.graphics.element) {

                        if(pool.element && pool.element.length) {
                            setElement = dataObj.graphics.element = pool.element.shift();
                            setElement.show();
                        }
                        // If there is no element in cachestore then create it freshly
                        else {
                            setElement = dataObj.graphics.element = paper.rect(attr, container);
                            isNewElement = true;
                        }
                        setElement.attr(attr);

                        setElement.animateWith(dummyObj, animObj, {
                            y: yPos,
                            height: height || 1
                        }, animationDuration, animType, (animFlag && initAnimCallBack));

                        animFlag = false;
                        config.elemCreated = true;
                    }

                    else {
                        drawSumLabel = drawDataLabel = drawErrorBar = true;

                        setElement = dataObj.graphics.element;

                        attr = {
                            x: xPos,
                            y: yPos,
                            width: columnWidth,
                            height: height || 1
                        };

                        setElement.animateWith(dummyObj, animObj, attr,
                            animationDuration, animType, (animFlag && animCallBack));

                        setElement.attr({
                            r: plotRadius,
                            ishot: !showTooltip,
                            fill: toRaphaelColor(colorArr[0]),
                            stroke: toRaphaelColor(colorArr[1]),
                            'stroke-width': plotBorderThickness,
                            'stroke-dasharray': plotBorderDashStyle,
                            'stroke-linejoin': miterStr,
                            'visibility': visible
                        });
                        config.elemCreated = false;
                    }

                    // The shadow element is set for the dataplots.
                    setElement
                    .shadow({opacity : showShadow}, shadowContainer)
                    .data('BBox', crispBox);

                    if (setLink || showTooltip) {
                        // Fix for touch devices.
                        if (height < HTP) {
                            yPos -= (HTP - height) / 2;
                            height = HTP;
                        }

                        // Setting attributes for the tooltip.
                        trackerConfig.attr = {
                            x: xPos,
                            y: yPos,
                            width: columnWidth,
                            height: height,
                            r: plotRadius,
                            stroke: TRACKER_FILL,
                            'stroke-width': plotBorderThickness,
                            fill: TRACKER_FILL,
                            ishot: true,
                            visibility: visible
                        };
                    }

                    groupId = datasetIndex + '_' + i;

                    // If algorithmic mouseTracking is enabled then attach these data to setElement
                    // because tracker element will not be drawn
                    chart.config.enablemousetracking && setElement
                        .data(GROUPID, groupId)
                        .data(EVENTARGS, trackerConfig.eventArgs)
                        .data(showHoverEffectStr, showHoverEffect)
                        .data(SETROLLOVERATTR, config.setRolloverAttr || {})
                        .data(SETROLLOUTATTR, config.setRolloutAttr || {});
                }

                removeDataArrLen && dataSet.remove();
                // The dataLabels are drawn if the drawDataLabel flag is set.
                drawDataLabel && dataSet.drawLabel();

                drawErrorBar && dataSet.drawErrorValue();
            },

            show : function() {
                var dataSet = this,
                    container = dataSet.graphics && dataSet.graphics.container,
                    dataLabelContainer = dataSet.graphics && dataSet.graphics.dataLabelContainer,
                    shadowContainer = dataSet.graphics && dataSet.graphics.shadowContainer,
                    errorGroupContainer = dataSet.graphics && dataSet.graphics.errorGroupContainer,
                    errorShadowContainer = dataSet.graphics && dataSet.graphics.errorShadowContainer,
                    is3D = dataSet.chart.is3D,
                    i,
                    data = dataSet.components.data,
                    dataSetLen = dataSet.JSONData.data && dataSet.JSONData.data.length,
                    categories = dataSet.chart.config.categories,
                    catLen = categories && categories.length,
                    yAxis = dataSet.yAxis,
                    chart = dataSet.chart,
                    len = mathMin(dataSetLen, catLen);

                chart._chartAnimation();
                dataSet.visible = true;
                dataSet._conatinerHidden = false;

                if (is3D) {
                    for (i = 0; i < len; i++) {
                        data[i].graphics.element && data[i].graphics.element.attr(visiblilityStr, visibleStr);
                    }
                }
                else {
                    container.show();
                }

                shadowContainer.show();
                dataLabelContainer && dataLabelContainer.show();
                errorGroupContainer && errorGroupContainer.show();
                errorShadowContainer && errorShadowContainer.show();

                chart._setAxisLimits();
                yAxis.draw();
                chart._drawDataset();
            },

            /*
             * This function is used to make a dataset hidden when clicked on its respective legend.
             * This fucntion is fired from drawGraph() every time an activated legend is clicked.
             */
            hide : function() {
                var dataSet = this,
                    yAxis = dataSet.yAxis,
                    chart = dataSet.chart;

                chart._chartAnimation();
                dataSet.visible = false;
                chart._setAxisLimits();
                yAxis.draw();
                chart._drawDataset();
            },

            drawErrorValue: function() {
                var dataSet = this,
                    JSONData = dataSet.JSONData,
                    //fcJSON = dataSet.fcJSON,
                    datasetIndex = dataSet.index,
                    conf = dataSet.config,
                    setDataArr = JSONData.data,
                    dataSetLen = setDataArr && setDataArr.length,
                    len,
                    setData,
                    attr,
                    i,
                    k,
                    visible = dataSet.visible,
                    chart = dataSet.chart,
                    catLen = chart.components.xAxis[0].getCategoryLen(),
                    parentContainer = chart.graphics.columnGroup,
                    paper = chart.components.paper,
                    //elements = chart.elements,
                    yAxis = chart.components.yAxis[0],
                    dataStore = dataSet.components.data,

                    groupManager = dataSet.groupManager,
                    positionValue = groupManager.getDataSetPosition(dataSet),
                    hiddenDatasetHeight = positionValue.height,

                    animationObj = chart.get(configStr, animationObjStr),
                    animType = animationObj.animType,
                    animObj = animationObj.animObj,
                    dummyObj = animationObj.dummyObj,
                    animationDuration = animationObj.duration,

                    errorBarThickness = conf.errorBarThickness,
                    errorBarWidthPercent = conf.errorBarWidthPercent,
                    errorBarColor = conf.errorBarColor,
                    showTooltip = conf.showTooltip,
                    shadowOpacity = conf.shadowOpacity,

                    errorGroupContainer = dataSet.graphics.errorGroupContainer,
                    errorShadowContainer = dataSet.graphics.errorShadowContainer,
                    setLink,
                    tooltext,
                    xPos,
                    yPos,

                    useCrispErrorPath = 1,
                    dataObj,
                    setValue,
                    // groupId,
                    config,
                    // eventArgs,
                    crispY,
                    crispX,
                    errorPath,
                    errorValPos,
                    errorValuePosFactor,
                    errorValueArr,
                    errorValueObj,
                    errorValue,
                    errorStartPos,
                    errorLen,
                    errorBarWidth,
                    halfErrorBarW,
                    groupId,
                    errorLineElem,
                    errorTrackerElem,
                    errorValueElem,
                    isNegative,
                    barXpos,
                    barYpos,
                    barWidth,
                    barHeight,
                    trackerConfig,
                    trackerTolerance = errorBarThickness > 5 ? (errorBarThickness / 2) : 2.5,
                    errorTrackerConfig;
                    // errorElemClick = function(e) {
                    //     var ele = this;
                    //     plotEventHandler.call(ele, chart, e);
                    // },
                    // erroElemHoverFN = function(e) {
                    //     var ele = this;
                    //     plotEventHandler.call(ele, chart, e, ROLLOVER);
                    // }, erroElemOutFN = function(e) {
                    //     var ele = this;
                    //     plotEventHandler.call(ele, chart, e, ROLLOUT);
                    // },
                    // getErrLinkClickFN = function(link) {
                    //     return function() {
                    //         (link !== undefined) &&
                    //             chart.linkClickFN.call({
                    //                 link: link
                    //             }, chart);
                    //     };
                    // };

                if (!errorGroupContainer) {
                    errorGroupContainer = dataSet.graphics.errorGroupContainer =
                     paper.group(errorBarStr, parentContainer);
                    /*if (!errorGroupContainer.attrs['clip-rect']) {
                        errorGroupContainer.attr({
                            'clip-rect': elements['clip-canvas']
                        });
                    }*/
                    if (!visible) {
                        errorGroupContainer.hide();
                    }
                }

                if (!errorShadowContainer) {
                    // Always sending the shadow group to the back of the plots group.
                    errorShadowContainer = dataSet.graphics.errorShadowContainer =
                        paper.group(errorShadowStr, parentContainer).toBack();
                    /*if (!errorShadowContainer.attrs['clip-rect']) {
                        errorShadowContainer.attr({
                            'clip-rect': elements['clip-canvas']
                        });
                    }*/
                    if (!visible) {
                        errorShadowContainer.hide();
                    }
                }

                len = mathMin(catLen, dataSetLen);

                // Loop through each data points
                for (i = 0; i < len; i++) {
                    setData = setDataArr && setDataArr[i];
                    dataObj = dataStore[i];
                    trackerConfig = dataObj.trackerConfig;
                    errorTrackerConfig = dataObj.errorTrackerConfig = {};
                    errorTrackerConfig.errorTrackerArr = [];
                    config = dataObj && dataObj.config;
                    setValue = config && config.setValue;

                    if (dataObj && (setValue === undefined || setValue === null)) {
                        if (dataObj.graphics.element) {
                            dataObj.graphics.element.hide();
                            dataObj.graphics.element.shadow(false);
                        }
                        dataObj.graphics.hotElement && dataObj.graphics.hotElement.hide();
                        errorLen = dataObj.graphics.error && dataObj.graphics.error.length;
                        for (k = 0; k < errorLen; k++) {
                            if (dataObj.graphics.error && dataObj.graphics.error[k]) {
                                dataObj.graphics.error[k].hide();
                                dataObj.graphics.error[k].shadow({opacity: 0});
                            }
                        }
                    }

                    // If plot value is found "null", continue the loop to next iteration.
                    if (dataObj === undefined || setValue === undefined || setValue === null) {
                        continue;
                    }

                    dataObj.errorBar && (delete dataObj.errorBar);

                    errorValueArr = config.errorValueArr;
                    errorTrackerConfig.errorLen = errorLen = errorValueArr.length;

                    !dataObj.graphics.error && (dataObj.graphics.error = []);
                    !dataObj.graphics.errorTracker && (dataObj.graphics.errorTracker = []);

                    if ((config.errorValue === BLANKSTRING || config.errorValue === undefined ||
                        (config.errorValue === null && config.positiveErrorValue === null &&
                        config.negativeErrorValue === null))) {

                        for (k = 0; k < errorLen; k++) {
                            if (dataObj.graphics.error && dataObj.graphics.error[k]) {
                                dataObj.graphics.error[k].hide();
                                dataObj.graphics.error[k].shadow({opacity: 0});
                            }
                        }
                        continue;
                    }

                    groupId = datasetIndex + '_' + i;

                    setLink  = config.setLink;

                    isNegative = (setValue < 0);

                    barXpos = dataObj._oriXPos;
                    barYpos = dataObj._oriYPos;
                    barWidth = dataObj._oriWidth;
                    barHeight = dataObj._oriHeight;

                    yPos = isNegative ? (barYpos + barHeight) : barYpos;
                    xPos = barXpos + (barWidth / 2);

                    dataObj.errorBar || (dataObj.errorBar = []);

                    //Loop through errorValue array
                    while (errorLen--) {
                        errorTrackerElem = errorLineElem = errorValueElem =
                            null;

                        errorTrackerConfig.errorTrackerArr[errorLen] = {};

                        errorValueObj = errorValueArr[errorLen];
                        errorTrackerConfig.errorTrackerArr[errorLen].tooltext = tooltext = errorValueObj.tooltext;
                        errorStartPos = yPos;
                        errorValue = errorValueObj.errorValue;

                        if (errorValue === null || isNaN(errorValue)) {
                            if (dataObj.graphics.error && dataObj.graphics.error[errorLen]) {
                                dataObj.graphics.error[errorLen].hide();
                                dataObj.graphics.error[errorLen].shadow({opacity: 0});
                            }

                            continue;
                        }
                        errorBarWidth = barWidth * (errorBarWidthPercent / 100);
                        halfErrorBarW = errorBarWidth / 2;

                        errorValuePosFactor = (hiddenDatasetHeight === 0) ? 0 : 1;
                        // Vertical Error drawing
                        errorValPos = barYpos +
                            ((yAxis.getAxisPosition(0) - yAxis.getAxisPosition(1)) * errorValue * errorValuePosFactor);
                        (isNegative) && (errorValPos = errorValPos + barHeight);
                        crispY = errorValPos;
                        crispX = xPos;
                        if (useCrispErrorPath) {
                            crispY = mathRound(errorValPos) +
                                (errorBarThickness % 2 / 2);
                            crispX = mathRound(xPos) +
                                (errorBarThickness % 2 / 2);
                        }
                        dataObj.errorBar[errorLen] || (dataObj.errorBar[errorLen] = []);
                        if (errorValueObj.errorEdgeBar) {
                            errorPath = [
                                M, crispX - halfErrorBarW, crispY,
                                H, (crispX + halfErrorBarW)
                            ];
                            dataObj.errorBar[errorLen][1] = {
                                _xPos: crispX - halfErrorBarW - trackerTolerance,
                                _yPos: crispY - trackerTolerance,
                                _height: 2 * trackerTolerance,
                                _width: 2 * (halfErrorBarW + trackerTolerance),
                                _toolText : errorValueObj.tooltext
                            };
                        } else {
                            errorPath = [
                                M, crispX, errorStartPos,
                                V, crispY
                            ];
                            dataObj.errorBar[errorLen][0] = {
                                _xPos: crispX - trackerTolerance,
                                _yPos: crispY < errorStartPos ? crispY : errorStartPos,
                                _height: mathAbs(errorStartPos - crispY),
                                _width: 2 * trackerTolerance,
                                _toolText : errorValueObj.tooltext
                            };
                        }


                        if (!dataObj.graphics.error[errorLen]) {
                            errorLineElem = dataObj.graphics.error[errorLen] =
                             paper.path(errorPath, errorGroupContainer)
                                .attr({
                                    stroke: errorBarColor,
                                    // In case of tooltip disabled this element should act as the hot element.
                                    ishot: !showTooltip,
                                    'stroke-width': errorBarThickness,
                                    'cursor': setLink ? POINTER : BLANKSTRING,
                                    'stroke-linecap': ROUND
                                });
                        }
                        else {
                            attr = {
                                path: errorPath
                            };

                            errorLineElem = dataObj.graphics.error[errorLen];

                            errorLineElem.animateWith(dummyObj, animObj, attr, animationDuration, animType);

                            errorLineElem.attr({
                                stroke: errorBarColor,
                                // In case of tooltip disabled this element should act as the hot element.
                                ishot: !showTooltip,
                                'stroke-width': errorBarThickness,
                                'cursor': setLink ? POINTER : BLANKSTRING,
                                'stroke-linecap': ROUND
                            });
                        }

                        errorLineElem.show();

                        errorLineElem
                            .shadow({opacity : shadowOpacity}, errorShadowContainer);

                        errorTrackerConfig.errorTrackerArr[errorLen].attr = {
                            path: errorPath,
                            stroke: TRACKER_FILL,
                            'stroke-width': (errorBarThickness < HTP) ? HTP : errorBarThickness,
                            'cursor': setLink ? POINTER : BLANKSTRING,
                            'ishot': !! setLink
                        };
                        chart.config.enablemousetracking && errorLineElem
                            .data(GROUPID, groupId)
                            .data(EVENTARGS, trackerConfig.eventArgs);

                    }

                    if (!config.notHalfErrorBar) {
                        for (k = 2; k < 4; k++) {
                            dataObj.graphics.error && dataObj.graphics.error[k] && dataObj.graphics.error[k].hide() &&
                            dataObj.graphics.error[k].shadow({opacity: 0});
                        }
                    }
                }
            },
            _rolloverResponseSetter : function (chart, data, event) {
                var dataGraphics = data.graphics,
                    errorBarHovered = data.errorBarHovered,
                    elem = dataGraphics && dataGraphics.element,
                    elData = elem && elem.getData();

                !errorBarHovered && elem &&
                    elData.showHoverEffect !== 0 && elem.attr(elem.getData().setRolloverAttr);
                elem && plotEventHandler.call(elem, chart, event, ROLLOVER);
            },
            _rolloutResponseSetter : function (chart, data, event) {
                var dataGraphics = data.graphics,
                    errorBarHovered = data.errorBarHovered,
                    elem = dataGraphics && dataGraphics.element,
                    elData = elem && elem.getData();

                !errorBarHovered && elem &&
                    elData.showHoverEffect !== 0 && elem.attr(elem.getData().setRolloutAttr);
                elem && plotEventHandler.call(elem, chart, event, ROLLOUT);
            },
            /**
             * This method handles all mouse events of an dataset.
             * @param {String} eventType name of the event
             * @param {number} plotIndex index of the plot where this event has been occured
             * @param {Event} originalEvent reference of the original mouse event
             */
            _firePlotEvent: function (eventType, plotIndex, e, datasetIndex) {
                var dataset = this,
                    chart = dataset.chart,
                    data = dataset.components.data[plotIndex],
                    setElement = data.graphics.element,
                    errorBarHovered = data.errorBarHovered,
                    tip = lib.toolTip,
                    originalEvent = e.originalEvent,
                    style = chart.components.paper.canvas.style,
                    config = data.config,
                    setLink = config.setLink;

                if (setElement) {
                    switch (eventType) {
                        case 'mouseover' :
                            dataset._decideTooltipType(plotIndex, datasetIndex, e);
                            dataset._rolloverResponseSetter(chart, data, originalEvent);
                            setLink && (style.cursor = POINTER);
                            break;
                        case 'mouseout' :
                            tip.hide(chart.chartInstance.id);
                            dataset._rolloutResponseSetter(chart, data, originalEvent);
                            setLink && (style.cursor = DEFAULT_CURSOR);
                            break;
                        case 'click' :
                            plotEventHandler.call(setElement, chart, originalEvent);
                            break;
                        case 'mousemove' :
                            dataset._decideTooltipType(plotIndex, datasetIndex, e);
                            if (errorBarHovered && !data._isRollover) {
                                setElement.showHoverEffect !== 0 &&
                                     setElement.attr(setElement.getData().setRolloutAttr);
                                data._isRollover = true;
                                data._isRollout = false;
                            }
                            else if (!errorBarHovered && !data._isRollout) {
                                setElement.showHoverEffect !== 0 &&
                                     setElement.attr(setElement.getData().setRolloverAttr);
                                data._isRollover = false;
                                data._isRollout = true;
                            }
                    }
                }
            },
            // Helper function of _checkPointerOverPlot().
            _checkPointerOverErrorBar : function (pX, chartX, chartY) {
                var dataset = this,
                    dataStore = dataset.components.data,
                    pointObj = dataStore[pX],
                    hovered,
                    errorBarArr,
                    errorBarCompArr,
                    len,
                    errorBarCompLen,
                    toolText,
                    xPos,
                    yPos,
                    height,
                    width;

                if (!pointObj) {
                    return;
                }

                errorBarArr = pointObj.errorBar;

                if (!errorBarArr) {
                    return;
                }

                len = errorBarArr && errorBarArr.length;
                while (len--) {
                    errorBarCompArr = errorBarArr[len];
                    errorBarCompLen = errorBarCompArr && errorBarCompArr.length;
                    while (errorBarCompLen--) {
                        if (!(errorBarCompArr[errorBarCompLen] && errorBarCompArr[errorBarCompLen]._xPos)) {
                            continue;
                        }
                        xPos = errorBarCompArr[errorBarCompLen]._xPos;
                        yPos = errorBarCompArr[errorBarCompLen]._yPos;
                        height = errorBarCompArr[errorBarCompLen]._height;
                        width = errorBarCompArr[errorBarCompLen]._width;
                        toolText = errorBarCompArr[errorBarCompLen]._toolText;

                        hovered = chartX >= xPos && chartX <= xPos + width &&
                            chartY >= yPos && chartY <= yPos + height;

                        if (hovered) {
                            return {
                                pointIndex: pX,
                                hovered: hovered,
                                pointObj: dataStore[pX],
                                toolText : toolText
                            };
                        }

                    }
                }
            },
            //Helper function of _getHoverPlot()
            _checkPointerOverPlot : function (pX, chartX, chartY) {
                var dataSet = this,
                    dataStore = dataSet.components.data,
                    data = dataStore[pX],
                    config = data && data.config,
                    hoverInfo;

                if (!data) {
                    return;
                }

                hoverInfo = dataSet._checkPointerOverErrorBar(pX, chartX, chartY);
                if (hoverInfo) {
                    data.errorBarHovered = true;
                    config.finalTooltext = hoverInfo.toolText;
                } else {
                    hoverInfo = dataSet._checkPointerOverColumn(pX, chartX, chartY);
                    data.errorBarHovered = false;

                    hoverInfo && (config.finalTooltext = (config.toolText !== false) &&
                                                (config.toolText + config.toolTipValue));
                }

                return hoverInfo;
            },
            /**
             * Function that retunr the nearest plot details
             * @param {number} x x-axis position of the mouse cordinate
             * @param {number} y y-axis position of the mouse cordinate
             * @returns {object} return an object with details of nearest polt and whether it is hovered or not
             */
            _getHoveredPlot: function (chartX, chartY) {
                var dataset = this,
                    chart = dataset.chart,
                    chartConfig = chart.config,
                    xAxis = chart.components.xAxis[0],
                    x,
                    canvas = chart.components.canvas,
                    canvasConfig = canvas.config,
                    canvasPadding = Math.max(canvasConfig.canvasPaddingLeft, canvasConfig.canvasPadding),
                    canvasLeft = chartConfig.canvasLeft,
                    pX;

                x = xAxis.getValue(chartX - canvasLeft - canvasPadding);
                pX = Math.round(x);

                // Checking for overlap between two cosecutive column plots along x-axis
                return (pX - x > 0 ? dataset._checkPointerOverPlot(pX, chartX, chartY) ||
                    dataset._checkPointerOverPlot(pX - 1, chartX, chartY) :
                        dataset._checkPointerOverPlot(pX + 1, chartX, chartY) ||
                            dataset._checkPointerOverPlot(pX, chartX, chartY));
            },
            // Function to remove a data from a dataset during real time update.
            remove : function () {
                var dataSet = this,
                    components = dataSet.components,
                    removeDataArr = components.removeDataArr,
                    pool = components.pool || (components.pool = {
                        element :[],
                        hotElement : [],
                        label : []
                    }),
                    len = removeDataArr.length,
                    removeData,
                    maxminFlag = dataSet.maxminFlag,
                    graphics,
                    i,
                    k;

                for (i = 0; i < len; i++) {
                    removeData = removeDataArr[0];
                    removeDataArr.splice(0,1);
                    // In case of non existing data plot continue;
                    if (!removeData || !removeData.graphics) {
                        continue;
                    }

                    graphics = removeData.graphics;

                    graphics.element && graphics.element.hide() && graphics.element.shadow({opacity: 0});
                    for (k = 0; k < 4; k++) {
                        graphics.error && graphics.error[k] && graphics.error[k].hide() &&
                        graphics.error[k].shadow({opacity: 0});
                    }
                    graphics.hotElement && graphics.hotElement.hide() && graphics.hotElement.attr({width : 0});

                    // Storing the graphic elements for reuse.
                    removeData.graphics.element && (pool.element = pool.element.concat(removeData.graphics.element));
                    removeData.graphics.hotElement && (pool.hotElement = pool.hotElement.concat(removeData.graphics.
                        hotElement));
                    removeData.graphics.label && (pool.label = pool.label.concat(removeData.graphics.label));
                }
                components.pool = pool;
                maxminFlag && dataSet.setMaxMin();
            }

        },'Column']);

    }
]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-errorline',
    function () {
        var global = this,
            lib = global.hcLib,
            //strings
            preDefStr = lib.preDefStr,
            colorStrings = preDefStr.colors,
            COLOR_AAAAAA = colorStrings.AAAAAA,

            configStr = preDefStr.configStr,
            animationObjStr = preDefStr.animationObjStr,
            errorBarStr = preDefStr.errorBarStr,
            errorShadowStr = preDefStr.errorShadowStr,
            ROUND = preDefStr.ROUND,
            PERCENTAGESTRING = preDefStr.PERCENTAGESTRING,

            LINE = preDefStr.line,
            BLANKSTRING = lib.BLANKSTRING,
            parseTooltext = lib.parseTooltext,
            //add the tools thats are requared
            pluck = lib.pluck,
            getValidValue = lib.getValidValue,
            pluckNumber = lib.pluckNumber,
            getFirstValue = lib.getFirstValue,
            // getDefinedColor = lib.getDefinedColor,
            isIE = lib.isIE,
            UNDEFINED,
            COMMASPACE = lib.COMMASPACE,
            POINTER = 'pointer',
            COMPONENT = 'component',
            DATASET = 'dataset',

            TRACKER_FILL = 'rgba(192,192,192,' + (isIE ? 0.002 : 0.000001) + ')', // invisible but clickable
            TOUCH_THRESHOLD_PIXELS = lib.TOUCH_THRESHOLD_PIXELS,
            CLICK_THRESHOLD_PIXELS = lib.CLICK_THRESHOLD_PIXELS,
            M = 'M',
            H = 'H',
            V = 'V',
            math = Math,
            mathRound = math.round,
            mathMin = math.min,
            mathMax = math.max,
            mathAbs = math.abs,
            hasTouch = lib.hasTouch,
            // hot/tracker threshold in pixels
            HTP = hasTouch ? TOUCH_THRESHOLD_PIXELS :
                CLICK_THRESHOLD_PIXELS,
            // getColumnColor = lib.graphics.getColumnColor,
            getFirstColor = lib.getFirstColor,
            // pluckColor = lib.pluckColor,
            getFirstAlpha = lib.getFirstAlpha,
            convertColor = lib.graphics.convertColor,
            // POSITION_CENTER = lib.POSITION_CENTER,
            // INT_ZERO = 0,
            // renderer = chartAPI,
            HUNDREDSTRING = lib.HUNDREDSTRING;

        FusionCharts.register(COMPONENT, [DATASET, 'ErrorLine', {
            type: LINE,

             /*
             * Parses all the attributes for dataset level and set level
             * Called from init function of area class and line class
             * Both line and area attributes configuration is done here
             */

            ErrorValueConfigure: function() {
                var dataSet = this,
                    chart = dataSet.chart,
                    conf = dataSet.config,
                    chartConfig = chart.config,
                    parentYAxis = conf.parentYAxis,
                    JSONData = dataSet.JSONData,
                    setDataArr = JSONData.data,
                    chartAttr = chart.jsonData.chart,
                    xAxis = chart.components.xAxis[0],
                    len = xAxis.getCategoryLen(),
                    parseUnsafeString = lib.parseUnsafeString,
                    setData,
                    dataObj,
                    config,
                    dataStore = dataSet.components.data,
                    numberFormatter = chart.components.numberFormatter,
                    toolTipValue,
                    errorBarAlpha,
                    errorBarThickness,
                    setErrorValue,
                    formatedVal,
                    setTooltext,
                    positiveCumulativeErrorTooltext,
                    negativeCumulativeErrorTooltext,
                    positiveErrorToolText,
                    negativeErrorToolText,
                    errorBarShadow,
                    lineThickness = conf.linethickness,
                    maxValue = -Infinity,
                    minValue = Infinity,
                    halfErrorBar,
                    maxErrorValue,
                    minErrorValue,
                    setValue,
                    errorValue,
                    notHalfErrorBar,
                    yAxisName = parseUnsafeString(chartAttr.yaxisname),
                    xAxisName = parseUnsafeString(chartAttr.xaxisname),
                    cumulativeValueOnErrorBar,
                    tooltipSepChar = pluck(chartAttr.tooltipsepchar, COMMASPACE),
                    macroIndices,
                    parserConfig,
                    seriesname,
                    errorInPercent,
                    errorDataValue,
                    errorPercentValue,
                    errorToolText,
                    seriesNameInTooltip = pluckNumber(chartAttr.seriesnameintooltip, 1),
                    getTooltext = function(setTooltext) {
                        var toolText;

                        if (!chartConfig.showtooltip) {
                            toolText = false;
                        }
                        else {
                            if (formatedVal === null) {
                                toolText = false;
                            }
                            else if (setTooltext !== undefined) {
                                macroIndices = [1,2,3,4,5,6,7,99,100,101,102];
                                parserConfig = {
                                    yaxisName: yAxisName,
                                    xaxisName: xAxisName ,
                                    formattedValue : config.toolTipValue,
                                    errorValue: setErrorValue,
                                    errorDataValue: config.errorToolTipValue,
                                    errorPercentValue: config.errorPercentValue,
                                    errorPercentDataValue: config.errorPercentValue,
                                    label : config.label
                                };
                                toolText = parseTooltext(setTooltext, macroIndices,
                                    parserConfig, setData, chartAttr, JSONData);
                            }
                            else {
                                if (seriesNameInTooltip) {
                                    seriesname = getFirstValue(JSONData && JSONData.seriesname);
                                }
                                toolText = seriesname ? seriesname + tooltipSepChar : BLANKSTRING;
                                toolText += config.label ? config.label + tooltipSepChar : BLANKSTRING;
                            }
                        }
                        return toolText;
                    },
                    i;

                conf.errorBarShadow = errorBarShadow = pluckNumber(chartAttr.errorbarshadow, chartAttr.showshadow, 1);
                conf.ignoreEmptyDatasets = pluckNumber(JSONData.ignoreemptydatasets, 0);
                halfErrorBar = pluckNumber(chartAttr.halferrorbar, 1);
                conf.notHalfErrorBar = notHalfErrorBar = !pluckNumber(chartAttr.halferrorbar, 1);

                errorBarAlpha = getFirstAlpha(pluck(
                        JSONData.errorbaralpha, chartAttr.errorbaralpha,  conf.alpha));
                conf.errorBarWidth = pluckNumber(JSONData.errorbarwidth,
                    chartAttr.errorbarwidth, 5);
                conf.errorBarColor = convertColor(getFirstColor(
                    pluck(JSONData.errorbarcolor, chartAttr.errorbarcolor,
                        COLOR_AAAAAA)), errorBarAlpha);
                errorBarThickness = pluckNumber(
                    JSONData.errorbarthickness, chartAttr.errorbarthickness, 1);
                conf.errorBarThickness = errorBarThickness > lineThickness ? lineThickness
                    : errorBarThickness;
                conf.shadowOpacity = errorBarShadow ? (errorBarAlpha / 250) : 0;

                conf.errorInPercent = errorInPercent = pluckNumber(JSONData.errorinpercent, chartAttr.errorinpercent);

                conf.cumulativeValueOnErrorBar =
                    pluckNumber(JSONData.cumulativevalueonerrorbar, chartAttr.cumulativevalueonerrorbar, 1);

                for (i = 0; i < len; i++) {

                    setData = setDataArr && setDataArr[i];

                    if (!setDataArr || !setData) {
                        continue;
                    }

                    dataObj = dataStore[i];
                    config = dataObj && dataObj.config;

                    if (!dataObj) {
                        dataObj = dataStore[i] = {
                            graphics : {}
                        };
                    }

                    if (!dataObj.config) {
                        config = dataStore[i].config = {};

                    }

                    setValue = config.setValue;

                    config.notHalfErrorBar = conf.notHalfErrorBar;
                    setErrorValue = numberFormatter.getCleanValue(setData.errorvalue);
                    config.errorToolTipValue = errorDataValue = numberFormatter.dataLabels(setErrorValue, parentYAxis);
                    errorPercentValue = (mathRound(((setErrorValue / setValue) * HUNDREDSTRING) * HUNDREDSTRING) /
                        HUNDREDSTRING) + PERCENTAGESTRING;
                    config.setErrorValue = config.errorValue = errorValue = setErrorValue;
                    config.hasErrorValue = pluckNumber(setData.errorvalue) !== UNDEFINED ? 1 : 0;

                    toolTipValue = config.errorToolTipValue;

                    formatedVal = toolTipValue;

                    // Parsing tooltext against various configurations provided by the user.
                    setTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
                        JSONData.errorplottooltext, chartAttr.errorplottooltext, formatedVal)));

                    errorToolText = getTooltext(setTooltext);

                    config.errorInPercent = pluckNumber(setData.errorinpercent, errorInPercent, 0);

                    config.errorInPercent &&
                    (config.setErrorValue = setErrorValue = pluckNumber(((setErrorValue / 100) * setValue).toFixed(2)));


                    config.cumulativeValueOnErrorBar = cumulativeValueOnErrorBar =
                        pluckNumber(setData.cumulativevalueonerrorbar, conf.cumulativeValueOnErrorBar, 1);

                    config.positiveErrorValue =
                        numberFormatter.getCleanValue(pluckNumber(setData.positiveerrorvalue, setData.errorvalue));

                    (config.errorInPercent && config.positiveErrorValue) &&
                    (config.positiveErrorValue = pluckNumber(((config.positiveErrorValue / 100) *
                        setValue).toFixed(2)));

                    config.positiveCumulativeErrorValue = setValue +
                        pluckNumber(config.positiveErrorValue, config.setErrorValue);

                    config.negativeErrorValue =
                        numberFormatter.getCleanValue(pluckNumber(setData.negativeerrorvalue, setData.errorvalue));

                    (config.errorInPercent && config.negativeErrorValue) &&
                    (config.negativeErrorValue = pluckNumber(((config.negativeErrorValue / 100) *
                        setValue).toFixed(2)));

                    config.negativeCumulativeErrorValue = setValue -
                        pluckNumber(config.negativeErrorValue, config.setErrorValue);

                    config.errorToolTipValue = errorDataValue = numberFormatter.dataLabels(setErrorValue, parentYAxis);

                    config.negativeErrorToolTipValue =
                        numberFormatter.dataLabels(config.negativeErrorValue, parentYAxis);

                    config.negativeCumulativeErrorTooltipValue =
                        numberFormatter.dataLabels(config.negativeCumulativeErrorValue, parentYAxis);

                    config.positiveErrorToolTipValue =
                        numberFormatter.dataLabels(config.positiveErrorValue, parentYAxis);

                    config.positiveCumulativeErrorTooltipValue =
                        numberFormatter.dataLabels(config.positiveCumulativeErrorValue, parentYAxis);

                    config.errorPercentValue = errorPercentValue =
                        (mathRound(((setErrorValue / setValue) * HUNDREDSTRING) * HUNDREDSTRING) /
                        HUNDREDSTRING) + PERCENTAGESTRING;

                    positiveErrorToolText = negativeErrorToolText = undefined;
                    setTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
                        JSONData.errorplottooltext, chartAttr.errorplottooltext,
                        config.positiveErrorToolTipValue)));

                    (setTooltext && config.positiveErrorToolTipValue) &&
                        (positiveErrorToolText = getTooltext(setTooltext));

                    setTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
                        JSONData.errorplottooltext, chartAttr.errorplottooltext,
                        config.negativeErrorToolTipValue)));

                    (setTooltext && config.negativeErrorToolTipValue) &&
                        (negativeErrorToolText = getTooltext(setTooltext));

                    if (setData.positiveerrorvalue || setData.negativeerrorvalue) {
                        config.halfErrorBar = 0;
                        config.notHalfErrorBar = true;
                    }

                    if (cumulativeValueOnErrorBar) {
                        setTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
                            JSONData.errorplottooltext, chartAttr.errorplottooltext,
                                config.positiveCumulativeErrorTooltipValue)));

                        (setTooltext && config.positiveCumulativeErrorTooltipValue) &&
                            (positiveCumulativeErrorTooltext = getTooltext(setTooltext));

                        setTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
                            JSONData.errorplottooltext, chartAttr.errorplottooltext,
                                config.negativeCumulativeErrorTooltipValue)));

                        (setTooltext && config.negativeCumulativeErrorTooltipValue) &&
                            (negativeCumulativeErrorTooltext = getTooltext(setTooltext));
                    }
                    maxErrorValue = setValue + (config.positiveErrorValue !== null ?
                        config.positiveErrorValue : setErrorValue);
                    minErrorValue = setValue - (config.halfErrorBar ? 0 :
                        ((config.negativeErrorValue < 0 && setValue < 0) ? 0 :
                            (config.negativeErrorValue != null ? config.negativeErrorValue : setErrorValue)));

                    maxValue = mathMax(maxValue, maxErrorValue, minErrorValue);
                    minValue = mathMin(minValue, maxErrorValue, minErrorValue);

                    (setErrorValue == null) && (setErrorValue = undefined);

                    config.errorValueArr = [];
                    (config.positiveErrorValue === null) && (config.positiveErrorValue = undefined);
                    errorValue = -config.positiveErrorValue;
                    config.errorValueArr.push({
                        errorValue: errorValue,
                        tooltext: cumulativeValueOnErrorBar ? positiveCumulativeErrorTooltext :
                            positiveErrorToolText || errorToolText,
                        errorEdgeBar : true
                    });

                    config.errorValueArr.push({
                        errorValue: errorValue,
                        tooltext: positiveErrorToolText || errorToolText
                    });

                    if (config.notHalfErrorBar) {
                        errorValue = config.negativeErrorValue;
                        config.errorValueArr.push({
                            errorValue: errorValue,
                            tooltext: cumulativeValueOnErrorBar ? negativeCumulativeErrorTooltext :
                                negativeErrorToolText || errorToolText,
                            errorEdgeBar : true
                        });
                        config.errorValueArr.push({
                            errorValue: errorValue,
                            tooltext: negativeErrorToolText || errorToolText
                        });
                    }

                    config.toolText = getTooltext(config.setTooltext); //toolText;
                }
                conf.maxValue = maxValue;
                conf.minValue = minValue;
            },
            /*
             * Initialization of line dataset
             * @param {object} chart - chart object of fusioncharts
             * @param {number} datasetIndex - index of line dataset
             * @param {boolean} isLineSet - Whether it is a lineset or a dataset
             * Called from draw graph of line
             */
            init: function (datasetJSON) {
                var dataSet = this,
                    chart = dataSet.chart,
                    components = chart.components,
                    isDual = chart.isDual,
                    yAxis;
                dataSet.chart = chart;
                yAxis = isDual ? components.yAxis[dataSet.yAxis ||  0] : components.yAxis[0];
                dataSet.yAxis = yAxis;
                dataSet.components = {

                };

                dataSet.graphics = {

                };
                dataSet.JSONData = datasetJSON;
                dataSet.visible = pluckNumber(dataSet.JSONData.visible,
                    !Number(dataSet.JSONData.initiallyhidden), 1) === 1;
                dataSet.configure();

            },

            /*
             * Makes a dataset visible when clicked on its respective legend
             * Fired every time a deactivated legend is clicked
             */
            show : function() {
                var dataSet = this,
                    chart = dataSet.chart,
                    yAxis = dataSet.yAxis,
                    container = dataSet.graphics && dataSet.graphics.container,
                    dataLabelContainer = dataSet.graphics && dataSet.graphics.dataLabelContainer,
                    errorGroupContainer = dataSet.graphics && dataSet.graphics.errorGroupContainer,
                    errorShadowContainer = dataSet.graphics && dataSet.graphics.errorShadowContainer;

                chart._chartAnimation();
                container.lineGroup.show();
                container.anchorGroup.show();
                container.anchorShadowGroup.show();
                container.lineShadowGroup.show();
                dataLabelContainer.show();
                dataSet.visible = true;
                errorGroupContainer && errorGroupContainer.show();
                errorShadowContainer && errorShadowContainer.show();
                dataSet._conatinerHidden = false;

                chart._setAxisLimits();
                yAxis.draw();
                // Calling the draw function for redrawing the dataset
                chart._drawDataset();
            },

            /*
             * Hides when clicked on its respective legend
             * Fired every time an activated legend is clicked
             */
            hide : function() {
                var dataSet = this,
                    chart = dataSet.chart,
                    yAxis = dataSet.yAxis;

                chart._chartAnimation();
                dataSet.visible = false;

                chart._setAxisLimits();
                yAxis.draw();
                chart._drawDataset();
            },

            drawErrorValue: function() {
                var dataSet = this,
                    JSONData = dataSet.JSONData,
                    // fcJSON = dataSet.fcJSON,
                    conf = dataSet.config,
                    chart = dataSet.chart,
                    parentContainer = chart.graphics.datasetGroup,
                    chartComponents = chart.components,
                    setDataArr = JSONData.data,
                    xAxis = chartComponents.xAxis[0],
                    len = xAxis.getCategoryLen(),
                    setData,
                    attr,
                    i,
                    j,
                    k,
                    visible = dataSet.visible,
                    paper = chartComponents.paper,
                    yAxis = dataSet.yAxis,
                    dataStore = dataSet.components.data,

                    animationObj = chart.get(configStr, animationObjStr),
                    animType = animationObj.animType,
                    animObj = animationObj.animObj,
                    dummyObj = animationObj.dummyObj,
                    animationDuration = animationObj.duration,

                    errorBarThickness = conf.errorBarThickness,
                    errorBarWidth = conf.errorBarWidth,
                    errorBarColor = conf.errorBarColor,
                    showTooltip = chart.config.showtooltip,
                    shadowOpacity = conf.shadowOpacity,

                    lineGroup = dataSet.graphics.container.lineGroup,
                    errorGroupContainer = dataSet.graphics.errorGroupContainer,
                    errorShadowContainer = dataSet.graphics.errorShadowContainer,
                    setLink,
                    tooltext,
                    xPos,
                    yPos,
                    useCrispErrorPath = /*!chartLogic.avoidCrispError*/1,
                    dataObj,
                    setValue,
                    // groupId,
                    config,
                    // eventArgs,
                    crispY,
                    crispX,
                    errorPath,
                    errorValPos,
                    errorValuePosFactor,
                    errorValueArr,
                    errorValueObj,
                    errorValue,
                    errorStartPos,
                    errorLen,
                    halfErrorBarW,
                    errorLineElem,
                    errorTrackerElem,
                    errorValueElem,
                    plotXpos,
                    trackerTolerance = errorBarThickness > 5 ? (errorBarThickness / 2) : 2.5,
                    plotYpos,
                    errorTrackerConfig;

                if (!errorGroupContainer) {
                    errorGroupContainer = dataSet.graphics.errorGroupContainer =
                     paper.group(errorBarStr, parentContainer).insertAfter(lineGroup);
                    /*if (!errorGroupContainer.attrs['clip-rect']) {
                        errorGroupContainer.attr({
                            'clip-rect': elements['clip-canvas']
                        });
                    }*/
                    if (!visible) {
                        errorGroupContainer.hide();
                    }
                }

                if (!errorShadowContainer) {
                    // Always sending the shadow group to the back of the plots group.
                    errorShadowContainer = dataSet.graphics.errorShadowContainer =
                        paper.group(errorShadowStr, parentContainer).insertBefore(errorGroupContainer);
                    /*if (!errorShadowContainer.attrs['clip-rect']) {
                        errorShadowContainer.attr({
                            'clip-rect': elements['clip-canvas']
                        });
                    }*/
                    if (!visible) {
                        errorShadowContainer.hide();
                    }
                }

                // Loop through each data points
                for (i = 0; i < len; i++) {
                    setData = setDataArr && setDataArr[i];
                    dataObj = dataStore[i];
                    errorTrackerConfig = dataObj.errorTrackerConfig = {};
                    errorTrackerConfig.errorTrackerArr = [];
                    config = dataObj && dataObj.config;
                    setValue = config && config.setValue;

                    // If plot value is found "null", continue the loop to next iteration.
                    if (dataObj === undefined || setValue === undefined || setValue === null) {

                        if (dataObj.graphics.error) {
                            for (j = 0; j < dataObj.graphics.error.length; j++) {
                                dataObj.graphics.error[j].hide();
                                dataObj.graphics.errorTracker[j].hide();
                                dataObj.graphics.error[j].shadow(false);
                            }
                        }
                        continue;
                    }

                    errorValueArr = config.errorValueArr;
                    errorTrackerConfig.errorLen = errorLen = errorValueArr.length;

                    !dataObj.graphics.error && (dataObj.graphics.error = []);
                    !dataObj.graphics.errorTracker && (dataObj.graphics.errorTracker = []);

                    if ((config.errorValue === BLANKSTRING || config.errorValue === undefined ||
                        (config.errorValue === null && config.positiveErrorValue === null &&
                        config.negativeErrorValue === null))) {

                        for (k = 0; k < errorLen; k++) {
                            if (dataObj.graphics.error && dataObj.graphics.error[k]) {
                                dataObj.graphics.error[k].hide();
                                dataObj.graphics.error[k].shadow({opacity: 0});
                            }
                        }
                        continue;
                    }
                    setLink  = config.setLink;

                    plotXpos = dataObj._xPos;
                    plotYpos = dataObj._yPos;

                    yPos = plotYpos;
                    xPos = plotXpos;

                    dataObj.errorBar && (delete dataObj.errorBar);
                    dataObj.errorBar = [];
                    //Loop through errorValue array
                    while (errorLen--) {
                        errorTrackerElem = errorLineElem = errorValueElem =
                            null;
                        errorTrackerConfig.errorTrackerArr[errorLen] = {};
                        errorValueObj = errorValueArr[errorLen];
                        errorTrackerConfig.errorTrackerArr[errorLen].tooltext = tooltext = errorValueObj.tooltext;
                        errorStartPos = yPos;
                        errorValue = errorValueObj.errorValue;
                        if (errorValue === null || isNaN(errorValue)) {
                            if (dataObj.graphics.error && dataObj.graphics.error[errorLen]) {
                                dataObj.graphics.error[errorLen].hide();
                                dataObj.graphics.error[errorLen].shadow({opacity: 0});
                            }
                            continue;
                        }
                        halfErrorBarW = errorBarWidth / 2;

                        errorValuePosFactor = (!visible) ? 0 : 1;
                        // Vertical Error drawing
                        errorValPos = plotYpos +
                            ((yAxis.getAxisPosition(0) - yAxis.getAxisPosition(1)) * errorValue * errorValuePosFactor);
                        crispY = errorValPos;
                        crispX = xPos;
                        if (useCrispErrorPath) {
                            crispY = mathRound(errorValPos) +
                                (errorBarThickness % 2 / 2);
                            crispX = mathRound(xPos) +
                                (errorBarThickness % 2 / 2);
                        }

                        dataObj.errorBar[errorLen] || (dataObj.errorBar[errorLen] = []);
                        if (!errorValueObj.errorEdgeBar) {
                            errorPath = [
                                M, crispX, errorStartPos,
                                V, crispY
                            ];
                            dataObj.errorBar[errorLen][0] = {
                                _xPos: crispX - trackerTolerance,
                                _yPos: crispY < errorStartPos ? crispY : errorStartPos,
                                _height: mathAbs(errorStartPos - crispY),
                                _width: 2 * trackerTolerance,
                                _toolText : errorValueObj.tooltext
                            };
                        } else {
                            errorPath = [
                                M, crispX - halfErrorBarW, crispY,
                                H, (crispX + halfErrorBarW)
                            ];
                            dataObj.errorBar[errorLen][1] = {
                                _xPos: crispX - halfErrorBarW - trackerTolerance,
                                _yPos: crispY - trackerTolerance,
                                _height: 2 * trackerTolerance,
                                _width: 2 * (halfErrorBarW + trackerTolerance),
                                _toolText : errorValueObj.tooltext
                            };
                        }

                        if (!dataObj.graphics.error[errorLen]) {
                            errorLineElem = dataObj.graphics.error[errorLen] =
                             paper.path(errorPath, errorGroupContainer)
                                .attr({
                                    stroke: errorBarColor,
                                    // In case of tooltip disabled this element should act as the hot element.
                                    ishot: !showTooltip,
                                    'stroke-width': errorBarThickness,
                                    'cursor': setLink ? POINTER : BLANKSTRING,
                                    'stroke-linecap': ROUND
                                });
                        }
                        else {
                            attr = {
                                path: errorPath
                            };

                            errorLineElem = dataObj.graphics.error[errorLen];

                            errorLineElem.animateWith(dummyObj, animObj, attr, animationDuration, animType);

                            errorLineElem.attr({
                                stroke: errorBarColor,
                                // In case of tooltip disabled this element should act as the hot element.
                                ishot: !showTooltip,
                                'stroke-width': errorBarThickness,
                                'cursor': setLink ? POINTER : BLANKSTRING,
                                'stroke-linecap': ROUND
                            });
                        }

                        errorLineElem.show();

                        errorLineElem
                            .shadow({opacity : shadowOpacity}, errorShadowContainer);

                        errorTrackerConfig.errorTrackerArr[errorLen].attr = {
                            path: errorPath,
                            stroke: TRACKER_FILL,
                            'stroke-width': (errorBarThickness < HTP) ? HTP : errorBarThickness,
                            'cursor': setLink ? POINTER : BLANKSTRING,
                            'ishot': !! setLink
                        };

                    }
                    if (!config.notHalfErrorBar) {
                        for (k = 2; k < 4; k++) {
                            dataObj.graphics.error && dataObj.graphics.error[k] && dataObj.graphics.error[k].hide() &&
                            dataObj.graphics.error[k].shadow({opacity: 0});
                        }
                    }
                }
            },
            _rolloverResponseSetter : FusionCharts.get(COMPONENT, [DATASET, 'ErrorBar2D'])
                                        .prototype._rolloverResponseSetter,
            _rolloutResponseSetter : FusionCharts.get(COMPONENT, [DATASET, 'ErrorBar2D'])
                                        .prototype._rolloutResponseSetter,
            _firePlotEvent : FusionCharts.get(COMPONENT, [DATASET, 'ErrorBar2D'])
                                        .prototype._firePlotEvent,
            _checkPointerOverErrorBar : FusionCharts.get(COMPONENT, [DATASET, 'ErrorBar2D'])
                                        .prototype._checkPointerOverErrorBar,

            //Helper function of _getHoverPlot()
            _checkPointerOverPlot : function (pX, chartX, chartY) {
                var dataSet = this,
                    dataStore = dataSet.components.data,
                    data = dataStore[pX],
                    config = data && data.config,
                    hoverInfo;
                if (!data) {
                    return;
                }


                hoverInfo = dataSet.isWithinShape(data, pX, chartX, chartY);

                if (hoverInfo) {
                    data.errorBarHovered = false;
                    config.finalTooltext = (config.toolText !== false) &&
                                            (config.toolText + config.toolTipValue);
                } else {
                    hoverInfo = dataSet._checkPointerOverErrorBar(pX, chartX, chartY);
                    if(hoverInfo) {
                        data.errorBarHovered = true;
                        config.finalTooltext = hoverInfo.toolText;
                    }
                }

                return hoverInfo;
            },
            _getHoveredPlot : FusionCharts.get(COMPONENT, [DATASET, 'ErrorBar2D'])
                                        .prototype._getHoveredPlot,
            /*
             * This functions calculate the space required for a dataset and return that to the chart
             *
             */
            manageSpace: function () {
                var dataset = this,
                conf = dataset.config,
                halfErrorBarW = conf.errorBarWidth * 0.5,
                components = dataset.components || {},
                chart = dataset.chart,
                dataLabelStyle = chart.config.dataLabelStyle,
                data = components.data || [],
                firstData = data[0],
                lastData = data[data.length - 1],
                dataConf,
                label,
                dataAnchorConf,
                labelDim = {},
                padding,
                labelSpace,
                showValue,
                SmartLabel = chart.linkedItems.smartLabel,
                retrunDimension = {
                    paddingLeft: 0,
                    paddingRight: 0
                };


                // @todo also calculate the space for the labels

                if (firstData) {
                    dataConf = firstData.config;
                    showValue = dataConf.showValue;
                    dataAnchorConf = dataConf && dataConf.anchorProps || {};
                    if (showValue) {
                        label = dataConf.displayValue;
                        SmartLabel.useEllipsesOnOverflow(chart.config.useEllipsesWhenOverflow);
                        SmartLabel.setStyle(dataLabelStyle);
                        labelDim = SmartLabel.getOriSize(label);
                    }
                    if (dataConf.setValue) {
                        padding = mathMax(pluckNumber(dataAnchorConf.radius, 0), halfErrorBarW) +
                        pluckNumber(dataAnchorConf.borderThickness, 0);
                        labelSpace = (labelDim.width || 0)/2;
                    }

                    retrunDimension.paddingLeft = mathMax(padding, labelSpace);
                }

                if (lastData) {
                    dataConf = lastData.config;
                    showValue = dataConf.showValue;
                    dataAnchorConf = dataConf && dataConf.anchorProps || {};
                    if (showValue) {
                        label = dataConf.displayValue;
                        SmartLabel.setStyle(dataLabelStyle);
                        labelDim = SmartLabel.getOriSize(label);
                    }
                    if (dataConf.setValue) {
                        padding = mathMax(pluckNumber(dataAnchorConf.radius, 0), halfErrorBarW) +
                            pluckNumber(dataAnchorConf.borderThickness, 0);
                        labelSpace = (labelDim.width || 0)/2;
                    }

                    retrunDimension.paddingRight = mathMax(padding, labelSpace);
                }

                return retrunDimension;
            },

            _removeDataVisuals : function (dataObj) {
                var graphics,
                    k;
                if (!dataObj) {
                    return;
                }
                graphics = dataObj.graphics;
                graphics.element && graphics.element.hide() && graphics.element.shadow({opacity: 0});

                for (k = 0; k < 4; k++) {
                    dataObj.graphics.error && dataObj.graphics.error[k] && dataObj.graphics.error[k].hide() &&
                    dataObj.graphics.error[k].shadow({opacity: 0});
                }
                graphics.hotElement && graphics.hotElement.hide() && graphics.hotElement.attr({width : 0});
            }

        },LINE]);

    }
]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-errorscatter',
    function () {
        var global = this,
            lib = global.hcLib,

            //strings
            preDefStr = lib.preDefStr,
            colorStrings = preDefStr.colors,
            COLOR_AAAAAA = colorStrings.AAAAAA,

            configStr = preDefStr.configStr,
            animationObjStr = preDefStr.animationObjStr,
            errorBarStr = preDefStr.errorBarStr,
            errorShadowStr = preDefStr.errorShadowStr,
            ROUND = preDefStr.ROUND,
            PERCENTAGESTRING = preDefStr.PERCENTAGESTRING,
            BLANK = lib.BLANKSTRING,
            BLANKSTRING = lib.BLANKSTRING,
            parseTooltext = lib.parseTooltext,
            //add the tools thats are requared
            pluck = lib.pluck,
            getValidValue = lib.getValidValue,
            pluckNumber = lib.pluckNumber,
            isIE = lib.isIE,
            UNDEFINED,
            COMMASPACE = lib.COMMASPACE,
            POINTER = 'pointer',
            COMPONENT = 'component',
            DATASET = 'dataset',
            TRACKER_FILL = 'rgba(192,192,192,' + (isIE ? 0.002 : 0.000001) + ')', // invisible but clickable
            TOUCH_THRESHOLD_PIXELS = lib.TOUCH_THRESHOLD_PIXELS,
            CLICK_THRESHOLD_PIXELS = lib.CLICK_THRESHOLD_PIXELS,
            M = 'M',
            H = 'H',
            V = 'V',
            math = Math,
            mathRound = math.round,
            mathMin = math.min,
            mathMax = math.max,
            mathAbs = math.abs,
            hasTouch = lib.hasTouch,
            // hot/tracker threshold in pixels
            HTP = hasTouch ? TOUCH_THRESHOLD_PIXELS :
                CLICK_THRESHOLD_PIXELS,
            // getColumnColor = lib.graphics.getColumnColor,
            getFirstColor = lib.getFirstColor,
            // pluckColor = lib.pluckColor,
            getFirstAlpha = lib.getFirstAlpha,
            convertColor = lib.graphics.convertColor,
            HUNDREDSTRING = lib.HUNDREDSTRING;

        FusionCharts.register(COMPONENT, [DATASET, 'ErrorScatter', {

            ErrorValueConfigure: function() {
                var dataSet = this,
                    chart = dataSet.chart,
                    chartComponents = chart.components,
                    conf = dataSet.config,
                    JSONData = dataSet.JSONData,
                    categories = chart.config.categories,
                    chartAttr = chart.jsonData.chart,
                    setDataArr = JSONData.data,
                    xAxis = chartComponents.xAxis[0],
                    catLen = xAxis.getCategoryLen(),
                    setDataLen = (setDataArr && setDataArr.length) || catLen,
                    parseUnsafeString = lib.parseUnsafeString,
                    setData,
                    dataObj,
                    config,
                    dataStore = dataSet.components.data,
                    numberFormatter = chartComponents.numberFormatter,
                    errorBarAlpha,
                    errorBarThickness,
                    setErrorValue,
                    errorBarShadow,
                    errorBarWidth,
                    errorBarColor,
                    halfHorizontalErrorBar,
                    halfVerticalErrorBar,
                    horizontalErrorBarAlpha,
                    verticalErrorBarAlpha,
                    horizontalErrorBarColor,
                    verticalErrorBarColor,
                    horizontalErrorBarThickness,
                    verticalErrorBarThickness,
                    hErrorValue,
                    vErrorValue,
                    hErrorToolTipValue,
                    vErrorToolTipValue,
                    useHorizontalErrorBar,
                    useVerticalErrorBar,
                    tooltipSepChar = pluck(chartAttr.tooltipsepchar, COMMASPACE),
                    yAxisName = parseUnsafeString(chartAttr.yaxisname),
                    xAxisName = parseUnsafeString(chartAttr.xaxisname),

                    parentYAxis = conf.parentYAxis,
                    setValue,
                    errorPercentValue,
                    formatedVal,
                    toolText,
                    horizontalErrorPercent,
                    verticalErrorPercent,
                    macroIndices,
                    parserConfig,
                    seriesname,
                    infMin = -Infinity,
                    infMax = +Infinity,
                    maxErrorValue,
                    minErrorValue,
                    vPositiveErrorValue,
                    hNegativeErrorValue,
                    hPositiveErrorValue,
                    hPositiveSetTooltext,
                    hPositiveErrorToolTipValue,
                    hCPErrorToolText,
                    hCPErrorToolTipValue,
                    hNegativeErrorToolTipValue,
                    hCNErrorToolTipValue,
                    vPositiveErrorToolTipValue,
                    hNegativeSetTooltext,
                    vCPErrorToolTipValue,
                    vNegativeErrorValue,
                    vCNErrorToolText,
                    vCNErrorToolTipValue,
                    vPositiveSetTooltext,
                    hCNErrorToolText,
                    vCPErrorToolText,
                    cumulativeValueOnErrorBar,
                    vNegativeSetTooltext,
                    vNegativeErrorToolTipValue,
                    yMax = infMin,
                    yMin = infMax,
                    xMin = infMax,
                    xMax = infMin,
                    errorValue,
                    getTooltext = function(setTooltext, errorValue) {
                        var toolText;

                        if (!conf.showTooltip) {
                            toolText = false;
                        }
                        else {
                            if (formatedVal === null) {
                                toolText = false;
                            }
                            else if (setTooltext !== undefined) {
                                macroIndices = [1,2,3,4,5,6,7,8,9,10,11,99,100,101,102,103,104,105,106,107,109];
                                parserConfig = {
                                    yaxisName: yAxisName,
                                    xaxisName: xAxisName,
                                    yDataValue: formatedVal,
                                    xDataValue: config.label,
                                    formattedValue : config.toolTipValue,
                                    horizontalErrorValue: hErrorValue,
                                    horizontalErrorDataValue: hErrorToolTipValue,
                                    verticalErrorValue: vErrorValue,
                                    verticalErrorDataValue: vErrorToolTipValue,
                                    horizontalErrorPercent: horizontalErrorPercent,
                                    verticalErrorPercent: verticalErrorPercent,
                                    label : config.label,
                                    errorValue: errorValue,
                                    errorDataValue: errorValue,
                                    errorPercentValue: config.errorPercentValue,
                                    errorPercentDataValue: config.errorPercentValue
                                };
                                toolText = parseTooltext(setTooltext, macroIndices,
                                    parserConfig, setData, chartAttr, JSONData);
                            }
                            else {
                                if (formatedVal === null) {
                                    toolText = false;
                                }
                                else {
                                    if (conf.seriesNameInTooltip) {
                                        seriesname = lib.getFirstValue(JSONData && JSONData.seriesname);
                                    }
                                    toolText = seriesname ? seriesname + tooltipSepChar : BLANK;
                                    toolText += setValue.x ? numberFormatter.xAxis(setValue.x) + tooltipSepChar : BLANK;
                                    toolText += config.toolTipValue;
                                }
                            }
                        }
                        return toolText;
                    },
                    i;

                conf.errorBarShadow = errorBarShadow = pluckNumber(chartAttr.errorbarshadow, chartAttr.showshadow, 0);
                conf.ignoreEmptyDatasets = pluckNumber(JSONData.ignoreemptydatasets, 0);
                conf.notHalfErrorBar = !pluckNumber(chartAttr.halferrorbar, 1);

                conf.errorBarAlpha = getFirstAlpha(pluck(
                        JSONData.errorbaralpha, chartAttr.errorbaralpha));
                conf.errorBarWidth = errorBarWidth = pluckNumber(JSONData.errorbarwidth,
                    chartAttr.errorbarwidth, 5);
                conf.errorBarColor = errorBarColor = convertColor(getFirstColor(
                    pluck(JSONData.errorbarcolor, chartAttr.errorbarcolor,
                        COLOR_AAAAAA)), errorBarAlpha);
                conf.errorBarThickness = errorBarThickness = pluckNumber(
                    JSONData.errorbarthickness, chartAttr.errorbarthickness, 1);
                conf.shadowOpacity = errorBarShadow ? (errorBarAlpha / 250) : 0;

                conf.halfHorizontalErrorBar = halfHorizontalErrorBar =
                    pluckNumber(chartAttr.halfhorizontalerrorbar, 1);
                conf.halfVerticalErrorBar = halfVerticalErrorBar =
                    pluckNumber(chartAttr.halfverticalerrorbar, 1);

                (conf.initAnimation === UNDEFINED) && (conf.initAnimation = chart.initAnimation);

                horizontalErrorBarAlpha =
                        pluck(JSONData.horizontalerrorbaralpha,
                            JSONData.errorbaralpha,
                            chartAttr.horizontalerrorbaralpha, errorBarAlpha);

                verticalErrorBarAlpha = pluckNumber(
                        JSONData.verticalerrorbaralpha, JSONData.errorbaralpha,
                        chartAttr.verticalerrorbaralpha, errorBarAlpha);

                horizontalErrorBarColor = convertColor(pluck(
                    JSONData.horizontalerrorbarcolor, JSONData.errorbarcolor,
                    chartAttr.horizontalerrorbarcolor, errorBarColor),
                    horizontalErrorBarAlpha
                );

                verticalErrorBarColor = convertColor(pluck(
                    JSONData.verticalerrorbarcolor, JSONData.errorbarcolor,
                    chartAttr.verticalerrorbarcolor, errorBarColor),
                    verticalErrorBarAlpha
                );

                horizontalErrorBarThickness = pluckNumber(
                        JSONData.horizontalerrorbarthickness,
                        JSONData.errorbarthickness,
                        chartAttr.horizontalerrorbarthickness,
                        errorBarThickness);

                verticalErrorBarThickness = pluckNumber(
                        JSONData.verticalerrorbarthickness,
                        JSONData.errorbarthickness,
                        chartAttr.verticalerrorbarthickness,
                        errorBarThickness);

                conf.horizontalErrorBarWidth = pluckNumber(
                        JSONData.horizontalerrorbarwidth,
                        chartAttr.horizontalerrorbarwidth,
                        errorBarWidth);

                conf.verticalErrorBarWidth = pluckNumber(
                        JSONData.verticalerrorbarwidth,
                        chartAttr.verticalerrorbarwidth,
                        errorBarWidth);

                conf.cumulativeValueOnErrorBar =
                    pluckNumber(JSONData.cumulativevalueonerrorbar, chartAttr.cumulativevalueonerrorbar, 1);

                for (i = 0; i < setDataLen; i++) {

                    if (!setDataArr) {
                        continue;
                    }

                    setData = setDataArr && setDataArr[i];
                    dataObj = dataStore[i];
                    config = dataObj && dataObj.config;

                    if (!dataObj) {
                        dataObj = dataStore[i] = {
                            graphics : {}
                        };
                    }

                    if (!dataObj.config) {
                        config = dataStore[i].config = {};

                    }

                    setErrorValue = numberFormatter.getCleanValue(setData.errorvalue);

                    setValue = config.setValue;
                    config.errorValue = errorValue = setData.errorvalue;

                    config.cumulativeValueOnErrorBar = cumulativeValueOnErrorBar =
                        pluckNumber(setData.cumulativevalueonerrorbar, conf.cumulativeValueOnErrorBar, 1);

                    config.hErrorValue = hErrorValue = numberFormatter.getCleanValue(
                        pluck(setData.horizontalerrorvalue, setData.errorvalue));

                    config.vErrorValue = vErrorValue = numberFormatter.getCleanValue(
                        pluck(setData.verticalerrorvalue, setData.errorvalue));

                    config.hPositiveErrorValue = hPositiveErrorValue = numberFormatter.getCleanValue(
                        pluck(setData.horizontalpositiveerrorvalue, setData.positiveerrorvalue, hErrorValue));
                    config.hNegativeErrorValue = hNegativeErrorValue = numberFormatter.getCleanValue(
                        pluck(setData.horizontalnegativeerrorvalue, setData.negativeerrorvalue, hErrorValue));


                    config.vPositiveErrorValue = vPositiveErrorValue = numberFormatter.getCleanValue(
                        pluck(setData.verticalpositiveerrorvalue, setData.positiveerrorvalue, vErrorValue));
                    config.vNegativeErrorValue = vNegativeErrorValue = numberFormatter.getCleanValue(
                        pluck(setData.verticalnegativeerrorvalue, setData.negativeerrorvalue, vErrorValue));

                    hPositiveErrorToolTipValue =
                        numberFormatter.dataLabels(hPositiveErrorValue, parentYAxis);

                    hPositiveSetTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
                        JSONData.errorplottooltext, chartAttr.errorplottooltext, hPositiveErrorToolTipValue)));

                    hNegativeErrorToolTipValue =
                        numberFormatter.dataLabels(hNegativeErrorValue, parentYAxis);

                    hNegativeSetTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
                        JSONData.errorplottooltext, chartAttr.errorplottooltext, hNegativeErrorToolTipValue)));

                    vPositiveErrorToolTipValue =
                        numberFormatter.dataLabels(vPositiveErrorValue, parentYAxis);

                    vPositiveSetTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
                        JSONData.errorplottooltext, chartAttr.errorplottooltext, vPositiveErrorToolTipValue)));

                    vNegativeErrorToolTipValue =
                        numberFormatter.dataLabels(vNegativeErrorValue, parentYAxis);

                    vNegativeSetTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
                        JSONData.errorplottooltext, chartAttr.errorplottooltext, vNegativeErrorToolTipValue)));
                    hCPErrorToolText = hCNErrorToolText = vCPErrorToolText = vCNErrorToolText = undefined;
                    if (cumulativeValueOnErrorBar) {
                        hCPErrorToolTipValue =
                            numberFormatter.dataLabels(setValue.x + hPositiveErrorValue, parentYAxis);
                        hCPErrorToolText = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
                            JSONData.errorplottooltext, chartAttr.errorplottooltext, hCPErrorToolTipValue)));

                        hCNErrorToolTipValue =
                            numberFormatter.dataLabels(setValue.x - hNegativeErrorValue, parentYAxis);
                        hCNErrorToolText = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
                            JSONData.errorplottooltext, chartAttr.errorplottooltext, hCNErrorToolTipValue)));

                        vCPErrorToolTipValue =
                            numberFormatter.dataLabels(setValue.y + vPositiveErrorValue, parentYAxis);
                        vCPErrorToolText = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
                            JSONData.errorplottooltext, chartAttr.errorplottooltext, vCPErrorToolTipValue)));

                        vCNErrorToolTipValue =
                            numberFormatter.dataLabels(setValue.y - vNegativeErrorValue, parentYAxis);
                        vCNErrorToolText = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
                            JSONData.errorplottooltext, chartAttr.errorplottooltext, vCNErrorToolTipValue)));
                    }

                    categories && categories[i] && (config.label =
                        getValidValue(parseUnsafeString(pluck (categories[i].tooltext, categories[i].label))));

                    if (setData.horizontalpositiveerrorvalue || setData.positiveerrorvalue ||
                        setData.horizontalnegativeerrorvalue || setData.negativeerrorvalue) {
                        config.halfHorizontalErrorBar = halfHorizontalErrorBar = 0;
                    } else {
                        config.halfHorizontalErrorBar = halfHorizontalErrorBar = conf.halfHorizontalErrorBar;
                    }

                    if (setData.verticalpositiveerrorvalue || setData.positiveerrorvalue ||
                        setData.verticalnegativeerrorvalue || setData.negativeerrorvalue) {
                        config.halfVerticalErrorBar = halfVerticalErrorBar = 0;
                    } else {
                        config.halfVerticalErrorBar = halfVerticalErrorBar = conf.halfVerticalErrorBar;
                    }

                    if (setValue.x !== null) {
                        maxErrorValue = setValue.x + Number(hPositiveErrorValue);
                        minErrorValue = setValue.x - (halfHorizontalErrorBar ? 0 : Number(hNegativeErrorValue));

                        xMax = mathMax(xMax, maxErrorValue, minErrorValue);
                        xMin = mathMin(xMin, maxErrorValue, minErrorValue);
                    }

                    if (setValue.y !== null) {
                        maxErrorValue = setValue.y + Number(vPositiveErrorValue);
                        minErrorValue = setValue.y - (halfVerticalErrorBar ? 0 : Number(vNegativeErrorValue));

                        yMax = mathMax(yMax, maxErrorValue, minErrorValue);
                        yMin = mathMin(yMin, maxErrorValue, minErrorValue);
                    }



                    useHorizontalErrorBar = config.useHorizontalErrorBar = pluckNumber(setData.usehorizontalerrorbar,
                        JSONData.usehorizontalerrorbar, chartAttr.usehorizontalerrorbar, 0);

                    useVerticalErrorBar = config.useVerticalErrorBar = pluckNumber(setData.useverticalerrorbar,
                        JSONData.useverticalerrorbar, chartAttr.useverticalerrorbar, 1);

                    config.errorValueArr = [];

                    config.errorValueArr.push({
                        errorValue: -(hPositiveErrorValue === null ? undefined : hPositiveErrorValue),
                        tooltext: getTooltext(hPositiveSetTooltext, hPositiveErrorToolTipValue),
                        errorBarColor: horizontalErrorBarColor,
                        isHorizontal: 1,
                        errorBarThickness: horizontalErrorBarThickness,
                        shadowOpacity : errorBarShadow ? (horizontalErrorBarAlpha / 250) : 0
                    });

                    config.errorValueArr.push({
                        errorValue: -(hPositiveErrorValue === null ? undefined : hPositiveErrorValue),
                        tooltext: cumulativeValueOnErrorBar ? getTooltext(hCPErrorToolText, hCPErrorToolTipValue) :
                             getTooltext(hPositiveSetTooltext, hPositiveErrorToolTipValue),
                        errorBarColor: horizontalErrorBarColor,
                        isHorizontal: 1,
                        errorBarThickness: horizontalErrorBarThickness,
                        shadowOpacity : errorBarShadow ? (horizontalErrorBarAlpha / 250) : 0,
                        errorEdgeBar : true
                    });

                    config.errorValueArr.push({
                        errorValue: hNegativeErrorValue,
                        tooltext: getTooltext(hNegativeSetTooltext, hNegativeErrorToolTipValue),
                        errorBarColor: horizontalErrorBarColor,
                        isHorizontal: 1,
                        errorBarThickness: horizontalErrorBarThickness,
                        shadowOpacity : errorBarShadow ? (horizontalErrorBarAlpha / 250) : 0
                    });

                    config.errorValueArr.push({
                        errorValue: hNegativeErrorValue,
                        tooltext: cumulativeValueOnErrorBar ? getTooltext(hCNErrorToolText, hCNErrorToolTipValue) :
                            getTooltext(hNegativeSetTooltext, hNegativeErrorToolTipValue),
                        errorBarColor: horizontalErrorBarColor,
                        isHorizontal: 1,
                        errorBarThickness: horizontalErrorBarThickness,
                        shadowOpacity : errorBarShadow ? (horizontalErrorBarAlpha / 250) : 0,
                        errorEdgeBar : true
                    });

                    config.errorValueArr.push({
                        errorValue: -(vPositiveErrorValue === null ? undefined : vPositiveErrorValue),
                        tooltext: getTooltext(vPositiveSetTooltext, vPositiveErrorToolTipValue),
                        errorBarColor: verticalErrorBarColor,
                        errorBarThickness: verticalErrorBarThickness,
                        shadowOpacity : errorBarShadow ? (verticalErrorBarAlpha / 250) : 0
                    });

                    config.errorValueArr.push({
                        errorValue: -(vPositiveErrorValue === null ? undefined : vPositiveErrorValue),
                        tooltext: cumulativeValueOnErrorBar ? getTooltext(vCPErrorToolText, vCPErrorToolTipValue) :
                            getTooltext(vPositiveSetTooltext, vPositiveErrorToolTipValue),
                        errorBarColor: verticalErrorBarColor,
                        errorBarThickness: verticalErrorBarThickness,
                        shadowOpacity : errorBarShadow ? (verticalErrorBarAlpha / 250) : 0,
                        errorEdgeBar : true
                    });

                    config.errorValueArr.push({
                        errorValue: vNegativeErrorValue,
                        tooltext: getTooltext(vNegativeSetTooltext, vNegativeErrorToolTipValue),
                        errorBarColor: verticalErrorBarColor,
                        errorBarThickness: verticalErrorBarThickness,
                        shadowOpacity : errorBarShadow ? (verticalErrorBarAlpha / 250) : 0
                    });

                    config.errorValueArr.push({
                        errorValue: vNegativeErrorValue,
                        tooltext: cumulativeValueOnErrorBar ? getTooltext(vCNErrorToolText, vCNErrorToolTipValue) :
                            getTooltext(vNegativeSetTooltext, vNegativeErrorToolTipValue),
                        errorBarColor: verticalErrorBarColor,
                        errorBarThickness: verticalErrorBarThickness,
                        shadowOpacity : errorBarShadow ? (verticalErrorBarAlpha / 250) : 0,
                        errorEdgeBar : true
                    });

                    setValue = config.setValue;

                    errorPercentValue = (mathRound(((setErrorValue / setValue) * HUNDREDSTRING) * HUNDREDSTRING) /
                        HUNDREDSTRING) + PERCENTAGESTRING;

                    horizontalErrorPercent = (mathRound(((hErrorValue / setValue) * HUNDREDSTRING) * HUNDREDSTRING) /
                        HUNDREDSTRING) + PERCENTAGESTRING;

                    verticalErrorPercent = (mathRound(((vErrorValue / setValue) * HUNDREDSTRING) * HUNDREDSTRING) /
                        HUNDREDSTRING) + PERCENTAGESTRING;

                    formatedVal = config.formatedVal;

                    // Initial tooltext parsing
                    if (!conf.showTooltip) {
                        toolText = false;
                    }
                    else if (config.setTooltext !== undefined) {
                        macroIndices = [1,2,3,4,5,6,7,8,9,10,11,99,100,101,102,103,104,105,106,107,109];
                        parserConfig = {
                            yaxisName: yAxisName,
                            xaxisName: xAxisName,
                            yDataValue: formatedVal,
                            xDataValue: config.label,
                            formattedValue : config.toolTipValue,
                            horizontalErrorValue: hErrorValue,
                            horizontalErrorDataValue: hErrorToolTipValue,
                            verticalErrorValue: vErrorValue,
                            verticalErrorDataValue: vErrorToolTipValue,
                            horizontalErrorPercent: horizontalErrorPercent,
                            verticalErrorPercent: verticalErrorPercent,
                            label : config.label
                        };
                        toolText = parseTooltext(config.setTooltext, macroIndices, parserConfig, setData, chartAttr,
                            JSONData);
                    }
                    //determine the default tooltext then.
                    else {
                        if (formatedVal === null) {
                            toolText = false;
                        }
                        else {
                            if (conf.seriesNameInTooltip) {
                                seriesname = lib.getFirstValue(JSONData && JSONData.seriesname);
                            }
                            toolText = seriesname ? seriesname + tooltipSepChar : BLANK;
                            toolText += setValue.x ? numberFormatter.xAxis(setValue.x) + tooltipSepChar : BLANK;
                            toolText += config.toolTipValue;
                        }
                    }
                    config.toolText = toolText;
                }

                conf.xMax = xMax;
                conf.xMin = xMin;
                conf.yMin = yMin;
                conf.yMax = yMax;
            },

            drawErrorValue: function() {
                var dataSet = this,
                    chart = dataSet.chart,
                    chartComponents = chart.components,
                    parentContainer = dataSet.parentContainer,
                    JSONData = dataSet.JSONData,
                    conf = dataSet.config,
                    setDataArr = JSONData.data,
                    dataSetLen = setDataArr && setDataArr.length,
                    setData,
                    attr,
                    i,
                    visible = dataSet.visible,
                    paper = chartComponents.paper,
                    xAxis = chartComponents.xAxis[0],
                    yAxis = dataSet.yAxis,
                    dataStore = dataSet.components.data,

                    isHorizontal,
                    errorBarThickness,
                    errorBarWidth,
                    errorBarColor,
                    showTooltip = conf.showTooltip,
                    shadowOpacity = conf.shadowOpacity,

                    animationObj = chart.get(configStr, animationObjStr),
                    animType = animationObj.animType,
                    animObj = animationObj.animObj,
                    dummyObj = animationObj.dummyObj,
                    animationDuration = animationObj.duration,

                    lineGroup = dataSet.graphics.container.lineGroup,
                    errorGroupContainer = dataSet.graphics.errorGroupContainer,
                    errorShadowContainer = dataSet.graphics.errorShadowContainer,
                    setLink,
                    tooltext,
                    xPos,
                    yPos,
                    useCrispErrorPath = 1,
                    dataObj,
                    setValue,
                    // groupId,
                    config,
                    // eventArgs,
                    crispY,
                    crispX,
                    errorPath,
                    errorValPos,
                    errorValuePosFactor,
                    errorValueArr,
                    errorValueObj,
                    errorValue,
                    errorStartPos,
                    errorLen,
                    halfErrorBarW,
                    errorLineElem,
                    errorTrackerElem,
                    errorValueElem,
                    plotXpos,
                    plotYpos,
                    errorBarSegmentLen,
                    errorBarSegmentStartPos,
                    l,
                    j,
                    k,
                    trackerTolerance,
                    searchDataArr = [],
                    errorTrackerConfig;

                if (!errorGroupContainer) {
                    errorGroupContainer = dataSet.graphics.errorGroupContainer =
                     paper.group(errorBarStr, parentContainer).insertAfter(lineGroup);
                    if (!visible) {
                        errorGroupContainer.hide();
                    }
                }

                if (!errorShadowContainer) {
                    // Always sending the shadow group to the back of the plots group.
                    errorShadowContainer = dataSet.graphics.errorShadowContainer =
                        paper.group(errorShadowStr, parentContainer).insertBefore(errorGroupContainer);
                    if (!visible) {
                        errorShadowContainer.hide();
                    }
                }

                // Loop through each data points
                for (i = 0; i < dataSetLen; i++) {
                    setData = setDataArr && setDataArr[i];
                    dataObj = dataStore[i];
                    errorTrackerConfig = dataObj.errorTrackerConfig = {};
                    errorTrackerConfig.errorTrackerArr = [];
                    config = dataObj && dataObj.config;
                    setValue = config && config.setValue;

                    errorValueArr = config.errorValueArr;

                    // If plot value is found "null", continue the loop to next iteration.
                    if (dataObj === undefined || setValue === undefined || setValue === null || !errorValueArr) {
                        continue;
                    }

                    errorValueArr = config.errorValueArr;
                    errorTrackerConfig.errorLen = errorLen = errorValueArr.length;

                    !dataObj.graphics.error && (dataObj.graphics.error = []);
                    !dataObj.graphics.errorTracker && (dataObj.graphics.errorTracker = []);

                    if (config.vErrorValue === null &&
                        config.vPositiveErrorValue === null && config.vNegativeErrorValue === null) {
                        for (k = 0; k < 4; k++) {
                            if (dataObj.graphics.error && dataObj.graphics.error[k]) {
                                dataObj.graphics.error[k].hide();
                                dataObj.graphics.error[k].shadow({opacity: 0});
                            }
                        }
                    }


                    if (config.hErrorValue === null &&
                        config.hPositiveErrorValue === null && config.vPositiveErrorValue === null) {
                        for (k = 4; k < 8; k++) {
                            if (dataObj.graphics.error && dataObj.graphics.error[k]) {
                                dataObj.graphics.error[k].hide();
                                dataObj.graphics.error[k].shadow({opacity: 0});
                            }
                        }
                    }

                    if (config.hErrorValue === null && config.vErrorValue === null && config.hPositiveErrorValue &&
                        config.hNegativeErrorValue && config.vPositiveErrorValue && config.vNegativeErrorValue) {
                        continue;
                    }

                    setLink  = config.setLink;

                    plotXpos = dataObj._xPos;
                    plotYpos = dataObj._yPos;

                    yPos = plotYpos;
                    xPos = plotXpos;

                    //Loop through errorValue array
                    for (j = 0; j < errorLen; j++) {

                        if (((!config.useHorizontalErrorBar) && (j === 0 || j === 1 || j === 2 || j === 3)) ||
                            ((!config.useVerticalErrorBar) && (j === 4 || j === 5 || j === 6 || j === 7) ) ||
                            ((j === 2 || j === 3) && config.halfHorizontalErrorBar) ||
                            ((j === 6 || j === 7) && config.halfVerticalErrorBar)) {

                            dataObj.graphics.error && dataObj.graphics.error[j] && dataObj.graphics.error[j].hide() &&
                            dataObj.graphics.error[j].shadow({opacity: 0});

                            dataObj.graphics.errorTracker && dataObj.graphics.errorTracker[j] &&
                            dataObj.graphics.errorTracker[j].hide() &&
                            dataObj.graphics.errorTracker[j].shadow({opacity: 0});
                            continue;
                        }

                        errorTrackerConfig.errorTrackerArr[j] = {};

                        errorTrackerElem = errorLineElem = errorValueElem =
                            null;
                        errorValueObj = errorValueArr[j];
                        errorTrackerConfig.errorTrackerArr[j].tooltext = tooltext = errorValueObj.tooltext;
                        errorStartPos = yPos;
                        errorValue = errorValueObj.errorValue;
                        if (errorValue === null || errorValue === undefined || isNaN(errorValue)) {
                            if (dataObj.graphics.error && dataObj.graphics.error[j]) {
                                dataObj.graphics.error[j].hide();
                                dataObj.graphics.error[j].shadow({opacity: j});
                            }

                            if (dataObj.graphics.errorTracker && dataObj.graphics.errorTracker[j]) {
                                dataObj.graphics.errorTracker[j].hide();
                                dataObj.graphics.errorTracker[j].shadow({opacity: 0});
                            }
                            continue;
                        }
                        errorBarColor = errorValueObj.errorBarColor;
                        isHorizontal =
                            pluckNumber(errorValueObj.isHorizontal, 0);
                        errorBarThickness =
                            pluckNumber(errorValueObj.errorBarThickness,
                                conf.errorBarThickness, 1);

                        errorBarWidth = isHorizontal ? conf.horizontalErrorBarWidth
                            : conf.verticalErrorBarWidth;

                        halfErrorBarW = (!visible) ? 0 : (errorBarWidth / 2);

                        errorValuePosFactor = (!visible) ? 0 : 1;

                        trackerTolerance = errorBarThickness > 5 ? (errorBarThickness) / 2 + 0.5 : 5.5 / 2;

                        if (isHorizontal) {
                            errorValPos = plotXpos +
                                ((xAxis.getAxisPosition(0) - xAxis.getAxisPosition(1)) *
                                errorValue * errorValuePosFactor);
                            crispY = errorValPos;
                            crispX = xPos;

                            if (useCrispErrorPath) {
                                crispY = mathRound(errorStartPos) +
                                    (errorBarThickness % 2 / 2);
                                crispX = mathRound(errorValPos) +
                                    (errorBarThickness % 2 / 2);
                            }

                            if(errorValueObj.errorEdgeBar) {
                                errorPath = [
                                    M, crispX, crispY - halfErrorBarW,
                                    V, (crispY + halfErrorBarW)
                                ];

                                errorBarSegmentLen = 2 * halfErrorBarW;
                                errorBarSegmentStartPos = crispY - halfErrorBarW;
                                for (l = trackerTolerance; l < errorBarSegmentLen; l += (2 * trackerTolerance)) {
                                    searchDataArr.push({
                                        x: crispX,
                                        y: errorBarSegmentStartPos + l,
                                        r: trackerTolerance,
                                        index: i,
                                        data: dataObj,
                                        toolText: errorValueObj.tooltext,
                                        barType: 'h'
                                    });
                                }
                            } else {
                                errorPath = [
                                    M, xPos, crispY,
                                    H, crispX
                                ];

                                errorBarSegmentLen = mathAbs(xPos - crispX);
                                errorBarSegmentStartPos = xPos > crispX ? crispX : xPos;
                                for (l = trackerTolerance; l < errorBarSegmentLen; l += (2 * trackerTolerance)) {
                                    searchDataArr.push({
                                        x: errorBarSegmentStartPos + l,
                                        y: crispY,
                                        r: trackerTolerance,
                                        index: i,
                                        data: dataObj,
                                        toolText: errorValueObj.tooltext,
                                        barType: 'h'
                                    });
                                }
                            }
                        }
                        // Vertical Error drawing
                        else {
                            // Vertical Error drawing
                            errorValPos = plotYpos +
                                ((yAxis.getAxisPosition(0) - yAxis.getAxisPosition(1)) *
                                errorValue * errorValuePosFactor);
                            crispY = errorValPos;
                            crispX = xPos;
                            if (useCrispErrorPath) {
                                crispY = mathRound(errorValPos) +
                                    (errorBarThickness % 2 / 2);
                                crispX = mathRound(xPos) +
                                    (errorBarThickness % 2 / 2);
                            }

                            if(errorValueObj.errorEdgeBar) {
                                errorPath = [
                                    M, crispX - halfErrorBarW, crispY,
                                    H, (crispX + halfErrorBarW)
                                ];

                                errorBarSegmentLen = 2 * halfErrorBarW;
                                errorBarSegmentStartPos = crispX - halfErrorBarW;
                                for (l = trackerTolerance; l <= errorBarSegmentLen; l += (2 * trackerTolerance)) {
                                    searchDataArr.push({
                                        x: errorBarSegmentStartPos + l,
                                        y: crispY,
                                        r: trackerTolerance,
                                        index: i,
                                        data: dataObj,
                                        toolText: errorValueObj.tooltext,
                                        barType: 'v'
                                    });
                                }
                            } else {
                                errorPath = [
                                    M, crispX, errorStartPos,
                                    V, crispY
                                ];

                                errorBarSegmentLen = mathAbs(errorStartPos - crispY);
                                errorBarSegmentStartPos = errorStartPos > crispY ? crispY : errorStartPos;
                                for (l = trackerTolerance; l <= errorBarSegmentLen; l += (2 * trackerTolerance)) {
                                    searchDataArr.push({
                                        x: crispX,
                                        y: errorBarSegmentStartPos + l,
                                        r: trackerTolerance,
                                        index: i,
                                        data: dataObj,
                                        toolText: errorValueObj.tooltext,
                                        barType: 'v'
                                    });
                                }
                            }
                        }

                        if (!dataObj.graphics.error[j]) {
                            errorLineElem = dataObj.graphics.error[j] =
                             paper.path(errorPath, errorGroupContainer)
                                .attr({
                                    stroke: errorBarColor,
                                    // In case of tooltip disabled this element should act as the hot element.
                                    ishot: !showTooltip,
                                    'stroke-width': errorBarThickness,
                                    'cursor': setLink ? POINTER : BLANKSTRING,
                                    'stroke-linecap': ROUND
                                });

                            if (conf.initAnimation) {
                                errorLineElem
                                .attr({
                                    opacity: 0
                                })
                                .animateWith(dummyObj, animObj, {
                                    opacity: 1
                                }, animationDuration, animType);
                            }
                        }
                        else {
                            errorLineElem = dataObj.graphics.error[j];

                            attr = {
                                path: errorPath,
                                'stroke-width': visible ? errorBarThickness : 0
                            };

                            errorLineElem.animateWith(dummyObj, animObj, attr, animationDuration, animType);

                            errorLineElem.attr({
                                stroke: errorBarColor,
                                // In case of tooltip disabled this element should act as the hot element.
                                ishot: !showTooltip,
                                'cursor': setLink ? POINTER : BLANKSTRING,
                                'stroke-linecap': ROUND
                            });

                        }
                        errorLineElem.show();
                        errorLineElem
                            .shadow({opacity : shadowOpacity}, errorShadowContainer);

                        errorTrackerConfig.errorTrackerArr[j].attr = {
                            path: errorPath,
                            stroke: TRACKER_FILL,
                            'stroke-width': visible ? (errorBarThickness < HTP ? HTP : errorBarThickness) : 0,
                            'cursor': setLink ? POINTER : BLANKSTRING,
                            'ishot': !! setLink
                        };
                    }
                }
                searchDataArr.length && (this.dataTreeB = new lib.KdTree().buildKdTree(searchDataArr));
                conf.initAnimation = false;
            },

            /*
             * Using kdtree algo for searching
            */
            _getHoveredPlot: function (x, y) {
                var res,
                    res1,
                    tooltext,
                    errorBarToolText,
                    hoverEffects,
                    element;

                res = this.dataTree.getNeighbour({
                    x: x,
                    y: y
                }, true);

                // searching neighbour from Kdtree with basic search flag on
                if (res) {
                    tooltext = res.data.config.toolText;
                    res.data.config.finalTooltext = tooltext;
                    hoverEffects = res.data.config.hoverEffects;
                    element = res.data.graphics.element;
                    element.data('hoverEnabled', hoverEffects.enabled);
                    hoverEffects.enabled && element.attr(element.getData().setRolloverAttr);
                    return {
                        pointIndex: res.index,
                        hovered: true,
                        pointObj: res.data
                    };
                } else {
                    res1 = this.dataTreeB && this.dataTreeB.getNeighbour({
                        x: x,
                        y: y
                    }, true);
                    if (res1) {
                        if (res1.barType === 'h') {
                            errorBarToolText = res1.toolText;
                        } else if (res1.barType === 'v') {
                            errorBarToolText = res1.toolText;
                        }
                        res1.data.config.finalTooltext = errorBarToolText;
                        element = res1.data.graphics.element;
                        element.data('hoverEnabled', false);
                        element.attr(element.getData().setRolloutAttr);
                        return {
                            pointIndex: res1.index,
                            hovered: true,
                            pointObj: res1.data
                        };
                    }
                }
            },
            /*
             * Makes a dataset visible when clicked on its respective legend
             * Fired every time a deactivated legend is clicked
             */
            show : function() {
                var dataSet = this,
                    chart = dataSet.chart,
                    yAxis = dataSet.yAxis,
                    errorGroupContainer = dataSet.graphics && dataSet.graphics.errorGroupContainer,
                    errorShadowContainer = dataSet.graphics && dataSet.graphics.errorShadowContainer;

                chart._chartAnimation();
                dataSet.visible = true;
                dataSet._conatinerHidden = false;

                errorGroupContainer && errorGroupContainer.show();
                errorShadowContainer && errorShadowContainer.show();

                chart._setAxisLimits();
                yAxis.draw();
                // Calling the draw function for redrawing the dataset
                dataSet.draw();
            },

            // Function to remove a data from a dataset during real time update.
            remove : function () {
                var dataSet = this,
                    components = dataSet.components,
                    removeDataArr = components.removeDataArr,
                    pool = components.pool || (components.pool = {
                        element :[],
                        hotElement : [],
                        label : []
                    }),
                    len = removeDataArr.length,
                    removeData,
                    maxminFlag = dataSet.maxminFlag,
                    graphics,
                    i,
                    j;

                for (i = 0; i < len; i++) {
                    removeData = removeDataArr[0];
                    removeDataArr.splice(0,1);
                    // In case of non existing data plot continue;
                    if (!removeData || !removeData.graphics) {
                        continue;
                    }

                    graphics = removeData.graphics;

                    graphics.element && graphics.element.hide() && graphics.element.shadow({opacity: 0});

                    for (j = 0; j < 8; j++) {
                        graphics.error && graphics.error[j] && graphics.error[j].hide() &&
                        graphics.error[j].shadow({opacity: 0});
                    }

                    // Storing the graphic elements for reuse.
                    removeData.graphics.element && (pool.element = pool.element.concat(removeData.graphics.element));
                    removeData.graphics.label && (pool.label = pool.label.concat(removeData.graphics.label));
                }
                components.pool = pool;
                maxminFlag && dataSet.setMaxMin();
            }

        },'Scatter']);

    }
]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-multiaxisline',
    function () {
        var global = this,
            lib = global.hcLib,
            pluckNumber = lib.pluckNumber,
            //strings
            preDefStr = lib.preDefStr,
            LINE = preDefStr.line,
            //add the tools thats are requared
            pluck = lib.pluck,
            COMPONENT = 'component',
            DATASET = 'dataset',
            HUNDREDSTRING = lib.HUNDREDSTRING;

        FusionCharts.register(COMPONENT, [DATASET, 'multiaxisline', {
            type : 'multiaxisline',

            pIndex : 2,

            customConfigFn : '_createDatasets',

            configure: function () {
                var dataSet = this,
                    chart = dataSet.chart,
                    datasetJSON = dataSet.JSONData,
                    dataSetConfig = dataSet.config,
                    conf = chart.config,
                    components = chart.components,
                    chartJSON = chart.jsonData,
                    axes = chartJSON.axis,
                    chartAttr = chartJSON.chart,
                    axis = axes[dataSet.axisIndex],
                    singleSeries = chart.singleseries,
                    Line = FusionCharts.get(COMPONENT, [DATASET, LINE]).prototype,
                    yAxis,
                    lineDashStyle,
                    lineDashed;

                Line.configure.call(this);
                yAxis = components.yAxis[dataSet.axisIndex];
                dataSet.yAxis = yAxis;
                conf.axesPadding = 5;
                conf.allowAxisShift = pluckNumber(chartAttr.allowaxisshift, 1);
                conf.allowSelection = pluckNumber(chartAttr.allowselection, 1);
                conf.checkBoxColor = pluck(chartAttr.checkboxcolor, '#2196f3');
                conf.axisConfigured = true;

                dataSetConfig.linethickness = pluckNumber(datasetJSON.linethickness, axis.linethickness,
                     chartAttr.linethickness, singleSeries ? 4 : 2);
                dataSetConfig.lineDashLen = pluckNumber(datasetJSON.linedashlen, axis.linedashlen,
                    chartAttr.linedashlen, 5);
                dataSetConfig.lineDashGap = pluckNumber(datasetJSON.linedashgap, axis.linedashgap,
                    chartAttr.linedashgap, 4);
                dataSetConfig.alpha = pluckNumber(datasetJSON.alpha, axis.linealpha,
                    chartAttr.linealpha, HUNDREDSTRING);
                dataSetConfig.linecolor = pluck(datasetJSON.color, axis.linecolor, axis.color, chartAttr.linecolor,
                    dataSetConfig.plotColor);


                dataSetConfig.legendSymbolColor = dataSet.type === LINE ? dataSetConfig.lineColor :
                dataSetConfig.plotFillColor;
                lineDashed = pluckNumber(datasetJSON.dashed, axis.linedashed, chartAttr.linedashed);
                lineDashStyle = lib.getDashStyle(dataSetConfig.lineDashLen, dataSetConfig.lineDashGap,
                    dataSetConfig.linethickness);
                dataSetConfig.anchorBorderColor = pluck(datasetJSON.anchorbordercolor,
                    chartAttr.anchorbordercolor, dataSetConfig.lineColor, dataSetConfig.plotColor);
                dataSetConfig.lineDashStyle = lineDashed ?
                        lineDashStyle : 'none';
                Line._setConfigure.call(this);
                (chart.hasLegend !== false) && dataSet._addLegend();
            },
            init: function (datasetJSON) {
                var dataSet = this,
                    chart = dataSet.chart;

                dataSet.chart = chart;
                dataSet.components = {

                };

                dataSet.conf ={

                };

                dataSet.graphics = {

                };
                dataSet.JSONData = datasetJSON;
                dataSet.visible = pluckNumber(dataSet.JSONData.visible,
                    !Number(dataSet.JSONData.initiallyhidden), 1) === 1;
                dataSet.configure();
            },
            // Fuction to be fired on legend click
            legendInteractivity : function (dataSet, legendItem) {
                var legend = this,
                    chart = dataSet.chart,
                    dataSets = chart.components.dataset,
                    axesArr = chart.config.axesArr,
                    legendConfig = legend.config,
                    visible = dataSet.visible,
                    config = legendItem.config,
                    legendGraphics = legendItem.graphics,
                    itemHiddenStyle = legendConfig.itemHiddenStyle,
                    hiddenColor = itemHiddenStyle.color,
                    itemStyle = legendConfig.itemStyle,
                    itemTextColor = itemStyle.color,
                    color = config.fillColor,
                    stroke = config.strokeColor,
                    checkboxes,
                    axisIndex = dataSet.axisIndex,
                    checkboxUncheck = true,
                    i;

                checkboxes = axesArr.checkBox;
                visible ? dataSet.hide() : dataSet.show();
                if (visible) {
                    for (i in dataSets) {
                        if(dataSets.hasOwnProperty(i)) {
                            if (dataSets[i].visible && dataSets[i].axisIndex === axisIndex) {
                                checkboxUncheck = false;
                            }
                        }
                    }
                    if (checkboxUncheck) {
                        checkboxes[axisIndex] && checkboxes[axisIndex].checkbox.uncheck();
                    }
                } else {
                    checkboxes[axisIndex] && checkboxes[axisIndex].checkbox.check();
                }
                if (!visible) {
                    legendGraphics.legendItemSymbol && legendGraphics.legendItemSymbol.attr({
                        fill: color,
                        'stroke': stroke
                    });
                    legendGraphics.legendItemText && legendGraphics.legendItemText.attr({
                        fill: itemTextColor
                    });
                    legendGraphics.legendIconLine && legendGraphics.legendIconLine.attr({
                        'stroke': color
                    });
                } else {
                    legendGraphics.legendItemSymbol && legendGraphics.legendItemSymbol.attr({
                        fill: hiddenColor,
                        'stroke': hiddenColor
                    });
                    legendGraphics.legendItemText && legendGraphics.legendItemText.attr({
                        fill: hiddenColor
                    });
                    legendGraphics.legendIconLine && legendGraphics.legendIconLine.attr({
                        'stroke': hiddenColor
                    });
                }
            }
        }, LINE]);

    }
]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-multilevelpie',
    function () {
        var global = this,
            lib = global.hcLib,
            convertColor = lib.graphics.convertColor,
            plotEventHandler = lib.plotEventHandler,
            //strings
            preDefStr = lib.preDefStr,
            colorStrings = preDefStr.colors,
            COLOR_FFFFFF = colorStrings.FFFFFF,
            COLOR_000000 = colorStrings.c000000,
            configStr = preDefStr.configStr,
            animationObjStr = preDefStr.animationObjStr,
            ZEROSTRING = lib.ZEROSTRING,
            BLANK = lib.BLANKSTRING,
            BLANKSTRING = lib.BLANKSTRING,
            parseTooltext = lib.parseTooltext,
            //add the tools thats are requared
            pluck = lib.pluck,
            getValidValue = lib.getValidValue,
            pluckNumber = lib.pluckNumber,
            getFirstValue = lib.getFirstValue,
            // getDefinedColor = lib.getDefinedColor,
            parseUnsafeString = lib.parseUnsafeString,
            getDashStyle = lib.getDashStyle, // returns dashed style of a line series
            toRaphaelColor = lib.toRaphaelColor,
            UNDEFINED,
            NONE = 'none',
            // The default value for stroke-dash attribute.
            DASH_DEF = NONE,
            ROLLOVER = 'DataPlotRollOver',
            ROLLOUT = 'DataPlotRollOut',
            PXSTRING = 'px',
            pInt = function (s, mag) {
                return parseInt(s, mag || 10);
            },
            COMMASPACE = lib.COMMASPACE,
            POINTER = 'pointer',
            NORMALSTRING = 'normal',
            EVENTARGS = 'eventArgs',
            COMPONENT = 'component',
            DATASET = 'dataset',
            schedular = lib.schedular,
            // CRISP = 'crisp',
            PX = PXSTRING,
            math = Math,
            mathSin = math.sin,
            mathCos = math.cos,
            mathPI = math.PI,
            mathRound = math.round,
            mathMin = math.min,
            mathMax = math.max;

        FusionCharts.register(COMPONENT, [DATASET, 'multiLevelPie', {
            init: function (datasetJSON) {
                var dataSet = this;

                !dataSet.components && (dataSet.components = {
                    data: []
                });

                dataSet.conf ={

                };

                dataSet.graphics = {

                };
                dataSet.JSONData = datasetJSON;
                dataSet.configure();
            },
            configure: function () {
                var maxLevel,
                    useHoverColor,
                    hoverFillColor,
                    fontBdrColor,
                    pierad,
                    dataSet = this,
                    chart = dataSet.chart,
                    chartConfig = chart.config,
                    dataSetConfig = dataSet.conf || (dataSet.conf = {}),
                    dataLabels = dataSetConfig.dataLabelOptions || (dataSetConfig.dataLabelOptions = {}),
                    piePlotOptions = dataSetConfig.piePlotOptions,
                    style = chart.config.style,
                    jsonData = dataSet.JSONData,
                    chartAttrs = chart.jsonData.chart,
                    enableAnimation = dataSetConfig.enableAnimation = pluckNumber(chartAttrs.animation,
                        chartAttrs.defaultanimation, 1),
                    centerAngle = pluckNumber(-chartAttrs.centerangle, 180),
                    totalAngle = pluckNumber(chartAttrs.totalangle, 360);
                dataSetConfig.animation = !enableAnimation ? false : {
                    duration: pluckNumber(chartAttrs.animationduration, chartAttrs.moveduration, 1) * 1000
                };
                dataSetConfig.showShadow = pluckNumber(chartAttrs.showshadow, 0);
                useHoverColor = (dataSetConfig.useHoverColor = Boolean(pluckNumber(chartAttrs.usehovercolor, 1)));
                hoverFillColor = (dataSetConfig.hoverFillColor = convertColor(pluck(chartAttrs.hoverfillcolor,
                    'FF5904'), pluckNumber(chartAttrs.hoverfillalpha, 100)));
                pierad = (dataSetConfig.pierad = parseInt(chartAttrs.pieradius, 10));

                fontBdrColor = getFirstValue(chartAttrs.valuebordercolor, BLANK);
                fontBdrColor = fontBdrColor ? convertColor(
                    fontBdrColor, pluckNumber(chartAttrs.valueborderalpha, chartAttrs.valuebgalpha,
                    chartAttrs.valuealpha, 100)) : BLANK;
                //create the style object if required.
                //fix for multilevel pie datavalue cosmetics issue RED-1594
                !dataLabels.style && (dataLabels.style = {
                    fontFamily: pluck(chartAttrs.valuefont, style.fontFamily),
                    fontSize: pluckNumber(chartAttrs.valuefontsize,
                        pInt(style.fontSize, 10)) + PX,
                    color: convertColor(pluck(chartAttrs.valuefontcolor, style.color),
                        pluckNumber(chartAttrs.valuefontalpha,
                        chartAttrs.valuealpha, 100)),
                    fontWeight: pluckNumber(chartAttrs.valuefontbold) ? 'bold' : NORMALSTRING,
                    fontStyle: pluckNumber(chartAttrs.valuefontitalic) ? 'italic' : NORMALSTRING,
                    backgroundColor: chartAttrs.valuebgcolor ?
                        convertColor(chartAttrs.valuebgcolor,
                        pluckNumber(chartAttrs.valuebgalpha, chartAttrs.valuealpha, 100)) : BLANK,
                    border: fontBdrColor || chartAttrs.valuebgcolor ?
                        (pluckNumber(chartAttrs.valueborderthickness, 1) + 'px solid') : BLANK,
                    borderPadding: pluckNumber(chartAttrs.valueborderpadding, 2),
                    borderThickness: pluckNumber(chartAttrs.valueborderthickness, style.borderThickness, 1),
                    borderRadius: pluckNumber(chartAttrs.valueborderradius, style.borderRadius, 0),
                    borderColor: fontBdrColor,
                    borderDash: pluckNumber(chartAttrs.valueborderdashed, 0) ?
                        getDashStyle(pluckNumber(chartAttrs.valueborderdashlen, 4),
                        pluckNumber(chartAttrs.valueborderdashgap, 2),
                        pluckNumber(chartAttrs.valueborderthickness, 1)) : DASH_DEF
                });

                //stop point slicing
                !piePlotOptions && (piePlotOptions = (dataSetConfig.piePlotOptions = {}));
                piePlotOptions.allowPointSelect = false;

                dataSetConfig.borderColor = convertColor(pluck(chartAttrs.plotbordercolor,
                        chartAttrs.piebordercolor, COLOR_FFFFFF), chartAttrs.showplotborder != ZEROSTRING ?
                    pluck(chartAttrs.plotborderalpha, chartAttrs.pieborderalpha, 100) : 0);
                dataSetConfig.showTooltip = pluckNumber(chartAttrs.showtooltip, 1);

                dataSetConfig.borderWidth = pluckNumber(chartAttrs.pieborderthickness,
                    chartAttrs.plotborderthickness, 1);

                piePlotOptions.startingAngle = 0; //set the chart's startingAngle as 0 [alwase]
                piePlotOptions.size = '100%';

                dataSetConfig.showLabels = pluckNumber(chartAttrs.showlabels, 1);
                dataSetConfig.showValues = pluckNumber(chartAttrs.showvalues, 0);
                dataSetConfig.showValuesInTooltip = pluckNumber(chartAttrs.showvaluesintooltip,
                    chartAttrs.showvalues, 0);
                dataSetConfig.showPercentValues = pluckNumber(chartAttrs.showpercentvalues,
                    chartAttrs.showpercentagevalues, 0);
                dataSetConfig.showPercentInTooltip = pluckNumber(chartAttrs.showpercentintooltip, 0);
                dataSetConfig.toolTipSepChar = pluck(chartAttrs.tooltipsepchar, chartAttrs.hovercapsepchar, COMMASPACE);
                dataSetConfig.labelSepChar = pluck(chartAttrs.labelsepchar, dataSetConfig.toolTipSepChar);
                dataSetConfig.tooltext = chartAttrs.plottooltext;
                dataSetConfig.alpha = pluck(chartAttrs.plotfillalpha, chartAttrs.piefillalpha, 100);
                dataSetConfig.startAngle = (centerAngle - (totalAngle / 2)) * (mathPI / 180);
                dataSetConfig.endtAngle = (centerAngle + (totalAngle / 2)) * (mathPI / 180);
                dataSetConfig.initialAngle = dataSetConfig.endtAngle;
                dataSetConfig.originX = pluckNumber(chartAttrs.originx);
                dataSetConfig.originY = pluckNumber(chartAttrs.originy);

                if (useHoverColor) {
                    dataSetConfig.events = {
                        mouseOver: function() {
                            var point = this.data('plotItem'),
                                selfRef = point.selfRef,
                                conf = dataSet.conf;
                            while (selfRef.graphics.element) {
                                (selfRef.graphics.element).attr({
                                    fill: conf.hoverFillColor
                                });
                                selfRef = selfRef.linkedItems.parent;
                            }
                        },
                        mouseOut: function() {
                            var point = this.data('plotItem'),
                                selfRef = point.selfRef;
                            while (selfRef.graphics.element) {
                                (selfRef.graphics.element).attr({
                                    fill: (selfRef.config || point).color
                                });
                                selfRef = selfRef.linkedItems.parent;
                            }
                        }
                    };
                }

                //remove the plotboder
                chartConfig.plotBorderWidth = 0;

                //remove the plotboder
                chartConfig.plotBorderWidth = 0;
                maxLevel = dataSetConfig.maxLevel = dataSet.addMSPieCat(jsonData, 1, dataSet, dataSetConfig.startAngle,
                    dataSetConfig.endtAngle);
                /*dataSet._addMSPieCat(jsonData, 0, 0, 100, pluck(chartAttrs.plotfillalpha,
                    chartAttrs.piefillalpha, 100), dataSetConfig, null);*/
                /*pierad = parseInt(chartAttrs.pieradius, 10);
                inner = 0;
                isPercent = true;
                if (pierad) {
                    serieswidth = (2 * pierad) / maxLevel;
                    isPercent = false;
                } else {
                    serieswidth = smallerDimension * parseInt(100 / maxLevel, 10);
                }*/
                dataSetConfig.pieRadius = parseInt(chartAttrs.pieradius, 10);
                dataLabels.distance = 0;
                dataLabels.placeLabelsInside = true;
                //chart.options.plotOptions.series.dataLabels.placeLabelsInside
                //iterate through all data series
                /*for (y = 0; y < series.length; y += 1) {

                    //set the size and iner radious
                    series[y].config.innerSize = inner + (isPercent ? '%' : BLANKSTRING);
                    series[y].config.size = (inner += serieswidth) + (isPercent ? '%' : BLANKSTRING);
                    if (series[y].components.data[series[y].components.data.length - 1].config.y === 0) {
                        series[y].components.data.pop();
                    }
                }*/

            },
            // doHide is a Boolean Flag to hide the element or not.
            // All the graphical elements in excess are pushed to the graphics pool. They are hidden only after the
            // entire draw is complete.
            removalFn: function(ele, doHide, prop) {
                var dataSet = this,
                    centerAngle,
                    ringpath,
                    pool = dataSet.pool || (dataSet.pool = {}),
                    chart = dataSet.chart,
                    animationObj = chart.get(configStr, animationObjStr),
                    animationDuration = animationObj.duration,
                    mainElm = animationObj.dummyObj,
                    animObj = animationObj.animObj,
                    animType = animationObj.animType,
                    hideFN = function (ele) {
                        (ele || this).hide();
                    };

                !pool[prop] && (pool[prop] = []);

                if (prop === 'element') {
                    ringpath = ele.attr('ringpath');
                    centerAngle = (ringpath[4] + ringpath[5]) / 2;
                    doHide ? ele.animateWith(mainElm, animObj, {
                            ringpath: [ringpath[0], ringpath[1], ringpath[2], ringpath[3], centerAngle, centerAngle]
                        }, animationDuration, animType, hideFN) : pool[prop].push(ele);
                }
                else {
                    doHide ? hideFN(ele) : pool[prop].push(ele);
                }
            },
            removeGraphics: function (obj, doHide) {
                var i,
                    prop,
                    dataSet = this,
                    childData = obj.components && obj.components.data,
                    len,
                    graphics = obj.graphics;
                if (childData) {
                    len = childData.length;
                    for (i = 0; i < len; i += 1) {
                        dataSet.removeGraphics(childData[i]);
                    }
                }

                if (obj.graphics) {
                    for (prop in graphics) {
                        if (graphics.hasOwnProperty(prop)) {
                            dataSet.removalFn(obj.graphics[prop], doHide, prop);
                        }
                    }
                }
            },
            removeChild: function (removalStore, doHide, type) {
                var i,
                    elemObj,
                    dataSet = this;
                if (removalStore.length) {
                    for (i = 0; i < removalStore.length; i += 1) {
                        elemObj = removalStore[i];
                        if (type) {
                            dataSet.removalFn(elemObj, doHide, type);
                        }
                        else {
                            dataSet.removeGraphics(elemObj, doHide);
                        }
                    }
                }
                // if the removalStore is in the Object structure.
                else {
                    for (i in removalStore) {
                        dataSet.removeChild(removalStore[i], doHide, i);
                    }
                }
            },
            addMSPieCat: function(cat, level, parentObj, startAngle, endAngle) {
                var dataObj,
                    dataObjLen,
                    catObjLen,
                    catLen = cat.length,
                    dataSet = this,
                    data = parentObj.components.data,
                    chart = dataSet.chart,
                    chartComponents = chart.components,
                    dataSetConfig = dataSet.conf,
                    plotBorderThickness = dataSetConfig.borderWidth,
                    plotBorderColor = dataSetConfig.borderColor,
                    numberFormatter = chartComponents.numberFormatter,
                    colorM = chartComponents.colorManager,
                    sharePercent,
                    totalValue = 0,
                    catObj,
                    catVal,
                    i,
                    label,
                    labelSepChar = dataSetConfig.labelSepChar,
                    fillalpha,
                    valueStr,
                    pValueStr,
                    toolText,
                    displayValue,
                    maxLevel = level,
                    dataLength = data.length,
                    removalFn = function () {
                        dataSet.removeChild.apply(dataSet, arguments);
                    },
                    catLength = cat.length,
                    totAngle = endAngle - startAngle,
                    tempAngle,
                    cumilative = 0,
                    preDataOldEndAngle;

                for (i = 0; i < catLen; i += 1) {
                    //store for letter use
                    catObj = cat[i];
                    catObj._userValue = numberFormatter.getCleanValue(catObj.value, true);
                    catObj._value = pluckNumber(catObj._userValue, 1);
                    totalValue += catObj._value;
                }
                // Total value can't be zero, since its used in denominator to find ratio.
                totalValue = totalValue || 1;

                //add the category
                sharePercent = totAngle / totalValue;
                for (i = catLen - 1; i >= 0; i -= 1) {
                    catObj = cat[i];
                    catVal = sharePercent * catObj._value;
                    label = parseUnsafeString(pluck(catObj.label, catObj.name));
                    valueStr = catObj._userValue !== null ?
                        numberFormatter.dataLabels(catObj._userValue) : BLANK;
                    pValueStr = numberFormatter.percentValue((catObj._value /
                        totalValue) * 100);
                    // pointIndex = sLevel.length - 1;
                    fillalpha = pluckNumber(catObj.alpha, dataSetConfig.alpha);
                    displayValue = dataSetConfig.showLabels ? label : BLANK;
                    if (dataSetConfig.showValues) {
                        if (dataSetConfig.showPercentValues) {
                            displayValue += displayValue !== BLANK ? (labelSepChar + pValueStr) : pValueStr;
                        } else if (valueStr !== UNDEFINED && valueStr !== BLANK) {
                            displayValue += displayValue !== BLANK ? (labelSepChar + valueStr) : valueStr;
                        }
                    }
                    toolText = dataSetConfig.showTooltip ? parseUnsafeString(pluck(catObj.tooltext, catObj.hovertext,
                        dataSetConfig.tooltext)) : UNDEFINED;
                    if (toolText === BLANK) {
                        toolText = label;
                        if (dataSetConfig.showValuesInTooltip) {
                            if (dataSetConfig.showPercentInTooltip) {
                                toolText += toolText !== BLANK ? (labelSepChar + pValueStr) : pValueStr;
                            } else if (valueStr !== undefined && valueStr !== BLANK) {
                                toolText += toolText !== BLANK ? (labelSepChar + valueStr) : valueStr;
                            }
                        }
                    } else {
                        toolText = parseTooltext(toolText, [1, 2, 3, 14], {
                            percentValue: pValueStr,
                            label: label,
                            formattedValue: valueStr
                        }, catObj);
                    }

                    dataObj = data[i];
                    tempAngle = startAngle + cumilative;
                    cumilative += catVal;
                    if (!dataObj) {
                        dataObj = data[i] = {
                            components: {
                                data: []
                            },
                            linkedItems: {},
                            config: {},
                            graphics: {}
                        };
                    }
                    // store old end angle for newly added element's aimation position
                    if (dataObj.graphics.element) {
                        preDataOldEndAngle = dataObj.config.startAngle + dataObj.config.angleStrech;
                    }
                    dataObj.config = {
                        initialAngle: preDataOldEndAngle || (parentObj.conf || parentObj.config).initialAngle,
                        startAngle: tempAngle,
                        angleStrech: catVal,
                        level: level,
                        displayValue: displayValue,
                        toolText: toolText,
                        link: getValidValue(catObj.link),
                        doNotSlice: true, //added to stop slicing
                        color: convertColor(catObj.color || colorM.getPlotColor(), fillalpha),
                        borderWidth: pluckNumber(catObj.borderwidth, plotBorderThickness),
                        borderColor: pluck(catObj.bordercolor, plotBorderColor),
                        dashStyle: pluckNumber(catObj.valueborderdashed, 0) ?
                            getDashStyle(pluckNumber(catObj.borderdashlen, 4),
                            pluckNumber(catObj.borderdashgap, 2),
                            pluckNumber(catObj.borderthickness, 1)) : DASH_DEF,
                        shadow: {
                            opacity: mathRound(fillalpha > 50 ? fillalpha * fillalpha * fillalpha * 0.0001 :
                                fillalpha * fillalpha * 0.01) * 0.01
                        },
                        isSingleTon: (catLen > 1) ? false : true
                    };
                    dataObj.linkedItems.parent = parentObj;

                    if (catObj.category) {
                        maxLevel = mathMax(maxLevel, dataSet.addMSPieCat(catObj.category, level + 1,
                            dataObj, tempAngle, (catVal + tempAngle)));
                        if ((dataObjLen = dataObj.components.data.length) > (catObjLen = catObj.category.length)) {
                            removalFn(dataObj.components.data.splice(dataObjLen - 1, catObjLen));
                        }
                    }
                    else if (dataObjLen = dataObj.components.data.length){
                        // no child category, recursively remove existing childs (dataObj.components.data)
                        removalFn(dataObj.components.data.splice(0, dataObjLen));
                    }
                }
                // remove estra data
                if (dataLength > catLength) {
                    // recursively remove elements with child
                    removalFn(data.splice(catLength, dataLength - 1));
                }
                return maxLevel;
            },
            draw: function (parentObj) {
                var angle,
                    _textAttr,
                    _textAttrs,
                    centerDistance,
                    level,
                    dataSet = this,
                    dataSetConfig = dataSet.conf || {},
                    chart = dataSet.chart,
                    jobList = chart.getJobList(),
                    chartComponents = chart.components,
                    chartConfig = chart.config,
                    chartGraphics = chart.graphics,
                    dataSetComponents = dataSet.components,
                    data = dataSetComponents.data,
                    len = data.length,
                    seriesDataLabelsStyle = chartConfig.dataLabelStyle,
                    seriesShadow = dataSetConfig.showShadow,
                    paper = chartComponents.paper,
                    textDirection = chartConfig.textDirection,
                    tooltipOptions = chartConfig.tooltip || {},
                    isTooltip = tooltipOptions && tooltipOptions.enabled !== false,
                    toolText,
                    canvasWidth = chartConfig.canvasWidth,
                    canvasHeight = chartConfig.canvasHeight,
                    cx = pluckNumber(dataSetConfig.originX, chartConfig.canvasLeft + canvasWidth * 0.5),
                    cy = pluckNumber(dataSetConfig.originY, chartConfig.canvasTop + canvasHeight * 0.5),
                    r,
                    r2,
                    plotItem,
                    color,
                    val,
                    displayValue,
                    setLink,
                    angle1,
                    angle2,
                    i,
                    datasetLayer = (chartGraphics.datasetGroup.trackTooltip(true)),
                    animationObj = chart.get(configStr, animationObjStr),
                    animationDuration = animationObj.duration || 0,
                    primaryItemAnimating = animationObj.dummyObj,
                    animObj = animationObj.animObj,
                    animType = animationObj.animType,
                    eventArgs,
                    setGraphics,
                    setConfig,
                    element,
                    label,
                    initialAngle,
                    dataLabelsLayer = chartGraphics.datalabels || (chartGraphics.datalabels = paper.group('datalabels')
                        .insertAfter(datasetLayer)),
                    events = dataSetConfig.events || {},
                    plotHoverFN = function(e) {
                        var o = this,
                            mouseOver = events.mouseOver;
                        plotEventHandler.call(o, chart, e, ROLLOVER);
                        mouseOver && mouseOver.call(o);
                    },
                    plotMouseOut = function(e) {
                        var o = this,
                            mouseOut = events.mouseOut;
                        plotEventHandler.call(o, chart, e, ROLLOUT);
                        mouseOut && mouseOut.call(o);
                    },
                    //Fired when clicked over the hot elements.
                    clickFunc = function (setDataArr) {
                        var ele = this;
                        plotEventHandler.call(ele, chart, setDataArr);
                    },
                    animStartFN = function () {
                        if (!dataSetConfig._drawn) {
                            dataSetConfig._drawn = true;
                            dataLabelsLayer.show();
                            jobList.labelDrawID.push(schedular.addJob(dataSet.drawLabel,
                                dataSet, [], lib.priorityList.label));
                            chart._animCallBack();
                        }
                    },
                    pool = dataSet.pool || (dataSet.pool = {}),
                    removeDataArr = dataSetComponents.removeDataArr,
                    removeDataArrLen = removeDataArr && removeDataArr.length,
                    // either the user-specified size is chosen or the minimum aspect dimension is choosen
                    pieSize = pluckNumber(dataSetConfig.pieRadius * 2, mathMin(canvasWidth, canvasHeight)),
                    seriesHalfWidth = pieSize / (2 * dataSetConfig.maxLevel);
                removeDataArrLen && dataSet.remove();
                animationDuration && dataLabelsLayer.hide();
                if (!parentObj) {
                    parentObj = dataSet;
                    dataLabelsLayer.css(seriesDataLabelsStyle);
                }
                len = parentObj.components.data.length;
                for (i = 0; i < len; i += 1) {
                    dataSet.draw(parentObj.components.data[i]);
                }
                setConfig = parentObj.config;
                level = setConfig.level;
                if (level) {
                    r = (level * seriesHalfWidth);
                    r2 = ((level - 1) * seriesHalfWidth);

                    setGraphics = parentObj.graphics;
                    val = setConfig.angleStrech;
                    displayValue = setConfig.displayValue;
                    toolText = setConfig.toolText;
                    setLink = !! setConfig.link;
                    color = setConfig.color;

                    angle1 = setConfig.startAngle;
                    angle2 = angle1 + setConfig.angleStrech;
                    initialAngle = setConfig.initialAngle;

                    element = setGraphics.element;
                    if (!element) {
                        // Reuse the cache element
                        if(pool.element && pool.element.length) {
                            element = setGraphics.element = pool.element.shift();
                            element.show();
                        }
                        // If there is no element in cachestore then create it freshly
                        else {
                            element = setGraphics.element = paper.ringpath(datasetLayer)
                                .mouseover(plotHoverFN)
                                .mouseout(plotMouseOut)
                                .mouseup(clickFunc);
                        }
                        element.attr({
                            ringpath: [cx, cy, r, r2, initialAngle, initialAngle]
                        });
                    }
                    setConfig.plotItem = plotItem = {
                        chart: chart,
                        link: setConfig.link,
                        value: val,
                        color: color,
                        labelText: displayValue,
                        graphics: {
                            element: element
                        },
                        selfRef: parentObj
                    };

                    setConfig.eventArgs = eventArgs = {
                        link: setConfig.link,
                        label: setConfig.displayValue,
                        toolText: setConfig.toolText
                    };
                    element.attr({
                        'stroke-width': setConfig.borderWidth,
                        'stroke': setConfig.borderColor,
                        fill: toRaphaelColor(setConfig.color),
                        'stroke-dasharray': setConfig.dashStyle,
                        // In case of tooltip disabled this element should act as the hot element.
                        ishot: !isTooltip,
                        cursor: setLink ? POINTER : BLANKSTRING
                    })
                    .tooltip(setConfig.toolText)
                    .shadow(seriesShadow && !! setConfig.shadow)
                    .data('plotItem', plotItem)
                    .data(EVENTARGS, eventArgs);
                    label = setGraphics.label;
                    if ((displayValue !== undefined) && (displayValue !== BLANKSTRING)) {
                        angle = (angle1 + angle2) / 2;
                        if (!(_textAttr = setConfig._textAttr)) {
                            _textAttr = setConfig._textAttr = {};
                        }
                        // for the innermost Concentric circle the center distance is presumed to be zero
                        centerDistance = ((r2 === 0) && setConfig.isSingleTon) ? 0 : r2 + ((r - r2) / 2);
                        label = setGraphics.label;

                        if (!(_textAttrs = setConfig._textAttrs)) {
                            _textAttrs = setConfig._textAttrs = {};
                        }

                        _textAttrs.text = displayValue;
                        _textAttrs.fill = seriesDataLabelsStyle.color || COLOR_000000;
                        _textAttrs.direction = textDirection;
                        _textAttrs.ishot = setLink;
                        _textAttrs.cursor = setLink ? POINTER : BLANKSTRING;
                        _textAttrs.x = cx + (centerDistance * mathCos(angle));
                        _textAttrs.y = cy + (centerDistance * mathSin(angle));
                        _textAttrs['text-bound'] = [seriesDataLabelsStyle.backgroundColor,
                            seriesDataLabelsStyle.borderColor,
                            seriesDataLabelsStyle.borderThickness,
                            seriesDataLabelsStyle.borderPadding,
                            seriesDataLabelsStyle.borderRadius,
                            seriesDataLabelsStyle.borderDash];

                    }
                    element.animateWith(primaryItemAnimating, animObj, {
                        ringpath: [cx, cy, r, r2, angle1, angle2]
                    }, animationDuration, animType, !i && animStartFN);
                }
                else {
                    // If the chart is already drawn, then instead of sheduling the label drawing, directly draw the
                    // labels.
                    dataSetConfig._drawn && dataSet.drawLabel();
                    // at the end of all the tree structure, hide all the pool elements.
                    dataSet.removeChild(dataSet.pool, true);
                }
            },
            /*
             * Draws the label in a ML pie chart.
            */
            drawLabel: function (parentObj) {
                var _textAttrs,
                    level,
                    dataSet = this,
                    dataSetConfig = dataSet.conf || {},
                    chart = dataSet.chart,
                    chartComponents = chart.components,
                    chartConfig = chart.config,
                    chartGraphics = chart.graphics,
                    dataSetComponents = dataSet.components,
                    data = dataSetComponents.data,
                    len = data.length,
                    seriesDataLabelsStyle = chartConfig.dataLabelStyle,
                    paper = chartComponents.paper,
                    tooltipOptions = chartConfig.tooltip || {},
                    isTooltip = tooltipOptions && tooltipOptions.enabled !== false,
                    toolText,
                    plotItem,
                    displayValue,
                    i,
                    setGraphics,
                    setConfig,
                    label,
                    events = dataSetConfig.events || {},
                    labelHoverFN = function(e) {
                        var o = this,
                            mouseOver = events.mouseOver;
                        plotEventHandler.call(o, chart, e, ROLLOVER);
                        mouseOver && mouseOver.call(o);
                    },
                    labelOutFN = function(e) {
                        var o = this,
                            mouseOut = events.mouseOut;
                        plotEventHandler.call(o, chart, e, ROLLOUT);
                        mouseOut && mouseOut.call(o);
                    },
                    //Fired when clicked over the hot elements.
                    clickFunc = function (setDataArr) {
                        var ele = this;
                        plotEventHandler.call(ele, chart, setDataArr);
                    },
                    pool = dataSet.pool || (dataSet.pool = {}),
                    dataLabelsLayer = chartGraphics.datalabels;
                !parentObj && (parentObj = dataSet);
                len = parentObj.components.data.length;
                for (i = 0; i < len; i += 1) {
                    dataSet.drawLabel(parentObj.components.data[i]);
                }
                setConfig = parentObj.config;
                plotItem = setConfig.plotItem;
                displayValue = setConfig.displayValue;
                _textAttrs = setConfig._textAttrs;
                level = setConfig.level;
                if (level) {
                    setGraphics = parentObj.graphics;
                    label = setGraphics.label;
                    if ((displayValue !== undefined) && (displayValue !== BLANKSTRING)) {
                        label = setGraphics.label;
                        if (!label) {
                            // Reuse the cache element
                            if(pool.label && pool.label.length) {
                                label = setGraphics.label = pool.label.shift();
                                label
                                .attr(_textAttrs)
                                .css(seriesDataLabelsStyle);
                            }
                            // If there is no element in cachestore then create it freshly
                            else {
                                label = setGraphics.label = paper.text(_textAttrs, seriesDataLabelsStyle,
                                    dataLabelsLayer)
                                .mouseover(labelHoverFN)
                                .mouseout(labelOutFN)
                                .mouseup(clickFunc);
                            }
                        }
                        else {
                            label
                            .attr(_textAttrs)
                            .css(seriesDataLabelsStyle);
                        }
                        plotItem.label = label
                        .show()
                        .data('plotItem', plotItem)
                        .data(EVENTARGS, setConfig.eventArgs);
                        isTooltip && label.tooltip(toolText);
                    }
                    else {
                        label && label.hide();
                    }
                }
                else {
                    // at the end of all the tree structure, hide all the pool elements.
                    dataSet.removeChild(dataSet.pool, true);
                }
            }
        }, 'Pie2D']);

    }
]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-dragnode',
    function () {
        var global = this,
            lib = global.hcLib,
            R = lib.Raphael,
            isVML = (R.type === 'VML'),

            //strings
            preDefStr = lib.preDefStr,
            configStr = preDefStr.configStr,
            animationObjStr = preDefStr.animationObjStr,
            visibleStr = preDefStr.visibleStr,
            ZEROSTRING = lib.ZEROSTRING,
            POSITION_TOP = preDefStr.POSITION_TOP,
            POSITION_BOTTOM = preDefStr.POSITION_BOTTOM,
            UNDERSCORE = preDefStr.UNDERSCORE,
            BLANK = lib.BLANKSTRING,
            BLANKSTRING = lib.BLANKSTRING,
            parseTooltext = lib.parseTooltext,
            //add the tools thats are requared
            pluck = lib.pluck,
            getValidValue = lib.getValidValue,
            pluckNumber = lib.pluckNumber,
            getFirstValue = lib.getFirstValue,
            // getDefinedColor = lib.getDefinedColor,
            parseUnsafeString = lib.parseUnsafeString,
            extend2 = lib.extend2, //old: jarendererExtend / margecolone
            toRaphaelColor = lib.toRaphaelColor,
            UNDEFINED,
            // The default value for stroke-dash attribute.
            ROLLOVER = 'DataPlotRollOver',
            ROLLOUT = 'DataPlotRollOut',
            POLYGON = 'polygon',
            CIRCLE = 'circle',
            RECTANGLE = 'rectangle',
            POINTER = 'pointer',
            EVENTARGS = 'eventArgs',
            COMPONENT = 'component',
            DATASET = 'dataset',
            GROUPID = 'groupId',

            schedular = lib.schedular,
            getTouchEvent = lib.getTouchEvent,
            defined = function(obj) {
                return obj !== UNDEFINED && obj !== null;
            },

            OBJECTBOUNDINGBOX = 'objectBoundingBox', // gradient unit
            COMMA = ',',
            POSITION_MIDDLE = 'middle',
            BGRATIOSTRING = lib.BGRATIOSTRING,
            math = Math,
            mathMin = math.min,
            mathMax = math.max,
            hasTouch = lib.hasTouch,
            // getColumnColor = lib.graphics.getColumnColor,
            getFirstColor = lib.getFirstColor,
            // pluckColor = lib.pluckColor,
            getFirstAlpha = lib.getFirstAlpha,
            getDarkColor = lib.graphics.getDarkColor,
            getLightColor = lib.graphics.getLightColor,
            convertColor = lib.graphics.convertColor,
            // renderer = chartAPI,
            mapSymbolName = lib.graphics.mapSymbolName,
            COMMASTRING = lib.COMMASTRING,
            HUNDREDSTRING = lib.HUNDREDSTRING,
            // COMMASPACE = lib.COMMASPACE,
            getMouseCoordinate = lib.getMouseCoordinate,
            plotEventHandler = lib.plotEventHandler,

            //strings
            BLANKSPACE = ' ',

            //add the tools thats are requared
            SHAPE_RECT = lib.SHAPE_RECT,
            stubEvent = {
                pageX: 0,
                pageY: 0
            },
            CLEAR_TIME_1000 = 1000,
            clearLongPress = function() {
                var ele = this;
                ele.data('move', false);
                clearTimeout(ele._longpressactive);
                delete ele._longpressactive;
            };

        // Drag node class
        FusionCharts.register(COMPONENT, [DATASET, 'Dragnode', {
            type: 'dragnode',
            // Configure
            configure: function () {
                var dataSet = this,
                    dIndex = dataSet.index,
                    chartObj = dataSet.chart,
                    chartComp = chartObj.components,
                    JSONData = dataSet.JSONData,
                    data = JSONData.data || [],
                    chartAttr = chartObj.jsonData.chart,
                    dataLength = data.length,
                    conf = dataSet.config,
                    showValues,
                    ZERO = ZEROSTRING,
                    colorM = chartComp.colorManager,
                    index,
                    plotFillAlpha,
                    showPlotBorder,
                    plotBorderColor,
                    plotBorderThickness,
                    plotBorderAlpha,
                    datasetId,
                    datasetPlotBorderThickness,
                    dataStore,
                    dataStoreLen,
                    useRoundEdges,
                    HUNDRED = HUNDREDSTRING;
                showValues = conf.showValues = pluckNumber(JSONData.showvalues, chartAttr.showvalues, 1);
                useRoundEdges = conf.useRoundEdges = pluckNumber(chartAttr.useroundedges);
                conf.zIndex = 1;
                conf.name = getValidValue(JSONData.seriesname);
                conf.viewMode = pluckNumber(chartAttr.viewmode, 0);
                datasetId = conf.id = pluck(JSONData.id, dataSet.index);
                if (pluckNumber(JSONData.includeinlegend) === 0 ||
                    conf.name === undefined) {
                    conf.showInLegend = false;
                }
                conf.includeInLegend = pluckNumber(JSONData.includeinlegend, 1);

                conf.showTooltip = pluckNumber(chartAttr.showtooltip, 1);
                conf.seriesNameInTooltip = pluckNumber(chartAttr.seriesnameintooltip, 1);
                conf.tooltipSepChar = pluck(chartAttr.tooltipsepchar, ' - ');
                //Plot Properties
                plotFillAlpha = conf.plotFillAlpha = pluck(chartAttr.plotfillalpha, HUNDRED);
                showPlotBorder = conf.showPlotBorder = pluckNumber(chartAttr.showplotborder, 1);
                plotBorderColor = conf.plotBorderColor = getFirstColor(pluck(chartAttr.plotbordercolor, '666666'));
                plotBorderThickness = conf.plotBorderThickness = pluckNumber(chartAttr.plotborderthickness,
                    useRoundEdges ? 2 : 1);
                plotBorderAlpha = conf.plotBorderAlpha = pluck(chartAttr.plotborderalpha, chartAttr.plotfillalpha,
                    useRoundEdges ? '35' : '95');

                //Node Properties
                conf.use3DLighting = Boolean(pluckNumber(chartAttr.use3dlighting,
                    chartAttr.is3d, useRoundEdges ? 1 : 0));
                //Store attributeshc
                conf.color = getFirstColor(pluck(JSONData.color, colorM.getPlotColor(dIndex)));
                conf.alpha = pluck(JSONData.plotfillalpha, JSONData.nodeFillAlpha,
                    JSONData.alpha, plotFillAlpha);
                //Data set plot properties
                conf.datasetShowPlotBorder = Boolean(pluckNumber(JSONData.showplotborder, showPlotBorder));
                conf.datasetPlotBorderColor = getFirstColor(pluck(JSONData.plotbordercolor, JSONData.nodebordercolor,
                    plotBorderColor));
                conf.datasetPlotBorderThickness = pluckNumber(JSONData.plotborderthickness,
                    JSONData.nodeborderthickness, plotBorderThickness);
                conf.datasetPlotBorderAlpha = (conf.datasetShowPlotBorder) ? pluck(JSONData.plotborderalpha,
                    JSONData.nodeborderalpha, JSONData.alpha, plotBorderAlpha) : ZERO;
                conf.seriesname = parseUnsafeString(JSONData.seriesname);
                //Drag Border properties
                conf.datasetAllowDrag = Boolean(pluckNumber(JSONData.allowdrag, 1));

                conf.colorObj = {
                    fillColor: convertColor(conf.color, conf.alpha),
                    lineColor: {
                        FCcolor: {
                            color: conf.datasetPlotBorderColor,
                            alpha: conf.datasetPlotBorderAlpha
                        }
                    }
                };
                conf.lineWidth = datasetPlotBorderThickness;
                conf.symbol = 'poly_4';
                dataStore = dataSet.components.data = dataSet.components.data || (dataSet.components.data = []);
                dataStoreLen = dataStore.length;
                if (dataStoreLen > dataLength) {
                    dataStore.splice(dataLength, dataStoreLen - dataLength);

                }

                dataSet.visible = pluckNumber(JSONData.visible,
                    !Number(JSONData.initiallyhidden), 1) === 1;
                conf.yMin = conf.yMax = conf.xMax = conf.xMin = 0;
                // This flag is true when data update is fired
                dataSet._refreshData = true;
                // Iterate through all level data
                for (index = 0; index < dataLength; index += 1) {
                    this._setConfigure(index);
                }
                dataSet._refreshData = false;
                dataSet._addLegend();
            },
            _setConfigure: function (index, updateObj) {
                var dataset = this,
                    JSONData = dataset.JSONData,
                    data = JSONData.data,
                    setData = updateObj ? updateObj : data[index],
                    dataStore = dataset.components.data,
                    conf = dataset.config,
                    dataObj = dataStore[index] = dataStore[index] || (dataStore[index] = {}),
                    config = dataObj.config = dataObj.config || (dataObj.config = {}),
                    datasetId = conf.id,
                    shape,
                    yMin = conf.yMin || +Infinity,
                    yMax = conf.yMax || -Infinity,
                    xMax = conf.xMax || -Infinity,
                    xMin = conf.xMin || +Infinity,
                    itemValueY,
                    itemValueX,
                    label,
                    safeLabel,
                    shapeType,
                    use3DLighting = conf.use3DLighting,
                    datasetPlotBorderThickness = conf.datasetPlotBorderThickness,
                    datasetPlotBorderColor = conf.datasetPlotBorderColor,
                    datasetPlotBorderAlpha = conf.datasetPlotBorderAlpha,
                    chart = dataset.chart,
                    chartAttr = chart.jsonData.chart,
                    datasetColor = conf.color,
                    datasetAlpha = conf.alpha,
                    fillColor,
                    datasetAllowDrag = conf.datasetAllowDrag,
                    numberFormatter = dataset.chart.components.numberFormatter;
                !dataObj.graphics && (dataObj.graphics = {});
                config._options = extend2({}, setData);
                if (setData || updateObj) {
                    itemValueY = config.y = numberFormatter.getCleanValue(pluck(setData.y));
                    itemValueX = config.x = numberFormatter.getCleanValue(pluck(setData.x));
                    config.index = index;
                    if (!config.dragStart) {
                        config.dragStart = {};
                    }
                    yMax = mathMax(yMax, config.y);
                    yMin = mathMin(yMin, config.y);
                    xMax = mathMax(xMax, config.x);
                    xMin = mathMin(xMin, config.x);
                    if (itemValueY === null) {
                        config.value = null;
                    }
                    else {
                        label = numberFormatter.xAxis(itemValueX);
                        //push the point object
                        config.formatedVal = (itemValueY === null ?
                            itemValueY : numberFormatter.dataLabels(itemValueY)),
                        config.setTooltext = getValidValue(parseUnsafeString(pluck(setData.tooltext,
                            JSONData.plottooltext, chartAttr.plottooltext)));
                        config.pointLabel = pluck(setData.label, setData.name);
                        safeLabel = parseUnsafeString(config.pointLabel);
                        config.label = safeLabel;
                        config.name = safeLabel;
                        config.displayValue = safeLabel;
                        config.xValue = label;

                        config.startConnectors = {};
                        config.endConnectors = {};
                        //create the tooltext
                        if (!conf.showTooltip) {
                            config.toolText = false;
                        }
                        else {
                            config.toolText = dataset._configureTooltext(config, conf, chartAttr);
                        }
                        config.link = setData.link;
                        // Shape and cosmetics related attributes
                        config.id = pluck(setData.id, (datasetId + UNDERSCORE + index));
                        config.allowDrag = Boolean(pluckNumber(setData.allowdrag, datasetAllowDrag));
                        shape = config.shape = getValidValue(pluck(setData.shape), RECTANGLE).toLowerCase(),
                        config.height = getValidValue(pluck(setData.height), 10),
                        config.width = getValidValue(pluck(setData.width), 10),
                        config.radius = getValidValue(pluck(setData.radius), 10),
                        config.numSides = getValidValue(pluck(setData.numsides), 4),
                        config.color = getFirstColor(pluck(setData.color, datasetColor));
                        config.borderColor = getFirstColor(pluck(setData.bordercolor, datasetPlotBorderColor));
                        config.alpha = pluck(setData.alpha, datasetAlpha),
                        config.imageURL = getValidValue(setData.imageurl),
                        config.imageNode = Boolean(pluckNumber(setData.imagenode));
                        config.imageWidth = setData.imagewidth;
                        config.imageHeight = setData.imageheight;
                        config.imageAlign = getValidValue(setData.imagealign, BLANK).toLowerCase();
                        config.labelAlign = pluck(setData.labelalign, config.imageNode &&
                            defined(config.imageURL) ? POSITION_TOP : POSITION_MIDDLE);
                        //If not required shape then set it to rectangle
                        switch (config.shape) {
                        case CIRCLE:
                            shapeType = 0;
                            break;
                        case POLYGON:
                            shapeType = 2;
                            shape = mapSymbolName(config.numSides);
                            break;
                        default:
                            shapeType = 1;
                            break;
                        }
                        config.symbol = shape;
                        if (use3DLighting) {
                            fillColor = config.fillColor = this.getPointColor(config.color,
                                config.alpha, shapeType);
                            config.cloneFillColor = this.getPointColor(config.color, 50, shapeType);
                        } else {
                            fillColor = config.fillColor = {
                                color: config.color,
                                alpha: config.alpha
                            };
                            config.cloneFillColor = convertColor(config.color, 50);
                        }

                        config.rollOverProperties = dataset.pointHoverOptions(dataObj, chartAttr, {
                            shapeType: shapeType,
                            use3D: use3DLighting,
                            height: config.height,
                            width: config.width,
                            radius: config.radius,
                            color: config.color,
                            alpha: config.alpha,
                            borderColor: config.borderColor,
                            borderAlpha: datasetPlotBorderAlpha,
                            borderThickness: datasetPlotBorderThickness
                        });
                    }
                    !config.update && updateObj && (config.update = updateObj.update);
                    !config.add && updateObj && (config.add = updateObj.add);
                    if (dataset._refreshData === true) {
                        delete dataObj.removed;
                    }
                }
                dataObj.dataset = dataset;
                conf.xMax = xMax;
                conf.xMin = xMin;
                conf.yMin = yMin;
                conf.yMax = yMax;
            },
            _configureTooltext: function (config, datasetConf, chartAttr) {
                var setTooltext = config.setTooltext,
                    formatedVal = config.formatedVal,
                    seriesname = datasetConf.seriesname,
                    label = config.label,
                    xValue = config.xValue,
                    pointLabel = config.pointLabel,
                    tooltipSepChar = datasetConf.tooltipSepChar,
                    toolText;
                if (setTooltext !== undefined) {
                    toolText = parseTooltext(setTooltext, [3, 4, 5, 6, 8, 9, 10, 11], {
                        yaxisName: parseUnsafeString(chartAttr.yaxisname),
                        xaxisName: parseUnsafeString(chartAttr.xaxisname),
                        yDataValue: formatedVal,
                        xDataValue: xValue,
                        label: label
                    }, config, chartAttr, datasetConf);
                } else if (pointLabel !== undefined) {
                    toolText = label;
                } else { //determine the tooltext then
                    if (formatedVal === null) {
                        toolText = false;
                    } else {
                        if (datasetConf.seriesNameInToolTip) {
                            seriesname = getFirstValue(datasetConf.seriesname);
                        }
                        toolText = seriesname ? seriesname + tooltipSepChar : BLANK;
                        toolText += xValue ? xValue + tooltipSepChar : BLANK;
                        toolText += formatedVal;
                    }
                }
                return toolText;
            },
            updatePointConfig: function (updateConf, index) {
                var dataset = this,
                    chart = dataset.chart,
                    dataStore = dataset.components.data,
                    conf = dataset.config,
                    dataObj = dataStore[index] || {},
                    config = dataObj.config,
                    numberFormatter = chart.components.numberFormatter,
                    chartAttr = chart.jsonData.chart,
                    yMin = conf.yMin || +Infinity,
                    yMax = conf.yMax || -Infinity,
                    xMax = conf.xMax || -Infinity,
                    xMin = conf.xMin || +Infinity,
                    xValue;
                if (config === UNDEFINED) {
                    return;
                }
                config.y = numberFormatter.getCleanValue(pluck(updateConf.y));
                config.x = numberFormatter.getCleanValue(pluck(updateConf.x));
                config._options.x = config.x;
                config._options.y = config.y;
                yMax = mathMax(yMax, config.y);
                yMin = mathMin(yMin, config.y);
                xMax = mathMax(xMax, config.x);
                xMin = mathMin(xMin, config.x);
                xValue = numberFormatter.xAxis(config.x);
                //push the point object
                config.formatedVal = (config.y === null ?
                    config.y : numberFormatter.dataLabels(config.y));
                config.xValue = xValue;
                if (!conf.showTooltip) {
                    config.toolText = false;
                }
                else {
                    config.toolText = dataset._configureTooltext(config, conf, chartAttr);
                }
                config.update = updateConf.update;
            },
            pointHoverOptions: function(dataObj, chartAttr, defaults) {
                var dataset = this,
                    hoverEffect = pluckNumber(dataObj.showhovereffect, dataset.showhovereffect,
                        chartAttr.plothovereffect, chartAttr.showhovereffect),
                    rolloverProperties = {},
                    hoverAttr = !!pluck(dataObj.hovercolor, dataset.hovercolor, chartAttr.plotfillhovercolor,
                        dataObj.hoveralpha, dataset.hoveralpha, chartAttr.plotfillhoveralpha,
                        dataObj.borderhovercolor, dataset.borderhovercolor, chartAttr.plotborderhovercolor,
                        dataObj.borderhoveralpha, dataset.borderhoveralpha, chartAttr.plotborderhoveralpha,
                        dataObj.borderhoverthickness, dataset.borderhoverthickness, chartAttr.plotborderhoverthickness,
                        dataObj.hoverheight, dataset.hoverheight, chartAttr.plothoverheight,
                        dataObj.hoverwidth, dataset.hoverwidth, chartAttr.plothoverwidth,
                        dataObj.hoverradius, dataset.hoverradius, chartAttr.plothoverradius, hoverEffect),
                    enabled = false,
                    color,
                    alpha,
                    fillColor;

                if ((hoverEffect === UNDEFINED && hoverAttr) || hoverEffect) {
                    enabled = true;
                    color = pluck(dataObj.hovercolor, dataset.hovercolor,
                        chartAttr.plotfillhovercolor, getLightColor(defaults.color, 70));
                    alpha  = pluck(dataObj.hoveralpha, dataset.hoveralpha,
                        chartAttr.plotfillhoveralpha, defaults.alpha);

                    rolloverProperties = {
                        stroke: convertColor(pluck(dataObj.borderhovercolor, dataset.borderhovercolor,
                            chartAttr.plotborderhovercolor, defaults.borderColor),
                            pluckNumber(dataObj.borderhoveralpha, dataset.borderhoveralpha,
                            chartAttr.plotborderhoveralpha, alpha, defaults.borderAlpha)),
                        'stroke-width': pluckNumber(dataObj.borderhoverthickness, dataset.borderhoverthickness,
                            chartAttr.plotborderhoverthickness, defaults.borderThickness),
                        height: pluckNumber(dataObj.hoverheight, dataset.hoverheight,
                            chartAttr.plothoverheight, defaults.height),
                        width: pluckNumber(dataObj.hoverwidth, dataset.hoverwidth,
                            chartAttr.plothoverwidth, defaults.width),
                        r: pluckNumber(dataObj.hoverradius, dataset.hoverradius,
                            chartAttr.plothoverradius, defaults.radius)
                    };

                    if (defaults.use3D) {
                        fillColor = this.getPointColor(getFirstColor(pluck(dataObj.hovercolor,
                            dataset.hovercolor, chartAttr.plotfillhovercolor,
                                getLightColor(defaults.color, 70))),
                            pluck(dataObj.hoveralpha, dataset.hoveralpha,
                                chartAttr.plotfillhoveralpha, defaults.alpha),
                            defaults.shapeType);
                    } else {
                        fillColor = convertColor(color, alpha);
                    }

                    rolloverProperties.fill = toRaphaelColor(fillColor);
                }

                return {
                    enabled: enabled,
                    rollOverAttrs: rolloverProperties
                };
            },
            // Get json data of dragnode dataset
            getJSONData: function () {
                var dataset = this,
                    dataStore = dataset.components.data,
                    len = dataStore.length,
                    jsonData = [],
                    dataObj,
                    i;
                for (i = 0; i < len; i++) {
                    dataObj = dataStore[i];
                    if (!dataObj.removed) {
                        if (dataObj.config._options) {
                            delete dataObj.config._options.update;
                            delete dataObj.config._options.add;
                            jsonData.push(dataObj.config._options);
                        }
                    }
                }
                return jsonData;
            },
            // Function that produce the point color
            getPointColor: function(color, alpha, shapeType) {
                var colorObj, innerColor, outerColor;
                color = getFirstColor(color);
                alpha = getFirstAlpha(alpha);
                innerColor = getLightColor(color, 80);
                outerColor = getDarkColor(color, 65);
                colorObj = {
                    FCcolor: {
                        gradientUnits: OBJECTBOUNDINGBOX,
                        color: innerColor + COMMA + outerColor,
                        alpha: alpha + COMMA + alpha,
                        ratio: BGRATIOSTRING
                    }
                };

                if (shapeType) {
                    if (shapeType === 1) {
                        colorObj.FCcolor.angle = 0;
                    } else {
                        colorObj.FCcolor.angle = 180;
                    }
                } else {
                    colorObj.FCcolor.cx = 0.4;
                    colorObj.FCcolor.cy = 0.4;
                    colorObj.FCcolor.r = '50%';
                    colorObj.FCcolor.radialGradient = true;
                }

                return colorObj;
            },
            init: function (jsonData) {
                var dataSet = this,
                    chart = dataSet.chart;
                dataSet.yAxis = chart.components.yAxis[0];
                dataSet.components = {

                };
                dataSet.graphics = {

                };

                dataSet.JSONData = jsonData;
                dataSet.plotType = 'dragnode';
                dataSet.configure();

            },
            _addLegend: function () {
                var dataset = this,
                    chart = dataset.chart,
                    conf = dataset.config,
                    legend = chart.components.legend,
                    config = {
                        enabled: conf.includeInLegend,
                        type : dataset.type,
                        fillColor : toRaphaelColor({
                            color: conf.color,
                            alpha: conf.alpha
                        }),
                        strokeColor: toRaphaelColor({
                            color: conf.plotBorderColor,
                            alpha: HUNDREDSTRING
                        }),
                        anchorSide: 4,
                        strokeWidth: conf.anchorBorderThickness,
                        label : getFirstValue(dataset.JSONData.seriesname)
                    };
                dataset.legendItemId = legend.addItems(dataset, dataset.legendInteractivity, config);
            },
            draw: function () {
                var dataset = this,
                    components = dataset.components,
                    datasetGraphics = dataset.graphics,
                    chart = dataset.chart,
                    jobList = chart.getJobList(),
                    smartLabel = chart.linkedItems.smartLabel,
                    data = components.data,
                    removeDataArr = dataset.components.removeDataArr || [],
                    removeDataArrLen = removeDataArr.length,
                    i,
                    paper = chart.components.paper,
                    ln,
                    group,
                    config,
                    style = chart.config.dataLabelStyle,
                    css = {
                        fontFamily: style.fontFamily,
                        fontSize: style.fontSize,
                        lineHeight: style.lineHeight,
                        fontWeight: style.fontWeight,
                        fontStyle: style.fontStyle
                    },
                    dragLabelGroup,
                    removed,
                    layers = chart.graphics,//requird for series drawing
                    gDataset = layers.datasetGroup;
                group = datasetGraphics.group = (datasetGraphics.group || paper.group(gDataset));
                dragLabelGroup = datasetGraphics.dragLabelGroup = (datasetGraphics.dragLabelGroup ||
                    paper.group('dragLabelGroup', gDataset));
                group.trackTooltip(true);
                smartLabel.useEllipsesOnOverflow(chart.config.useEllipsesWhenOverflow);
                smartLabel.setStyle(style);
                group.css(css);
                //draw data
                for (i = 0, ln = data.length; i < ln; i += 1) {
                    config = data[i].config;
                    removed = data[i].removed;
                    !removed && this._drawNode(i);
                }
                // jobList.trackerDrawID.push(schedular.addJob(dataset.drawTracker, dataset, [],
                //     lib.priorityList.tracker));
                !dataset.drawn && jobList.labelDrawID.push(schedular.addJob(dataset.drawLabel, dataset, [],
                    lib.priorityList.label));
                dataset.drawn = true;

                if (dataset.visible) {
                    group.show();
                    dragLabelGroup.show();
                }
                // Remove the extra elements
                for (i = 0; i < removeDataArrLen; i++) {
                    dataset._removeDataVisuals(removeDataArr.shift());
                }

            },
            rolloverResponseSetter: function (elem, enabled) {
                return function (data) {
                    var ele = this,
                        _data = ele.data('drag-options'),
                        chart = _data.chart,
                        dataObj = _data.dataObj,
                        config = dataObj.config,
                        dragStart = config.dragStart,
                        keysNo = dragStart && Object.keys(dragStart).length,
                        hoverAttr = ele.data('hoverAttr');
                    if (!keysNo) {
                        enabled && elem.graphics.element.attr(hoverAttr);
                        plotEventHandler.call(ele, chart, data, ROLLOVER);
                    }
                };
            },
            rolloutResponseSetter: function (elem, enabled) {
                return function (data) {
                    var ele = this,
                        _data = ele.data('drag-options'),
                        dataObj = _data.dataObj,
                        chart = _data.chart,
                        config = dataObj.config,
                        dragStart = config.dragStart,
                        keysNo = dragStart && Object.keys(dragStart).length,
                        unHoverAttr = ele.data('unHoverAttr');
                    if (!keysNo) {
                        enabled && elem.graphics.element.attr(unHoverAttr);
                        plotEventHandler.call(ele, chart, data, ROLLOUT);
                    }
                };
            },
            dragUp: function (event) {
                var ele = this,
                    data = ele.data('drag-options'),
                    dataset = data.dataset;
                dataset._dragUp.call(ele, event);
            },
            dragMove: function (dx, dy, px, py) {
                var ele = this,
                    data = ele.data('drag-options'),
                    dataset = data.dataset,
                    chart = data.chart;
                dataset._dragMove.call(ele, dx, dy, px, py, chart);
            },
            dragStart: function (x, y, event) {
                var ele = this,
                    data = ele.data('drag-options'),
                    dataset = data.dataset,
                    chart = data.chart;
                dataset._dragStart.call(ele, event, chart);
            },
            _drawNode: function (i) {
                var dataset = this,
                    chart = dataset.chart,
                    datasetIndex = dataset.index,
                    chartComp = chart.components,
                    manager = dataset.groupManager,
                    nodes = manager.nodes,
                    paper = chartComp.paper,
                    xAxis = dataset.xAxis = chartComp.xAxis[0],
                    yAxis = dataset.yAxis = chartComp.yAxis[0],
                    data = dataset.components.data,
                    set = data[i],
                    config = set.config,
                    conf = dataset.config,
                    animationObj = chart.get(configStr, animationObjStr) || {},
                    animation = animationObj.duration,
                    dummyAnimElem = animationObj.dummyObj,
                    dummyAnimObj = animationObj.animObj,
                    xPos,
                    yPos,
                    setGraphics = set.graphics || (set.graphics = {}),
                    symbol = config.symbol,
                    width,
                    height,
                    radius,
                    id,
                    groupId,
                    imageNode,
                    confShapeArg,
                    imageURL,
                    imageAlign,
                    labelAlign,
                    lineColor = conf.colorObj.lineColor,
                    lineWidth = conf.datasetPlotBorderThickness,
                    plotWidth,
                    plotHeight,
                    isRectangle,
                    layers = chart.graphics,
                    datasetGraphics = dataset.graphics,
                    gDataset = layers.datasetGroup,
                    group = datasetGraphics.group,
                    rollOverProperties = set.config.rollOverProperties,
                    imageWidth,
                    imageHeight,
                    imageY,
                    graphic,
                    pointAttr,
                    pointOptions,
                    rolloverResponseSetter = dataset.rolloverResponseSetter,
                    rolloutResponseSetter = dataset.rolloutResponseSetter,
                    dragUp = dataset.dragUp,
                    dragMove = dataset.dragMove,
                    dragStart = dataset.dragStart,
                    fill,
                    link,
                    eventArgs,
                    shapeType = config.shapeType,
                    cursor = config.link ? POINTER : config.allowDrag ? 'move' : BLANKSTRING,
                    rollOverAttrs,
                    pool = dataset.components.pool || {},
                    poolElemType,
                    type,
                    polypath,
                    setElement = setGraphics.graphic,
                    cloneText = setGraphics.cloneText,
                    cloneGraphic = setGraphics.cloneGraphic,
                    cloneImage = setGraphics.cloneImage,
                    imageElement = setGraphics.image,
                    attr,
                    elemType,
                    labelElement = setGraphics.label;

                datasetGraphics.cloneGraphicGroup = datasetGraphics.cloneGraphicGroup ||
                        paper.group('clone', gDataset);

                datasetGraphics.cloneGraphicGroup.attr({
                    opacity: 0.3
                });

                config._yPos = yPos = yAxis.getAxisPosition(config.y);
                config._xPos = xPos = xAxis.getAxisPosition(config.x);
                // only draw the point if y is defined
                if (yPos !== UNDEFINED && !isNaN(yPos)) {
                    config.shapeArg = {};
                    confShapeArg = config.shapeArg;
                    pointOptions = set._options;
                    graphic = set.graphic;
                    height = pluckNumber(config.height);
                    width = pluckNumber(config.width);
                    radius = pluckNumber(config.radius);
                    isRectangle = symbol === RECTANGLE;
                    id = config.id;
                    imageNode = config.imageNode;
                    imageURL = config.imageURL;
                    imageAlign = config.imageAlign; //TOP, MIDDLE or BOTTOM
                    labelAlign = config.labelAlign;
                    plotWidth = isRectangle ? width : radius * 1.4;
                    imageWidth = pluckNumber(config.imageWidth, plotWidth);
                    plotHeight = isRectangle ? height : radius * 1.4;
                    imageHeight = pluckNumber(config.imageHeight, plotHeight),
                    link = config.link;
                    fill = toRaphaelColor(config.fillColor);
                    config._plotWidth = plotWidth;
                    config._plotHeight = plotHeight;
                    pointAttr = {
                        fill: fill,
                        'stroke-width': lineWidth,
                        stroke: toRaphaelColor(lineColor)
                    };
                    symbol = confShapeArg.symbol = pluck(config.symbol,
                        conf.symbol, BLANK);
                    symbol = symbol.split(UNDERSCORE);

                    polypath = [symbol[1], xPos, yPos, config.radius, config.startAngle, 0];

                    if (symbol[0] === 'poly' || symbol[0] === CIRCLE) {
                        config.shapeType = symbol[0];
                        elemType = 'polypath';
                        poolElemType = 'path';
                        attr = {
                            polypath: polypath
                        };
                        confShapeArg.x = xPos;
                        confShapeArg.y = yPos;
                        confShapeArg.radius = config.radius;
                        confShapeArg.sides = symbol[1];
                    }
                    else {
                        config.shapeType = SHAPE_RECT;
                        elemType = 'rect';
                        poolElemType = 'rect';
                        confShapeArg.x = xPos - (width / 2);
                        confShapeArg.y = yPos - (height / 2);
                        confShapeArg.r = 0;
                        confShapeArg.width = width;
                        confShapeArg.height = height;
                        attr = {
                            x: confShapeArg.x,
                            y: confShapeArg.y,
                            width: width,
                            height: height,
                            r: 0
                        };
                        pointAttr.width = width;
                        pointAttr.height = height;
                        pointAttr.x = xPos - (width / 2);
                        pointAttr.y = yPos - (height / 2);
                        // Readjust x and y of the rectangle if hover width or height is
                        // changed
                        if (rollOverProperties && rollOverProperties.enabled) {
                            rollOverAttrs = rollOverProperties.rollOverAttrs;
                            rollOverAttrs.x = xPos - (rollOverAttrs.width / 2);
                            rollOverAttrs.y = yPos - (rollOverAttrs.height / 2);
                            delete rollOverAttrs.r;
                        }
                    }

                    setElement = setGraphics.element;
                    type = setElement && setElement.type;
                    if (elemType.indexOf(type) === -1 && setElement) {
                        setElement.remove();
                        setElement = setGraphics.element = null;
                        labelElement && labelElement.remove();
                        imageElement && imageElement.remove();
                        delete setGraphics.label;
                        delete setGraphics.image;
                        imageElement = null;
                        labelElement = null;
                    }

                    // Create a new element
                    if (!setElement) {
                        // Reuse element from pool if any
                        if (pool.element && pool.element[poolElemType] &&
                            pool.element[poolElemType].length) {
                            setElement = setGraphics.element = pool.element[poolElemType].shift();
                            setElement.toFront();
                        }
                        else {
                            setElement = setGraphics.element = paper[elemType](group);
                            setElement.attr(attr);
                        }

                        setElement.hover(rolloverResponseSetter(set,
                            rollOverProperties && rollOverProperties.enabled),
                            rolloutResponseSetter(set, rollOverProperties && rollOverProperties.enabled));

                        // If dragging is allowed for that node then only we bind drag functions to the setElement
                        setElement.drag(dragMove, dragStart, dragUp);
                    }


                    setElement.show().animateWith(dummyAnimElem, dummyAnimObj, attr, animation);

                    setElement.attr({
                        fill: fill,
                        'stroke-width': lineWidth,
                        stroke: toRaphaelColor(lineColor)
                    });

                    manager.animationDone = true;

                    eventArgs = {
                        index: i,
                        link: config.link,
                        y: config.y,
                        x: config.x,
                        shape: pluck(shapeType, 'rect'),
                        width: width,
                        height: height,
                        radius: radius,
                        sides: config.numSides,
                        label: config.displayValue,
                        toolText: config.toolText,
                        id: config.id,
                        datasetIndex: dataset.index,
                        datasetName: dataset.JSONData.seriesname,
                        sourceType: 'dataplot'
                    };
                    groupId = datasetIndex + '_' + i;

                    if (cloneGraphic) {
                        if (cloneGraphic.type === setElement.type) {
                            attr.fill = fill;
                            attr['stroke-width'] = lineWidth;
                            attr.stroke = toRaphaelColor(lineColor);
                            cloneGraphic.transform(BLANKSTRING);
                            cloneGraphic.attr(attr);
                        }
                        else  {
                            cloneGraphic.remove();
                            delete set.graphics.cloneGraphic;
                            /*if (cloneImage) {
                                cloneImage.remove();
                                delete set.graphics.cloneImage;
                            }*/
                            if (cloneText) {
                                cloneText.remove();
                                delete set.graphics.cloneText;
                            }
                        }
                    }

                    // Draw the imageNode if available
                    if (imageNode && imageURL) {
                        if (imageHeight > plotHeight) {
                            imageHeight = plotHeight;
                        }
                        if (imageWidth > plotWidth) {
                            imageWidth = plotWidth;
                        }
                        switch (imageAlign) {
                        case POSITION_MIDDLE:
                            imageY = yPos - (imageHeight / 2);
                            break;
                        case POSITION_BOTTOM:
                            imageY = plotHeight > imageHeight ? yPos +
                                (plotHeight / 2) - imageHeight :
                                yPos - imageHeight / 2;
                            break;
                        default:
                            imageY = plotHeight > imageHeight ?
                                yPos - (plotHeight * 0.5) :
                                yPos - imageHeight / 2;
                            break;
                        }
                        config.imageX = xPos - (imageWidth / 2);
                        config.imageY = imageY;
                        config.imageWidth = imageWidth;
                        config.imageHeight = imageHeight;
                        poolElemType = 'image';
                        if (!imageElement) {
                            if (pool.image && pool.image[poolElemType] && pool.image[poolElemType].length) {
                                imageElement = setGraphics.image = pool.image[poolElemType].shift();
                                imageElement.toFront();
                            }
                            else {
                                imageElement = setGraphics.image = paper.image(group);
                                imageElement.tooltip(config.toolText);
                                imageElement.hover(rolloverResponseSetter(set,
                                    rollOverProperties && rollOverProperties.enabled),
                                    rolloutResponseSetter(set, rollOverProperties && rollOverProperties.enabled));

                                // If dragging is allowed for that node then only
                                //we bind drag functions to the imageElement
                                imageElement.drag(dragMove, dragStart, dragUp);
                            }
                        }

                        imageElement.show().attr({
                            src: imageURL,
                            x: config.imageX,
                            y: imageY,
                            width: imageWidth,
                            height: imageHeight
                        });

                        imageElement.attr({
                            cursor : cursor
                        });
                        imageElement.tooltip(config.toolText);

                        imageElement.data('drag-options',{
                                dataObj: set,
                                dataset: dataset,
                                datasetIndex: dataset.index,
                                pointIndex: set.config.index,
                                cursor: cursor,
                                chart: chart,
                                link: set.link
                            });

                        imageElement.data(GROUPID, groupId);
                        imageElement.data(EVENTARGS, eventArgs);
                        imageElement.data('hoverAttr', rollOverProperties && rollOverProperties.rollOverAttrs);
                        imageElement.data('unHoverAttr', pointAttr);

                        if (cloneImage) {
                            cloneImage.transform(BLANKSTRING);
                            cloneImage.attr({
                                src: imageURL,
                                x: config.imageX,
                                y: imageY,
                                width: imageWidth,
                                height: imageHeight
                            });
                        }
                    }
                    config.pointAttr = pointAttr;
                    dataset.drawn && dataset.drawLabel(i);
                    nodes[id] = set;



                    setElement.attr({
                        cursor : cursor
                    });
                    setElement.tooltip(config.toolText);

                    setElement.data('drag-options',{
                            dataObj: set,
                            dataset: dataset,
                            datasetIndex: dataset.index,
                            pointIndex: set.config.index,
                            cursor: cursor,
                            chart: chart,
                            link: set.link
                        });



                    setElement.data(GROUPID, groupId);
                    setElement.data(EVENTARGS, eventArgs);
                    setElement.data('hoverAttr', rollOverProperties && rollOverProperties.rollOverAttrs);
                    setElement.data('unHoverAttr', pointAttr);
                }
            },
            drawLabel: function (index) {
                var dataset = this,
                    chart = dataset.chart,
                    datasetIndex = dataset.index,
                    paper = chart.components.paper,
                    dataStore = dataset.components.data,
                    i,
                    len = dataStore.length,
                    labelAttrs,
                    labelElement,
                    group = dataset.graphics.group,
                    style = chart.config.dataLabelStyle,
                    animationObj = chart.get('config', 'animationObj'),
                    dummyAnimElem = animationObj.dummyObj,
                    dummyAnimObj = animationObj.animObj,
                    animationDuration = animationObj.duration,
                    pool = dataset.components.pool || {},
                    config,
                    valueString,
                    chartConfig = chart.config,
                    poolElemType,
                    cursor,
                    smartTextObj,
                    labelDisplacement,
                    eventArgs,
                    set,
                    yAdjustment,
                    animType = animationObj.animType,
                    xPos,
                    labelY,
                    groupId,
                    cloneText,
                    plotWidth,
                    plotHeight,
                    labelAlign,
                    setGraphics,
                    rolloverResponseSetter = dataset.rolloverResponseSetter,
                    rolloutResponseSetter = dataset.rolloutResponseSetter,
                    dragUp = dataset.dragUp,
                    dragMove = dataset.dragMove,
                    dragStart = dataset.dragStart,
                    rollOverProperties,
                    shapeType,
                    yPos,
                    smartLabel = chart.linkedItems.smartLabel,
                    setElement;


                if (index !== UNDEFINED) {
                    i = index;
                    len = i + 1;
                }
                else {
                    i = 0;
                }

                for (; i < len; i++) {
                    set = dataStore[i];
                    config = set.config;
                    plotWidth = config._plotWidth;
                    plotHeight = config._plotHeight;
                    valueString = config.displayValue;
                    labelAlign = config.labelAlign;
                    setGraphics = set.graphics;
                    cloneText = setGraphics.cloneText;
                    rollOverProperties = set.config.rollOverProperties;
                    shapeType = config.shapeType;

                    if (defined(valueString) || valueString !== BLANK) {
                        poolElemType = 'text';
                        // Get the displayValue text according to the canvas width.
                        smartLabel.useEllipsesOnOverflow(chartConfig.useEllipsesWhenOverflow);
                        smartTextObj = smartLabel.getSmartText(valueString,
                            plotWidth, plotHeight);

                        // label displacement for top or bottom
                        labelDisplacement = plotHeight * 0.5 -
                            (smartTextObj.height * 0.5);
                        // label at TOP
                        switch (labelAlign) {
                            case POSITION_TOP:
                                labelDisplacement = -labelDisplacement;
                                break;
                            case POSITION_BOTTOM:
                                labelDisplacement = labelDisplacement;
                                break;
                            default:
                                labelDisplacement = 0;
                                break;
                        }
                        xPos = config._xPos;
                        yPos = config._yPos;
                        set._yAdjustment = yAdjustment = labelDisplacement;
                        labelY = yPos + yAdjustment;

                        labelAttrs = {
                            text: smartTextObj.text,
                            title: (smartTextObj.tooltext || BLANKSTRING),
                            fill: style.color,
                            'text-bound': [style.backgroundColor, style.borderColor,
                                style.borderThickness, style.borderPadding,
                                style.borderRadius, style.borderDash
                            ]
                        };

                        labelElement = setGraphics.label =
                            setGraphics.label || (pool.label && pool.label[poolElemType] &&
                                pool.label[poolElemType].shift());

                        if (!labelElement) {
                            labelAttrs.x = xPos;
                            labelAttrs.y = labelY;
                            labelElement = setGraphics.label = paper.text(labelAttrs, group);

                            labelElement.hover(rolloverResponseSetter(set,
                                rollOverProperties && rollOverProperties.enabled),
                                rolloutResponseSetter(set, rollOverProperties && rollOverProperties.enabled));

                            // If dragging is allowed for that node then only we bind drag functions to the labelElement
                            labelElement.drag(dragMove, dragStart, dragUp);
                        }
                        else {
                            labelElement.attr(labelAttrs);
                            labelElement.show().animateWith(dummyAnimElem, dummyAnimObj, {
                                x: xPos,
                                y: labelY
                            }, animationDuration, animType);
                        }

                        setElement = setGraphics && (setGraphics.image || setGraphics.element);

                        setElement && labelElement.insertAfter(setElement);

                        if (cloneText) {
                            cloneText.transform(BLANKSTRING);
                            cloneText.attr({
                                x: xPos,
                                y: labelY,
                                text: smartTextObj.text,
                                title: (smartTextObj.tooltext || BLANKSTRING),
                                fill: style.color,
                                'text-bound': [style.backgroundColor, style.borderColor,
                                    style.borderThickness, style.borderPadding,
                                    style.borderRadius, style.borderDash
                                ]
                            });
                        }
                        cursor = config.link ? POINTER : config.allowDrag ? 'move' : BLANKSTRING;
                        labelElement.attr({
                            cursor : cursor
                        });
                        labelElement.tooltip(config.toolText);

                        labelElement.data('drag-options',{
                                dataObj: set,
                                dataset: dataset,
                                datasetIndex: dataset.index,
                                pointIndex: set.config.index,
                                cursor: cursor,
                                chart: chart,
                                link: set.link
                            });

                        eventArgs = {
                            index: i,
                            link: config.link,
                            y: config.y,
                            x: config.x,
                            shape: pluck(shapeType, 'rect'),
                            width: config.width,
                            height: config.height,
                            radius: config.radius,
                            sides: config.numSides,
                            label: config.displayValue,
                            toolText: config.toolText,
                            id: config.id,
                            datasetIndex: dataset.index,
                            datasetName: dataset.JSONData.seriesname,
                            sourceType: 'dataplot'
                        };

                        groupId = datasetIndex + '_' + i;
                        labelElement.data(GROUPID, groupId);
                        labelElement.data(EVENTARGS, eventArgs);
                        labelElement.data('hoverAttr', rollOverProperties && rollOverProperties.rollOverAttrs);
                        labelElement.data('unHoverAttr', setElement.data('unHoverAttr'));
                    }
                    else {
                        setGraphics.label && setGraphics.label.hide();
                    }
                }

            },
            _removeDataVisuals : function (dataObj) {
                var dataSet = this,
                    pool = dataSet.components.pool || (dataSet.components.pool = {}),
                    elementPool,
                    ele,
                    graphics,
                    elemSpecificPool,
                    type,
                    graphicsObj;
                if (!dataObj) {
                    return;
                }
                graphics = dataObj.graphics;
                for (ele in graphics) {
                    elementPool = pool[ele] || (pool[ele] = {});

                    graphicsObj = graphics[ele];
                    type = graphicsObj && graphicsObj.type;
                    elemSpecificPool = elementPool[type] || (elementPool[type] = []);

                    if (graphicsObj.hide && typeof graphicsObj.hide === 'function') {
                        graphicsObj.attr({
                            'text-bound': []
                        });
                        graphicsObj.hide();
                        graphicsObj.transform && graphicsObj.transform(BLANKSTRING);
                    }
                    elemSpecificPool.push(graphics[ele]);
                }
            },
            show: function () {
                var dataset = this,
                    graphics = dataset.graphics,
                    group = graphics.group,
                    dragLabelGroup = graphics.dragLabelGroup;

                group.show();
                dragLabelGroup.show();
                dataset.visible = true;

            },
            hide: function () {
                var dataset = this,
                    graphics = dataset.graphics,
                    group = graphics.group,
                    dragLabelGroup = graphics.dragLabelGroup;
                group.hide();
                dragLabelGroup.hide();
                dataset.visible = false;
            },
            _dragStart: function (e, chart) {
                var element = this,
                    data = element.data('drag-options'),
                    dataObj = data.dataObj,
                    dataGraphics = dataObj.graphics,
                    ele = dataGraphics.element,
                    bBox = ele.getBBox(),
                    config = dataObj.config,
                    dataset = data.dataset,
                    groupManager = dataset.groupManager,
                    graphics  = groupManager.graphics,
                    waitElement = graphics.waitElement,
                    conf = data.dataset.config,
                    viewMode = conf.viewMode,
                    touchEvent = (hasTouch && getTouchEvent(e)) || stubEvent,
                    layerX = e.layerX || touchEvent.layerX,
                    layerY = e.layerY || touchEvent.layerY,
                    paper = chart.components.paper,
                    trackerGroup = dataset.graphics.group,
                    dragStart = config.dragStart || (config.dragStart = {}),
                    cloneGraphic = dataObj.graphics.cloneGraphic,
                    cloneGraphicGroup = dataset.graphics.cloneGraphicGroup,
                    cloneText = dataObj.graphics.cloneText,
                    image = dataObj.graphics.image,
                    displayValue = config.displayValue,
                    cloneImage = dataObj.graphics.cloneImage,
                    style = chart.config.dataLabelStyle,
                    labelAttr,
                    label = dataObj.graphics.label,
                    shapesInfo = {
                        circle: 'circ',
                        rectangle: 'rect',
                        polygon: 'poly'
                    },
                    attr;
                // Set dirty flag to 1 so that bbox is recalculated again
                if (isVML) {
                    ele._.dirty = 1;
                }

                attr = [config.symbol.split(UNDERSCORE)[1], config._xPos,
                        config._yPos, config.radius, config.startAngle, 0];
                labelAttr = {
                    text: displayValue,
                    'class': 'fusioncharts-label',
                    x: config._xPos,
                    y: config._yPos,
                    fill: 'rgba(96,99,78,.4)',
                    'font-size': style.fontSize,
                    'font-weight': style.fontWeight,
                    'font-style': style.fontStyle,
                    'font-family': style.fontFamily,
                    visibility: visibleStr
                };
                if (config.allowDrag) {
                    if (!cloneGraphic && dataObj.graphics.element) {
                        cloneGraphic = dataObj.graphics.cloneGraphic = dataObj.graphics.element.clone();
                        cloneGraphicGroup.appendChild(cloneGraphic);
                    }
                    if (label && !cloneText) {
                        cloneText = dataObj.graphics.cloneText = dataObj.graphics.label.clone();
                        if (cloneText.followers[0] && cloneText.followers[0].el) {
                            cloneGraphicGroup.appendChild(cloneText.followers[0].el);
                        }
                        cloneGraphicGroup.appendChild(cloneText);
                    }
                    if (image && !cloneImage) {
                        cloneImage = dataObj.graphics.cloneImage =
                            dataObj.graphics.image.clone();
                        cloneGraphicGroup.appendChild(cloneImage);
                    }
                    cloneText && cloneText.show();
                    cloneImage && cloneImage.show();
                    cloneGraphic && cloneGraphic.show();
                }
                dragStart.xPos = config._xPos;
                dragStart.yPos = config._yPos;
                dragStart.x = config.x;
                dragStart.y = config.y;
                dragStart.bBox = bBox;
                 // store original x, y positions
                dragStart.origX = dragStart.lastDx || (dragStart.lastDx = 0);
                dragStart.origY = dragStart.lastDy || (dragStart.lastDy = 0);

                // Whether to fire the click event ot not
                ele.data('fire_click_event', 1);
                ele.data('mousedown', 1);
                clearTimeout(ele._longpressactive);
                // DragNode mouse progress cursor added.
                ele.data('move', true);
                // If view mode is enabled, don't open the node edit UI.
                if (!viewMode) {
                    waitElement || (waitElement = graphics.waitElement = paper
                        .ringpath(config._xPos, config._yPos, 8, 11, 0, 0, trackerGroup)
                        .attr({
                            fill: toRaphaelColor({
                                alpha: '100,100',
                                angle: 120,
                                color: 'CCCCCC,FFFFFF',
                                ratio: '30,50'
                            }),
                            'stroke-width': 0
                        }));
                    layerX += 11;
                    layerY -= 21;
                    waitElement.attr({
                        ringpath: [config._xPos, config._yPos, 8, 11, 0, 0]
                    })
                    .show()
                    .animate({
                        ringpath: [config._xPos, config._yPos, 8, 11, 0, 6.28]
                    }, CLEAR_TIME_1000);

                    ele._longpressactive = setTimeout(function() {
                        var seriesName = (conf.name !== BLANK &&
                                conf.name !== UNDEFINED) ?
                                conf.name + COMMASTRING +
                                BLANKSPACE : BLANK,
                            seriesId = conf.id;
                        graphics.waitElement && graphics.waitElement.hide();
                        // Whether to fire the click event ot not
                        ele.data('fire_click_event', 0);
                        groupManager.showNodeUpdateUI(chart, {
                            x: {
                                value: config.x
                            },
                            y: {
                                value: config.y
                            },
                            draggable: {
                                value: getFirstValue(config.allowdrag, 1)
                            },
                            color: {
                                value: config.color
                            },
                            alpha: {
                                value: config.alpha
                            },
                            label: {
                                value: getFirstValue(config.label,
                                    config.name)
                            },
                            tooltip: {
                                value: config.toolText
                            },
                            shape: {
                                value: shapesInfo[config.shape]
                            },
                            rectWidth: {
                                value: config.width
                            },
                            rectHeight: {
                                value: config.height
                            },
                            circPolyRadius: {
                                value: config.radius
                            },
                            polySides: {
                                value: config.numsides
                            },
                            image: {
                                value: config.imageNode
                            },
                            imgWidth: {
                                value: config.imageWidth
                            },
                            imgHeight: {
                                value: config.imageHeight
                            },
                            imgAlign: {
                                value: config.imageAlign
                            },
                            imgUrl: {
                                value: config.imageURL
                            },
                            id: {
                                value: config.id,
                                disabled: true
                            },
                            link: {
                                value: config.link
                            },
                            dataset: {
                                innerHTML: '<option value="' +
                                    seriesId + '">' + seriesName +
                                    seriesId + '</option>',
                                disabled: true
                            },
                            datasetIndex: dataset.index
                        }, true);
                    }, CLEAR_TIME_1000);
                }
                cloneGraphic && cloneGraphic.show();
                cloneText && cloneText.show();
                cloneImage && cloneImage.show();
            },
            _dragMove: function (dx, dy, px, py, chart) {
                var element = this,
                    data = element.data('drag-options'),
                    dataObj = data.dataObj,
                    ele = dataObj.graphics.element,
                    cloneGraphic = dataObj.graphics.cloneGraphic,
                    cloneImage = dataObj.graphics.cloneImage,
                    cloneText = dataObj.graphics.cloneText,
                    config = dataObj.config,
                    dragStart = config.dragStart,
                    startX = dragStart.bBox.x + dx,
                    endX = dragStart.bBox.x2 + dx,
                    startY = dragStart.bBox.y + dy,
                    endY = dragStart.bBox.y2 + dy,
                    graphics = data.dataset.groupManager.graphics,
                    canvasLeft = chart.config.canvasLeft,
                    canvasRight = chart.config.canvasRight,
                    transform,
                    canvasTop = chart.config.canvasTop,
                    canvasBottom = chart.config.canvasBottom;

                // Bound limits
                if (startX < canvasLeft) {
                    dx += (canvasLeft - startX);
                }
                if (endX > canvasRight) {
                    dx -= (endX - canvasRight);
                }
                if (startY < canvasTop) {
                    dy += (canvasTop - startY);
                }
                if (endY > canvasBottom) {
                    dy -= (endY - canvasBottom);
                }
                if (dx || dy) {
                    graphics.waitElement && graphics.waitElement.hide();
                    // Whether to fire the click event or not
                    ele.data('fire_click_event', 0);
                    clearLongPress.call(ele);
                }
                if (config.allowDrag) {
                    dragStart.draged = true;
                    dragStart.lastDx = dx;
                    dragStart.lastDy = dy;

                    transform = data._transformObj = {
                        transform: 't' + (dragStart.origX + dx) + COMMA +
                            (dragStart.origY + dy)
                    };
                    if (cloneGraphic) {
                        cloneGraphic.attr(transform);
                    }
                    if (cloneImage) {
                        cloneImage.attr(transform);
                    }
                    if (cloneText) {
                        cloneText.attr({
                            x: config._xPos + dx,
                            y: config._yPos + dy
                        });

                    }
                }

            },
            removeData: function (index, stretch) {
                var dataSet = this,
                    components = dataSet.components,
                    manager = dataSet.groupManager,
                    dataStore = components.data,
                    removeDataArr = components.removeDataArr || (components.removeDataArr = []);

                stretch = stretch || 1;
                index = index || 0;

                if (index < 0) {
                    index = 0;
                }
                components.removeDataArr = removeDataArr = removeDataArr.concat(dataStore.splice(index, stretch));
                manager._clearConnectors();
            },
            _dragUp: function (event) {
                var element = this,
                    data = element.data('drag-options'),
                    dataset = data.dataset,
                    chart = dataset.chart,
                    dataStore = dataset.components.data,
                    dataObj = data.dataObj,
                    ele = dataObj.graphics.element,
                    groupManager = data.dataset.groupManager,
                    startConnectors,
                    endConnectors,
                    sourceEvent = 'dataplotdragend',
                    fireClick = ele.data('fire_click_event'),
                    config = dataObj.config,
                    canvasTop = chart.config.canvasTop,
                    canvasLeft = chart.config.canvasLeft,
                    dragStart = dataObj.config.dragStart || {},
                    yAxis = dataset.yAxis,
                    i,
                    setObj,
                    len,
                    eventCord,
                    eventArgs,
                    cloneText = dataObj.graphics.cloneText,
                    graphics = dataset.groupManager.graphics,
                    xAxis = chart.components.xAxis[0],
                    updateObj = {},
                    fromObj,
                    toObj,
                    datasetIndex,
                    connectorSet,
                    connector,
                    cloneGraphic = dataObj.graphics.cloneGraphic,
                    cloneImage = dataObj.graphics.cloneImage,
                    drawNodeConnectors = function (connectorsObj) {
                        var i;
                        if (!connectorsObj) {
                            return;
                        }
                        for (i in connectorsObj) {
                            connector = connectorsObj[i];
                            if (connector) {
                                datasetIndex = connector.config.datasetIndex;
                                fromObj = connector.config.fromPointObj;
                                toObj = connector.config.toPointObj;
                                connectorSet = groupManager.connectorSet[datasetIndex];

                                if (connectorSet) {
                                    connectorSet && connectorSet.connectors.drawConnector(connector, fromObj, toObj);
                                }

                            }
                        }
                    };


                graphics.waitElement && graphics.waitElement.hide();
                clearLongPress.call(this);
                ele.data('mousedown', 0);
                fireClick && plotEventHandler.call(ele, chart, event);
                if (dragStart.draged) {
                    dragStart.origX += dragStart.lastDx;
                    dragStart.origY += dragStart.lastDy;
                    dataObj.config._xPos = dragStart.xPos + dragStart.lastDx;
                    dataObj.config._yPos = dragStart.yPos + dragStart.lastDy;
                    updateObj.x = xAxis.getValue(dataObj.config._xPos - canvasLeft);
                    updateObj.y = yAxis.getValue(dataObj.config._yPos - canvasTop);
                    updateObj.update = true;
                    for (i = 0, len = dataStore.length; i < len; i++) {
                        setObj = dataStore[i];
                        if (dataObj.config.id === setObj.config.id) {
                            break;
                        }
                    }

                    dataset.updatePointConfig(updateObj, i);
                    eventArgs = ele.data(EVENTARGS);
                    eventArgs.x = updateObj.x;
                    eventArgs.y = updateObj.y;
                    dataset._drawNode(i);
                    // dataset.drawTracker(i, i + 1);
                    startConnectors = dataObj.config.startConnectors;
                    endConnectors = dataObj.config.endConnectors;
                    drawNodeConnectors(startConnectors);
                    drawNodeConnectors(endConnectors);
                    eventCord = getMouseCoordinate(chart.linkedItems.container, event);
                    eventCord.sourceEvent = sourceEvent;
                    // Fire the ChartUpdated event
                    lib.raiseEvent('chartupdated', extend2(eventCord, eventArgs),
                        chart.chartInstance);

                    // groupManager.draw();
                    dragStart.draged = false;
                }
                cloneText && cloneText.hide();
                cloneGraphic && cloneGraphic.hide();
                cloneImage && cloneImage.hide();
                delete config.dragStart;

            },
            getDataLimits: function () {
                var conf = this.config;
                return {
                    max : conf.yMax,
                    min : conf.yMin,
                    xMax : conf.xMax,
                    xMin : conf.xMin
                };
            }
        }, 'Area']);

    }
]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-connector',
    function () {
        var global = this,
            lib = global.hcLib,

            //strings
            preDefStr = lib.preDefStr,

            configStr = preDefStr.configStr,
            BLANK = lib.BLANKSTRING,
            BLANKSTRING = lib.BLANKSTRING,
            parseTooltext = lib.parseTooltext,
            //add the tools thats are requared
            pluck = lib.pluck,
            getValidValue = lib.getValidValue,
            pluckNumber = lib.pluckNumber,
            // getDefinedColor = lib.getDefinedColor,
            parseUnsafeString = lib.parseUnsafeString,
            getDashStyle = lib.getDashStyle, // returns dashed style of a line series
            toRaphaelColor = lib.toRaphaelColor,
            NONE = 'none',
            // The default value for stroke-dash attribute.
            DASH_DEF = NONE,
            POINTER = 'pointer',
            EVENTARGS = 'eventArgs',
            COMPONENT = 'component',
            DATASET = 'dataset',
            schedular = lib.schedular,
            // CRISP = 'crisp',
            M = 'M',
            L = 'L',
            math = Math,
            mathSin = math.sin,
            mathCos = math.cos,
            mathAbs = math.abs,
            // getColumnColor = lib.graphics.getColumnColor,
            getFirstColor = lib.getFirstColor,
            HUNDREDSTRING = lib.HUNDREDSTRING,
            plotEventHandler = lib.plotEventHandler,

            //add the tools thats are requared
            SHAPE_RECT = lib.SHAPE_RECT,
            OPTIONSTR = '<option>',
            OPTIONCLOSESTR = '</option>',
            CLEAR_TIME_1000 = 1000,
            clearLongPress = function() {
                var ele = this;
                ele.data('move', false);
                clearTimeout(ele._longpressactive);
                delete ele._longpressactive;
            };

        FusionCharts.register(COMPONENT, [DATASET, 'Connector', {
            type: 'connector',
            configure: function () {
                var connectors = this,
                    chartObj = connectors.chart,
                    rawData = chartObj.jsonData,
                    chartAttr = rawData.chart,
                    conf = connectors.config,
                    dataStore = connectors.components.data || (connectors.components.data = []),
                    dataStoreLen,
                    connectorsObj = connectors.JSONData,
                    connectorsArr = connectorsObj.connector,
                    length = connectorsArr && connectorsArr.length,
                    index,
                    seriesConnector,
                    HUNDRED = HUNDREDSTRING,
                    parseUnsafeString = lib.parseUnsafeString;

                conf.connectorsTooltext = getValidValue(parseUnsafeString(pluck(
                        connectorsObj.connectortooltext, chartAttr.connectortooltext)));

                //Extract attributes of this node.
                conf.stdThickness = pluckNumber(connectorsObj.stdthickness, 1);
                conf.conColor = getFirstColor(pluck(connectorsObj.color, 'FF5904'));
                conf.conAlpha = pluck(connectorsObj.alpha, HUNDRED);
                conf.conDashGap = pluckNumber(connectorsObj.dashgap, 5);
                conf.conDashLen = pluckNumber(connectorsObj.dashlen, 5);
                conf.conDashed = Boolean(pluckNumber(connectorsObj.dashed, 0));
                conf.arrowAtStart = Boolean(pluckNumber(connectorsObj.arrowatstart, 1));
                conf.arrowAtEnd = Boolean(pluckNumber(connectorsObj.arrowatend, 1));
                conf.conStrength = pluckNumber(connectorsObj.strength, 1);
                conf.toolTipSepChar = pluck(chartAttr.tooltipsepchar, ' - ');
                seriesConnector = connectors.connector;
                conf.showTooltip = pluckNumber(chartAttr.showtooltip, 1);
                conf.viewMode = pluckNumber(chartAttr.viewmode, 1);

                dataStoreLen = dataStore.length;

                if (dataStoreLen > length) {
                    dataStore.splice(length, dataStoreLen - length);
                }
                conf._refreshData = true;
                for (index = 0; index < length; index += 1) {
                    this._setConfigure(index, connectorsArr[index]);
                }
                conf._refreshData = true;
            },
            _setConfigure: function (index, connectorObj) {
                //connector label.
                var dataset = this,
                    connectorStore = dataset.components.data,
                    connObj = connectorStore[index] || (connectorStore[index] = connectorStore[index] = {}),
                    conf = dataset.config,
                    chartObj = dataset.chart,
                    connectorLabel = parseUnsafeString(pluck(connectorObj.label, connectorObj.name)),
                    setConAlpha  = pluck(connectorObj.alpha, conf.conAlpha),
                    smartLabel = chartObj.linkedItems.smartLabel,
                    tooltipSepChar = conf.toolTipSepChar,
                    defToolTextMacro = '$fromLabel' + tooltipSepChar + '$toLabel',
                    setConColor = {
                        FCcolor: {
                            color: getFirstColor(pluck(connectorObj.color, conf.conColor)),
                            alpha: setConAlpha
                        }
                    },
                    toolText,
                    config,
                    labelTextObj,
                    connectorsTooltext = conf.connectorsTooltext,
                    connectorToolText = getValidValue(parseUnsafeString(pluck(connectorObj.tooltext,
                        connectorsTooltext)));

                smartLabel.useEllipsesOnOverflow(chartObj.config.useEllipsesWhenOverflow);
                labelTextObj = smartLabel.getOriSize(connectorLabel);
                config = connObj.config = connObj.config || (connObj.config = {});
                !connObj.graphics && (connObj.graphics = {});
                //create the tooltext
                if (!conf.showTooltip) {
                    toolText = false;
                } else { //determine the tooltext then
                    toolText = pluck(connectorToolText, connectorLabel ?
                        '$label' : defToolTextMacro);
                }
                config = connObj.config = {
                    _options: connectorObj,
                    id: pluck(connectorObj.id, index).toString(),
                    from: pluck(connectorObj.from, BLANK),
                    to: pluck(connectorObj.to, BLANK),
                    label: connectorLabel,
                    toolText: toolText,
                    customToolText: connectorToolText,
                    color: setConColor,
                    index: index,
                    dashStyle: Boolean(pluckNumber(connectorObj.dashed, conf.conDashed)) ?
                        getDashStyle(pluckNumber(connectorObj.dashlen, conf.conDashLen),
                            pluckNumber(connectorObj.dashgap, conf.conDashGap), conf.stdThickness) : DASH_DEF,
                    dashed: connectorObj.dashed,
                    dashlen: connectorObj.dashlen,
                    dashgap: connectorObj.dashgap,
                    arrowAtStart: Boolean(pluckNumber(connectorObj.arrowatstart, conf.arrowAtStart)),
                    arrowAtEnd: Boolean(pluckNumber(connectorObj.arrowatend, conf.arrowAtEnd)),
                    conStrength: pluckNumber(connectorObj.strength, conf.conStrength),
                    link: connectorObj.link,
                    stdThickness: conf.stdThickness,
                    labelWidth: labelTextObj.widht,
                    labelHeight: labelTextObj.height
                };
                config.datasetIndex = dataset.index;
                config.add = connectorObj.add;
                config.update = connectorObj.update;
                if (conf._refreshData) {
                    delete connObj.removed;
                }
            },
            init: function (jsonData) {
                var dataSet = this,
                    chart = dataSet.chart;
                dataSet.yAxis = chart.components.yAxis[0];
                dataSet.components = {

                };

                dataSet.graphics = {

                };

                dataSet.JSONData = jsonData;
                dataSet.configure();
            },
            draw: function () {
                var connectors = this,
                    chart = connectors.chart,
                    manager = connectors.groupManager,
                    conf = connectors.config,
                    chartObj = connectors.chart,
                    chartComp = chartObj.components,
                    chartGraphics = chart.graphics,
                    nodes = manager.nodes,
                    connectorStore = connectors.components.data,
                    connector,
                    fromId,
                    toId,
                    paper = chartComp.paper,
                    jobList = chart.getJobList(),
                    datasetGroup = chartGraphics.datasetGroup,
                    fromPointObj,
                    toPointObj,
                    style = chart.config.dataLabelStyle,
                    graphics,
                    i,
                    length = connectorStore.length,
                    removeDataArr = connectors.components.removeDataArr || [],
                    removeDataArrLen = removeDataArr.length,
                    connectorsGroup,
                    config;

                if (!connectorsGroup) {
                    connectorsGroup = connectors.graphics.connectorGroup =
                        connectors.graphics.connectorGroup || paper.group('connectorGroup').insertBefore(datasetGroup);
                }

                if (conf.showTooltip) {
                    connectorsGroup.trackTooltip(true);
                }
                conf.cleared = false;
                connectorsGroup.css(style);
                for (i = 0; i < length; i++) {
                    connector = connectorStore[i];
                    config = connector.config;
                    graphics = connector.graphics || (connector.graphics = {});
                    fromId = config.from;
                    toId = config.to;
                    fromPointObj = nodes[fromId];
                    toPointObj = nodes[toId];
                    if (fromPointObj && toPointObj && config.deleted !== true) {
                        connectors.drawConnector(connector, fromPointObj, toPointObj, i);
                    }
                }
                // For first time render label is drawn in a separate thread
                connectors.drawn !== true && jobList.labelDrawID.push(schedular.addJob(connectors.drawLabel, connectors,
                    [], lib.priorityList.label));
                connectors.drawn = true;

                for (i = 0; i < removeDataArrLen; i++) {
                    connectors._removeDataVisuals(removeDataArr.shift());
                }
            },
            mouseDown: function () {
                var ele = this,
                    config = ele.data(configStr),
                    dataset = ele.data('dataset'),
                    manager = dataset.groupManager,
                    chart = dataset.chart,
                    conf = dataset.config,
                    options = config || {};

                ele._longpressactive = clearTimeout(ele._longpressactive);

                // Whether to fire the click event ot not
                ele.data('fire_click_event', 1);

                ele._longpressactive = setTimeout(function() {

                    // Whether to fire the click event ot not
                    ele.data('fire_click_event', 0);

                    if (!ele.data('viewMode')) {
                        //add a selection method for start and end
                        manager.showConnectorUpdateUI(chart, {
                            fromid: {
                                val: options.from,
                                innerHTML: OPTIONSTR + options.from + OPTIONCLOSESTR,
                                disabled: true
                            },
                            toid: {
                                val: options.to,
                                innerHTML: OPTIONSTR + options.to + OPTIONCLOSESTR,
                                disabled: true
                            },
                            datasetIndex: dataset.index,
                            index: config.index,
                            arratstart: {
                                val: Boolean(pluckNumber(options.arrowatstart, 1))
                            },
                            arratend: {
                                val: Boolean(pluckNumber(options.arrowatend, 1))
                            },
                            dashed: {
                                val: pluckNumber(options.dashed)
                            },
                            dashgap: {
                                val: options.dashgap
                            },
                            dashlen: {
                                val: options.dashlen
                            },
                            label: {
                                val: options.label
                            },
                            tooltext: {
                                val: options.tooltext
                            },
                            id: {
                                val: conf.id,
                                disabled: true
                            },
                            strength: {
                                val: options.conStrength
                            },
                            alpha: {
                                val: options.alpha
                            },
                            color: {
                                val: options.color.FCcolor.color
                            }
                        }, true);
                    }
                }, CLEAR_TIME_1000);
            },
            mousemove: function() {
                // Whether to fire the click event ot not
                this.data('fire_click_event', 0);
                clearLongPress.call(this);
            },
            mouseup: function(data) {
                var ele = this,
                dataset = ele.data('dataset'),
                chart = dataset.chart;

                clearLongPress.call(ele);
                plotEventHandler.call(ele, chart, data, 'ConnectorClick');
            },
            hoverIn: function(data) {
                var ele = this,
                dataset = ele.data('dataset'),
                chart = dataset.chart;
                plotEventHandler.call(ele, chart, data, 'ConnectorRollover');
            },
            hoverOut: function(data) {
                var ele = this,
                dataset = ele.data('dataset'),
                chart = dataset.chart;
                plotEventHandler.call(ele, chart, data, 'ConnectorRollout');
            },
            drawConnector: function (connector, fromPointObj, toPointObj) {
                if (connector.removed) {
                    return;
                }
                var dataset = this,
                    chart = dataset.chart,
                    fromX,
                    toX,
                    fromY,
                    toY,
                    strokeWidth,
                    textBgColor,
                    paper = chart.components.paper,
                    NumberFormatter = chart.components.numberFormatter,
                    pathArr,
                    graphics = connector.graphics,
                    startConnectors,
                    endConnectors,
                    element,
                    animationObj = chart.get('config', 'animationObj'),
                    connectorsGroup = dataset.graphics.connectorGroup,
                    dummyAnimObj = animationObj.animObj,
                    dummyAnimElem = animationObj.dummyObj,
                    animType = animationObj.animType,
                    animationDuration = animationObj.duration,
                    config = connector.config,
                    label,
                    tooltext = config.toolText,
                    fromConf,
                    toConf,
                    eventArgs = config.eventArgs || (config.eventArgs = {}),
                    color,
                    conf = dataset.config,
                    pool = dataset.components.pool || {},
                    id;

                config.fromPointObj = fromPointObj;
                config.toPointObj = toPointObj;
                fromConf = fromPointObj.config;
                toConf = toPointObj.config;
                config.fromX = fromX = fromConf._xPos;
                config.fromY = fromY = fromConf._yPos;
                config.toX = toX = toConf._xPos;
                config.toY = toY = toConf._yPos;
                config._labelX = (fromX + toX) / 2;
                config._labelY = (fromY + toY) / 2;
                config.strokeWidth = strokeWidth = (config.conStrength * config.stdThickness);
                color = config.color;
                config.textBgColor = textBgColor = color && color.FCcolor &&
                    color.FCcolor.color;
                label = eventArgs.label = config.label;
                eventArgs.arrowAtStart = config.arrowAtStart;
                eventArgs.arrowAtEnd = config.arrowAtEnd;
                eventArgs.link = config.link;
                eventArgs.id = config.id;
                eventArgs.fromNodeId = fromConf.id;
                eventArgs.toNodeId = toConf.id;
                tooltext = config.toolText = parseTooltext(config.toolText, [3, 83,
                    84, 85, 86, 87, 88, 89, 90, 91, 92
                ], {
                    label: config.label,
                    fromXValue: NumberFormatter.dataLabels(fromPointObj.config.x),
                    fromYValue: NumberFormatter.dataLabels(fromPointObj.config.y),
                    fromXDataValue: fromPointObj.config.x,
                    fromYDataValue: fromPointObj.config.y,
                    fromLabel: pluck(fromPointObj.config.displayValue, fromPointObj.config.id),
                    toXValue: NumberFormatter.dataLabels(toPointObj.config.x),
                    toYValue: NumberFormatter.dataLabels(toPointObj.config.y),
                    toXDataValue: toPointObj.config.x,
                    toYDataValue: toPointObj.config.y,
                    toLabel: pluck(toPointObj.config.displayValue, toPointObj.config.id)
                });


                fromConf = fromPointObj.config;
                toConf = toPointObj.config;

                startConnectors = fromConf.startConnectors;
                endConnectors = toConf.endConnectors;

                id = connector.config.id + '-' + fromConf.id + '-' + toConf.id;

                startConnectors[id] = connector;
                endConnectors[id] = connector;

                pathArr = this._getlinePath(connector);
                element = graphics.graphic;
                //draw the line
                if (!graphics.graphic) {
                    if (pool.graphic && pool.graphic.path && pool.graphic.path.length) {
                        element = graphics.graphic = pool.graphic.path.shift();
                    }
                    else {
                        element = graphics.graphic = paper.path(connectorsGroup)
                            .mousedown(dataset.mouseDown)
                            .mousemove(dataset.mousemove)
                            .mouseup(dataset.mouseup)
                            .hover(dataset.hoverIn, dataset.hoverOut);
                        element.attr({
                            path: pathArr
                        });
                    }
                }

                element.show().animateWith(dummyAnimElem, dummyAnimObj, {
                    path: pathArr
                }, animationDuration, animType);
                element.attr({
                    'stroke-width': strokeWidth,
                    ishot: true,
                    'stroke-dasharray': config.dashStyle,
                    cursor: config.link ? POINTER : BLANKSTRING,
                    stroke: toRaphaelColor(color)
                })
                .data(EVENTARGS, eventArgs)
                .data('viewMode', conf.viewMode)
                .data(configStr, config)
                .data('dataset', dataset)
                .tooltip(tooltext);
                // If this is not the first render then label is drawn instantly otherwise it is drawn in
                // another thread for performance optimization
                dataset.drawn && dataset.drawLabel(connector);
            },
            drawLabel: function (connector) {
                var dataset = this,
                    groupManager = dataset.groupManager,
                    nodes = groupManager.nodes,
                    conf = dataset.config,
                    chart = dataset.chart,
                    paper = chart.components.paper,
                    animationObj = chart.get('config', 'animationObj'),
                    connectorsGroup = dataset.graphics.connectorGroup,
                    dummyAnimObj = animationObj.animObj,
                    dummyAnimElem = animationObj.dummyObj,
                    animType = animationObj.animType,
                    animationDuration = animationObj.duration,
                    config,
                    label,
                    tooltext,
                    labelAttrs,
                    style = chart.config.dataLabelStyle,
                    labelElement,
                    graphics,
                    connectorObj,
                    i,
                    labelX,
                    labelY,
                    textBgColor,
                    dataStore = dataset.components.data,
                    pool = dataset.components.pool || {},
                    len = dataStore.length,
                    fromPointObj,
                    toPointObj,
                    fromId,
                    toId,
                    drawIndividualLabel = function (connector) {
                        config = connector.config;
                        tooltext = config.toolText;
                        graphics = connector.graphics;
                        label = config.label;
                        labelX = config._labelX;
                        labelY = config._labelY;
                        fromId = config.from;
                        toId = config.to;
                        fromPointObj = nodes[fromId];
                        toPointObj = nodes[toId];
                        textBgColor = config.textBgColor;
//                         if (label && fromPointObj && toPointObj) {
//                             labelElement = graphics.text = graphics.text || (pool.text && pool.text.shift());
// =======
//                         textBgColor = config.textBgColor;
                        if (label) {
                            labelElement = graphics.text = graphics.text || (pool.element && pool.element.text &&
                                pool.element.text.shift());
                            labelAttrs = {
                                text: label,
                                fill: style.color,
                                ishot: true,
                                direction: BLANKSTRING,
                                cursor: config.link ? POINTER : BLANKSTRING,
                                'text-bound': [pluck(style.backgroundColor, textBgColor),
                                    pluck(style.borderColor, textBgColor), 1, '2'
                                ]
                            };

                            // Drawing the connector Label
                            if (!graphics.text) {
                                labelAttrs.x = labelX;
                                labelAttrs.y = labelY;
                                graphics.text = labelElement = paper.text(labelAttrs, connectorsGroup)
                                    .mousedown(dataset.mouseDown)
                                    .mousemove(dataset.mousemove)
                                    .mouseup(dataset.mouseup)
                                    .hover(dataset.hoverIn, dataset.hoverOut);
                            }
                            else {
                                labelElement.show().animateWith(dummyAnimElem, dummyAnimObj, {
                                    x: labelX,
                                    y: labelY
                                }, animationDuration, animType);
                                labelElement.attr(labelAttrs);
                            }
                            labelElement.data(EVENTARGS, config.eventArgs)
                                .data('viewMode', conf.viewMode)
                                .data(configStr, config)
                                .data('dataset', dataset)
                                .tooltip(tooltext);
                        }
                        else {
                            graphics.text && graphics.text.hide();
                        }
                    };

                if (connector) {
                    drawIndividualLabel(connector);
                }
                else {
                    for (i = 0; i < len; i++) {
                        connectorObj = dataStore[i];
                        drawIndividualLabel(connectorObj);
                    }
                }
            },
            // Get jsondata of connector dataset
            getJSONData: function () {
                var dataset = this,
                    dataStore = dataset.components.data,
                    len = dataStore.length,
                    jsonData = [],
                    dataObj,
                    i;
                for (i = 0; i < len; i++) {
                    dataObj = dataStore[i];
                    if (!dataObj.removed) {
                        if (dataObj.config._options) {
                            delete dataObj.config._options.update;
                            delete dataObj.config._options.add;
                        }
                        jsonData.push(dataObj.config._options);
                    }
                }
                return jsonData;
            },

            _updateFromPos: function (x, y) {
                var connector = this;
                connector.fromX = x;
                connector.fromY = y;
                connector.graphic && connector.graphic.animate({
                    path: connector.getlinePath()
                });

                connector.text && connector.text.animate({
                    x: (connector.fromX + connector.toX) / 2,
                    y: (connector.fromY + connector.toY) / 2
                });
            },

            _updateToPos: function (x, y) {
                var connector = this;
                connector.toX = x;
                connector.toY = y;
                connector.graphic && connector.graphic.animate({
                    path: connector.getlinePath()
                });

                connector.text && connector.text.animate({
                    x: (connector.fromX + connector.toX) / 2,
                    y: (connector.fromY + connector.toY) / 2
                });
            },

            _getlinePath: function (connector) {
                var config = connector.config,
                    fromPointObj = config.fromPointObj,
                    toPointObj = config.toPointObj,
                    fromX = config.fromX,
                    fromY = config.fromY,
                    toX = config.toX,
                    toY = config.toY,
                    path = [M, fromX, fromY],
                    pointConfig;

                if (config.arrowAtStart) {
                    pointConfig = fromPointObj.config;
                    if (pointConfig.shapeType === SHAPE_RECT) {
                        path = path.concat(this._drawArrow(fromX, fromY, toX, toY,
                            pointConfig.shapeArg.width, pointConfig.shapeArg.height));
                    } else {
                        path = path.concat(this._drawArrow(fromX, fromY, toX, toY,
                            pointConfig.shapeArg.radius));
                    }
                }

                // Calculating path for connector Arrow
                if (config.arrowAtEnd) {
                    pointConfig = toPointObj.config;
                    if (pointConfig.shapeType === SHAPE_RECT) {
                        path = path.concat(this._drawArrow(toX, toY, fromX, fromY,
                            pointConfig.shapeArg.width, pointConfig.shapeArg.height));
                    } else {
                        path = path.concat(this._drawArrow(toX, toY, fromX, fromY,
                            pointConfig.shapeArg.radius));
                    }
                }
                path.push(L, toX, toY);
                return path;
            },

            _drawArrow: function (X1, Y1, X2, Y2, R, H) {
                var tanganent = (Y1 - Y2) / (X1 - X2),
                    angle = math.atan(tanganent),
                    PX, PY, RHlf, HHlf,
                    arr = [];


                //make all angle as positive
                if (angle < 0) {
                    angle = (2 * math.PI) + angle;
                }
                if (Y2 > Y1) { ///PI >angle > 0
                    if ((X2 >= X1 && angle > math.PI) || (X2 < X1 && angle > math.PI)) {
                        angle = angle - math.PI;
                    }
                } else { /// PI <= angle < 360 || angle == 0
                    //angle may not be 360 in that case it will be 0 as atan work
                    if ((X2 >= X1 && angle < math.PI && angle !== 0) || (X2 < X1 && angle < math.PI)) {
                        angle = angle + math.PI;
                    }
                }

                if (typeof H == 'undefined') {
                    ///arrow start point
                    PX = X1 + (R * mathCos(angle));
                    PY = Y1 + (R * mathSin(angle));
                } else { ///rectangle
                    RHlf = mathAbs(R) / 2;
                    HHlf = mathAbs(H) / 2;

                    //asume it will intersect a vertical side
                    PX = X1 + (RHlf = X1 < X2 ? RHlf : -RHlf);
                    PY = Y1 + (RHlf * math.tan(angle));
                    //validate PY
                    //if not validate then it will cross the horizontal axis
                    if (mathAbs(Y1 - PY) > mathAbs(HHlf)) {
                        PY = Y1 + (HHlf = Y1 < Y2 ? HHlf : -HHlf);
                        PX = X1 + (HHlf / math.tan(angle));
                    }
                }

                arr.push(L, PX, PY,
                    ///arrowone half
                    PX + (10 * mathCos(angle + 0.79)),
                    PY + (10 * mathSin(angle + 0.79)),
                    ///arrowone half
                    M, PX + (10 * mathCos(angle - 0.79)),
                    PY + (10 * mathSin(angle - 0.79)),
                    //return to th eedege
                    L, PX, PY);

                return arr;
            },

            removeData: function (index, stretch) {
                var dataset = this,
                    components = dataset.components,
                    dataStore = components.data,
                    removeDataArr;

                if (index < 0) {
                    index = 0;
                }
                components.removeDataArr = removeDataArr = dataStore.splice(index, stretch);

            }
        },'Dragnode']);

    }
]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-dragablelabels',
    function () {
        var global = this,
            lib = global.hcLib,

            //strings
            preDefStr = lib.preDefStr,

            configStr = preDefStr.configStr,
            animationObjStr = preDefStr.animationObjStr,
            visibleStr = preDefStr.visibleStr,
            BLANKSTRING = lib.BLANKSTRING,
            //add the tools thats are requared
            pluck = lib.pluck,
            pluckNumber = lib.pluckNumber,
            // getDefinedColor = lib.getDefinedColor,
            parseUnsafeString = lib.parseUnsafeString,
            extend2 = lib.extend2, //old: jarendererExtend / margecolone
            getDashStyle = lib.getDashStyle, // returns dashed style of a line series
            isIE = lib.isIE,
            dropHash = lib.regex.dropHash,
            HASHSTRING = lib.HASHSTRING,
            UNDEFINED,
            NONE = 'none',
            // The default value for stroke-dash attribute.
            DASH_DEF = NONE,
            // getLinkAction = lib.getLinkAction,
            POSITION_CENTER = 'center',
            // NumberFormatter = lib.NumberFormatter,
            hashify = lib.hashify,
            PXSTRING = 'px',
            EVENTARGS = 'eventArgs',
            COMPONENT = 'component',
            DATASET = 'dataset',
            schedular = lib.schedular,
            TRACKER_FILL = 'rgba(192,192,192,' + (isIE ? 0.002 : 0.000001) + ')', // invisible but clickable
            PX = PXSTRING,
            setLineHeight = lib.setLineHeight,
            // renderer = chartAPI,
            // COMMASPACE = lib.COMMASPACE,
            getMouseCoordinate = lib.getMouseCoordinate,
            plotEventHandler = lib.plotEventHandler,
            CLEAR_TIME_1000 = 1000;

        FusionCharts.register(COMPONENT, [DATASET, 'DragableLabels', {
            configure: function () {
                var dataset = this,
                    chart = dataset.chart,
                    jsonData = chart.jsonData,
                    chartAttr = jsonData.chart,
                    conf = dataset.config,
                    setDataArr = dataset.JSONData || [],
                    len = setDataArr.length,
                    dataStoreLen,
                    dataStore = dataset.components.data,
                    i;
                conf.viewMode = pluckNumber(chartAttr.viewmode, 0);
                if (!dataStore) {
                    dataStore = dataset.components.data = [];
                }
                dataStoreLen = dataStore.length;

                if (dataStoreLen > len) {
                    dataStore.splice(len, dataStoreLen - len);
                }

                for (i = 0; i < len; i++) {
                    dataset._setConfigure(i);
                }

            },
            _setConfigure: function (index, updateObj) {
                var dataset = this,
                    setDataArr = dataset.JSONData,
                    chart = dataset.chart,
                    setData = updateObj ? updateObj : setDataArr[index],
                    dataStore = dataset.components.data,
                    dataObj,
                    text,
                    style = chart.config.style,
                    inCanvasStyle = style.inCanvasStyle,
                    inCanFontSize = inCanvasStyle.fontSize,
                    labelColor,
                    labelBGColor,
                    config,
                    labelBDColor,
                    alpha,
                    labelFontSize;
                dataObj = dataStore[index];
                !dataObj && (dataObj = dataStore[index] = {});
                !dataObj.graphics && (dataObj.graphics = {});

                config = dataObj.config = dataObj.config || (dataObj.config = {});
                text = parseUnsafeString(pluck(setData.text, setData.label));
                config._options = setData;
                config.add = setData.add;
                if (text) {
                    config.text = text;
                    config.x = setData.x || 0;
                    config.y = setData.y || 0;
                    config.labelFontSize = labelFontSize = pluckNumber(setData.fontsize, inCanFontSize);

                    config.labelColor = labelColor = hashify(pluck(setData.color,
                        inCanvasStyle.color));
                    config.alpha = alpha = (pluckNumber(setData.alpha, 100)) / 100;
                    config.allowdrag = pluckNumber(setData.allowdrag, 1);
                    config.padding = pluckNumber(setData.padding, 5);

                    // config.labelColor = labelColor = convertColor(pluck(setData.color, inCanvasStyle.color),
                    //     pluckNumber(setData.alpha, 100));

                    if (setData.fontsize) {
                        config.labelCSS = {
                            fontSize: labelFontSize + PX
                        };
                    }
                    else {
                        config.labelCSS = UNDEFINED;
                    }

                    config.labelBGColor = labelBGColor = pluck(setData.bgcolor &&
                        setData.bgcolor.replace(dropHash, HASHSTRING));
                    config.labelBDColor = labelBDColor = pluck(setData.bordercolor &&
                        setData.bordercolor.replace(dropHash, HASHSTRING));
                    config.link = setData.link;
                    config.allowDrag = pluckNumber(setData.allowdrag, 1);
                    config.borderThickness = setData.borderthickness;
                    config.dashLen = setData.dashlen;
                    config.dashGap = setData.dashgap;
                    config.dashed = setData.dashed;
                    config.radius = setData.radius;
                }
            },
            init: function (jsonData) {
                var dataSet = this,
                    chart = dataSet.chart;
                dataSet.yAxis = chart.components.yAxis[0];
                dataSet.components = {

                };

                dataSet.graphics = {

                };

                dataSet.JSONData = jsonData;
                dataSet.configure();
            },
            // Get jsondata of dragable label dataset
            getJSONData: function () {
                var dataset = this,
                    dataStore = dataset.components.data,
                    len = dataStore.length,
                    jsonData = [],
                    dataObj,
                    i;
                for (i = 0; i < len; i++) {
                    dataObj = dataStore[i];
                    if (!dataObj.removed) {
                        if (dataObj.config._options) {
                            jsonData.push(dataObj.config._options);
                        }
                    }
                }
                return jsonData;
            },
            draw: function () {
                var dataset = this,
                    dataStore = dataset.components.data,
                    chart = dataset.chart,
                    jobList = chart.getJobList(),
                    animationObj = chart.get(configStr, animationObjStr),
                    animationDuration = animationObj.duration,
                    animType = animationObj.animType,
                    dummyAnimElem = animationObj.dummyObj,
                    dummyAnimObj = animationObj.animObj,
                    paper = chart.components.paper,
                    yAxis = chart.components.yAxis[0],
                    xAxis = chart.components.xAxis[0],
                    SmartLabel = chart.linkedItems.smartLabel,
                    dataLabelsLayer = chart.graphics.datalabelsGroup,
                    trackerGroup = chart.graphics.trackerGroup,
                    style = chart.config.dataLabelStyle,
                    dashLen,
                    dashGap,
                    dashed,
                    x,
                    y,
                    color,
                    text,
                    bgColor,
                    borderColor,
                    padding,
                    config,
                    attr,
                    alpha,
                    dataObj,
                    allowDrag,
                    fontSize,
                    eventArgs,
                    radius,
                    element,
                    dim,
                    borderThickness,
                    len = dataStore.length,
                    lStyle,
                    removeDataArr = dataset.components.removeDataArr || [],
                    removeDataArrLen =  removeDataArr.length,
                    pool = dataset.components.pool || {},
                    i,
                    trackerContainer,
                    dataLabelContainer,
                    labelCSS;

                dataLabelContainer = dataset.graphics.dataLabelContainer = dataset.graphics.dataLabelContainer ||
                    paper.group('datalabels', dataLabelsLayer);
                trackerContainer = dataset.graphics.trackerContainer = dataset.graphics.trackerContainer ||
                    paper.group('tracker', trackerGroup);

                dataLabelContainer.css({
                    'font-weight': style.fontWeight,
                    'font-style': style.fontStyle,
                    'font-size': style.fontSize,
                    'font-family': style.fontFamily
                });

                for (i = 0; i < len; i++) {
                    dataObj =  dataStore[i];
                    if (dataObj.removed) {
                        continue;
                    }
                    config = dataObj.config;
                    !dataObj.graphics && (dataObj.graphics = {});
                    config.index = i;
                    x = xAxis.getPixel(config.x);
                    y = yAxis.getPixel(config.y);
                    text = config.text;
                    bgColor = config.labelBGColor;
                    borderColor = config.labelBDColor;
                    padding = config.padding;
                    allowDrag = config.allowDrag;
                    fontSize = config.labelFontSize;
                    color = config.labelColor;
                    alpha = config.alpha;
                    radius = config.radius;
                    dashed = config.dashed;
                    borderThickness = config.borderThickness;
                    dashLen = config.dashLen;
                    dashGap = config.dashGap;
                    borderThickness = config.borderThickness;
                    labelCSS = config.labelCSS;

                    attr = {
                        x: x,
                        y: y,
                        text: text,
                        align: POSITION_CENTER,
                        fill: color,
                        'text-bound': [(bgColor || BLANKSTRING), (borderColor || BLANKSTRING),
                            pluckNumber(borderThickness, 1),
                            padding,
                            pluckNumber(radius, 0),
                            pluckNumber(dashed, 0) ?
                            getDashStyle(pluckNumber(dashLen, 5),
                                pluckNumber(dashGap, 4),
                                pluckNumber(borderThickness, 1)) :
                            DASH_DEF
                        ],
                        visibility: visibleStr
                    };

                    lStyle =  {
                        backgroundColor: bgColor,
                        borderColor: borderColor,
                        borderPadding: padding,
                        fontSize: fontSize + PXSTRING,
                        fontStyle: style.fontStyle,
                        fontWeight: style.fontWeight,
                        borderRadius: 0,
                        borderDash: DASH_DEF,
                        fontFamily: style.fontFamily
                    };
                    setLineHeight(lStyle);
                    SmartLabel.useEllipsesOnOverflow(chart.config.useEllipsesWhenOverflow);
                    SmartLabel.setStyle(lStyle);
                    eventArgs = {
                        link: config.link,
                        text: text,
                        x: x,
                        y: y,
                        allowdrag: allowDrag,
                        sourceType: 'labelnode'
                    };

                    element = dataObj.graphics.element = dataObj.graphics.element ||
                        (pool.element && pool.element.text && pool.element.text.shift());

                    if (!element) {
                        element = dataObj.graphics.element = paper.text(attr, labelCSS, dataLabelContainer);
                    }
                    else {
                        // If label css was applied on this element and now label css is not given then remove css
                        if (config.labelCSSApplied && !labelCSS) {
                            element.removeCSS();
                        }

                        element.show()
                        .animateWith(dummyAnimElem, dummyAnimObj, attr, animationDuration, animType)
                        .css(labelCSS);
                    }

                    config.labelCSSApplied = labelCSS;

                    element.data('eventArgs', eventArgs);
                    dim = SmartLabel.getOriSize(text);
                    config.width = dim.width;
                    config.height = dim.height;
                    config.xPos = x;
                    config.yPos = y;
                }
                jobList.trackerDrawID.push(schedular.addJob(dataset.drawTracker, dataset, [],
                    lib.priorityList.tracker));
                for (i = 0; i < removeDataArrLen; i++) {
                    dataset._removeDataVisuals(removeDataArr.shift());
                }

            },
            removeData: function (index, stretch) {
                var dataset = this,
                    components = dataset.components,
                    dataStore = components.data;
                components.removeDataArr = dataStore.splice(index, stretch);
            },
            drawTracker: function () {
                var dataset = this,
                    dataStore = dataset.components.data,
                    chart = dataset.chart,
                    paper = chart.components.paper,
                    manager = dataset.groupManager,
                    conf = dataset.config,
                    trackerGroup = dataset.graphics.trackerContainer,
                    len = dataStore.length,
                    dataObj,
                    config,
                    padding,
                    elemMouseDownFN = function(labelObj) { // Long press eve
                        var ele = this;
                        ele.data('fire_click_event', 1);
                        clearTimeout(ele._longpressactive);
                        ele._longpressactive = setTimeout(function() {
                            ele.data('fire_click_event', 0);
                            if (!ele.data('viewMode')) {
                                manager.showLabelDeleteUI(labelObj);
                            }
                        }, CLEAR_TIME_1000);
                    },
                    elemMouseMoveFN = function() {
                        // Whether to fire the click event ot not
                        var ele = this;
                        if (ele.data('fire_click_event')) {
                            ele.data('fire_click_event', 0);
                            manager.clearLongPress.call(this);
                        }
                    },
                    elemMouseUPFN = function(data) {
                        var ele = this,
                            fireClick = ele.data('fire_click_event');
                        manager.clearLongPress.call(ele);
                        if (fireClick) {
                            /**
                             *
                             * > Applicable to `dragnode` chart only.
                             *
                             * @event FusionCharts#labelClick
                             * @group chart-powercharts:dragnode
                             *
                             * @param {number} chartX - x-coordinate of the pointer relative to the chart.
                             * @param {number} chartY - y-coordinate of the pointer relative to the chart.
                             * @param {number} pageX - x-coordinate of the pointer relative to the page.
                             * @param {number} pageY - y-coordinate of the pointer relative to the page.
                             *
                             * @param {number} x - The x-value of the label node scaled as per the axis of the chart.
                             * @param {number} y - The y-value of the label node scaled as per the axis of the chart.
                             *
                             * @param {string} text - The text value of the label.
                             */
                            plotEventHandler.call(ele, chart, data, 'LabelClick');
                        }
                    },
                    elemHoverFN = function(data) {
                        var ele = this;
                        /**
                         *
                         * > Applicable to `dragnode` chart only.
                         *
                         * @event FusionCharts#labelRollOver
                         * @group chart-powercharts:dragnode
                         *
                         * @param {number} chartX - x-coordinate of the pointer relative to the chart.
                         * @param {number} chartY - y-coordinate of the pointer relative to the chart.
                         * @param {number} pageX - x-coordinate of the pointer relative to the page.
                         * @param {number} pageY - y-coordinate of the pointer relative to the page.
                         *
                         * @param {number} x - The x-value of the label node scaled as per the axis of the chart.
                         * @param {number} y - The y-value of the label node scaled as per the axis of the chart.
                         *
                         * @param {string} text - The text value of the label.
                         */
                        plotEventHandler.call(ele, chart, data, 'LabelRollover');
                    },
                    elemOutFN = function(data) {
                        var ele = this;
                        /**
                         *
                         * > Applicable to `dragnode` chart only.
                         *
                         * @event FusionCharts#labelRollOut
                         * @group chart-powercharts:dragnode
                         *
                         * @param {number} chartX - x-coordinate of the pointer relative to the chart.
                         * @param {number} chartY - y-coordinate of the pointer relative to the chart.
                         * @param {number} pageX - x-coordinate of the pointer relative to the page.
                         * @param {number} pageY - y-coordinate of the pointer relative to the page.
                         *
                         * @param {number} x - The x-value of the label node scaled as per the axis of the chart.
                         * @param {number} y - The y-value of the label node scaled as per the axis of the chart.
                         *
                         * @param {string} text - The text value of the label.
                         */
                        plotEventHandler.call(ele, chart, data, 'LabelRollout');
                    },
                    eventArgs,
                    attr,
                    allowDrag,
                    text,
                    trackerElement,
                    x,
                    y,
                    width,
                    height,
                    dragMove = function(dx, dy, px, py, event) {
                        var ele = this;
                        dataset._labelDragMove.call(ele, dx, dy, px, py, chart, event);
                    },
                    dragStart = function(event) {
                        var ele = this;
                        dataset._labelDragStart.call(ele, event, chart);
                    },
                    dragUp = function(event) {
                        var ele = this;
                        dataset._labelDragUp.call(ele, event);
                    },
                    i;

                for (i = 0; i < len; i++) {
                    dataObj = dataStore[i];
                    if (dataObj.removed) {
                        continue;
                    }
                    config = dataObj.config;
                    padding = config.padding || 0;
                    width = config.width;
                    height = config.height;
                    x = config.xPos - width / 2;
                    y = config.yPos - height / 2;
                    allowDrag = config.allowDrag;
                    text = config.text;
                    trackerElement = dataObj.graphics.trackerElement;
                    attr = {
                        x: x - padding,
                        y: y - padding,
                        width: width + padding * 2,
                        height: height + padding * 2,
                        cursor: config.allowDrag ? 'move' : BLANKSTRING,
                        fill: TRACKER_FILL,
                        stroke: TRACKER_FILL,
                        ishot: true
                    };
                    eventArgs = {
                        link: config.link,
                        text: text,
                        x: x,
                        y: y,
                        allowdrag: allowDrag,
                        sourceType: 'labelnode'
                    };
                    if (!trackerElement) {
                        trackerElement = dataObj.graphics.trackerElement = paper.rect(trackerGroup)
                        .mousedown(elemMouseDownFN)
                        .mousemove(elemMouseMoveFN)
                        .mouseup(elemMouseUPFN)
                        .data('viewMode', conf.viewMode)
                        .data(EVENTARGS, eventArgs)
                        .hover(elemHoverFN, elemOutFN)
                        .drag(dragMove, dragStart, dragUp);
                    }
                    trackerElement.attr(attr);
                    trackerElement.data('drag-options', {
                        index: i,
                        dataset: dataset
                    });
                }
            },
            _labelDragStart: function () {
                var ele = this,
                    bBox = ele.getBBox(),
                    data = ele.data('drag-options'),
                    dataset = data.dataset,
                    manager = dataset.groupManager,
                    index = data.index,
                    labelObj = dataset.components.data[index],
                    labelElement = labelObj.graphics.element,
                    dragStart = labelObj.dragStart = labelObj.dragStart || (labelObj.dragStart = {});
                data.ox = labelElement.attr('x');
                data.oy = labelElement.attr('y');
                data.bBox = bBox;
                dragStart.xPos = labelObj.config.xPos;
                dragStart.yPos = labelObj.config.yPos;
                dragStart.bBox = bBox;
                ele.data('fire_click_event', 1);
                ele.data('fire_dragend', 0);
                clearTimeout(ele._longpressactive);
                ele._longpressactive = setTimeout(function() {
                    ele.data('fire_click_event', 0);
                    if (!ele.data('viewMode')) {
                        manager.showLabelDeleteUI(labelObj);
                    }
                }, CLEAR_TIME_1000);
            },
            _labelDragMove: function (dx, dy, px, py, chart, event) {
                var ele = this,
                    chartConfig = chart.config,
                    canvasLeft = chartConfig.canvasLeft,
                    canvasRight = chartConfig.canvasRight,
                    canvasBottom = chartConfig.canvasBottom,
                    canvasTop = chartConfig.canvasTop,
                    data = ele.data('drag-options'),
                    index = data.index,
                    dataset = data.dataset,
                    manager = dataset.groupManager,
                    labelObj =  dataset.components.data[index],
                    labelElement = labelObj.graphics.element,
                    dragStart = labelObj.dragStart,
                    bBox = dragStart.bBox,
                    startX = dragStart.bBox.x + dx,
                    endX = dragStart.bBox.x2 + dx,
                    startY = dragStart.bBox.y + dy,
                    endY = dragStart.bBox.y2 + dy,
                    yAxis = chart.components.yAxis[0],
                    xAxis = chart.components.xAxis[0],
                    xPos,
                    yPos;
                // Bound limits
                if (startX < canvasLeft) {
                    dx += (canvasLeft - startX);
                }
                if (endX > canvasRight) {
                    dx -= (endX - canvasRight);
                }
                if (startY < canvasTop) {
                    dy += (canvasTop - startY);
                }
                if (endY > canvasBottom) {
                    dy -= (endY - canvasBottom);
                }
                dragStart.draged = true;
                ele.attr({
                    x: bBox.x + dx,
                    y: bBox.y + dy
                });

                xPos = data.ox + dx;
                yPos = data.oy + dy;
                labelElement.attr({
                    x: data.ox + dx,
                    y: data.oy + dy
                });
                labelObj.config.x = xAxis.getValue(xPos - canvasLeft);
                labelObj.config.y = yAxis.getValue(yPos - canvasTop);
                if (!ele.data('fire_dragend')) {
                    /**
                     *
                     * > Applicable to `dragnode` chart only.
                     *
                     * @event FusionCharts#labelDragStart
                     * @group chart-powercharts:dragnode
                     *
                     * @param {number} chartX - x-coordinate of the pointer relative to the chart.
                     * @param {number} chartY - y-coordinate of the pointer relative to the chart.
                     * @param {number} pageX - x-coordinate of the pointer relative to the page.
                     * @param {number} pageY - y-coordinate of the pointer relative to the page.
                     *
                     * @param {number} x - The x-value of the label node scaled as per the axis of the chart.
                     * @param {number} y - The y-value of the label node scaled as per the axis of the chart.
                     *
                     * @param {string} text - The text value of the label.
                     */
                    plotEventHandler.call(ele, chart, event, 'LabelDragStart');
                    ele.data('fire_dragend', 1);
                }
                if (ele.data('fire_click_event')) {
                    ele.data('fire_click_event', 0);
                    manager.clearLongPress.call(ele);
                }
            },
            _labelDragUp: function (event) {
                var ele = this,
                    data = ele.data('drag-options'),
                    index = data.index,
                    dataset = data.dataset,
                    chart = dataset.chart,
                    manager = dataset.groupManager,
                    sourceEvent = 'labeldragend',
                    labelObj =  dataset.components.data[index],
                    dragStart = labelObj.dragStart,
                    eventArgs = ele.data(EVENTARGS),
                    xAxis = chart.components.xAxis[0],
                    yAxis = dataset.yAxis,
                    eventCord;
                eventArgs.x = xAxis.getValue(ele.attr('x')),
                eventArgs.y = yAxis.getValue(ele.attr('y')),

                dragStart.draged = false;
                if (ele.data('fire_dragend')) {
                    eventCord = getMouseCoordinate(chart.linkedItems.container, event);
                    eventCord.sourceEvent = sourceEvent;

                    // Fire the ChartUpdated event
                    lib.raiseEvent('chartupdated',
                        extend2(eventCord, eventArgs),
                        chart.chartInstance);
                    /**
                     *
                     * > Applicable to `dragnode` chart only.
                     *
                     * @event FusionCharts#labelDragEnd
                     * @group chart-powercharts:dragnode
                     *
                     * @param {number} chartX - x-coordinate of the pointer relative to the chart.
                     * @param {number} chartY - y-coordinate of the pointer relative to the chart.
                     * @param {number} pageX - x-coordinate of the pointer relative to the page.
                     * @param {number} pageY - y-coordinate of the pointer relative to the page.
                     *
                     * @param {number} x - The x-value of the label node scaled as per the axis of the chart.
                     * @param {number} y - The y-value of the label node scaled as per the axis of the chart.
                     *
                     * @param {string} text - The text value of the label.
                     */
                    plotEventHandler.call(ele, chart, event, sourceEvent);
                }
                manager.clearLongPress.call(ele);
            }
        }, 'Dragnode']);

    }
]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-dragcolumn',
    function () {
        var global = this,
            lib = global.hcLib,
            //add the tools thats are requared
            pluck = lib.pluck,
            pluckNumber = lib.pluckNumber,
            parseUnsafeString = lib.parseUnsafeString,
            getValidValue = lib.getValidValue,
            // getDefinedColor = lib.getDefinedColor,
            toRaphaelColor = lib.toRaphaelColor,
            hasSVG = lib.hasSVG,
            SETROLLOVERATTR = 'setRolloverAttr',
            SETROLLOUTATTR = 'setRolloutAttr',
            ROLLOVER = 'DataPlotRollOver',
            ROLLOUT = 'DataPlotRollOut',
            COMPONENT = 'component',
            DATASET = 'dataset',
            math = Math,
            mathRound = math.round,
            mathAbs = math.abs,
            plotEventHandler = lib.plotEventHandler;

        FusionCharts.register(COMPONENT, [DATASET, 'DragColumn',{
            /*
             * Function for drawing 2D columns.
             * This function is called every time for each dataset when they are initially drawn or shown/hidden from
             * the drawGraph() function.
             */
            configure: function () {
                var dataset = this,
                    conf,
                    chartAttr = dataset.chart.jsonData.chart,
                    data,
                    i,
                    config,
                    JSONData = dataset.JSONData,
                    setDataArr = dataset.JSONData.data || [],
                    length,
                    setData;
                this.__base__.configure.call(dataset);
                conf = dataset.config;
                data = dataset.components.data;
                conf.allowDrag = pluckNumber(JSONData.allowdrag, 1);
                conf.allowNegDrag = pluckNumber(JSONData.allownegativedrag, 1);
                conf.allowAxisChange = pluckNumber(chartAttr.allowaxischange, 1);
                conf.snapToDivOnly = pluckNumber(chartAttr.snaptodivonly, 0);
                conf.snapToDiv = conf.snapToDivOnly ? 1 : pluckNumber(chartAttr.snaptodiv, 1);
                conf.doNotSnap = pluckNumber(chartAttr.donotsnap, 0);
                conf.snapToDivRelaxation = pluckNumber(chartAttr.snaptodivrelaxation, 10);
                if (conf.doNotSnap) {
                    conf.snapToDiv = conf.snapToDivOnly = 0;
                }
                length = data.length;
                for (i = 0; i < length; i++) {
                    setData = setDataArr[i] || {};
                    config = data[i].config;
                    config.allowDrag = pluckNumber(setData.allowdrag, conf.allowDrag);
                    config.allowNegDrag = pluckNumber(setData.allownegativedrag, conf.allowNegDrag);
                }

            },
            /**
             * This method handles all mouse events of an dataset.
             * @param {String} eventType name of the event
             * @param {number} plotIndex index of the plot where this event has been occured
             * @param {Event} originalEvent reference of the original mouse event
             */
            _firePlotEvent: function (eventType, plotIndex, e) {
                var dataset = this,
                    JSONData = dataset.JSONData,
                    chartAttr = dataset.chart.jsonData.chart,
                    chart = dataset.chart,
                    dataSetConf = dataset.config,
                    chartConfig = chart.config,
                    useplotgradientcolor = chartConfig.useplotgradientcolor,
                    useroundedges = chartConfig.useroundedges,
                    chartComp = chart.components,
                    paper = chartComp.paper,
                    canvas = paper.canvas,
                    style = canvas.style,
                    NumberFormatter = chartComp.numberFormatter,
                    data = dataset.components.data[plotIndex],
                    config = data.config,
                    setElement = data.graphics.element,
                    setTooltext,
                    toolText = config.finalTooltext,
                    tip = lib.toolTip,
                    originalEvent = e.originalEvent,
                    dragMouseAttr = hasSVG && 'ns-resize' || 'n-resize',
                    pointerMouseAttr = 'default',
                    tolerance,
                    oriEvent = e.originalEvent,
                    coordinate = lib.getMouseCoordinate(chart.linkedItems.container, oriEvent),
                    chartY = coordinate.chartY,
                    yPos = data._yPos,
                    height = data._height,
                    formattedVal,
                    yAxis = chartComp.yAxis[0],
                    yBasePos = yAxis.getPixel(yAxis.getAxisBase()),
                    value,
                    yActual,
                    canvasTop = chartConfig.canvasTop,
                    canvasBottom = chartConfig.canvasBottom,
                    allowDrag = config.allowDrag,
                    allowNegDrag = config.allowNegDrag,
                    lowerDragBoundary = allowNegDrag ? canvasBottom : yBasePos,
                    eventArgsArr,
                    eventArgs,
                    rolloverdata,
                    rolloutedata,
                    fill,
                    angle,
                    colTop = yPos,
                    colBottom = yPos + height;

                tolerance = chartConfig.dragTolerance + 1;

                value = config.setValue;

                yActual = (yPos >= yBasePos) ? (yPos + height) : yPos;

                if (setElement) {
                    setTooltext = getValidValue(parseUnsafeString(pluck(config.origToolText,
                        JSONData.plottooltext, chartAttr.plottooltext)));
                    switch (eventType) {
                        case 'mouseover' :
                            //set flag on mouse over
                            dataSetConf.mouseIn = true;
                            toolText && tip.setStyle(paper);
                            if (chartY <= colBottom  - tolerance && chartY >= colTop + tolerance) {
                                tip.setPosition(originalEvent);
                                tip.draw(toolText, paper);
                            }

                            //fire _rollOverResponseSetter if its not already fired and
                            //cursor position is on column body
                            if(!config._rollOverResponseSetterFire && chartY <= colBottom && chartY >= colTop) {
                                dataset._rolloverResponseSetter(chart, setElement, originalEvent);
                                //set flag true as _rollOverResponseSetter is fired
                                config._rollOverResponseSetterFire = true;
                            }
                            break;

                        case 'mouseout' :
                            //set flag on mouse out
                            dataSetConf.mouseIn = false;
                            style.cursor = pointerMouseAttr;
                            //fire _rolloutResponseSetter if _rolloverResponseSetter is fired
                            config._rollOverResponseSetterFire &&
                                dataset._rolloutResponseSetter(chart, setElement, originalEvent);
                            //set flag false as _rolloutResponseSetter is fired
                            config._rollOverResponseSetterFire = false;
                            tip.hide();
                            break;

                        case 'click' :
                            plotEventHandler.call(setElement, chart, originalEvent);
                            break;

                        case 'touchmove' :
                        case 'mousemove' :
                            if (config.dragStart) {
                                (oriEvent.preventDefault) ? oriEvent.preventDefault() : oriEvent.returnValue = false;
                                config._rollOverResponseSetterFire = false;
                                style.cursor = dragMouseAttr;
                                //counter on drag move
                                config._pointerDy++;
                                //calculate chartY with _dragBuffer
                                chartY += config._dragBuffer;
                                //update chartY on canvas edge crossing
                                if(chartY < canvasTop) {
                                    chartY = canvasTop;
                                } else if(chartY > lowerDragBoundary) {
                                    chartY = lowerDragBoundary;
                                }
                                //calculate yPos
                                yPos = yBasePos < chartY ? yBasePos : chartY;
                                //calculate height
                                height = mathAbs(yBasePos - chartY);
                                data._yPos = yPos;
                                data._height = height;
                                yActual = (yPos >= yBasePos) ? (yPos + height) : yPos;
                                value = config.setValue = mathRound(yAxis.getValue(yActual - canvasTop));
                                formattedVal = NumberFormatter.dataLabels(value);
                                config.toolTipValue = formattedVal;
                                config.displayValue = pluck(config.setDisplayValue, formattedVal);
                                if (useplotgradientcolor && !useroundedges) {
                                    config.colorArr[0].FCcolor.angle = angle = yPos < yBasePos ? 90 : 270;
                                }
                                setElement.attr({
                                    y : data._yPos,
                                    height : data._height,
                                    fill : toRaphaelColor(config.colorArr[0])
                                });

                                dataset.drawLabel(plotIndex, plotIndex + 1);
                                data.graphics.element = setElement;
                                tip.hide();

                                //fire dataplotDragStart event
                                if (config._pointerDy == 1) {
                                    eventArgs = {
                                        dataIndex: plotIndex,
                                        datasetIndex: data.datasetIndex,
                                        startValue: data.startValue,
                                        datasetName: data.name
                                    };
                                    global.raiseEvent('dataplotDragStart', eventArgs, chart.chartInstance);
                                }
                            }
                            else {
                                yActual = (yPos >= yBasePos) ? (yPos + height) : yPos;

                                if (allowDrag && chartY >= yActual - tolerance && chartY <= yActual + tolerance) {
                                    style.cursor = dragMouseAttr;
                                    tip.hide();
                                }
                                else {
                                    style.cursor = pointerMouseAttr;
                                    if (config._rollOverResponseSetterFire) {
                                        tip.setPosition(originalEvent);
                                        tip.draw(toolText, paper);
                                    }
                                }
                                //fire _rollOverResponseSetter if its not already fired and
                                //cursor position is on column body
                                if (!config._rollOverResponseSetterFire && chartY <= colBottom && chartY >= colTop) {
                                    dataset._rolloverResponseSetter(chart, setElement, originalEvent);
                                    config._rollOverResponseSetterFire = true;
                                }
                                else if (config._rollOverResponseSetterFire &&
                                                                !(chartY <= colBottom && chartY >= colTop)) {
                                    tip.hide();
                                    config._rollOverResponseSetterFire = false;
                                    dataset._rolloutResponseSetter(chart, setElement, originalEvent);
                                }
                            }
                            break;

                        case 'touchend':
                        case 'mouseup' :
                            dataSetConf.mousedown = false;
                            if (config.dragStart) {
                                dataset.setMaxMin();
                                chart._setDataLimits();
                                eventArgs = {
                                    dataIndex: plotIndex,
                                    datasetIndex: data.datasetIndex,
                                    startValue: data.startValue,
                                    endValue: config.setValue,
                                    datasetName: data.name
                                };
                                eventArgsArr = [
                                    chart.chartInstance.id,
                                    eventArgs.dataIndex,
                                    eventArgs.datasetIndex,
                                    eventArgs.datasetName,
                                    eventArgs.startValue,
                                    eventArgs.endValue
                                ];

                                if (config._pointerDy) {
                                    global.raiseEvent('dataplotDragEnd', eventArgs, chart.chartInstance);

                                    // Fire the ChartUpdated event
                                    lib.raiseEvent('chartupdated', eventArgs, chart.chartInstance, eventArgsArr);
                                }
                                if (useplotgradientcolor && !useroundedges) {
                                    angle = yPos >= yBasePos ? 90 : 270;
                                    if ((rolloverdata = setElement.data(SETROLLOVERATTR)) && rolloverdata.fill) {
                                        fill = rolloverdata.fill;
                                        fill = fill.split('-');
                                        fill[0] = angle;
                                        rolloverdata.fill = fill.join('-');
                                    }
                                    if ((rolloutedata = setElement.data(SETROLLOUTATTR)) && rolloutedata.fill) {
                                        fill = rolloutedata.fill;
                                        fill = fill.split('-');
                                        fill[0] = angle;
                                        rolloutedata.fill = fill.join('-');
                                    }
                                }
                            }
                            //difference on actualY and chartY
                            config._dragBuffer = 0;
                            //counter on drag move
                            config._pointerDy = 0;
                            config.dragStart = false;
                            config.dragStart = false;
                            toolText = config.finalTooltext = config.toolText !== false ? (config.toolText +
                                (setTooltext ? '' : config.toolTipValue)) : '';
                            if (!(chartY >= yActual - tolerance &&
                                            chartY <= yActual + tolerance)) {
                                style.cursor = pointerMouseAttr;
                            }
                            break;

                        case 'touchstart' :
                        case 'mousedown' :
                            if (dataSetConf.mouseIn) {
                                dataSetConf.mousedown = true;
                                yActual = (yPos >= yBasePos) ? (yPos + height) : yPos;
                                if (allowDrag && chartY >= yActual - tolerance &&
                                        chartY <= yActual + tolerance) {
                                    //set drag flag
                                    config.dragStart = true;
                                    config._pointerDy = 0;
                                    config._dragStartY = chartY;
                                    //difference on actualY and chartY
                                    config._dragBuffer = yActual - chartY;

                                    data.startValue = config.setValue;
                                    data.name = dataSetConf.seriesname;
                                    data.datasetIndex = dataset.positionIndex;

                                    data.dragged = true;
                                }
                                else {
                                    config.dragStart = false;
                                }
                            }

                    }
                }
            },
            _rolloverResponseSetter : function (chart, elem, event) {
                var elData = elem.getData();
                // Check whether the plot is in dragged state or not if
                // drag then dont fire rolloverevent
                if (elData.showHoverEffect !== 0 && elData.draged !== true) {
                    elem.attr(elem.getData().setRolloverAttr);
                    plotEventHandler.call(elem, chart, event, ROLLOVER);
                }
            },

            _rolloutResponseSetter : function (chart, elem, event) {
                var elData = elem.getData();
                // Check whether the plot is in draggedstate or not if drag then dont fire rolloutevent
                if (elData.showHoverEffect !== 0 && elData.draged !== true) {
                    elem.attr(elem.getData().setRolloutAttr);
                    plotEventHandler.call(elem, chart, event, ROLLOUT);
                }
            },
            getJSONData: function () {
                var dataset = this,
                    JSONData = dataset.JSONData.data,
                    dataStore = dataset.components.data,
                    dataArr = [],
                    obj = {},
                    updatedDataObj,
                    dataObj,
                    prop,
                    len,
                    i;

                for (i = 0, len = JSONData.length; i < len; i++) {
                    dataObj = JSONData[i];
                    updatedDataObj = dataStore[i];
                    obj = {};
                    for (prop in dataObj) {
                        if (prop === 'value') {
                            obj[prop] = updatedDataObj.config.setValue;
                        }
                        else {
                            obj[prop] = dataObj[prop];
                        }
                    }
                    dataArr.push(obj);
                }
                return {
                    data: dataArr
                };
            }
        }, 'Column']);

    }
]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-dragarea',
    function () {
        var global = this,
            lib = global.hcLib,
            R = lib.Raphael,
            isVML = (R.type === 'VML'),
            BLANKSTRING = lib.BLANKSTRING,
            preDefStr = lib.preDefStr,
            parseUnsafeString = lib.parseUnsafeString,
            getValidValue = lib.getValidValue,
            DRAGLINE = 'dragline',
            hiddenStr = preDefStr.hiddenStr,
            //add the tools thats are requared
            pluck = lib.pluck,
            pluckNumber = lib.pluckNumber,
            hasSVG = lib.hasSVG,
            SETROLLOVERATTR = 'setRolloverAttr',
            SETROLLOUTATTR = 'setRolloutAttr',
            COMPONENT = 'component',
            DATASET = 'dataset',
            math = Math,
            mathRound = math.round,
            mathMin = math.min,
            mathMax = math.max,
            ROLLOVER = 'DataPlotRollOver',
            ROLLOUT = 'DataPlotRollOut',
            DATAPLOTCLICK = 'dataplotclick',
            plotEventHandler = lib.plotEventHandler;

        FusionCharts.register(COMPONENT, [DATASET, 'DragArea',{
            configure: function () {
                var dataset = this,
                    conf,
                    chart = dataset.chart,
                    chartAttr = chart.jsonData.chart,
                    Area = FusionCharts.get(COMPONENT, [DATASET, 'area']),
                    data,
                    i,
                    config,
                    setData,
                    JSONData = dataset.JSONData,
                    setDataArr = JSONData.data || [],
                    length;
                Area.prototype.configure.call(dataset);
                conf = dataset.config;
                data = dataset.components.data;
                conf.allowDrag = pluckNumber(JSONData.allowdrag, 1);
                conf.allowNegDrag = pluckNumber(JSONData.allownegativedrag, 1);
                conf.allowAxisChange = pluckNumber(chartAttr.allowaxischange, 1);
                conf.snapToDivOnly = pluckNumber(chartAttr.snaptodivonly, 0);
                conf.doNotSnap = pluckNumber(chartAttr.donotsnap, 0);
                conf.snapToDiv = pluckNumber(chartAttr.snaptodiv, 1);
                conf.snapToDivRelaxation = pluckNumber(chartAttr.snaptodivrelaxation, 10);
                if (conf.doNotSnap) {
                    conf.snapToDiv = conf.snapToDivOnly = 0;
                }
                length = data.length;
                for (i = 0; i < length; i++) {
                    setData = setDataArr[i] || {};
                    config = data[i].config;
                    config.allowDrag = pluckNumber(setData.allowdrag, conf.allowDrag);
                    config.allowNegDrag = pluckNumber(setData.allownegativedrag, conf.allowNegDrag);
                }

            },
            updateImage: function (dataObj) {
                var dataset = this,
                    chart = dataset.chart,
                    graphics = dataObj.graphics,
                    image = graphics.image || graphics.element,
                    config = dataObj.config,
                    anchorProps = config.anchorProps,
                    hoverEffects = config.hoverEffects,
                    imgRef = image && image.data('imgRef'),
                    getPathString = function (data) {
                        var PathArrLength = data.length,
                            pathString = BLANKSTRING,
                            ittr;
                        for (ittr = 0; ittr < PathArrLength; ittr += 1) {
                            pathString += ' '+data[ittr];
                        }
                        return pathString;
                    },
                    scale = anchorProps.imageScale,
                    paper = chart.components.paper,
                    imgH = imgRef.height * scale * 0.01,
                    imgW = imgRef.width * scale * 0.01,
                    x = dataObj._xPos,
                    y = dataObj._yPos,
                    hoverScale = hoverEffects.imageHoverScale,
                    hotW = (imgRef.width * hoverScale * 0.01),
                    hotH = (imgRef.height * hoverScale * 0.01),
                    isAnchorRadius = anchorProps.isAnchorRadius,
                    markerRadius = anchorProps.radius = isAnchorRadius ?
                        anchorProps.radius : mathMin(imgW, imgH)/2,
                    imagePadding = anchorProps.imagePadding,
                    rolloutClipRadius = markerRadius - imagePadding - anchorProps.borderThickness * 0.5,
                    rolloverClipRadius = hoverEffects.radius -
                        imagePadding - hoverEffects.anchorBorderThickness * 0.5,
                    symbol = anchorProps.symbol[1],
                    imageRollOverPath,
                    setRolloverAttr,
                    tempPath = paper.polypath(symbol || 2, x, y,
                        rolloutClipRadius > 0 ? rolloutClipRadius : 0,
                        anchorProps.startAngle,
                        0)
                    .attr({visibility : hiddenStr}),
                    imageRolloutPath = getPathString(tempPath.attrs.path),
                    setRolloutAttr = {
                        x: x - imgRef.width * scale * 0.005,
                        y: y - imgRef.height * scale * 0.005,
                        width: imgW,
                        height: imgH,
                        alpha: 100
                    };

                if (!isVML) {
                    setRolloutAttr['clip-path'] = imageRolloutPath;
                }
                tempPath.remove();

                tempPath = paper.polypath(symbol || 2, x, y,
                    rolloverClipRadius > 0 ? rolloverClipRadius : 0,
                    hoverEffects.startAngle,
                    hoverEffects.dip);

                imageRollOverPath = getPathString(tempPath.attrs.path);

                tempPath.remove();
                setRolloverAttr = {
                    x: x - imgRef.width * hoverScale * 0.005,
                    y: y - imgRef.height * hoverScale * 0.005,
                    width: hotW,
                    height: hotH,
                    alpha: 100
                };

                if (!isVML) {
                    setRolloverAttr['clip-path'] = imageRollOverPath;
                }
                image.attr(setRolloutAttr);
                image.data(SETROLLOVERATTR, setRolloverAttr);
                image.data(SETROLLOUTATTR, setRolloutAttr);
            },
            /**
             * This method handles all mouse events of an dataset.
             * @param {String} eventType name of the event
             * @param {number} plotIndex index of the plot where this event has been occured
             * @param {Event} originalEvent reference of the original mouse event
             */
            _firePlotEvent: function (eventType, plotIndex, eventObj) {
                var dataset = this,
                    JSONData = dataset.JSONData,
                    chartAttr = dataset.chart.jsonData.chart,
                    chart = dataset.chart,
                    chartConfig = chart.config,
                    chartComp = chart.components,
                    paper = chartComp.paper,
                    tip = lib.toolTip,
                    canvas = paper.canvas,
                    style = canvas.style,
                    NumberFormatter = chartComp.numberFormatter,
                    datasetComp = dataset.components,
                    plotItem = datasetComp.data[plotIndex],
                    length = datasetComp.data.length,
                    dataArr,
                    DragArea = FusionCharts.get(COMPONENT, [DATASET, 'DragArea']),
                    dataSetConf = dataset.config,
                    datasetIndex = dataset.index,
                    originalEvent = eventObj.originalEvent,
                    dragMouseAttr = hasSVG && 'ns-resize' || 'n-resize',
                    pointerMouseAttr = 'default',
                    tolerance,
                    coordinate,
                    chartY,
                    chartX,
                    yPos,
                    xPos,
                    i,
                    setObj,
                    pathArr,
                    startIndex,
                    endIndex,
                    connector,
                    element,
                    hoverEnabled,
                    setTooltext,
                    toolText,
                    link,
                    eventArgs,
                    eventArgsArr,
                    config,
                    formattedVal,
                    changedTouch,
                    yBasePos = plotItem && plotItem._yBasePos,
                    value,
                    yAxis = chartComp.yAxis[0],
                    canvasTop = chartConfig.canvasTop,
                    canvasBottom = chartConfig.canvasBottom,
                    allowDrag,
                    allowNegDrag,
                    datasetGraphics = dataset.graphics,
                    mainLineElement = datasetGraphics.lineElement,
                    anchorProps,
                    anchorImageUrl,
                    anchorElement,
                    image,
                    path,
                    lowerDragBoundary = allowNegDrag ? canvasBottom : yBasePos,
                    radius,
                    hoverRadius,
                    hoverAnchorSides,
                    hoverAnchorAngle,
                    anchorStartAngle,
                    rolloverData,
                    rolloverdata,
                    rolloutdata,
                    isHoverEnabled,
                    isDragLine = dataset.type === DRAGLINE ? true : false;

                if (eventType === 'touchend') {
                    changedTouch = originalEvent.changedTouches[0];
                    originalEvent.pageX = changedTouch && changedTouch.pageX;
                    originalEvent.pageY = changedTouch && changedTouch.pageY;
                }
                coordinate = lib.getMouseCoordinate(chart.linkedItems.container, originalEvent);
                chartY = coordinate.chartY;
                chartX = coordinate.chartX;

                if (plotItem) {
                    element = plotItem.graphics.element;
                    config = plotItem.config;
                    anchorProps = config.anchorProps;
                    anchorImageUrl = anchorProps.imageUrl;
                    image = plotItem.graphics.image;
                    anchorElement = element;
                    rolloverData = anchorElement && anchorElement.data(SETROLLOVERATTR);
                    isHoverEnabled = config.hoverEffects && config.hoverEffects.enabled;
                    hoverRadius = isHoverEnabled && rolloverData.polypath[3];
                    hoverAnchorSides = isHoverEnabled && rolloverData.polypath[0];
                    hoverAnchorAngle = isHoverEnabled && rolloverData.polypath[4];
                    anchorStartAngle = anchorProps.startAngle || 90;
                    link = config.setLink;
                    setTooltext = getValidValue(parseUnsafeString(pluck(config.origToolText,
                        JSONData.plottooltext, chartAttr.plottooltext)));
                    toolText = config.finalTooltext;
                    hoverEnabled = config.hoverEffects.enabled;
                    eventArgs = config.eventArgs;
                    yPos = plotItem._yPos;
                    xPos = plotItem._xPos;
                    allowDrag = config.allowDrag;
                    allowNegDrag = config.allowNegDrag;
                    lowerDragBoundary = allowNegDrag ? canvasBottom : yBasePos;
                    radius = anchorProps.radius;
                    config.dragTolerance =  config.dragTolerance < anchorProps.markerRadius ?
                                                                anchorProps.markerRadius + 0.5 : config.dragTolerance;
                    tolerance = mathMax(config.dragTolerance, config.hoverEffects.anchorRadius || 0) + 1;

                    switch (eventType) {
                        case 'mouseover':
                            dataSetConf.mouseIn = true;
                            if (config.allowDrag) {
                                style.cursor = dragMouseAttr;
                            }
                            if (!config.dragStart && toolText && !config.dragStart) {
                                tip.setStyle(paper);
                                tip.setPosition(originalEvent);
                                tip.draw(toolText, paper);
                            }
                            if (!config.dragStart) {
                                hoverEnabled && dataset._hoverPlotAnchor(plotItem, ROLLOVER);
                                element && plotEventHandler.call(element, chart, originalEvent, ROLLOVER, eventArgs);
                            }
                            break;

                        case 'mouseout':
                            dataSetConf.mouseIn = false;
                            style.cursor = pointerMouseAttr;

                            hoverEnabled && dataset._hoverPlotAnchor(plotItem, ROLLOUT);
                            element && plotEventHandler.call(element, chart, originalEvent, ROLLOUT, eventArgs);
                            tip.hide();
                            break;

                        case 'touchmove':
                        case 'mousemove':
                            if (config.dragStart) {
                                (originalEvent.preventDefault) ? originalEvent.preventDefault() :
                                    originalEvent.returnValue = false;
                                config.allowDrag && (style.cursor = dragMouseAttr);
                                config._pointerDy++;
                                chartY += config._dragBuffer;
                                if(chartY < canvasTop) {
                                    chartY = canvasTop;
                                } else if(chartY > lowerDragBoundary) {
                                    chartY = lowerDragBoundary;
                                }
                                plotItem._yPos = chartY;
                                value = config.setValue = mathRound(yAxis.getValue(yPos - canvasTop));
                                formattedVal = NumberFormatter.dataLabels(value);
                                config.toolTipValue = formattedVal;
                                config.displayValue = formattedVal;

                                dataset.drawLabel(plotIndex, plotIndex + 1);
                                plotItem.graphics.element = element;

                                if (isVML && anchorImageUrl) {
                                    image = anchorElement;
                                }
                                else {

                                    if (isHoverEnabled && (rolloverdata = anchorElement.data(SETROLLOVERATTR))) {
                                        rolloverdata.polypath[2] = plotItem._yPos;
                                    }
                                    if (isHoverEnabled && (rolloutdata = anchorElement.data(SETROLLOUTATTR))) {
                                        rolloutdata.polypath[2] = plotItem._yPos;
                                    }

                                    anchorElement && anchorElement.attr(rolloutdata || {
                                        polypath: [anchorProps.symbol[1] || 2, xPos, plotItem._yPos,
                                            anchorProps.radius, anchorStartAngle, 0]
                                    });
                                }

                                if (image) {
                                    DragArea.prototype.updateImage.call(dataset, plotItem);
                                }

                                dataArr = datasetComp.data;
                                path = dataset.getLinePath(dataArr, {});

                                if (isDragLine) {
                                    for (i = 0; i < length; i++) {
                                        connector = dataArr[i].graphics && dataArr[i].graphics.connector;

                                        if (connector) {

                                            setObj = dataArr[i];
                                            startIndex = setObj.config.connStartIndex;
                                            endIndex = setObj.config.connEndIndex;

                                            pathArr = dataset.getLinePath(dataArr, {}, {
                                                begin: startIndex,
                                                end: endIndex + 1
                                            });

                                            connector.attr({
                                                path: pathArr.getPathArr()
                                            });
                                        }
                                    }
                                }

                                if (mainLineElement) {
                                    dataSetConf = dataset.config;
                                    startIndex = config.pathStartIndex;
                                    endIndex = config.pathEndIndex;
                                    pathArr = config.lastPath;
                                    pathArr = dataset.getLinePath(dataArr, {}, {
                                        begin: startIndex,
                                        end: endIndex
                                    });
                                    mainLineElement.attr({
                                        path: pathArr.getPathArr()
                                    });
                                }

                                if (config._pointerDy == 1) {
                                    eventArgs = {
                                        dataIndex: plotIndex,
                                        datasetIndex: datasetIndex,
                                        startValue: plotItem.startValue,
                                        endValue: config.setValue,
                                        datasetName: plotItem.name
                                    };
                                    global.raiseEvent('dataplotDragStart', eventArgs, chart.chartInstance);
                                }
                            }
                            if (!config.dragStart && toolText &&
                                        chartY >= yPos - tolerance && chartY <= yPos + tolerance &&
                                                    chartX <= xPos + tolerance && chartX >= xPos - tolerance) {
                                tip.setPosition(originalEvent);
                                tip.draw(toolText, paper);
                            } else {
                                tip.hide();
                            }

                            break;

                        case 'click':
                            element && plotEventHandler.call(element, chart, originalEvent, DATAPLOTCLICK, eventArgs);
                            break;

                        case 'touchend':
                        case 'mouseup' :
                            dataSetConf.mousedown = false;
                            if (config.dragStart) {
                                dataset.setMaxMin();
                                chart._setDataLimits();

                                eventArgs = {
                                    dataIndex: plotIndex,
                                    datasetIndex: datasetIndex,
                                    startValue: plotItem.startValue,
                                    endValue: config.setValue,
                                    datasetName: plotItem.name
                                };
                                eventArgsArr = [
                                    chart.chartInstance.id,
                                    eventArgs.dataIndex,
                                    eventArgs.datasetIndex,
                                    eventArgs.datasetName,
                                    eventArgs.startValue,
                                    eventArgs.endValue
                                ];
                                /**
                                 * The four dragable charts: `dragnode`, `dragcolumn2d`, `dragline` and `dragarea`
                                 * fires this event when their data plots are stopped being dragged.
                                 *
                                 * @event FusionCharts#dataplotDragEnd
                                 * @group chart-powercharts:drag
                                 */
                                if (config._pointerDy) {
                                    hoverEnabled && dataset._hoverPlotAnchor(plotItem, ROLLOUT);
                                    global.raiseEvent('dataplotDragEnd', eventArgs, chart.chartInstance);
                                    // Fire the ChartUpdated event
                                    lib.raiseEvent('chartupdated', eventArgs, chart.chartInstance, eventArgsArr);
                                }
                            }
                            toolText = config.finalTooltext = config.toolText !== false ? (config.toolText +
                                (setTooltext ? '' : config.toolTipValue)) : '';

                            if (!(chartY >= yPos - tolerance && chartY <= yPos + tolerance &&
                                                    chartX <= xPos + tolerance && chartX >= xPos - tolerance)) {

                                style.cursor = pointerMouseAttr;
                            }
                            if (dataSetConf.mouseIn && !config.dragStart) {
                                tip.setPosition(originalEvent);
                                tip.draw(toolText, paper);
                            }
                            config._dragBuffer = 0;
                            config._pointerDy = 0;
                            config.dragStart = false;
                            break;

                        case 'touchstart':
                        case 'mousedown' :
                            if (dataSetConf.mouseIn) {
                                dataSetConf.mousedown = true;
                                if (allowDrag &&
                                        chartY >= yPos - tolerance &&  chartY <= yPos + tolerance &&
                                            chartX <= xPos + tolerance && chartX >= xPos - tolerance) {
                                    config.dragStart = true;
                                    config._pointerDy = 0;
                                    config._dragStartY = chartY;
                                    config._dragBuffer = yPos - chartY;

                                    plotItem.dragged = true;

                                    plotItem.startValue = config.setValue;
                                    plotItem.name = dataSetConf.seriesname;
                                    plotItem.datasetIndex = dataset.positionIndex;
                                    eventArgs = {
                                        dataIndex: plotIndex + 1,
                                        datasetIndex: plotItem.datasetIndex,
                                        startValue: plotItem.startValue,
                                        datasetName: plotItem.name
                                    };
                                } else {
                                    config.dragStart = false;
                                }
                            }
                    }
                }
            },
            getJSONData: function () {
                var dataset = this,
                    JSONData = dataset.JSONData.data,
                    dataStore = dataset.components.data,
                    dataArr = [],
                    obj = {},
                    dataObj,
                    updatedDataObj,
                    prop,
                    len,
                    i;
                for (i = 0, len = JSONData.length; i < len; i++) {
                    dataObj = JSONData[i];
                    updatedDataObj = dataStore[i];
                    obj = {};
                    for (prop in dataObj) {
                        if (prop === 'value') {
                            obj[prop] = updatedDataObj.config.setValue;
                        }
                        else {
                            obj[prop] = dataObj[prop];
                        }
                    }
                    dataArr.push(obj);
                }
                return {
                    data: dataArr
                };
            }
        }, 'Area']);

    }
]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-dragline',
    function () {
        var global = this,
            lib = global.hcLib,
            preDefStr = lib.preDefStr,
            LINE = preDefStr.line,
            COMPONENT = 'component',
            DATASET = 'dataset';

        FusionCharts.register(COMPONENT, [DATASET, 'DragLine', {
            type : 'dragline',
            configure: FusionCharts.get(COMPONENT, [DATASET, 'DragArea']).prototype.configure,
            /**
             * This method handles all mouse events of an dataset.
             * @param {String} eventType name of the event
             * @param {number} plotIndex index of the plot where this event has been occured
             * @param {Event} originalEvent reference of the original mouse event
             */
            _firePlotEvent: FusionCharts.get(COMPONENT, [DATASET, 'DragArea']).prototype._firePlotEvent,
            getJSONData: function () {
                var dataset = this,
                    JSONData = dataset.JSONData.data,
                    dataStore = dataset.components.data,
                    dataArr = [],
                    obj = {},
                    dataObj,
                    prop,
                    updatedDataObj,
                    len,
                    i;
                for (i = 0, len = JSONData.length; i < len; i++) {
                    dataObj = JSONData[i];
                    updatedDataObj = dataStore[i];
                    obj = {};
                    for (prop in dataObj) {
                        if (prop === 'value') {
                            obj[prop] = updatedDataObj.config.setValue;
                        }
                        else {
                            obj[prop] = dataObj[prop];
                        }
                    }
                    dataArr.push(obj);
                }
                return {
                    data: dataArr
                };
            }
        }, LINE]);

    }
]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-selectscatter',
    function () {
        var global = this,
            lib = global.hcLib,
            convertColor = lib.graphics.convertColor,
            preDefStr = lib.preDefStr,
            altHGridColorStr = preDefStr.altHGridColorStr,
            altHGridAlphaStr = preDefStr.altHGridAlphaStr,
            colorStrings = preDefStr.colors,
            COLOR_FFFFFF = colorStrings.FFFFFF,
            getValidValue = lib.getValidValue,
            ZEROSTRING = lib.ZEROSTRING,
            bindSelectionEvent = lib.bindSelectionEvent,
            getMouseCoordinate = lib.getMouseCoordinate,
            extend2 = lib.extend2,
            //add the tools thats are requared
            pluck = lib.pluck,
            pluckNumber = lib.pluckNumber,
            COMPONENT = 'component',
            DATASET = 'dataset';

        FusionCharts.register(COMPONENT, [DATASET, 'selectScatter', {
            configure : function () {
                var dataSet = this,
                    chart = dataSet.chart,
                    chartConfig = chart.config,
                    chartComponents = chart.components,
                    chartAttr = chart.jsonData.chart,
                    colorM = chartComponents.colorManager,
                    borderColor = pluck(chartAttr.selectbordercolor,
                        colorM.getColor('canvasBorderColor')),
                    borderAlpha = pluckNumber(chartAttr.selectborderalpha,
                        colorM.getColor('canvasBorderAlpha'));

                FusionCharts.get(COMPONENT, [DATASET, 'scatter']).prototype.configure.call(dataSet);

                chartConfig.selectBorderColor = //convertColor(borderColor, borderAlpha);
                {
                    FCcolor: {
                        color: borderColor,
                        alpha: borderAlpha
                    }
                };
                chartConfig.selectFillColor = convertColor(
                    pluck(chartAttr.selectfillcolor,
                        colorM.getColor(altHGridColorStr)),
                    pluckNumber(chartAttr.selectfillalpha,
                        colorM.getColor(altHGridAlphaStr)));

                chartConfig.selectionCancelButtonBorderColor = convertColor(pluck(
                        chartAttr.selectioncancelbuttonbordercolor, borderColor),
                    pluckNumber(chartAttr.selectioncancelbuttonborderalpha, borderAlpha));
                chartConfig.selectionCancelButtonFillColor = convertColor(pluck(
                        chartAttr.selectioncancelbuttonfillcolor, COLOR_FFFFFF),
                    pluckNumber(chartAttr.selectioncancelbuttonfillalpha, 100));
                chartConfig.connativeZoom = false;
                chartConfig.zoomType = 'xy';

                chartConfig.formAction = getValidValue(chartAttr.formaction);

                if (chartAttr.submitdataasxml === ZEROSTRING && !chartAttr.formdataformat) {
                    chartAttr.formdataformat = global.dataFormats.CSV;
                }

                chartConfig.formDataFormat = pluck(chartAttr.formdataformat,
                    global.dataFormats.XML);
                chartConfig.formTarget = pluck(chartAttr.formtarget, '_self');
                chartConfig.formMethod = pluck(chartAttr.formmethod, 'POST');
                chartConfig.submitFormAsAjax = pluckNumber(chartAttr.submitformusingajax, 1);
            },

            draw : function() {
                var dataSet = this,
                    chart = dataSet.chart,
                    container = chart.linkedItems.container;

                FusionCharts.get(COMPONENT, [DATASET, 'scatter']).prototype.draw.call(dataSet);

                bindSelectionEvent(chart, {
                    selectionStart: function(data) {
                        var pos = getMouseCoordinate(container, data.originalEvent),
                            eventArgs = extend2({
                                selectionLeft: data.selectionLeft,
                                selectionTop: data.selectionTop,
                                selectionWidth: data.selectionWidth,
                                selectionHeight: data.selectionHeight,
                                startXValue: data.chart.components.xAxis[0].getAxisPosition(data.selectionLeft, 1),
                                startYValue: data.chart.components.yAxis[0].getAxisPosition(data.selectionTop, 1)
                            }, pos);
                        /**
                         * Raised when user starts to draw a selection box on a `selectScatter` chart.
                         * @event FusionCharts#selectionStart
                         *
                         * @param {number} chartX - The x-coordinate of the mouse with respect to the chart.
                         * @param {number} chartY - The y-coordinate of the mouse with respect to the chart.
                         * @param {number} pageX - The x-coordinate of the mouse with respect to the page.
                         * @param {number} pageY - The y-coordinate of the mouse with respect to the page.
                         * @param {number} startXValue - The value on the canvas x-axis where the selection started.
                         * @param {number} startYValue - The value on the canvas y-axis where the selection started.
                         */
                        global.raiseEvent('selectionStart', eventArgs, data.chart.chartInstance);
                    },
                    selectionEnd: function(data) {
                        var pos = getMouseCoordinate(container, data.originalEvent),
                            xAxis = data.chart.components.xAxis[0],
                            yAxis = data.chart.components.yAxis[0],
                            eventArgs = extend2({
                                selectionLeft: data.selectionLeft,
                                selectionTop: data.selectionTop,
                                selectionWidth: data.selectionWidth,
                                selectionHeight: data.selectionHeight,
                                startXValue: xAxis.getAxisPosition(data.selectionLeft, 1),
                                startYValue: yAxis.getAxisPosition(data.selectionTop, 1),
                                endXValue: xAxis.getAxisPosition(data.selectionLeft + data.selectionWidth, 1),
                                endYValue: yAxis.getAxisPosition(data.selectionTop + data.selectionHeight, 1)
                            }, pos);

                        /**
                         * Raised when user completes a selection box on a `selectScatter` chart.
                         * @event FusionCharts#selectionEnd
                         *
                         * @param {number} chartX - The x-coordinate of the mouse with respect to the chart.
                         * @param {number} chartY - The y-coordinate of the mouse with respect to the chart.
                         * @param {number} pageX - The x-coordinate of the mouse with respect to the page.
                         * @param {number} pageY - The y-coordinate of the mouse with respect to the page.
                         * @param {number} startXValue - The value on the canvas x-axis where the selection started.
                         * @param {number} startYValue - The value on the canvas y-axis where the selection started.
                         * @param {number} endXValue - The value on the canvas x-axis where the selection ended.
                         * @param {number} endYValue - The value on the canvas y-axis where the selection ended.
                         * @param {number} selectionLeft - The x-coordinate from where selection started with
                         * respect to the chart.
                         * @param {number} selectionTop - The y-coordinate from where selection started with
                         * respect to the chart.
                         * @param {number} selectionWidth - The width of the selection in pixels.
                         * @param {number} selectionHeight - The height of the selection box in pixels.
                         */
                        global.raiseEvent('selectionEnd', eventArgs, data.chart.chartInstance);
                        data.chart.createSelectionBox(data);
                    }
                });
            }
        },'scatter']);

    }
]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-candlestick',
    function () {
        var global = this,
            lib = global.hcLib,
            preDefStr = lib.preDefStr,
            LINE = preDefStr.line,
            VOLUME = preDefStr.volume,
            BAR = preDefStr.bar,
            BLANKSTRING = lib.BLANKSTRING,
            getValidValue = lib.getValidValue,
            getFirstValue = lib.getFirstValue,
            getFirstColor = lib.getFirstColor,
            SETROLLOVERATTR = preDefStr.setRolloverAttrStr,
            SETROLLOUTATTR = preDefStr.setRolloutAttrStr,
            ZEROSTRING = lib.ZEROSTRING,
            parseUnsafeString = lib.parseUnsafeString,
            COLUMN = preDefStr.column,
            HUNDRED = '100',
            getDashStyle = lib.getDashStyle,
            animationObjStr = preDefStr.animationObjStr,
            UNDEFINED,
            columnStr = preDefStr.columnStr,
            shadowStr = preDefStr.shadowStr,
            toRaphaelColor = lib.toRaphaelColor,
            miterStr = preDefStr.miterStr,
            schedular = lib.schedular,
            t = 't',
            COMMA = ',',
            showHoverEffectStr = preDefStr.showHoverEffectStr,
            M = 'M',
            L = 'L',
            H = 'H',
            V = 'V',
            EVENTARGS = 'eventArgs',
            POINTER = 'pointer',
            DEFAULT = 'default',
            ROUND = preDefStr.ROUND,
            visibleStr = preDefStr.visibleStr,
            errorBarStr = preDefStr.errorBarStr,
            errorHotStr = preDefStr.errorHotStr,
            defined = function(obj) {
                return obj !== UNDEFINED && obj !== null;
            },
            NONE = 'none',
            // The default value for stroke-dash attribute.
            DASH_DEF = NONE,
            UNDERSCORE = preDefStr.UNDERSCORE,
            parseTooltext = lib.parseTooltext,
            BOLDSTARTTAG = '<b>',
            BOLDENDTAG = '</b>',
            BLANKSPACE = ' ',
            BREAKSTRING = '<br />',
            colorStrings = preDefStr.colors,
            extend2 = lib.extend2,
            configStr = preDefStr.configStr,
            COLOR_B90000 = colorStrings.B90000,
            COLOR_FFFFFF = colorStrings.FFFFFF,
            //add the tools thats are requared
            pluck = lib.pluck,
            pluckNumber = lib.pluckNumber,
            COMPONENT = 'component',
            DATASET = 'dataset',
            math = Math,
            mathRound = math.round,
            mathMin = math.min,
            mathMax = math.max,
            mathAbs = math.abs,
            ROLLOVER = 'DataPlotRollOver',
            ROLLOUT = 'DataPlotRollOut',
            plotEventHandler = lib.plotEventHandler;

        FusionCharts.register(COMPONENT, [DATASET, 'Candlestick', {
            type: 'Candlestick',
            configure: function () {
                if (this.plotType === VOLUME) {
                    this._configureVolume();
                    return;
                }
                var dataset = this,
                    conf = dataset.config,
                    chart = dataset.chart,
                    chartComponents = chart.components,
                    rawDataObj = chart.jsonData,
                    JSONData = dataset.JSONData,
                    dataArr = JSONData.data || [],
                    chartAttr = rawDataObj.chart,
                    BLANK = BLANKSTRING,
                    dataLength = dataArr.length,
                    plotPriceAs = conf.plotPriceAs = getValidValue(chartAttr.plotpriceas, BLANK).toLowerCase(),
                    numberFormatter = chartComponents.numberFormatter,
                    colorM = chartComponents.colorManager,
                    valueText,
                    setColor,
                    setBorderColor,
                    setAlpha,
                    dashStyle,
                    //Candle stick properties.
                    //Bear fill and border color - (Close lower than open)
                    bearBorderColor = conf.bearBorderColor =
                        getFirstColor(pluck(chartAttr.bearbordercolor, COLOR_B90000)),
                    bearFillColor = conf.bearFillColor =
                        getFirstColor(pluck(chartAttr.bearfillcolor, COLOR_B90000)),
                    //Bull fill and border color - Close higher than open
                    bullBorderColor = conf.bullBorderColor =
                        getFirstColor(pluck(chartAttr.bullbordercolor,
                        colorM.getColor('canvasBorderColor'))),
                    bullFillColor = conf.bullFillColor =
                    getFirstColor(pluck(chartAttr.bullfillcolor,
                        COLOR_FFFFFF)),
                    //Line Properties - Serves as line for bar & line and border for candle stick
                    plotLineThickness = conf.linethickness = conf.plotBorderThickness =
                        pluckNumber(chartAttr.plotlinethickness, (plotPriceAs == LINE ||
                        plotPriceAs == BAR) ? 2 : 1),
                    plotLineDashLen = conf.plotLineDashLen = pluckNumber(chartAttr.plotlinedashlen, 5),
                    plotLineDashGap = conf.plotLineDashGap = pluckNumber(chartAttr.plotlinedashgap, 4),
                    // Anchor cosmetics in data points
                    // Getting anchor cosmetics for the data points or its default values
                    // The default value is different from flash in order to render a
                    // perfect circle when no anchorside is provided.
                    drawAnchors = !! pluckNumber(chartAttr.drawanchors, 1),
                    setAnchorAngle = pluckNumber(chartAttr.anchorstartangle, 90),
                    setAnchorRadius = pluckNumber(chartAttr.anchorradius,
                        this.anchorRadius, 3),
                    setAnchorBorderColor = getFirstColor(pluck(chartAttr.anchorbordercolor,
                        bullBorderColor)),
                    setAnchorBorderThickness = pluckNumber(chartAttr.anchorborderthickness,
                        this.anchorBorderThickness, 1),
                    setAnchorBgColor = getFirstColor(pluck(chartAttr.anchorbgcolor,
                        colorM.getColor('anchorBgColor'))),
                    setAnchorAlpha = pluck(chartAttr.anchoralpha, ZEROSTRING),
                    setAnchorBgAlpha = pluck(chartAttr.anchorbgalpha, setAnchorAlpha),
                    pointShadow,
                    index,
                    dataObj,
                    toolText,
                    open,
                    close,
                    high,
                    low,
                    volume,
                    minValue,
                    maxValue,
                    x,
                    closeVal,
                    borderColor,
                    yVal,
                    isLine,
                    openVal,
                    dataStore,
                    setData,
                    config,
                    isCandleStick = false,
                    displayValue,
                    plotSpacePercent,
                    yMax = -Infinity,
                    yMin = +Infinity,
                    xMax = -Infinity,
                    xMin = +Infinity,
                    userMaxColWidth,
                    enableAnimation,
                    mapSymbolName = lib.graphics.mapSymbolName;
                conf.parentYAxis = 0;
                conf.toolText = getValidValue(parseUnsafeString(pluck(JSONData.tooltext, chartAttr.plottooltext)));
                // Dataset seriesname
                conf.name = getValidValue(JSONData.seriesname);
                conf.showTooltip = pluck(chartAttr.showtooltip, 1);
                switch (plotPriceAs) {
                case LINE:
                    conf.plotType = LINE;
                    break;
                case BAR:
                    conf.plotType = BAR;
                    break;
                default:
                    conf.plotType = COLUMN;
                    conf.showErrorValue = true;
                    conf.errorBarWidthPercent = 0;
                    isCandleStick = true;
                    break;
                }
                conf.animation = {
                        duration : 200
                    };
                userMaxColWidth = pluck(chartAttr.maxcolwidth);
                conf.maxColWidth = mathAbs(pluckNumber(
                    userMaxColWidth, 50)) || 1;
                // Animation related attributes configuration
                conf.enableAnimation = enableAnimation = pluckNumber(chartAttr.animation,
                    chartAttr.defaultanimation, 1);
                conf.animation = !enableAnimation ? false : {
                    duration: pluckNumber(chartAttr.animationduration, 1) * 1000
                };
                conf.lineAlpha = pluck(chartAttr.plotlinealpha, HUNDRED);
                plotSpacePercent = mathMax(pluckNumber(chartAttr.plotspacepercent, 20) % 100, 0);
                conf.plotSpacePercent = conf.groupPadding = plotSpacePercent / 200;
                dataStore = dataset.components.data = dataset.components.data || (dataset.components.data = []);
                conf.valuePadding = pluckNumber(JSONData.valuepadding, chartAttr.valuepadding, 2);
                conf.plotBorderThickness = plotLineThickness;
                // Iterate through all level data
                for (index = 0; index < dataLength; index += 1) {
                    // Individual data obj
                    // for further manipulation
                    setData = dataArr[index];
                    dataObj = dataStore[index];
                    if (!dataObj) {
                        dataObj = dataStore[index] = {};
                    }
                    !dataObj.config && (dataObj.config = {});
                    !dataObj.graphics && (dataObj.graphics = {});
                    config = dataObj.config;
                    if (setData && !setData.vline) {
                        config.setLink = pluck(setData.link);
                        open = config.open = numberFormatter.getCleanValue(setData.open);
                        close = config.close = numberFormatter.getCleanValue(setData.close);
                        high = config.high = numberFormatter.getCleanValue(setData.high);
                        low = config.low = numberFormatter.getCleanValue(setData.low);
                        volume = config.volume = numberFormatter.getCleanValue(setData.volume, true);
                        if (volume !== null) {
                            chart.config.drawVolume = true;
                        }
                        x = config.x = numberFormatter.getCleanValue(setData.x);
                        openVal = config.openVal = isCandleStick ? mathAbs(close - open) : open;
                        closeVal = config.closeVal = mathMin(open, close);
                        yVal = config.yVal = mathMax(open, close);
                        isLine = plotPriceAs === LINE ? 1 : 0;
                        minValue = mathMin(open, close, high, low);
                        maxValue = mathMax(open, close, high, low);

                        valueText = parseUnsafeString(getValidValue(setData.valuetext, BLANK));

                        setBorderColor = getFirstColor(pluck(setData.bordercolor, close < open ? bearBorderColor :
                            bullBorderColor));
                        setAlpha = pluck(setData.alpha, isLine ? conf.lineAlpha : HUNDRED);
                        setColor = getFirstColor(pluck(setData.color, close < open ? bearFillColor :
                            bullFillColor));
                        dashStyle = Boolean(pluckNumber(setData.dashed)) ? getDashStyle(plotLineDashLen,
                            plotLineDashGap) : DASH_DEF;
                        config.dashStyle = dashStyle;
                        // Set alpha of the shadow
                        pointShadow = {
                            opacity: setAlpha / 100
                        };
                        config.color =  isCandleStick ? setColor : setBorderColor,
                        config.alpha = setAlpha;
                        /*
                         * Storing the set level color and set level alpha which is required in drawing of line
                         * In line we are checking setColor and setAlpha of current line segment is same as the previous
                         * line segment's setColor and setAlpha by accesing config.setColor and config.setAlpha
                         */
                        config.setColor = config.color;
                        config.setAlpha = config.alpha;
                        config.anchorImageUrl = pluck(setData.anchorimageurl, JSONData.anchorimageurl,
                            chartAttr.anchorimageurl);
                        // Finally add the data
                        // we call getPointStub function that manage displayValue, toolText and link
                        borderColor = config.borderColor = setBorderColor;
                        config.borderAlpha = config.plotLineAlpha;
                        config.colorArr = [{
                            color: config.color,
                            alpha: config.alpha
                        },
                        {
                            color: config.borderColor,
                            alpha: config.borderAlpha
                        }];
                        config.anchorSides = pluckNumber(setData.anchorsides, JSONData.anchorsides,
                            chartAttr.anchorsides);
                        config.symbol = mapSymbolName(config.anchorSides).split(UNDERSCORE);
                        config.anchorProps = {
                            enabled: drawAnchors,
                            bgColor: setAnchorBgColor,
                            symbol: config.symbol,
                            bgAlpha: ((setAnchorBgAlpha * setAnchorAlpha) / 100) + BLANK,
                            borderColor: setAnchorBorderColor,
                            borderAlpha: setAnchorAlpha,
                            anchorAlpha: setAnchorAlpha,
                            borderThickness: setAnchorBorderThickness,
                            imageUrl: config.anchorImageUrl,
                            radius: setAnchorRadius,
                            imageScale: pluckNumber(setData.imagescale, JSONData.imagescale, chartAttr.imagescale, 100),
                            imagePadding: pluckNumber(setData.anchorimagepadding, JSONData.anchorimagepadding,
                                chartAttr.anchorimagepadding, 1),
                            imageAlpha: pluckNumber(JSONData.anchorimagealpha, chartAttr.anchorimagealpha, 100),
                            startAngle: setAnchorAngle
                        };
                        config.showValue = 1;
                        config.hoverEffects = {};
                        switch (conf.plotType) {
                            case LINE:
                                config.y = close;
                                config.link = pluck(setData.link);
                                break;
                            case COLUMN:
                                config.y = mathAbs(close - open);
                                config.previousY = closeVal;
                                config.link = pluck(setData.link);
                                config.errorValue = [];
                                if (high - yVal > 0) {
                                    config.errorValue.push({
                                        errorValue: high - yVal,
                                        errorStartValue: yVal,
                                        errorBarColor: borderColor,
                                        errorBarThickness: plotLineThickness,
                                        opacity: 1
                                    });
                                }
                                if (low - closeVal < 0) {
                                    config.errorValue.push({
                                        errorValue: low - closeVal,
                                        errorStartValue: closeVal,
                                        errorBarColor: borderColor,
                                        errorBarThickness: plotLineThickness,
                                        opacity: 1
                                    });
                                }
                                break;
                            default:
                                config.y = open;
                                config.previousY = close;
                                config.link = pluck(setData.link);
                                break;
                        }
                        config.setValue = config.y;

                        if (minValue !== null) {
                            (!yMax && yMax !== 0) && (yMax = minValue);
                            (!yMin && yMin !== 0) && (yMin = minValue);
                            yMax = mathMax(yMax, minValue);
                            yMin = mathMin(yMin, minValue);
                        }
                        if (maxValue !== null) {
                            (!yMax && yMax !== 0) && (yMax = maxValue);
                            (!yMin && yMin !== 0) && (yMin = maxValue);
                            yMax = mathMax(yMax, maxValue);
                            yMin = mathMin(yMin, maxValue);
                        }
                        if (x !== null) {
                            xMax = mathMax(xMax, x);
                            xMin = mathMin(xMin, x);
                        }

                        toolText = this._parseToolText(index);
                        config.toolText = toolText;
                        config.toolTipValue = BLANKSTRING;
                        x = x ? x : index + 1;
                        config.x = x;

                        displayValue = config.displayValue = parseUnsafeString(pluck(setData.displayvalue,
                                setData.valuetext, BLANK));
                        config.high = mathMax(open, close, high, low);
                        config.low =  mathMin(open, close, high, low);
                        config.shadow = pointShadow;
                    }
                }
                conf.yMax = yMax;
                conf.yMin = yMin;
                conf.xMax = xMax;
                conf.xMin = xMin;

            },
            _parseToolText: function (i) {
                var dataset = this,
                    conf = dataset.config,
                    setDataArr = dataset.JSONData.data,
                    data = dataset.components.data,
                    chart = dataset.chart,
                    xAxis = chart.components.xAxis[0],
                    chartAttr = chart.jsonData.chart,
                    isLine = conf.plotType === LINE ? 1 : 0,
                    toolText,
                    BLANK = BLANKSTRING,
                    setData = setDataArr[i],
                    config = data[i].config,
                    label = xAxis.getLabel(config.x).label,
                    open = config.open,
                    close = config.close,
                    yAxis = dataset.yAxis,
                    high = config.high,
                    low = config.low,
                    volume = config.volume,
                    volumeToolText = volume !== undefined ? setData.volumetooltext : undefined;

                //create the tooltext
                if (!conf.showTooltip) {
                    toolText = BLANK;
                } else {
                    toolText = getValidValue(parseUnsafeString(pluck(volumeToolText,
                        setData.tooltext, conf.volumeToolText, conf.toolText)));

                    if (toolText !== undefined) {
                        toolText = parseTooltext(toolText, [3, 5, 6, 10, 54, 55, 56, 57,
                            58, 59, 60, 61, 81, 82
                        ], {
                            label: label,
                            yaxisName: parseUnsafeString(chartAttr.yaxisname),
                            xaxisName: parseUnsafeString(chartAttr.xaxisname),
                            openValue: setData.open,
                            openDataValue:yAxis.dataLabels(open),
                            closeValue: setData.close,
                            closeDataValue:yAxis.dataLabels(close),
                            highValue: setData.high,
                            highDataValue:yAxis.dataLabels(high),
                            lowValue: setData.low,
                            lowDataValue:yAxis.dataLabels(low),
                            volumeValue: setData.volume,
                            volumeDataValue:yAxis.dataLabels(volume)
                        }, setData, chartAttr);
                    } else {
                        toolText = (open !== null && !isLine) ? BOLDSTARTTAG + 'Open:' + BOLDENDTAG + BLANKSPACE +
                            yAxis.dataLabels(open) +
                            BREAKSTRING : BLANK;
                        toolText += close !== null ? BOLDSTARTTAG + 'Close:' + BOLDENDTAG + BLANKSPACE +
                            yAxis.dataLabels(close) + BREAKSTRING :
                            BLANK;
                        toolText += (high !== null && !isLine) ? BOLDSTARTTAG + 'High:' + BOLDENDTAG + BLANKSPACE +
                            yAxis.dataLabels(high) +
                            BREAKSTRING : BLANK;
                        toolText += (low !== null && !isLine) ? BOLDSTARTTAG + 'Low:' + BOLDENDTAG + BLANKSPACE +
                            yAxis.dataLabels(low) +
                            BREAKSTRING : BLANK;
                        toolText += volume !== null ? BOLDSTARTTAG + 'Volume:' + BOLDENDTAG + BLANKSPACE +
                            yAxis.dataLabels(volume) : BLANK;
                    }
                }
                return toolText;
            },
            // Initialization of dataset of candlestick chart
            init: function (datasetJSON, type) {
                var dataset = this,
                    chart = dataset.chart,
                    yAxis;
                if (type === VOLUME) {
                    yAxis = chart.components.yAxis[1];
                }
                else {
                    yAxis = chart.components.yAxis[0];
                }

                dataset.yAxis = yAxis;
                dataset.components = {

                };

                dataset.graphics = {

                };
                dataset.JSONData = datasetJSON;
                dataset.visible = 1;
                dataset.plotType = type;
                dataset.configure();

            },
            _configureVolume: function () {
                var dataset = this,
                    conf = dataset.config,
                    chart = dataset.chart,
                    chartComponents = chart.components,
                    rawDataObj = chart.jsonData,
                    JSONData = dataset.JSONData,
                    dataArr = JSONData.data || [],
                    chartAttr = rawDataObj.chart,
                    BLANK = BLANKSTRING,
                    dataLength = dataArr.length,
                    colorM = chartComponents.colorManager,
                    valueText,
                    setColor,
                    setBorderColor,
                    setAlpha,
                    dashStyle,
                    pointShadow,
                    index,
                    dataObj,
                    toolText,
                    open,
                    close,
                    high,
                    low,
                    volume,
                    x,
                    closeVal,
                    borderColor,
                    numberFormatterAttrs,
                    //Candle stick properties.
                    //Bear fill and border color - (Close lower than open)
                    bearBorderColor = conf.bearBorderColor =
                        getFirstColor(pluck(chartAttr.bearbordercolor, COLOR_B90000)),
                    bearFillColor = conf.bearFillColor =
                        getFirstColor(pluck(chartAttr.bearfillcolor, COLOR_B90000)),
                    //Bull fill and border color - Close higher than open
                    bullBorderColor = conf.bullBorderColor =
                        getFirstColor(pluck(chartAttr.bullbordercolor,
                        colorM.getColor('canvasBorderColor'))),
                    bullFillColor = conf.bullFillColor =
                    getFirstColor(pluck(chartAttr.bullfillcolor,
                        COLOR_FFFFFF)),
                    showVPlotBorder = pluckNumber(chartAttr.showvplotborder, 1),
                    //VPlotBorder is border properties for the volume chart.
                    vPlotBorderThickness = showVPlotBorder ? pluckNumber(chartAttr.vplotborderthickness, 1) : 0,
                    plotLineDashLen = conf.plotLineDashLen = pluckNumber(chartAttr.plotlinedashlen, 5),
                    plotLineDashGap = conf.plotLineDashGap = pluckNumber(chartAttr.plotlinedashgap, 4),
                    openVal,
                    dataStore,
                    setData,
                    config,
                    enableAnimation,
                    isCandleStick = true,
                    plotSpacePercent,
                    yAxis = dataset.yAxis,
                    yMax = -Infinity,
                    yMin = +Infinity,
                    xMax = -Infinity,
                    xMin = +Infinity,
                    userMaxColWidth,
                    vNumberFormatter = chart.components.vNumberFormatter;
                conf.plotType = COLUMN;
                conf.parentYAxis = 1;
                conf.volumeToolText = getValidValue(parseUnsafeString(pluck(JSONData.volumetooltext,
                    chartAttr.volumetooltext, chartAttr.plottooltext)));
                // Dataset seriesname
                conf.name = getValidValue(JSONData.seriesname);
                conf.showTooltip = pluck(chartAttr.showtooltip, 1);
                // Animation related attributes configuration
                conf.enableAnimation = enableAnimation = pluckNumber(chartAttr.animation,
                    chartAttr.defaultanimation, 1);
                conf.animation = !enableAnimation ? false : {
                    duration: pluckNumber(chartAttr.animationduration, 1) * 1000
                };
                userMaxColWidth = pluck(chartAttr.maxcolwidth);
                conf.maxColWidth = mathAbs(pluckNumber(
                    userMaxColWidth, 50)) || 1;
                plotSpacePercent = mathMax(pluckNumber(chartAttr.plotspacepercent, 20) % 100, 0);
                conf.plotSpacePercent = conf.groupPadding = plotSpacePercent / 200;
                conf.plotBorderThickness = vPlotBorderThickness;
                dataStore = dataset.components.data = dataset.components.data || (dataset.components.data = []);
                numberFormatterAttrs = extend2(extend2({}, chartAttr), {
                    forcedecimals: getFirstValue(chartAttr.forcevdecimals,
                        chartAttr.forcedecimals),
                    forceyaxisvaluedecimals: getFirstValue(
                        chartAttr.forcevyaxisvaluedecimals,
                        chartAttr.forceyaxisvaluedecimals),
                    yaxisvaluedecimals: getFirstValue(
                        chartAttr.vyaxisvaluedecimals,
                        chartAttr.yaxisvaluedecimals),
                    formatnumber: getFirstValue(chartAttr.vformatnumber,
                        chartAttr.formatnumber),
                    formatnumberscale: getFirstValue(
                        chartAttr.vformatnumberscale,
                        chartAttr.formatnumberscale),
                    defaultnumberscale: getFirstValue(
                        chartAttr.vdefaultnumberscale,
                        chartAttr.defaultnumberscale),
                    numberscaleunit: getFirstValue(
                        chartAttr.vnumberscaleunit, chartAttr.numberscaleunit),
                    vnumberscalevalue: getFirstValue(
                        chartAttr.vnumberscalevalue,
                        chartAttr.numberscalevalue),
                    scalerecursively: getFirstValue(
                        chartAttr.vscalerecursively,
                        chartAttr.scalerecursively),
                    maxscalerecursion: getFirstValue(
                        chartAttr.vmaxscalerecursion,
                        chartAttr.maxscalerecursion),
                    scaleseparator: getFirstValue(chartAttr.vscaleseparator,
                        chartAttr.scaleseparator),
                    numberprefix: getFirstValue(chartAttr.vnumberprefix,
                        chartAttr.numberprefix),
                    numbersuffix: getFirstValue(chartAttr.vnumbersuffix,
                        chartAttr.numbersuffix),
                    decimals: getFirstValue(chartAttr.vdecimals,
                        chartAttr.decimals)
                });
                if (!vNumberFormatter) {
                    vNumberFormatter = chart.components.vNumberFormatter = new lib.NumberFormatter(chart,
                        numberFormatterAttrs);
                }
                else {
                    vNumberFormatter.configure(numberFormatterAttrs);
                }



                yAxis.setNumberFormatter(vNumberFormatter);
                // Iterate through all level data
                for (index = 0; index < dataLength; index += 1) {
                    // Individual data obj
                    // for further manipulation
                    setData = dataArr[index];
                    dataObj = dataStore[index];
                    if (!dataObj) {
                        dataObj = dataStore[index] = {};
                    }
                    !dataObj.config && (dataObj.config = {});
                    !dataObj.graphics && (dataObj.graphics = {});
                    config = dataObj.config;
                    if (setData && !setData.vline) {
                        open = config.open = yAxis.getCleanValue(setData.open);
                        close = config.close = yAxis.getCleanValue(setData.close);
                        high = config.high = yAxis.getCleanValue(setData.high);
                        low = config.low = yAxis.getCleanValue(setData.low);
                        volume = config.volume = yAxis.getCleanValue(setData.volume, true);
                        x = config.x = yAxis.getCleanValue(setData.x);
                        openVal = config.openVal = isCandleStick ? mathAbs(close - open) : open;
                        closeVal = config.closeVal = mathMin(open, close);

                        yMax = mathMax(yMax, volume);
                        yMin = mathMin(yMin, volume);
                        xMax = mathMax(xMax, x);
                        xMin = mathMin(xMin, x);
                        valueText = parseUnsafeString(getValidValue(setData.valuetext, BLANK));

                        setBorderColor = getFirstColor(pluck(setData.bordercolor, close < open ? bearBorderColor :
                            bullBorderColor));
                        setAlpha = pluck(setData.alpha, HUNDRED);
                        setColor = getFirstColor(pluck(setData.color, close < open ? bearFillColor :
                            bullFillColor));
                        dashStyle = config.dashStyle = Boolean(pluckNumber(setData.dashed)) ?
                            getDashStyle(plotLineDashLen, plotLineDashGap) : DASH_DEF;
                        // Set alpha of the shadow
                        pointShadow = {
                            opacity: setAlpha / 100
                        };
                        config.color =  isCandleStick ? setColor : setBorderColor,
                        config.alpha = setAlpha;
                        config.setLink = setData.link;
                        config.borderWidth = vPlotBorderThickness;
                        borderColor = config.borderColor = setBorderColor;
                        config.borderAlpha = pluck(config.plotLineAlpha, setAlpha);
                        config.y = volume;
                        config.colorArr = [{
                            color: config.color,
                            alpha: config.alpha
                        },
                        {
                            color: config.borderColor,
                            alpha: config.borderAlpha
                        }];
                        config.setValue = config.y;

                        //create the tooltext
                        toolText = this._parseToolText(index);
                        config.toolText = toolText;
                        config.toolTipValue = BLANKSTRING;
                        x = x ? x : index + 1;
                        config.x = x;
                        config.shadow = pointShadow;
                    }
                }
                conf.yMax = yMax;
                conf.yMin = yMin;
                conf.xMax = xMax;
                conf.xMin = xMin;

            },
            draw: function () {
                var dataset = this,
                    conf = dataset.config,
                    plotType = conf.plotType,
                    sortedData = dataset.JSONData && dataset.JSONData.data.slice();
                sortedData.sort(function (a, b) {
                    return a.x - b.x;
                });
                dataset.JSONData.sortedData = sortedData;
                if (plotType === LINE) {
                    this.__base__.draw.call(dataset);
                }
                else if (plotType === COLUMN) {
                    this._drawColumn();
                    if (conf.showErrorValue) {
                        this._drawErrorValue();
                    }
                }
                else {
                    this._drawCandlestickBar();
                }

                dataset.drawn = true;
            },
            _drawColumn: function () {
                var dataSet = this,
                    JSONData = dataSet.JSONData,
                    chart = dataSet.chart,
                    jobList = chart.getJobList(),
                    chartAttr = dataSet.chart.jsonData.chart,
                    conf = dataSet.config,
                    datasetIndex = dataSet.index,
                    setDataArr = JSONData.data,
                    dataSetLen = setDataArr && setDataArr.length,
                    len,
                    setData,
                    attr,
                    i,
                    visible = dataSet.visible,
                    paper = chart.components.paper,
                    xAxis = chart.components.xAxis[0],
                    yAxis = dataSet.yAxis,
                    xPos,
                    yPos,
                    crispBox,
                    layers = chart.graphics,
                    parseUnsafeString = lib.parseUnsafeString,
                    getValidValue = lib.getValidValue,
                    R = lib.Raphael,
                    trackerConfig,
                    showTooltip = conf.showTooltip,
                    animObj = chart.get(configStr, animationObjStr),
                    animationDuration = animObj.duration,
                    dummyAnimElem = animObj.dummyObj,
                    dummyAnimObj = animObj.animObj,
                    groupMaxWidth = xAxis.getPVR(),
                    definedGroupPadding = conf.definedGroupPadding,
                    plotSpacePercent = conf.plotSpacePercent,
                    plotPaddingPercent  = conf.plotPaddingPercent,
                    groupPadding = plotSpacePercent,
                    numOfColumns = 1,
                    columnPosition = 0,
                    maxColWidth = conf.maxColWidth,
                    overlapColumns = 0,
                    // Calculating the net width occupied by bars for each category
                    groupNetWidth = (1 - definedGroupPadding * 0.01) * groupMaxWidth || mathMin(
                        groupMaxWidth * (1 - groupPadding * 2),
                        maxColWidth * numOfColumns
                    ),
                    groupNetHalfWidth = groupNetWidth / 2,
                    columnWidth = groupNetWidth / numOfColumns,
                    plotPadding = numOfColumns > 1 ? !overlapColumns && plotPaddingPercent === UNDEFINED ?
                        4 :
                        plotPaddingPercent > 0 ? (columnWidth * plotPaddingPercent / 100) : 0 : 0,
                    plotEffectivePadding = mathMin(columnWidth - 1, plotPadding),
                    xPosOffset = (columnPosition * columnWidth) - groupNetHalfWidth + plotEffectivePadding / 2,
                    height,
                    toolText,
                    dataStore = dataSet.components.data,
                    dataObj,
                    setTooltext,
                    setElement,
                    setLink,
                    setValue,
                    eventArgs,
                    displayValue,
                    groupId,
                    x,
                    config,
                    isPositive,
                    yBase = yAxis.getAxisBase(),
                    yBasePos = yAxis.yBasePos = yAxis.getAxisPosition(yBase),
                    previousY,
                    previousYPos,
                    heightBase = 0,
                    plotBorderThickness = conf.plotBorderThickness,
                    plotRadius = conf.plotRadius || 0,
                    container = dataSet.graphics.container,
                    shadowContainer = dataSet.graphics.shadowContainer,
                    colorArr,
                    plotBorderDashStyle,
                    isCrisp = true,
                    width,
                    borderWidth,
                    shadow,
                    isNewElem,
                    animFlag = !chart.config.plotAnimDone,
                    removeDataArr = dataSet.components.removeDataArr || [],
                    removeDataArrLen = removeDataArr.length,
                    Column = FusionCharts.get(COMPONENT, [DATASET, COLUMN]),
                    drawLabel = Column.prototype.drawLabel,
                    initAnimCallBack = function () {
                        var graphics = dataSet.graphics,
                            errorGroupContainer = graphics.errorGroupContainer;
                        errorGroupContainer && errorGroupContainer.show();
                    },
                    datasetLayer = layers.datasetGroup,
                    pool = dataSet.components.pool || [],
                    components = chart.components,
                    canvas = components.canvas,
                    canvasConfig =  canvas.config,
                    volumeCanvas = components.canvasVolume,
                    vCanvasConfig = volumeCanvas.config,
                    rollOverBandColor = chart.config.rollOverBandColor,
                    rollOverBandPath,
                    rollOverBand,
                    sortedData;
                    // clickFunc = function (setDataArr) {
                    //     var ele = this;
                    //     plotEventHandler.call(ele, chart, setDataArr);
                    // };
                /*
                 * Creating a container group for the graphic element of column plots if
                 * not present and attaching it to its parent group.
                 */
                if (!container) {
                    container = dataSet.graphics.container = paper.group(columnStr, datasetLayer);
                    if (!visible) {
                        container.hide();
                    }
                }


                //chart.addCSSDefinition('.fusioncharts-datalabels .fusioncharts-label', labelCSS);

                /*
                 * Creating the shadow element container group for each plots if not present
                 * and attaching it its parent group.
                 */
                if (!shadowContainer) {
                    // Always sending the shadow group to the back of the plots group.
                    shadowContainer = dataSet.graphics.shadowContainer =
                        paper.group(shadowStr, datasetLayer).toBack();
                    if (!visible) {
                        shadowContainer.hide();
                    }

                }

                if (!rollOverBand) {
                    rollOverBandPath = [M, 0, canvasConfig.canvasTop, L, 0, canvasConfig.canvasBottom, M, 0,
                        vCanvasConfig.canvasTop - vCanvasConfig.canvasBorderWidth,
                            L, 0, vCanvasConfig.canvasTop + vCanvasConfig.canvasHeight +
                            vCanvasConfig.canvasBorderWidth / 2];

                    if (!rollOverBand) {
                        rollOverBand = chart.graphics.rollOverBand = paper.path(datasetLayer);
                    }
                    rollOverBand.transform(BLANKSTRING);
                    rollOverBand.attr({
                        path: rollOverBandPath,
                        'stroke-width': columnWidth,
                        ishot: true,
                        stroke: rollOverBandColor,
                        'stroke-linecap': 'butt'
                    });
                    rollOverBand.data('width', columnWidth);
                    rollOverBand.toBack();
                    rollOverBand.hide();
                }

                len = dataSetLen;
                width = columnWidth;
                conf.columnWidth = columnWidth;
                // Create plot elements.
                for (i = 0; i < len; i++) {
                    setData = setDataArr[i];
                    dataObj = dataStore[i];
                    setData.originalIndex = i;
                    config = dataObj && dataObj.config;
                    setLink = config.setLink;
                    setValue = config.y;
                    x = pluckNumber(config.x, i);
                    borderWidth = config.borderWidth;
                    colorArr = config.colorArr;
                    shadow = config.shadow;
                    isPositive = setValue >= 0;
                    // Skipping the remaining calculations if data entered by the user is null for a plot.
                    if (setValue === null) {
                        continue;
                    }
                    setLink  = config.setLink;

                    // Creating the data structure if not present for storing the graphics elements.
                    if (!dataObj.graphics) {
                        dataStore[i].graphics = {};

                    }
                    groupId = dataSet.index + UNDERSCORE + i;
                    config.groupId = groupId;
                    displayValue = config.displayValue;

                    setTooltext = getValidValue(parseUnsafeString(pluck(setData.tooltext,
                            JSONData.plottooltext, chartAttr.plottooltext)));
                    previousY = config.previousY;
                    // Getting the previous yposition of the plot and calculating the current yposition of the plot.
                    previousYPos = yAxis.getAxisPosition(previousY || yBase);
                    yPos = yAxis.getAxisPosition(setValue + (previousY || 0));
                    xPos = xAxis.getAxisPosition(x) + xPosOffset;
                    height = mathAbs(yPos - previousYPos);
                    // crisp column
                    crispBox = R.crispBound(xPos, yPos, width, height,
                        plotBorderThickness);
                    if (isCrisp) {
                        xPos = crispBox.x;
                        yPos = crispBox.y;
                        width = crispBox.width;
                        height = crispBox.height || 1;
                    }

                    // Setting the final tooltext.
                    toolText = config.toolText;
                    plotBorderDashStyle = config.dashStyle;
                    dataObj.trackerConfig = {};
                    trackerConfig = dataObj.trackerConfig;
                    eventArgs = trackerConfig.eventArgs = trackerConfig.eventArgs || {};

                    // Setting the event arguments.
                    eventArgs.index = i;
                    eventArgs.link = setLink;
                    eventArgs.value = setValue;
                    eventArgs.displayValue = displayValue;
                    eventArgs.categoryLabel = xAxis.getLabel(i).label;
                    eventArgs.toolText = toolText;
                    eventArgs.id = BLANKSTRING;
                    eventArgs.datasetIndex = datasetIndex;
                    eventArgs.datasetName = JSONData.seriesname;
                    eventArgs.visible = visible;
                    // eventArgs = {
                    //     index: i,
                    //     link: setLink,
                    //     value: setValue,
                    //     displayValue: displayValue,
                    //     categoryLabel: xAxis.getLabel(i).label,
                    //     toolText: toolText,
                    //     id: BLANKSTRING,
                    //     datasetIndex: datasetIndex,
                    //     datasetName: JSONData.seriesname,
                    //     visible: visible
                    // };

                    //todo- remove _ to make it public
                    dataObj._xPos = xPos;
                    dataObj._yPos = yPos;
                    dataObj._height = height;
                    dataObj._width = columnWidth;
                    setElement = dataObj.graphics.element;
                    isNewElem = false;
                    /*
                     * If the data plots are not present then they are created, else only attributes are set for the
                     * existing plots.
                     */
                    if (!setElement) {
                        if (pool.element && pool.element.length) {
                            setElement = dataObj.graphics.element = pool.element.shift();
                        }
                        else {
                            setElement = dataObj.graphics.element = paper.rect(container);
                            isNewElem = true;
                            if (animationDuration) {
                                setElement.attr({
                                    x: xPos,
                                    y: yBasePos,
                                    width: width,
                                    height: heightBase
                                });
                            }
                        }
                    }

                    attr = config._elemPositions;

                    if (!attr) {
                        attr = config._elemPositions = {};
                    }

                    attr.x = xPos;
                    attr.y = yPos;
                    attr.width = width;
                    attr.height = height;

                    // Animate column plot for candlestick chart
                    setElement.show().animateWith(dummyAnimElem, dummyAnimObj, attr,
                        animationDuration, animObj.animType, animFlag && initAnimCallBack);

                    attr = config._elemCosmetics;

                    if (!attr) {
                        attr = config._elemCosmetics = {};
                    }

                    attr.r = plotRadius;
                    attr.ishot = !showTooltip;
                    attr.fill = toRaphaelColor(colorArr[0]);
                    attr.stroke = toRaphaelColor(colorArr[1]);
                    attr['stroke-width'] = plotBorderThickness;
                    attr['stroke-dasharray'] = plotBorderDashStyle;
                    attr['stroke-linejoin'] = miterStr;
                    attr.visibility = visible;
                    attr.cursor = setLink ? POINTER : DEFAULT;

                    setElement.attr(attr).shadow(config.shadow, shadowContainer).data('dataObj', dataObj);

                    chart.config.plotAnimDone = true;

                    // If algorithmic mouseTracking is enabled then attach these data to setElement
                    // because tracker element will not be drawn
                    chart.config.enablemousetracking && setElement
                        .data(EVENTARGS, eventArgs)
                        .data(showHoverEffectStr, true/*showHoverEffect*/)
                        .data(SETROLLOVERATTR, config.setRolloverAttr || {})
                        .data(SETROLLOUTATTR, config.setRolloutAttr || {});
                }

                dataSet.drawn ? drawLabel.call(dataSet, 0, dataStore.length) :
                    jobList.labelDrawID.push(schedular.addJob(drawLabel, dataSet, [0, dataStore.length],
                    lib.priorityList.label));
                // dataSet.drawTracker();
                // drawLabel.call(dataSet, 0, dataStore.length);
                for (i = 0; i < removeDataArrLen; i++) {
                    dataObj = removeDataArr[0];
                    if (!dataObj) {
                        continue;
                    }
                    dataSet._removeDataVisuals(dataObj.graphics);
                    removeDataArr.shift();
                }
                dataSet.drawn = true;

                sortedData = dataSet.JSONData.data;
                for (i = sortedData.length;i--;) {
                    dataSet.JSONData.data[i].originalIndex = i;
                }
                chart.config.toleranceBottom = canvasConfig.intermediarySpace +
                    (chart.config.canvasBorderWidth * 2);
            },

            _getHoveredPlot: function (chartX, chartY) {
                var dataset = this,
                    conf = dataset.config,
                    plotType = conf.plotType;
                if (plotType === LINE) {
                    return dataset._getHoveredPlotCandleLine(chartX, chartY);
                }
                else if (plotType === COLUMN) {
                    return dataset._getHoveredPlotCandleColumn(chartX, chartY);
                }
            },

            _getHoveredPlotCandleLine: function (chartX, chartY) {
                var dataset = this,
                    chart = dataset.chart,
                    chartConfig = chart.config,
                    canvas = chart.components.canvas,
                    canvasConf = canvas.config,
                    xAxis = chart.components.xAxis[0],
                    dataStore = dataset.components.data,
                    pointObj,
                    xMin,
                    xMax,
                    len = dataStore.length,
                    returnValue,
                    conf = dataset.config,
                    canvasLeft = chartConfig.canvasLeft,
                    canvasPaddingLeft = canvasConf.canvasPaddingLeft,
                    canvasPadding = canvasConf.canvasPadding,
                    axisX = chartX - canvasLeft - Math.max(canvasPaddingLeft, canvasPadding),
                    i,
                    maxRadius = conf && conf.radius || 0;

                xMin = Math.floor(Math.max(xAxis.getValue(axisX - maxRadius), 0));
                xMin = dataset.getPlotIndices(xMin);

                xMax = Math.ceil(Math.min(xAxis.getValue(axisX + maxRadius), len - 1));
                xMax = dataset.getPlotIndices(xMax);

                for (i = xMin.length; i--;) {
                    pointObj = dataStore[xMin[i].originalIndex];
                    if (pointObj) {
                        returnValue = dataset.isWithinShape(pointObj, xMin[i].originalIndex, chartX, chartY);
                        if (returnValue) {
                            return returnValue;
                        }
                    }
                }

                for (i = xMax.length; i--;) {
                    pointObj = dataStore[xMax[i].originalIndex];
                    if (pointObj) {
                        returnValue = dataset.isWithinShape(pointObj, xMax[i].originalIndex, chartX, chartY);
                        if (returnValue) {
                            return returnValue;
                        }
                    }
                }
            },

            _getHoveredPlotCandleColumn: function (chartX, chartY) {
                var dataset = this,
                    chart = dataset.chart,
                    chartConfig = chart.config,
                    xAxis = chart.components.xAxis[0],
                    x,
                    canvas = chart.components.canvas,
                    canvasConfig = canvas.config,
                    canvasPadding = Math.max(canvasConfig.canvasPaddingLeft, canvasConfig.canvasPadding),
                    canvasLeft = chartConfig.canvasLeft,
                    pX,
                    i,
                    returnValue;

                x = xAxis.getValue(chartX - canvasLeft - canvasPadding);
                pX = dataset.getPlotIndices(x);

                // Checking for overlap between two cosecutive column plots along x-axis
                for (i = pX.length; i--;) {
                    if (dataset._checkPointerOverErrorBar(pX[i].originalIndex, chartX, chartY)) {
                        returnValue = dataset._checkPointerOverErrorBar(pX[i].originalIndex, chartX, chartY);
                    }
                    if (dataset._checkPointerOverColumn(pX[i].originalIndex, chartX, chartY)) {
                        returnValue = dataset._checkPointerOverColumn(pX[i].originalIndex, chartX, chartY);
                    }
                }
                return returnValue;
            },

            getPlotIndices: function (x) {
                var dataset = this,
                    i,
                    minX = Math.floor(x),
                    maxX = Math.ceil(x),
                    data,
                    returnIndices = [],
                    sortedData = dataset.JSONData && dataset.JSONData.sortedData;

                for (i = sortedData.length; i--;) {
                    data = dataset.JSONData.sortedData[i];
                    if (data.x >= minX && data.x <= maxX) {
                        returnIndices.push(data);
                    }
                }
                return returnIndices;
            },

            // Helper function of _checkPointerOverPlot().
            _checkPointerOverErrorBar : function (pX, chartX, chartY) {
                var dataset = this,
                    dataStore = dataset.components.data,
                    pointObj = dataStore[pX],
                    hovered,
                    errorBarArr,
                    errorBarCompArr,
                    len,
                    errorBarCompLen,
                    xPos,
                    yPos,
                    height,
                    width;

                if (!pointObj) {
                    return;
                }

                errorBarArr = pointObj.errorBar;

                if (!errorBarArr) {
                    return;
                }

                len = errorBarArr && errorBarArr.length;
                while (len--) {
                    errorBarCompArr = errorBarArr[len];
                    errorBarCompLen = errorBarCompArr && errorBarCompArr.length;
                    while (errorBarCompLen--) {
                        if (!(errorBarCompArr[errorBarCompLen] && errorBarCompArr[errorBarCompLen]._xPos)) {
                            continue;
                        }
                        xPos = errorBarCompArr[errorBarCompLen]._xPos;
                        yPos = errorBarCompArr[errorBarCompLen]._yPos;
                        height = errorBarCompArr[errorBarCompLen]._height;
                        width = errorBarCompArr[errorBarCompLen]._width;

                        hovered = chartX >= xPos && chartX <= xPos + width &&
                            chartY >= yPos && chartY <= yPos + height;

                        if (hovered) {
                            return {
                                pointIndex: pX,
                                hovered: hovered,
                                pointObj: dataStore[pX]
                            };
                        }

                    }
                }
            },


            _checkPointerOverColumn : function (pX, chartX, chartY) {
                var dataset = this,
                    chart = dataset.chart,
                    chartConfig = chart.config,
                    plotBorderThickness = chartConfig.plotborderthickness,
                    showPlotBorder = chartConfig.showplotborder,
                    dataStore = dataset.components.data,
                    pointObj = dataStore[pX],
                    pY,
                    dx,
                    dy,
                    hovered,
                    halfPlotBorderThickness,
                    viewPortConfig = chartConfig.viewPortConfig,
                    x = viewPortConfig.x,
                    scaleX = viewPortConfig.scaleX,
                    dragTolerance = chartConfig.dragTolerance || 0;

                if (!pointObj) {
                    return;
                }

                pY = pointObj.config.setValue;

                plotBorderThickness = showPlotBorder ? plotBorderThickness : 0;
                halfPlotBorderThickness = plotBorderThickness / 2;

                halfPlotBorderThickness = halfPlotBorderThickness % 2 === 0 ? halfPlotBorderThickness + 1    :
                    Math.round(halfPlotBorderThickness);

                if (pY !== null) {

                    dx = chartX - (pointObj._xPos - x * scaleX) + halfPlotBorderThickness;
                    dy = chartY - pointObj._yPos + halfPlotBorderThickness + (pY > 0 ? dragTolerance : 0);

                    hovered = dx >= 0 && dx <= pointObj._width + plotBorderThickness && dy >= 0 &&
                        dy <= pointObj._height + plotBorderThickness + (pY > 0 ? 0 : dragTolerance);

                    //hovered && console.log(dy, pointObj._height + plotBorderThickness + dragTolerance)


                    if (hovered) {
                        return {
                            pointIndex: pX,
                            hovered: hovered,
                            pointObj: dataStore[pX]
                        };
                    }
                }
            },

            _firePlotEvent: function (eventType, plotIndex, e) {
                var dataset = this,
                    conf = dataset.config,
                    plotType = conf.plotType;
                if (plotType === LINE) {
                    return dataset.__base__._firePlotEvent.call(dataset, eventType, plotIndex, e);
                }
                else if (plotType === COLUMN) {
                    return FusionCharts.get('component',['dataset', 'column'])
                        .prototype._firePlotEvent.call(dataset, eventType, plotIndex, e);
                }
            },

            _rolloverResponseSetter: function (chart, setElement, event) {
                var dataset = this,
                    sharedAnchor = dataset.graphics.sharedAnchor,
                    elements = chart.graphics,
                    dataObj = setElement,//setElement.data && setElement.data('dataObj'),
                    xPos = dataObj._xPos,
                    rollOverBand = elements.rollOverBand,
                    width = dataObj._width || 0,
                    elem = setElement.graphics.element || sharedAnchor.element;

                rollOverBand.transform(t + (xPos + width / 2) + COMMA + 0)
                    .show();
                plotEventHandler.call(elem, chart, event, ROLLOVER);
            },
            _rolloutResponseSetter: function (chart, setElement, event) {
                var dataset = this,
                    sharedAnchor = dataset.graphics.sharedAnchor,
                    elements = chart.graphics,
                    rollOverBand = elements.rollOverBand,
                    elem = setElement.graphics.element || sharedAnchor.element;
                rollOverBand.hide();
                plotEventHandler.call(elem, chart, event, ROLLOUT);
            },

            _removeDataVisuals : function (graphics) {
                var dataSet = this,
                    pool = dataSet.components.pool || (dataSet.components.pool = {}),
                    elementPool,
                    ele,
                    graphicsObj,
                    j,
                    len;
                if (graphics.graphics) {
                    graphics = graphics.graphics;
                }
                for (ele in graphics) {
                    elementPool = pool[ele] || (pool[ele] = []);
                    graphicsObj = graphics[ele];
                    if (graphicsObj instanceof Array) {
                        for (j = 0, len = graphicsObj.length; j < len; j++) {
                            dataSet._removeDataVisuals(graphicsObj[j]);
                        }
                    }
                    else {
                        if (graphicsObj.hide && typeof graphicsObj.hide === 'function') {
                            graphicsObj.hide();
                        }
                    }
                    elementPool.push(graphics[ele]);

                }

            },
            // Function for drawing candlestick bars
            _drawCandlestickBar: function () {
                var dataset = this,
                    chart = dataset.chart,
                    chartComponents = chart.components,
                    config,
                    conf = dataset.config,
                    components = dataset.components,
                    data = components.data,
                    length = data.length,
                    xAxis = chartComponents.xAxis[0],
                    yAxis = dataset.yAxis,
                    layers = chart.graphics,
                    paper = chartComponents.paper,
                    numColumns = conf.numColumns || 1,
                    columnPosition = conf.columnPosition || 0,
                    groupMaxWidth = xAxis.getPVR(),
                    definedGroupPadding = conf.plotspacepercent,
                    groupPadding = conf.groupPadding,
                    maxColWidth = conf.maxColWidth,
                    groupNetWidth = (1 - definedGroupPadding * 0.01) * groupMaxWidth ||
                        mathMin(
                            groupMaxWidth * (1 - groupPadding * 2),
                            maxColWidth * numColumns
                    ),
                    groupNetHalfWidth = groupNetWidth / 2,
                    columnWidth = groupNetWidth / numColumns,
                    xPosOffset = (columnPosition * columnWidth) - groupNetHalfWidth,

                    datasetLayer = layers.datasetGroup,
                    i,
                    set,
                    setLink,
                    x,
                    y,
                    previousY,
                    xPos,
                    yPos,
                    previousYPos,
                    height,
                    width,
                    animationObj = chart.get(configStr, animationObjStr) || {},
                    animationDuration = animationObj.duration,
                    dummyAnimElem = animationObj.dummyObj,
                    dummyAnimObj = animationObj.animObj,
                    group = datasetLayer,
                    container = dataset.graphics.container,
                    // marimekko variables
                    fixedWidth,
                    setElem,
                    hotElem,
                    pool  = dataset.components.pool || {},
                    visible = dataset.visible,
                    targetGroup,
                    highPos,
                    lowPos,
                    halfW,
                    path,
                    removeDataArr = dataset.components.removeDataArr || [],
                    removeDataArrLen = removeDataArr.lengt ,
                    graphics;
                if (!container) {
                    container = dataset.graphics.container = paper.group(columnStr, group);
                    if (!visible) {
                        container.hide();
                    }
                }

                targetGroup = container;

                //draw plots
                for (i = 0; i < length; i += 1) {
                    set = data[i];
                    config = set.config;
                    graphics = set.graphics;
                    y = config.y;
                    setElem = hotElem = null;

                    if (y === null) {
                        setElem = graphics.element;
                    }
                    // when valid value
                    else {
                        x = pluckNumber(config.x, i);
                        setLink = config.link;
                        config.setLink = config.link;
                        fixedWidth = config._FCW * groupMaxWidth;

                        xPos = xAxis.getAxisPosition(x);
                        previousY = config.previousY;
                        previousYPos = yAxis.getAxisPosition(previousY);
                        yPos = yAxis.getAxisPosition(y);
                        highPos = yAxis.getAxisPosition(config.high);
                        lowPos = yAxis.getAxisPosition(config.low);

                        height = mathAbs(yPos - previousYPos);
                        width = fixedWidth || columnWidth;

                        halfW = yPos < previousYPos ? xPosOffset : xPosOffset;

                        path = [M, xPos, lowPos, L, xPos, highPos,
                            M, xPos, yPos, L, (xPos + halfW), yPos,
                            M, xPos, previousYPos, L, (xPos - halfW), previousYPos
                        ];
                        setElem = graphics.element;
                        if (!setElem) {
                            if (pool.element && pool.element.length) {
                                graphics.element = paper.path(group);
                            }
                            else {
                                setElem = graphics.element = paper.path(path, container);
                            }
                        }

                        // Animate candlestick bar element
                        setElem.show().animateWith(dummyAnimElem, dummyAnimObj, {
                            path: path
                        }, animationDuration, animationObj.animType);

                        chart.config.plotAnimDone = true;

                        setElem.attr({
                            fill: toRaphaelColor(config.color),
                            stroke: toRaphaelColor(config.borderColor),
                            'stroke-width': conf.linethickness,
                            'stroke-dasharray': config.dashStyle,
                            'stroke-linecap': ROUND,
                            'stroke-linejoin': ROUND,
                            'shape-rendering': 'crisp',
                            'cursor': setLink ? POINTER : BLANKSTRING,
                            'visibility': visibleStr
                        })
                        .shadow(config.shadow);
                    }
                }
                for (i = 0; i < removeDataArrLen; i++) {
                    dataset._removeDataVisuals(removeDataArr.shift());
                }
            },
            _drawErrorValue: function () {
                var dataSet = this,
                    JSONData = dataSet.JSONData,
                    trackerTolerance = 2,
                    conf = dataSet.config,
                    setDataArr = JSONData.data,
                    dataSetLen = setDataArr && setDataArr.length,
                    len,
                    setData,
                    i,
                    visible = dataSet.visible,
                    chart = dataSet.chart,
                    paper = chart.components.paper,
                    //elements = chart.elements,
                    yAxis = chart.components.yAxis[0],
                    dataStore = dataSet.components.data,
                    errorBarThickness,
                    errorBarWidthPercent = conf.errorBarWidthPercent,
                    errorBarColor,
                    layers = chart.graphics,
                    datasetLayer = layers.datasetGroup,
                    showTooltip = conf.showTooltip,
                    errorGroupContainer = dataSet.graphics.errorGroupContainer,
                    errorTrackerContainer = dataSet.graphics.errorTrackerContainer,
                    trackerLayer = layers.trackerGroup,
                    setLink,
                    xPos,
                    yPos,
                    //chartLogic = chart.logic,
                    useCrispErrorPath = 1,
                    dataObj,
                    setValue,
                    config,
                    crispY,
                    crispX,
                    errorPath,
                    errorValPos,
                    errorValuePosFactor,
                    animationObj = chart.get(configStr, animationObjStr),
                    animationDuration = animationObj.duration,
                    dummyAnimElem = animationObj.dummyObj,
                    dummyAnimObj = animationObj.animObj,
                    errorValueArr,
                    errorValueObj,
                    errorValue,
                    errorStartPos,
                    errorLen,
                    errorStartValue,
                    errorBarWidth,
                    halfErrorBarW,
                    errorLineElem,
                    errorTrackerElem,
                    isNegative,
                    barXpos,
                    y,
                    barYpos,
                    barWidth,
                    drawn = dataSet.drawn,
                    toolText,
                    errorGraphics,
                    isNewElem,
                    // errorElemClick = function(e) {
                    //     var ele = this;
                    //     plotEventHandler.call(ele, chart, e);
                    // },
                    // getErrLinkClickFN = function(link) {
                    //     return function() {
                    //         (link !== undefined) &&
                    //             linkedItems.linkClickFN.call({
                    //                 link: link
                    //             }, chart);
                    //     };
                    // },
                    pool = dataSet.components.pool || [],
                    errorElements,
                    errorElemLen,
                    removeErrorElem,
                    groupId,
                    graphicEle,
                    ii,
                    barHeight;

                if (!errorGroupContainer) {
                    errorGroupContainer = dataSet.graphics.errorGroupContainer =
                     paper.group(errorBarStr, datasetLayer);
                    if (!visible) {
                        errorGroupContainer.hide();
                    }
                }

                if (!errorTrackerContainer) {
                    errorTrackerContainer = dataSet.graphics.errorTrackerContainer =
                     paper.group(errorHotStr, trackerLayer).toBack();
                    if (!visible) {
                        errorTrackerContainer.hide();
                    }
                }

                if (visible) {
                    errorGroupContainer.show();
                    errorTrackerContainer.show();
                }

                len = dataSetLen;
                if (animationDuration && !drawn) {
                    errorGroupContainer.hide();
                }
                // Loop through each data points
                for (i = 0; i < len; i++) {
                    setData = setDataArr && setDataArr[i];
                    dataObj = dataStore[i];
                    config = dataObj && dataObj.config;
                    setValue = config.y;
                    setLink = config.setLink;
                    errorValueArr = config.errorValue;
                    errorLen = errorValueArr.length;
                    toolText = config.toolText;
                    !dataObj.graphics.error && (dataObj.graphics.error = []);

                    // Skipping the remaining calculations if data entered by the user is null for a plot.
                    if (setValue === null) {
                        continue;
                    }
                    setLink  = config.setLink;

                    isNegative = (setValue < 0);

                    barXpos = dataObj._xPos;
                    barYpos = dataObj._yPos;
                    barWidth = dataObj._width;
                    barHeight = dataObj._height;

                    yPos = isNegative ? (barYpos +barHeight) : barYpos + barHeight;
                    xPos = barXpos + (barWidth / 2);

                    errorElements = dataObj.graphics.error;
                    errorElemLen = errorElements.length;
                    isNewElem = false;
                    if (errorElemLen > errorLen) {

                        for (ii = errorLen; ii < errorElemLen; ii++) {
                            removeErrorElem = errorElements.pop();
                            dataSet._removeDataVisuals(removeErrorElem);
                        }
                    }
                    dataObj.errorBar || (dataObj.errorBar = []);
                    //Loop through errorValue array
                    while (errorLen--) {
                        errorGraphics = dataObj.graphics.error[errorLen];
                        if (!errorGraphics) {
                            errorGraphics = dataObj.graphics.error[errorLen] = {};
                        }
                        errorTrackerElem = errorGraphics.errorTrackerElem;
                        errorLineElem = errorGraphics.errorLineElem;
                        errorValueObj = errorValueArr[errorLen];
                        errorValue = errorValueObj.errorValue;
                        errorStartValue = errorValueObj.errorStartValue;
                        errorBarColor = errorValueObj.errorBarColor;
                        errorBarThickness = errorValueObj.errorBarThickness;
                        errorStartPos = !isNaN(errorStartValue) ?
                            yAxis.getAxisPosition(errorStartValue) : yPos;
                        errorBarWidth = barWidth * (errorBarWidthPercent / 100);
                        halfErrorBarW = errorBarWidth / 2;

                        errorValuePosFactor = 1;
                        // Vertical Error drawing
                        errorValPos = yAxis.getAxisPosition(
                            (defined(errorStartValue) ? errorStartValue : y) + errorValue);
                        isNegative && (errorValPos = errorValPos + barHeight);
                        crispY = errorValPos;
                        crispX = xPos;
                        if (useCrispErrorPath) {
                            crispY = mathRound(errorValPos) +
                                (errorBarThickness % 2 / 2);
                            crispX = mathRound(xPos) +
                                (errorBarThickness % 2 / 2);
                        }

                        errorPath = [
                            M, crispX, errorStartPos,
                            V, crispY,
                            M, crispX - halfErrorBarW, crispY,
                            H, (crispX + halfErrorBarW)
                        ];
                        errorValueObj.errorPath = errorPath;
                        graphicEle = dataObj.graphics.hotElement || dataObj.graphics.element;
                        groupId = graphicEle.data('groupId');
                        dataObj.errorBar[errorLen] || (dataObj.errorBar[errorLen] = []);
                        dataObj.errorBar[errorLen][0] = {
                            _xPos: crispX - trackerTolerance,
                            _yPos: crispY < errorStartPos ? crispY : errorStartPos,
                            _height: mathAbs(errorStartPos - crispY),
                            _width: 2 * trackerTolerance
                        };
                        // dataObj.errorBar[errorLen][0] = {
                        //     _xPos: crispX - halfErrorBarW - trackerTolerance,
                        //     _yPos: crispY - trackerTolerance,
                        //     _height: 2 * trackerTolerance,
                        //     _width: 2 * (halfErrorBarW + trackerTolerance)
                        // };
                        if (!errorLineElem) {
                            if (pool.errorLineElem && pool.errorLineElem.length) {
                                errorLineElem = errorGraphics.errorLineElem = pool.errorLineElem.shift();
                            }
                            else {
                                errorLineElem = errorGraphics.errorLineElem = paper.path(errorGroupContainer);
                                isNewElem = true;
                            }
                        }

                        // Animate the error Line Element
                        errorLineElem.show().animateWith(dummyAnimElem, dummyAnimObj, {
                            path: errorPath
                        }, animationDuration, animationObj.animType);

                        errorLineElem.attr({
                            stroke: errorBarColor,
                            // In case of tooltip disabled this element should act as the hot element.
                            ishot: !showTooltip,
                            'stroke-width': errorBarThickness,
                            'cursor': setLink ? POINTER : BLANKSTRING,
                            'stroke-linecap': ROUND
                        });

                        // if ((setLink || showTooltip) && errorBarThickness < HTP) {
                        //     errorTrackerElem = errorGraphics.errorTrackerElem;
                        //     if (!errorTrackerElem) {
                        //         if (pool.errorTrackerElem && pool.errorTrackerElem.length) {
                        //             errorTrackerElem = errorGraphics.errorTrackerElem =
                        // pool.errorTrackerElem.shift();
                        //         }
                        //         else {
                        //             errorTrackerElem = errorGraphics.errorTrackerElem =
                        //                 paper.path(errorTrackerContainer);
                        //             isNewElem = true;
                        //         }
                        //     }
                        //     errorTrackerElem.attr({
                        //         path: errorPath,
                        //         stroke: TRACKER_FILL,
                        //         'stroke-width': HTP,
                        //         'cursor': setLink ? POINTER : BLANKSTRING,
                        //         'ishot': !! setLink,
                        //         'visibility': visible
                        //     })
                        //     .data('groupId', groupId)
                        //     .tooltip(toolText);
                        //     errorTrackerElem.data('eventArgs', graphicEle && graphicEle.data('eventArgs') || {});
                        // }

                        // if (isNewElem) {
                        //     (errorTrackerElem || errorLineElem).click(errorElemClick)
                        //     .hover(erroElemHoverFN, erroElemOutFN);
                        //     (setLink || showTooltip) &&
                        //             errorTrackerElem.click(getErrLinkClickFN(setLink));
                        // }
                    }
                }
                dataSet.components.data = dataStore;
            },
            // Function for returning the data limits of candlestick dataset
            getDataLimits: function () {
                var conf = this.config;
                return  {
                    max: conf.yMax,
                    min: conf.yMin,
                    xMax: conf.xMax,
                    xMin: conf.xMin
                };
            },
            // Function to remove a data with a given index.
            removeData : function (index, stretch) {
                var dataSet = this,
                    components = dataSet.components,
                    dataStore = components.data,
                    removeDataArr = components.removeDataArr || (components.removeDataArr = []);

                stretch = stretch || 1;
                index = index || 0;

                components.removeDataArr = removeDataArr = removeDataArr.concat(dataStore.splice(index, stretch));
            }
        }, LINE]);

    }
]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-trendset',
    function () {
        var global = this,
            lib = global.hcLib,

            //strings
            preDefStr = lib.preDefStr,

            configStr = preDefStr.configStr,
            animationObjStr = preDefStr.animationObjStr,
            miterStr = preDefStr.miterStr,
            ROUND = preDefStr.ROUND,
            LINE = preDefStr.line,
            //add the tools thats are requared
            pluck = lib.pluck,
            getValidValue = lib.getValidValue,
            pluckNumber = lib.pluckNumber,
            getFirstValue = lib.getFirstValue,
            // getDefinedColor = lib.getDefinedColor,
            getDashStyle = lib.getDashStyle, // returns dashed style of a line series
            toRaphaelColor = lib.toRaphaelColor,
            MAX_MITER_LINEJOIN = 2,
            NONE = 'none',
            // The default value for stroke-dash attribute.
            DASH_DEF = NONE,
            COMPONENT = 'component',
            DATASET = 'dataset',
            // CRISP = 'crisp',
            HUNDRED = '100',
            math = Math,
            mathMin = math.min,
            mathMax = math.max,
            // getColumnColor = lib.graphics.getColumnColor,
            getFirstColor = lib.getFirstColor,
            // pluckColor = lib.pluckColor,
            HUNDREDSTRING = lib.HUNDREDSTRING;

        FusionCharts.register(COMPONENT, [DATASET, 'Trendset', {
            configure: function () {
                var dataset = this,
                    chart = dataset.chart,
                    rawDataObj = chart.jsonData,
                    chartAttr = rawDataObj.chart,
                    trendset = dataset.JSONData,
                    index = dataset.index,
                    setDataArr = trendset.data || trendset.set || [],
                    conf = dataset.config,
                    dataObj,
                    itemValue,
                    dataStore = dataset.components.data,
                    dataStoreObj,
                    config,
                    maxValue = -Infinity,
                    minValue = +Infinity,
                    x,
                    length,
                    xMax = -Infinity,
                    xMin = +Infinity,
                    NumberFormatter = chart.components.numberFormatter,
                    //Trend-sets default properties
                    trendSetColor = getFirstColor(pluck(trendset.color, chartAttr.trendsetcolor, '666666')),
                    trendSetAlpha = pluck(trendset.alpha, chartAttr.trendsetalpha, HUNDRED),
                    trendSetThickness = pluckNumber(trendset.thickness, chartAttr.trendsetthickness, 2),
                    trendSetDashed = Boolean(pluckNumber(trendset.dashed, chartAttr.trendsetdashed, 0)),
                    trendSetDashLen = pluckNumber(trendset.dashlen, chartAttr.trendsetdashlen, 4),
                    trendSetDashGap = pluckNumber(trendset.dashgap, chartAttr.trendsetdashgap, 4);
                conf.includeInLegend = pluckNumber(trendset.includeinlegend, 1);
                conf.lineColor = trendSetColor;
                conf.lineAlpha = trendSetAlpha;
                conf.connectNullData = pluckNumber(chartAttr.connectnulldata, 0);
                conf.lineThickness = trendSetThickness;
                conf.lineDashStyle = trendSetDashed ? getDashStyle(trendSetDashLen, trendSetDashGap) : DASH_DEF;
                conf.name = getValidValue(trendset.name);

                conf.includeInLegend = pluckNumber(trendset.includeinlegend, 1);
                if (!dataStore) {
                    dataStore = dataset.components.data = [];
                }
                for (index = 0, length = setDataArr.length; index < length; index += 1) {
                    dataObj = setDataArr[index];
                    if (dataObj && !dataObj.vline) {
                        dataStoreObj = dataStore[index] = dataStore[index] || (dataStore[index]= {});
                        config = dataStoreObj.config = dataStoreObj.config || (dataStoreObj.config = {});
                        itemValue = config.setValue = NumberFormatter.getCleanValue(dataObj.value);
                        x = NumberFormatter.getCleanValue(dataObj.x);
                        x = config.x = x !== null ? x : index + 1;
                        maxValue = mathMax(maxValue, itemValue);
                        minValue = mathMin(minValue, itemValue);
                        xMin = mathMin(xMin, x);
                        xMax = mathMax(xMax, x);
                        if (!dataStoreObj.graphics) {
                            dataStoreObj.graphics = {};
                        }
                    }
                }
                conf.max = maxValue;
                conf.min = minValue;
                conf.xMax = xMax;
                conf.xMin = xMin;
                dataset.yAxis = chart.components.yAxis[0];
                dataset.visible = true;
                dataset._addLegend();
            },
            _addLegend: function () {
                var dataset = this,
                    chart = dataset.chart,
                    JSONData = dataset.JSONData,
                    conf = dataset.config,
                    legend = chart.components.legend,
                    config = {
                        enabled: conf.includeInLegend,
                        interactiveLegend: false,
                        type : dataset.type,
                        drawLine: true,
                        strokeColor: toRaphaelColor({
                            color: conf.lineColor,
                            alpha: HUNDREDSTRING
                        }),
                        label : getFirstValue(JSONData.name)
                    };
                dataset.legendItemId = legend.addItems(dataset, dataset.legendInteractivity, config);
            },
            legendInteractivity: function () {

            },
            draw: function () {// retrive requitrd objects
                var dataSet = this,
                    JSONData = dataSet.JSONData,
                    chart = dataSet.chart,
                    chartComponents = chart.components,
                    conf = dataSet.config,
                    setDataArr = JSONData.data,
                    dataSetLen = dataSet.components.data.length,
                    clip = chartComponents.canvas.config.clip,
                    len = dataSetLen,
                    setData,
                    i,
                    paper = chartComponents.paper,
                    xAxis = chartComponents.xAxis[0],
                    yAxis = dataSet.yAxis,
                    xPos,
                    yPos,
                    layers = chart.graphics,
                    setLink,
                    setValue,
                    animObj = chart.get(configStr, animationObjStr),
                    animationDuration = animObj.duration,
                    dummyAnimElem = animObj.dummyObj,
                    dummyAnimObj = animObj.animObj,
                    animType = animObj.animType,
                    dataStore = dataSet.components.data,
                    dataObj,
                    lineThickness = conf.lineThickness,
                    container = dataSet.graphics.container,
                    group = layers.datasetGroup,
                    shadow = conf.shadow,
                    config,
                    initAnimCallBack = function () {
                        group.line.attr({
                            'clip-rect': null
                        });
                        //group.line.removeCSS('clip-path');
                        container.lineShadowGroup.show();
                    },
                    clipCanvas = clip['clip-canvas'].slice(0),
                    clipCanvasInit = clip['clip-canvas-init'].slice(0),
                    lineDashStyle = conf.lineDashStyle,
                    lineColorObj = {
                        color: conf.lineColor,
                        alpha: conf.lineAlpha
                    },
                    linePath,
                    linePathArr,
                    initialAnimation = false,
                    lineElement = dataSet.graphics.lineElement,
                    visible = dataSet.visible,
                    x;

                // Creating the line group and appending it to dataset layer if not created
                group.line = group.line ||
                    paper.group(LINE, group);
                /*
                 * Creating lineConnector group and appending it to dataset layer if not created
                 * Lineconnector group has the anchorgroups of all datasets
                 */
                group.lineConnector = group.lineConnector ||
                    paper.group('line-connector', group);
                // Create dataset container if not created
                if (!container) {
                    container = dataSet.graphics.container = {
                        lineShadowGroup: paper.group('connector-shadow', group.line),
                        lineGroup: paper.group(LINE, group.line)
                    };
                    if (!visible) {
                        container.lineShadowGroup.hide();
                        container.lineGroup.hide();
                    }

                }


                //create plot elements
                for (i = 0; i < len; i++) {

                    setData = setDataArr && setDataArr[i];
                    dataObj = dataStore[i];
                    config = dataObj.config;
                    setValue = config.setValue;
                    x = config.x;
                    setLink  = config.setLink;
                    xPos = xAxis.getAxisPosition(x);
                    yPos = yAxis.getAxisPosition(setValue);
                    /*Storing the x position and y position in dataObject for future reference
                    For example - when drawing labels we need this xPos and yPos
                    */
                    dataObj._xPos = xPos;
                    dataObj._yPos = yPos;
                }
                linePath = dataSet.getLinePath(dataStore, {});
                linePathArr = linePath.getPathArr();

                if (!lineElement) {
                    lineElement = dataSet.graphics.lineElement = paper.path(container.lineGroup);
                    initialAnimation = true;
                }

                lineElement.show().animateWith(dummyAnimElem, dummyAnimObj, {
                    path: linePathArr
                }, animationDuration, animType);

                lineElement.attr({
                    'stroke-dasharray': lineDashStyle,
                    'stroke-width': lineThickness,
                    'stroke': toRaphaelColor(lineColorObj),
                    'stroke-linecap': ROUND,
                    /*  for lines even with thickness as 2 we need to have round line join
                        otherwise the line join may look like exceeding the correct position
                    */
                    'stroke-linejoin': lineThickness >= MAX_MITER_LINEJOIN ? ROUND : miterStr
                })
                .shadow(shadow, container.lineShadowGroup);

                if (animationDuration && visible && initialAnimation) {
                    container.lineShadowGroup.hide();
                    group.line.attr({
                        'clip-rect': clipCanvasInit
                    })
                    .animateWith(dummyAnimElem, dummyAnimObj, {
                        'clip-rect': clipCanvas
                    }, animationDuration, animType, initAnimCallBack);
                }

            },
            getDataLimits: function () {
                var conf = this.config;
                return {
                    max: conf.max,
                    min: conf.min,
                    xMax: conf.xMax,
                    xMin: conf.xMin
                };
            }
        }, LINE]);

    }
]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-boxandwhisker2d',
    function () {
        var global = this,
            lib = global.hcLib,

            //strings
            preDefStr = lib.preDefStr,
            colorStrings = preDefStr.colors,
            COLOR_000000 = colorStrings.c000000,

            configStr = preDefStr.configStr,
            animationObjStr = preDefStr.animationObjStr,
            showHoverEffectStr = preDefStr.showHoverEffectStr,
            shadowStr = preDefStr.shadowStr,
            dataLabelStr = preDefStr.dataLabelStr,
            visibleStr = preDefStr.visibleStr,
            ROUND = preDefStr.ROUND,
            ZEROSTRING = lib.ZEROSTRING,
            pStr = preDefStr.pStr,
            sStr = preDefStr.sStr,
            POSITION_START = preDefStr.POSITION_START,
            POSITION_TOP = preDefStr.POSITION_TOP,
            POSITION_END = preDefStr.POSITION_END,
            POSITION_BOTTOM = preDefStr.POSITION_BOTTOM,
            PLOTFILLCOLOR_STR = preDefStr.PLOTFILLCOLOR_STR,
            UNDERSCORE = preDefStr.UNDERSCORE,
            MAXIMUM_STR = 'Maximum',
            Q3_STR = 'Q3',
            MEDIAN_STR = 'Median',
            Q1_STR = 'Q1',
            MINIMUM_STR = 'Minimum',
            MEAN_STR = 'Mean',
            SD_STR = 'SD',
            MD_STR = 'MD',
            QD_STR = 'QD',
            OUTLIERS_STR = 'Outliers',
            OUTLIER_STR = 'Outlier',

            meanStr = 'mean',
            sdStr = 'sd',
            mdStr = 'md',
            qdStr = 'qd',
            outlierStr = 'outlier',

            iconradiusStr = 'iconradius',
            iconcolorStr = 'iconcolor',
            iconalphaStr = 'iconalpha',
            iconsidesStr = 'iconsides',

            LINE = preDefStr.line,
            BLANK = lib.BLANKSTRING,
            BLANKSTRING = lib.BLANKSTRING,
            //add the tools thats are requared
            pluck = lib.pluck,
            getValidValue = lib.getValidValue,
            pluckNumber = lib.pluckNumber,
            getFirstValue = lib.getFirstValue,
            // getDefinedColor = lib.getDefinedColor,
            extend2 = lib.extend2, //old: jarendererExtend / margecolone
            toRaphaelColor = lib.toRaphaelColor,
            UNDEFINED,
            defined = function(obj) {
                return obj !== UNDEFINED && obj !== null;
            },
            NONE = 'none',
            ROLLOVER = 'DataPlotRollOver',
            ROLLOUT = 'DataPlotRollOut',
            parseConfiguration = lib.parseConfiguration,

            PLOTBORDERCOLOR = 'plotBorderColor',
            PLOTGRADIENTCOLOR = 'plotGradientColor',
            SHOWSHADOW = 'showShadow',
            BOLDSTARTTAG = '<b>',
            BOLDENDTAG = '</b>',
            BREAKSTRING = '<br />',
            POLYGON = 'polygon',
            SPOKE = 'spoke',
            POINTER = 'pointer',
            SETROLLOVERATTR = 'setRolloverAttr',
            SETROLLOUTATTR = 'setRolloutAttr',
            EVENTARGS = 'eventArgs',
            GROUPID = 'groupId',
            COMPONENT = 'component',
            DATASET = 'dataset',
            // CRISP = 'crisp',
            M = 'M',
            H = 'H',
            V = 'V',
            COMMA = ',',
            POSITION_MIDDLE = 'middle',
            math = Math,
            mathRound = math.round,
            mathMin = math.min,
            mathMax = math.max,
            // getColumnColor = lib.graphics.getColumnColor,
            getFirstColor = lib.getFirstColor,
            // pluckColor = lib.pluckColor,
            getFirstAlpha = lib.getFirstAlpha,
            getLightColor = lib.graphics.getLightColor,
            convertColor = lib.graphics.convertColor,
            // POSITION_CENTER = lib.POSITION_CENTER,
            POSITION_LEFT = lib.POSITION_LEFT,
            COMMASTRING = lib.COMMASTRING,
            HUNDREDSTRING = lib.HUNDREDSTRING,
            // COMMASPACE = lib.COMMASPACE,
            plotEventHandler = lib.plotEventHandler,
            LABEL = 'label';

        FusionCharts.register(COMPONENT, [DATASET, 'boxandwhisker2d', {

            type: 'boxandwhisker2d',
            configure : function () {
                var dataSet = this,
                    chart = dataSet.chart,
                    conf = dataSet.config,
                    JSONData = dataSet.JSONData,
                    setDataArr = JSONData.data,
                    setDataLen = setDataArr && setDataArr.length,
                    categories = chart.config.categories,
                    singleSeries = chart.singleseries,
                    chartConfig = chart.config,
                    catLen = categories && categories.length,
                    len = mathMin(catLen, setDataLen),
                    chartAttr = chart.jsonData.chart,
                    colorM = chart.components.colorManager,
                    index = dataSet.index || dataSet.positionIndex,
                    showplotborder,
                    plotColor = conf.plotColor = colorM.getPlotColor(index),
                    plotBorderDash = pluckNumber(JSONData.dashed, chartAttr.plotborderdashed),
                    usePlotGradientColor = pluckNumber(chartAttr.useplotgradientcolor, 1),
                    showTooltip,
                    parseUnsafeString = lib.parseUnsafeString,
                    yAxisName = parseUnsafeString(chartAttr.yaxisname),
                    xAxisName = parseUnsafeString(chartAttr.xaxisname),
                    tooltipSepChar = parseUnsafeString(pluck(chartAttr.tooltipsepchar, ': ')),
                    parseTooltext = lib.parseTooltext,
                    formatedVal,
                    parserConfig,
                    setTooltext,
                    macroIndices,
                    tempPlotfillAngle,
                    toolText,
                    plotDashLen,
                    plotDashGap,
                    plotBorderThickness,
                    isRoundEdges,
                    showHoverEffect,
                    plotfillAngle,
                    plotFillAlpha,
                    plotRadius,
                    plotFillRatio,
                    plotgradientcolor,
                    plotBorderAlpha,
                    plotBorderColor,
                    plotBorderDashStyle,
                    initailPlotBorderDashStyle,
                    setData,
                    setValue,
                    dataObj,
                    config,
                    label,
                    colorArr,
                    upperBoxHoverColor,
                    upperBoxHoverAlpha,
                    upperBoxBorderHoverColor,
                    upperBoxBorderHoverAlpha,
                    upperBoxBorderHoverThickness,
                    lowerBoxHoverColor,
                    lowerBoxHoverAlpha,
                    lowerBoxBorderHoverColor,
                    lowerBoxBorderHoverAlpha,
                    lowerBoxBorderHoverThickness,
                    upperQuartileHoverColor,
                    upperQuartileHoverAlpha,
                    upperQuartileHoverThickness,
                    lowerQuartileHoverColor,
                    lowerQuartileHoverAlpha,
                    lowerQuartileHoverThickness,
                    medianHoverColor,
                    medianHoverAlpha,
                    medianHoverThickness,
                    getDashStyle = lib.getDashStyle,
                    dataStore = dataSet.components.data,
                    numberFormatter = chart.components.numberFormatter,
                    toolTipValue,
                    setDisplayValue,
                    definedGroupPadding,

                    use3DLighting,
                    parentYAxis,
                    setDataDashed,
                    setDataPlotDashLen,
                    setDataPlotDashGap,
                    i,
                    maxValue = 0,
                    minValue = 0,

                    BoxAndWhiskerStatisticalCalc = lib.BoxAndWhiskerStatisticalCalc,
                    bwCalc,
                    quartile,
                    q1,
                    q3,
                    limits,
                    min,
                    max,
                    medianValue,
                    mean,
                    md,
                    sd,
                    qd,
                    highValue,
                    lowValue,
                    itemValue,
                    upperBoxColor,
                    upperBoxAlpha,
                    lowerBoxColor,
                    lowerBoxAlpha,
                    upperWhiskerAlpha,
                    showValues,
                    showAllOutliers,
                    difference,
                    lowerWhiskerAlpha,
                    showMean,
                    showSD,
                    showMD,
                    showQD,

                    outlierDS,
                    OutliersLength,
                    maxNumberOfOutliers = 0,
                    j;

                dataSet.visible = pluckNumber(dataSet.JSONData.visible,
                    !Number(dataSet.JSONData.initiallyhidden), 1) === 1;

                // set the default configurations
                dataSet.__setDefaultConfig();
                parseConfiguration(JSONData, conf, chartConfig, {data: true});

                conf.includeInLegend = pluckNumber(JSONData.includeinlegend, 1);
                conf.legendSymbolColor = conf.plotColor;
                showplotborder = conf.showplotborder;
                plotDashLen = conf.plotborderdashlen;
                plotDashGap = conf.plotborderdashgap;
                plotFillAlpha = conf.plotfillalpha;
                isRoundEdges = conf.useroundedges;
                plotFillRatio = conf.ratio;
                plotBorderThickness = conf.plotborderthickness;
                showValues = conf.showvalues;
                showTooltip = conf.showtooltip;
                conf.rotatevalues && (conf.rotatevalues = 270);
                use3DLighting = conf.use3dlighting;
                showAllOutliers = conf.showalloutliers;

                conf.plotfillAngle = plotfillAngle =  pluckNumber(360 - chartAttr.plotfillangle, 90);
                conf.plotColor = plotColor = pluck(JSONData.color, plotColor);
                conf.plotRadius = plotRadius = pluckNumber(chartAttr.useroundedges, isRoundEdges ? 1 : 0);
                conf.plotgradientcolor = plotgradientcolor = lib.getDefinedColor(chartAttr.plotgradientcolor,
                    colorM.getColor(PLOTGRADIENTCOLOR));
                !usePlotGradientColor && (plotgradientcolor = BLANKSTRING);
                conf.plotBorderAlpha = plotBorderAlpha = showplotborder ? pluck(chartAttr.plotborderalpha,
                    plotFillAlpha, HUNDREDSTRING): 0;
                conf.plotBorderColor = plotBorderColor = pluck(chartAttr.plotbordercolor,
                    colorM.getColor(PLOTBORDERCOLOR));
                conf.plotBorderDashStyle = initailPlotBorderDashStyle = plotBorderDash ?
                            getDashStyle(plotDashLen, plotDashGap, plotBorderThickness) : NONE;

                conf.showShadow = isRoundEdges ? pluckNumber(chartAttr.showshadow, 1) :
                    pluckNumber(chartAttr.showshadow, colorM.getColor(SHOWSHADOW));
                conf.showHoverEffect = showHoverEffect = pluckNumber(chartAttr.plothovereffect,
                    chartAttr.showhovereffect, UNDEFINED);

                conf.definedGroupPadding = definedGroupPadding = mathMax(pluckNumber(chartAttr.plotspacepercent), 0);
                conf.plotSpacePercent = mathMax(pluckNumber(chartAttr.plotspacepercent, 20) % 100, 0);

                conf.parentYAxis = parentYAxis = pluck(JSONData.parentyaxis && JSONData.parentyaxis.toLowerCase(),
                    pStr) === sStr ? 1 : 0 ;

                conf.dataSeparator = COMMASTRING;
                conf.bwCalc = bwCalc = new BoxAndWhiskerStatisticalCalc(
                    UNDEFINED, numberFormatter,
                    conf.dataSeparator);

                conf.textDirection = chartAttr.hasrtltext === '1' ? 'rtl' : BLANKSTRING;

                conf.showMeanLegend = conf.showSDLegend = conf.showMDLegend = conf.showQDLegend =
                    conf.showOutliersLegend = 0;

                !dataSet.components.data && (dataSet.components.data = []);
                dataStore = dataSet.components.data;

                // Parsing the attributes and values at set level.
                for (i = 0; i < len; i++) {
                    setData = setDataArr && setDataArr[i];
                    dataObj = dataStore[i];
                    config = dataObj && dataObj.config;

                    if (!dataObj) {
                        dataObj = dataStore[i] = {
                            graphics : {}
                        };
                    }

                    if (!dataObj.config) {
                        config = dataStore[i].config = {};

                    }

                    if (!setData.value) {
                        continue;
                    }

                    if (setData.value) {
                        bwCalc.setArray(setData.value);
                        quartile = bwCalc.getQuartiles();
                        q1 = quartile.q1;
                        q3 = quartile.q3;

                        limits = bwCalc.getMinMax();
                        config.min = min = lowValue = limits.min;
                        config.max = max = limits.max;
                        medianValue = bwCalc.getMedian();
                        config.mean = mean = bwCalc.getMean();
                        config.md = md = bwCalc.getMD();
                        config.sd = sd = bwCalc.getSD();
                        config.qd = qd = bwCalc.getQD();

                        // get the valid value
                        highValue = itemValue = max;
                    }

                    if (setData.outliers) {
                        config.outliers = setData.outliers.split(COMMA);
                        maxNumberOfOutliers = mathMax(maxNumberOfOutliers, config.outliers.length);
                    }

                    config.showMean = showMean = pluckNumber(setData.showmean, conf.showmean);
                    config.showSD = showSD = pluckNumber(setData.showsd, conf.showsd);
                    config.showMD = showMD = pluckNumber(setData.showmd, conf.showmd);
                    config.showQD = showQD = pluckNumber(setData.showqd, conf.showqd);
                    setData.outliers && (conf.showOutliersLegend = 1);

                    showMean && (conf.showMeanLegend = 1);
                    showSD && (conf.showSDLegend = 1);
                    showMD && (conf.showMDLegend = 1);
                    showQD && (conf.showQDLegend = 1);

                    config.upperQuartile = {
                        value: q3,
                        color: convertColor(pluck(
                                setData.upperquartilecolor, JSONData.upperquartilecolor, chartAttr.upperquartilecolor,
                                chartAttr.plotbordercolor, colorM.getColor (PLOTBORDERCOLOR)),
                            pluckNumber(setData.upperquartilealpha, JSONData.upperquartilealpha,
                                chartAttr.upperquartilealpha, chartAttr.plotborderalpha,
                                100)),
                        borderWidth: pluckNumber(
                            setData.upperquartilethickness, JSONData.upperquartilethickness,
                            chartAttr.upperquartilethickness, chartAttr.plotborderthickness,
                            !isRoundEdges ? 1 : 0),

                        displayValue: numberFormatter.dataLabels(q3)
                    };

                    config.lowerQuartile = {
                        value: q1,
                        color: convertColor(pluck(
                                setData.lowerquartilecolor, JSONData.lowerquartilecolor, chartAttr.lowerquartilecolor,
                                chartAttr.plotbordercolor, colorM.getColor (PLOTBORDERCOLOR)),
                            pluckNumber(setData.lowerquartilealpha, JSONData.lowerquartilealpha,
                                chartAttr.lowerquartilealpha, chartAttr.plotborderalpha,
                                100)),
                        borderWidth: pluckNumber(
                            setData.lowerquartilethickness, JSONData.lowerquartilethickness,
                            chartAttr.lowerquartilethickness, chartAttr.plotborderthickness,
                            !isRoundEdges ? 1 : 0),

                        displayValue: numberFormatter.dataLabels(q1)
                    };

                    config.upperBoxBorder = {
                        color: convertColor(pluck(
                                setData.upperboxbordercolor, JSONData.upperboxbordercolor,
                                chartAttr.upperboxbordercolor, chartAttr.plotbordercolor,
                                colorM.getColor (PLOTBORDERCOLOR)),
                            pluckNumber(setData.upperboxborderalpha, JSONData.upperboxborderalpha,
                                chartAttr.upperboxborderalpha, chartAttr.plotborderalpha,
                                100)),
                        borderWidth: pluckNumber(
                            setData.upperboxborderthickness, JSONData.upperboxborderthickness,
                            chartAttr.upperboxborderthickness, !isRoundEdges && chartAttr.plotborderthickness,
                            !isRoundEdges ? 1 : 0)
                    };

                    config.lowerBoxBorder = {
                        color: convertColor(pluck(
                                setData.lowerboxbordercolor, JSONData.lowerboxbordercolor,
                                chartAttr.lowerboxbordercolor, chartAttr.plotbordercolor,
                                colorM.getColor (PLOTBORDERCOLOR)),
                            pluckNumber(setData.lowerboxborderalpha, JSONData.lowerboxborderalpha,
                                chartAttr.lowerboxborderalpha, chartAttr.plotborderalpha,
                                100)),
                        borderWidth: pluckNumber(
                            setData.lowerboxborderthickness, JSONData.lowerboxborderthickness,
                            chartAttr.lowerboxborderthickness, !isRoundEdges && chartAttr.plotborderthickness,
                            !isRoundEdges ? 1 : 0)
                    };

                    config.median = {
                        value: medianValue,
                        color: convertColor(pluck(
                                setData.mediancolor, JSONData.mediancolor,
                                chartAttr.mediancolor, chartAttr.plotbordercolor,
                                colorM.getColor (PLOTBORDERCOLOR)),
                            pluckNumber(setData.medianalpha, JSONData.medianalpha,
                                chartAttr.medianalpha, chartAttr.plotborderalpha,
                                100)),
                        borderWidth: pluckNumber(
                            setData.medianthickness, JSONData.medianthickness,
                            chartAttr.medianthickness, chartAttr.plotborderthickness,
                            1),

                        displayValue: numberFormatter.dataLabels(medianValue)
                    };

                    conf.upperBoxColor = upperBoxColor = pluck(setData.upperboxcolor, JSONData.upperboxcolor,
                        chartAttr.upperboxcolor, colorM.getPlotColor(index * 2));

                    upperBoxAlpha = conf.upperBoxAlpha = pluck(setData.upperboxalpha, JSONData.upperboxalpha,
                        chartAttr.upperboxalpha, plotFillAlpha, HUNDREDSTRING);

                    conf.lowerBoxColor = lowerBoxColor = pluck(setData.lowerboxcolor, JSONData.lowerboxcolor,
                        chartAttr.lowerboxcolor, colorM.getPlotColor((index * 2) + 1));

                    lowerBoxAlpha = conf.lowerBoxAlpha = pluck(setData.lowerboxalpha, JSONData.lowerboxalpha,
                        chartAttr.lowerboxalpha, plotFillAlpha, HUNDREDSTRING);

                    config.upperColorArr = lib.graphics.getColumnColor (
                            upperBoxColor,
                            upperBoxAlpha,
                            UNDEFINED,
                            UNDEFINED,
                            isRoundEdges,
                            plotBorderColor,
                            plotBorderAlpha.toString(),
                            0,
                            false
                            );

                    config.lowerColorArr = lib.graphics.getColumnColor (
                            lowerBoxColor,
                            lowerBoxAlpha,
                            UNDEFINED,
                            UNDEFINED,
                            isRoundEdges,
                            plotBorderColor,
                            plotBorderAlpha.toString(),
                            0,
                            false
                            );

                    config.showMinValues = showValues ? pluckNumber(setData.showminvalues, conf.showminvalues) : 0;

                    config.showMaxValues = showValues ? pluckNumber(setData.showmaxvalues, conf.showmaxvalues) : 0;

                    config.showQ1Values = showValues ? pluckNumber(setData.showq1values, conf.showq1values) : 0;

                    config.showQ3Values = showValues ? pluckNumber(setData.showq3values, conf.showq3values) : 0;

                    config.showMedianValues = showValues ? pluckNumber(setData.showmedianvalues,
                        conf.showmedianvalues) : 0;

                    config.upperWhiskerAlpha = upperWhiskerAlpha = getFirstAlpha(pluck(setData.upperwhiskeralpha,
                        JSONData.upperwhiskeralpha, chartAttr.upperwhiskeralpha, chartAttr.plotborderalpha, 100));

                    config.upperWhiskerColor = convertColor(getFirstColor(pluck(setData.upperwhiskercolor,
                        JSONData.upperwhiskercolor,
                        chartAttr.upperwhiskercolor,
                        chartAttr.plotbordercolor, colorM.getColor (PLOTBORDERCOLOR))), upperWhiskerAlpha);

                    config.upperWhiskerThickness = pluckNumber(setData.upperwhiskerthickness,
                        JSONData.upperwhiskerthickness, chartAttr.upperwhiskerthickness, chartAttr.plotborderthickness,
                         1);

                    config.upperWhiskerShadowOpacity = conf.showShadow ? (upperWhiskerAlpha / 250) : 0;

                    config.lowerWhiskerAlpha = lowerWhiskerAlpha = getFirstAlpha(pluck(setData.lowerwhiskeralpha,
                        JSONData.lowerwhiskeralpha, chartAttr.lowerwhiskeralpha, chartAttr.plotborderalpha, 100));

                    config.lowerWhiskerColor = convertColor(getFirstColor(pluck(setData.lowerwhiskercolor,
                        JSONData.lowerwhiskercolor,
                        chartAttr.lowerwhiskercolor, chartAttr.plotbordercolor,
                         colorM.getColor (PLOTBORDERCOLOR))), lowerWhiskerAlpha);

                    config.lowerWhiskerThickness = pluckNumber(setData.lowerwhiskerthickness,
                        JSONData.lowerwhiskerthickness, chartAttr.lowerwhiskerthickness, chartAttr.plotborderthickness,
                         1);

                    config.lowerWhiskerShadowOpacity = conf.showShadow ? (lowerWhiskerAlpha / 250) : 0;

                    config.showValue = pluckNumber(setData.showvalue, conf.showvalues);
                    config.setValue = setValue = numberFormatter.getCleanValue(setData.value);
                    config.setLink  = pluck(setData.link);
                    config.toolTipValue = toolTipValue = numberFormatter.dataLabels(setValue, parentYAxis);
                    config.setDisplayValue = setDisplayValue = parseUnsafeString(setData.displayvalue);
                    config.displayValue = pluck(setDisplayValue, toolTipValue);
                    setDataDashed = pluckNumber(setData.dashed);
                    setDataPlotDashLen = pluckNumber(setData.dashlen, plotDashLen);
                    setDataPlotDashGap = plotDashGap = pluckNumber(setData.dashgap, plotDashGap);

                    maxValue = mathMax(maxValue, max);
                    minValue = mathMin(minValue, min);

                    if (showAllOutliers && setData.outliers) {
                        for (j = 0; j < config.outliers.length; j++) {
                            maxValue = mathMax(maxValue, config.outliers[j]);
                            minValue = mathMin(minValue, config.outliers[j]);
                        }
                    }

                    config.plotBorderDashStyle = plotBorderDashStyle =  setDataDashed === 1 ?
                        getDashStyle(setDataPlotDashLen, setDataPlotDashGap, plotBorderThickness) :
                            (setDataDashed === 0 ? NONE : initailPlotBorderDashStyle);
                    if (singleSeries) {
                        plotColor = colorM.getPlotColor(i);
                        plotColor = pluck(setData.color, plotColor);
                        plotFillRatio = pluck(setData.ratio, conf.ratio);
                    }
                    else {
                        plotColor = pluck(setData.color, conf.plotColor);
                    }
                    plotFillAlpha = pluck(setData.alpha, conf.plotfillalpha);

                    // Setting the angle for plot fill for negative data
                    if (setValue < 0 && !isRoundEdges) {

                        tempPlotfillAngle = plotfillAngle;
                        plotfillAngle = 360 - plotfillAngle;
                    }

                    // Setting the color Array to be applied to the bar/column.
                    config.colorArr = colorArr = lib.graphics.getColumnColor (
                            plotColor + COMMA + plotgradientcolor,
                            plotFillAlpha,
                            plotFillRatio,
                            plotfillAngle,
                            isRoundEdges,
                            plotBorderColor,
                            plotBorderAlpha.toString(),
                            0,
                            false
                            );

                    config.label = label=
                        getValidValue(parseUnsafeString(pluck (categories[i].tooltext, categories[i].label)));

                    // Parsing the hover effects only if showhovereffect is not 0.
                    if (showHoverEffect !== 0) {

                        upperBoxHoverColor = pluck(setData.upperboxhovercolor, JSONData.upperboxhovercolor,
                            chartAttr.upperboxhovercolor, upperBoxColor);

                        upperBoxHoverAlpha = pluck(setData.upperboxhoveralpha, JSONData.upperboxhoveralpha,
                            chartAttr.upperboxhoveralpha, upperBoxAlpha);

                        upperBoxBorderHoverColor = pluck(setData.upperboxborderhovercolor,
                            JSONData.upperboxborderhovercolor,
                            chartAttr.upperboxborderhovercolor, setData.upperboxbordercolor,
                            JSONData.upperboxbordercolor,
                            chartAttr.upperboxbordercolor, chartAttr.plotbordercolor,
                            colorM.getColor (PLOTBORDERCOLOR));

                        upperBoxBorderHoverAlpha = pluck(setData.upperboxborderhoveralpha,
                            JSONData.upperboxborderhoveralpha,
                            chartAttr.upperboxborderhoveralpha, setData.upperboxborderalpha,
                            JSONData.upperboxborderalpha,
                            chartAttr.upperboxborderalpha, chartAttr.plotborderalpha,
                            100);

                        upperBoxBorderHoverThickness = !isRoundEdges ? pluck(setData.upperboxborderhoverthickness,
                            JSONData.upperboxborderhoverthickness,
                            chartAttr.upperboxborderhoverthickness, config.upperBoxBorder.borderWidth) : 0;

                        lowerBoxHoverColor = pluck(setData.lowerboxhovercolor, JSONData.lowerboxhovercolor,
                            chartAttr.lowerboxhovercolor, lowerBoxColor);

                        lowerBoxHoverAlpha = pluck(setData.lowerboxhoveralpha, JSONData.lowerboxhoveralpha,
                            chartAttr.lowerboxhoveralpha, lowerBoxAlpha);

                        lowerBoxBorderHoverColor = pluck(setData.lowerboxborderhovercolor,
                            JSONData.lowerboxborderhovercolor,
                            chartAttr.lowerboxborderhovercolor, setData.lowerboxbordercolor,
                            JSONData.lowerboxbordercolor,
                            chartAttr.lowerboxbordercolor, chartAttr.plotbordercolor,
                            colorM.getColor (PLOTBORDERCOLOR));

                        lowerBoxBorderHoverAlpha = pluck(setData.lowerboxborderhoveralpha,
                            JSONData.lowerboxborderhoveralpha,
                            chartAttr.lowerboxborderhoveralpha, setData.lowerboxborderalpha,
                            JSONData.lowerboxborderalpha,
                            chartAttr.lowerboxborderalpha, chartAttr.plotborderalpha,
                            100);

                        lowerBoxBorderHoverThickness = !isRoundEdges ? pluck(setData.lowerboxborderhoverthickness,
                            JSONData.lowerboxborderhoverthickness,
                            chartAttr.lowerboxborderhoverthickness, config.lowerBoxBorder.borderWidth) : 0;

                        upperQuartileHoverColor = pluck(setData.upperquartilehovercolor,
                            JSONData.upperquartilehovercolor,
                            chartAttr.upperquartilehovercolor, setData.upperquartilecolor,
                            JSONData.upperquartilecolor,
                            chartAttr.upperquartilecolor, chartAttr.plotbordercolor,
                            colorM.getColor (PLOTBORDERCOLOR));

                        upperQuartileHoverAlpha = pluck(setData.upperquartilehoveralpha,
                            JSONData.upperquartilehoveralpha,
                            chartAttr.upperquartilehoveralpha, setData.upperquartilealpha,
                            JSONData.upperquartilealpha,
                            chartAttr.upperquartilealpha, chartAttr.plotborderalpha,
                            100);

                        upperQuartileHoverThickness = pluck(setData.upperquartilehoverthickness,
                            JSONData.upperquartilehoverthickness,
                            chartAttr.upperquartilehoverthickness, config.upperQuartile.borderWidth);

                        lowerQuartileHoverColor = pluck(setData.lowerquartilehovercolor,
                            JSONData.lowerquartilehovercolor,
                            chartAttr.lowerquartilehovercolor, setData.lowerquartilecolor,
                            JSONData.lowerquartilecolor,
                            chartAttr.lowerquartilecolor, chartAttr.plotbordercolor,
                            colorM.getColor (PLOTBORDERCOLOR));

                        lowerQuartileHoverAlpha = pluck(setData.lowerquartilehoveralpha,
                            JSONData.lowerquartilehoveralpha,
                            chartAttr.lowerquartilehoveralpha, setData.lowerquartilealpha,
                            JSONData.lowerquartilealpha,
                            chartAttr.lowerquartilealpha, chartAttr.plotborderalpha,
                            100);

                        lowerQuartileHoverThickness = pluck(setData.lowerquartilehoverthickness,
                            JSONData.lowerquartilehoverthickness,
                            chartAttr.lowerquartilehoverthickness, config.lowerQuartile.borderWidth);

                        medianHoverColor = pluck(setData.medianhovercolor,
                            JSONData.medianhovercolor,
                            chartAttr.medianhovercolor, setData.mediancolor,
                            JSONData.mediancolor,
                            chartAttr.mediancolor, chartAttr.plotbordercolor,
                            colorM.getColor (PLOTBORDERCOLOR));

                        medianHoverAlpha = pluck(setData.medianhoveralpha,
                            JSONData.medianhoveralpha,
                            chartAttr.medianhoveralpha, setData.medianalpha,
                            JSONData.medianalpha,
                            chartAttr.medianalpha, chartAttr.plotborderalpha,
                            100);

                        medianHoverThickness = pluck(setData.medianhoverthickness,
                            JSONData.medianhoverthickness,
                            chartAttr.medianhoverthickness, config.median.borderWidth);

                        /* If no hover effects are explicitly defined and
                         * showHoverEffect is not 0 then hoverColor is set.
                         */
                        if (showHoverEffect == 1) {
                            upperBoxColor === upperBoxHoverColor &&
                                (upperBoxHoverColor = getLightColor(upperBoxHoverColor, 70));
                            lowerBoxColor === lowerBoxHoverColor &&
                                (lowerBoxHoverColor = getLightColor(lowerBoxHoverColor, 70));

                        }

                        config.upperBoxHoverColorArr = lib.graphics.getColumnColor (
                            upperBoxHoverColor,
                            upperBoxHoverAlpha,
                            UNDEFINED,
                            UNDEFINED,
                            isRoundEdges,
                            plotBorderColor,
                            plotBorderAlpha.toString(),
                            0,
                            false
                            );

                        config.lowerBoxHoverColorArr = lib.graphics.getColumnColor (
                            lowerBoxHoverColor,
                            lowerBoxHoverAlpha,
                            UNDEFINED,
                            UNDEFINED,
                            isRoundEdges,
                            plotBorderColor,
                            plotBorderAlpha.toString(),
                            0,
                            false
                            );

                        config.setUpperBoxRolloutAttr = {
                            fill: toRaphaelColor(config.upperColorArr[0])
                        };
                        config.setUpperBoxRolloverAttr = {
                            fill: toRaphaelColor(config.upperBoxHoverColorArr[0])
                        };

                        config.setLowerBoxRolloutAttr = {
                            fill: toRaphaelColor(config.lowerColorArr[0])
                        };
                        config.setLowerBoxRolloverAttr = {
                            fill: toRaphaelColor(config.lowerBoxHoverColorArr[0])
                        };

                        config.setUpperBoxBorderRolloverAttr = {
                            stroke: convertColor(upperBoxBorderHoverColor, upperBoxBorderHoverAlpha),
                            'stroke-width': upperBoxBorderHoverThickness
                        };
                        config.setUpperBoxBorderRolloutAttr = {
                            stroke: config.upperBoxBorder.color,
                            'stroke-width': config.upperBoxBorder.borderWidth
                        };

                        config.setLowerBoxBorderRolloverAttr = {
                            stroke: convertColor(lowerBoxBorderHoverColor, lowerBoxBorderHoverAlpha),
                            'stroke-width': lowerBoxBorderHoverThickness
                        };
                        config.setLowerBoxBorderRolloutAttr = {
                            stroke: config.lowerBoxBorder.color,
                            'stroke-width': config.lowerBoxBorder.borderWidth
                        };

                        config.setUpperQuartileRolloverAttr = {
                            stroke: convertColor(upperQuartileHoverColor, upperQuartileHoverAlpha),
                            'stroke-width': upperQuartileHoverThickness
                        };
                        config.setUpperQuartileRolloutAttr = {
                            stroke: config.upperQuartile.color,
                            'stroke-width': config.upperQuartile.borderWidth
                        };

                        config.setLowerQuartileRolloverAttr = {
                            stroke: convertColor(lowerQuartileHoverColor, lowerQuartileHoverAlpha),
                            'stroke-width': lowerQuartileHoverThickness
                        };
                        config.setLowerQuartileRolloutAttr = {
                            stroke: config.lowerQuartile.color,
                            'stroke-width': config.lowerQuartile.borderWidth
                        };

                        config.setMedianRolloverAttr = {
                            stroke: convertColor(medianHoverColor, medianHoverAlpha),
                            'stroke-width': medianHoverThickness
                        };
                        config.setMedianRolloutAttr = {
                            stroke: config.median.color,
                            'stroke-width': config.median.borderWidth
                        };
                    }

                    formatedVal = config.toolTipValue;

                    // Parsing tooltext against various configurations provided by the user.
                    setTooltext = getValidValue(parseUnsafeString(pluck(setData.tooltext,
                        JSONData.plottooltext, chartAttr.plottooltext)));
                    if (!showTooltip) {
                        toolText = false;
                    }
                    else {
                        if (formatedVal === null) {
                            toolText = false;
                        }
                        else if (setTooltext !== UNDEFINED) {
                            macroIndices = [1, 2, 3, 4, 5, 6, 62, 63, 64, 65,
                                66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80
                            ];
                            parserConfig = {
                                maxValue: max,
                                maxDataValue: numberFormatter.dataLabels(max),
                                minValue: min,
                                minDataValue: numberFormatter.dataLabels(min),
                                Q1: numberFormatter.dataLabels(q1),
                                unformattedQ1: q1,
                                Q3: numberFormatter.dataLabels(q3),
                                unformattedQ3: q3,
                                median: numberFormatter.dataLabels(medianValue),
                                unformattedMedian: medianValue,

                                SD: numberFormatter.dataLabels(sd),
                                unformattedsd: sd,
                                QD: numberFormatter.dataLabels(qd),
                                unformattedQD: qd,
                                MD: numberFormatter.dataLabels(md),
                                unformattedMD: md,
                                mean: numberFormatter.dataLabels(mean),
                                unformattedMean: mean,
                                label: label,
                                yaxisName: yAxisName,
                                xaxisName: xAxisName,
                                formattedValue: formatedVal,
                                value: label
                            };
                            toolText = parseTooltext(setTooltext, macroIndices,
                                parserConfig, setData, chartAttr, JSONData);
                        }
                        else {
                            toolText = BOLDSTARTTAG + MAXIMUM_STR + tooltipSepChar + BOLDENDTAG +
                                numberFormatter.dataLabels(max) + BREAKSTRING +
                                BOLDSTARTTAG + Q3_STR + tooltipSepChar + BOLDENDTAG +
                                numberFormatter.dataLabels(q3) + BREAKSTRING +
                                BOLDSTARTTAG + MEDIAN_STR + tooltipSepChar + BOLDENDTAG +
                                numberFormatter.dataLabels(medianValue) + BREAKSTRING +
                                BOLDSTARTTAG + Q1_STR + tooltipSepChar + BOLDENDTAG +
                                numberFormatter.dataLabels(q1) + BREAKSTRING +
                                BOLDSTARTTAG + MINIMUM_STR + tooltipSepChar + BOLDENDTAG +
                                numberFormatter.dataLabels(min);
                        }
                    }
                    config.toolText = toolText;
                    config.setTooltext = toolText;
                    tempPlotfillAngle && (plotfillAngle = tempPlotfillAngle);
                }

                conf.maxNumberOfOutliers = maxNumberOfOutliers;

                conf.maxValue = maxValue;
                conf.minValue = minValue;

                if (!showAllOutliers) {
                    difference = maxValue - minValue;
                    conf.maxValue += (conf.outliersupperrangeratio * difference);
                    conf.minValue -= (conf.outlierslowerrangeratio * difference);
                }

                (chart.hasLegend !== false) && dataSet._addLegend();

                dataSet.subDS = 0;

                (dataSet.components.mean = dataSet._createSubDS(0, MEAN_STR));

                conf.showMeanLegend && (dataSet._addLegendSubDS(dataSet.components.mean));
                conf.showMeanLegend && (dataSet.subDS += 1);

                (dataSet.components.sd = dataSet._createSubDS(1, SD_STR));
                conf.showSDLegend && (dataSet._addLegendSubDS(dataSet.components.sd));
                conf.showSDLegend && (dataSet.subDS += 1);

                (dataSet.components.md = dataSet._createSubDS(2, MD_STR));
                conf.showMDLegend && (dataSet._addLegendSubDS(dataSet.components.md));
                conf.showMDLegend && (dataSet.subDS += 1);

                (dataSet.components.qd = dataSet._createSubDS(3, QD_STR));
                conf.showQDLegend && (dataSet._addLegendSubDS(dataSet.components.qd));
                conf.showQDLegend && (dataSet.subDS += 1);

                !dataSet.components.outliers && (dataSet.components.outliers = []);

                OutliersLength = dataSet.config.maxNumberOfOutliers || dataSet.components.outliers.length;

                for (i = 0; i < OutliersLength; i++) {
                    outlierDS = (dataSet._createSubDS(4 + i, OUTLIERS_STR, i));
                    dataSet.components.outliers[i] = outlierDS;
                }
                conf.showOutliersLegend && (dataSet._addLegendOutliers(dataSet.components.outliers));
                conf.showOutliersLegend && (dataSet.subDS += 1);
            },

            _createSubDS : function (index, name, outlierIndex) {
                var dataSet = this,
                    chart = dataSet.chart,

                    dataObj = chart.jsonData,
                    dataset = dataObj.dataset,
                    length = dataset && dataset.length,

                    subDSIndex,
                    dsType = 'subDS',
                    components = dataSet.components,
                    datasetStore,
                    DsClass,
                    datasetObj,
                    JSONData,
                    legend = chart.components.legend,
                    dsCount = {};

                datasetStore = components.dataset  || (components.dataset = []);

                subDSIndex = (length * (index + 1)) + dataSet.index;

                if (!datasetStore[index]) {
                    DsClass = FusionCharts.get(COMPONENT, [DATASET, dsType]);
                    if (DsClass) {
                        if (dsCount[dsType] === UNDEFINED) {
                            dsCount[dsType] = 0;
                        }
                        else {
                            dsCount[dsType]++;
                        }

                        // create the dataset Object
                        datasetObj = new DsClass();
                        datasetObj.chart = chart;
                        datasetObj.index = subDSIndex;
                        datasetStore.push(datasetObj);
                        JSONData = extend2({}, dataSet.JSONData);
                        dataSet.initSubDataset(JSONData, datasetObj);
                        datasetObj.name = name;
                    }
                }
                else {
                    datasetObj = datasetStore[index];
                    datasetObj.index = subDSIndex;
                    JSONData = extend2({}, dataSet.JSONData);
                    datasetObj.JSONData = JSONData;
                }

                // JSONData = extend2({}, dataSet.JSONData);
                // dataSet.initSubDataset(JSONData, datasetObj);

                switch(index) {
                    case 0:
                        dataSet.configureMean(datasetObj);
                        // if (!dataSet.config.showMeanLegend) {
                        //     legendItems.pop();
                        // }
                        !dataSet.config.showMeanLegend && legend.removeItem(datasetObj.legendItemId);
                        break;
                    case 1:
                        dataSet.configureSD(datasetObj);
                        !dataSet.config.showQDLegend && legend.removeItem(datasetObj.legendItemId);
                        break;
                    case 2:
                        dataSet.configureMD(datasetObj);
                        !dataSet.config.showMDLegend && legend.removeItem(datasetObj.legendItemId);
                        break;
                    case 3:
                        dataSet.configureQD(datasetObj);
                        !dataSet.config.showQDLegend && legend.removeItem(datasetObj.legendItemId);
                        break;
                    default:
                        dataSet.configureOutliers(datasetObj, outlierIndex);
                        !dataSet.config.showOutliersLegend &&
                            legend.removeItem(dataSet.components.outliers.legendItemId);
                        break;
                }

                return datasetObj;
            },

            configureMean: function (dataSet) {
                var chart = dataSet.chart,
                    chartComponents = chart.components,
                    parseUnsafeString = lib.parseUnsafeString,
                    conf = dataSet.config,
                    JSONData = dataSet.JSONData,
                    chartAttr = chart.jsonData.chart,
                    singleSeries = chart.singleseries,
                    colorM = chartComponents.colorManager,
                    index = dataSet.index || dataSet.stackIndex,
                    plotType = dataSet.type,
                    // showplotborder = pluckNumber(JSONData.showplotborder, chartAttr.showplotborder || 1),
                    plotFillColor = !singleSeries || getValidValue(chartAttr.palettecolors) ?
                        colorM.getPlotColor(index) : colorM.getColor(PLOTFILLCOLOR_STR).split(/\s*\,\s*/)[0],
                    // plotBorderDash,
                    // usePlotGradientColor,
                    setDataArr = JSONData.data,
                    setData,
                    dataObj,
                    dataSetLen = setDataArr && setDataArr.length,
                    categories = chart.config.categories,
                    catLen = categories && categories.length,
                    len = mathMin(catLen, dataSetLen),
                    dataStore,
                    // areaAlpha = chart.areaAlpha,
                    numberFormatter = chartComponents.numberFormatter,
                    config,
                    i,
                    toolText,
                    use3dlineshift = chart.use3dlineshift,
                    toolTipValue,
                    setValue,
                    setDisplayValue,
                    formatedVal,
                    maxValue = -Infinity,
                    minValue = +Infinity,
                    parentYAxis,
                    enableAnimation,
                    lineDashStyle,
                    stack100Percent,
                    defaultShadow,
                    tooltipSepChar = pluck(chartAttr.tooltipsepchar, ': '),
                    lineDashed = pluckNumber(JSONData.dashed, chartAttr.linedashed),
                    isStacked = chart.isStacked,
                    hasLineSet = chart.hasLineSet,
                    catObj,
                    xAxis = chartComponents.xAxis[0],
                    meanIconShape,
                    thisConfig;

                dataSet.visible = pluckNumber(dataSet.JSONData.visible,
                    !Number(dataSet.JSONData.initiallyhidden), 1) === 1;

                if (use3dlineshift !== UNDEFINED) {
                    conf.use3dlineshift = pluckNumber(chartAttr.use3dlineshift, use3dlineshift);
                }
                else {
                    conf.use3dlineshift = 1;
                }
                conf.plotColor = plotFillColor;
                conf.legendSymbolColor = conf.plotColor;
                defaultShadow = pluckNumber(chart.defaultPlotShadow, colorM.getColor(SHOWSHADOW));

                // Functional attributes configuration

                conf.drawFullAreaBorder = pluckNumber(chartAttr.drawfullareaborder, 1);
                // ParentYAxis is always 1 for lineset
                if (hasLineSet) {
                    conf.parentYAxis = parentYAxis = 1;
                }
                else {
                    conf.parentYAxis = parentYAxis = pluck(JSONData.parentyaxis && JSONData.parentyaxis.toLowerCase(),
                    pStr) === sStr ? 1 : 0 ;
                }
                conf.connectNullData = pluckNumber(chartAttr.connectnulldata, 0);

                // Animation related attributes configuration
                conf.enableAnimation = enableAnimation = pluckNumber(chartAttr.animation,
                    chartAttr.defaultanimation, 1);
                conf.animation = !enableAnimation ? false : {
                    duration: pluckNumber(chartAttr.animationduration, 1) * 1000
                };
                conf.transposeanimation = pluckNumber(chartAttr.transposeanimation, enableAnimation);
                conf.transposeanimduration = pluckNumber(chartAttr.transposeanimduration, 0.2) * 1000;

                // Value related configurations
                conf.showValues = 0;
                conf.valuePadding = pluckNumber(chartAttr.valuepadding, 2);
                conf.valuePosition = pluck(JSONData.valueposition, chartAttr.valueposition, 'auto');
                conf.stack100Percent = stack100Percent = pluckNumber(chartAttr.stack100percent, 0),
                conf.showPercentValues = pluckNumber(chartAttr.showpercentvalues, (isStacked && stack100Percent) ?
                    1 : 0);
                conf.showPercentInToolTip = pluckNumber(chartAttr.showpercentintooltip,
                    (isStacked && stack100Percent) ? 1 : 0);

                // Tooltip related attributes
                conf.showTooltip = pluckNumber(chartAttr.showtooltip, 1);
                conf.seriesNameInTooltip = pluckNumber(chartAttr.seriesnameintooltip, 1);

                conf.showHoverEffect = pluckNumber(chartAttr.plothovereffect, chartAttr.anchorhovereffect,
                    chartAttr.showhovereffect, UNDEFINED);

                conf.rotateValues = pluckNumber(chartAttr.rotatevalues) ? 270 : 0;
                // Line configuration attributes parsing
                conf.linethickness = pluckNumber(JSONData.linethickness,
                     chartAttr.linethickness, 1);
                conf.lineDashLen = pluckNumber(JSONData.linedashlen, chartAttr.linedashlen, 5);
                conf.lineDashGap = pluckNumber(JSONData.linedashgap, chartAttr.linedashgap, 4);
                conf.drawLine = conf.alpha =
                    pluckNumber(chartAttr.drawmeanconnector, JSONData.drawmeanconnector, 0) && 100;

                lineDashStyle = lib.getDashStyle(conf.lineDashLen, conf.lineDashGap, conf.linethickness);
                conf.lineDashStyle = lineDashed ?
                        lineDashStyle : NONE;

                conf.shadow = {
                    opacity: pluckNumber(chartAttr.showshadow, defaultShadow) ?
                        (plotType === LINE ? conf.alpha/100 :
                        conf.plotBorderAlpha/100) : 0
                };
                // Anchor cosmetics attributes in dataset level
                conf.drawAnchors = pluckNumber(JSONData.drawanchors, JSONData.showanchors, chartAttr.drawanchors,
                    chartAttr.showanchors);

                conf.anchorBgColor = pluck(JSONData.meaniconcolor,
                    chartAttr.meaniconcolor, COLOR_000000);
                conf.anchorBorderColor = COLOR_000000;
                conf.anchorRadius = pluckNumber(JSONData.meaniconradius, chartAttr.meaniconradius, 5);
                conf.anchorAlpha = pluck(JSONData.alpha,
                    JSONData.meaniconalpha, chartAttr.meaniconalpha);
                conf.anchorBgAlpha = pluck(JSONData.meaniconalpha, chartAttr.meaniconalpha, 100);
                conf.anchorBorderThickness = pluck(JSONData.anchorborderthickness,
                    chartAttr.anchorborderthickness, 1);
                conf.anchorSides = pluck(JSONData.meaniconsides, chartAttr.meaniconsides, 3);

                conf.linecolor = conf.anchorBgColor;

                // Spline attributes
                conf.minimizeTendency = pluckNumber(chartAttr.minimizetendency,chartAttr.minimisetendency,0);

                // Anchor image cosmetics attributes
                conf.anchorImageUrl = pluck(JSONData.anchorimageurl, chartAttr.anchorimageurl);
                conf.anchorImageAlpha = pluckNumber(JSONData.anchorimagealpha, chartAttr.anchorimagealpha, 100);
                conf.anchorImageScale = pluckNumber(JSONData.anchorimagescale, chartAttr.anchorimagescale, 100);
                conf.anchorImagePadding = pluckNumber(JSONData.anchorimagepadding, chartAttr.anchorimagepadding, 1);
                conf.anchorStartAngle = pluckNumber(JSONData.anchorstartangle, chartAttr.anchorstartangle, 90);
                conf.anchorShadow = pluckNumber(JSONData.anchorshadow, chartAttr.anchorshadow, 0);

                !dataSet.components.data && (dataSet.components.data = []);
                dataStore = dataSet.components.data;

                for (i=0; i<len; i++) {
                    setData = setDataArr && setDataArr[i];
                    dataObj = dataStore[i] =  dataStore[i] || {};
                    dataObj.config = dataObj.config || {};
                    config = dataObj.config;
                    thisConfig = this.components.data[i].config;

                    if (thisConfig.showMean) {
                        setData.value = thisConfig.mean;
                    }
                    else {
                        setData.value = null;
                    }

                    config.x = this.components.data[i]._xPos;

                    config.setValue = setValue = numberFormatter.getCleanValue(setData.value);
                    config.setLink  = pluck(setData.link);
                    // Parsing the anchor properties for set level
                    config.anchorProps = this._parseAnchorProperties(i, dataSet, meanStr);
                    catObj = xAxis.getLabel(i);
                    config.label = lib.getValidValue(parseUnsafeString(pluck(catObj.tooltext,
                        catObj.label, catObj.name)));
                    config.showValue = 0;

                    // Dashed, color and alpha configuration in set level is only for line chart
                    config.dashed = pluckNumber(setData.dashed, lineDashed);
                    config.color = pluck(setData.color, conf.lineColor);
                    config.alpha = pluck(setData.alpha, setData.alpha, conf.alpha);
                    maxValue = mathMax(maxValue, setValue);
                    minValue = mathMin(minValue, setValue);
                    config.dashStyle = config.dashed ? lineDashStyle : NONE;
                    config.toolTipValue = toolTipValue = numberFormatter.dataLabels(setValue, parentYAxis);
                    config.setDisplayValue = setDisplayValue = parseUnsafeString(setData.displayvalue);
                    config.displayValue = pluck(setDisplayValue, toolTipValue);
                    config.formatedVal = formatedVal = config.toolTipValue;
                    config.setTooltext = lib.getValidValue(parseUnsafeString(pluck(setData.tooltext,
                       JSONData.plottooltext, chartAttr.plottooltext)));

                    meanIconShape = pluck(setData.meaniconshape, JSONData.meaniconshape,
                                        chartAttr.meaniconshape, POLYGON);
                    conf.dip = config.dip = (meanIconShape === POLYGON) ? 0 : (meanIconShape === SPOKE) ? 1 : 0;
                    // Initial tooltext parsing

                    if (!conf.showTooltip) {
                        toolText = false;
                    }
                    else {
                        toolText = BOLDSTARTTAG + MEAN_STR + tooltipSepChar + BOLDENDTAG;
                    }
                    config.toolText = toolText;
                    // Storing the initial parsed tooltext which will be later used in stack100percent calculations
                    // on legend click
                    config.setTooltext = toolText;
                    if (!dataObj) {
                        dataObj = dataStore[i] = {
                            graphics : {}
                        };
                    }
                    else if (!dataObj.graphics) {
                        dataStore[i].graphics = {};

                    }
                    config.hoverEffects = {
                        enabled: false
                    };
                }
                conf.maxValue = maxValue;
                conf.minValue = minValue;
            },

            configureSD: function (dataSet) {
                var chart = dataSet.chart,
                    chartComponents = chart.components,
                    parseUnsafeString = lib.parseUnsafeString,
                    conf = dataSet.config,
                    JSONData = dataSet.JSONData,
                    chartAttr = chart.jsonData.chart,
                    singleSeries = chart.singleseries,
                    colorM = chartComponents.colorManager,
                    index = dataSet.index || dataSet.stackIndex,
                    plotType = dataSet.type,
                    plotFillColor = !singleSeries || getValidValue(chartAttr.palettecolors) ?
                        colorM.getPlotColor(index) : colorM.getColor(PLOTFILLCOLOR_STR).split(/\s*\,\s*/)[0],
                    setDataArr = JSONData.data,
                    setData,
                    dataObj,
                    dataSetLen = setDataArr && setDataArr.length,
                    categories = chart.config.categories,
                    catLen = categories && categories.length,
                    len = mathMin(catLen, dataSetLen),
                    dataStore,
                    numberFormatter = chartComponents.numberFormatter,
                    config,
                    i,
                    toolText,
                    use3dlineshift = chart.use3dlineshift,
                    toolTipValue,
                    setValue,
                    setDisplayValue,
                    formatedVal,
                    maxValue = -Infinity,
                    minValue = +Infinity,
                    parentYAxis,
                    enableAnimation,
                    lineDashStyle,
                    stack100Percent,
                    defaultShadow,
                    tooltipSepChar = pluck(chartAttr.tooltipsepchar, ': '),
                    lineDashed = pluckNumber(JSONData.dashed, chartAttr.linedashed),
                    isStacked = chart.isStacked,
                    hasLineSet = chart.hasLineSet,
                    catObj,
                    xAxis = chartComponents.xAxis[0],
                    SDIconShape,
                    thisConfig;

                dataSet.visible = pluckNumber(dataSet.JSONData.visible,
                    !Number(dataSet.JSONData.initiallyhidden), 1) === 1;

                if (use3dlineshift !== UNDEFINED) {
                    conf.use3dlineshift = pluckNumber(chartAttr.use3dlineshift, use3dlineshift);
                }
                else {
                    conf.use3dlineshift = 1;
                }
                conf.plotColor = plotFillColor;
                conf.legendSymbolColor = conf.plotColor;
                defaultShadow = pluckNumber(chart.defaultPlotShadow, colorM.getColor(SHOWSHADOW));

                // Functional attributes configuration

                conf.drawFullAreaBorder = pluckNumber(chartAttr.drawfullareaborder, 1);
                // ParentYAxis is always 1 for lineset
                if (hasLineSet) {
                    conf.parentYAxis = parentYAxis = 1;
                }
                else {
                    conf.parentYAxis = parentYAxis = pluck(JSONData.parentyaxis && JSONData.parentyaxis.toLowerCase(),
                    pStr) === sStr ? 1 : 0 ;
                }
                conf.connectNullData = pluckNumber(chartAttr.connectnulldata, 0);

                // Animation related attributes configuration
                conf.enableAnimation = enableAnimation = pluckNumber(chartAttr.animation,
                    chartAttr.defaultanimation, 1);
                conf.animation = !enableAnimation ? false : {
                    duration: pluckNumber(chartAttr.animationduration, 1) * 1000
                };
                conf.transposeanimation = pluckNumber(chartAttr.transposeanimation, enableAnimation);
                conf.transposeanimduration = pluckNumber(chartAttr.transposeanimduration, 0.2) * 1000;

                // Value related configurations
                conf.showValues = 0;
                conf.valuePadding = pluckNumber(chartAttr.valuepadding, 2);
                conf.valuePosition = pluck(JSONData.valueposition, chartAttr.valueposition, 'auto');
                conf.stack100Percent = stack100Percent = pluckNumber(chartAttr.stack100percent, 0),
                conf.showPercentValues = pluckNumber(chartAttr.showpercentvalues, (isStacked && stack100Percent) ?
                    1 : 0);
                conf.showPercentInToolTip = pluckNumber(chartAttr.showpercentintooltip,
                    (isStacked && stack100Percent) ? 1 : 0);

                // Tooltip related attributes
                conf.showTooltip = pluckNumber(chartAttr.showtooltip, 1);
                conf.seriesNameInTooltip = pluckNumber(chartAttr.seriesnameintooltip, 1);

                conf.showHoverEffect = pluckNumber(chartAttr.plothovereffect, chartAttr.anchorhovereffect,
                    chartAttr.showhovereffect, UNDEFINED);

                conf.rotateValues = pluckNumber(chartAttr.rotatevalues) ? 270 : 0;
                // Line configuration attributes parsing
                conf.linethickness = pluckNumber(JSONData.linethickness,
                     chartAttr.linethickness, 1);
                conf.lineDashLen = pluckNumber(JSONData.linedashlen, chartAttr.linedashlen, 5);
                conf.lineDashGap = pluckNumber(JSONData.linedashgap, chartAttr.linedashgap, 4);
                conf.drawLine = conf.alpha =
                    pluckNumber(chartAttr.drawsdconnector, JSONData.drawsdconnector, 0) && 100;

                lineDashStyle = lib.getDashStyle(conf.lineDashLen, conf.lineDashGap, conf.linethickness);
                conf.lineDashStyle = lineDashed ?
                        lineDashStyle : NONE;

                conf.shadow = {
                    opacity: pluckNumber(chartAttr.showshadow, defaultShadow) ?
                        (plotType === LINE ? conf.alpha/100 :
                        conf.plotBorderAlpha/100) : 0
                };
                // Anchor cosmetics attributes in dataset level
                conf.drawAnchors = pluckNumber(JSONData.drawanchors, JSONData.showanchors, chartAttr.drawanchors,
                    chartAttr.showanchors);

                conf.anchorBgColor = pluck(JSONData.sdiconcolor,
                    chartAttr.sdiconcolor, COLOR_000000);
                conf.anchorBorderColor = COLOR_000000;
                conf.anchorRadius = pluckNumber(JSONData.sdiconradius, chartAttr.sdiconradius, 5);
                conf.anchorAlpha = pluck(JSONData.alpha,
                    JSONData.sdiconalpha, chartAttr.sdiconalpha);
                conf.anchorBgAlpha = pluck(JSONData.sdiconalpha, chartAttr.sdiconalpha, 100);
                conf.anchorBorderThickness = pluck(JSONData.anchorborderthickness,
                    chartAttr.anchorborderthickness, 1);
                conf.anchorSides = pluck(JSONData.sdiconsides, chartAttr.sdiconsides, 3);

                conf.linecolor = conf.anchorBgColor;

                // Spline attributes
                conf.minimizeTendency = pluckNumber(chartAttr.minimizetendency,chartAttr.minimisetendency,0);

                // Anchor image cosmetics attributes
                conf.anchorImageUrl = pluck(JSONData.anchorimageurl, chartAttr.anchorimageurl);
                conf.anchorImageAlpha = pluckNumber(JSONData.anchorimagealpha, chartAttr.anchorimagealpha, 100);
                conf.anchorImageScale = pluckNumber(JSONData.anchorimagescale, chartAttr.anchorimagescale, 100);
                conf.anchorImagePadding = pluckNumber(JSONData.anchorimagepadding, chartAttr.anchorimagepadding, 1);
                conf.anchorStartAngle = pluckNumber(JSONData.anchorstartangle, chartAttr.anchorstartangle, 90);
                conf.anchorShadow = pluckNumber(JSONData.anchorshadow, chartAttr.anchorshadow, 0);
                !dataSet.components.data && (dataSet.components.data = []);
                dataStore = dataSet.components.data;

                for (i=0; i<len; i++) {
                    setData = setDataArr && setDataArr[i];
                    dataObj = dataStore[i] =  dataStore[i] || {};
                    dataObj.config = dataObj.config || {};
                    config = dataObj.config;
                    thisConfig = this.components.data[i].config;

                    if (thisConfig.showSD) {
                        setData.value = thisConfig.sd;
                    }
                    else {
                        setData.value = null;
                    }

                    config.x = this.components.data[i]._xPos;

                    config.setValue = setValue = numberFormatter.getCleanValue(setData.value);
                    config.setLink  = pluck(setData.link);
                    // Parsing the anchor properties for set level
                    config.anchorProps = this._parseAnchorProperties(i, dataSet, sdStr);
                    catObj = xAxis.getLabel(i);
                    config.label = lib.getValidValue(parseUnsafeString(pluck(catObj.tooltext,
                        catObj.label, catObj.name)));
                    config.showValue = 0;

                    // Dashed, color and alpha configuration in set level is only for line chart
                    config.dashed = pluckNumber(setData.dashed, lineDashed);
                    config.color = pluck(setData.color, conf.lineColor);
                    config.alpha = pluck(setData.alpha, setData.alpha, conf.alpha);
                    maxValue = mathMax(maxValue, setValue);
                    minValue = mathMin(minValue, setValue);
                    config.dashStyle = config.dashed ? lineDashStyle : NONE;
                    config.toolTipValue = toolTipValue = numberFormatter.dataLabels(setValue, parentYAxis);
                    config.setDisplayValue = setDisplayValue = parseUnsafeString(setData.displayvalue);
                    config.displayValue = pluck(setDisplayValue, toolTipValue);
                    config.formatedVal = formatedVal = config.toolTipValue;
                    config.setTooltext = lib.getValidValue(parseUnsafeString(pluck(setData.tooltext,
                       JSONData.plottooltext, chartAttr.plottooltext)));
                    SDIconShape = pluck(setData.sdiconshape, JSONData.sdiconshape,
                                        chartAttr.sdiconshape, POLYGON);
                    conf.dip = config.dip = (SDIconShape === POLYGON) ? 0 : (SDIconShape === SPOKE) ? 1 : 0;
                    // Initial tooltext parsing

                    if (!conf.showTooltip) {
                        toolText = false;
                    }
                    else {
                        if (formatedVal === null) {
                            toolText = false;
                        }
                        else {
                            toolText = BOLDSTARTTAG + SD_STR + tooltipSepChar + BOLDENDTAG;
                        }
                    }
                    config.toolText = toolText;
                    // Storing the initial parsed tooltext which will be later used in stack100percent calculations
                    // on legend click
                    config.setTooltext = toolText;
                    if (!dataObj) {
                        dataObj = dataStore[i] = {
                            graphics : {}
                        };
                    }
                    else if (!dataObj.graphics) {
                        dataStore[i].graphics = {};

                    }
                    config.hoverEffects = {
                        enabled: false
                    };
                }
                conf.maxValue = maxValue;
                conf.minValue = minValue;
            },

            configureMD: function (dataSet) {
                var chart = dataSet.chart,
                    chartComponents = chart.components,
                    parseUnsafeString = lib.parseUnsafeString,
                    conf = dataSet.config,
                    JSONData = dataSet.JSONData,
                    chartAttr = chart.jsonData.chart,
                    singleSeries = chart.singleseries,
                    colorM = chartComponents.colorManager,
                    index = dataSet.index || dataSet.stackIndex,
                    plotType = dataSet.type,
                    plotFillColor = !singleSeries || getValidValue(chartAttr.palettecolors) ?
                        colorM.getPlotColor(index) : colorM.getColor(PLOTFILLCOLOR_STR).split(/\s*\,\s*/)[0],
                    setDataArr = JSONData.data,
                    setData,
                    dataObj,
                    dataSetLen = setDataArr && setDataArr.length,
                    categories = chart.config.categories,
                    catLen = categories && categories.length,
                    len = mathMin(catLen, dataSetLen),
                    dataStore,
                    numberFormatter = chartComponents.numberFormatter,
                    config,
                    i,
                    toolText,
                    use3dlineshift = chart.use3dlineshift,
                    toolTipValue,
                    setValue,
                    setDisplayValue,
                    formatedVal,
                    maxValue = -Infinity,
                    minValue = +Infinity,
                    parentYAxis,
                    enableAnimation,
                    lineDashStyle,
                    stack100Percent,
                    defaultShadow,
                    tooltipSepChar = pluck(chartAttr.tooltipsepchar, ': '),
                    lineDashed = pluckNumber(JSONData.dashed, chartAttr.linedashed),
                    isStacked = chart.isStacked,
                    hasLineSet = chart.hasLineSet,
                    catObj,
                    xAxis = chartComponents.xAxis[0],
                    MDIconShape,
                    thisConfig;

                dataSet.visible = pluckNumber(dataSet.JSONData.visible,
                    !Number(dataSet.JSONData.initiallyhidden), 1) === 1;

                if (use3dlineshift !== UNDEFINED) {
                    conf.use3dlineshift = pluckNumber(chartAttr.use3dlineshift, use3dlineshift);
                }
                else {
                    conf.use3dlineshift = 1;
                }
                conf.plotColor = plotFillColor;
                conf.legendSymbolColor = conf.plotColor;
                defaultShadow = pluckNumber(chart.defaultPlotShadow, colorM.getColor(SHOWSHADOW));

                // Functional attributes configuration

                conf.drawFullAreaBorder = pluckNumber(chartAttr.drawfullareaborder, 1);
                // ParentYAxis is always 1 for lineset
                if (hasLineSet) {
                    conf.parentYAxis = parentYAxis = 1;
                }
                else {
                    conf.parentYAxis = parentYAxis = pluck(JSONData.parentyaxis && JSONData.parentyaxis.toLowerCase(),
                    pStr) === sStr ? 1 : 0 ;
                }
                conf.connectNullData = pluckNumber(chartAttr.connectnulldata, 0);

                // Animation related attributes configuration
                conf.enableAnimation = enableAnimation = pluckNumber(chartAttr.animation,
                    chartAttr.defaultanimation, 1);
                conf.animation = !enableAnimation ? false : {
                    duration: pluckNumber(chartAttr.animationduration, 1) * 1000
                };
                conf.transposeanimation = pluckNumber(chartAttr.transposeanimation, enableAnimation);
                conf.transposeanimduration = pluckNumber(chartAttr.transposeanimduration, 0.2) * 1000;

                // Value related configurations
                conf.showValues = 0;
                conf.valuePadding = pluckNumber(chartAttr.valuepadding, 2);
                conf.valuePosition = pluck(JSONData.valueposition, chartAttr.valueposition, 'auto');
                conf.stack100Percent = stack100Percent = pluckNumber(chartAttr.stack100percent, 0),
                conf.showPercentValues = pluckNumber(chartAttr.showpercentvalues, (isStacked && stack100Percent) ?
                    1 : 0);
                conf.showPercentInToolTip = pluckNumber(chartAttr.showpercentintooltip,
                    (isStacked && stack100Percent) ? 1 : 0);

                // Tooltip related attributes
                conf.showTooltip = pluckNumber(chartAttr.showtooltip, 1);
                conf.seriesNameInTooltip = pluckNumber(chartAttr.seriesnameintooltip, 1);

                conf.showHoverEffect = pluckNumber(chartAttr.plothovereffect, chartAttr.anchorhovereffect,
                    chartAttr.showhovereffect, UNDEFINED);

                conf.rotateValues = pluckNumber(chartAttr.rotatevalues) ? 270 : 0;
                // Line configuration attributes parsing
                conf.linethickness = pluckNumber(JSONData.linethickness,
                     chartAttr.linethickness, 1);
                conf.lineDashLen = pluckNumber(JSONData.linedashlen, chartAttr.linedashlen, 5);
                conf.lineDashGap = pluckNumber(JSONData.linedashgap, chartAttr.linedashgap, 4);
                conf.drawLine = conf.alpha =
                    pluckNumber(chartAttr.drawmdconnector, JSONData.drawmdconnector, 0) && 100;

                lineDashStyle = lib.getDashStyle(conf.lineDashLen, conf.lineDashGap, conf.linethickness);
                conf.lineDashStyle = lineDashed ?
                        lineDashStyle : NONE;

                conf.shadow = {
                    opacity: pluckNumber(chartAttr.showshadow, defaultShadow) ?
                        (plotType === LINE ? conf.alpha/100 :
                        conf.plotBorderAlpha/100) : 0
                };
                // Anchor cosmetics attributes in dataset level
                conf.drawAnchors = pluckNumber(JSONData.drawanchors, JSONData.showanchors, chartAttr.drawanchors,
                    chartAttr.showanchors);

                conf.anchorBgColor = pluck(JSONData.mdiconcolor,
                    chartAttr.mdiconcolor, COLOR_000000);
                conf.anchorBorderColor = COLOR_000000;
                conf.anchorRadius = pluckNumber(JSONData.mdiconradius, chartAttr.mdiconradius, 5);
                conf.anchorAlpha = pluck(JSONData.alpha,
                    JSONData.mdiconalpha, chartAttr.mdiconalpha);
                conf.anchorBgAlpha = pluck(JSONData.mdiconalpha, chartAttr.mdiconalpha, 100);
                conf.anchorBorderThickness = pluck(JSONData.anchorborderthickness,
                    chartAttr.anchorborderthickness, 1);
                conf.anchorSides = pluck(JSONData.mdiconsides, chartAttr.mdiconsides, 3);

                conf.linecolor = conf.anchorBgColor;

                // Spline attributes
                conf.minimizeTendency = pluckNumber(chartAttr.minimizetendency,chartAttr.minimisetendency,0);

                // Anchor image cosmetics attributes
                conf.anchorImageUrl = pluck(JSONData.anchorimageurl, chartAttr.anchorimageurl);
                conf.anchorImageAlpha = pluckNumber(JSONData.anchorimagealpha, chartAttr.anchorimagealpha, 100);
                conf.anchorImageScale = pluckNumber(JSONData.anchorimagescale, chartAttr.anchorimagescale, 100);
                conf.anchorImagePadding = pluckNumber(JSONData.anchorimagepadding, chartAttr.anchorimagepadding, 1);
                conf.anchorStartAngle = pluckNumber(JSONData.anchorstartangle, chartAttr.anchorstartangle, 90);
                conf.anchorShadow = pluckNumber(JSONData.anchorshadow, chartAttr.anchorshadow, 0);
                !dataSet.components.data && (dataSet.components.data = []);
                dataStore = dataSet.components.data;

                for (i=0; i<len; i++) {
                    setData = setDataArr && setDataArr[i];
                    dataObj = dataStore[i] =  dataStore[i] || {};
                    dataObj.config = dataObj.config || {};
                    config = dataObj.config;
                    thisConfig = this.components.data[i].config;

                    if (thisConfig.showMD) {
                        setData.value = thisConfig.md;
                    }
                    else {
                        setData.value = null;
                    }

                    config.x = this.components.data[i]._xPos;

                    config.setValue = setValue = numberFormatter.getCleanValue(setData.value);
                    config.setLink  = pluck(setData.link);
                    // Parsing the anchor properties for set level
                    config.anchorProps = this._parseAnchorProperties(i, dataSet, mdStr);
                    catObj = xAxis.getLabel(i);
                    config.label = lib.getValidValue(parseUnsafeString(pluck(catObj.tooltext,
                        catObj.label, catObj.name)));
                    config.showValue = 0;

                    // Dashed, color and alpha configuration in set level is only for line chart
                    config.dashed = pluckNumber(setData.dashed, lineDashed);
                    config.color = pluck(setData.color, conf.lineColor);
                    config.alpha = pluck(setData.alpha, setData.alpha, conf.alpha);
                    maxValue = mathMax(maxValue, setValue);
                    minValue = mathMin(minValue, setValue);
                    config.dashStyle = config.dashed ? lineDashStyle : NONE;
                    config.toolTipValue = toolTipValue = numberFormatter.dataLabels(setValue, parentYAxis);
                    config.setDisplayValue = setDisplayValue = parseUnsafeString(setData.displayvalue);
                    config.displayValue = pluck(setDisplayValue, toolTipValue);
                    config.formatedVal = formatedVal = config.toolTipValue;
                    config.setTooltext = lib.getValidValue(parseUnsafeString(pluck(setData.tooltext,
                       JSONData.plottooltext, chartAttr.plottooltext)));
                    MDIconShape = pluck(setData.mdiconshape, JSONData.mdiconshape,
                                        chartAttr.mdiconshape, POLYGON);
                    conf.dip = config.dip = (MDIconShape === POLYGON) ? 0 : (MDIconShape === SPOKE) ? 1 : 0;
                    // Initial tooltext parsing

                    if (!conf.showTooltip) {
                        toolText = false;
                    }
                    else {
                        toolText = BOLDSTARTTAG + MD_STR + tooltipSepChar + BOLDENDTAG;
                    }
                    config.toolText = toolText;
                    // Storing the initial parsed tooltext which will be later used in stack100percent calculations
                    // on legend click
                    config.setTooltext = toolText;
                    if (!dataObj) {
                        dataObj = dataStore[i] = {
                            graphics : {}
                        };
                    }
                    else if (!dataObj.graphics) {
                        dataStore[i].graphics = {};

                    }
                    config.hoverEffects = {
                        enabled: false
                    };
                }
                conf.maxValue = maxValue;
                conf.minValue = minValue;
            },

            configureQD: function (dataSet) {
                var chart = dataSet.chart,
                    chartComponents = chart.components,
                    parseUnsafeString = lib.parseUnsafeString,
                    conf = dataSet.config,
                    JSONData = dataSet.JSONData,
                    chartAttr = chart.jsonData.chart,
                    singleSeries = chart.singleseries,
                    colorM = chartComponents.colorManager,
                    index = dataSet.index || dataSet.stackIndex,
                    plotType = dataSet.type,
                    plotFillColor = !singleSeries || getValidValue(chartAttr.palettecolors) ?
                        colorM.getPlotColor(index) : colorM.getColor(PLOTFILLCOLOR_STR).split(/\s*\,\s*/)[0],
                    setDataArr = JSONData.data,
                    setData,
                    dataObj,
                    dataSetLen = setDataArr && setDataArr.length,
                    categories = chart.config.categories,
                    catLen = categories && categories.length,
                    len = mathMin(catLen, dataSetLen),
                    dataStore,
                    numberFormatter = chartComponents.numberFormatter,
                    config,
                    i,
                    toolText,
                    use3dlineshift = chart.use3dlineshift,
                    toolTipValue,
                    setValue,
                    setDisplayValue,
                    formatedVal,
                    maxValue = -Infinity,
                    minValue = +Infinity,
                    parentYAxis,
                    enableAnimation,
                    lineDashStyle,
                    stack100Percent,
                    defaultShadow,
                    tooltipSepChar = pluck(chartAttr.tooltipsepchar, ': '),
                    lineDashed = pluckNumber(JSONData.dashed, chartAttr.linedashed),
                    isStacked = chart.isStacked,
                    hasLineSet = chart.hasLineSet,
                    catObj,
                    xAxis = chartComponents.xAxis[0],
                    QDIconShape,
                    thisConfig;

                dataSet.visible = pluckNumber(dataSet.JSONData.visible,
                    !Number(dataSet.JSONData.initiallyhidden), 1) === 1;

                if (use3dlineshift !== UNDEFINED) {
                    conf.use3dlineshift = pluckNumber(chartAttr.use3dlineshift, use3dlineshift);
                }
                else {
                    conf.use3dlineshift = 1;
                }
                conf.plotColor = plotFillColor;
                conf.legendSymbolColor = conf.plotColor;
                defaultShadow = pluckNumber(chart.defaultPlotShadow, colorM.getColor(SHOWSHADOW));

                // Functional attributes configuration

                conf.drawFullAreaBorder = pluckNumber(chartAttr.drawfullareaborder, 1);
                // ParentYAxis is always 1 for lineset
                if (hasLineSet) {
                    conf.parentYAxis = parentYAxis = 1;
                }
                else {
                    conf.parentYAxis = parentYAxis = pluck(JSONData.parentyaxis && JSONData.parentyaxis.toLowerCase(),
                    pStr) === sStr ? 1 : 0 ;
                }
                conf.connectNullData = pluckNumber(chartAttr.connectnulldata, 0);

                // Animation related attributes configuration
                conf.enableAnimation = enableAnimation = pluckNumber(chartAttr.animation,
                    chartAttr.defaultanimation, 1);
                conf.animation = !enableAnimation ? false : {
                    duration: pluckNumber(chartAttr.animationduration, 1) * 1000
                };
                conf.transposeanimation = pluckNumber(chartAttr.transposeanimation, enableAnimation);
                conf.transposeanimduration = pluckNumber(chartAttr.transposeanimduration, 0.2) * 1000;

                // Value related configurations
                conf.showValues = 0;
                conf.valuePadding = pluckNumber(chartAttr.valuepadding, 2);
                conf.valuePosition = pluck(JSONData.valueposition, chartAttr.valueposition, 'auto');
                conf.stack100Percent = stack100Percent = pluckNumber(chartAttr.stack100percent, 0),
                conf.showPercentValues = pluckNumber(chartAttr.showpercentvalues, (isStacked && stack100Percent) ?
                    1 : 0);
                conf.showPercentInToolTip = pluckNumber(chartAttr.showpercentintooltip,
                    (isStacked && stack100Percent) ? 1 : 0);

                // Tooltip related attributes
                conf.showTooltip = pluckNumber(chartAttr.showtooltip, 1);
                conf.seriesNameInTooltip = pluckNumber(chartAttr.seriesnameintooltip, 1);

                conf.showHoverEffect = pluckNumber(chartAttr.plothovereffect, chartAttr.anchorhovereffect,
                    chartAttr.showhovereffect, UNDEFINED);

                conf.rotateValues = pluckNumber(chartAttr.rotatevalues) ? 270 : 0;
                // Line configuration attributes parsing
                conf.linethickness = pluckNumber(JSONData.linethickness,
                     chartAttr.linethickness, 1);
                conf.lineDashLen = pluckNumber(JSONData.linedashlen, chartAttr.linedashlen, 5);
                conf.lineDashGap = pluckNumber(JSONData.linedashgap, chartAttr.linedashgap, 4);
                conf.drawLine = conf.alpha =
                    pluckNumber(chartAttr.drawqdconnector, JSONData.drawqdconnector, 0) && 100;

                lineDashStyle = lib.getDashStyle(conf.lineDashLen, conf.lineDashGap, conf.linethickness);
                conf.lineDashStyle = lineDashed ?
                        lineDashStyle : NONE;

                conf.shadow = {
                    opacity: pluckNumber(chartAttr.showshadow, defaultShadow) ?
                        (plotType === LINE ? conf.alpha/100 :
                        conf.plotBorderAlpha/100) : 0
                };
                // Anchor cosmetics attributes in dataset level
                conf.drawAnchors = pluckNumber(JSONData.drawanchors, JSONData.showanchors, chartAttr.drawanchors,
                    chartAttr.showanchors);

                conf.anchorBgColor = pluck(JSONData.qdiconcolor,
                    chartAttr.qdiconcolor, COLOR_000000);
                conf.anchorBorderColor = COLOR_000000;
                conf.anchorRadius = pluckNumber(JSONData.qdiconradius, chartAttr.qdiconradius, 5);
                conf.anchorAlpha = pluck(JSONData.alpha,
                    JSONData.qdiconalpha, chartAttr.qdiconalpha);
                conf.anchorBgAlpha = pluck(JSONData.qdiconalpha, chartAttr.qdiconalpha, 100);
                conf.anchorBorderThickness = pluck(JSONData.anchorborderthickness,
                    chartAttr.anchorborderthickness, 1);
                conf.anchorSides = pluck(JSONData.qdiconsides, chartAttr.qdiconsides, 3);

                conf.linecolor = conf.anchorBgColor;

                // Spline attributes
                conf.minimizeTendency = pluckNumber(chartAttr.minimizetendency,chartAttr.minimisetendency,0);

                // Anchor image cosmetics attributes
                conf.anchorImageUrl = pluck(JSONData.anchorimageurl, chartAttr.anchorimageurl);
                conf.anchorImageAlpha = pluckNumber(JSONData.anchorimagealpha, chartAttr.anchorimagealpha, 100);
                conf.anchorImageScale = pluckNumber(JSONData.anchorimagescale, chartAttr.anchorimagescale, 100);
                conf.anchorImagePadding = pluckNumber(JSONData.anchorimagepadding, chartAttr.anchorimagepadding, 1);
                conf.anchorStartAngle = pluckNumber(JSONData.anchorstartangle, chartAttr.anchorstartangle, 90);
                conf.anchorShadow = pluckNumber(JSONData.anchorshadow, chartAttr.anchorshadow, 0);
                !dataSet.components.data && (dataSet.components.data = []);
                dataStore = dataSet.components.data;

                for (i=0; i<len; i++) {
                    setData = setDataArr && setDataArr[i];
                    dataObj = dataStore[i] =  dataStore[i] || {};
                    dataObj.config = dataObj.config || {};
                    config = dataObj.config;
                    thisConfig = this.components.data[i].config;

                    if (thisConfig.showQD) {
                        setData.value = thisConfig.qd;
                    }
                    else {
                        setData.value = null;
                    }

                    config.x = this.components.data[i]._xPos;

                    config.setValue = setValue = numberFormatter.getCleanValue(setData.value);
                    config.setLink  = pluck(setData.link);
                    // Parsing the anchor properties for set level
                    config.anchorProps = this._parseAnchorProperties(i, dataSet, qdStr);
                    catObj = xAxis.getLabel(i);
                    config.label = lib.getValidValue(parseUnsafeString(pluck(catObj.tooltext,
                        catObj.label, catObj.name)));
                    config.showValue = 0;

                    // Dashed, color and alpha configuration in set level is only for line chart
                    config.dashed = pluckNumber(setData.dashed, lineDashed);
                    config.color = pluck(setData.color, conf.lineColor);
                    config.alpha = pluck(setData.alpha, setData.alpha, conf.alpha);
                    maxValue = mathMax(maxValue, setValue);
                    minValue = mathMin(minValue, setValue);
                    config.dashStyle = config.dashed ? lineDashStyle : NONE;
                    config.toolTipValue = toolTipValue = numberFormatter.dataLabels(setValue, parentYAxis);
                    config.setDisplayValue = setDisplayValue = parseUnsafeString(setData.displayvalue);
                    config.displayValue = pluck(setDisplayValue, toolTipValue);
                    config.formatedVal = formatedVal = config.toolTipValue;
                    config.setTooltext = lib.getValidValue(parseUnsafeString(pluck(setData.tooltext,
                       JSONData.plottooltext, chartAttr.plottooltext)));
                    QDIconShape = pluck(setData.qdiconshape, JSONData.qdiconshape,
                                        chartAttr.qdiconshape, POLYGON);
                    conf.dip = config.dip = (QDIconShape === POLYGON) ? 0 : (QDIconShape === SPOKE) ? 1 : 0;
                    // Initial tooltext parsing

                    if (!conf.showTooltip) {
                        toolText = false;
                    }
                    else {
                        if (formatedVal === null) {
                            toolText = false;
                        }
                        else {
                            toolText = BOLDSTARTTAG + QD_STR + tooltipSepChar + BOLDENDTAG;
                        }
                    }
                    config.toolText = toolText;
                    // Storing the initial parsed tooltext which will be later used in stack100percent calculations
                    // on legend click
                    config.setTooltext = toolText;
                    if (!dataObj) {
                        dataObj = dataStore[i] = {
                            graphics : {}
                        };
                    }
                    else if (!dataObj.graphics) {
                        dataStore[i].graphics = {};

                    }
                    config.hoverEffects = {
                        enabled: false
                    };
                }
                conf.maxValue = maxValue;
                conf.minValue = minValue;
            },

            configureOutliers: function (dataSet, outlierIndex) {
                var chart = dataSet.chart,
                    chartComponents = chart.components,
                    parseUnsafeString = lib.parseUnsafeString,
                    conf = dataSet.config,
                    JSONData = dataSet.JSONData,
                    chartAttr = chart.jsonData.chart,
                    singleSeries = chart.singleseries,
                    colorM = chartComponents.colorManager,
                    index = dataSet.index || dataSet.stackIndex,
                    plotType = dataSet.type,
                    plotFillColor = !singleSeries || getValidValue(chartAttr.palettecolors) ?
                        colorM.getPlotColor(index) : colorM.getColor(PLOTFILLCOLOR_STR).split(/\s*\,\s*/)[0],
                    setDataArr = JSONData.data,
                    setData,
                    dataObj,
                    dataSetLen = setDataArr && setDataArr.length,
                    categories = chart.config.categories,
                    catLen = categories && categories.length,
                    len = mathMin(catLen, dataSetLen),
                    dataStore,
                    numberFormatter = chartComponents.numberFormatter,
                    config,
                    i,
                    toolText,
                    use3dlineshift = chart.use3dlineshift,
                    toolTipValue,
                    setValue,
                    setDisplayValue,
                    formatedVal,
                    maxValue = -Infinity,
                    minValue = +Infinity,
                    parentYAxis,
                    enableAnimation,
                    lineDashStyle,
                    stack100Percent,
                    defaultShadow,
                    tooltipSepChar = pluck(chartAttr.tooltipsepchar, ': '),
                    lineDashed = pluckNumber(JSONData.dashed, chartAttr.linedashed),
                    isStacked = chart.isStacked,
                    hasLineSet = chart.hasLineSet,
                    catObj,
                    xAxis = chartComponents.xAxis[0],
                    outlierIconShape,
                    thisConfig;

                dataSet.visible = pluckNumber(dataSet.JSONData.visible,
                    !Number(dataSet.JSONData.initiallyhidden), 1) === 1;

                if (use3dlineshift !== UNDEFINED) {
                    conf.use3dlineshift = pluckNumber(chartAttr.use3dlineshift, use3dlineshift);
                }
                else {
                    conf.use3dlineshift = 1;
                }
                conf.plotColor = plotFillColor;
                conf.legendSymbolColor = conf.plotColor;
                defaultShadow = pluckNumber(chart.defaultPlotShadow, colorM.getColor(SHOWSHADOW));

                // Functional attributes configuration

                conf.drawFullAreaBorder = pluckNumber(chartAttr.drawfullareaborder, 1);
                // ParentYAxis is always 1 for lineset
                if (hasLineSet) {
                    conf.parentYAxis = parentYAxis = 1;
                }
                else {
                    conf.parentYAxis = parentYAxis = pluck(JSONData.parentyaxis && JSONData.parentyaxis.toLowerCase(),
                    pStr) === sStr ? 1 : 0 ;
                }
                conf.connectNullData = pluckNumber(chartAttr.connectnulldata, 0);

                // Animation related attributes configuration
                conf.enableAnimation = enableAnimation = pluckNumber(chartAttr.animation,
                    chartAttr.defaultanimation, 1);
                conf.animation = !enableAnimation ? false : {
                    duration: pluckNumber(chartAttr.animationduration, 1) * 1000
                };
                conf.transposeanimation = pluckNumber(chartAttr.transposeanimation, enableAnimation);
                conf.transposeanimduration = pluckNumber(chartAttr.transposeanimduration, 0.2) * 1000;

                // Value related configurations
                conf.showValues = 0;
                conf.valuePadding = pluckNumber(chartAttr.valuepadding, 2);
                conf.valuePosition = pluck(JSONData.valueposition, chartAttr.valueposition, 'auto');
                conf.stack100Percent = stack100Percent = pluckNumber(chartAttr.stack100percent, 0),
                conf.showPercentValues = pluckNumber(chartAttr.showpercentvalues, (isStacked && stack100Percent) ?
                    1 : 0);
                conf.showPercentInToolTip = pluckNumber(chartAttr.showpercentintooltip,
                    (isStacked && stack100Percent) ? 1 : 0);

                // Tooltip related attributes
                conf.showTooltip = pluckNumber(chartAttr.showtooltip, 1);
                conf.seriesNameInTooltip = pluckNumber(chartAttr.seriesnameintooltip, 1);

                conf.showHoverEffect = pluckNumber(chartAttr.plothovereffect, chartAttr.anchorhovereffect,
                    chartAttr.showhovereffect, UNDEFINED);

                conf.rotateValues = pluckNumber(chartAttr.rotatevalues) ? 270 : 0;
                // Line configuration attributes parsing
                conf.linethickness = pluckNumber(JSONData.linethickness,
                     chartAttr.linethickness, 1);
                conf.lineDashLen = pluckNumber(JSONData.linedashlen, chartAttr.linedashlen, 5);
                conf.lineDashGap = pluckNumber(JSONData.linedashgap, chartAttr.linedashgap, 4);
                conf.alpha = 0;

                lineDashStyle = lib.getDashStyle(conf.lineDashLen, conf.lineDashGap, conf.linethickness);
                conf.lineDashStyle = lineDashed ?
                        lineDashStyle : NONE;

                conf.shadow = {
                    opacity: pluckNumber(chartAttr.showshadow, defaultShadow) ?
                        (plotType === LINE ? conf.alpha/100 :
                        conf.plotBorderAlpha/100) : 0
                };
                // Anchor cosmetics attributes in dataset level
                conf.drawAnchors = pluckNumber(JSONData.drawanchors, JSONData.showanchors, chartAttr.drawanchors,
                    chartAttr.showanchors);

                conf.anchorBgColor = pluck(JSONData.outliericoncolor,
                    chartAttr.outliericoncolor, COLOR_000000);
                conf.anchorBorderColor = COLOR_000000;
                conf.anchorRadius = pluckNumber(JSONData.outliericonradius, chartAttr.outliericonradius, 5);
                conf.anchorAlpha = pluck(JSONData.alpha,
                    JSONData.outliericonalpha, chartAttr.outliericonalpha);
                conf.anchorBgAlpha = pluck(JSONData.outliericonalpha, chartAttr.outliericonalpha, 100);
                conf.anchorBorderThickness = pluck(JSONData.anchorborderthickness,
                    chartAttr.anchorborderthickness, 1);
                conf.anchorSides = pluck(JSONData.outliericonsides, chartAttr.outliericonsides, 3);

                conf.linecolor = conf.anchorBgColor;

                // Spline attributes
                conf.minimizeTendency = pluckNumber(chartAttr.minimizetendency,chartAttr.minimisetendency,0);

                // Anchor image cosmetics attributes
                conf.anchorImageUrl = pluck(JSONData.anchorimageurl, chartAttr.anchorimageurl);
                conf.anchorImageAlpha = pluckNumber(JSONData.anchorimagealpha, chartAttr.anchorimagealpha, 100);
                conf.anchorImageScale = pluckNumber(JSONData.anchorimagescale, chartAttr.anchorimagescale, 100);
                conf.anchorImagePadding = pluckNumber(JSONData.anchorimagepadding, chartAttr.anchorimagepadding, 1);
                conf.anchorStartAngle = pluckNumber(JSONData.anchorstartangle, chartAttr.anchorstartangle, 90);
                conf.anchorShadow = pluckNumber(JSONData.anchorshadow, chartAttr.anchorshadow, 0);
                !dataSet.components.data && (dataSet.components.data = []);
                dataStore = dataSet.components.data;

                for (i=0; i<len; i++) {
                    setData = setDataArr && setDataArr[i];
                    dataObj = dataStore[i] =  dataStore[i] || {};
                    dataObj.config = dataObj.config || {};
                    config = dataObj.config;
                    thisConfig = this.components.data[i].config;

                    if (thisConfig.outliers) {
                        setData.value = thisConfig.outliers[outlierIndex];
                    }
                    else {
                        setData.value = null;
                    }

                    config.x = this.components.data[i]._xPos;

                    config.setValue = setValue = numberFormatter.getCleanValue(setData.value);

                    if ((setValue >= thisConfig.min) && (setValue <= thisConfig.max)) {
                        config.setValue = setData.value = null;
                    }

                    config.setLink  = pluck(setData.link);
                    // Parsing the anchor properties for set level
                    config.anchorProps = this._parseAnchorProperties(i, dataSet, outlierStr);
                    catObj = xAxis.getLabel(i);
                    config.label = lib.getValidValue(parseUnsafeString(pluck(catObj.tooltext,
                        catObj.label, catObj.name)));
                    config.showValue = 0;

                    // Dashed, color and alpha configuration in set level is only for line chart
                    config.dashed = pluckNumber(setData.dashed, lineDashed);
                    config.color = pluck(setData.color, conf.lineColor);
                    config.alpha = pluck(setData.alpha, setData.alpha, conf.alpha);
                    maxValue = mathMax(maxValue, setValue);
                    minValue = mathMin(minValue, setValue);
                    config.dashStyle = config.dashed ? lineDashStyle : NONE;
                    config.toolTipValue = toolTipValue = numberFormatter.dataLabels(setValue, parentYAxis);
                    config.setDisplayValue = setDisplayValue = parseUnsafeString(setData.displayvalue);
                    config.displayValue = pluck(setDisplayValue, toolTipValue);
                    config.formatedVal = formatedVal = config.toolTipValue;
                    config.setTooltext = lib.getValidValue(parseUnsafeString(pluck(setData.tooltext,
                       JSONData.plottooltext, chartAttr.plottooltext)));
                    outlierIconShape = pluck(setData.outliericonshape, JSONData.outliericonshape,
                                        chartAttr.outliericonshape, POLYGON);
                    conf.dip = config.dip = (outlierIconShape === POLYGON) ? 0 : (outlierIconShape === SPOKE) ? 1 : 0;
                    // Initial tooltext parsing

                    if (!conf.showTooltip) {
                        toolText = false;
                    }
                    else {
                        if (formatedVal === null) {
                            toolText = false;
                        }
                        else {
                            toolText = BOLDSTARTTAG + OUTLIER_STR + tooltipSepChar + BOLDENDTAG;
                        }
                    }
                    config.toolText = toolText;
                    // Storing the initial parsed tooltext which will be later used in stack100percent calculations
                    // on legend click
                    config.setTooltext = toolText;
                    if (!dataObj) {
                        dataObj = dataStore[i] = {
                            graphics : {}
                        };
                    }
                    else if (!dataObj.graphics) {
                        dataStore[i].graphics = {};

                    }
                    config.hoverEffects = {
                        enabled: false
                    };
                }
                conf.maxValue = maxValue;
                conf.minValue = minValue;
            },

            initSubDataset: function (datasetJSON, dataSet) {
                var chart = dataSet.chart,
                    components = chart.components,
                    hasLineSet = chart.hasLineSet,
                    parentYAxis = ((datasetJSON.parentyaxis && datasetJSON.parentyaxis.toLowerCase() === sStr) ||
                        hasLineSet) ? 1 : 0,
                    yAxis;
                dataSet.chart = chart;
                yAxis = components.yAxis[parentYAxis];
                dataSet.yAxis = yAxis;
                dataSet.components = {

                };

                dataSet.graphics = {

                };
                dataSet.JSONData = datasetJSON;
                // dataSet.visible = pluckNumber(dataSet.JSONData.visible,
                //     !Number(dataSet.JSONData.initiallyhidden), 1) === 1;
            },

            _parseAnchorProperties : function (i, dataSet, type) {
                var conf = dataSet.config,
                    plotType = dataSet.type,
                    defaultAnchorVisibility = plotType === 'area' ? 0 : 1,
                    JSONData = dataSet.JSONData,
                    chartAttr = dataSet.chart.jsonData.chart,
                    setDataArr = JSONData.data,
                    setData = setDataArr[i],
                    anchorProps = {},
                    mapSymbolName = lib.graphics.mapSymbolName,
                    anchorAlpha,
                    anchorAttrsDefined,
                    drawAnchors;
                // Check if anchor attributes are defined
                anchorAttrsDefined = pluck(setData.anchorstartangle, JSONData.anchorstartangle,
                    chartAttr.anchorstartangle,
                    setData.anchorimagealpha, JSONData.anchorimagealpha, chartAttr.anchorimagealpha,
                    setData.anchorimagescale, JSONData.anchorimagescale, chartAttr.anchorimagescale,
                    setData.anchorimagepadding, JSONData.anchorimagepadding, chartAttr.anchorimagepadding,
                    setData.anchorimageurl, JSONData.anchorimageurl, chartAttr.anchorimageurl,
                    setData.meaniconradius, JSONData.meaniconradius, chartAttr.meaniconradius,
                    setData.meaniconcolor, JSONData.meaniconcolor, chartAttr.meaniconcolor,
                    setData.anchorbordercolor, JSONData.anchorbordercolor, chartAttr.anchorbordercolor,
                    setData.anchoralpha, JSONData.anchoralpha, chartAttr.anchoralpha,
                    setData.meaniconsides, JSONData.meaniconsides, chartAttr.meaniconsides,
                    setData.anchorborderthickness, JSONData.anchorborderthickness,
                    chartAttr.anchorborderthickness, UNDEFINED
                ) !== UNDEFINED;
                drawAnchors = pluckNumber(setData.drawanchors, conf.drawAnchors);
                /*
                    If any anchor attribute is defined then we choose between draw anchors attribute
                    and whether any anchor attributes are defined
                    Otherwise we choose between default anchor visibility which is false for area
                    and true for line and drawanchors attribute
                */
                if (anchorAttrsDefined) {
                    anchorProps.enabled = pluckNumber(drawAnchors, anchorAttrsDefined);
                }
                else {
                    anchorProps.enabled = pluckNumber(drawAnchors, defaultAnchorVisibility);
                }
                anchorProps.startAngle = pluckNumber(setData.anchorstartangle, conf.anchorStartAngle);
                anchorProps.imageAlpha = pluckNumber(setData.anchorimagealpha, conf.anchorImageAlpha);
                anchorProps.imageScale = pluckNumber(setData.anchorimagescale, conf.anchorImageScale);
                anchorProps.imagePadding = pluckNumber(setData.anchorimagepadding, conf.anchorImagePadding);
                if (anchorProps.imagePadding < 0) {
                    anchorProps.imagePadding =  0;
                }
                anchorProps.imageUrl = pluck(setData.anchorimageurl, conf.anchorImageUrl);
                anchorProps.radius = pluckNumber(setData[type + iconradiusStr], conf.anchorRadius);
                anchorProps.isAnchorRadius = anchorProps.radius;
                anchorProps.bgColor = pluck(setData[type + iconcolorStr], conf.anchorBgColor);
                if (!anchorProps.enabled) {
                    anchorAlpha = 0;
                }
                else {
                    anchorAlpha = getFirstAlpha(pluck(setData.anchoralpha, conf.anchorAlpha,
                        anchorProps.enabled ? HUNDREDSTRING : ZEROSTRING));
                }

                anchorProps.bgAlpha = getFirstAlpha(pluck(setData[type + iconalphaStr],
                    conf.meaniconalpha, anchorAlpha));

                anchorProps.borderColor = pluck(setData.anchorbordercolor, conf.anchorBorderColor);
                anchorProps.borderAlpha = anchorAlpha;
                anchorProps.anchorAlpha = anchorAlpha;
                anchorProps.sides = pluck(setData[type + iconsidesStr], conf.anchorSides);
                anchorProps.borderThickness = pluck(setData.anchorborderthickness, conf.anchorBorderThickness);
                anchorProps.symbol = mapSymbolName(anchorProps.sides).split(UNDERSCORE);
                anchorProps.shadow = (pluckNumber(setData.anchorshadow, conf.anchorShadow) &&
                    anchorProps.radius >= 1) ? {
                        opacity: anchorAlpha / 100
                    } : false;
                conf.attachEvents = true;
                return anchorProps;
            },

            init : function(datasetJSON) {
                var dataSet = this,
                    chart = dataSet.chart,
                    components = chart.components,
                    parentYAxis = datasetJSON.parentyaxis && datasetJSON.parentyaxis.toLowerCase() === sStr ? 1 : 0,
                    yAxis = components.yAxis[parentYAxis];

                if (!datasetJSON) {
                    return false;
                }
                dataSet.JSONData = datasetJSON;
                dataSet.yAxis = yAxis;
                dataSet.chartGraphics = chart.chartGraphics;
                dataSet.components = {
                };

                dataSet.graphics = {
                };

                dataSet.configure();
            },

            draw: function () {
                var dataSet = this,
                    JSONData = dataSet.JSONData,
                    conf = dataSet.config,
                    groupManager = dataSet.groupManager,
                    datasetIndex = dataSet.index,
                    categories = dataSet.chart.config.categories,
                    setDataArr = JSONData.data,
                    catLen = categories && categories.length,
                    dataSetLen = setDataArr && setDataArr.length,
                    len,
                    setData,
                    attr,
                    i,
                    visible = dataSet.visible,
                    chart = dataSet.chart,
                    chartConfig = chart.config,
                    paper = chart.components.paper,
                    xAxis = chart.components.xAxis[0],
                    yAxis = dataSet.yAxis,
                    parentContainer = chart.graphics.columnGroup,
                    xPos,
                    yPos,
                    layers = chart.graphics,
                    showTooltip = conf.showtooltip,

                    animationObj = chart.get(configStr, animationObjStr),
                    animType = animationObj.animType,
                    animObj = animationObj.animObj,
                    dummyObj = animationObj.dummyObj,
                    animationDuration = animationObj.duration,

                    xAxisZeroPos = xAxis.getAxisPosition(0),
                    xAxisFirstPos = xAxis.getAxisPosition(1),
                    groupMaxWidth = xAxisFirstPos - xAxisZeroPos,
                    definedGroupPadding = conf.definedGroupPadding,
                    plotSpacePercent = conf.plotSpacePercent,
                    groupPadding = plotSpacePercent / 200,
                    numOfColumns = 1,
                    positionValue = groupManager.getDataSetPosition(dataSet),
                    maxColWidth = conf.maxcolwidth,
                    // Calculating the net width occupied by bars for each category
                    groupNetWidth = (1 - definedGroupPadding * 0.01) * groupMaxWidth || mathMin(
                        groupMaxWidth * (1 - groupPadding * 2),
                        maxColWidth * numOfColumns
                    ),
                    initialColumnWidth = pluckNumber(positionValue.columnWidth, (groupNetWidth / numOfColumns)),
                    columnWidth,
                    xPosOffset = positionValue.xPosOffset || 0,
                    hiddenDatasetHeight = positionValue.height,
                    toolText,
                    dataStore = dataSet.components.data,
                    dataObj,
                    setLink,
                    setValue,
                    eventArgs,
                    displayValue,
                    config,
                    isPositive,
                    yBase = yAxis.getAxisBase(),
                    previousY,
                    previousYPos,
                    showShadow = conf.showShadow,

                    upperBoxContainer = dataSet.graphics.upperBoxContainer,
                    lowerBoxContainer = dataSet.graphics.lowerBoxContainer,
                    medianContainer = dataSet.graphics.medianContainer,

                    upperWhiskerContainer = dataSet.graphics.upperWhiskerContainer,
                    lowerWhiskerContainer = dataSet.graphics.lowerWhiskerContainer,

                    dataLabelContainer = dataSet.graphics.dataLabelContainer,
                    shadowContainer = dataSet.graphics.shadowContainer,

                    colorArr,
                    upperQuartile,
                    yTop,
                    yTopPos,
                    lowerQuartile,
                    yBottom,
                    yBottomPos,
                    median,
                    yMed,
                    yMedPos,
                    upperBoxH,
                    lowerBoxH,
                    upperBoxBorder,
                    lowerBoxBorder,
                    upperBoxElem,
                    upperBoxBorderEle,
                    upperQuartileEle,
                    lowerBoxElem,
                    lowerBoxBorderEle,
                    lowerQuartileEle,
                    midLineElem,
                    crispX,
                    crispX2,
                    crispY,
                    style = chart.config.dataLabelStyle,
                    dataLabelsLayer =  layers.datalabelsGroup,
                    hoverOutEffects,
                    rotateValues = conf.rotatevalues,
                    valuePadding = conf.valuepadding,

                    numberFormatter = chart.components.numberFormatter,
                    textAlign = rotateValues ? POSITION_LEFT : POSITION_MIDDLE,
                    smartLabel = chart.linkedItems.smartLabel,
                    graphic,
                    groupId,
                    errorStartPos,
                    errorBarWidth,
                    halfErrorBarW,
                    errorValPos,
                    crispyX,
                    crispyY,
                    upperWhiskerEle,
                    errorPath,
                    lowerWhiskerEle,
                    smartText,
                    lineHeight,
                    labelBottomY,
                    labelTopY,
                    lastDataSetHeight = +Infinity,
                    lastDataSetYpos,
                    j,
                    animFlag = true,
                    removeDataArr = dataSet.components.removeDataArr || [],
                    removeDataArrLen = removeDataArr.length,
                    newupperBoxElem,
                    newlowerBoxElem,
                    newupperBoxBorderEle,
                    newlowerBoxBorderEle,
                    newupperQuartileEle,
                    newlowerQuartileEle,
                    newmidLineElem,
                    newupperWhiskerEle,
                    newlowerWhiskerEle,
                    hoverInAttr,
                    hoverOutAttr,
                    showHoverEffect = conf.showHoverEffect,
                    x,
                    y,
                    upperBoxStartPos,
                    lowerBoxYPos,
                    lowerBoxHeight,
                    lowerBoxEndPos,

                    // Fired when clicked over the hot elements.
                    clickFunc = function (setDataArr) {
                            var ele = this;
                            plotEventHandler.call(ele, chart, setDataArr);
                        },

                    //Fired on mouse-in over the hot elements.
                    rolloverResponseSetter = function (obj) {
                            return function (data) {
                                var ele = this,
                                    elem;

                                if (ele.data(showHoverEffectStr) !== 0) {
                                    for (elem in obj) {
                                        if (elem !== LABEL) {
                                            obj[elem].attr(ele.data(SETROLLOVERATTR)[elem]);
                                            plotEventHandler.call(ele, chart, data, ROLLOVER);
                                        }
                                    }
                                }
                            };
                        },

                    //Fired on mouse-out over the hot elements.
                    rolloutResponseSetter = function (obj) {
                            return function (data) {
                                var ele = this,
                                    elem;

                                if (ele.data(showHoverEffectStr) !== 0) {
                                    for (elem in obj) {
                                        if (elem !== LABEL) {
                                            obj[elem].attr(ele.data(SETROLLOUTATTR)[elem]);
                                            plotEventHandler.call(ele, chart, data, ROLLOUT);
                                        }
                                    }
                                }
                            };
                        },
                    animCallBack = function () {
                        if (dataSet.visible === false && (dataSet._conatinerHidden === false ||
                                dataSet._conatinerHidden=== UNDEFINED)) {
                            upperBoxContainer.hide();
                            lowerBoxContainer.hide();
                            upperWhiskerContainer.hide();
                            lowerWhiskerContainer.hide();
                            medianContainer.hide();
                            shadowContainer.hide();
                            dataLabelContainer && dataLabelContainer.hide();
                            dataSet._conatinerHidden = true;
                        }
                    };

                if (!dataLabelContainer) {
                    dataLabelContainer = dataSet.graphics.dataLabelContainer =
                        paper.group(dataLabelStr, dataLabelsLayer);
                    if (!visible) {
                        dataLabelContainer.hide();
                    }
                }

                /*
                 * Creating a container group for the graphic element of column plots if
                 * not present and attaching it to its parent group.
                 */
                if (!upperBoxContainer) {
                    upperBoxContainer = dataSet.graphics.upperBoxContainer =
                        paper.group('upperBox', parentContainer).trackTooltip(true).toBack();
                    if (!visible) {
                        upperBoxContainer.hide();
                    }
                }

                if (!upperWhiskerContainer) {
                    upperWhiskerContainer = dataSet.graphics.upperWhiskerContainer =
                        paper.group('upperWhisker', parentContainer).trackTooltip(true);
                    if (!visible) {
                        upperWhiskerContainer.hide();
                    }
                }

                if (!lowerBoxContainer) {
                    lowerBoxContainer = dataSet.graphics.lowerBoxContainer = paper.group('lowerBox', parentContainer)
                        .trackTooltip(true).toBack();
                    if (!visible) {
                        lowerBoxContainer.hide();
                    }
                }

                if (!lowerWhiskerContainer) {
                    lowerWhiskerContainer = dataSet.graphics.lowerWhiskerContainer =
                        paper.group('lowerWhisker', parentContainer).trackTooltip(true);
                    if (!visible) {
                        lowerWhiskerContainer.hide();
                    }
                }

                if (!medianContainer) {
                    medianContainer = dataSet.graphics.medianContainer = paper.group('median', parentContainer)
                        .trackTooltip(true);
                    if (!visible) {
                        medianContainer.hide();
                    }
                }

                /*
                 * Creating the shadow element container group for each plots if not present
                 * and attaching it its parent group.
                 */
                if (!shadowContainer) {
                    // Always sending the shadow group to the back of the plots group.
                    shadowContainer = dataSet.graphics.shadowContainer =
                        paper.group(shadowStr, parentContainer).toBack();
                    if (!visible) {
                        shadowContainer.hide();
                    }

                }

                if (visible) {
                    // Showing the groups when visible set to true
                    upperBoxContainer.show();
                    lowerBoxContainer.show();
                    upperWhiskerContainer.show();
                    lowerWhiskerContainer.show();
                    medianContainer.show();
                    shadowContainer.show();
                    dataLabelContainer && dataLabelContainer.show();
                    dataSet._conatinerHidden = false;

                    dataSet.components.mean.visible && dataSet.components.mean.show();
                    dataSet.components.sd.visible && dataSet.components.sd.show();
                    dataSet.components.qd.visible && dataSet.components.qd.show();
                    dataSet.components.md.visible && dataSet.components.md.show();
                }

                len = mathMin(catLen, dataSetLen);

                // Create plot elements.
                for (i = 0; i < len; i++) {
                    setData = setDataArr && setDataArr[i];
                    dataObj = dataStore[i];
                    config = dataObj && dataObj.config;
                    setValue = config && config.setValue;

                    newupperBoxElem = false;
                    newlowerBoxElem = false;
                    newupperBoxBorderEle = false;
                    newlowerBoxBorderEle = false;
                    newupperQuartileEle = false;
                    newlowerQuartileEle = false;
                    newmidLineElem = false;
                    newupperWhiskerEle = false;
                    newlowerWhiskerEle = false;

                    // If plot value is found "null", continue the loop to next iteration.
                    if (dataObj === UNDEFINED || setValue === UNDEFINED || setValue === null) {
                        continue;
                    }

                    graphic = dataObj.graphics;

                    isPositive = setValue >= 0;

                    setLink  = config.setLink;
                    colorArr = config.colorArr;

                    // Creating the data structure if not present for storing the graphics elements.
                    if (!dataObj.graphics) {
                        dataStore[i].graphics = {};

                    }
                    if (!graphic.label) {
                        dataStore[i].graphics.label = [];

                    }

                    displayValue = config.displayValue;

                    previousY = isPositive ? config.previousPositiveY : config.previousNegativeY;

                    // Getting the previous yposition of the plot and calculating the current yposition of the plot.
                    previousYPos = yAxis.getAxisPosition( previousY|| yBase);
                    xPos = xAxis.getAxisPosition(i) + xPosOffset;

                    /*
                     * Check for setting the height of the datasets which are hidden. If the datasets are hidden then
                     * the height is set to 0 and ypos is set to the ypos of the previous plot.
                     */
                    if (hiddenDatasetHeight === 0) {
                        lastDataSetHeight = 0;
                        lastDataSetYpos = previousYPos;
                    }
                    yPos = mathMin(yPos,previousYPos);

                    columnWidth = initialColumnWidth;

                    upperQuartile = config.upperQuartile || {};
                    yTop = upperQuartile && upperQuartile.value;
                    yTopPos = (yTop  || yTop === 0)&& yAxis.getAxisPosition(yTop);

                    lowerQuartile = config.lowerQuartile || {};
                    yBottom = lowerQuartile && lowerQuartile.value;
                    yBottomPos = (yBottom || yBottom === 0) && yAxis.getAxisPosition(yBottom);

                    median = config.median;
                    yMed = median && median.value; // || yBottom;
                    yMedPos = (yMed || yMed === 0) && yAxis.getAxisPosition(yMed);

                    upperBoxH = yMedPos - yTopPos;
                    lowerBoxH = yBottomPos - yMedPos;

                    upperBoxBorder = config.upperBoxBorder || {};
                    lowerBoxBorder = config.lowerBoxBorder || {};

                    toolText = config.toolText;
                    groupId = dataSet.index + UNDERSCORE + i;

                    eventArgs = {
                        index: i,
                        link: setLink,
                        maximum: config.max,
                        minimum: config.min,
                        median: yMed,
                        q3: upperQuartile.value,
                        q1: lowerQuartile.value,
                        maxDisplayValue: config.showMaxValues ? numberFormatter.dataLabels(config.max) : BLANKSTRING,
                        minDisplayValue: config.showMinValues ? numberFormatter.dataLabels(config.min) : BLANKSTRING,
                        medianDisplayValue: config.showMedianValues ? numberFormatter.dataLabels(yMed) : BLANKSTRING,
                        q1DisplayValue: config.showQ1Values ? numberFormatter.dataLabels(lowerQuartile.value) :
                            BLANKSTRING,
                        q3DisplayValue: config.showQ3Values ? numberFormatter.dataLabels(upperQuartile.value) :
                            BLANKSTRING,
                        categoryLabel: config.label,
                        toolText: toolText,
                        datasetIndex: datasetIndex,
                        datasetName: JSONData.seriesname,
                        visible: visible
                    };

                    // upperBox
                    crispX = mathRound(xPos) + upperBoxBorder.borderWidth % 2 *
                        0.5;
                    crispX2 = mathRound(xPos + columnWidth) +
                        upperBoxBorder.borderWidth % 2 * 0.5;
                    crispY = mathRound(yTopPos) + upperQuartile.borderWidth %
                        2 * 0.5;
                    columnWidth = crispX2 - crispX;

                    hoverOutEffects = {
                        upperBox: {
                            fill: toRaphaelColor(config.upperColorArr[0]), //upperQuartile.color
                            'stroke-width': 0,
                            'stroke-dasharray': NONE,
                            cursor: setLink ? POINTER : BLANKSTRING,
                            ishot: true,
                            visibility: visible
                        },
                        lowerBox: {
                            fill: toRaphaelColor(config.lowerColorArr[0]),
                            'stroke-width': 0,
                            'stroke-dasharray': NONE,
                            cursor: setLink ? POINTER : BLANK,
                            ishot: true,
                            visibility: visible
                        },
                        upperBoxBorder: {
                            stroke: upperBoxBorder.color,
                            'stroke-width': upperBoxBorder.borderWidth,
                            'stroke-linecap': ROUND,
                            dashstyle: upperBoxBorder.dashStyle,
                            ishot: true,
                            visibility: visible
                        },
                        lowerBoxBorder: {
                            stroke: lowerBoxBorder.color,
                            'stroke-width': lowerBoxBorder.borderWidth,
                            dashstyle: lowerBoxBorder.dashStyle,
                            'stroke-linecap': ROUND,
                            ishot: true,
                            visibility: visible
                        },
                        upperQuartile: {
                            stroke: toRaphaelColor(upperQuartile.color),
                            'stroke-width': upperQuartile.borderWidth,
                            'stroke-dasharray': upperQuartile.dashSyle,
                            'stroke-linecap': ROUND,
                            cursor: setLink ? POINTER : BLANK,
                            ishot: true,
                            visibility: visible
                        },
                        lowerQuartile: {
                            stroke: toRaphaelColor(lowerQuartile.color),
                            'stroke-width': lowerQuartile.borderWidth,
                            'stroke-dasharray': lowerQuartile.dashSyle,
                            cursor: setLink ? POINTER : BLANKSTRING,
                            'stroke-linecap': ROUND,
                            ishot: true,
                            visibility: visible
                        },
                        median: {
                            stroke: toRaphaelColor(median.color),
                            'stroke-width': median.borderWidth,
                            'stroke-dasharray': median.dashSyle,
                            cursor: setLink ? POINTER : BLANKSTRING,
                            'stroke-linecap': ROUND,
                            ishot: true,
                            visibility: visible
                        }
                    };

                    upperBoxStartPos = lastDataSetYpos || crispY;

                    // draw upperbox element
                    attr = {
                        x: crispX,
                        y: lastDataSetYpos || crispY,
                        width: mathMax(columnWidth, 0),
                        height: mathMax(mathMin(lastDataSetHeight, upperBoxH), 0),
                        r: 0
                    };

                    upperBoxElem = dataObj.graphics.upperBoxElem;

                    if (!upperBoxElem) {
                        upperBoxElem = dataObj.graphics.upperBoxElem = paper.rect(attr, upperBoxContainer);
                        newupperBoxElem = true;
                    }
                    else
                    {
                        upperBoxElem.animateWith(dummyObj, animObj, attr, animationDuration,
                            animType, (animFlag && animCallBack));
                        animFlag = false;
                    }

                    upperBoxElem.attr(hoverOutEffects.upperBox)
                        .shadow({opacity : showShadow ? conf.upperBoxAlpha / 100 : 0}, shadowContainer);

                    // draw upperBoxBorder element
                    attr = {
                        path: [M, crispX, lastDataSetYpos || crispY, V, lastDataSetYpos || crispY + upperBoxH,
                                M, crispX2, lastDataSetYpos || crispY, V, lastDataSetYpos || crispY + upperBoxH]
                    };

                    upperBoxBorderEle = dataObj.graphics.upperBoxBorderEle;

                    if (!upperBoxBorderEle) {
                        upperBoxBorderEle = dataObj.graphics.upperBoxBorderEle = paper.path(attr, upperBoxContainer);
                        newupperBoxBorderEle = true;
                    }
                    else
                    {
                        upperBoxBorderEle.animateWith(dummyObj, animObj, attr, animationDuration,
                            animType, (animFlag && animCallBack));
                    }

                    upperBoxBorderEle.attr(hoverOutEffects.upperBoxBorder);

                    // draw upperQuartileBorder element
                    attr = {
                        path: [M, crispX, (lastDataSetYpos || crispY), H, (crispX + columnWidth)]
                    };

                    upperQuartileEle = dataObj.graphics.upperQuartileEle;

                    if (!upperQuartileEle) {
                        upperQuartileEle = dataObj.graphics.upperQuartileEle = paper.path(attr, upperBoxContainer);
                        newupperQuartileEle = true;
                    }
                    else
                    {
                        upperQuartileEle.animateWith(dummyObj, animObj, attr, animationDuration,
                            animType, (animFlag && animCallBack));
                    }

                    upperQuartileEle.attr(hoverOutEffects.upperQuartile);

                    errorStartPos = crispY;
                    errorBarWidth = columnWidth * (conf.whiskerslimitswidthratio / 100);
                    halfErrorBarW = errorBarWidth / 2;

                    // Vertical Error drawing
                    errorValPos = yAxis.getAxisPosition(config.max);
                    crispyY = errorValPos;
                    crispyX = crispX;

                    crispyY = mathRound(errorValPos) +
                        (config.upperWhiskerThickness % 2 / 2);
                    crispX = mathRound(crispX + (columnWidth / 2)) +
                        (config.upperWhiskerThickness % 2 / 2);

                    errorPath = [
                        M, crispX, lastDataSetYpos || errorStartPos,
                        V, mathMin(lastDataSetYpos || crispyY, upperBoxStartPos),
                        M, crispX - halfErrorBarW, mathMin(lastDataSetYpos || crispyY, upperBoxStartPos),
                        H, (crispX + halfErrorBarW)
                    ];

                    upperWhiskerEle = dataObj.graphics.upperWhiskerEle;

                    attr = {
                        path: errorPath,
                        // In case of tooltip disabled this element should act as the hot element.
                        ishot: !showTooltip,
                        'stroke-width': config.upperWhiskerThickness,
                        'cursor': setLink ? POINTER : BLANKSTRING,
                        'stroke-linecap': ROUND
                    };

                    if (!upperWhiskerEle) {
                        upperWhiskerEle = dataObj.graphics.upperWhiskerEle =
                         paper.path(attr, upperWhiskerContainer);
                        newupperWhiskerEle = true;
                    }
                    else
                    {
                        upperWhiskerEle.animateWith(dummyObj, animObj, attr, animationDuration,
                            animType, (animFlag && animCallBack));
                    }

                    upperWhiskerEle.attr({
                        stroke: config.upperWhiskerColor
                    });

                    upperWhiskerEle.shadow({opacity : config.upperWhiskerShadowOpacity}, shadowContainer);
                    smartLabel.useEllipsesOnOverflow(chart.config.useEllipsesWhenOverflow);
                    smartLabel.setStyle(style);
                    smartText = smartLabel.getOriSize(numberFormatter.dataLabels(config.max));
                    lineHeight = (rotateValues ? smartText.width :
                        smartText.height);
                    labelTopY = errorValPos - config.upperWhiskerThickness *
                        0.5 - valuePadding - lineHeight * (rotateValues ? 0.5 : 1);

                    if ((labelTopY -  (rotateValues ? (lineHeight / 2) : 0)) < chartConfig.canvasTop) {
                        labelTopY = chartConfig.canvasTop + (rotateValues ? (lineHeight / 2) : 0);
                    }

                    attr = {
                        text: numberFormatter.dataLabels(config.max),
                        x: crispyX + columnWidth / 2,
                        title: (upperQuartile.originalText || BLANKSTRING),
                        y: labelTopY,
                        'text-anchor': rotateValues ? POSITION_MIDDLE : textAlign,
                        'vertical-align': rotateValues ? POSITION_MIDDLE : POSITION_TOP,
                        'visibility': visibleStr,
                        direction: conf.textDirection,
                        fill: style.color,
                        transform: paper.getSuggestiveRotation(rotateValues, crispyX + columnWidth / 2, labelTopY),
                        'text-bound': [style.backgroundColor, style.borderColor,
                            style.borderThickness, style.borderPadding,
                            style.borderRadius, style.borderDash
                        ]
                    };

                    if (config.showMaxValues) {
                        if (!graphic.label[3]) {
                            graphic.label[3] =
                                paper.text(attr, dataLabelContainer);
                                // .hover(rolloverResponseSetter(plotItem, set.hoverEffects),
                                //     rolloutResponseSetter(plotItem, hoverOutEffects))
                        }
                        else {
                            graphic.label[3].show();
                            x = crispyX + columnWidth / 2;
                            y = lastDataSetYpos || labelTopY;

                            graphic.label[3].attr({
                                text: numberFormatter.dataLabels(config.max),
                                title: (upperQuartile.originalText || BLANKSTRING),
                                'text-anchor': rotateValues ? POSITION_MIDDLE : textAlign,
                                'vertical-align': rotateValues ? POSITION_MIDDLE : POSITION_TOP,
                                'visibility': visibleStr,
                                direction: conf.textDirection,
                                fill: style.color,
                                'text-bound': [style.backgroundColor, style.borderColor,
                                    style.borderThickness, style.borderPadding,
                                    style.borderRadius, style.borderDash
                                ]
                            });

                            graphic.label[3].animateWith(dummyObj, animObj, {
                                x: x,
                                y: y,
                                transform: paper.getSuggestiveRotation(rotateValues, x, y)
                            }, animationDuration, animType, (animFlag && animCallBack));
                        }
                        graphic.label[3]
                            .data(GROUPID, groupId);
                    }
                    else {
                        graphic.label[3] && graphic.label[3].hide() && graphic.label[3].attr({'text-bound': []});
                    }

                    crispX = mathRound(xPos) + lowerBoxBorder.borderWidth % 2 *
                        0.5;
                    crispX2 = mathRound(xPos + columnWidth) +
                        lowerBoxBorder.borderWidth % 2 * 0.5;
                    crispY = mathRound(yMedPos + lowerBoxH) +
                        lowerQuartile.borderWidth % 2 * 0.5;

                    lowerBoxYPos = lastDataSetYpos || yMedPos;
                    lowerBoxHeight = mathMax(mathMin(lastDataSetHeight, (crispY - yMedPos)), 0);

                    lowerBoxEndPos = (lowerBoxYPos + lowerBoxHeight);

                    // draw lower element
                    attr = {
                        x: crispX,
                        y: lowerBoxYPos,
                        width: mathMax(columnWidth, 0),
                        height: lowerBoxHeight,
                        r: 0
                    };

                    lowerBoxElem = dataObj.graphics.lowerBoxElem;

                    if (!lowerBoxElem) {
                        lowerBoxElem = dataObj.graphics.lowerBoxElem = paper.rect(attr, lowerBoxContainer);
                        newlowerBoxElem = true;
                    }
                    else
                    {
                        lowerBoxElem.animateWith(dummyObj, animObj, attr, animationDuration,
                            animType, (animFlag && animCallBack));
                    }

                    lowerBoxElem.attr(hoverOutEffects.lowerBox)
                        .shadow({opacity : showShadow ? conf.lowerBoxAlpha / 100 : 0}, shadowContainer);

                    // draw lowerBoxBorder element
                    attr = {
                        path: [M, crispX, lastDataSetYpos || yMedPos, V, lastDataSetYpos || yMedPos +
                                lowerBoxH, M, crispX2, lastDataSetYpos || yMedPos, V,
                                lastDataSetYpos || yMedPos + lowerBoxH]
                    };

                    lowerBoxBorderEle = dataObj.graphics.lowerBoxBorderEle;

                    if (!lowerBoxBorderEle) {
                        lowerBoxBorderEle = dataObj.graphics.lowerBoxBorderEle = paper.path(attr, lowerBoxContainer);
                        newlowerBoxBorderEle = true;
                    }
                    else
                    {
                        lowerBoxBorderEle.animateWith(dummyObj, animObj, attr, animationDuration,
                            animType, (animFlag && animCallBack));
                    }

                    lowerBoxBorderEle.attr(hoverOutEffects.lowerBoxBorder);

                    // draw lowerQuartileBorder element
                    crispY = mathRound(yMedPos + lowerBoxH) +
                        lowerQuartile.borderWidth % 2 * 0.5;

                    attr = {
                        path: [M, crispX, lastDataSetYpos || crispY, H, (crispX + columnWidth)]
                    };

                    lowerQuartileEle = dataObj.graphics.lowerQuartileEle;

                    if (!lowerQuartileEle) {
                        lowerQuartileEle = dataObj.graphics.lowerQuartileEle = paper.path(attr, lowerBoxContainer);
                        newlowerQuartileEle = true;
                    }
                    else
                    {
                        lowerQuartileEle.animateWith(dummyObj, animObj, attr, animationDuration,
                            animType, (animFlag && animCallBack));
                    }

                    lowerQuartileEle.attr(hoverOutEffects.lowerQuartile);

                    errorStartPos = crispY;
                    errorBarWidth = columnWidth * (conf.whiskerslimitswidthratio / 100);
                    halfErrorBarW = errorBarWidth / 2;

                    // Vertical Error drawing
                    errorValPos = yAxis.getAxisPosition(config.min);
                    crispyY = errorValPos;
                    crispyX = crispX;

                    crispyY = mathRound(errorValPos) +
                        (config.lowerWhiskerThickness % 2 / 2);
                    crispyX = mathRound(crispyX + (columnWidth / 2)) +
                        (config.lowerWhiskerThickness % 2 / 2);

                    errorPath = [
                        M, crispyX, lastDataSetYpos || errorStartPos,
                        V, mathMax(lastDataSetYpos || crispyY, lowerBoxEndPos),
                        M, crispyX - halfErrorBarW, mathMax(lastDataSetYpos || crispyY, lowerBoxEndPos),
                        H, (crispyX + halfErrorBarW)
                    ];

                    lowerWhiskerEle = dataObj.graphics.lowerWhiskerEle;

                    smartLabel.setStyle(style);
                    smartText = smartLabel.getOriSize(numberFormatter.dataLabels(config.min));
                    lineHeight = (rotateValues ? smartText.width :
                        smartText.height);

                    labelBottomY = errorValPos + (config.lowerWhiskerThickness * 0.5) + valuePadding;

                    if ((labelBottomY + lineHeight) > chartConfig.canvasBottom) {
                        labelBottomY = chartConfig.canvasBottom - lineHeight;
                    }

                    attr = {
                        text: numberFormatter.dataLabels(config.min),
                        x: crispyX,
                        title: (upperQuartile.originalText || BLANKSTRING),
                        y: labelBottomY,
                        'text-anchor': rotateValues ? POSITION_END : textAlign,
                        'vertical-align': rotateValues ? POSITION_MIDDLE : POSITION_TOP,
                        'visibility': visibleStr,
                        direction: conf.textDirection,
                        fill: style.color,
                        transform: paper.getSuggestiveRotation(rotateValues, crispyX, labelBottomY),
                        'text-bound': [style.backgroundColor, style.borderColor,
                            style.borderThickness, style.borderPadding,
                            style.borderRadius, style.borderDash
                        ]
                    };

                    if (config.showMinValues) {
                        if (!graphic.label[4]) {
                            graphic.label[4] =
                                paper.text(attr, dataLabelContainer);
                                // .hover(rolloverResponseSetter(plotItem, set.hoverEffects),
                                //     rolloutResponseSetter(plotItem, hoverOutEffects))
                        }
                        else {
                            graphic.label[4].show();
                            x = crispyX;
                            y = lastDataSetYpos || labelBottomY;

                            graphic.label[4].animateWith(dummyObj, animObj, {
                                x: x,
                                y: y,
                                transform: paper.getSuggestiveRotation(rotateValues, x, y)
                            }, animationDuration, animType, (animFlag && animCallBack));

                            graphic.label[4].attr({
                                text: numberFormatter.dataLabels(config.min),
                                title: (upperQuartile.originalText || BLANKSTRING),
                                'text-anchor': rotateValues ? POSITION_END : textAlign,
                                'vertical-align': rotateValues ? POSITION_MIDDLE : POSITION_TOP,
                                'visibility': visibleStr,
                                direction: conf.textDirection,
                                fill: style.color,
                                'text-bound': [style.backgroundColor, style.borderColor,
                                    style.borderThickness, style.borderPadding,
                                    style.borderRadius, style.borderDash
                                ]
                            });
                        }
                        graphic.label[4]
                            .data(GROUPID, groupId);
                    }
                    else {
                        graphic.label[4] && graphic.label[4].hide() && graphic.label[4].attr({'text-bound': []});
                    }

                    attr = {
                        path: errorPath,
                        // In case of tooltip disabled this element should act as the hot element.
                        ishot: !showTooltip,
                        'stroke-width': config.lowerWhiskerThickness,
                        'cursor': setLink ? POINTER : BLANKSTRING,
                        'stroke-linecap': ROUND
                    };

                    if (!lowerWhiskerEle) {
                        lowerWhiskerEle = dataObj.graphics.lowerWhiskerEle =
                         paper.path(attr, lowerWhiskerContainer);
                        newlowerWhiskerEle = true;
                    }
                    else
                    {
                        lowerWhiskerEle.animateWith(dummyObj, animObj, attr, animationDuration,
                            animType, (animFlag && animCallBack));
                    }

                    lowerWhiskerEle.attr({
                        stroke: config.lowerWhiskerColor
                    });

                    lowerWhiskerEle.shadow({opacity : config.lowerWhiskerShadowOpacity}, shadowContainer);

                    // draw medianBorder
                    crispY = mathRound(yMedPos) + median.borderWidth % 2 * 0.5;

                    attr = {
                        path: [M, crispX, lastDataSetYpos || crispY, H, (crispX + columnWidth)]
                    };

                    midLineElem = dataObj.graphics.midLineElem;

                    if (!midLineElem) {
                        midLineElem = dataObj.graphics.midLineElem = paper.path(attr, medianContainer);
                        newmidLineElem = true;
                    }
                    else
                    {
                        midLineElem.animateWith(dummyObj, animObj, attr, animationDuration,
                            animType, (animFlag && animCallBack));
                    }

                    midLineElem.attr(hoverOutEffects.median);

                    hoverInAttr = {
                        upperBoxElem: config.setUpperBoxRolloverAttr,
                        lowerBoxElem: config.setLowerBoxRolloverAttr,
                        upperBoxBorderEle: config.setUpperBoxBorderRolloverAttr,
                        lowerBoxBorderEle: config.setLowerBoxBorderRolloverAttr,
                        upperQuartileEle: config.setUpperQuartileRolloverAttr,
                        lowerQuartileEle: config.setLowerQuartileRolloverAttr,
                        midLineElem: config.setMedianRolloverAttr

                    };

                    hoverOutAttr = {
                        upperBoxElem: config.setUpperBoxRolloutAttr,
                        lowerBoxElem: config.setLowerBoxRolloutAttr,
                        upperBoxBorderEle: config.setUpperBoxBorderRolloutAttr,
                        lowerBoxBorderEle: config.setLowerBoxBorderRolloutAttr,
                        upperQuartileEle: config.setUpperQuartileRolloutAttr,
                        lowerQuartileEle: config.setLowerQuartileRolloutAttr,
                        midLineElem: config.setMedianRolloutAttr
                    };

                    upperBoxElem.data(GROUPID, groupId)
                        .data(EVENTARGS, eventArgs)
                        .data(showHoverEffectStr, showHoverEffect)
                        .data(SETROLLOVERATTR, hoverInAttr)
                        .data(SETROLLOUTATTR, hoverOutAttr);

                    if (newupperBoxElem) {
                        upperBoxElem
                        .click(clickFunc)
                        .hover(
                                rolloverResponseSetter(dataObj.graphics),
                                rolloutResponseSetter(dataObj.graphics)
                            );
                    }

                    lowerBoxElem.data(GROUPID, groupId)
                        .data(EVENTARGS, eventArgs)
                        .data(showHoverEffectStr, showHoverEffect)
                        .data(SETROLLOVERATTR, hoverInAttr)
                        .data(SETROLLOUTATTR, hoverOutAttr);


                    if (newlowerBoxElem) {
                        lowerBoxElem
                        .click(clickFunc)
                        .hover(
                                rolloverResponseSetter(dataObj.graphics),
                                rolloutResponseSetter(dataObj.graphics)
                            );
                    }

                    upperBoxBorderEle.data(GROUPID, groupId)
                        .data(EVENTARGS, eventArgs)
                        .data(showHoverEffectStr, showHoverEffect)
                        .data(SETROLLOVERATTR, hoverInAttr)
                        .data(SETROLLOUTATTR, hoverOutAttr);

                    if (newupperBoxBorderEle) {
                        upperBoxBorderEle
                        .click(clickFunc)
                        .hover(
                                rolloverResponseSetter(dataObj.graphics),
                                rolloutResponseSetter(dataObj.graphics)
                            );
                    }

                    lowerBoxBorderEle.data(GROUPID, groupId)
                        .data(EVENTARGS, eventArgs)
                        .data(showHoverEffectStr, showHoverEffect)
                        .data(SETROLLOVERATTR, hoverInAttr)
                        .data(SETROLLOUTATTR, hoverOutAttr);

                    if (newlowerBoxBorderEle) {
                        lowerBoxBorderEle
                        .click(clickFunc)
                        .hover(
                                rolloverResponseSetter(dataObj.graphics),
                                rolloutResponseSetter(dataObj.graphics)
                            );
                    }

                    upperQuartileEle.data(GROUPID, groupId)
                        .data(EVENTARGS, eventArgs)
                        .data(showHoverEffectStr, showHoverEffect)
                        .data(SETROLLOVERATTR, hoverInAttr)
                        .data(SETROLLOUTATTR, hoverOutAttr);

                    if (newupperQuartileEle) {
                        upperQuartileEle
                        .click(clickFunc)
                        .hover(
                                rolloverResponseSetter(dataObj.graphics),
                                rolloutResponseSetter(dataObj.graphics)
                            );
                    }

                    lowerQuartileEle.data(GROUPID, groupId)
                        .data(EVENTARGS, eventArgs)
                        .data(showHoverEffectStr, showHoverEffect)
                        .data(SETROLLOVERATTR, hoverInAttr)
                        .data(SETROLLOUTATTR, hoverOutAttr);

                    if (newlowerQuartileEle) {
                        lowerQuartileEle
                        .click(clickFunc)
                        .hover(
                                rolloverResponseSetter(dataObj.graphics),
                                rolloutResponseSetter(dataObj.graphics)
                            );
                    }

                    midLineElem.data(GROUPID, groupId)
                        .data(EVENTARGS, eventArgs)
                        .data(showHoverEffectStr, showHoverEffect)
                        .data(SETROLLOVERATTR, hoverInAttr)
                        .data(SETROLLOUTATTR, hoverOutAttr);

                    if (newmidLineElem) {
                        midLineElem
                        .click(clickFunc)
                        .hover(
                                rolloverResponseSetter(dataObj.graphics),
                                rolloutResponseSetter(dataObj.graphics)
                            );
                    }

                    upperWhiskerEle.data(GROUPID, groupId)
                        .data(EVENTARGS, eventArgs)
                        .data(showHoverEffectStr, showHoverEffect)
                        .data(SETROLLOVERATTR, hoverInAttr)
                        .data(SETROLLOUTATTR, hoverOutAttr);

                    if (newupperWhiskerEle) {
                        upperWhiskerEle
                        .click(clickFunc)
                        .hover(
                                rolloverResponseSetter(dataObj.graphics),
                                rolloutResponseSetter(dataObj.graphics)
                            );
                    }

                    lowerWhiskerEle.data(GROUPID, groupId)
                        .data(EVENTARGS, eventArgs)
                        .data(showHoverEffectStr, showHoverEffect)
                        .data(SETROLLOVERATTR, hoverInAttr)
                        .data(SETROLLOUTATTR, hoverOutAttr);

                    if (newlowerWhiskerEle) {
                        lowerWhiskerEle
                        .click(clickFunc)
                        .hover(
                                rolloverResponseSetter(dataObj.graphics),
                                rolloutResponseSetter(dataObj.graphics)
                            );
                    }

                    textAlign = rotateValues ? POSITION_LEFT :
                            POSITION_MIDDLE;

                    attr = {
                        text: upperQuartile.displayValue,
                        x: xPos + (columnWidth / 2),
                        title: (upperQuartile.originalText || BLANKSTRING),
                        y: yTopPos - valuePadding,
                        'text-anchor': rotateValues ? POSITION_START : textAlign,
                        'vertical-align': rotateValues ? POSITION_MIDDLE : POSITION_BOTTOM,
                        'visibility': visibleStr,
                        direction: conf.textDirection,
                        fill: style.color,
                        transform: paper.getSuggestiveRotation(rotateValues, xPos + (columnWidth / 2),
                            yTopPos - valuePadding),
                        'text-bound': [style.backgroundColor, style.borderColor,
                            style.borderThickness, style.borderPadding,
                            style.borderRadius, style.borderDash
                        ]
                    };

                    if (defined(upperQuartile.displayValue) &&
                        upperQuartile.displayValue !== BLANK && config.showQ3Values) {
                        if (!graphic.label[0]) {
                            graphic.label[0] =
                                paper.text(attr, dataLabelContainer);
                                // .hover(rolloverResponseSetter(plotItem, set.hoverEffects),
                                //     rolloutResponseSetter(plotItem, hoverOutEffects))
                        }
                        else {
                            graphic.label[0].show();
                            x = xPos + (columnWidth / 2);
                            y = lastDataSetYpos || yTopPos - valuePadding;
                            graphic.label[0].animateWith(dummyObj, animObj, {
                                x: x,
                                y: y,
                                transform: paper.getSuggestiveRotation(rotateValues, x, y)
                            }, animationDuration, animType, (animFlag && animCallBack));

                            graphic.label[0].attr({
                                text: upperQuartile.displayValue,
                                title: (upperQuartile.originalText || BLANKSTRING),
                                'text-anchor': rotateValues ? POSITION_START : textAlign,
                                'vertical-align': rotateValues ? POSITION_MIDDLE : POSITION_BOTTOM,
                                'visibility': visibleStr,
                                direction: conf.textDirection,
                                fill: style.color,
                                'text-bound': [style.backgroundColor, style.borderColor,
                                    style.borderThickness, style.borderPadding,
                                    style.borderRadius, style.borderDash
                                ]
                            });
                        }
                        graphic.label[0]
                            .data(GROUPID, groupId);
                    }
                    else {
                        graphic.label[0] && graphic.label[0].hide() && graphic.label[0].attr({'text-bound': []});
                    }

                    attr = {
                        text: median.displayValue,
                        x: crispX + columnWidth/2,
                        y: yMedPos - valuePadding,
                        title: (median.originalText || BLANKSTRING),
                        'text-anchor': rotateValues ? POSITION_START : textAlign,
                        'vertical-align': rotateValues ? POSITION_MIDDLE : POSITION_BOTTOM,
                        'visibility': visibleStr,
                        direction: conf.textDirection,
                        fill: style.color,
                        transform: paper.getSuggestiveRotation(rotateValues, crispX + columnWidth/2,
                            yMedPos - valuePadding),
                        'text-bound': [style.backgroundColor, style.borderColor,
                            style.borderThickness, style.borderPadding,
                            style.borderRadius, style.borderDash
                        ]
                    };

                    if (defined(median.displayValue) && median.displayValue !== BLANK && config.showMedianValues) {
                        if (!graphic.label[1]) {
                            graphic.label[1] =
                                paper.text(attr, dataLabelContainer);
                                // .hover(rolloverResponseSetter(plotItem, set.hoverEffects),
                                //     rolloutResponseSetter(plotItem, hoverOutEffects))
                        }
                        else {
                            graphic.label[1].show();

                            x = crispX + columnWidth/2;
                            y = lastDataSetYpos || yMedPos - valuePadding;

                            graphic.label[1].animateWith(dummyObj, animObj, {
                                x: x,
                                y: y,
                                transform: paper.getSuggestiveRotation(rotateValues, x, y)
                            }, animationDuration, animType, (animFlag && animCallBack));

                            graphic.label[1].attr({
                                text: median.displayValue,
                                title: (median.originalText || BLANKSTRING),
                                'text-anchor': rotateValues ? POSITION_START : textAlign,
                                'vertical-align': rotateValues ? POSITION_MIDDLE : POSITION_BOTTOM,
                                'visibility': visibleStr,
                                direction: conf.textDirection,
                                fill: style.color,
                                'text-bound': [style.backgroundColor, style.borderColor,
                                    style.borderThickness, style.borderPadding,
                                    style.borderRadius, style.borderDash
                                ]
                            });

                        }
                        graphic.label[1]
                            .data(GROUPID, groupId);
                    }
                    else {
                        graphic.label[1] && graphic.label[1].hide() && graphic.label[1].attr({'text-bound': []});
                    }

                    attr = {
                        text: lowerQuartile.displayValue,
                        x: xPos + columnWidth / 2,
                        y: yBottomPos + valuePadding,
                        title: (lowerQuartile.originalText || BLANKSTRING),
                        'text-anchor': rotateValues ? POSITION_START : textAlign,
                        'vertical-align': rotateValues ? POSITION_MIDDLE : POSITION_TOP,
                        'visibility': visibleStr,
                        direction: conf.textDirection,
                        fill: style.color,
                        transform: paper.getSuggestiveRotation(rotateValues, xPos + columnWidth / 2,
                            yBottomPos + valuePadding),
                        'text-bound': [style.backgroundColor, style.borderColor,
                            style.borderThickness, style.borderPadding,
                            style.borderRadius, style.borderDash
                        ]
                    };

                    if (defined(lowerQuartile.displayValue) &&
                        lowerQuartile.displayValue !== BLANK && config.showQ1Values) {
                        if (!graphic.label[2]) {
                            graphic.label[2] =
                                paper.text(attr, dataLabelContainer);
                                // .hover(rolloverResponseSetter(plotItem, set.hoverEffects),
                                //     rolloutResponseSetter(plotItem, hoverOutEffects))
                        }
                        else {
                            graphic.label[2].show();

                            x = xPos + columnWidth / 2;
                            y = lastDataSetYpos || yBottomPos + valuePadding;

                            graphic.label[2].animateWith(dummyObj, animObj, {
                                x: x,
                                y: y,
                                transform: paper.getSuggestiveRotation(rotateValues, x, y)
                            }, animationDuration, animType, (animFlag && animCallBack));

                            graphic.label[2].attr({
                                text: lowerQuartile.displayValue,
                                title: (lowerQuartile.originalText || BLANKSTRING),
                                'text-anchor': rotateValues ? POSITION_START : textAlign,
                                'vertical-align': rotateValues ? POSITION_MIDDLE : POSITION_TOP,
                                'visibility': visibleStr,
                                direction: conf.textDirection,
                                fill: style.color,
                                'text-bound': [style.backgroundColor, style.borderColor,
                                    style.borderThickness, style.borderPadding,
                                    style.borderRadius, style.borderDash
                                ]
                            });
                        }
                        graphic.label[2]
                            .data(GROUPID, groupId);
                    }
                    else {
                        graphic.label[2] && graphic.label[2].hide() && graphic.label[2].attr({'text-bound': []});
                    }

                    animFlag && animCallBack();

                    if (showTooltip) {
                        upperBoxElem.tooltip(toolText);
                        lowerBoxElem.tooltip(toolText);
                        upperBoxBorderEle.tooltip(toolText);
                        lowerBoxBorderEle.tooltip(toolText);
                        upperQuartileEle.tooltip(toolText);
                        lowerQuartileEle.tooltip(toolText);
                        midLineElem.tooltip(toolText);
                        upperWhiskerEle.tooltip(toolText);
                        lowerWhiskerEle.tooltip(toolText);
                    }
                    else {
                        upperBoxElem.tooltip(false);
                        lowerBoxElem.tooltip(false);
                        upperBoxBorderEle.tooltip(false);
                        lowerBoxBorderEle.tooltip(false);
                        upperQuartileEle.tooltip(false);
                        lowerQuartileEle.tooltip(false);
                        midLineElem.tooltip(false);
                        upperWhiskerEle.tooltip(false);
                        lowerWhiskerEle.tooltip(false);
                    }

                    xPos += (columnWidth / 2);
                    dataSet.components.mean.components.data[i].config.xPos = xPos;
                    dataSet.components.sd.components.data[i].config.xPos = xPos;
                    dataSet.components.qd.components.data[i].config.xPos = xPos;
                    dataSet.components.md.components.data[i].config.xPos = xPos;

                    for (j = 0; j < conf.maxNumberOfOutliers; j++) {
                        dataSet.components.outliers[j].components.data[i].config.xPos = xPos;
                    }

                }

                dataSet.flag = true;
                removeDataArrLen && dataSet.remove();
            },

            // Function to remove a data from a dataset during real time update.
            remove : function () {
                var dataSet = this,
                    components = dataSet.components,
                    removeDataArr = components.removeDataArr,
                    pool = components.pool || (components.pool = {
                        element :[],
                        hotElement : [],
                        label : []
                    }),
                    len = removeDataArr.length,
                    removeData,
                    maxminFlag = dataSet.maxminFlag,
                    ele,
                    graphics,
                    i,
                    innerLen,
                    j;

                for (i = 0; i < len; i++) {
                    removeData = removeDataArr[0];
                    removeDataArr.splice(0,1);
                    // In case of non existing data plot continue;
                    if (!removeData || !removeData.graphics) {
                        continue;
                    }

                    graphics = removeData.graphics;
                    for (ele in graphics) {
                        if (ele !== LABEL) {
                            graphics[ele].shadow({opacity: 0});
                            graphics[ele].hide();
                        }
                        else {
                            innerLen = graphics[ele].length;
                            for (j = 0; j < innerLen; j++) {
                                if (graphics[ele][j]) {
                                    graphics[ele][j].shadow({opacity: 0});
                                    graphics[ele][j].hide();
                                    graphics[ele][j].attr({'text-bound': []});
                                }
                            }
                        }
                    }

                    // Storing the graphic elements for reuse.
                    removeData.graphics.element && (pool.element = pool.element.concat(removeData.graphics.element));
                    removeData.graphics.hotElement && (pool.hotElement = pool.hotElement.concat(removeData.graphics.
                        hotElement));
                    removeData.graphics.label && (pool.label = pool.label.concat(removeData.graphics.label));
                }
                components.pool = pool;
                maxminFlag && dataSet.setMaxMin();
            },

            // Function to remove a data with a given index.
            removeData : function (index, stretch, draw) {
                var dataSet = this,
                    components = dataSet.components,
                    dataStore = components.data,
                    removeDataArr = components.removeDataArr || (components.removeDataArr = []),
                    meanArr = components.mean.components.removeDataArr ||
                                (components.mean.components.removeDataArr = []),
                    sdArr = components.sd.components.removeDataArr ||
                                (components.sd.components.removeDataArr = []),
                    mdArr = components.md.components.removeDataArr ||
                                (components.md.components.removeDataArr = []),
                    qdArr = components.qd.components.removeDataArr ||
                                (components.qd.components.removeDataArr = []),
                    outliersArr,
                    conf = dataSet.config,
                    i,
                    config,
                    groupManager = dataSet.groupManager,
                    len,
                    maxminFlag = dataSet.maxminFlag;

                stretch = stretch || 1;
                index = index || 0;

                // Storing the direction of input data for the type of animation to be done during remove.
                if ((index + stretch)=== dataStore.length ) {
                    dataSet.endPosition = true;
                }
                else if (index === 0 || index === UNDEFINED) {
                    dataSet.endPosition = false;
                }

                components.removeDataArr = removeDataArr = removeDataArr.concat(dataStore.splice(index, stretch));

                components.mean.components.removeDataArr =
                    meanArr.concat(components.mean.components.data.splice(index, stretch));

                components.sd.components.removeDataArr =
                    sdArr.concat(components.sd.components.data.splice(index, stretch));

                components.md.components.removeDataArr =
                    mdArr.concat(components.md.components.data.splice(index, stretch));

                components.qd.components.removeDataArr =
                    qdArr.concat(components.qd.components.data.splice(index, stretch));

                len = components.outliers.length;

                for (i = 0; i < len; i++) {
                    outliersArr = components.outliers[i].components.removeDataArr ||
                                (components.outliers[i].components.removeDataArr = []);

                    components.outliers[i].components.removeDataArr =
                        outliersArr.concat(components.outliers[i].components.data.splice(index, stretch));
                }

                groupManager && groupManager.removeSumLabels &&
                    groupManager.removeSumLabels(index, stretch, dataSet.positionIndex);

                len = removeDataArr.length;
                for (i = 0; i < len; i++) {
                    if (!removeDataArr[i]) {
                        continue;
                    }
                    config = removeDataArr[i].config;
                    if (config.setValue === conf.maxValue || config.setValue === conf.minValue) {
                        maxminFlag = dataSet.maxminFlag = true;
                    }
                    if (maxminFlag) {
                        break;
                    }
                }

                maxminFlag && dataSet.setMaxMin();
                draw && dataSet.draw();
            },

            _addLegendSubDS: function (dataSet) {
                var dataset = dataSet,
                    chart = dataset.chart,
                    config,
                    conf = dataset.config,
                    thisConf = this.config,
                    upperBoxColor = thisConf.upperBoxColor,
                    legend = chart.components.legend,
                    color = conf.anchorBgColor;

                config = {
                    anchorSide: conf.anchorSides,
                    legendBackgroundColor: upperBoxColor,
                    fillColor : convertColor(color),
                    strokeColor: convertColor(COLOR_000000),
                    enabled: this.config.includeInLegend,
                    label : this.JSONData.seriesname && getFirstValue(dataset.name),
                    customLegendIcon: false,
                    spoke: conf.dip ? 1 : 0,
                    drawLine: conf.drawLine ? true : false,
                    lineColor: toRaphaelColor({
                        color: color,
                        alpha: HUNDREDSTRING
                    })
                };
                dataset.itemId = legend.addItems(dataset, dataset.legendInteractivity, config);
            },

            _addLegendOutliers: function (Outliers) {
                var dataset = this,
                    JSONData = dataset.JSONData,
                    chart = dataset.chart,
                    chartAttr = chart.jsonData.chart,
                    strokeColor,
                    fillColor,
                    config,
                    conf = dataset.config,
                    upperBoxColor = conf.upperBoxColor,
                    legend = dataset.chart.components.legend,
                    color = pluck(JSONData.outliericoncolor, chartAttr.outliericoncolor, COLOR_000000);
                strokeColor = COLOR_000000;

                fillColor = {
                    FCcolor: {
                        color: color,
                        angle: 0,
                        ratio: ZEROSTRING,
                        alpha: HUNDREDSTRING
                    }
                };

                config = {
                    anchorSide: pluckNumber(JSONData.outliericonsides, chartAttr.outliericonsides, 3),
                    fillColor : convertColor(color),
                    legendBackgroundColor: upperBoxColor,
                    strokeColor: convertColor(COLOR_000000),
                    enabled: conf.includeInLegend,
                    label : dataset.JSONData.seriesname && OUTLIERS_STR,
                    customLegendIcon: false,
                    spoke: Outliers[0].config.dip ? 1 : 0,
                    drawLine: false,
                    datasetObj: Outliers[0]
                };
                Outliers.visible = pluckNumber(dataset.JSONData.visible,
                    !Number(dataset.JSONData.initiallyhidden), 1) === 1;
                // (Outliers.visible === UNDEFINED) && (Outliers.visible = true);
                Outliers[0] &&
                (Outliers[0].itemId = legend.addItems(Outliers, dataset.legendInteractivityOutliers, config));
            },

            legendInteractivityOutliers : function (dataSet, legendItem) {
                var legend = this,
                    legendConfig = legend.config,
                    config = legendItem.config,
                    legendGraphics = legendItem.graphics,
                    itemHiddenStyle = legendConfig.itemHiddenStyle,
                    hiddenColor = itemHiddenStyle.color,
                    itemStyle = legendConfig.itemStyle,
                    itemTextColor = itemStyle.color,
                    color = config.fillColor,
                    stroke = config.strokeColor,
                    i,
                    visible;

                dataSet.visible = dataSet.visible ? false : true;

                for (i = 0; i < dataSet.length; i++) {

                    visible = dataSet[i].visible;

                    if (visible) {
                        dataSet[i].visible = false;
                    }
                    else {
                        dataSet[i].visible = true;
                    }

                    dataSet[i].draw();

                    if (!visible) {
                        legendGraphics.legendItemSymbol && legendGraphics.legendItemSymbol.attr({
                            fill: color,
                            'stroke': stroke
                        });
                        legendGraphics.legendItemText && legendGraphics.legendItemText.attr({
                            fill: itemTextColor
                        });
                        legendGraphics.legendIconLine && legendGraphics.legendIconLine.attr({
                            'stroke': color
                        });
                    } else {
                        dataSet.visible = false;
                        legendGraphics.legendItemSymbol && legendGraphics.legendItemSymbol.attr({
                            fill: hiddenColor,
                            'stroke': hiddenColor
                        });
                        legendGraphics.legendItemText && legendGraphics.legendItemText.attr({
                            fill: hiddenColor
                        });
                        legendGraphics.legendIconLine && legendGraphics.legendIconLine.attr({
                            'stroke': hiddenColor
                        });
                    }
                }
            },

            _addLegend: function () {
                var dataset = this,
                    chart = dataset.chart,
                    strokeColor,
                    fillColor,
                    config,
                    conf = dataset.config,
                    legend = chart.components.legend,
                    upperBoxColor = conf.upperBoxColor,
                    lowerBoxColor = conf.lowerBoxColor;

                strokeColor = COLOR_000000;

                fillColor = {
                    FCcolor: {
                        color: upperBoxColor + COMMA + lowerBoxColor,
                        angle: 90,
                        ratio: '50, 0',
                        alpha: '100, 100'
                    }
                };

                config = {
                    fillColor : toRaphaelColor(fillColor),
                    legendBackgroundColor: upperBoxColor,
                    strokeColor: toRaphaelColor(strokeColor),
                    rawFillColor: upperBoxColor,
                    rawStrokeColor: strokeColor,
                    enabled: conf.includeInLegend,
                    label : getFirstValue(dataset.JSONData.seriesname),
                    index: dataset.index,
                    mainDS: true
                };
                dataset.itemId = legend.addItems(dataset, dataset.legendInteractivity, config);
            },

            legendInteractivity : function (dataSet, legendItem) {
                var legend = this,
                    legendConfig = legend.config,
                    visible = dataSet.visible,
                    config = legendItem.config,
                    legendGraphics = legendItem.graphics,
                    itemHiddenStyle = legendConfig.itemHiddenStyle,
                    hiddenColor = itemHiddenStyle.color,
                    itemStyle = legendConfig.itemStyle,
                    itemTextColor = itemStyle.color,
                    color = config.fillColor,
                    stroke = config.strokeColor,
                    legendItemIndex = legendItem.index,
                    subDSNumber = dataSet.subDS,
                    legendItems,
                    i;

                visible ? dataSet.hide() : dataSet.show();
                if (!visible) {
                    legendGraphics.legendItemSymbol && legendGraphics.legendItemSymbol.attr({
                        fill: color,
                        'stroke': stroke
                    });
                    legendGraphics.legendItemText && legendGraphics.legendItemText.attr({
                        fill: itemTextColor
                    });
                    legendGraphics.legendItemLine && legendGraphics.legendItemLine.attr({
                        'stroke': color
                    });

                    for (i = legendItemIndex + 1; i <= (legendItemIndex + subDSNumber); i++) {

                        legendItems = legend.components.items[i];
                        legendGraphics = legendItems && legendItems.graphics;

                        if (!legendGraphics) {
                            continue;
                        }

                        config = legendItems.config;
                        itemTextColor = itemStyle.color;
                        color = config.fillColor;
                        stroke = config.strokeColor;

                        legendGraphics.legendItemSymbol && legendGraphics.legendItemSymbol.attr({
                            fill: color,
                            'stroke': stroke
                        });
                        legendGraphics.legendItemText && legendGraphics.legendItemText.attr({
                            fill: itemTextColor
                        });
                        legendGraphics.legendItemLine && legendGraphics.legendItemLine.attr({
                            'stroke': color
                        });
                    }

                } else {
                    legendGraphics.legendItemSymbol && legendGraphics.legendItemSymbol.attr({
                        fill: hiddenColor,
                        'stroke': hiddenColor
                    });
                    legendGraphics.legendItemText && legendGraphics.legendItemText.attr({
                        fill: hiddenColor
                    });
                    legendGraphics.legendItemLine && legendGraphics.legendItemLine.attr({
                        'stroke': hiddenColor
                    });


                    for (i = legendItemIndex + 1; i <= (legendItemIndex + subDSNumber); i++) {

                        legendItems = legend.components.items[i];
                        legendGraphics = legendItems && legendItems.graphics;

                        if (!legendGraphics) {
                            continue;
                        }

                        legendGraphics.legendItemSymbol && legendGraphics.legendItemSymbol.attr({
                            fill: hiddenColor,
                            'stroke': hiddenColor
                        });
                        legendGraphics.legendItemText && legendGraphics.legendItemText.attr({
                            fill: hiddenColor
                        });
                        legendGraphics.legendItemLine && legendGraphics.legendItemLine.attr({
                            'stroke': hiddenColor
                        });
                    }
                }
            },

             /*
             * This function is used to make a dataset visible when clicked on its respective legend.
             * This fucntion is fired from drawGraph() every time a deactivated legend is clicked.
             */
            show : function() {
                var dataSet = this,
                    upperBoxContainer = dataSet.graphics.upperBoxContainer,
                    lowerBoxContainer = dataSet.graphics.lowerBoxContainer,
                    medianContainer = dataSet.graphics.medianContainer,

                    upperWhiskerContainer = dataSet.graphics.upperWhiskerContainer,
                    lowerWhiskerContainer = dataSet.graphics.lowerWhiskerContainer,

                    dataLabelContainer = dataSet.graphics.dataLabelContainer,
                    shadowContainer = dataSet.graphics.shadowContainer,
                    chart = dataSet.chart,
                    yAxis = dataSet.yAxis,
                    i;

                chart._chartAnimation();
                dataSet.visible = true;

                dataSet.components.outliers.visible = true;

                dataSet._conatinerHidden = false;

                upperBoxContainer.show();
                lowerBoxContainer.show();
                medianContainer.show();
                upperWhiskerContainer.show();
                lowerWhiskerContainer.show();
                dataLabelContainer.show();
                shadowContainer.show();

                for (i = 0; i < dataSet.config.maxNumberOfOutliers; i++) {
                    dataSet.components.outliers[i].show();
                }

                chart._setAxisLimits();
                yAxis.draw();
                chart._drawDataset();

                dataSet.components.mean.show();
                dataSet.components.sd.show();
                dataSet.components.qd.show();
                dataSet.components.md.show();
            },

            /*
             * This function is used to make a dataset hidden when clicked on its respective legend.
             * This fucntion is fired from drawGraph() every time an activated legend is clicked.
             */
            hide : function() {
                var dataSet = this,
                    chart = dataSet.chart,
                    yAxis = dataSet.yAxis,
                    len,
                    i;

                chart._chartAnimation();
                dataSet.visible = false;

                len = dataSet.config.maxNumberOfOutliers;

                for (i = 0; i < len; i++) {
                    dataSet.components.outliers[i].hide();
                }

                chart._setAxisLimits();
                yAxis.draw();
                chart._drawDataset();

                dataSet.components.mean.hide();
                dataSet.components.sd.hide();
                dataSet.components.qd.hide();
                dataSet.components.md.hide();

                len = dataSet.config.maxNumberOfOutliers || dataSet.components.outliers.length;

                dataSet.components.outliers.visible = false;

                for (i = 0; i < len; i++) {
                    dataSet.components.outliers[i].visible = false;
                    dataSet.components.outliers[i].draw();
                }
            }

        },'Column', {
            showplotborder: UNDEFINED,
            plotborderdashlen: UNDEFINED,
            plotborderdashgap: UNDEFINED,
            plotfillalpha: UNDEFINED,
            useroundedges: UNDEFINED,
            ratio: UNDEFINED,
            plotborderthickness: UNDEFINED,
            showvalues: UNDEFINED,
            valuepadding: UNDEFINED,
            showtooltip: UNDEFINED,
            maxcolwidth: UNDEFINED,
            rotatevalues: UNDEFINED,
            use3dlighting: UNDEFINED,
            whiskerslimitswidthratio: UNDEFINED,
            outliersupperrangeratio: UNDEFINED,
            outlierslowerrangeratio: UNDEFINED,
            showalloutliers: UNDEFINED,
            showmean: UNDEFINED,
            showsd: UNDEFINED,
            showmd: UNDEFINED,
            showqd: UNDEFINED,
            showminvalues: UNDEFINED,
            showmaxvalues: UNDEFINED,
            showq1values: UNDEFINED,
            showq3values: UNDEFINED,
            showmedianvalues: UNDEFINED
        }]);

    }
]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-subds',
    function () {
        var COMPONENT = 'component',
            DATASET = 'dataset';

        FusionCharts.register(COMPONENT, [DATASET, 'subDS', {
            show : function() {
                var dataSet = this,
                    chart = dataSet.chart,
                    yAxis = dataSet.yAxis;

                chart._chartAnimation();
                dataSet.visible = true;
                dataSet._conatinerHidden = false;
                if (chart.config.transposeAxis) {
                    chart._setAxisLimits();
                    yAxis.draw();
                }
                // Calling the draw function for redrawing the dataset
                dataSet.draw();
            },

            hide : function() {
                var dataSet = this,
                    chart = dataSet.chart,
                    yAxis = dataSet.yAxis;
                chart._chartAnimation();
                dataSet.visible = false;
                if (chart.config.transposeAxis) {
                    chart._setAxisLimits();
                    yAxis.draw();
                }
                dataSet.draw();
            },

            getEventArgs: function () {
                var dataset = this,
                    config = dataset.config || {},
                    eventArgs = {
                        datasetName: dataset.name,
                        datasetIndex: dataset.index,
                        id: config.userID,
                        visible: dataset.visible
                    };
                return eventArgs;
            },

            // Fuction to be fired on legend click
            legendInteractivity : function (dataSet, legendItem) {
                var legend = this,
                    legendConfig = legend.config,
                    visible = dataSet.visible,
                    config = legendItem.config,
                    legendGraphics = legendItem.graphics,
                    itemHiddenStyle = legendConfig.itemHiddenStyle,
                    hiddenColor = itemHiddenStyle.color,
                    itemStyle = legendConfig.itemStyle,
                    itemTextColor = itemStyle.color,
                    color = config.fillColor,
                    attrObj,
                    type,
                    element,
                    stroke = config.strokeColor;

                visible ? dataSet.hide() : dataSet.show();
                attrObj = {
                    'legendItemSymbol': {
                        fill: visible ? hiddenColor : color,
                        'stroke': visible ? hiddenColor : stroke
                    },
                    legendItemText: {
                        fill: visible ? hiddenColor : itemTextColor
                    },
                    legendItemLine: {
                        'stroke': visible ? hiddenColor : (config.lineAttr && config.lineAttr.stroke)
                    }
                };

                for (type in legendGraphics) {
                    element = legendGraphics[type];
                    if (element && attrObj[type]) {
                        element.attr(attrObj[type]);
                    }
                }
            }

        },'Line']);

    }
]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-heatmap',
    function () {
        var global = this,
            lib = global.hcLib,
            //strings
            preDefStr = lib.preDefStr,
            colorStrings = preDefStr.colors,
            COLOR_FFFFFF = colorStrings.FFFFFF,

            configStr = preDefStr.configStr,
            animationObjStr = preDefStr.animationObjStr,
            showHoverEffectStr = preDefStr.showHoverEffectStr,
            columnStr = preDefStr.columnStr,
            shadowStr = preDefStr.shadowStr,
            dataLabelStr = preDefStr.dataLabelStr,
            miterStr = preDefStr.miterStr,
            hiddenStr = preDefStr.hiddenStr,
            visibleStr = preDefStr.visibleStr,
            ZEROSTRING = lib.ZEROSTRING,
            pStr = preDefStr.pStr,
            sStr = preDefStr.sStr,
            POSITION_START = preDefStr.POSITION_START,
            POSITION_TOP = preDefStr.POSITION_TOP,
            POSITION_END = preDefStr.POSITION_END,
            POSITION_BOTTOM = preDefStr.POSITION_BOTTOM,
            NORMAL = preDefStr.NORMAL,
            pInt = function (s, mag) {
                return parseInt(s, mag || 10);
            },
            PXSTRING = 'px',

            tlLabelStr = 'tlLabel',
            blLabelStr = 'blLabel',
            trLabelStr = 'trLabel',
            brLabelStr = 'brLabel',
            BLANK = lib.BLANKSTRING,
            BLANKSTRING = lib.BLANKSTRING,
            //add the tools thats are requared
            pluck = lib.pluck,
            getValidValue = lib.getValidValue,
            pluckNumber = lib.pluckNumber,
            toRaphaelColor = lib.toRaphaelColor,
            isIE = lib.isIE,
            dropHash = lib.regex.dropHash,
            HASHSTRING = lib.HASHSTRING,
            UNDEFINED,
            NONE = 'none',

            PLOTBORDERCOLOR = 'plotBorderColor',
            PLOTGRADIENTCOLOR = 'plotGradientColor',
            SHOWSHADOW = 'showShadow',
            BOLDSTARTTAG = '<b>',
            BOLDENDTAG = '</b>',
            BREAKSTRING = '<br />',
            POINTER = 'pointer',
            SETROLLOVERATTR = 'setRolloverAttr',
            SETROLLOUTATTR = 'setRolloutAttr',
            EVENTARGS = 'eventArgs',
            COMPONENT = 'component',
            DATASET = 'dataset',

            schedular = lib.schedular,
            defined = function(obj) {
                return obj !== UNDEFINED && obj !== null;
            },
            TRACKER_FILL = 'rgba(192,192,192,' + (isIE ? 0.002 : 0.000001) + ')', // invisible but clickable
            TOUCH_THRESHOLD_PIXELS = lib.TOUCH_THRESHOLD_PIXELS,
            CLICK_THRESHOLD_PIXELS = lib.CLICK_THRESHOLD_PIXELS,
            COMMA = ',',
            math = Math,
            mathRound = math.round,
            mathMin = math.min,
            mathMax = math.max,
            hasTouch = lib.hasTouch,
            // hot/tracker threshold in pixels
            HTP = hasTouch ? TOUCH_THRESHOLD_PIXELS :
                CLICK_THRESHOLD_PIXELS,
            setLineHeight = lib.setLineHeight,
            getLightColor = lib.graphics.getLightColor,
            convertColor = lib.graphics.convertColor,
            // POSITION_CENTER = lib.POSITION_CENTER,
            // INT_ZERO = 0,
            HUNDREDSTRING = lib.HUNDREDSTRING;

        FusionCharts.register(COMPONENT, [DATASET, 'HeatMap', {
            type: 'heatmap',
            configure : function () {
                var dataSet = this,
                    chart = dataSet.chart,
                    components = chart.components,
                    postLegendInitFn = components.postLegendInitFn,
                    gradientLegend = components.gradientLegend,
                    chartConfig = chart.config,
                    // dataLabelStyle = chartConfig.dataLabelStyle,
                    style = chartConfig.style,

                    conf = dataSet.config,
                    jsonData = chart.jsonData,

                    JSONData = dataSet.JSONData,
                    setDataArr = JSONData.data,

                    singleSeries = chart.singleseries,

                    len = setDataArr && setDataArr.length,
                    chartAttr = chart.jsonData.chart,
                    colorM = chart.components.colorManager,
                    index = dataSet.index || dataSet.positionIndex,
                    showplotborder,
                    plotColor = conf.plotColor = colorM.getPlotColor(index),
                    plotBorderDash = pluckNumber(JSONData.dashed, chartAttr.plotborderdashed),
                    usePlotGradientColor = pluckNumber(chartAttr.useplotgradientcolor, 1),
                    showTooltip = pluckNumber(chartAttr.showtooltip, 1),
                    parseUnsafeString = lib.parseUnsafeString,
                    yAxisName = parseUnsafeString(chartAttr.yaxisname),
                    xAxisName = parseUnsafeString(chartAttr.xaxisname),
                    tooltipSepChar = parseUnsafeString(pluck(chartAttr.tooltipsepchar, ': ')),

                    parseTooltext = lib.parseTooltext,
                    formatedVal,
                    parserConfig,
                    setTooltext,

                    macroIndices,
                    tempPlotfillAngle,
                    toolText,
                    plotDashLen,
                    plotDashGap,
                    plotBorderThickness,
                    isRoundEdges,
                    showHoverEffect,
                    plotfillAngle,
                    plotFillAlpha,
                    plotRadius,
                    plotFillRatio,
                    plotgradientcolor,
                    plotBorderAlpha,
                    plotBorderColor,
                    plotBorderDashStyle,
                    initailPlotBorderDashStyle,
                    setData,
                    setValue,
                    dataObj,
                    config,

                    colorRange = jsonData.colorrange || {},
                    colorArr,
                    xAxis = chart.components.xAxis[0],
                    yAxis = chart.components.yAxis[0],
                    column,
                    row,
                    mapByPercent = conf.mapByPercent = pluckNumber(colorRange.mapbypercent, 0),
                    mapByCategory = conf.mapByCategory =
                        pluckNumber(chartAttr.mapbycategory, 0),
                    rawData = chart.jsonData,
                    useColorGradient = rawData.colorrange && pluckNumber(rawData.colorrange.gradient),
                    ColorRangeManager = lib.nonGradientColorRange,
                    hoverColor,
                    hoverAlpha,
                    hoverGradientColor,
                    hoverRatio,
                    hoverAngle,
                    hoverBorderColor,
                    hoverBorderAlpha,
                    hoverBorderThickness,
                    hoverBorderDashed,
                    hoverBorderDashGap,
                    hoverBorderDashLen,
                    hoverDashStyle,
                    hoverColorArr,
                    getDashStyle = lib.getDashStyle,
                    dataStore = dataSet.components.data,
                    plotGrid = dataSet.components.plotGrid = [],
                    numberFormatter = chart.components.numberFormatter,
                    toolTipValue,
                    setDisplayValue,
                    definedGroupPadding,
                    isBar = chart.isBar,
                    is3D = chart.is3D,
                    enableAnimation,
                    parentYAxis,
                    setDataDashed,
                    setDataPlotDashLen,
                    setDataPlotDashGap,
                    i,
                    r,
                    c,
                    maxValue = -Infinity,
                    minValue = +Infinity,
                    heatRange,
                    colorObj,
                    tlType = getValidValue(chartAttr.tltype, BLANK),
                    trType = getValidValue(chartAttr.trtype, BLANK),
                    blType = getValidValue(chartAttr.bltype, BLANK),
                    brType = getValidValue(chartAttr.brtype, BLANK),
                    tlLabel,
                    trLabel,
                    blLabel,
                    brLabel,
                    tlTypeToolText = BLANK,
                    trTypeToolText = BLANK,
                    blTypeToolText = BLANK,
                    brTypeToolText = BLANK,
                    percentValue,
                    toolTextValue,
                    font,
                    fontSize,
                    fontColor,
                    fontWeight,
                    fontStyle,
                    value,
                    totalRows = jsonData.rows.row.length,
                    totalColumns = jsonData.columns.column.length,
                    color;

                for (r = 0; r < totalRows; r++) {
                    plotGrid.push([]);
                    for(c = 0; c < totalColumns; c++) {
                        plotGrid[r].push([]);
                    }
                }


                showplotborder = conf.showplotborder = pluckNumber(chartAttr.showplotborder, is3D ? 0 : 1);
                conf.plotDashLen = plotDashLen = pluckNumber(chartAttr.plotborderdashlen, 5);
                conf.plotDashGap = plotDashGap = pluckNumber(chartAttr.plotborderdashgap, 4);
                conf.plotfillAngle = plotfillAngle =  pluckNumber(360 - chartAttr.plotfillangle, (isBar ? 180 : 90));
                conf.plotFillAlpha =  plotFillAlpha = pluck(JSONData.alpha, chartAttr.plotfillalpha, HUNDREDSTRING);
                conf.plotColor = plotColor = pluck(JSONData.color, plotColor);
                conf.isRoundEdges = isRoundEdges = pluckNumber(chartAttr.useroundedges,0);
                conf.plotRadius = plotRadius = pluckNumber(chartAttr.useRoundEdges, conf.isRoundEdges ? 1 : 0);
                conf.plotFillRatio = plotFillRatio = pluck(JSONData.ratio, chartAttr.plotfillratio);
                conf.plotgradientcolor = plotgradientcolor = lib.getDefinedColor(chartAttr.plotgradientcolor,
                    colorM.getColor(PLOTGRADIENTCOLOR));
                !usePlotGradientColor && (plotgradientcolor = BLANKSTRING);
                conf.plotBorderAlpha = plotBorderAlpha = showplotborder ? pluck(chartAttr.plotborderalpha,
                    plotFillAlpha, HUNDREDSTRING): 0;
                conf.plotBorderColor = plotBorderColor = pluck(chartAttr.plotbordercolor,
                    is3D ? COLOR_FFFFFF : colorM.getColor(PLOTBORDERCOLOR));
                conf.plotBorderThickness = plotBorderThickness = pluckNumber(chartAttr.plotborderthickness, 1);
                conf.plotBorderDashStyle = initailPlotBorderDashStyle = plotBorderDash ?
                            getDashStyle(plotDashLen, plotDashGap, plotBorderThickness) : NONE;
                conf.showValues = pluckNumber(JSONData.showvalues, chartAttr.showvalues, 1);
                conf.valuePadding = pluckNumber(chartAttr.valuepadding, 2);
                conf.enableAnimation = enableAnimation = pluckNumber(chartAttr.animation,
                    chartAttr.defaultanimation, 1);
                conf.animation = !enableAnimation ? false : {
                    duration: pluckNumber(chartAttr.animationduration, 1) * 1000
                };
                conf.transposeAnimation =
                    pluckNumber(chartAttr.transposeanimation, enableAnimation);
                conf.transposeAnimDuration = pluckNumber(chartAttr.transposeanimduration, 0.2) * 1000;

                conf.showShadow = (isRoundEdges || is3D) ? pluckNumber(chartAttr.showshadow, 1) :
                    pluckNumber(chartAttr.showshadow, colorM.getColor(SHOWSHADOW));
                conf.showHoverEffect = showHoverEffect = pluckNumber(chartAttr.plothovereffect,
                    chartAttr.showhovereffect, UNDEFINED);
                conf.showTooltip = pluckNumber(chartAttr.showtooltip, 1);
                conf.definedGroupPadding = definedGroupPadding = mathMax(pluckNumber(chartAttr.plotspacepercent), 0);
                conf.plotSpacePercent = mathMax(pluckNumber(chartAttr.plotspacepercent, 20) % 100, 0);
                conf.maxColWidth = pluckNumber(isBar ? chartAttr.maxbarheight : chartAttr.maxcolwidth, 50);
                conf.plotPaddingPercent = pluckNumber(chartAttr.plotpaddingpercent),
                conf.rotateValues = pluckNumber(chartAttr.rotatevalues) ? 270 : 0;
                conf.placeValuesInside = pluckNumber(chartAttr.placevaluesinside, 0);

                font = style.inCanfontFamily;
                fontSize = pInt(style.inCanfontSize, 10);
                fontColor = style.inCancolor;
                fontWeight = NORMAL;
                fontStyle = NORMAL;

                conf.tlLabelStyle = {
                    fontFamily: pluck(chartAttr.tlfont, font),
                    fontSize: pluckNumber(chartAttr.tlfontsize, fontSize) + PXSTRING,
                    color: convertColor(pluck(chartAttr.tlfontcolor, fontColor), 100),
                    fontWeight: fontWeight,
                    fontStyle: fontStyle
                };

                setLineHeight(conf.tlLabelStyle);

                conf.trLabelStyle = {
                    fontFamily: pluck(chartAttr.trfont, font),
                    fontSize: pluckNumber(chartAttr.trfontsize, fontSize) + PXSTRING,
                    color: convertColor(pluck(chartAttr.trfontcolor, fontColor), 100),
                    fontWeight: fontWeight,
                    fontStyle: fontStyle
                };

                conf.brLabelStyle = {
                    fontFamily: pluck(chartAttr.brfont, font),
                    fontSize: pluckNumber(chartAttr.brfontsize, fontSize) + PXSTRING,
                    color: convertColor(pluck(chartAttr.brfontcolor, fontColor), 100),
                    fontWeight: fontWeight,
                    fontStyle: fontStyle
                };

                conf.blLabelStyle = {
                    fontFamily: pluck(chartAttr.blfont, font),
                    fontSize: pluckNumber(chartAttr.blfontsize, fontSize) + PXSTRING,
                    color: convertColor(pluck(chartAttr.blfontcolor, fontColor), 100),
                    fontWeight: fontWeight,
                    fontStyle: fontStyle
                };

                conf.use3DLighting = pluckNumber(chartAttr.use3dlighting, 1);
                conf.parentYAxis = parentYAxis = pluck(JSONData.parentyaxis && JSONData.parentyaxis.toLowerCase(),
                    pStr) === sStr ? 1 : 0 ;
                if (!dataStore) {
                    dataStore = dataSet.components.data = [];
                }

                // Parsing the attributes and values at set level.
                for (i = 0; i < len; i++) {
                    setData = setDataArr && setDataArr[i];
                    dataObj = dataStore[i];
                    config = dataObj && dataObj.config;

                    if (!dataObj) {
                        dataObj = dataStore[i] = {
                            graphics : {}
                        };
                    }

                    if (!dataObj.config) {
                        config = dataStore[i].config = {};

                    }

                    config.showValue = pluckNumber(setData.showvalue, conf.showValues);
                    config.setValue = setValue = numberFormatter.getCleanValue(setData.value);
                    config.setLink  = pluck(setData.link);
                    config.toolTipValue = toolTipValue = numberFormatter.dataLabels(setValue, parentYAxis);
                    config.setDisplayValue = setDisplayValue = parseUnsafeString(setData.displayvalue);
                    config.displayValue = pluck(setDisplayValue, toolTipValue);
                    setDataDashed = pluckNumber(setData.dashed);
                    setDataPlotDashLen = pluckNumber(setData.dashlen, plotDashLen);
                    setDataPlotDashGap = plotDashGap = pluckNumber(setData.dashgap, plotDashGap);

                    maxValue = mathMax(maxValue, setValue);
                    minValue = mathMin(minValue, setValue);

                    config.plotBorderDashStyle = plotBorderDashStyle =  setDataDashed === 1 ?
                        getDashStyle(setDataPlotDashLen, setDataPlotDashGap, plotBorderThickness) :
                            (setDataDashed === 0 ? NONE : initailPlotBorderDashStyle);
                    if (singleSeries) {
                        plotColor = colorM.getPlotColor(i);
                        plotColor = pluck(setData.color, plotColor);
                        plotFillRatio = pluck(setData.ratio, conf.plotFillRatio);
                    }
                    else {
                        plotColor = pluck(setData.color, conf.plotColor);
                    }
                    config.plotFillAlpha = plotFillAlpha = pluck(setData.alpha, conf.plotFillAlpha);

                    // Setting the angle for plot fill for negative data
                    if (setValue < 0 && !isRoundEdges) {

                        tempPlotfillAngle = plotfillAngle;
                        plotfillAngle = isBar ? 180 - plotfillAngle : 360 - plotfillAngle;
                    }
                    config.colorArr = colorArr = lib.graphics.getColumnColor (
                            plotColor + COMMA + conf.plotgradientcolor,
                            plotFillAlpha,
                            plotFillRatio = conf.plotFillRatio,
                            plotfillAngle,
                            isRoundEdges,
                            conf.plotBorderColor,
                            plotBorderAlpha.toString(),
                            (isBar ? 1 : 0),
                            (is3D ? true : false)
                            );

                    formatedVal = config.toolTipValue;
                    tempPlotfillAngle && (plotfillAngle = tempPlotfillAngle);
                }

                conf.maxValue = maxValue;
                conf.minValue = minValue;
                heatRange = maxValue - minValue;

                if (useColorGradient && !mapByCategory) {
                    postLegendInitFn({
                        min: minValue,
                        max: maxValue
                    });

                    // gradientLegend.notifyWhenUpdate(dataSet.updatePlot, dataSet);
                    dataSet.components.colorRange = colorRange = gradientLegend.colorRange;
                }
                else {
                    dataSet.components.colorRange = colorRange = new ColorRangeManager({
                        colorRange: jsonData.colorrange,
                        dataMin: minValue,
                        dataMax: maxValue,
                        sortLegend: 0,
                        mapByCategory: mapByCategory,
                        defaultColor: 'cccccc',
                        numberFormatter: numberFormatter
                    });

                    conf.colorMap = [];

                    for (i = 0; i < colorRange.colorArr.length; i++) {
                        conf.colorMap[i] = {
                            config: colorRange.colorArr[i],
                            dataSet: dataSet
                        };
                        conf.colorMap[i].config.visible = true;
                    }
                    if (conf.colorMap.length === 0) {
                        chart.setChartMessage();
                        gradientLegend && gradientLegend.elem && gradientLegend.elem.gl.carpet.group.hide();
                    }
                }

                for (i = 0; i < len; i++) {
                    setData = setDataArr && setDataArr[i];
                    dataObj = dataStore[i];
                    config = dataObj && dataObj.config;

                    if (mapByPercent) {
                        config.percentValue = percentValue = setData.value && (mathRound((setData.value -
                                                    minValue) / heatRange * 10000) / 100);
                    }
                    else {
                        config.percentValue = UNDEFINED;
                    }

                    config.value = value = mapByCategory ?
                        (setData.colorrangelabel || setData.categoryid) : mapByPercent ? percentValue : config.setValue;

                    if (useColorGradient && !mapByCategory) {
                        color = colorRange.getColorByValue(value);
                    }
                    else {
                        colorObj = colorRange.getColorObj(value);
                        dataObj.legendItemIndex = colorObj.seriesIndex;
                    }
                    if (colorObj === UNDEFINED && color === UNDEFINED) {
                        config.visible = false;
                        continue;
                    }

                    if (colorObj && colorObj.outOfRange) {
                        config.visible = false;
                        config.displayValue = BLANKSTRING;
                        continue;
                    }
                    config.visible = true;

                    plotColor = pluck(setData.color, (colorObj && colorObj.code) || color);
                    config.color = convertColor(plotColor, pluck(setData.alpha, conf.plotFillAlpha));

                    // Parsing the hover effects only if showhovereffect is not 0.
                    if (showHoverEffect !== 0) {

                        hoverColor = pluck(setData.hovercolor, JSONData.hovercolor, chartAttr.plotfillhovercolor,
                            chartAttr.columnhovercolor, plotColor);
                        hoverAlpha = pluck(setData.hoveralpha, JSONData.hoveralpha,
                            chartAttr.plotfillhoveralpha, chartAttr.columnhoveralpha, '25');
                        hoverGradientColor = pluck(setData.hovergradientcolor,
                            JSONData.hovergradientcolor, chartAttr.plothovergradientcolor, plotgradientcolor);
                        !hoverGradientColor && (hoverGradientColor = BLANKSTRING);
                        hoverRatio = pluck(setData.hoverratio,
                            JSONData.hoverratio, chartAttr.plothoverratio, plotFillRatio);
                        hoverAngle = pluckNumber(360 - setData.hoverangle,
                            360 - JSONData.hoverangle, 360 - chartAttr.plothoverangle, plotfillAngle);
                        hoverBorderColor = pluck(setData.borderhovercolor,
                            JSONData.borderhovercolor, chartAttr.plotborderhovercolor, plotBorderColor);
                        hoverBorderAlpha = pluck(setData.borderhoveralpha,
                            JSONData.borderhoveralpha, chartAttr.plotborderhoveralpha, plotBorderAlpha, plotFillAlpha);
                        hoverBorderThickness = pluckNumber(setData.borderhoverthickness,
                            JSONData.borderhoverthickness, chartAttr.plotborderhoverthickness, plotBorderThickness);
                        hoverBorderDashed = pluckNumber(setData.borderhoverdashed,
                            JSONData.borderhoverdashed, chartAttr.plotborderhoverdashed);
                        hoverBorderDashGap = pluckNumber(setData.borderhoverdashgap,
                            JSONData.borderhoverdashgap, chartAttr.plotborderhoverdashgap, plotDashLen);
                        hoverBorderDashLen = pluckNumber(setData.borderhoverdashlen,
                            JSONData.borderhoverdashlen, chartAttr.plotborderhoverdashlen, plotDashGap);
                        hoverDashStyle = hoverBorderDashed ?
                            getDashStyle(hoverBorderDashLen, hoverBorderDashGap, hoverBorderThickness) :
                                plotBorderDashStyle;

                        /* If no hover effects are explicitly defined and
                         * showHoverEffect is not 0 then hoverColor is set.
                         */
                        if (showHoverEffect == 1 && hoverColor === plotColor) {
                            hoverColor = getLightColor(hoverColor, 70);
                        }

                        // setting the hover color array which is always applied except when showHoverEffect is not 0.
                        hoverColorArr = lib.graphics.getColumnColor (
                            hoverColor,
                            hoverAlpha,
                            hoverRatio,
                            hoverAngle,
                            isRoundEdges,
                            hoverBorderColor,
                            hoverBorderAlpha.toString(),
                            (isBar ? 1 : 0),
                            (is3D ? true : false)
                            );

                        config.setRolloutAttr = {
                            fill: toRaphaelColor(config.color),
                            stroke: showplotborder && toRaphaelColor(hoverColorArr[1]),
                            'stroke-width': plotBorderThickness,
                            'stroke-dasharray': plotBorderDashStyle
                        };
                        config.setRolloverAttr = {
                            fill: toRaphaelColor(hoverColorArr[0]),
                            stroke: showplotborder && toRaphaelColor(hoverColorArr[1]),
                            'stroke-width': hoverBorderThickness,
                            'stroke-dasharray': hoverDashStyle
                        };
                    }

                    mapByPercent && (percentValue = numberFormatter.percentValue(percentValue));

                    config.setValue = setValue = numberFormatter.getCleanValue(setData.value);
                    config.toolTipValue = toolTipValue = numberFormatter.dataLabels(setValue, parentYAxis);
                    formatedVal = config.toolTipValue;
                    setTooltext = getValidValue(parseUnsafeString(pluck(setData.tooltext,
                        JSONData.plottooltext, chartAttr.plottooltext)));

                    config.tlLabel = tlLabel = parseUnsafeString(pluck(setData.tllabel, setData.ltlabel));
                    config.trLabel = trLabel = parseUnsafeString(pluck(setData.trlabel, setData.rtlabel));
                    config.blLabel = blLabel = parseUnsafeString(pluck(setData.bllabel, setData.lblabel));
                    config.brLabel = brLabel = parseUnsafeString(pluck(setData.brlabel, setData.rblabel));

                    setDisplayValue = getValidValue(parseUnsafeString(
                        setData.displayvalue));
                    toolTextValue = mapByCategory ?
                        setDisplayValue : pluck(setData.displayvalue, formatedVal);

                    config.displayValue = pluck(setDisplayValue, percentValue, config.toolTipValue);

                    if (tlType !== BLANK) {
                        tlTypeToolText = BOLDSTARTTAG + tlType + tooltipSepChar + BOLDENDTAG;
                    }
                    if (trType !== BLANK) {
                        trTypeToolText = BOLDSTARTTAG + trType + tooltipSepChar + BOLDENDTAG;
                    }
                    if (blType !== BLANK) {
                        blTypeToolText = BOLDSTARTTAG + blType + tooltipSepChar + BOLDENDTAG;
                    }
                    if (brType !== BLANK) {
                        brTypeToolText = BOLDSTARTTAG + brType + tooltipSepChar + BOLDENDTAG;
                    }

                    column = xAxis.getCategoryFromId(setDataArr[i].columnid.toLowerCase());
                    row = yAxis.getCategoryFromId(setDataArr[i].rowid.toLowerCase());

                    //create the tooltext
                    if (!showTooltip) {
                        config.toolText = false;
                    }
                    else {
                        if (formatedVal === null) {
                            toolText = false;
                        }
                        else if (setTooltext !== UNDEFINED) {
                            macroIndices = [1, 2, 5, 6, 7, 14, 93, 94, 95, 96, 97, 98, 112, 113, 114, 115, 116,
                                117];
                            parserConfig = {
                                formattedValue : formatedVal,
                                value: setData.value,
                                yaxisName: yAxisName,
                                xaxisName: xAxisName,
                                displayValue: setDisplayValue,
                                percentValue: mapByPercent ? percentValue : BLANK,
                                tlLabel: tlLabel,
                                trLabel: trLabel,
                                blLabel: blLabel,
                                brLabel: brLabel,
                                rowLabel: row.catObj && row.catObj.label,
                                columnLabel: column.catObj && column.catObj.label,
                                percentDataValue: mapByPercent ? percentValue : BLANK,
                                trtype: trType,
                                tltype: tlType,
                                brType: brType,
                                blType: blType,
                                colorRangeLabel: config.colorRangeLabel
                            };
                            toolText = parseTooltext(setTooltext, macroIndices,
                                parserConfig, setData, chartAttr, parserConfig);
                        }
                        else {
                            toolText = ((mapByPercent ? BOLDSTARTTAG + 'Value' + tooltipSepChar + BOLDENDTAG +
                                formatedVal +
                                BREAKSTRING + BOLDSTARTTAG + 'Percentage' + tooltipSepChar + BOLDENDTAG +
                                percentValue :
                                toolTextValue) +
                            // Now we add special labels in toolTip
                            (tlLabel !== BLANK ? BREAKSTRING +
                                (tlTypeToolText + tlLabel) : BLANK) + (trLabel !== BLANK ? BREAKSTRING +
                                trTypeToolText + trLabel : BLANK) + (blLabel !== BLANK ? BREAKSTRING +
                                blTypeToolText + blLabel : BLANK) + (brLabel !== BLANK ? BREAKSTRING +
                                brTypeToolText + brLabel : BLANK));
                        }
                        config.toolText = toolText;
                        config.setTooltext = toolText;
                    }

                    // dataObj = extend2(dataObj, this.getPointStub(dataObj,
                    //     dataObj.value, BLANK, HCObj, FCObj));
                }
                (chart.hasLegend !== false && (!useColorGradient || mapByCategory)) && dataSet._addLegend();
            },

            /*
             * Function for initializing the column class object.
             * This function is called once.
             * @param {object} chart - The default FutionCharts chart object.
             * @param {number} datasetIndex - The postion index of a dataset.
             * @param {number} stackIndex - The stack index of a dataset.
             */
            init : function(datasetJSON) {
                var dataSet = this,
                    chart = dataSet.chart,
                    components = chart.components,
                    visible,
                    parentYAxis = datasetJSON.parentyaxis && datasetJSON.parentyaxis.toLowerCase() === sStr ? 1 : 0,
                    yAxis = components.yAxis[parentYAxis];



                if (!datasetJSON) {
                    return false;
                }
                dataSet.JSONData = datasetJSON;
                dataSet.yAxis = yAxis;
                dataSet.chartGraphics = chart.chartGraphics;
                dataSet.components = {
                };

                dataSet.graphics = {
                };

                dataSet.visible = visible = pluckNumber(dataSet.JSONData.visible,
                    !Number(dataSet.JSONData.initiallyhidden), 1) === 1;
                dataSet.configure();
            },

            _addLegend: function () {
                var dataset = this,
                    entityComponents = dataset.components.data,
                    chart = dataset.chart,
                    chartAttr = chart.jsonData.chart,
                    strokeColor,
                    fillColor,
                    lightColor,
                    config,
                    conf = dataset.config,
                    colorMap = conf.colorMap,
                    colorRange = dataset.components.colorRange,
                    color,
                    i,
                    j,
                    colorCode,
                    len,
                    item,
                    legend = chart.components.legend,
                    use3DLighting = pluckNumber(chartAttr.us3dlighting, chartAttr.useplotgradientcolor, 1);

                legend.emptyItems();

                for (i = 0, len = colorMap.length; i < len; i++) {
                    item = colorMap[i];
                    color = colorRange.colorArr[i].code;
                    strokeColor = getLightColor(color, 60).replace(dropHash, HASHSTRING);
                    lightColor = getLightColor(color, 40);
                    if (use3DLighting) {
                        lightColor = getLightColor(color, 40);
                        fillColor = {
                            FCcolor: {
                                color: color + COMMA + color + COMMA + lightColor,
                                ratio: '0,70,30',
                                angle: 270,
                                alpha: '100,100,100'
                            }
                        };
                    }
                    else {
                        fillColor = {
                            FCcolor: {
                                color: color,
                                angle: 0,
                                ratio: ZEROSTRING,
                                alpha: HUNDREDSTRING
                            }
                        };
                    }
                    config = {
                        fillColor: toRaphaelColor(fillColor),
                        label: item.config.label,
                        rawFillColor: color,
                        strokeColor: toRaphaelColor(strokeColor),
                        datasetObj: dataset
                    };
                    colorMap[i].legendItemId =
                        chart.components.legend.addItems(item, dataset.legendInteractivity, config);
                }

                for (i = 0; i < entityComponents.length; i++) {
                    colorCode = colorRange.getColorObj(entityComponents[i].config.value).code;

                    for (j = 0; j < colorMap.length; j++) {
                        if (colorMap[j].config.code == colorCode) {
                            entityComponents[i].legendItemId = colorMap[j].legendItemId;
                            entityComponents[i].datasetIndex = j;
                            entityComponents[i].datasetName = colorMap[j].config.label;
                            break;
                        }
                    }
                }
            },

            legendInteractivity: function (item, legendItem) {
                var legend = this,
                    legendConfig = legend.config,
                    visible = item.config.visible,
                    dataset = item.dataSet,
                    config = legendItem.config,
                    legendGraphics = legendItem.graphics,
                    itemHiddenStyle = legendConfig.itemHiddenStyle,
                    hiddenColor = itemHiddenStyle.color,
                    itemStyle = legendConfig.itemStyle,
                    itemTextColor = itemStyle.color,
                    color = config.fillColor,
                    stroke = config.strokeColor;

                visible ? dataset.hide(item) : dataset.show(item);

                if (!visible) {
                    legendGraphics.legendItemSymbol && legendGraphics.legendItemSymbol.attr({
                        fill: color,
                        'stroke': stroke
                    });
                    legendGraphics.legendItemText && legendGraphics.legendItemText.attr({
                        fill: itemTextColor
                    });
                    legendGraphics.legendIconLine && legendGraphics.legendIconLine.attr({
                        'stroke': color
                    });
                } else {
                    legendGraphics.legendItemSymbol && legendGraphics.legendItemSymbol.attr({
                        fill: hiddenColor,
                        'stroke': hiddenColor
                    });
                    legendGraphics.legendItemText && legendGraphics.legendItemText.attr({
                        fill: hiddenColor
                    });
                    legendGraphics.legendIconLine && legendGraphics.legendIconLine.attr({
                        'stroke': hiddenColor
                    });
                }
            },

            hide: function (item) {
                var dataset = this,
                    entityComponents = dataset.components.data,
                    chart = dataset.chart,
                    animationObj = chart.get(configStr, animationObjStr),
                    animType = animationObj.animType,
                    animObj = animationObj.animObj,
                    dummyObj = animationObj.dummyObj,
                    animationDuration = animationObj.duration,
                    colorRange = dataset.components.colorRange,
                    i,
                    len,
                    config,
                    legendItemColor,
                    colorCode;

                legendItemColor = item.config.code;

                for (i = 0, len = entityComponents.length; i < len; i++) {

                    colorCode = colorRange.getColorObj(entityComponents[i].config.value).code;
                    config = entityComponents[i].config;

                    if (legendItemColor === colorCode) {
                        entityComponents[i].graphics.element && entityComponents[i].graphics.element
                        .animateWith(dummyObj, animObj, {
                            'fill-opacity': 0,
                            'stroke-width': 0
                        }, animationDuration, animType);

                        //animFlagHide = false;

                        entityComponents[i].graphics.hotElement &&
                            entityComponents[i].graphics.hotElement.hide();
                        entityComponents[i].graphics.valEle && entityComponents[i].graphics.valEle.hide();

                        entityComponents[i].graphics.tlLabel && entityComponents[i].graphics.tlLabel.hide();
                        entityComponents[i].graphics.trLabel && entityComponents[i].graphics.trLabel.hide();
                        entityComponents[i].graphics.blLabel && entityComponents[i].graphics.blLabel.hide();
                        entityComponents[i].graphics.brLabel && entityComponents[i].graphics.brLabel.hide();
                        config.visible = false;
                        entityComponents[i].visible = false;
                    }
                }
                item.visible = false;
                item.config.visible = false;
            },

            show: function (item) {
                var dataset = this,
                    entityComponents = dataset.components.data,
                    conf = dataset.config,
                    chart = dataset.chart,
                    animationObj = chart.get(configStr, animationObjStr),
                    animType = animationObj.animType,
                    animObj = animationObj.animObj,
                    dummyObj = animationObj.dummyObj,
                    animationDuration = animationObj.duration,
                    config,
                    plotFillAlpha,
                    colorRange = dataset.components.colorRange,
                    i,
                    len,
                    legendItemColor,
                    colorCode;

                legendItemColor = item.config.code;

                for (i = 0, len = entityComponents.length; i < len; i++) {
                    config = entityComponents[i].config;
                    plotFillAlpha = config.plotFillAlpha / 100;
                    colorCode = colorRange.getColorObj(entityComponents[i].config.value).code;

                    if (legendItemColor === colorCode) {

                        entityComponents[i].graphics.element && entityComponents[i].graphics.element
                        .attr({
                            'visibility': visibleStr
                        })
                        .animateWith(dummyObj, animObj, {
                            'fill-opacity': plotFillAlpha,
                            'stroke-width': conf.plotBorderThickness
                        }, animationDuration, animType);

                        //animFlagShow = false;

                        entityComponents[i].graphics.hotElement &&
                            entityComponents[i].graphics.hotElement.show();
                        entityComponents[i].graphics.valEle && entityComponents[i].graphics.valEle.show();

                        entityComponents[i].graphics.tlLabel && entityComponents[i].graphics.tlLabel.show();
                        entityComponents[i].graphics.trLabel && entityComponents[i].graphics.trLabel.show();
                        entityComponents[i].graphics.blLabel && entityComponents[i].graphics.blLabel.show();
                        entityComponents[i].graphics.brLabel && entityComponents[i].graphics.brLabel.show();
                        config.visible = true;
                        entityComponents[i].visible = true;
                    }
                }
                item.visible = true;
                item.config.visible = true;
            },

            updatePlot : function() {
                var dataset = this,
                    minValue = arguments[0],
                    maxValue = arguments[1],

                    conf = dataset.config,
                    chart = dataset.chart,
                    animationObj = chart.get(configStr, animationObjStr),
                    animType = animationObj.animType,
                    animObj = animationObj.animObj,
                    dummyObj = animationObj.dummyObj,
                    animationDuration = animationObj.duration,
                    config,
                    plotFillAlpha,
                    entityComponents = dataset.components.data,
                    i,
                    len,
                    value;

                for (i = 0, len = entityComponents.length; i < len; i++) {

                    config = entityComponents[i].config;
                    plotFillAlpha = config.plotFillAlpha / 100;

                    value = entityComponents[i].config.value;

                    if (value < minValue || value > maxValue) {
                        if(config.visible) {
                            entityComponents[i].graphics.element && entityComponents[i].graphics.element
                            .animateWith(dummyObj, animObj, {
                                'fill-opacity': 0,
                                'stroke-width': 0
                            }, animationDuration, animType);

                            //animFlagHide = false;

                            entityComponents[i].graphics.hotElement &&
                                entityComponents[i].graphics.hotElement.hide();
                            entityComponents[i].graphics.valEle && entityComponents[i].graphics.valEle.hide();

                            entityComponents[i].graphics.tlLabel && entityComponents[i].graphics.tlLabel.hide();
                            entityComponents[i].graphics.trLabel && entityComponents[i].graphics.trLabel.hide();
                            entityComponents[i].graphics.blLabel && entityComponents[i].graphics.blLabel.hide();
                            entityComponents[i].graphics.brLabel && entityComponents[i].graphics.brLabel.hide();
                            config.visible = false;
                            entityComponents[i].visible = false;
                        }
                    }
                    else {
                        if (!config.visible) {
                            entityComponents[i].graphics.element && entityComponents[i].graphics.element
                            .animateWith(dummyObj, animObj, {
                                'fill-opacity': plotFillAlpha,
                                'stroke-width': conf.plotBorderThickness
                            }, animationDuration, animType);

                            //animFlagShow = false;

                            entityComponents[i].graphics.hotElement &&
                                entityComponents[i].graphics.hotElement.show();
                            entityComponents[i].graphics.valEle && entityComponents[i].graphics.valEle.show();

                            entityComponents[i].graphics.tlLabel && entityComponents[i].graphics.tlLabel.show();
                            entityComponents[i].graphics.trLabel && entityComponents[i].graphics.trLabel.show();
                            entityComponents[i].graphics.blLabel && entityComponents[i].graphics.blLabel.show();
                            entityComponents[i].graphics.brLabel && entityComponents[i].graphics.brLabel.show();
                            config.visible = true;
                            entityComponents[i].visible = true;
                        }
                    }

                }
            },
            //helper function for gethoveredplot function
            _checkPointObj : function (pX, pY, chartX, chartY) {
                var dataset = this,
                    plotGrid = dataset.components.plotGrid,
                    pointObj,
                    chart = dataset.chart,
                    chartConfig = chart.config,
                    viewPortConfig = chartConfig.viewPortConfig,
                    x = viewPortConfig.x,
                    scaleX = viewPortConfig.scaleX,
                    plotBorderThickness = chartConfig.plotborderthickness,
                    showPlotBorder = chartConfig.showplotborder,
                    halfPlotBorderThickness,
                    dx,
                    dy,
                    hovered;

                pointObj = plotGrid[pY] && plotGrid[pY][pX];
                plotBorderThickness = showPlotBorder ? plotBorderThickness : 0;
                halfPlotBorderThickness = plotBorderThickness / 2;

                halfPlotBorderThickness = halfPlotBorderThickness % 2 === 0 ? halfPlotBorderThickness + 1 :
                 Math.round(halfPlotBorderThickness);

                if(pointObj && pointObj.config && pointObj.config.visible){
                    dx = chartX - (pointObj._xPos - x * scaleX) + halfPlotBorderThickness;
                    dy = chartY - pointObj._yPos + halfPlotBorderThickness;

                    hovered = dx >= 0 && dx <= pointObj._width + plotBorderThickness && dy >= 0 &&
                        dy <= pointObj._height + plotBorderThickness;

                    if (hovered) {
                        return {
                            pointIndex: pointObj._index,
                            hovered: hovered,
                            pointObj: pointObj
                        };
                    }
                }
            },
            // function to return the hovered data object
            _getHoveredPlot : function (chartX, chartY) {
                var dataset = this,
                    chart = dataset.chart,
                    chartConfig = chart.config,
                    xAxis = chart.components.xAxis[0],
                    yAxis = chart.components.yAxis[0],
                    height = chart.config.canvasHeight / chart.jsonData.rows.row.length,
                    canvas = chart.components.canvas,
                    canvasConfig = canvas.config,
                    canvasPadding = Math.max(canvasConfig.canvasPaddingLeft, canvasConfig.canvasPadding),
                    canvasLeft = chartConfig.canvasLeft,
                    canvasTop = chartConfig.canvasTop,
                    x,
                    y,
                    pX,
                    pY;

                y = yAxis.getValue(chartY + height/2 - canvasTop - canvasPadding);
                pY = Math.floor(y);

                x = xAxis.getValue(chartX - canvasLeft - canvasPadding);
                pX = Math.round(x);

                if(pX - x > 0){
                    return (y - pY > 0.5) ? (dataset._checkPointObj(pX, pY, chartX, chartY) ||
                     dataset._checkPointObj(pX - 1, pY, chartX, chartY)) :
                    (dataset._checkPointObj(pX, pY - 1, chartX, chartY) ||
                        dataset._checkPointObj(pX, pY, chartX, chartY));
                }else{
                    return (y - pY > 0.5) ? (dataset._checkPointObj(pX + 1, pY, chartX, chartY) ||
                        dataset._checkPointObj(pX, pY, chartX, chartY)) :
                    (dataset._checkPointObj(pX, pY - 1, chartX, chartY) ||
                        dataset._checkPointObj(pX + 1, pY, chartX, chartY) ||
                        dataset._checkPointObj(pX, pY, chartX, chartY));
                }
            },
            draw: function () {
                var dataSet = this,
                    JSONData = dataSet.JSONData,
                    conf = dataSet.config,
                    setDataArr = JSONData.data,
                    len,
                    setData,
                    attr,
                    i,
                    visible = dataSet.visible,
                    chart = dataSet.chart,
                    jobList = chart.getJobList(),
                    paper = chart.components.paper,
                    xAxis = chart.components.xAxis[0],
                    yAxis = chart.components.yAxis[0],
                    gradientLegend = chart.components.gradientLegend,
                    parentContainer = chart.graphics.datasetGroup,
                    xPos,
                    yPos,
                    crispBox,
                    layers = chart.graphics,
                    showTooltip = chart.config.showtooltip,

                    animationObj = chart.get(configStr, animationObjStr),
                    animType = animationObj.animType,
                    animObj = animationObj.animObj,
                    dummyObj = animationObj.dummyObj,
                    animationDuration = animationObj.duration,

                    columnWidth,
                    height,
                    toolText,
                    dataStore = dataSet.components.data,
                    dataObj,
                    setElement,
                    clip = chart.components.canvas.config.clip,
                    clipCanvas = clip['clip-canvas'].slice(0),
                    // hotElement,
                    setLink,
                    setValue,
                    // eventArgs,
                    displayValue,
                    // groupId,
                    config,
                    setRolloutAttr = {},
                    setRolloverAttr = {},
                    isPositive,
                    yBase = yAxis.getAxisBase(),
                    yBasePos = yAxis.yBasePos = yAxis.getAxisPosition(yBase),
                    heightBase = 0,
                    showShadow = conf.showShadow,
                    plotBorderThickness = conf.plotBorderThickness,
                    plotRadius = conf.plotRadius,
                    container = dataSet.graphics.container,
                    dataLabelContainer = dataSet.graphics.dataLabelContainer,
                    shadowContainer = dataSet.graphics.shadowContainer,
                    dataLabelsLayer =  layers.datalabelsGroup,
                    colorArr,
                    plotBorderDashStyle,
                    animFlag = true,
                    drawDataLabel = false,
                    removeLabel = false,
                    legendActive = chart.components.legend.config.isActive,
                    plotGrid = dataSet.components.plotGrid,

                    width,
                    column,
                    row,

                    elemIdStore = [],
                    elemId,
                    removeDataArr = dataSet.components.removeDataArr || [],
                    removeDataArrLen = removeDataArr.length,
                    isNewElem,
                    showHoverEffect = conf.showHoverEffect,
                    trackerConfig;

                (gradientLegend && gradientLegend.enabled) && (gradientLegend.resetLegend(),
                    gradientLegend.clearListeners());
                gradientLegend.notifyWhenUpdate(dataSet.updatePlot, dataSet);

                /*
                 * Creating a container group for the graphic element of column plots if
                 * not present and attaching it to its parent group.
                 */
                if (!container) {
                    container = dataSet.graphics.container = paper.group(columnStr, parentContainer);
                    // Clipping the group so that the plots do not come out of the canvas area when given thick border.
                    container.attr({
                        'clip-rect': clipCanvas
                    });

                    if (!visible) {
                        container.hide();
                    }
                }

                //chart.addCSSDefinition('.fusioncharts-datalabels .fusioncharts-label', labelCSS);

                /*
                 * Creating the shadow element container group for each plots if not present
                 * and attaching it its parent group.
                 */
                if (!shadowContainer) {
                    // Always sending the shadow group to the back of the plots group.
                    shadowContainer = dataSet.graphics.shadowContainer =
                        paper.group(shadowStr, parentContainer).toBack();
                    // Clipping the group so that the shadow do not come out of the canvas area when given thick border.
                    // if (!shadowContainer.attrs['clip-rect'] && !isScroll) {
                    //     shadowContainer.attr({
                    //         'clip-rect': elements['clip-canvas']
                    //     });
                    // }
                    if (!visible) {
                        shadowContainer.hide();
                    }

                }

                if (!dataLabelContainer) {
                    dataLabelContainer = dataSet.graphics.dataLabelContainer =
                        paper.group(dataLabelStr, dataLabelsLayer);
                    if (!visible) {
                        dataLabelContainer.hide();
                    }
                }

                len = setDataArr && setDataArr.length;

                width = chart.config.canvasWidth / chart.jsonData.columns.column.length;
                height = chart.config.canvasHeight / chart.jsonData.rows.row.length;

                // Create plot elements.
                for (i = 0; i < len; i++) {
                    setData = setDataArr && setDataArr[i];
                    dataObj = dataStore[i];
                    trackerConfig = dataObj.trackerConfig = {};
                    config = dataObj && dataObj.config;
                    setValue = config.setValue;
                    isPositive = setValue >= 0;
                    isNewElem = false;
                    (gradientLegend && gradientLegend.enabled && !legendActive) && (config.visible = true);
                    column = xAxis.getCategoryFromId(setDataArr[i].columnid.toLowerCase());
                    row = yAxis.getCategoryFromId(setDataArr[i].rowid.toLowerCase());

                    if (!column.catObj || !row.catObj || (config.value === BLANKSTRING)) {
                        continue;
                    }

                    if (!conf.mapByCategory && setValue === null) {
                        dataObj.graphics.element && dataObj.graphics.element.hide();
                        dataObj.graphics.hotElement && dataObj.graphics.hotElement.hide();
                        removeLabel = true;
                        continue;
                    }

                    removeLabel = false;

                    elemId = column.index.toString() + row.index.toString();

                    elemIdStore.push(elemId);

                    setLink  = config.setLink;
                    colorArr = config.colorArr;

                    // Creating the data structure if not present for storing the graphics elements.
                    if (!dataObj.graphics) {
                        dataStore[i].graphics = {};

                    }

                    displayValue = config.displayValue;

                    xPos = xAxis.getAxisPosition(column.index) - width/2;

                    yPos = yAxis.getAxisPosition(row.index) - height/2;

                    columnWidth = width;

                    // Setting the final tooltext.
                    toolText = config.toolText;
                    toolText && (config.finalTooltext = toolText);

                    dataObj.graphics.valEle && dataObj.graphics.valEle.hide();
                    dataObj.graphics.tlLabel && dataObj.graphics.tlLabel.hide();
                    dataObj.graphics.trLabel && dataObj.graphics.trLabel.hide();
                    dataObj.graphics.blLabel && dataObj.graphics.blLabel.hide();
                    dataObj.graphics.brLabel && dataObj.graphics.brLabel.hide();

                    // Setting the event arguments.
                    trackerConfig.eventArgs = {
                        index: i,
                        link: setLink,
                        value: config.percentValue || setValue,
                        displayValue: displayValue,
                        columnId: column.catObj.id,
                        rowId: row.catObj.id,
                        tlLabel: config.tlLabel,
                        trLabel: config.trLabel,
                        blLabel: config.blLabel,
                        brLabel: config.brLabel,
                        //categoryLabel: categories[i].label,
                        toolText: !toolText ? '' : toolText,
                        id: BLANKSTRING,
                        datasetIndex: legendActive ? dataObj.datasetIndex : UNDEFINED,
                        datasetName: legendActive ? dataObj.datasetName : UNDEFINED,
                        visible: visible
                    };

                    setRolloutAttr = config.setRolloutAttr;
                    setRolloverAttr = config.setRolloverAttr;

                    yBasePos = yPos;
                    heightBase = height;

                    // Setting the attributes for plot drawing.
                    attr = {
                        x: xPos,
                        y: yBasePos,
                        width: columnWidth,
                        height: heightBase || 1,
                        r: plotRadius,
                        ishot: !showTooltip,
                        fill: config.color,
                        stroke: toRaphaelColor(colorArr[1]),
                        'stroke-width': animationDuration ? 0 : plotBorderThickness,
                        'stroke-dasharray': plotBorderDashStyle,
                        'fill-opacity': animationDuration ? 0 : config.plotFillAlpha / 100,
                        'stroke-linejoin': miterStr,
                        'visibility': config.visible ? visibleStr : hiddenStr,
                        cursor: setLink ? POINTER : BLANKSTRING
                    };

                    //todo- remove _ to make it public
                    dataObj._xPos = xPos;
                    dataObj._yPos = yPos;
                    dataObj._height = height;
                    dataObj._width = columnWidth;
                    dataObj._index = i;
                    plotGrid[row.index][column.index] = dataObj;
                    /*
                     * If the data plots are not present then they are created, else only attributes are set for the
                     * existing plots.
                     */
                    if (!dataObj.graphics.element) {
                        setElement = dataObj.graphics.element = paper.rect(attr, container);
                        isNewElem = true;

                        setElement.animateWith(dummyObj, animObj, {
                            'fill-opacity': config.plotFillAlpha / 100,
                            'stroke-width': plotBorderThickness
                        }, animationDuration, animType/*, (animFlag && initAnimCallBack)*/);

                        animFlag = false;
                        config.elemCreated = true;
                    }

                    else {
                        drawDataLabel = true;
                        attr = {
                            x: xPos,
                            y: yPos,
                            width: columnWidth,
                            height: height || 1
                        };

                        setElement = dataObj.graphics.element;

                        setElement.animateWith(dummyObj, animObj, attr,
                            animationDuration, animationObj.animType);

                        setElement.attr({
                            ishot: !showTooltip,
                            fill: config.color,
                            stroke: toRaphaelColor(colorArr[1]),
                            'fill-opacity': config.visible ? config.plotFillAlpha / 100 : 0,
                            'stroke-width': config.visible ? plotBorderThickness : 0,
                            'stroke-dasharray': plotBorderDashStyle,
                            'stroke-linejoin': miterStr,
                            'visibility': config.visible ? visibleStr : hiddenStr,
                            cursor: setLink ? POINTER : BLANKSTRING
                        });
                        config.elemCreated = false;
                    }

                    // The shadow element is set for the dataplots.
                    setElement
                    .shadow({opacity : showShadow}, shadowContainer)
                    .data('BBox', crispBox);

                    if (setLink || showTooltip) {
                        // Fix for touch devices.
                        if (height < HTP) {
                            yPos -= (HTP - height) / 2;
                            height = HTP;
                        }

                        // Setting attributes for the tooltip.
                        trackerConfig.attr = {
                            x: xPos,
                            y: yPos,
                            width: columnWidth,
                            height: height,
                            r: plotRadius,
                            cursor: setLink ? POINTER : BLANKSTRING,
                            stroke: TRACKER_FILL,
                            'stroke-width': plotBorderThickness,
                            fill: TRACKER_FILL,
                            ishot: true,
                            'visibility': config.visible ? visibleStr : hiddenStr
                        };
                    }

                    chart.config.enablemousetracking && setElement
                        .data(EVENTARGS, trackerConfig.eventArgs)
                        .data(showHoverEffectStr, showHoverEffect)
                        .data(SETROLLOVERATTR, config.setRolloverAttr || {})
                        .data(SETROLLOUTATTR, config.setRolloutAttr || {});
                }

                dataSet.drawn ? dataSet.drawLabel() : jobList.labelDrawID.push(schedular.addJob(dataSet.drawLabel,
                    dataSet, [], lib.priorityList.label));
                dataSet.drawn = true;
                // (drawDataLabel || removeLabel) && dataSet.drawLabel();
                removeDataArrLen && dataSet.remove();
            },

            drawLabel: function () {
                var dataSet = this,
                    chart = dataSet.chart,
                    chartConf = chart.config,
                    layers = chart.graphics,
                    chartComponents = chart.components,
                    canvasConf = chartComponents.canvas.config,
                    paper = chartComponents.paper,
                    smartLabel = chart.linkedItems.smartLabel,
                    style = chart.config.dataLabelStyle,
                    conf = dataSet.config,
                    JSONData = dataSet.JSONData,
                    setDataArr = JSONData.data,
                    len = setDataArr.length,
                    components = dataSet.components,
                    dataStore = components.data,
                    visible = dataSet.visible,
                    dataObj,
                    dataLabelsLayer,
                    i,
                    displayValue,
                    canvasHeight = chartConf.canvasHeight,
                    graphic,
                    textY,
                    textX,
                    yDepth = canvasConf.yDepth,
                    yPos,
                    xPos,
                    attr,
                    dataLabelContainer = dataSet.graphics.dataLabelContainer,

                    tlLabelContainer = dataSet.graphics.tlLabelContainer,
                    blLabelContainer = dataSet.graphics.blLabelContainer,
                    trLabelContainer = dataSet.graphics.trLabelContainer,
                    brLabelContainer = dataSet.graphics.brLabelContainer,
                    tlStyle,
                    trStyle,
                    blStyle,
                    brStyle,
                    tlCss,
                    trCss,
                    blCss,
                    brCss,
                    graphicEle,
                    pointW,
                    pointH,
                    pointX,
                    pointY,
                    smartTextObj,
                    tlLabel,
                    trLabel,
                    blLabel,
                    brLabel,
                    isTLLabel,
                    isTRLabel,
                    isBLLabel,
                    isBRLabel,
                    maxWidth,
                    maxHeight,
                    config,
                    setValue,

                    animationObj = chart.get(configStr, animationObjStr),
                    animObj = animationObj.animObj,
                    dummyObj = animationObj.dummyObj,
                    animationDuration = animationObj.duration,

                    MAX_PERCENT_SPACE = 0.9,
                    POINT_FIVE = 0.5,
                    GUTTER_4 = 4;

                dataLabelsLayer =  layers.datalabelsGroup;
                canvasHeight = canvasHeight + yDepth;

                // Creating the dataLabel container group if not present and appending it to its parent.
                if (!dataLabelContainer) {
                    dataLabelContainer = dataSet.graphics.dataLabelContainer =
                        paper.group(dataLabelStr, dataLabelsLayer);
                    if (!visible) {
                        dataLabelContainer.hide();
                    }
                }

                if (!tlLabelContainer) {
                    tlLabelContainer = dataSet.graphics.tlLabelContainer =
                        paper.group(tlLabelStr, dataLabelsLayer);
                }

                if (!blLabelContainer) {
                    blLabelContainer = dataSet.graphics.blLabelContainer =
                        paper.group(blLabelStr, dataLabelsLayer);
                }

                if (!trLabelContainer) {
                    trLabelContainer = dataSet.graphics.trLabelContainer =
                        paper.group(trLabelStr, dataLabelsLayer);
                }

                if (!brLabelContainer) {
                    brLabelContainer = dataSet.graphics.brLabelContainer =
                        paper.group(brLabelStr, dataLabelsLayer);
                }

                tlStyle = conf.tlLabelStyle;
                trStyle = conf.trLabelStyle;
                blStyle = conf.blLabelStyle;
                brStyle = conf.brLabelStyle;

                tlCss = {
                    fontFamily: tlStyle.fontFamily,
                    fontSize: tlStyle.fontSize,
                    lineHeight: tlStyle.lineHeight,
                    fontWeight: tlStyle.fontWeight,
                    fontStyle: tlStyle.fontStyle
                };
                trCss = {
                    fontFamily: trStyle.fontFamily,
                    fontSize: trStyle.fontSize,
                    lineHeight: trStyle.lineHeight,
                    fontWeight: trStyle.fontWeight,
                    fontStyle: trStyle.fontStyle
                };
                blCss = {
                    fontFamily: blStyle.fontFamily,
                    fontSize: blStyle.fontSize,
                    lineHeight: blStyle.lineHeight,
                    fontWeight: blStyle.fontWeight,
                    fontStyle: blStyle.fontStyle
                };
                brCss = {
                    fontFamily: brStyle.fontFamily,
                    fontSize: brStyle.fontSize,
                    lineHeight: brStyle.lineHeight,
                    fontWeight: brStyle.fontWeight,
                    fontStyle: brStyle.fontStyle
                };
                smartLabel.useEllipsesOnOverflow(chartConf.useEllipsesWhenOverflow);
                smartLabel.setStyle(style);

                tlLabelContainer.css(tlCss);
                blLabelContainer.css(blCss);
                trLabelContainer.css(trCss);
                brLabelContainer.css(brCss);

                for(i = 0; i < len; i++) {
                    dataObj = dataStore[i];
                    // Condition arises when user has removed data in real time update
                    if (dataObj === undefined) {
                        continue;
                    }
                    graphic = dataObj.graphics;

                    // Condition arises when feedData enters less number of data in a dataset compared to the other.
                    if (!graphic) {
                        continue;
                    }

                    config = dataObj && dataObj.config;
                    setValue = config.setValue;

                    if (!conf.mapByCategory && setValue === null) {
                        dataObj.graphics.valEle && dataObj.graphics.valEle.hide();
                        dataObj.graphics.tlLabel && dataObj.graphics.tlLabel.hide();
                        dataObj.graphics.trLabel && dataObj.graphics.trLabel.hide();
                        dataObj.graphics.blLabel && dataObj.graphics.blLabel.hide();
                        dataObj.graphics.brLabel && dataObj.graphics.brLabel.hide();
                        continue;
                    }

                    displayValue = config.displayValue;

                    graphicEle = dataObj.graphics.element;

                    if (!graphicEle) {
                        continue;
                    }

                    pointW = dataObj._width;
                    pointH = dataObj._height;
                    pointX = dataObj._xPos;
                    pointY = dataObj._yPos;

                    // Setting style for smartLabel
                    smartLabel.setStyle(style);

                    // Drawing of displayValue
                    if (defined(displayValue) && displayValue !== BLANK && config.showValue) {
                        // First render the value text
                        // Get the displayValue text according to the
                        smartTextObj = smartLabel.getSmartText(displayValue,
                            pointW, pointH, false);
                        displayValue = smartTextObj.text;

                        textY = pointY + (pointH * 0.5);
                        textX = pointX + (pointW * 0.5);

                        if (!dataObj.graphics.valEle) {
                            attr = {
                                text: displayValue,
                                title: (smartTextObj.tooltext || BLANKSTRING),
                                visibility: config.visible ? visibleStr : hiddenStr,
                                fill: style.color,
                                direction: config.textDirection,
                                x: textX,
                                y: textY,
                                'text-bound': [style.backgroundColor, style.borderColor,
                                    style.borderThickness, style.borderPadding,
                                    style.borderRadius, style.borderDash
                                ]
                            };
                            dataObj.graphics.valEle = paper.text(attr, dataLabelContainer);

                            // dataObj.graphics.valEle.attr({
                            //     text: displayValue,
                            //     title: (smartTextObj.tooltext || BLANKSTRING),
                            //     visibility: config.visible ? visibleStr : hiddenStr,
                            //     fill: style.color,
                            //     direction: config.textDirection,
                            //     x: textX,
                            //     y: textY,
                            //     'text-bound': [style.backgroundColor, style.borderColor,
                            //         style.borderThickness, style.borderPadding,
                            //         style.borderRadius, style.borderDash
                            //     ]
                            // });
                        }
                        else {

                            dataObj.graphics.valEle.animateWith(dummyObj, animObj, {
                                x: textX,
                                y: textY
                            }, animationDuration, animationObj.animType);

                            dataObj.graphics.valEle.attr({
                                text: displayValue,
                                title: (smartTextObj.tooltext || BLANKSTRING),
                                visibility: config.visible ? visibleStr : hiddenStr,
                                fill: style.color,
                                direction: config.textDirection,
                                'text-bound': [style.backgroundColor, style.borderColor,
                                    style.borderThickness, style.borderPadding,
                                    style.borderRadius, style.borderDash
                                ]
                            });
                        }

                        config.visible && dataObj.graphics.valEle.show();

                        tlLabel = config.tlLabel;
                        trLabel = config.trLabel;
                        blLabel = config.blLabel;
                        brLabel = config.brLabel;

                        isTLLabel = (defined(tlLabel) &&
                            tlLabel !== BLANK);
                        isTRLabel = (defined(trLabel) &&
                            trLabel !== BLANK);
                        isBLLabel = (defined(blLabel) &&
                            blLabel !== BLANK);
                        isBRLabel = (defined(brLabel) &&
                            brLabel !== BLANK);

                        maxWidth = pointW * (isTLLabel && isTRLabel ?
                            POINT_FIVE : MAX_PERCENT_SPACE);
                        maxHeight = (pointH - (smartTextObj && smartTextObj.height || 0)) * 0.5;
                        // For top labels
                        yPos = pointY + GUTTER_4;

                        if (isTLLabel) {
                            // Setting style for smartLabel
                            smartLabel.setStyle(tlStyle);
                            smartTextObj = smartLabel.getSmartText(tlLabel,
                                maxWidth, maxHeight, false);
                            displayValue = smartTextObj.text;
                            // Get the x and y position of the dataValue
                            xPos = pointX;

                            if (!dataObj.graphics.tlLabel) {
                                attr = {
                                    text: displayValue,
                                    title: (smartTextObj.tooltext || BLANKSTRING),
                                    visibility: config.visible ? visibleStr : hiddenStr,
                                    fill: tlStyle.color,
                                    'text-anchor': POSITION_START,
                                    'vertical-align': POSITION_TOP,
                                    direction: config.textDirection,
                                    x: xPos + GUTTER_4,
                                    y: yPos,
                                    'text-bound': [tlStyle.backgroundColor, tlStyle.borderColor,
                                        tlStyle.borderThickness, tlStyle.borderPadding,
                                        tlStyle.borderRadius, tlStyle.borderDash]
                                };
                                dataObj.graphics.tlLabel = paper.text(attr, tlLabelContainer);

                                // dataObj.graphics.tlLabel.attr({
                                //     text: displayValue,
                                //     title: (smartTextObj.tooltext || BLANKSTRING),
                                //     visibility: config.visible ? visibleStr : hiddenStr,
                                //     fill: tlStyle.color,
                                //     'text-anchor': POSITION_START,
                                //     'vertical-align': POSITION_TOP,
                                //     direction: config.textDirection,
                                //     x: xPos + GUTTER_4,
                                //     y: yPos,
                                //     'text-bound': [tlStyle.backgroundColor, tlStyle.borderColor,
                                //         tlStyle.borderThickness, tlStyle.borderPadding,
                                //         tlStyle.borderRadius, tlStyle.borderDash]
                                // });
                            }
                            else {

                                dataObj.graphics.tlLabel.animateWith(dummyObj, animObj, {
                                    x: xPos + GUTTER_4,
                                    y: yPos
                                }, animationDuration, animationObj.animType);

                                dataObj.graphics.tlLabel.attr({
                                    text: displayValue,
                                    title: (smartTextObj.tooltext || BLANKSTRING),
                                    visibility: config.visible ? visibleStr : hiddenStr,
                                    fill: tlStyle.color,
                                    'text-anchor': POSITION_START,
                                    'vertical-align': POSITION_TOP,
                                    direction: config.textDirection,
                                    'text-bound': [tlStyle.backgroundColor, tlStyle.borderColor,
                                        tlStyle.borderThickness, tlStyle.borderPadding,
                                        tlStyle.borderRadius, tlStyle.borderDash]
                                });
                            }
                            config.visible && dataObj.graphics.tlLabel.show();
                        }
                        else {
                            if (dataObj.graphics.tlLabel) {
                                dataObj.graphics.tlLabel.remove();
                                delete dataObj.graphics.tlLabel;
                            }
                        }

                        if (isTRLabel) {
                            // Setting style for smartRabel
                            smartLabel.setStyle(trStyle);
                            smartTextObj = smartLabel.getSmartText(trLabel,
                                maxWidth, maxHeight, false);
                            displayValue = smartTextObj.text;
                            // Get the x and y position of the dataValue
                            xPos = pointX + pointW;
                            if (!dataObj.graphics.trLabel) {
                                attr = {
                                    text: displayValue,
                                    title: (smartTextObj.tooltext || BLANKSTRING),
                                    visibility: config.visible ? visibleStr : hiddenStr,
                                    fill: trStyle.color,
                                    'text-anchor': POSITION_END,
                                    'vertical-align': POSITION_TOP,
                                    direction: config.textDirection,
                                    x: xPos - GUTTER_4,
                                    y: yPos,
                                    'text-bound': [trStyle.backgroundColor, trStyle.borderColor,
                                        trStyle.borderThickness, trStyle.borderPadding,
                                        trStyle.borderRadius, trStyle.borderDash]
                                };
                                dataObj.graphics.trLabel = paper.text(attr, trLabelContainer);

                                // dataObj.graphics.trLabel.attr({
                                //     text: displayValue,
                                //     title: (smartTextObj.tooltext || BLANKSTRING),
                                //     visibility: config.visible ? visibleStr : hiddenStr,
                                //     fill: trStyle.color,
                                //     'text-anchor': POSITION_END,
                                //     'vertical-align': POSITION_TOP,
                                //     direction: config.textDirection,
                                //     x: xPos - GUTTER_4,
                                //     y: yPos,
                                //     'text-bound': [trStyle.backgroundColor, trStyle.borderColor,
                                //         trStyle.borderThickness, trStyle.borderPadding,
                                //         trStyle.borderRadius, trStyle.borderDash]
                                // });
                            }
                            else {

                                dataObj.graphics.trLabel.animateWith(dummyObj, animObj, {
                                    x: xPos - GUTTER_4,
                                    y: yPos
                                }, animationDuration, animationObj.animType);

                                dataObj.graphics.trLabel.attr({
                                    text: displayValue,
                                    title: (smartTextObj.tooltext || BLANKSTRING),
                                    visibility: config.visible ? visibleStr : hiddenStr,
                                    fill: trStyle.color,
                                    'text-anchor': POSITION_END,
                                    'vertical-align': POSITION_TOP,
                                    direction: config.textDirection,
                                    'text-bound': [trStyle.backgroundColor, trStyle.borderColor,
                                        trStyle.borderThickness, trStyle.borderPadding,
                                        trStyle.borderRadius, trStyle.borderDash]
                                });
                            }
                            config.visible && dataObj.graphics.trLabel.show();
                        }
                        else {
                            if (dataObj.graphics.trLabel) {
                                dataObj.graphics.trLabel.remove();
                                delete dataObj.graphics.trLabel;
                            }
                        }

                        // For top labels
                        yPos = (pointY + pointH) - GUTTER_4;

                        if (isBLLabel) {
                            // Setting style for smartRabel
                            smartLabel.setStyle(blStyle);
                            smartTextObj = smartLabel.getSmartText(blLabel,
                                maxWidth, maxHeight, false);
                            displayValue = smartTextObj.text;
                            // Get the x and y position of the dataValue
                            xPos = pointX;
                            if (!dataObj.graphics.blLabel) {
                                attr = {
                                    text: displayValue,
                                    title: (smartTextObj.tooltext || BLANKSTRING),
                                    visibility: config.visible ? visibleStr : hiddenStr,
                                    fill: blStyle.color,
                                    'text-anchor': POSITION_START,
                                    'vertical-align': POSITION_BOTTOM,
                                    direction: config.textDirection,
                                    x: xPos + GUTTER_4,
                                    y: yPos,
                                    'text-bound': [blStyle.backgroundColor, blStyle.borderColor,
                                        blStyle.borderThickness, blStyle.borderPadding,
                                        blStyle.borderRadius, blStyle.borderDash]
                                };
                                dataObj.graphics.blLabel = paper.text(attr, blLabelContainer);

                                // dataObj.graphics.blLabel.attr({
                                //     text: displayValue,
                                //     title: (smartTextObj.tooltext || BLANKSTRING),
                                //     visibility: config.visible ? visibleStr : hiddenStr,
                                //     fill: blStyle.color,
                                //     'text-anchor': POSITION_START,
                                //     'vertical-align': POSITION_BOTTOM,
                                //     direction: config.textDirection,
                                //     x: xPos + GUTTER_4,
                                //     y: yPos,
                                //     'text-bound': [blStyle.backgroundColor, blStyle.borderColor,
                                //         blStyle.borderThickness, blStyle.borderPadding,
                                //         blStyle.borderRadius, blStyle.borderDash]
                                // });
                            }
                            else {

                                dataObj.graphics.blLabel.animateWith(dummyObj, animObj, {
                                    x: xPos + GUTTER_4,
                                    y: yPos
                                }, animationDuration, animationObj.animType);

                                dataObj.graphics.blLabel.attr({
                                    text: displayValue,
                                    title: (smartTextObj.tooltext || BLANKSTRING),
                                    visibility: config.visible ? visibleStr : hiddenStr,
                                    fill: blStyle.color,
                                    'text-anchor': POSITION_START,
                                    'vertical-align': POSITION_BOTTOM,
                                    direction: config.textDirection,
                                    'text-bound': [blStyle.backgroundColor, blStyle.borderColor,
                                        blStyle.borderThickness, blStyle.borderPadding,
                                        blStyle.borderRadius, blStyle.borderDash]
                                });
                            }
                            config.visible && dataObj.graphics.blLabel.show();
                        }
                        else {
                            if (dataObj.graphics.blLabel) {
                                dataObj.graphics.blLabel.remove();
                                delete dataObj.graphics.blLabel;
                            }
                        }

                        if (isBRLabel) {
                            // Setting style for smartRabel
                            smartLabel.setStyle(blStyle);
                            smartTextObj = smartLabel.getSmartText(brLabel,
                                maxWidth, maxHeight, false);
                            displayValue = smartTextObj.text;
                            // Get the x and y position of the dataValue
                            xPos = pointX + pointW - GUTTER_4;
                            if (!dataObj.graphics.brLabel) {
                                attr = {
                                    text: displayValue,
                                    title: (smartTextObj.tooltext || BLANKSTRING),
                                    visibility: config.visible ? visibleStr : hiddenStr,
                                    fill: brStyle.color,
                                    'text-anchor': POSITION_END,
                                    'vertical-align': POSITION_BOTTOM,
                                    direction: config.textDirection,
                                    x: xPos,
                                    y: yPos,
                                    'text-bound': [brStyle.backgroundColor, brStyle.borderColor,
                                        brStyle.borderThickness, brStyle.borderPadding,
                                        brStyle.borderRadius, brStyle.borderDash]
                                };
                                dataObj.graphics.brLabel = paper.text(attr, brLabelContainer);

                                // dataObj.graphics.brLabel.attr({
                                //     text: displayValue,
                                //     title: (smartTextObj.tooltext || BLANKSTRING),
                                //     visibility: config.visible ? visibleStr : hiddenStr,
                                //     fill: brStyle.color,
                                //     'text-anchor': POSITION_END,
                                //     'vertical-align': POSITION_BOTTOM,
                                //     direction: config.textDirection,
                                //     x: xPos,
                                //     y: yPos,
                                //     'text-bound': [brStyle.backgroundColor, brStyle.borderColor,
                                //         brStyle.borderThickness, brStyle.borderPadding,
                                //         brStyle.borderRadius, brStyle.borderDash]
                                // });
                            }
                            else {

                                dataObj.graphics.brLabel.animateWith(dummyObj, animObj, {
                                    x: xPos,
                                    y: yPos
                                }, animationDuration, animationObj.animType);

                                dataObj.graphics.brLabel.attr({
                                    text: displayValue,
                                    title: (smartTextObj.tooltext || BLANKSTRING),
                                    visibility: config.visible ? visibleStr : hiddenStr,
                                    fill: brStyle.color,
                                    'text-anchor': POSITION_END,
                                    'vertical-align': POSITION_BOTTOM,
                                    direction: config.textDirection,
                                    'text-bound': [brStyle.backgroundColor, brStyle.borderColor,
                                        brStyle.borderThickness, brStyle.borderPadding,
                                        brStyle.borderRadius, brStyle.borderDash]
                                });
                            }
                            config.visible && dataObj.graphics.brLabel.show();
                        }
                        else {
                            if (dataObj.graphics.brLabel) {
                                dataObj.graphics.brLabel.remove();
                                delete dataObj.graphics.brLabel;
                            }
                        }

                    }
                    else {

                        if (dataObj.graphics.valEle) {
                            dataObj.graphics.valEle.remove();
                            delete dataObj.graphics.valEle;
                        }

                        if (dataObj.graphics.tlLabel) {
                            dataObj.graphics.tlLabel.remove();
                            delete dataObj.graphics.tlLabel;
                        }

                        if (dataObj.graphics.trLabel) {
                            dataObj.graphics.trLabel.remove();
                            delete dataObj.graphics.trLabel;
                        }

                        if (dataObj.graphics.blLabel) {
                            dataObj.graphics.blLabel.remove();
                            delete dataObj.graphics.blLabel;
                        }

                        if (dataObj.graphics.brLabel) {
                            dataObj.graphics.brLabel.remove();
                            delete dataObj.graphics.brLabel;
                        }
                    }

                }

                dataSet.labelDrawn = true;
            },

            // Function to remove a data from a dataset during real time update.
            remove : function () {
                var dataSet = this,
                    components = dataSet.components,
                    removeDataArr = components.removeDataArr,
                    pool = components.pool || (components.pool = {
                        element :[],
                        hotElement : [],
                        label : []
                    }),
                    len = removeDataArr.length,
                    removeData,
                    maxminFlag = dataSet.maxminFlag,
                    ele,
                    graphics,
                    i;

                for (i = 0; i < len; i++) {
                    removeData = removeDataArr[0];
                    removeDataArr.splice(0,1);
                    // In case of non existing data plot continue;
                    if (!removeData || !removeData.graphics) {
                        continue;
                    }

                    graphics = removeData.graphics;
                    for (ele in graphics) {
                        // Stopping any previous animation.
                        graphics[ele].stop();
                        graphics[ele].hide();
                    }

                    // Storing the graphic elements for reuse.
                    removeData.graphics.element && (pool.element = pool.element.concat(removeData.graphics.element));
                    removeData.graphics.hotElement && (pool.hotElement = pool.hotElement.concat(removeData.graphics.
                        hotElement));
                    removeData.graphics.label && (pool.label = pool.label.concat(removeData.graphics.label));
                }
                components.pool = pool;
                maxminFlag && dataSet.setMaxMin();
            },

            getEventArgs: function (legendItem) {
                var dataset = legendItem.dataset,
                    config = dataset.config || {},
                    label = config.label,
                    index = legendItem.index,
                    eventArgs = {
                        datasetName: label,
                        datasetIndex: index,
                        visible: config.visible
                    };
                return eventArgs;
            }

        },'Column']);

    }
]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-kagi',
    function () {
        var global = this,
            lib = global.hcLib,
            win = global.window,
            Image = win.Image,

            //strings
            preDefStr = lib.preDefStr,

            configStr = preDefStr.configStr,
            animationObjStr = preDefStr.animationObjStr,
            dataLabelStr = preDefStr.dataLabelStr,
            hiddenStr = preDefStr.hiddenStr,
            ROUND = preDefStr.ROUND,
            POSITION_TOP = preDefStr.POSITION_TOP,
            POSITION_BOTTOM = preDefStr.POSITION_BOTTOM,

            LINE = preDefStr.line,
            BLANKSTRING = lib.BLANKSTRING,
            //add the tools thats are requared
            pluck = lib.pluck,
            pluckNumber = lib.pluckNumber,
            toRaphaelColor = lib.toRaphaelColor,
            UNDEFINED,
            EVENTARGS = 'eventArgs',
            NONE = 'none',
            SETROLLOVERATTR = 'setRolloverAttr',
            SETROLLOUTATTR = 'setRolloutAttr',
            COMPONENT = 'component',
            DATASET = 'dataset',

            schedular = lib.schedular,
            each = lib.each,
            defined = function(obj) {
                return obj !== UNDEFINED && obj !== null;
            },
            TOUCH_THRESHOLD_PIXELS = lib.TOUCH_THRESHOLD_PIXELS,
            CLICK_THRESHOLD_PIXELS = lib.CLICK_THRESHOLD_PIXELS,
            M = 'M',
            H = 'H',
            V = 'V',
            POSITION_MIDDLE = 'middle',
            math = Math,
            mathRound = math.round,
            mathMin = math.min,
            mathMax = math.max,
            mathAbs = math.abs,
            hasTouch = lib.hasTouch,
            // hot/tracker threshold in pixels
            HTP = hasTouch ? TOUCH_THRESHOLD_PIXELS :
                CLICK_THRESHOLD_PIXELS,
            // POSITION_CENTER = lib.POSITION_CENTER,
            POSITION_RIGHT = lib.POSITION_RIGHT;

        FusionCharts.register(COMPONENT, [DATASET, 'Kagi', {
            type: 'kagi',
            _parseShadowOptions: function () {
                var dataSet = this,
                    chart = dataSet.chart,
                    conf = dataSet.config,
                    chartAttr = chart.jsonData.chart;
                return {
                    opacity: pluckNumber(chartAttr.showshadow, 1) ? conf.alpha/100 : 0
                };
            },
            configure: function () {
                var dataSetComponents,
                    datasetObj = this,
                    removeDataArr,
                    chart = datasetObj.chart,
                    canvasWidth = chart.config.canvasWidth,
                    xAxis = chart.components.xAxis[0],
                    temp = 0,
                    data,
                    catArr = [],
                    series,
                    JSONData,
                    FCChartObj,
                    valueMax,
                    valueMin,
                    isRallyInitialised,
                    shiftCounter,
                    vLinePosition,
                    reversalValue,
                    reversalPercentage,
                    lastFcDataObj,
                    rallyDashLen,
                    rallyDashGap,
                    declineDashLen,
                    declineDashGap,
                    getDashStyle = lib.getDashStyle,
                    lastPlotValue,
                    setShowLabel,
                    length,
                    index,
                    fcIndex,
                    fcDataObj,
                    lastShift,
                    prevDataObj,
                    plotValue,
                    dataObj,
                    nextDataValue,
                    valueDifference,
                    dataValue,
                    isRally,
                    lastLow,
                    lastHigh,
                    isMovingUp,
                    isShift,
                    checkValue,
                    t,
                    count = 0,
                    vAlign,
                    effectiveCanvasWidth,
                    maxHShiftPercent,
                    canvasPadding,
                    align;
                //call the base class i.e. line dataset configure().
                datasetObj.__base__.configure.call(datasetObj);
                dataSetComponents = datasetObj.components;
                data = dataSetComponents.data;
                series = datasetObj.config;
                JSONData = datasetObj.JSONData.data;
                FCChartObj = chart.jsonData.chart;
                valueMax = series.maxValue;
                valueMin = series.minValue;
                removeDataArr = dataSetComponents.removeDataArr || (dataSetComponents.removeDataArr = []),
                // First vertical point for shift is yet to be obtained
                isRallyInitialised = false;
                // Initialised to one to avoid zero dividing the width of the canvas
                // (as the case may be) to get the xShiftLength
                shiftCounter = 0;
                vLinePosition = 0.5;
                // The value which determines whether to make a horizontal shift
                // to deal with the next point
                reversalValue = pluckNumber(FCChartObj.reversalvalue, -1);
                // The percentage of the range of values, which determines whether
                // to make a horizontal shift to deal with the next point
                reversalPercentage = pluckNumber(FCChartObj.reversalpercentage, 5);
                lastFcDataObj = {};

                for (index = 0; index < data.length; index += 1) {
                    data[index].config.__nullCount = count;
                    if (data[index].config.setValue === null) {
                        removeDataArr.push(data.splice(index, 1)[0]);
                        count ++;
                        index -= 1;
                    }
                }
                if (data.length) {
                    // Color of line denoting rally
                    series.rallyColor = pluck(FCChartObj.rallycolor, 'FF0000');
                    series.rallyAlpha = pluckNumber(FCChartObj.rallyalpha,
                        FCChartObj.linealpha, 100);
                    //color of line denoting decline
                    series.declineColor = pluck(FCChartObj.declinecolor, '0000FF');
                    series.declineAlpha = pluckNumber(FCChartObj.declinealpha,
                        FCChartObj.linealpha, 100);
                    //Default canvasPadding is 15.
                    canvasPadding = series.canvasPadding = pluckNumber(FCChartObj.canvaspadding, 15);
                    // The maximum horizontal shift in percentage of the
                    // available canvas width
                    maxHShiftPercent = series.maxHShiftPercent = pluckNumber(FCChartObj.maxhshiftpercent, 10);
                    effectiveCanvasWidth = canvasWidth - canvasPadding * 2;
                    // Thickness of line denoting rally
                    series.rallyThickness = pluckNumber(FCChartObj.rallythickness,
                        FCChartObj.linethickness, 2);
                    // length of the dash
                    rallyDashLen = pluckNumber(FCChartObj.rallydashlen,
                        FCChartObj.linedashlen, 5);
                    // distance between dash
                    rallyDashGap = pluckNumber(FCChartObj.rallydashgap,
                        FCChartObj.linedashgap, 4);

                    // Thickness of line denoting decline
                    series.declineThickness = pluckNumber(FCChartObj.declinethickness,
                        FCChartObj.linethickness, 2);
                    // length of the dash
                    declineDashLen = pluckNumber(FCChartObj.declinedashlen,
                        FCChartObj.linedashlen, 5);
                    // distance between dash
                    declineDashGap = pluckNumber(FCChartObj.declinedashgap,
                        FCChartObj.linedashgap, 4);

                    series.lineDashed = {
                        'true': pluckNumber(FCChartObj.rallydashed,
                            FCChartObj.linedashed, 0),
                        'false': pluckNumber(FCChartObj.declinedashed,
                            FCChartObj.linedashed, 0)
                    };

                    // Storing dashStyle in series to be use while drawing graph and
                    series.rallyDashed = pluckNumber(FCChartObj.rallydashed,
                        FCChartObj.linedashed, 0) ? getDashStyle(rallyDashLen, rallyDashGap,
                        series.rallyThickness) : NONE;
                    series.declineDashed = pluckNumber(FCChartObj.declinedashed,
                        FCChartObj.linedashed, 0) ? getDashStyle(declineDashLen, declineDashGap,
                        series.declineThickness) : NONE;

                    //canvasPadding to be use by Kagi chart Drawing
                    series.canvasPadding = pluckNumber(FCChartObj.canvaspadding,
                        this.canvasPadding, 15);

                    //setting the reversal value
                    reversalValue = (reversalValue > 0) ?
                        reversalValue : reversalPercentage * (valueMax - valueMin) / 100;

                    // Initialised by the first data value
                    lastPlotValue = data[0].config.setValue;
                    // Local function to set anchor and value visibility of
                    // unwanted points, after the first point is found to draw
                    // vertical kagi line
                    setShowLabel = function(id, _isRally) {
                        // Initial data value
                        var dataXValue, r = 1,
                            data1Value = data[0].config.setValue;
                        // Looping to check for unwanted points
                        while (r < id) {
                            // Value of point under check
                            dataXValue = data[r].config.setValue;
                            // If current trend is rally
                            if (_isRally) {
                                if (dataXValue <= data1Value) {
                                    data[r].config.isDefined = false;
                                }
                                // Else current trend is decline
                            } else {
                                if (dataXValue >= data1Value) {
                                    data[r].config.isDefined = false;
                                }
                            }
                            r += 1;
                        }
                        // Setting alignment of value for the first data
                        data[0].config.vAlign = (_isRally) ? POSITION_BOTTOM :
                            POSITION_TOP;
                        data[0].config.align = 'center';
                    };

                    length = JSONData.length;
                    //iterating to set values of properties in data for each respective
                    //point (main algorithm of KagiChart)
                    //loop counter starts from 2 since data for plot 1 is unique
                    for (index = 0, fcIndex = 0; fcIndex < length; fcIndex += 1, index += 1) {
                        fcDataObj = JSONData[fcIndex];
                        // Calculation of vLine based on hShift.
                        if (fcDataObj && fcDataObj.vline) {
                            continue;
                        }
                        dataObj = data[index] && data[index].config;
                        lastFcDataObj = JSONData[fcIndex];
                        // Special handling for vLines
                        if (lastShift) {
                            lastShift = false;
                            vLinePosition += 0.5;
                        }
                        dataObj && (dataObj.isDefined = true);
                        if (!(fcDataObj.tooltext || datasetObj.JSONData.plottooltext || FCChartObj.plottooltext)){
                            dataObj && (dataObj.toolText += dataObj.displayValue);
                        }
                        if (index && dataObj) {
                            dataObj.isShift = undefined;

                            prevDataObj = data[index - 1].config;
                            dataObj.vAlign = POSITION_MIDDLE;
                            dataObj.align = POSITION_RIGHT;
                            dataObj.showLabel = false;
                            //initialised to null each time
                            plotValue = null;
                            //data value of plot under current loop
                            dataValue = dataObj.setValue;
                            //data value of previous plot
                            //lastDataValue = data[i-1].y;
                            //data value of next plot
                            nextDataValue = data[index + 1] && data[index + 1].config.setValue;
                            valueDifference = mathAbs(lastPlotValue - dataValue);

                            //if current plot is yet render the trend,then care is taken
                            //to make few initial assumptions as algorithm starts with it
                            if (!isRallyInitialised) {
                                //if current plot is higher than the last plotted one
                                //(first data) by significant amount
                                if (dataValue > lastPlotValue && valueDifference > reversalValue) {
                                    //is assumed to be true
                                    isRally = true;
                                    //value of last low point of swing (assumed)
                                    lastLow = lastPlotValue;
                                    //none assumed
                                    lastHigh = null;
                                    //kagi rising
                                    isMovingUp = true;
                                    //first vertical point for shift is obtained
                                    isRallyInitialised = true;
                                    //call of local function to set visibility false for
                                    //anchors and values of unwanted points
                                    setShowLabel(index, isRally);
                                    //if current plot is lower than the last plotted one
                                    //(first data) by significant amount
                                } else if (dataValue < lastPlotValue && valueDifference > reversalValue) {
                                    //is assumed to be false
                                    isRally = false;
                                    //none assumed
                                    lastLow = null;
                                    //value of last high point of swing (assumed)
                                    lastHigh = lastPlotValue;
                                    //kagi falling
                                    isMovingUp = false;
                                    //first vertical point for shift is obtained
                                    isRallyInitialised = true;
                                    //call of local function to set visibility false for
                                    //anchors and values of unwanted points
                                    setShowLabel(index, isRally);
                                    // else, point under loop is not significant to
                                    // draw the first vertical kagi line to
                                } else {
                                    //is set to null
                                    isRally = null;
                                    //vertical shifting direction is set to null
                                    isMovingUp = null;
                                    //first vertical point for shift is yet to be obtained
                                    isRallyInitialised = false;
                                }
                                //trend property for plot 1 is set
                                if (defined(prevDataObj)) {
                                    prevDataObj.isRally = isRally;
                                }
                                if (isRally != null) {
                                    //to get the initial horizontal line in trend color
                                    //(in case data[1].value = data[2].value=... so on or not)
                                    data[0].config.isRally = isRally;
                                }
                                //else, for plot 3 and above, only trend is evaluated
                            } else {
                                //setting trends by concept of Kagi Chart
                                if (dataValue < lastLow && isRally) {
                                    isRally = false;
                                } else if (dataValue > lastHigh && !isRally) {
                                    isRally = true;
                                }
                                //else isRally remains unchanged
                            }

                            // Setting in data for the plot
                            dataObj.isRally = isRally;
                            // To check for having horizontal shift or not,
                            // we need to use the pertinent value
                            if ((isMovingUp && dataValue < lastPlotValue) ||
                                (!isMovingUp && dataValue > lastPlotValue)) {
                                plotValue = lastPlotValue;
                            }
                            // To find if there is a horizontal shift associated
                            // with this plot
                            checkValue = (plotValue) ? plotValue : dataValue;
                            valueDifference = mathAbs(checkValue - nextDataValue);
                            //if the line is static till now
                            if (isMovingUp == null) {
                                isShift = null;
                                //if the line is rising
                            } else if (isMovingUp) {
                                isShift = (checkValue > nextDataValue &&
                                    valueDifference >= reversalValue);
                                //else if the line is falling
                            } else {
                                isShift = (checkValue < nextDataValue &&
                                    valueDifference >= reversalValue);
                            }

                            //To get the last extremes preceding the current point
                            //and setting the vertical/horizontal
                            //alignment of the value to be shown for it.
                            if (prevDataObj && prevDataObj.isShift) {
                                if (isMovingUp) {
                                    lastLow = lastPlotValue;
                                    vAlign = POSITION_BOTTOM;
                                } else if (!isMovingUp) {
                                    lastHigh = lastPlotValue;
                                    vAlign = POSITION_TOP;
                                }
                                align = 'center';
                                //looping to get the actual plot corresponding to the
                                //maxima/minima and setting label properties for the same
                                for (t = index; t > 1; t -= 1) {
                                    if (data[t].y == lastPlotValue) {
                                        data[t].vAlign = vAlign;
                                        data[t].align = align;
                                        data[t].showLabel = true;
                                        //extreme obtained and thus stop looping
                                        break;
                                    }
                                }
                            }
                            //if there is a horizontal shift, then
                            if (isShift) {
                                //updating counter to have to total number of horizontal
                                // shifts in the total plot.This is vital for calculation
                                //of the length of each horizontal shifts.
                                shiftCounter += 1;
                                vLinePosition += 0.5;
                                lastShift = true;
                                //updating the flag by reversing the boolean
                                // value of the flag itself
                                isMovingUp = !isMovingUp;
                                //setting in data for the plot, to be used for
                                //drawing the graph
                                dataObj.isShift = true;
                                //updating last plotting value
                                lastPlotValue = checkValue;
                                catArr.push(JSONData[index + dataObj.__nullCount]);
                                temp = datasetObj._appendCategory(temp, index, catArr, 0);
                            } else if ((isMovingUp && dataValue > lastPlotValue) ||
                                (!isMovingUp && dataValue < lastPlotValue)) {
                                //updating last plotting value
                                lastPlotValue = dataValue;
                                //if cuurent data value is to be skipped for plotting
                            } else {
                                //setting the value to be plotted
                                //(virtually drawing pen stays still due to this)
                                plotValue = lastPlotValue;
                            }
                            //plotValue assigned is either defined or set to null
                            dataObj.plotValue = plotValue;
                            //few local variables are bundled together in an object to be
                            //used later-on to work around a Catch-22 problem
                            dataObj.objParams = {
                                isRally: isRally,
                                lastHigh: lastHigh,
                                lastLow: lastLow,
                                isRallyInitialised: isRallyInitialised
                            };
                        }
                    }
                    // insert if any remaining categories to be appended.
                    datasetObj._appendCategory(temp, index, catArr, 1);
                    // insert the categories before setting the final category.
                    catArr.push(fcDataObj);
                    xAxis.setCategory(catArr);
                    series.shiftCount = shiftCounter + 1;
                }
            },
            _appendCategory: function (temp, index, catArr, lineposition) {
                var i,
                    catObj,
                    catData,
                    refIndex,
                    datasetObj = this,
                    catOnlyData = datasetObj.JSONData.catData;
                if (temp < catOnlyData.length) {
                    for (i = temp; i < catOnlyData.length; i += 1, temp = i){
                        catObj = catOnlyData[i];
                        catData = catObj.data;
                        refIndex = catObj.index - (i + 1);
                        if (refIndex < index) {
                            catData.lineposition = pluckNumber(catData.lineposition, lineposition);
                        }
                        else if (refIndex > index){
                            break;
                        }
                        catArr.push(catData);
                    }
                }
                return temp;
            },
            manageSpace: function () {},
            _getHoveredPlot: function (chartX, chartY) {
                var dataset = this,
                    chart = dataset.chart,
                    chartConfig = chart.config,
                    xAxis = chart.components.xAxis[0],
                    conf = dataset.config,
                    trackIndex = conf.trackIndex,
                    dataStore = dataset.components.data,
                    canvas = chart.components.canvas,
                    canvasConfig = canvas.config,
                    canvasPadding = Math.max(canvasConfig.canvasPaddingLeft, canvasConfig.canvasPadding),
                    canvasLeft = chartConfig.canvasLeft,
                    axisX = chartX - canvasLeft - canvasPadding,
                    i,
                    j,
                    index,
                    returnValue,
                    xMin,
                    xMax,
                    pointObjs,
                    len;

                xMin = Math.floor(Math.max(xAxis.getValue(axisX - conf.maxRadius)));
                xMax = Math.ceil(Math.min(xAxis.getValue(axisX + conf.maxRadius)));

                for(j = xMax; j >= xMin; j--){
                    pointObjs = trackIndex[j];
                    len = pointObjs && pointObjs.length;
                    // search point objects under current value
                    for(i = len; i >= 0; i--){
                        index = pointObjs[i];
                        returnValue = dataset.isWithinShape(dataStore[index], index, chartX, chartY);
                        if (returnValue) {
                            return returnValue;
                        }
                    }
                }
            },
            draw: function () {// retrive requitrd objects
                var i,
                    trackerConfig,
                    graphics,
                    dataSet = this,
                    datasetGraphics = dataSet.graphics,
                    JSONData = dataSet.JSONData,
                    chart  = dataSet.chart,
                    jobList = chart.getJobList(),
                    chartComponents = chart.components,
                    chartConfig = chart.config,
                    conf = dataSet.config,
                    //temp hardcoded.
                    datasetIndex = 0,
                    trackIndex = conf.trackIndex = {},
                    dataSetComponents = dataSet.components,
                    setDataArr = dataSetComponents.data,
                    removeDataArr = dataSetComponents.removeDataArr,
                    removeDataArrLen = removeDataArr && removeDataArr.length,
                    categories = setDataArr,
                    catLen = categories && categories.length,
                    dataSetLen = setDataArr && setDataArr.length,
                    len,
                    paper = chartComponents.paper,
                    xAxis = chartComponents.xAxis[0],
                    xPos,
                    yPos,
                    layers = chart.graphics,
                    dataLabelsLayer = layers.datalabelsGroup,
                    toolText,
                    setElement,
                    setLink,
                    setValue,
                    eventArgs,
                    displayValue,
                    dataStore = dataSet.components.data,
                    dataObj,
                    setRolloutAttr,
                    setRolloverAttr,
                    container = datasetGraphics.container,
                    anchorRadius,
                    group = layers.datasetGroup,
                    hoverEffects,
                    shadow = conf.shadow,
                    anchorShadow,
                    dataLabelContainer = datasetGraphics.dataLabelContainer,
                    anchorProps = {},
                    imgRef,
                    symbol,
                    config,
                    showValue,
                    isNewElem = false,
                    // animCompleteFn = chart.getAnimationCompleteFn(),
                    /*
                        Called when the initial animation compeletes
                        for showing the dataset
                    */
                    initAnimCallBack = function () {
                        container.lineGroup.attr({
                            'clip-rect': null
                        });
                        container.lineShadowGroup.show();
                        container.anchorShadowGroup.show();
                        container.anchorGroup.show();
                        dataLabelContainer && dataLabelContainer.show();
                        // animCompleteFn();
                    },
                    animFlag = true,
                    xAxisZeroPos = xAxis.getAxisPosition(0),
                    xAxisFirstPos = xAxis.getAxisPosition(1),
                    pointDistance = xAxisFirstPos - xAxisZeroPos,
                    totalCanvasWidth,
                    clipCanvas = {
                        'clip-rect': [ mathMax(0, chartConfig.canvasLeft), mathMax(0, chartConfig.canvasTop),
                            mathMax(1, chartConfig.canvasWidth), mathMax(1, chartConfig.canvasHeight)]
                    },
                    clipCanvasInit = {
                        'clip-rect': [ mathMax(0, chartConfig.canvasLeft), mathMax(0, chartConfig.canvasTop), 1,
                        mathMax(1, chartConfig.canvasHeight)]
                    },
                    initialAnimation = false,
                    rallyThickness = conf.rallyThickness,
                    declineThickness = conf.declineThickness,
                    rallyAttr = {
                        stroke: toRaphaelColor({
                            color: conf.rallyColor,
                            alpha: conf.rallyAlpha
                        }),
                        'stroke-linecap': ROUND,
                        'stroke-linejoin': ROUND,
                        'stroke-width': rallyThickness,
                        'stroke-dasharray': conf.rallyDashed
                    },
                    declineAttr = {
                        stroke: toRaphaelColor({
                            color: conf.declineColor,
                            alpha: conf.declineAlpha
                        }),
                        'stroke-linecap': ROUND,
                        'stroke-linejoin': ROUND,
                        'stroke-width': declineThickness,
                        'stroke-dasharray': conf.declineDashed
                    },
                    thickness = {
                        'true': rallyThickness,
                        'false': declineThickness
                    },
                    rallyPath = [],
                    declinePath = [],
                    rallyElem = datasetGraphics.rallyElem,
                    declineElem = datasetGraphics.declineElem,
                    visible = dataSet.visible,
                    xValue = 0,
                    plotX = xAxis.getAxisPosition(xValue),
                    isRally = setDataArr[0] && !! setDataArr[0].isRally,
                    nextPointIsRally,
                    startX = xAxisZeroPos - (pointDistance / 2),
                    plotY,
                    setShadow,
                    crispY,
                    nextPoint,
                    path,
                    lineElement = datasetGraphics.lineElement,
                    pool = dataSet.pool || (dataSet.pool = {}),
                    animationObj = chart.get(configStr, animationObjStr),
                    animationDuration = animationObj.duration || 0,
                    mainElm = animationObj.dummyObj,
                    animObj = animationObj.animObj,
                    noOfImages = 0,
                    animType = animationObj.animType,
                    imageElement;

                conf.imagesLoaded = 0;
                removeDataArrLen && dataSet.remove();
                // save the world if no valid data is there.
                if (!setDataArr.length) {
                    rallyElem && rallyElem.hide();
                    declineElem && declineElem.hide();
                    return;
                }
                else {
                    rallyElem && rallyElem.show();
                    declineElem && declineElem.show();
                }
                // Create dataset container if not created
                if (!container) {
                    container = dataSet.graphics.container = {
                        lineShadowGroup: paper.group('connector-shadow', group).attr(clipCanvasInit),
                        anchorShadowGroup: paper.group('anchor-shadow', group).attr(clipCanvasInit),
                        lineGroup: paper.group(LINE, group).attr(clipCanvasInit),
                        anchorGroup: paper.group('anchors', group).attr(clipCanvasInit)
                    };
                    if (!visible) {
                        container.lineShadowGroup.hide();
                        container.anchorShadowGroup.hide();
                        container.lineGroup.hide();
                        container.anchorGroup.hide();
                    }

                }

                if (!dataStore) {
                    dataStore = dataSet.components.data = [];
                }


                if (!dataLabelContainer) {
                    dataLabelContainer = dataSet.graphics.dataLabelContainer = dataSet.graphics.dataLabelContainer ||
                        paper.group(dataLabelStr, dataLabelsLayer);
                    if (!visible) {
                        dataLabelContainer.hide();
                    }
                }
                len = mathMin(catLen, dataSetLen);
                /*  Calculating total canvas width
                    Required for scroll charts
                */
                totalCanvasWidth = pointDistance * len;

                //draw graph
                // Special situation for first null data.
                if (!setDataArr[0].config.setValue) {
                    for (i = 1; i < dataSetLen; i += 1) {
                        setValue = setDataArr[i].config.setValue;
                        if (setValue) {
                            // Get the first valid value.
                            plotY = setDataArr[i].config.plotY;
                            break;
                        }
                    }
                }
                else {
                    plotY = setDataArr[0].config.plotY;
                }
                isRally = !! setDataArr[0].config.isRally;
                setShadow = setDataArr[0].config.shadow;
                //drawing starts with an initial half horizontal-shift
                crispY = mathRound(plotY) + (thickness[isRally] % 2 / 2);
                if (isRally) {
                    rallyPath.push(M, startX, crispY, H, plotX);
                } else {
                    declinePath.push(M, startX, crispY, H, plotX);
                }

                each(setDataArr, function(point, i) {
                    point = point.config;
                    dataObj = dataStore[i];
                    config = dataObj.config;
                    trackerConfig = point.trackerConfig = {};
                    graphics = dataObj.graphics;
                    imageElement = graphics.image;
                    hoverEffects = config.hoverEffects;
                    setValue = config.setValue;
                    showValue = config.showValue;
                    displayValue = config.displayValue;
                    isNewElem = false;
                    //looping to draw the plots
                    nextPoint = (setDataArr[i + 1] && setDataArr[i + 1].config) || {};
                    if (nextPoint) {
                        path = [M, plotX, plotY];
                        isRally = point.isRally;
                        //if there is a shift corresponding to this point
                        if (point.isShift) {
                            plotX += pointDistance;
                            plotY = point.graphY;
                            path.push(H, plotX);
                            path[2] = mathRound(path[2]) +
                                (thickness[isRally] % 2 / 2);
                            path = path.toString();
                            //draw the path
                            if (isRally) {
                                rallyPath.push(path);
                            } else {
                                declinePath.push(path);
                            }
                            path = [M, plotX, plotY];
                        }
                        //if there is a change in trend between the current and
                        //the next points
                        if (nextPoint.isChanged) {
                            plotY = nextPoint.ty;
                            path.push(V, plotY);
                            path[1] = mathRound(path[1]) +
                                (thickness[isRally] % 2 / 2);
                            path = path.toString();
                            if (isRally) {
                                rallyPath.push(path);
                            } else {
                                declinePath.push(path);
                            }
                            path = [M, plotX, plotY];
                        }

                        nextPointIsRally = nextPoint.isRally;
                        /** @todo: If path contains move to and line to at the
                         * same point line is not visible in native VML brewers
                         * need to remove this code when this issue in fixed in
                         * core.
                         */

                        if (nextPoint.graphY !== path[2]) {
                            path.push(V, nextPoint.graphY);
                            path[1] = mathRound(path[1]) +
                                (thickness[nextPointIsRally] % 2 / 2);
                            path = path.toString();
                            if (nextPointIsRally) {
                                rallyPath.push(path);
                            } else {
                                declinePath.push(path);
                            }
                        }
                        //updating value
                        plotY = nextPoint.graphY;
                    }
                    xPos = (dataObj._xPos = xAxis.getAxisPosition(point.plotX));
                    yPos = (dataObj._yPos = point.plotY);
                    trackIndex[point.plotX] ? trackIndex[point.plotX].push(i) : (trackIndex[point.plotX] = [],
                        trackIndex[point.plotX].push(i));
                    dataObj._index = point.plotX;
                    anchorProps = config.anchorProps;
                    symbol = anchorProps.symbol;
                    anchorShadow = anchorProps.shadow;
                    toolText = point.finalTooltext = point.toolText;
                    setLink = config.setLink;
                    if (yPos !== UNDEFINED && !isNaN(yPos) && point.isDefined) {

                        // Storing the event arguments
                        eventArgs = point.eventArgs = point.eventArgs || {};

                        // point.eventArgs = {
                        //     index: i,
                        //     link: setLink,
                        //     value: setValue,
                        //     displayValue: displayValue,
                        //     categoryLabel: config.label,
                        //     toolText: toolText,
                        //     id: conf.userID,
                        //     datasetIndex: datasetIndex,
                        //     datasetName: JSONData.seriesname,
                        //     visible: visible
                        // };

                        // Storing the event arguments
                        eventArgs.index = i;
                        eventArgs.link = setLink;
                        eventArgs.value = setValue;
                        eventArgs.displayValue = displayValue;
                        eventArgs.categoryLabel = config.label;
                        eventArgs.toolText = toolText;
                        eventArgs.id = conf.userID;
                        eventArgs.datasetIndex = datasetIndex || 0;
                        eventArgs.datasetName = JSONData.seriesname;
                        eventArgs.visible = visible;

                        // Hover consmetics
                        setRolloutAttr = setRolloverAttr = {};

                        // If imageurl is present
                        if (anchorProps.imageUrl) {
                            imgRef = new Image();
                            config.anchorImageLoaded = false;
                            imgRef.onload = dataSet._onAnchorImageLoad(dataSet, i, eventArgs, xPos, yPos, dataObj);
                            imgRef.onerror = dataSet._onErrorSetter(dataSet, i);
                            imgRef.src = anchorProps.imageUrl;
                            noOfImages++;
                        }
                        else {
                            imageElement && imageElement.hide();
                            setElement = graphics.element;
                            // If there is no existing graphics element then create it
                            if (!setElement) {
                                // Reuse the cache element
                                if(pool.element && pool.element.length) {
                                    setElement = graphics.element = pool.element.shift();
                                }
                                // If there is no element in cachestore then create it freshly
                                else {
                                    setElement = graphics.element = paper.polypath(container.anchorGroup);
                                    isNewElem = true;
                                }
                                initialAnimation = true;
                                setElement.attr({
                                    polypath: [symbol[1] || 2, xPos, yPos, anchorProps.radius,
                                        anchorProps.startAngle, 0]
                                });
                            }
                            else {
                                setElement.animateWith(mainElm, animObj, {
                                    polypath: [symbol[1] || 2, xPos, yPos, anchorProps.radius,
                                        anchorProps.startAngle, 0]
                                },animationDuration, animType);
                                animFlag && initAnimCallBack();
                                animFlag = false;
                            }

                            // Set all attributes that are not related to non position
                            setElement.attr({
                                fill: toRaphaelColor({
                                    color: anchorProps.bgColor,
                                    alpha: anchorProps.bgAlpha
                                }),
                                stroke: toRaphaelColor({
                                    color: anchorProps.borderColor,
                                    alpha: anchorProps.borderAlpha
                                }),
                                'stroke-width': anchorProps.borderThickness,
                                visibility: !anchorProps.radius ? hiddenStr : visible
                            })
                            .shadow(anchorShadow, container.anchorShadowGroup)
                            .data('anchorRadius', anchorProps.radius)
                            .data('anchorHoverRadius', hoverEffects.anchorRadius)
                            .data('hoverEnabled', hoverEffects.enabled)
                            .data(EVENTARGS,eventArgs);

                            // anchor Radius of hot element is set to maximum of hover radius and anchor radius
                            anchorRadius = mathMax(anchorProps.radius,
                                hoverEffects &&

                                hoverEffects.anchorRadius || 0, HTP)+ anchorProps.borderThickness / 2;

                            trackerConfig.trackerRadius = anchorRadius;
                        }


                        if (hoverEffects.enabled) {
                            setRolloverAttr = {
                                polypath: [hoverEffects.anchorSides || 2,
                                            xPos, yPos,
                                            hoverEffects.anchorRadius,
                                            hoverEffects.startAngle,
                                            hoverEffects.dip
                                        ],
                                fill: toRaphaelColor({
                                    color: hoverEffects.anchorColor,
                                    alpha: hoverEffects.anchorBgAlpha
                                }),
                                stroke: toRaphaelColor({
                                    color: hoverEffects.anchorBorderColor,
                                    alpha: hoverEffects.anchorBorderAlpha
                                }),
                                'stroke-width': hoverEffects.anchorBorderThickness
                            };
                            setRolloutAttr = {
                                polypath: [anchorProps.sides, xPos, yPos,
                                            anchorProps.radius, anchorProps.startAngle, 0
                                        ],
                                fill: toRaphaelColor({
                                    color: anchorProps.bgColor,
                                    alpha: anchorProps.bgAlpha
                                }),
                                stroke: toRaphaelColor({
                                    color: anchorProps.borderColor,
                                    alpha: anchorProps.borderAlpha
                                }),
                                'stroke-width': anchorProps.borderThickness
                            };
                            setElement && setElement
                            .data('anchorRadius', anchorProps.radius)
                            .data('anchorHoverRadius', hoverEffects.anchorRadius)
                            .data('hoverEnabled', hoverEffects.enabled)
                            .data(SETROLLOVERATTR, setRolloverAttr)
                            .data(SETROLLOUTATTR, setRolloutAttr)
                            .data(EVENTARGS,eventArgs);
                        }

                        // dataSet.drawLabel(i);
                    }
                    else {
                        graphics.element && graphics.element.hide();
                        imageElement && imageElement.hide();
                    }
                });

                if (!lineElement) {
                    if (!rallyElem) {
                        lineElement = rallyElem = datasetGraphics.rallyElem = paper.path(container.lineGroup);
                    }
                    rallyElem
                    .animateWith(mainElm, animObj, {
                        path: rallyPath
                    }, animFlag ? 0 : animationDuration, animType)
                    .attr(rallyAttr)
                    .shadow(rallyThickness && shadow, container.lineShadowGroup);
                    if (!declineElem) {
                        lineElement = declineElem = datasetGraphics.declineElem = paper.path(container.lineGroup);
                    }
                    declineElem
                    .animateWith(mainElm, animObj, {
                        path: declinePath
                    }, animFlag ? 0 : animationDuration, animType)
                    .attr(declineAttr)
                    .shadow(declineThickness && shadow, container.lineShadowGroup);
                    initialAnimation = true;
                }

                !(animationDuration && animFlag) && (animFlag = false);

                conf.noOfImages = conf.totalImages = noOfImages;
                if (noOfImages === 0) {
                    dataSet.drawn ? dataSet.drawLabel() :
                        jobList.labelDrawID.push(schedular.addJob(dataSet.drawLabel, dataSet, [],
                        lib.priorityList.tracker));
                }
                dataSet.drawn = true;
                container.anchorGroup
                .animateWith(mainElm, animObj, clipCanvas, animationDuration, animType);
                // container.anchorGroup.hide();
                dataLabelContainer.hide();
                container.lineShadowGroup
                .animateWith(mainElm, animObj, clipCanvas, animationDuration, animType);
                container.anchorShadowGroup
                .animateWith(mainElm, animObj, clipCanvas, animationDuration, animType);

                container.lineShadowGroup
                .animateWith(mainElm, animObj, clipCanvas, animationDuration, animType);

                // clip-canvas animation to line chart
                container.lineGroup
                .animateWith(mainElm, animObj, clipCanvas, animationDuration, animType, initAnimCallBack);
            },
            hidingPosition: function () {
                return function (data) {
                    var element = data.graphics.element,
                        oldPos = element && element.attr('polypath');
                    return {
                        // Only the radius of the anchor elements.
                        polypath: (oldPos[3] = 0 && oldPos),
                        // for the hot elements to be zero radius.
                        r: 0,
                        // for the text element to hide itself.
                        text: BLANKSTRING
                    };
                };
            }
        },'Line']);

    }
]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-group-errorbar2d',
    function () {
        var global = this,
            lib = global.hcLib,
            COMPONENT = 'component',
            DATASET_GROUP = 'datasetGroup',
            preDefStr = lib.preDefStr,
            COLUMN = preDefStr.column;

        FusionCharts.register(COMPONENT, [DATASET_GROUP, 'errorbar2d', {
        },COLUMN]);
    }
]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-group-dragnode',
    function() {
        var global = this,
            lib = global.hcLib,
            //strings
            preDefStr = lib.preDefStr,
            colorStrings = preDefStr.colors,
            COLOR_FFFFFF = colorStrings.FFFFFF,
            COLOR_000000 = colorStrings.c000000,

            configStr = preDefStr.configStr,
            animationObjStr = preDefStr.animationObjStr,
            BLANK = lib.BLANKSTRING,
            BLANKSTRING = lib.BLANKSTRING,
            //add the tools thats are requared
            pluck = lib.pluck,
            getFirstValue = lib.getFirstValue,
            // getDefinedColor = lib.getDefinedColor,
            extend2 = lib.extend2, //old: jarendererExtend / margecolone
            HASHSTRING = lib.HASHSTRING,
            UNDEFINED,
            // The default value for stroke-dash attribute.
            // getLinkAction = lib.getLinkAction,
            // NumberFormatter = lib.NumberFormatter,
            hashify = lib.hashify,
            PXSTRING = 'px',
            POLYGON = 'polygon',
            CIRCLE = 'circle',
            RECTANGLE = 'rectangle',
            POINTER = 'pointer',
            NORMALSTRING = 'normal',
            COMPONENT = 'component',
            DATASET = 'dataset',
            DATASET_GROUP = 'datasetGroup',
            each = lib.each,
            componentDispose = lib.componentDispose,
            defined = function(obj) {
                return obj !== UNDEFINED && obj !== null;
            },

            // CRISP = 'crisp',
            PX = PXSTRING,
            COMMA = ',',
            math = Math,
            mathMin = math.min,
            mathMax = math.max,
            hasTouch = lib.hasTouch,
            // hot/tracker threshold in pixels
            // getColumnColor = lib.graphics.getColumnColor,
            // pluckColor = lib.pluckColor,
            COMMASTRING = lib.COMMASTRING,
            HUNDREDSTRING = lib.HUNDREDSTRING,
            // COMMASPACE = lib.COMMASPACE,
            //strings
            BLANKSPACE = ' ',
            //add the tools thats are requared
            libGraphics = lib.graphics,
            parseColor = libGraphics.parseColor,
            getValidColor = libGraphics.getValidColor,
            LABEL = 'label',
            INPUT = 'input';

        FusionCharts.register(COMPONENT, [DATASET_GROUP, 'Dragnode', {
            init: function() {
                var manager = this;
                manager.connectorSet = [];
                manager.nodes = {};
                manager.datasets = [];
                manager.components = [];
                manager.graphics = {};
                manager.labelSet = [];
            },
            addDataset: function(dataSet, index) {
                var manager = this,
                    dataset = manager.datasets[index];
                dataSet.groupManager = manager;
                dataSet.datasetIndex = index;
                if (!dataset) {
                    dataset = manager.datasets[index] = {
                        dataset: dataSet
                    };
                }

            },
            addLabels: function(labels, index) {
                var manager = this,
                    labelSet = manager.labelSet[index];
                labels.groupManager = manager;
                if (!labelSet) {
                    labelSet = manager.labelSet[index] = {
                        labels: labels
                    };
                }
            },
            addConnectors: function(connectors, index) {
                var manager = this,
                    connectorSet = manager.connectorSet[index];
                connectors.groupManager = manager;
                if (!connectorSet) {
                    connectorSet = manager.connectorSet[index] = {
                        connectors: connectors
                    };
                }
            },
            showNodeAddUI: function() {
                var manager = this,
                    chart = manager.chart,
                    datasets = chart.components.dataset,
                    datasetDropDownStr = BLANKSTRING,
                    str1 = '<option value="',
                    str2 = '">',
                    str3 = '</option>',
                    index,
                    conf,
                    dataset,
                    type,
                    i;
                for (i = 0; i < datasets.length; i++) {
                    dataset = datasets[i] || {};
                    index = dataset.index;
                    conf = dataset.config;
                    type = dataset.plotType;
                    if (type === 'dragnode') {
                        datasetDropDownStr += str1 + conf.id + str2 + ((conf.name !== BLANK && conf.name !==
                            UNDEFINED) && conf.name + COMMASTRING + BLANKSPACE || BLANK) + conf.id + str3;
                    }

                }
                manager.showNodeUpdateUI(chart, {
                    dataset: {
                        innerHTML: datasetDropDownStr
                    }
                });
            },
            showConnectorAddUI: function() {
                var manager = this,
                    chart = manager.chart,
                    nodes = manager.nodes,
                    nodeStr = BLANKSTRING,
                    str1 = '<option value="',
                    str2 = '">',
                    str3 = '</option>',
                    id,
                    i,
                    config,
                    node;
                for (i in nodes) {
                    node = nodes[i];
                    config = node.config;
                    id = config.id;
                    nodeStr += str1 + id + str2 + id + str3;
                }
                manager.showConnectorUpdateUI(chart, {
                    fromid: {
                        innerHTML: nodeStr
                    },
                    toid: {
                        innerHTML: nodeStr
                    }
                });
            },
            draw: function() {
                var manager = this,
                    datasets = manager.datasets,
                    connectorSet = manager.connectorSet,
                    i,
                    dataset,
                    connectors,
                    labelSet = manager.labelSet,
                    labels,
                    ln;

                manager.updateUIvisuals();
                for (i = 0, ln = datasets.length; i < ln; i++) {
                    dataset = datasets[i].dataset;
                    dataset.draw();
                }
                for (i = 0, ln = connectorSet.length; i < ln; i++) {
                    connectors = connectorSet[i].connectors;
                    connectors.draw();
                }
                for (i = 0, ln = labelSet.length; i < ln; i++) {
                    labels = labelSet[i].labels;
                    labels.draw();
                }
                manager.drawn = true;
            },
            getJSONData: function() {
                var manager = this,
                    nodeSets = manager.datasets,
                    connectorSets = manager.connectorSet,
                    labelSets = manager.labelSet,
                    jsonData = {},
                    i,
                    len,
                    JSONData,
                    dataset;
                jsonData.dataset = [];
                jsonData.connectors = [];
                jsonData.labels = [];
                for (i = 0, len = nodeSets.length; i < len; i++) {
                    dataset = nodeSets[i] && nodeSets[i].dataset;
                    JSONData = dataset.JSONData;
                    if (!jsonData.dataset[i]) {
                        jsonData.dataset[i] = extend2({}, dataset.JSONData);
                    }
                    jsonData.dataset[i].data = dataset.getJSONData();
                }
                for (i = 0, len = connectorSets.length; i < len; i++) {
                    dataset = connectorSets[i] && connectorSets[i].connectors;
                    if (!jsonData.connectors[i]) {
                        jsonData.connectors[i] = extend2({}, dataset.JSONData);
                    }
                    jsonData.connectors[i].connector = dataset.getJSONData();
                }
                for (i = 0, len = labelSets.length; i < len; i++) {
                    dataset = labelSets[i] && labelSets[i].labels;
                    if (!jsonData.labels[i]) {
                        jsonData.labels[i] = {
                            label: []
                        };
                    }
                    jsonData.labels[i].label = dataset.getJSONData();
                }
                return jsonData;
            },
            clearLongPress: function() {
                var ele = this;
                ele.data('move', false);
                clearTimeout(ele._longpressactive);
                delete ele._longpressactive;
            },
            createHtmlDialog: function(chart, dialogWidth, dialogHeight,
                onsubmit, oncancel, onremove, cacheUI) {
                var paper = chart.components.paper,
                    conf = chart.config,
                    inCanvasStyle = conf.style.inCanvasStyle || {},
                    chartWidth = chart.config.width,
                    chartHeight = chart.config.height,
                    padding = 5,
                    dialogAttrs,
                    okAttrs,
                    cancelAttrs,
                    removeAttrs,
                    transposeAnimDuration = chart.get(configStr, animationObjStr).transposeAnimDuration,
                    buttonStyle = {
                        color: hashify(inCanvasStyle.color),
                        textAlign: 'center',
                        paddingTop: 1 + PX,
                        border: '1px solid #cccccc',
                        borderRadius: 4 + PX,
                        cursor: POINTER,
                        '_cursor': 'hand',
                        backgroundColor: HASHSTRING + COLOR_FFFFFF,
                        zIndex: 21,
                        '-webkit-border-radius': 4 + PX
                    },
                    ui = cacheUI;
                if (!ui) {
                    ui = paper.html('div', {
                        fill: 'transparent',
                        width: chartWidth,
                        height: chartHeight
                    }, {
                        fontSize: 10 + PX,
                        lineHeight: 15 + PX,
                        fontFamily: inCanvasStyle.fontFamily
                    }, chart.linkedItems.container);
                } else {
                    if (transposeAnimDuration) {
                        ui.animate({
                            width: chartWidth,
                            height: chartHeight
                        }, transposeAnimDuration, NORMALSTRING);
                    } else {
                        ui.attr({
                            width: chartWidth,
                            height: chartHeight
                        });
                    }
                }
                if (!ui.veil) {
                    ui.veil = paper.html('div', {
                        fill: COLOR_000000,
                        width: chartWidth,
                        height: chartHeight,
                        opacity: 0.3
                    }, undefined, ui);
                } else {
                    if (transposeAnimDuration) {
                        ui.veil.animate({
                            width: chartWidth,
                            height: chartHeight
                        }, transposeAnimDuration, NORMALSTRING);
                    } else {
                        ui.veil.attr({
                            width: chartWidth,
                            height: chartHeight
                        });
                    }
                }
                dialogAttrs = {
                    x: (chartWidth - dialogWidth) / 2,
                    y: (chartHeight - dialogHeight) / 2,
                    fill: 'efefef',
                    strokeWidth: 1,
                    stroke: COLOR_000000,
                    width: dialogWidth,
                    height: dialogHeight
                };
                if (!ui.dialog) {
                    ui.dialog = paper.html('div', dialogAttrs, {
                        borderRadius: 5 + PX,
                        boxShadow: '1px 1px 3px #000000',
                        '-webkit-border-radius': 5 + PX,
                        '-webkit-box-shadow': '1px 1px 3px #000000',
                        filter: 'progid:DXImageTransform.Microsoft.Shadow(Strength=4, Direction=135, Color="#000000")'
                    }, ui);
                } else {
                    if (transposeAnimDuration) {
                        ui.dialog.animate({
                            x: dialogAttrs.x,
                            y: dialogAttrs.y,
                            width: dialogAttrs.width,
                            height: dialogAttrs.height
                        }, transposeAnimDuration, NORMALSTRING);
                    } else {
                        ui.dialog.attr(dialogAttrs);
                    }
                }

                okAttrs = {
                    x: dialogWidth - 70 - padding,
                    y: dialogHeight - 23 - padding,
                    width: 65,
                    height: 17,
                    text: 'Submit',
                    tabIndex: 1
                };
                if (!ui.ok) {
                    ui.ok = paper.html('div', okAttrs, buttonStyle, ui.dialog)
                        .on('click', onsubmit);
                } else {
                    if (transposeAnimDuration) {
                        ui.ok.animate({
                            x: okAttrs.x,
                            y: okAttrs.y,
                            width: okAttrs.width,
                            height: okAttrs.height
                        }, transposeAnimDuration, NORMALSTRING);
                    } else {
                        ui.ok.attr(okAttrs);
                    }
                }

                cancelAttrs = {
                    x: dialogWidth - 140 - padding,
                    y: dialogHeight - 23 - padding,
                    width: 65,
                    height: 17,
                    text: 'Cancel',
                    tabIndex: 2
                };
                if (!ui.cancel) {
                    ui.cancel = paper.html('div', cancelAttrs, buttonStyle, ui.dialog).on('click', oncancel);
                } else {
                    if (transposeAnimDuration) {
                        ui.cancel.animate({
                            x: cancelAttrs.x,
                            y: cancelAttrs.y,
                            width: cancelAttrs.width,
                            height: cancelAttrs.height
                        }, transposeAnimDuration, NORMALSTRING);
                    } else {
                        ui.cancel.attr(cancelAttrs);
                    }
                }

                removeAttrs = {
                    x: dialogWidth - 210 - padding,
                    y: dialogHeight - 23 - padding,
                    width: 65,
                    height: 17,
                    text: 'Delete',
                    tabIndex: 3
                };
                if (!ui.remove) {
                    ui.remove = paper.html('div', removeAttrs, buttonStyle, ui.dialog).on('click', onremove);
                } else {
                    if (transposeAnimDuration) {
                        ui.remove.animate({
                            x: removeAttrs.x,
                            y: removeAttrs.y,
                            width: removeAttrs.width,
                            height: removeAttrs.height
                        }, transposeAnimDuration, NORMALSTRING);
                    } else {
                        ui.remove.attr(removeAttrs);
                    }
                }

                if (!ui.handleKeyPress) {
                    // Add an event that would handle enter and esc on input
                    // elements
                    ui.handleKeyPress = function(e) {
                        if (e.keyCode === 13) {
                            ui.ok.trigger(hasTouch ? 'touchStart' : 'click', e);
                        } else if (e.keyCode === 27) {
                            ui.cancel.trigger(hasTouch ? 'touchStart' : 'click', e);
                        }
                    };
                }

                // Keep initially hidden.
                // ui.hide();

                return ui;
            },
            updateUIvisuals: function() {
                var manager = this,
                    cacheConnectorUpdateUI = manager.graphics.cacheConnectorUpdateUI,
                    chart = manager.chart,
                    cacheLabelUpdateUI = manager.graphics.cacheLabelUpdateUI,
                    cacheLabelDeleteUI = manager.graphics.cacheLabelDeleteUI,
                    cacheUpdateUI = manager.graphics.cacheUpdateUI;
                if (cacheConnectorUpdateUI) {
                    manager.createHtmlDialog(chart, 350, 215, undefined, undefined, undefined, cacheConnectorUpdateUI);
                }
                if (cacheUpdateUI) {
                    manager.createHtmlDialog(chart, 350, 215, undefined, undefined, undefined, cacheUpdateUI);
                }
                if (cacheLabelUpdateUI) {
                    manager.createHtmlDialog(chart, 350, 215, undefined, undefined, undefined, cacheLabelUpdateUI);
                }
                if (cacheLabelDeleteUI) {
                    manager.createHtmlDialog(chart, 350, 215, undefined, undefined, undefined, cacheLabelDeleteUI);
                }

            },
            showConnectorUpdateUI: function(chart, config, edit) {
                var manager = this,
                    renderer = chart.components.paper,
                    conf = chart.config,
                    inCanvasStyle = conf.style.inCanvasStyle || {},
                    ui = manager.cacheConnectorUpdateUI,
                    inputStyle = {
                        border: '1px solid #cccccc',
                        fontSize: 10 + PX,
                        lineHeight: 15 + PX,
                        fontFamily: inCanvasStyle.fontFamily,
                        padding: 2 + PX
                    },
                    labelStyle = {
                        textAlign: 'right'
                    },
                    fields = ui && ui.fields,
                    labels = ui && ui.labels,
                    innerHTML,
                    field,
                    value,
                    onDelete = function() {
                        var fields = ui && ui.fields,
                            config = {
                                from: fields.fromid.val(),
                                to: fields.toid.val(),
                                id: fields.id.val()
                            };

                        chart.deleteConnector(config);
                        ui.hide();
                    },
                    dialog;

                if (!ui) {
                    ui = manager.graphics.cacheConnectorUpdateUI = manager.createHtmlDialog(chart,
                        315, 215,
                        function() {
                            var fields = ui && ui.fields,
                                submitObj;
                            if (fields) {
                                submitObj = {
                                    from: fields.fromid.val(),
                                    to: fields.toid.val(),
                                    id: fields.id.val(),
                                    label: fields.label.val(),
                                    color: fields.color.val(),
                                    alpha: fields.alpha.val(),
                                    link: fields.url.val(),
                                    tooltext: fields.tooltext.val(),
                                    strength: fields.strength.val(),
                                    arrowatstart: fields.arratstart.val(),
                                    arrowatend: fields.arratend.val(),
                                    dashed: fields.dashed.val(),
                                    dashlen: fields.dashlen.val(),
                                    dashgap: fields.dashgap.val()
                                };

                                // Validate
                                if (submitObj.from) {
                                    if (submitObj.to) {
                                        if (submitObj.from != submitObj.to) {
                                            edit ? chart.editConnector(submitObj) :
                                                chart.addConnector(submitObj);
                                            ui.enableFields();
                                            ui.hide();
                                            ui.clearFields();
                                            return;
                                        } else {
                                            ui.error.attr({
                                                text: 'Connector cannot start and end at the same node!'
                                            });
                                            fields.fromid.focus();
                                        }
                                    } else {
                                        ui.error.attr({
                                            text: 'Please select a valid connector end.'
                                        });
                                        fields.toid.focus();
                                    }
                                } else {
                                    ui.error.attr({
                                        text: 'Please select a valid connector start.'
                                    });
                                    fields.fromid.focus();
                                }
                            }
                        },
                        // Cancel function
                        function() {
                            ui.error.attr({
                                text: BLANKSTRING
                            });
                            ui.enableFields();
                            ui.hide();
                        },
                        // Delete function
                        onDelete);
                    dialog = ui.dialog;
                    labels = ui.labels = {};
                    fields = ui.fields = {};
                } else {
                    ui.attr({
                        width: chart.config.width,
                        height: chart.config.height
                    });
                    ui.veil.attr({
                        width: chart.config.width,
                        height: chart.config.height
                    });
                    ui.dialog.attr({
                        x: (chart.config.width - 315) / 2,
                        y: (chart.config.height - 215) / 2,
                        width: 315,
                        height: 215
                    });
                }
                ui.config = config;
                if (!ui.enableFields) {
                    ui.enableFields = function() {
                        var key;
                        for (key in config) {
                            if (config[key] && config[key].disabled && fields[key]) {
                                fields[key].element.removeAttribute('disabled');
                            }
                        }
                    };
                }
                if (!ui.clearFields) {
                    ui.clearFields = function() {
                        var key,
                            fields = ui.fields;
                        for (key in fields) {
                            if (!fields[key].element.disabled) {
                                fields[key].element.value = BLANKSTRING;
                            }
                        }
                    };
                }




                each(manager.connectorUpdateUIDefinition, function(def) {
                    var key = def.key,
                        attr = config[key] || {};

                    if (!labels[key]) {
                        labels[key] = renderer.html(LABEL, {
                            x: def.x,
                            y: def.y,
                            width: def.labelWidth || 45,
                            text: def.text
                        }, labelStyle, dialog);
                    }

                    // No need to proceed of this label has no input box
                    // associated with itself.
                    if (def.noInput) {
                        return;
                    }

                    if (!(field = fields[key])) {
                        field = fields[key] = renderer.html(def.inputType || INPUT, {
                            y: -2 + (def.inputPaddingTop || 0),
                            x: def.labelWidth && (def.labelWidth + 5) || 50,
                            width: def.inputWidth || 50,
                            name: key || BLANKSTRING
                        }, inputStyle);

                        if (def.inputType !== 'select') {
                            field.attr({
                                type: def.type || 'text'
                            }).on('keyup', ui.handleKeyPress);
                        }
                        field.add(labels[key]);
                    }

                    if ((innerHTML = pluck(attr.innerHTML, def.innerHTML))) {
                        field.attr({
                            innerHTML: innerHTML
                        });
                    }
                    if ((value = pluck(attr.val, def.val)) !== undefined) {
                        field.val(value);
                    }
                    if (attr.disabled) {
                        field.attr({
                            disabled: 'disabled'
                        });
                    }
                });

                //dash checking and ui modification
                //call to set default fro the first time
                ui.checkDash = function() {
                    var checked = fields.dashed && fields.dashed.val(),
                        showHideFn = checked ? 'show' : 'hide';
                    labels.dashgap && labels.dashgap[showHideFn]();
                    fields.dashgap && fields.dashgap[showHideFn]();
                    labels.dashlen && labels.dashlen[showHideFn]();
                    fields.dashlen && fields.dashlen[showHideFn]();
                };
                ui.checkDash();
                fields.dashed.on('click', ui.checkDash);

                if (!ui.error) {
                    ui.error = renderer.html('span', {
                        color: 'ff0000',
                        x: 10,
                        y: 170
                    }, undefined, dialog);
                }


                ui.remove[edit ? 'show' : 'hide']();
                // Show the dialog box
                if (chart.animation) {
                    ui.fadeIn('fast');
                } else {
                    ui.show();
                }
            },
            labelUpdateUIDefinition: [{
                key: LABEL,
                text: 'Label*',
                x: 10,
                y: 15,
                inputWidth: 235
            }, {
                key: 'size',
                text: 'Size',
                x: 10,
                y: 40
            }, {
                key: 'padding',
                text: 'Padding',
                x: 10,
                y: 65
            }, {
                key: 'x',
                text: 'Position',
                x: 120,
                y: 65,
                labelWidth: 70,
                inputWidth: 25
            }, {
                key: 'y',
                text: COMMA,
                x: 225,
                y: 65,
                labelWidth: 10,
                inputWidth: 25
            }, {
                key: 'xy',
                text: '(x, y)',
                x: 260,
                y: 65,
                noInput: true
            }, {
                key: 'allowdrag',
                text: 'Allow Drag',
                x: 120,
                y: 40,
                inputType: 'checkbox',
                inputPaddingTop: 3,
                inputWidth: 15,
                labelWidth: 70,
                val: 1
            }, {
                key: 'color',
                text: 'Color',
                x: 10,
                y: 90
            }, {
                key: 'alpha',
                text: 'Alpha',
                x: 145,
                y: 90,
                inputWidth: 30,
                val: HUNDREDSTRING
            }, {
                key: 'bordercolor',
                text: 'Border Color',
                x: 10,
                y: 125,
                labelWidth: 100
            }, {
                key: 'bgcolor',
                text: 'Background Color',
                x: 10,
                y: 150,
                labelWidth: 100
            }],
            showLabelUpdateUI: function(chart, options) {
                var manager = this,
                    paper = chart.components.paper,
                    conf = chart.config,
                    inCanvasStyle = conf.style.inCanvasStyle || {},
                    ui = manager.graphics.cacheLabelUpdateUI,
                    inputStyle = {
                        border: '1px solid #cccccc',
                        fontSize: 10 + PX,
                        lineHeight: 15 + PX,
                        fontFamily: inCanvasStyle.fontFamily,
                        padding: 2 + PX
                    },
                    labelStyle = {
                        textAlign: 'right'
                    },
                    fields = ui && ui.fields,
                    labels = ui && ui.labels,
                    field,
                    value,
                    dialog;

                if (!ui) {
                    ui = manager.graphics.cacheLabelUpdateUI = manager.createHtmlDialog(chart,
                        315, 205,
                        function() {
                            var fields = ui && ui.fields,
                                submitObj;
                            if (fields) {
                                // Prepare obbject for submission.
                                submitObj = {
                                    text: fields.label.val(),
                                    x: fields.x.val(),
                                    y: fields.y.val(),
                                    color: fields.color.val(),
                                    alpha: fields.alpha.val(),
                                    bgcolor: fields.bgcolor.val(),
                                    bordercolor: fields.bordercolor.val(),
                                    fontsize: fields.size.val(),
                                    allowdrag: fields.allowdrag.val(),
                                    padding: fields.padding.val()
                                };

                                if (submitObj.text) {
                                    chart.addLabel && chart.addLabel(submitObj);
                                    ui.hide();
                                    return;
                                } else {
                                    ui.error.attr({
                                        text: 'Label cannot be blank.'
                                    });
                                    fields.label.focus();

                                }
                            }
                        },
                        function() {
                            ui.error.attr({
                                text: BLANKSTRING
                            });
                            ui.hide();
                        });
                    dialog = ui.dialog;
                    labels = ui.labels = {};
                    fields = ui.fields = {};
                }

                each(manager.labelUpdateUIDefinition, function(def) {
                    var key = def.key;

                    if (!labels[key]) {
                        labels[key] = paper.html(LABEL, {
                            x: def.x,
                            y: def.y,
                            width: def.labelWidth || 45,
                            text: def.text
                        }, labelStyle, dialog);
                    }

                    // No need to proceed of this label has no input box
                    // associated with itself.
                    if (def.noInput) {
                        return;
                    }

                    if (!(field = fields[key])) {
                        field = fields[key] = paper.html(INPUT, {
                            y: -2 + (def.inputPaddingTop || 0),
                            x: def.labelWidth && (def.labelWidth + 5) || 50,
                            width: def.inputWidth || 50,
                            type: def.inputType || 'text',
                            name: key || BLANKSTRING
                        }, inputStyle, labels[key]).on('keyup', ui.handleKeyPress);
                    }

                    if ((value = pluck(options[key], def.val)) !== undefined) {
                        field.val(value);
                    }

                });

                if (!ui.error) {
                    ui.error = paper.html('span', {
                        color: 'ff0000',
                        x: 10,
                        y: 180
                    }, undefined, dialog);
                }

                // Show the dialog box
                if (chart.animation) {
                    ui.fadeIn('fast');
                } else {
                    ui.show();
                }
                // Focus on label textbox
                ui.fields.label.focus();
            },
            showLabelDeleteUI: function(label) {
                var manager = this,
                    chart = manager.chart,
                    animationObj = chart.get(configStr, animationObjStr),
                    animation = animationObj.duration,
                    paper = chart.components.paper,
                    ui = manager.graphics.cacheLabelDeleteUI;
                if (!ui) {
                    ui = manager.graphics.cacheLabelDeleteUI =
                        manager.createHtmlDialog(chart, 250, 100, undefined, function() {
                                ui.hide();
                            },
                            function() {
                                chart.deleteLabel(label.config.index);
                                ui.hide();
                            });

                    // create a location where to show the text message
                    ui.message = paper.html('span', {
                        x: 10,
                        y: 10,
                        width: 230,
                        height: 80
                    }).add(ui.dialog);
                    // since submit button is not needed, hide it and move the
                    // delete button to its place.
                    ui.ok.hide();
                    ui.remove.translate(175).show();
                }

                // Update the message with proper text.
                ui.message.attr({
                    text: 'Would you really like to delete the label: \"' +
                        label.config.text + '\"?'
                });

                // Show the dialog box
                if (animation) {
                    ui.fadeIn('fast');
                } else {
                    ui.show();
                }
            },
            connectorUpdateUIDefinition: [{
                key: 'fromid',
                text: 'Connect From',
                inputType: 'select',
                x: 10,
                y: 15,
                labelWidth: 80,
                inputWidth: 100
            }, {
                key: 'toid',
                text: 'Connect To',
                inputType: 'select',
                x: 10,
                y: 40,
                labelWidth: 80,
                inputWidth: 100
            }, {
                key: 'arratstart',
                text: 'Arrow At Start',
                x: 200,
                y: 15,
                type: 'checkbox',
                inputPaddingTop: 3,
                labelWidth: 80,
                inputWidth: 15
            }, {
                key: 'arratend',
                text: 'Arrow At End',
                x: 200,
                y: 40,
                type: 'checkbox',
                inputPaddingTop: 3,
                labelWidth: 80,
                inputWidth: 15
            }, {
                key: LABEL,
                text: 'Label',
                x: 10,
                y: 75,
                labelWidth: 40,
                inputWidth: 120
            }, {
                key: 'id',
                text: 'Node ID',
                x: 190,
                y: 75,
                inputWidth: 55
            }, {
                key: 'color',
                text: 'Color',
                x: 10,
                y: 100,
                labelWidth: 40,
                inputWidth: 35
            }, {
                key: 'alpha',
                text: 'Alpha',
                x: 110,
                y: 100,
                inputWidth: 25,
                labelWidth: 35
            }, {
                key: 'strength',
                text: 'Strength',
                x: 190,
                y: 100,
                inputWidth: 55,
                val: '0.1'
            }, {
                key: 'url',
                text: 'Link',
                x: 10,
                y: 125,
                labelWidth: 40,
                inputWidth: 120
            }, {
                key: 'tooltext',
                text: 'Tooltip',
                x: 190,
                y: 125,
                labelWidth: 40,
                inputWidth: 60
            }, {
                key: 'dashed',
                text: 'Dashed',
                x: 10,
                y: 150,
                type: 'checkbox',
                inputPaddingTop: 3,
                inputWidth: 15,
                labelWidth: 40
            }, {
                key: 'dashgap',
                text: 'Dash Gap',
                x: 85,
                y: 150,
                labelWidth: 60,
                inputWidth: 25
            }, {
                key: 'dashlen',
                text: 'Dash Length',
                x: 190,
                y: 150,
                labelWidth: 70,
                inputWidth: 30
            }],
            nodeUpdateUIDefinition: [{
                key: 'id',
                text: 'Id',
                inputWidth: 60,
                x: 10,
                y: 15
            }, {
                key: DATASET,
                text: DATASET,
                inputType: 'select',
                inputWidth: 110,
                innerHTML: undefined,
                x: 170,
                y: 15
            }, {
                key: 'x',
                text: 'Value',
                x: 10,
                y: 40,
                inputWidth: 21
            }, {
                key: 'y',
                text: COMMA,
                x: 88,
                y: 40,
                inputWidth: 21,
                labelWidth: 5
            }, {
                text: '(x, y)',
                x: 125,
                y: 40,
                labelWidth: 33,
                noInput: true
            }, {
                key: 'tooltip',
                text: 'Tooltip',
                inputWidth: 105,
                x: 170,
                y: 40
            }, {
                key: LABEL,
                text: 'Label',
                inputWidth: 92,
                x: 10,
                y: 65
            }, {
                key: 'labelalign',
                text: 'Align',
                labelWidth: 70,
                inputWidth: 110,
                inputType: 'select',
                innerHTML: '<option></option><option value="top">Top</option><option value="middle">Middle</option>' +
                    '<option value="bottom">Bottom</option>',
                x: 145,
                y: 63
            }, {
                key: 'color',
                text: 'Color',
                x: 10,
                y: 90,
                inputWidth: 60
            }, {
                key: 'colorOut',
                innerHTML: '&nbsp;',
                x: 85,
                y: 90,
                inputWidth: 15,
                inputType: 'span'
            }, {
                key: 'alpha',
                text: 'Alpha',
                x: 170,
                y: 90,
                inputWidth: 20
            }, {
                key: 'draggable',
                text: 'Allow Drag',
                value: true,
                inputWidth: 20,
                x: 250,
                y: 90,
                labelWidth: 58,
                inputPaddingTop: 3,
                type: 'checkbox'
            }, {
                key: 'shape',
                text: 'Shape',
                inputType: 'select',
                inputWidth: 97,
                innerHTML: '<option value="rect">Rectangle</option><option value="circ">Circle</option><option ' +
                    'value="poly">Polygon</option>',
                x: 10,
                y: 115
            }, {
                key: 'rectHeight',
                text: 'Height',
                x: 170,
                y: 115,
                inputWidth: 20
            }, {
                key: 'rectWidth',
                text: 'Width',
                x: 255,
                y: 115,
                inputWidth: 20
            }, {
                key: 'circPolyRadius',
                text: 'Radius',
                x: 170,
                y: 115,
                inputWidth: 20
            }, {
                key: 'polySides',
                text: 'Sides',
                x: 255,
                y: 115,
                inputWidth: 20
            }, {
                key: 'link',
                text: 'Link',
                x: 10,
                y: 140,
                inputWidth: 92
            }, {
                key: 'image',
                text: 'Image',
                type: 'checkbox',
                inputPaddingTop: 4,
                inputWidth: 20,
                x: 10,
                y: 170
            }, {
                key: 'imgUrl',
                text: 'URL',
                inputWidth: 105,
                x: 170,
                y: 170
            }, {
                key: 'imgWidth',
                text: 'Width',
                inputWidth: 20,
                x: 10,
                y: 195
            }, {
                key: 'imgHeight',
                text: 'Height',
                inputWidth: 20,
                x: 82,
                y: 195
            }, {
                key: 'imgAlign',
                text: 'Align',
                inputType: 'select',
                inputWidth: 75,
                innerHTML: '<option value="top">Top</option><option value="middle">Middle</option><option ' +
                    'value="bottom">Bottom</option>',
                x: 170,
                y: 195
            }],
            showNodeUpdateUI: (function() {
                var manageShapeFields = function() {
                        var ui = this.graphics.cacheUpdateUI,
                            fields = ui.fields,
                            ele = fields.shape,
                            shapeFields = ['rectWidth', 'rectHeight', 'circPolyRadius',
                                'polySides'
                            ],
                            i = shapeFields.length,
                            key;

                        while (i--) {
                            key = shapeFields[i];
                            if (/rect|poly|circ/ig.test(key)) {
                                ui.labels[key].hide();
                                ui.fields[key].hide();
                            }
                            if (new RegExp(pluck(ele.val(), 'rect'), 'ig').test(key)) {
                                ui.labels[key].show();
                                ui.fields[key].show();
                            }
                        }
                    },
                    showGivenColor = function() {
                        var ui = this.graphics.cacheUpdateUI,
                            fields = ui.fields,
                            color = getValidColor(fields.color.val());

                        color && fields.colorOut.css({
                            background: parseColor(color)
                        });
                    },
                    manageImageFields = function(chart, animate) {
                        var ui = this.graphics.cacheUpdateUI,
                            fields = ui.fields,
                            ele = fields.image,
                            chartHeight = chart.config.height,
                            padding = 5,
                            isChecked = ele.val(),
                            animation = animate ? 300 : 0,
                            imgKey = ['imgWidth', 'imgHeight', 'imgAlign', 'imgUrl'],
                            dialogHeight,
                            i,
                            key;

                        dialogHeight = isChecked ? 250 : 215;

                        ui.ok.hide();
                        ui.cancel.hide();
                        ui.remove.hide();
                        ui.error.hide();
                        i = imgKey.length;
                        while (!isChecked && i--) {
                            key = imgKey[i];
                            ui.labels[key].hide();
                            ui.fields[key].hide();
                        }

                        lib.danimate.animate(ui.dialog.element, {
                            top: (chartHeight - dialogHeight) / 2,
                            height: dialogHeight
                        }, animation, 'linear', function() {
                            i = imgKey.length;
                            while (i-- && isChecked) {
                                key = imgKey[i];
                                ui.labels[key].show();
                                ui.fields[key].show();
                            }
                            ui.ok.attr({
                                y: dialogHeight - 23 - padding
                            }).show();
                            ui.cancel.attr({
                                y: dialogHeight - 23 - padding
                            }).show();
                            ui.remove.attr({
                                y: dialogHeight - 23 - padding
                            });
                            ui.error.attr({
                                y: dialogHeight - 23 - padding + 4
                            }).show();
                            if (ui.edit) {
                                ui.remove.show();
                            } else {
                                ui.remove.hide();
                            }
                        });

                    };

                return function(chart, config, edit) {
                    var manager = this,
                        graphics = manager.graphics,
                        ui = graphics.cacheUpdateUI,
                        nodes = manager.nodes,
                        conf = chart.config,
                        animation = conf.animation,
                        inCanvasStyle = conf.style.inCanvasStyle || {},
                        paper = chart.components.paper,
                        borderStyle = '1px solid #cccccc',
                        inputStyle = {
                            width: 80 + PX,
                            border: borderStyle,
                            fontSize: 10 + PX,
                            lineHeight: 15 + PX,
                            padding: 2 + PX,
                            fontFamily: inCanvasStyle.fontFamily
                        },
                        labelStyle = {
                            textAlign: 'right'
                        },
                        fields = ui && ui.fields,
                        labels = ui && ui.labels,
                        dialog,
                        node,
                        index,
                        onSubmit = function() {
                            var fields = ui && ui.fields,
                                edit = ui.edit,
                                chart = manager.chart,
                                components = chart.components,
                                xMin,
                                yMin,
                                datasets,
                                sLn,
                                idFound,
                                id,
                                submitObj,
                                shapeType;

                            xMin = components.xAxis[0].config.axisRange.min;
                            yMin = components.yAxis[0].config.axisRange.min;
                            datasets = manager.datasets;
                            sLn = datasets.length;

                            if (fields) {
                                switch (fields.shape.val()) {
                                    case 'circ':
                                        shapeType = CIRCLE;
                                        break;
                                    case 'poly':
                                        shapeType = POLYGON;
                                        break;
                                    default:
                                        shapeType = RECTANGLE;
                                        break;
                                }

                                submitObj = {
                                    x: getFirstValue(fields.x.val(), xMin),
                                    y: getFirstValue(fields.y.val(), yMin),
                                    id: id = fields.id.val(),
                                    datasetId: fields.dataset.val(),
                                    name: fields.label.val(),
                                    tooltext: fields.tooltip.val(),
                                    color: fields.color.val(),
                                    alpha: fields.alpha.val(),
                                    labelalign: fields.labelalign.val(),
                                    allowdrag: fields.draggable.val(),
                                    shape: shapeType,
                                    width: fields.rectWidth.val(),
                                    height: fields.rectHeight.val(),
                                    radius: fields.circPolyRadius.val(),
                                    numsides: fields.polySides.val(),
                                    imagenode: fields.image.val(),
                                    imagewidth: fields.imgWidth.val(),
                                    imageheight: fields.imgHeight.val(),
                                    imagealign: fields.imgAlign.val(),
                                    imageurl: fields.imgUrl.val(),
                                    link: fields.link.val()
                                };

                                // Check if node already exists
                                if (nodes[submitObj.id]) {
                                    idFound = true;
                                }

                                // If node already exists then we do not add a node and show an error
                                if (!idFound || edit !== undefined) {
                                    node = nodes[submitObj.id] || {};
                                    id = submitObj.datasetId;
                                    // Dont add nodes when dataset id is not given
                                    if (id !== BLANKSTRING || edit) {
                                        id = Number(id);
                                        index = node.config && node.config.index;
                                        edit ? chart.updateNode(submitObj) : chart.addNode(submitObj);
                                        ui.hide();
                                        ui.visible = false;
                                    }

                                    return;
                                } else {
                                    ui.error.attr({
                                        text: 'ID already exist.'
                                    });
                                    fields.label.focus();
                                }
                            }
                            // Remobe disabled from attr
                            ui.enableFields();
                        },
                        onCancel = function() {
                            // Hide the UI
                            ui.hide();
                            ui.visible = false;
                            // Remobe disabled from attr
                            ui.enableFields();
                            // Hide error msg
                            ui.error.attr({
                                text: BLANK
                            });
                            ui.visible = false;
                        },
                        onDelete = function() {
                            chart.deleteNode(ui.fields.id.val());
                            ui.hide();
                            ui.visible = false;
                        };

                    if (!ui) {
                        ui = graphics.cacheUpdateUI = this.createHtmlDialog(chart,
                            350, 215, onSubmit, onCancel, onDelete);
                        // add fields.
                        dialog = ui.dialog;
                        labels = ui.labels = {};
                        fields = ui.fields = {};
                    }
                    ui.config = config;
                    ui.edit = edit;
                    if (!ui.error) {
                        ui.error = paper.html('span', {
                            color: 'ff0000',
                            x: 30,
                            y: 228
                        }, undefined, dialog);
                    }
                    if (!ui.enableFields) {
                        ui.enableFields = function() {
                            var key;
                            for (key in config) {
                                if (config[key] && config[key].disabled && fields[key]) {
                                    fields[key].element.removeAttribute('disabled');
                                }
                            }
                        };
                    }
                    if (!ui.clearFields) {
                        ui.clearFields = function() {
                            var key,
                                fields = ui.fields;
                            for (key in fields) {
                                if (!fields[key].element.disabled) {
                                    fields[key].element.value = BLANKSTRING;
                                }
                            }
                        };
                    }

                    each(this.nodeUpdateUIDefinition, function(def) {
                        var field,
                            key = def.key,
                            attrs = {},
                            confObj = config[key] || {},
                            innerHTML,
                            value;

                        !labels[key] && (labels[key] = paper.html(LABEL, {
                            x: def.x,
                            y: def.y,
                            width: def.labelWidth || 45,
                            text: def.text
                        }, labelStyle, dialog));


                        // No need to proceed of this label has no input box
                        // associated with itself.
                        if (def.noInput) {
                            return;
                        }

                        field = fields[key];

                        if (!field) {
                            inputStyle.border = def.type == 'checkbox' ? BLANK : borderStyle;
                            field = fields[key] =
                                paper.html(def.inputType || 'input', {
                                    x: def.labelWidth && (def.labelWidth + 5) || 50,
                                    y: -2 + (def.inputPaddingTop || 0),
                                    width: def.inputWidth || 50,
                                    name: key || BLANKSTRING
                                }, inputStyle);

                            if (def.inputType !== 'select') {
                                field.attr({
                                    type: def.type || 'text'
                                }).on('keyup', ui.handleKeyPress);
                            }
                            field.add(labels[key]);
                        }


                        if (defined(innerHTML = getFirstValue(confObj.innerHTML, def.innerHTML))) {
                            attrs.innerHTML = innerHTML;
                        }
                        if (confObj.disabled) {
                            attrs.disabled = 'disabled';
                        } else {

                            field.element && (field.element.disabled = false);
                        }
                        field.attr(attrs);
                        if (defined(value = getFirstValue(confObj.value, def.value))) {
                            field.val(value);
                        }

                        key == 'shape' && field.on('change', function() {
                            manageShapeFields.call(manager, chart);
                        });
                        key == 'image' && field.on('click', function() {
                            manageImageFields.call(manager, chart, true);
                        });
                        key == 'color' && field.on('keyup', function() {
                            showGivenColor.call(manager, chart);
                        });
                    });

                    showGivenColor.call(this, chart);
                    manageImageFields.call(this, chart);
                    manageShapeFields.call(this, chart);
                    if (animation) {
                        ui.fadeIn('fast');
                    } else {
                        ui.show();
                    }
                    ui.visible = true;
                    ui.fields[edit ? LABEL : 'id'].focus();
                };
            })(),
            getDataLimits: function() {
                var manager = this,
                    datasets = manager.datasets,
                    i,
                    yMin = +Infinity,
                    yMax = -Infinity,
                    xMax = -Infinity,
                    xMin = +Infinity,
                    conf;
                for (i = 0; i < datasets.length; i++) {
                    conf = datasets[i].dataset.config;
                    yMax = mathMax(yMax, conf.yMax);
                    yMin = mathMin(yMin, conf.yMin);
                    xMax = mathMax(xMax, conf.xMax);
                    xMin = mathMin(xMin, conf.xMin);
                }
                return {
                    max: yMax,
                    min: yMin,
                    xMax: xMax,
                    xMin: xMin
                };
            },
            removeNodeDataset: function(index) {
                var manager = this,
                    datasets = manager.datasets;
                datasets.splice(index);
            },
            removeConnectorSet: function(index) {
                var manager = this,
                    datasets = manager.connectorSet;
                datasets.splice(index);
            },
            removeLabelSet: function(index) {
                var manager = this,
                    datasets = manager.labelSet;

                datasets.splice(index);
            },
            _clearConnectors: function() {
                var manager = this,
                    nodes = manager.nodes,
                    id,
                    startConnectors,
                    endConnectors,
                    graphics,
                    j,
                    node;
                // Deleting all connectors from nodes object
                for (id in nodes) {
                    node = nodes[id];
                    if (node) {
                        startConnectors = node.config.startConnectors || {};
                        endConnectors = node.config.endConnectors || {};
                        for (j in startConnectors) {
                            graphics = {
                                graphics: startConnectors[j].graphics || {}
                            };
                            componentDispose.call(graphics);
                        }
                        for (j in endConnectors) {
                            graphics = {
                                graphics: endConnectors[j].graphics || {}
                            };
                            componentDispose.call(graphics);
                        }
                    }
                }
                // Clearing nodes object
                manager.nodes = {};
            }
        }]);
    }
]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-group-dragcolumn',
    function () {
        var global = this,
            lib = global.hcLib,
            extend2 = lib.extend2,
            COMPONENT = 'component',
            DATASET_GROUP = 'datasetGroup',
            math = Math,
            mathCeil = math.ceil,
            preDefStr = lib.preDefStr,
            COLUMN = preDefStr.column;

        FusionCharts.register(COMPONENT, [DATASET_GROUP, 'DragColumn', {
            getJSONData: function () {
                var manager = this,
                    chart = manager.chart,
                    datasets = chart.components.dataset,
                    rawDatasets = chart.jsonData && chart.jsonData.dataset,
                    jsonData = [],
                    dataset,
                    datasetObj,
                    rawDataset,
                    i,
                    len = datasets.length;
                for (i = 0; i < len; i++) {
                    dataset = datasets[i];
                    rawDataset = extend2({}, rawDatasets[i]);
                    delete rawDataset.data;
                    datasetObj = dataset.getJSONData();
                    jsonData.push(extend2(rawDataset, datasetObj));
                }
                return jsonData;
            },
            //helper function of skipOverlapPlot()
            _decidePlotableData : function (data, plotsPerBin, visible, isLast) {
                var group = this,
                    stackSumValues = group.stackSumValue && group.stackSumValue[0],
                    i,
                    j,
                    k,
                    l,
                    chart = group.chart,
                    chartConfig = chart.config,
                    binSize = chartConfig.binSize,
                    lenData = data && data.length,
                    value,
                    dataConfig,
                    dataGraphics,
                    element,
                    limit = lenData - plotsPerBin,
                    count,
                    isDataRestored = chartConfig.isDataRestored,
                    drawLabelFlag,
                    labelSkipMatrics = mathCeil((1 / binSize) * chartConfig.labelBinSize),
                    lastPlotIndexPositive,
                    lastPlotIndexNegative,
                    positvePlot,
                    negativePlot;


                for (k = 0, i = 0, j = 0, count = 0; k < limit && visible; k += plotsPerBin, i++, j++) {
                    drawLabelFlag = count % labelSkipMatrics;
                    count++;
                    positvePlot = negativePlot = undefined;
                    for(l = (k + plotsPerBin); l >= k + 1; l--) {
                        dataConfig = data[l].config;
                        dataGraphics = data[l].graphics;
                        element = dataGraphics && dataGraphics.element;
                        value = (stackSumValues && stackSumValues[l]) || dataConfig.setValue;

                        isDataRestored && (delete data[l].dragged);

                        if (!data[l].dragged) {
                            dataConfig.labelSkip = true;
                            dataConfig.isSkipped = true;
                        }

                        if(value >= 0) {
                            if(!positvePlot) {
                                positvePlot = value;
                                (drawLabelFlag === 0) && (delete dataConfig.labelSkip);
                                lastPlotIndexPositive = l;
                                delete dataConfig.isSkipped;
                            }
                            if(positvePlot < value) {
                                positvePlot = value;
                                lastPlotIndexPositive = l;
                                delete dataConfig.isSkipped;
                            }
                        } else {
                            if(!negativePlot) {
                                negativePlot = value;
                                (drawLabelFlag === 0) && (delete dataConfig.labelSkip);
                                lastPlotIndexNegative = l;
                                delete dataConfig.isSkipped;
                            }
                            if(negativePlot > value) {
                                negativePlot = value;
                                lastPlotIndexNegative = l;
                                delete dataConfig.isSkipped;
                            }
                        }
                    }

                    if (drawLabelFlag === 0) {
                        data[lastPlotIndexPositive] && (delete data[lastPlotIndexPositive].config.labelSkip);
                        data[lastPlotIndexNegative] && (delete data[lastPlotIndexNegative].config.labelSkip);
                    }
                }
                isLast && (delete group.lastPlot);
            }
        }, COLUMN]);
    }
]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-group-dragarea',
    function () {
        var global = this,
            lib = global.hcLib,
            extend2 = lib.extend2,
            math = Math,
            mathCeil = math.ceil,
            COMPONENT = 'component',
            DATASET_GROUP = 'datasetGroup';

        FusionCharts.register(COMPONENT, [DATASET_GROUP, 'DragArea', {
            getJSONData: function () {
                var manager = this,
                    chart = manager.chart,
                    datasets = chart.components.dataset,
                    rawDatasets = chart.jsonData && chart.jsonData.dataset,
                    jsonData = [],
                    dataset,
                    datasetObj,
                    rawDataset,
                    i,
                    len = datasets.length;
                for (i = 0; i < len; i++) {
                    dataset = datasets[i];
                    rawDataset = extend2({}, rawDatasets[i]);
                    delete rawDataset.data;
                    datasetObj = dataset.getJSONData();
                    jsonData.push(extend2(rawDataset, datasetObj));
                }
                return jsonData;
            },
            //helper function of skipOverlapPlot()
            _decidePlotableData : function (data, plotsPerBin, visible) {
                var group = this,
                    chart = group.chart,
                    chartConfig = chart.config,
                    isDataRestored = chartConfig.isDataRestored,
                    binSize = chartConfig.binSize,
                    i,
                    j,
                    k,
                    l,
                    lenData = data && data.length,
                    setValue,
                    dataConfig,
                    maxValueIndex,
                    minValueIndex,
                    maxValue,
                    minValue,
                    limit = lenData - plotsPerBin,
                    count,
                    drawLabelFlag,
                    labelSkipMatrics = mathCeil((1 / binSize) * chartConfig.labelBinSize);

                for (k = 0, i = 0, j = 0, count = 0; k < limit && visible; k += plotsPerBin, i++, j++) {
                    drawLabelFlag = count % labelSkipMatrics;
                    count++;
                    maxValueIndex = minValueIndex = maxValue = minValue = undefined;
                    for(l = (k + plotsPerBin); l >= k + 1; l--) {
                        dataConfig = data[l].config;
                        setValue = dataConfig.setValue;

                        isDataRestored && (delete data[l].dragged);

                        if (!data[l].dragged) {
                            dataConfig.labelSkip = true;
                            dataConfig.isSkipped = true;
                        }
                        if (!maxValue) {
                            maxValueIndex = l;
                            maxValue = setValue;
                        } else {
                            if (maxValue < setValue) {
                                maxValueIndex = l;
                                maxValue = setValue;
                            }
                        }

                        if (!minValue) {
                            minValueIndex = l;
                            minValue = setValue;
                        } else {
                            if (minValue > setValue) {
                                minValueIndex = l;
                                minValue = setValue;
                            }
                        }

                    }
                    delete data[minValueIndex].config.isSkipped;
                    delete data[maxValueIndex].config.isSkipped;
                    if (drawLabelFlag === 0) {
                        delete data[minValueIndex].config.labelSkip;
                        delete data[maxValueIndex].config.labelSkip;
                    }
                }
            }
        }, 'area']);
    }
]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-group-dragline',
    function () {
        var COMPONENT = 'component',
            DATASET_GROUP = 'datasetGroup';

        FusionCharts.register(COMPONENT, [DATASET_GROUP, 'DragLine', {

            //helper function of skipOverlapPlot()
            _decidePlotableData :
                FusionCharts.get(COMPONENT, [DATASET_GROUP, 'DragArea']).prototype._decidePlotableData
        }, 'line']);
    }
]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-group-boxandwhisker2d',
    function () {
        var global = this,
            lib = global.hcLib,
            extend2 = lib.extend2,
            COMPONENT = 'component',
            DATASET_GROUP = 'datasetGroup',
            preDefStr = lib.preDefStr,
            configStr = preDefStr.configStr,
            animationObjStr = preDefStr.animationObjStr,
            COLUMN = preDefStr.column;

        FusionCharts.register(COMPONENT, [DATASET_GROUP, 'boxandwhisker2d', {
            draw : function() {
                var group = this,
                    positionStackArr = group.positionStackArr,
                    length = positionStackArr.length,
                    i,
                    j,
                    subDataset,
                    subDatasetLen,
                    dataSet,
                    chart = group.chart,
                    elements = chart.components.canvas.config.clip,
                    parentContainer = chart.graphics.datasetGroup,
                    graphics = chart.graphics,
                    clipCanvas = elements['clip-canvas'].slice(0),
                    clipCanvasInit = extend2([], chart.components.canvas.config.clip['clip-canvas-init']),
                    dataLabelsLayer =  graphics.datalabelsGroup,

                    animationObj = chart.get(configStr, animationObjStr),
                    animType = animationObj.animType,
                    animObj = animationObj.animObj,
                    dummyObj = animationObj.dummyObj,
                    animationDuration = animationObj.duration;

                if (chart.fireInitialAnimation) {
                    parentContainer.attr({
                        'clip-rect': clipCanvasInit
                    });

                    dataLabelsLayer.attr({
                        'clip-rect': clipCanvasInit
                    });

                }
                chart.fireInitialAnimation = false;

                parentContainer.animateWith(dummyObj, animObj, {
                    'clip-rect': clipCanvas
                }, animationDuration, animType);

                dataLabelsLayer.animateWith(dummyObj, animObj, {
                    'clip-rect': clipCanvas
                }, animationDuration, animType);

                group.preDrawCalculate();
                group.drawSumValueFlag = true;
                for( i=0; i<length; i++) {
                    subDataset = positionStackArr[i];
                    subDatasetLen = subDataset.length;
                    group.manageClip = true;
                    for(j=0; j<subDatasetLen; j++) {
                        dataSet = positionStackArr[i][j].dataSet;
                        dataSet.draw();
                    }
                }
            }
        },COLUMN]);
    }
]);

FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-group-heatmap',
    function () {
        var global = this,
            lib = global.hcLib,
            COMPONENT = 'component',
            DATASET_GROUP = 'datasetGroup',
            preDefStr = lib.preDefStr,
            COLUMN = preDefStr.column;

        FusionCharts.register(COMPONENT, [DATASET_GROUP, 'heatmap', {
        },COLUMN]);
    }
]);

/* jshint ignore: end */

}));
