/*! 
* DevExpress ChartJS
* Version: 13.1.8
* Build date: Oct 24, 2013
*
* Copyright (c) 2012 - 2013 Developer Express Inc. ALL RIGHTS RESERVED
* EULA: http://chartjs.devexpress.com/EULA
*/

"use strict";

if (!window.DevExpress) {
    /*! Module core, file devexpress.js */
    (function($, global, undefined) {
        (function checkjQueryVersion(version) {
            version = version.split(".");
            if (version[0] < 1 || version[0] === 1 && version[1] < 8)
                throw Error("Your version of jQuery is too old. Please upgrade jQuery to 1.8.0 or later.");
        })($.fn.jquery);
        var Class = function() {
                var wrapOverridden = function(baseProto, methodName, method) {
                        return function() {
                                var prevCallBase = this.callBase;
                                this.callBase = baseProto[methodName];
                                try {
                                    return method.apply(this, arguments)
                                }
                                finally {
                                    this.callBase = prevCallBase
                                }
                            }
                    };
                var clonePrototype = function(obj) {
                        var func = function(){};
                        func.prototype = obj.prototype;
                        return new func
                    };
                var classImpl = function(){};
                var redefine = function(members) {
                        var self = this;
                        if (!members)
                            return self;
                        var memberNames = $.map(members, function(_, k) {
                                return k
                            });
                        $.each(["toString", "toLocaleString", "valueOf"], function() {
                            if (members[this])
                                memberNames.push(this)
                        });
                        $.each(memberNames, function() {
                            var overridden = $.isFunction(self.prototype[this]) && $.isFunction(members[this]);
                            self.prototype[this] = overridden ? wrapOverridden(self.parent.prototype, this, members[this]) : members[this]
                        });
                        return self
                    };
                var include = function() {
                        var classObj = this;
                        $.each(arguments, function() {
                            if (this.ctor)
                                classObj._includedCtors.push(this.ctor);
                            for (var name in this) {
                                if (name === "ctor")
                                    continue;
                                if (name in classObj.prototype)
                                    throw Error("Member name collision: " + name);
                                classObj.prototype[name] = this[name]
                            }
                        });
                        return classObj
                    };
                var subclassOf = function(parentClass) {
                        if (this.parent === parentClass)
                            return true;
                        if (!this.parent || !this.parent.subclassOf)
                            return false;
                        return this.parent.subclassOf(parentClass)
                    };
                classImpl.inherit = function(members) {
                    var inheritor = function() {
                            if (!this || this.constructor !== inheritor)
                                throw Error("A class must be instantiated using the 'new' keyword");
                            var instance = this,
                                ctor = instance.ctor;
                            if (ctor)
                                ctor.apply(instance, arguments);
                            $.each(instance.constructor._includedCtors, function() {
                                this.call(instance)
                            })
                        };
                    inheritor.prototype = clonePrototype(this);
                    inheritor.inherit = this.inherit;
                    inheritor.redefine = redefine;
                    inheritor.include = include;
                    inheritor.subclassOf = subclassOf;
                    inheritor.parent = this;
                    inheritor._includedCtors = this._includedCtors ? this._includedCtors.slice(0) : [];
                    inheritor.prototype.constructor = inheritor;
                    inheritor.redefine(members);
                    return inheritor
                };
                return classImpl
            }();
        var enqueue = function() {
                var tasks = [],
                    busy = false;
                var exec = function() {
                        while (tasks.length) {
                            var task = tasks.shift(),
                                result = task();
                            if (result === undefined)
                                continue;
                            if (result.then) {
                                busy = true;
                                $.when(result).always(exec);
                                return
                            }
                            throw Error();
                        }
                        busy = false
                    };
                return function(task) {
                        tasks.push(task);
                        if (!busy)
                            exec()
                    }
            }();
        var parseUrl = function() {
                var a = document.createElement("a"),
                    props = ["protocol", "hostname", "port", "pathname", "search", "hash"];
                var normalizePath = function(value) {
                        if (value.charAt(0) !== "/")
                            value = "/" + value;
                        return value
                    };
                return function(url) {
                        a.href = url;
                        var result = {};
                        $.each(props, function() {
                            result[this] = a[this]
                        });
                        result.pathname = normalizePath(result.pathname);
                        return result
                    }
            }();
        global.DevExpress = global.DevExpress || {};
        var enqueueAsync = function(task) {
                var deferred = $.Deferred();
                setTimeout(function() {
                    deferred.resolve(task())
                }, 60);
                return deferred
            };
        var backButtonCallback = function() {
                var callbacks = [];
                return {
                        add: function(callback) {
                            callbacks.push(callback)
                        },
                        remove: function(callback) {
                            var indexOfCallback = $.inArray(callback, callbacks);
                            if (indexOfCallback !== -1)
                                callbacks.splice(indexOfCallback, 1)
                        },
                        fire: function() {
                            var callback = callbacks.pop(),
                                result = !!callback;
                            if (result)
                                callback();
                            return result
                        }
                    }
            }();
        var overlayTargetContainer = function() {
                var defaultTargetContainer = null;
                return function(targetContainer) {
                        if (arguments.length)
                            defaultTargetContainer = targetContainer;
                        return defaultTargetContainer
                    }
            }();
        $.extend(global.DevExpress, {
            abstract: function() {
                throw Error("Not implemented");
            },
            Class: Class,
            enqueue: enqueue,
            enqueueAsync: enqueueAsync,
            parseUrl: parseUrl,
            backButtonCallback: backButtonCallback,
            overlayTargetContainer: overlayTargetContainer
        })
    })(jQuery, this);
    /*! Module core, file inflector.js */
    (function($, DX, undefined) {
        var _normalize = function(text) {
                if (text === undefined || text === null)
                    return "";
                return String(text)
            };
        var _ucfirst = function(text) {
                return _normalize(text).charAt(0).toUpperCase() + text.substr(1)
            };
        var _chop = function(text) {
                return _normalize(text).replace(/([a-z\d])([A-Z])/g, "$1 $2").split(/[\s_-]+/)
            };
        var dasherize = function(text) {
                return $.map(_chop(text), function(p) {
                        return p.toLowerCase()
                    }).join("-")
            };
        var underscore = function(text) {
                return dasherize(text).replace(/-/g, "_")
            };
        var camelize = function(text, upperFirst) {
                return $.map(_chop(text), function(p, i) {
                        p = p.toLowerCase();
                        if (upperFirst || i > 0)
                            p = _ucfirst(p);
                        return p
                    }).join("")
            };
        var humanize = function(text) {
                return _ucfirst(dasherize(text).replace(/-/g, " "))
            };
        var titleize = function(text) {
                return $.map(_chop(text), function(p) {
                        return _ucfirst(p.toLowerCase())
                    }).join(" ")
            };
        DX.inflector = {
            dasherize: dasherize,
            camelize: camelize,
            humanize: humanize,
            titleize: titleize,
            underscore: underscore
        }
    })(jQuery, DevExpress);
    /*! Module core, file support.js */
    (function($, DX, window) {
        var cssPrefixes = ["", "Webkit", "Moz", "O", "ms"],
            styles = document.createElement("dx").style;
        var transitionEndEventNames = {
                WebkitTransition: 'webkitTransitionEnd',
                MozTransition: 'transitionend',
                OTransition: 'oTransitionEnd',
                msTransition: 'MsTransitionEnd',
                transition: 'transitionend'
            };
        var styleProp = function(prop) {
                prop = DX.inflector.camelize(prop, true);
                for (var i = 0, cssPrefixesCount = cssPrefixes.length; i < cssPrefixesCount; i++) {
                    var specific = cssPrefixes[i] + prop;
                    if (specific in styles)
                        return specific
                }
            };
        var supportProp = function(prop) {
                return !!styleProp(prop)
            };
        DX.support = {
            touch: "ontouchstart" in window,
            transform3d: supportProp("perspective"),
            transition: supportProp("transition"),
            transitionEndEventName: transitionEndEventNames[styleProp("transition")],
            animation: supportProp("animation"),
            winJS: "WinJS" in window,
            styleProp: styleProp,
            supportProp: supportProp
        }
    })(jQuery, DevExpress, this);
    /*! Module core, file browser.js */
    (function($, DX, global, undefined) {
        var webkitRegExp = /(webkit)[ \/]([\w.]+)/,
            operaRegExp = /(opera)(?:.*version)?[ \/]([\w.]+)/,
            ieRegExp = /(msie) ([\w.]+)/,
            mozillaRegExp = /(mozilla)(?:.*? rv:([\w.]+))?/;
        var ua = navigator.userAgent.toLowerCase();
        var browser = function() {
                var result = {},
                    matches = webkitRegExp.exec(ua) || operaRegExp.exec(ua) || ieRegExp.exec(ua) || ua.indexOf("compatible") < 0 && mozillaRegExp.exec(ua) || [],
                    browserName = matches[1],
                    browserVersion = matches[2];
                if (browserName) {
                    result[browserName] = true;
                    result.version = browserVersion
                }
                return result
            }();
        DX.browser = browser
    })(jQuery, DevExpress, this);
    /*! Module core, file position.js */
    (function($, DX, undefined) {
        var horzRe = /left|right/,
            vertRe = /top|bottom/,
            collisionRe = /fit|flip/;
        var splitPair = function(raw) {
                switch (typeof raw) {
                    case"string":
                        return raw.split(/\s+/, 2);
                    case"object":
                        return [raw.x || raw.h, raw.y || raw.v];
                    case"number":
                        return [raw];
                    default:
                        return raw
                }
            };
        var normalizeAlign = function(raw) {
                var result = {
                        h: "center",
                        v: "center"
                    };
                var pair = splitPair(raw);
                if (pair)
                    $.each(pair, function() {
                        var w = String(this).toLowerCase();
                        if (horzRe.test(w))
                            result.h = w;
                        else if (vertRe.test(w))
                            result.v = w
                    });
                return result
            };
        var normalizeOffset = function(raw) {
                var pair = splitPair(raw),
                    h = parseInt(pair && pair[0], 10),
                    v = parseInt(pair && pair[1], 10);
                if (!isFinite(h))
                    h = 0;
                if (!isFinite(v))
                    v = h;
                return {
                        h: h,
                        v: v
                    }
            };
        var normalizeCollision = function(raw) {
                var pair = splitPair(raw),
                    h = String(pair && pair[0]).toLowerCase(),
                    v = String(pair && pair[1]).toLowerCase();
                if (!collisionRe.test(h))
                    h = "none";
                if (!collisionRe.test(v))
                    v = h;
                return {
                        h: h,
                        v: v
                    }
            };
        var getAlignFactor = function(align) {
                switch (align) {
                    case"center":
                        return 0.5;
                    case"right":
                    case"bottom":
                        return 1;
                    default:
                        return 0
                }
            };
        var inverseAlign = function(align) {
                switch (align) {
                    case"left":
                        return "right";
                    case"right":
                        return "left";
                    case"top":
                        return "bottom";
                    case"bottom":
                        return "top";
                    default:
                        return align
                }
            };
        var initMyLocation = function(data) {
                data.myLocation = data.atLocation + getAlignFactor(data.atAlign) * data.atSize - getAlignFactor(data.myAlign) * data.mySize + data.offset
            };
        var decolliders = {
                fit: function(data, bounds) {
                    if (data.myLocation > bounds.max)
                        data.myLocation = bounds.max;
                    if (data.myLocation < bounds.min)
                        data.myLocation = bounds.min
                },
                flip: function(data, bounds) {
                    if (data.myAlign === "center" && data.atAlign === "center")
                        return;
                    if (data.myLocation < bounds.min || data.myLocation > bounds.max) {
                        var inverseData = $.extend({}, data, {
                                myAlign: inverseAlign(data.myAlign),
                                atAlign: inverseAlign(data.atAlign),
                                offset: -data.offset
                            });
                        initMyLocation(inverseData);
                        if (inverseData.myLocation >= bounds.min && inverseData.myLocation <= bounds.max || inverseData.myLocation > data.myLocation)
                            data.myLocation = inverseData.myLocation
                    }
                }
            };
        var scrollbarWidth;
        var position = function(what, options) {
                var $what = $(what);
                if (!options)
                    return $what.offset();
                var my = normalizeAlign(options.my),
                    at = normalizeAlign(options.at),
                    of = options.of || window,
                    offset = normalizeOffset(options.offset),
                    collision = normalizeCollision(options.collision);
                var h = {
                        mySize: $what.outerWidth(),
                        myAlign: my.h,
                        atAlign: at.h,
                        offset: offset.h,
                        collision: collision.h
                    };
                var v = {
                        mySize: $what.outerHeight(),
                        myAlign: my.v,
                        atAlign: at.v,
                        offset: offset.v,
                        collision: collision.v
                    };
                if (of.preventDefault) {
                    h.atLocation = of.pageX;
                    v.atLocation = of.pageY;
                    h.atSize = 0;
                    v.atSize = 0
                }
                else {
                    of = $(of);
                    if ($.isWindow(of[0])) {
                        h.atLocation = of.scrollLeft();
                        v.atLocation = of.scrollTop();
                        h.atSize = of.width();
                        v.atSize = of.height()
                    }
                    else if (of[0].nodeType === 9) {
                        h.atLocation = 0;
                        v.atLocation = 0;
                        h.atSize = of.width();
                        v.atSize = of.height()
                    }
                    else {
                        var o = of.offset();
                        h.atLocation = o.left;
                        v.atLocation = o.top;
                        h.atSize = of.outerWidth();
                        v.atSize = of.outerHeight()
                    }
                }
                initMyLocation(h);
                initMyLocation(v);
                var bounds = function() {
                        var win = $(window),
                            left = win.scrollLeft(),
                            top = win.scrollTop();
                        if (scrollbarWidth === undefined)
                            scrollbarWidth = calculateScrollbarWidth();
                        var hScrollbar = document.width > document.documentElement.clientWidth,
                            vScrollbar = document.height > document.documentElement.clientHeight,
                            hZoomLevel = DX.support.touch ? document.documentElement.clientWidth / (vScrollbar ? window.innerWidth - scrollbarWidth : window.innerWidth) : 1,
                            vZoomLevel = DX.support.touch ? document.documentElement.clientHeight / (hScrollbar ? window.innerHeight - scrollbarWidth : window.innerHeight) : 1;
                        return {
                                h: {
                                    min: left,
                                    max: left + win.width() / hZoomLevel - h.mySize
                                },
                                v: {
                                    min: top,
                                    max: top + win.height() / vZoomLevel - v.mySize
                                }
                            }
                    }();
                if (decolliders[h.collision])
                    decolliders[h.collision](h, bounds.h);
                if (decolliders[v.collision])
                    decolliders[v.collision](v, bounds.v);
                $what.offset({
                    left: Math.round(h.myLocation),
                    top: Math.round(v.myLocation)
                })
            };
        DX.position = position;
        var calculateScrollbarWidth = function() {
                var $scrollDiv = $("<div>").css({
                        width: 100,
                        height: 100,
                        overflow: "scroll",
                        position: "absolute",
                        top: -9999
                    }).appendTo($("body")),
                    result = $scrollDiv.get(0).offsetWidth - $scrollDiv.get(0).clientWidth;
                $scrollDiv.remove();
                return result
            }
    })(jQuery, DevExpress);
    /*! Module core, file action.js */
    (function($, DX, undefined) {
        var actionExecutors = {};
        var registerExecutor = function(name, executor) {
                if ($.isPlainObject(name)) {
                    $.each(name, registerExecutor);
                    return
                }
                actionExecutors[name] = executor
            };
        var unregisterExecutor = function(name) {
                var args = $.makeArray(arguments);
                $.each(args, function() {
                    delete actionExecutors[this]
                })
            };
        registerExecutor({
            func: {execute: function(e) {
                    if ($.isFunction(e.action)) {
                        e.result = e.action.apply(e.context, e.args);
                        e.handled = true
                    }
                }},
            url: {execute: function(e) {
                    if (typeof e.action === "string" && e.action.charAt(0) !== "#")
                        document.location = e.action
                }},
            hash: {execute: function(e) {
                    if (typeof e.action === "string" && e.action.charAt(0) === "#")
                        document.location.hash = e.action
                }}
        });
        var Action = DX.Class.inherit({
                ctor: function(action, config) {
                    config = config || {};
                    this._action = action || $.noop;
                    this._context = config.context || window;
                    this._beforeExecute = config.beforeExecute || $.noop;
                    this._afterExecute = config.afterExecute || $.noop;
                    this._component = config.component;
                    this._allowedForGesture = !!config.allowedForGesture
                },
                execute: function() {
                    var e = {
                            action: this._action,
                            args: Array.prototype.slice.call(arguments),
                            context: this._context,
                            component: this._component,
                            canceled: false,
                            handled: false,
                            allowedForGesture: this._allowedForGesture
                        };
                    if (!this._validateAction(e))
                        return;
                    this._beforeExecute.call(this._context, e);
                    if (e.canceled)
                        return;
                    var result = this._executeAction(e);
                    this._afterExecute.call(this._context, e);
                    return result
                },
                _validateAction: function(e) {
                    $.each(actionExecutors, function(index, executor) {
                        if (executor.validate)
                            executor.validate(e);
                        if (e.canceled)
                            return false
                    });
                    return !e.canceled
                },
                _executeAction: function(e) {
                    var result;
                    $.each(actionExecutors, function(index, executor) {
                        if (executor.execute)
                            executor.execute(e);
                        if (e.handled) {
                            result = e.result;
                            return false
                        }
                    });
                    return result
                }
            });
        $.extend(DX, {
            registerActionExecutor: registerExecutor,
            unregisterActionExecutor: unregisterExecutor,
            Action: Action
        });
        DX.__internals = {actionExecutors: actionExecutors}
    })(jQuery, DevExpress);
    /*! Module core, file utils.js */
    (function($, DX, undefined) {
        var PI = Math.PI,
            LN10 = Math.LN10;
        var cos = Math.cos,
            sin = Math.sin,
            abs = Math.abs,
            log = Math.log,
            floor = Math.floor,
            ceil = Math.ceil,
            max = Math.max,
            min = Math.min,
            isNaN = window.isNaN,
            Number = window.Number,
            NaN = window.NaN;
        var dateUnitIntervals = ['millisecond', 'second', 'minute', 'hour', 'day', 'week', 'month', 'quarter', 'year'];
        var isDefined = function(object) {
                return object !== null && object !== undefined
            };
        var isString = function(object) {
                return $.type(object) === 'string'
            };
        var isNumber = function(object) {
                return $.isNumeric(object)
            };
        var isObject = function(object) {
                return $.type(object) === 'object'
            };
        var isArray = function(object) {
                return $.type(object) === 'array'
            };
        var isDate = function(object) {
                return $.type(object) === 'date'
            };
        var isFunction = function(object) {
                return $.type(object) === 'function'
            };
        var toMilliseconds = function(value) {
                switch (value) {
                    case'millisecond':
                        return 1;
                    case'second':
                        return toMilliseconds('millisecond') * 1000;
                    case'minute':
                        return toMilliseconds('second') * 60;
                    case'hour':
                        return toMilliseconds('minute') * 60;
                    case'day':
                        return toMilliseconds('hour') * 24;
                    case'week':
                        return toMilliseconds('day') * 7;
                    case'month':
                        return toMilliseconds('day') * 30;
                    case'quarter':
                        return toMilliseconds('month') * 3;
                    case'year':
                        return toMilliseconds('day') * 365;
                    default:
                        return 0
                }
            };
        var convertDateUnitToMilliseconds = function(dateUnit, count) {
                return toMilliseconds(dateUnit) * count
            };
        var convertMillisecondsToDateUnits = function(value) {
                var i,
                    dateUnitCount,
                    dateUnitInterval,
                    dateUnitIntervals = ['millisecond', 'second', 'minute', 'hour', 'day', 'month', 'year'],
                    result = {};
                for (i = dateUnitIntervals.length - 1; i >= 0; i--) {
                    dateUnitInterval = dateUnitIntervals[i];
                    dateUnitCount = Math.floor(value / toMilliseconds(dateUnitInterval));
                    if (dateUnitCount > 0) {
                        result[dateUnitInterval + 's'] = dateUnitCount;
                        value -= convertDateUnitToMilliseconds(dateUnitInterval, dateUnitCount)
                    }
                }
                return result
            };
        var convertDateTickIntervalToMilliseconds = function(tickInterval) {
                var milliseconds = 0;
                if (isObject(tickInterval))
                    $.each(tickInterval, function(key, value) {
                        milliseconds += convertDateUnitToMilliseconds(key.substr(0, key.length - 1), value)
                    });
                if (isString(tickInterval))
                    milliseconds = convertDateUnitToMilliseconds(tickInterval, 1);
                return milliseconds
            };
        var getDatesDifferences = function(date1, date2) {
                var differences,
                    counter = 0;
                differences = {
                    year: date1.getFullYear() !== date2.getFullYear(),
                    month: date1.getMonth() !== date2.getMonth(),
                    day: date1.getDate() !== date2.getDate(),
                    hour: date1.getHours() !== date2.getHours(),
                    minute: date1.getMinutes() !== date2.getMinutes(),
                    second: date1.getSeconds() !== date2.getSeconds()
                };
                $.each(differences, function(key, value) {
                    if (value)
                        counter++
                });
                differences.count = counter;
                return differences
            };
        var getFraction = function(value) {
                var valueString,
                    dotIndex;
                if (isNumber(value)) {
                    valueString = value.toString();
                    dotIndex = valueString.indexOf('.');
                    if (dotIndex >= 0)
                        if (isExponential(value))
                            return valueString.substr(dotIndex + 1, valueString.indexOf('e') - dotIndex - 1);
                        else {
                            valueString = value.toFixed(20);
                            return valueString.substr(dotIndex + 1, valueString.length - dotIndex + 1)
                        }
                }
                return ''
            };
        var getSignificantDigitPosition = function(value) {
                var fraction = getFraction(value),
                    i;
                if (fraction)
                    for (i = 0; i < fraction.length; i++)
                        if (fraction.charAt(i) !== '0')
                            return i + 1;
                return 0
            };
        var addSubValues = function(value1, value2, isSub) {
                return value1 + (isSub ? -1 : 1) * value2
            };
        var isExponential = function(value) {
                return isNumber(value) && value.toString().indexOf('e') !== -1
            };
        var addInterval = function(value, interval, isNegative) {
                var result = null,
                    intervalObject;
                if (isDate(value)) {
                    intervalObject = isString(interval) ? getDateIntervalByString(interval.toLowerCase()) : interval;
                    result = new Date(value.getTime());
                    if (intervalObject.years)
                        result.setFullYear(addSubValues(result.getFullYear(), intervalObject.years, isNegative));
                    if (intervalObject.quarters)
                        result.setMonth(addSubValues(result.getMonth(), 3 * intervalObject.quarters, isNegative));
                    if (intervalObject.months)
                        result.setMonth(addSubValues(result.getMonth(), intervalObject.months, isNegative));
                    if (intervalObject.weeks)
                        result.setDate(addSubValues(result.getDate(), 7 * intervalObject.weeks, isNegative));
                    if (intervalObject.days)
                        result.setDate(addSubValues(result.getDate(), intervalObject.days, isNegative));
                    if (intervalObject.hours)
                        result.setHours(addSubValues(result.getHours(), intervalObject.hours, isNegative));
                    if (intervalObject.minutes)
                        result.setMinutes(addSubValues(result.getMinutes(), intervalObject.minutes, isNegative));
                    if (intervalObject.seconds)
                        result.setSeconds(addSubValues(result.getSeconds(), intervalObject.seconds, isNegative));
                    if (intervalObject.milliseconds)
                        result.setMilliseconds(addSubValues(value.getMilliseconds(), intervalObject.milliseconds, isNegative))
                }
                else
                    result = addSubValues(value, interval, isNegative);
                return result
            };
        var getDateUnitInterval = function(tickInterval) {
                var maxInterval = -1,
                    i;
                if (isString(tickInterval))
                    return tickInterval;
                if (isObject(tickInterval)) {
                    $.each(tickInterval, function(key, value) {
                        for (i = 0; i < dateUnitIntervals.length; i++)
                            if (value && (key === dateUnitIntervals[i] + 's' || key === dateUnitIntervals[i]) && maxInterval < i)
                                maxInterval = i
                    });
                    return dateUnitIntervals[maxInterval]
                }
                return ''
            };
        var correctDateWithUnitBeginning = function(date, dateInterval) {
                var dayMonth,
                    firstQuarterMonth,
                    dateUnitInterval = getDateUnitInterval(dateInterval);
                switch (dateUnitInterval) {
                    case'second':
                        date.setMilliseconds(0);
                        break;
                    case'minute':
                        date.setSeconds(0, 0);
                        break;
                    case'hour':
                        date.setMinutes(0, 0, 0);
                        break;
                    case'year':
                        date.setMonth(0);
                    case'month':
                        date.setDate(1);
                    case'day':
                        date.setHours(0, 0, 0, 0);
                        break;
                    case'week':
                        dayMonth = date.getDate();
                        if (date.getDay() !== 0)
                            dayMonth += 7 - date.getDay();
                        date.setDate(dayMonth);
                        date.setHours(0, 0, 0, 0);
                        break;
                    case'quarter':
                        firstQuarterMonth = DX.formatHelper.getFirstQuarterMonth(date.getMonth());
                        if (date.getMonth() !== firstQuarterMonth)
                            date.setMonth(firstQuarterMonth);
                        date.setDate(1);
                        date.setHours(0, 0, 0, 0);
                        break
                }
            };
        var roundValue = function(value, precision) {
                if (isNumber(value))
                    if (isExponential(value))
                        return Number(value.toExponential(precision));
                    else
                        return Number(value.toFixed(precision))
            };
        var getPrecision = function(value) {
                var stringFraction,
                    stringValue = value.toString(),
                    pointIndex = stringValue.indexOf('.');
                if (pointIndex !== -1) {
                    stringFraction = stringValue.substring(pointIndex + 1);
                    return stringFraction.length
                }
                return 0
            };
        var applyPrecisionByMinDelta = function(min, delta, value) {
                var minPrecision = getPrecision(min),
                    deltaPrecision = getPrecision(delta);
                return roundValue(value, minPrecision < deltaPrecision ? deltaPrecision : minPrecision)
            };
        var adjustValue = function(value) {
                var fraction = getFraction(value),
                    nextValue,
                    i;
                if (fraction)
                    for (i = 1; i <= fraction.length; i++) {
                        nextValue = roundValue(value, i);
                        if (nextValue !== 0 && fraction[i - 2] && fraction[i - 1] && fraction[i - 2] === fraction[i - 1])
                            return nextValue
                    }
                return value
            };
        var getDateIntervalByString = function(intervalString) {
                var result = {};
                switch (intervalString) {
                    case'year':
                        result.years = 1;
                        break;
                    case'month':
                        result.months = 1;
                        break;
                    case'quarter':
                        result.months = 3;
                        break;
                    case'week':
                        result.days = 7;
                        break;
                    case'day':
                        result.days = 1;
                        break;
                    case'hour':
                        result.hours = 1;
                        break;
                    case'minute':
                        result.minutes = 1;
                        break;
                    case'second':
                        result.seconds = 1;
                        break;
                    case'millisecond':
                        result.milliseconds = 1;
                        break
                }
                return result
            };
        var normalizeAngle = function(angle) {
                return (angle % 360 + 360) % 360
            };
        var convertAngleToRendererSpace = function(angle) {
                return 90 - angle
            };
        var degreesToRadians = function(value) {
                return PI * value / 180
            };
        var getCosAndSin = function(angle) {
                var angleInRadians = degreesToRadians(angle);
                return {
                        cos: cos(angleInRadians),
                        sin: sin(angleInRadians)
                    }
            };
        var DECIMAL_ORDER_THRESHOLD = 1E-14;
        var getDecimalOrder = function(number) {
                var n = abs(number),
                    cn;
                if (!isNaN(n)) {
                    if (n > 0) {
                        n = log(n) / LN10;
                        cn = ceil(n);
                        return cn - n < DECIMAL_ORDER_THRESHOLD ? cn : floor(n)
                    }
                    return 0
                }
                return NaN
            };
        var getAppropriateFormat = function(start, end, count) {
                var order = max(getDecimalOrder(start), getDecimalOrder(end)),
                    precision = -getDecimalOrder(abs(end - start) / count),
                    format;
                if (!isNaN(order) && !isNaN(precision)) {
                    if (abs(order) <= 4) {
                        format = 'fixedPoint';
                        precision < 0 && (precision = 0);
                        precision > 4 && (precision = 4)
                    }
                    else {
                        format = 'exponential';
                        precision += order - 1;
                        precision > 3 && (precision = 3)
                    }
                    return {
                            format: format,
                            precision: precision
                        }
                }
                return null
            };
        var createResizeHandler = function(callback) {
                var $window = $(window),
                    timeout;
                var debug_callback = arguments[1];
                var handler = function() {
                        var width = $window.width(),
                            height = $window.height();
                        clearTimeout(timeout);
                        timeout = setTimeout(function() {
                            $window.width() === width && $window.height() === height && callback();
                            debug_callback && debug_callback()
                        }, 100)
                    };
                handler.stop = function() {
                    clearTimeout(timeout);
                    return this
                };
                return handler
            };
        var logger = function() {
                var info = function() {
                        if (window.console && arguments[0])
                            console.info(arguments[0])
                    };
                var warn = function() {
                        if (window.console && arguments[0])
                            console.warn(arguments[0])
                    };
                var error = function() {
                        if (window.console && arguments[0])
                            console.error(arguments[0])
                    };
                return {
                        info: info,
                        warn: warn,
                        error: error
                    }
            }();
        var debug = function() {
                function assert(condition, message) {
                    if (!condition)
                        throw new Error(message);
                }
                function assertParam(parameter, message) {
                    assert(parameter !== null && parameter !== undefined, message)
                }
                return {
                        assert: assert,
                        assertParam: assertParam
                    }
            }();
        var windowResizeCallbacks = function() {
                var prevSize,
                    callbacks = $.Callbacks(),
                    jqWindow = $(window);
                var formatSize = function() {
                        return [jqWindow.width(), jqWindow.height()].join()
                    };
                var handleResize = function() {
                        var now = formatSize();
                        if (now === prevSize)
                            return;
                        prevSize = now;
                        callbacks.fire()
                    };
                jqWindow.on("resize", handleResize);
                prevSize = formatSize();
                return callbacks
            }();
        var createMarkupFromString = function(str) {
                var tempElement = $("<div />");
                if (window.WinJS)
                    WinJS.Utilities.setInnerHTMLUnsafe(tempElement.get(0), str);
                else
                    tempElement.append(str);
                return tempElement.contents()
            };
        var numClipRect = 1;
        var numPattern = 1;
        var getNextClipId = function() {
                return 'DevExpress_' + numClipRect++
            };
        var getNextPatternId = function() {
                return 'DevExpressPattern_' + numPattern++
            };
        var extendFromDataAttributes = function(target, $el, overrideExistingValues) {
                target = target || {};
                var source = {};
                var prefix = "data-dx-";
                var attributes = $el.get(0).attributes;
                for (var i = 0; i < attributes.length; i++) {
                    var name = attributes[i].name;
                    if (name.indexOf(prefix) === 0) {
                        var propertyName = DX.inflector.camelize(name.substr(prefix.length));
                        source[propertyName] = attributes[i].value
                    }
                }
                return extendFromObject(target, source, overrideExistingValues)
            };
        var extendFromObject = function(target, source, overrideExistingValues) {
                target = target || {};
                for (var prop in source)
                    if (source.hasOwnProperty(prop)) {
                        var value = source[prop];
                        if (!(prop in target) || overrideExistingValues)
                            target[prop] = value
                    }
                return target
            };
        var subscribeEventToDocument = function(event, handler, data) {
                var currentWindow = window;
                $(document).on(event, data, handler)
            };
        var unsubscribeEventFromDocument = function(event) {
                var currentWindow = window;
                $(document).off(event)
            };
        function Clone(){}
        var clone = function(obj) {
                Clone.prototype = obj;
                return new Clone
            };
        var executeAsync = function(action, context) {
                var deferred = $.Deferred(),
                    normalizedContext = context || this;
                setTimeout(function() {
                    var result = action.call(normalizedContext);
                    if (result && result.done && $.isFunction(result.done))
                        result.done(function() {
                            deferred.resolveWith(normalizedContext)
                        });
                    else
                        deferred.resolveWith(normalizedContext)
                }, 0);
                return deferred.promise()
            };
        DX.utils = {
            dateUnitIntervals: dateUnitIntervals,
            isDefined: isDefined,
            isString: isString,
            isNumber: isNumber,
            isObject: isObject,
            isArray: isArray,
            isDate: isDate,
            isFunction: isFunction,
            normalizeAngle: normalizeAngle,
            convertAngleToRendererSpace: convertAngleToRendererSpace,
            degreesToRadians: degreesToRadians,
            getCosAndSin: getCosAndSin,
            getDecimalOrder: getDecimalOrder,
            getAppropriateFormat: getAppropriateFormat,
            getFraction: getFraction,
            adjustValue: adjustValue,
            convertMillisecondsToDateUnits: convertMillisecondsToDateUnits,
            convertDateTickIntervalToMilliseconds: convertDateTickIntervalToMilliseconds,
            convertDateUnitToMilliseconds: convertDateUnitToMilliseconds,
            getDateUnitInterval: getDateUnitInterval,
            getDatesDifferences: getDatesDifferences,
            correctDateWithUnitBeginning: correctDateWithUnitBeginning,
            roundValue: roundValue,
            isExponential: isExponential,
            applyPrecisionByMinDelta: applyPrecisionByMinDelta,
            getSignificantDigitPosition: getSignificantDigitPosition,
            addInterval: addInterval,
            getDateIntervalByString: getDateIntervalByString,
            logger: logger,
            debug: debug,
            createResizeHandler: createResizeHandler,
            windowResizeCallbacks: windowResizeCallbacks,
            createMarkupFromString: createMarkupFromString,
            getNextClipId: getNextClipId,
            getNextPatternId: getNextPatternId,
            extendFromDataAttributes: extendFromDataAttributes,
            extendFromObject: extendFromObject,
            subscribeEventToDocument: subscribeEventToDocument,
            unsubscribeEventFromDocument: unsubscribeEventFromDocument,
            clone: clone,
            executeAsync: executeAsync
        }
    })(jQuery, DevExpress);
    /*! Module core, file translator.js */
    (function($, DX, undefined) {
        var support = DX.support,
            TRANSFORM_MATRIX_REGEX = /matrix(3d)?\((.+?)\)/,
            TRANSLATE_REGEX = /translate(?:3d)?\((.+?)\)/;
        var locate = function($element) {
                var result,
                    position;
                if (support.transform3d) {
                    var translate = getTranslate($element);
                    result = {
                        left: translate.x,
                        top: translate.y
                    }
                }
                else {
                    position = $element.position();
                    result = {
                        left: position.left,
                        top: position.top
                    }
                }
                return result
            };
        var move = function($element, position) {
                if (!support.transform3d) {
                    $element.css(position);
                    return
                }
                var translate = getTranslate($element),
                    left = position.left,
                    top = position.top;
                if (left !== undefined)
                    translate.x = left;
                if (top !== undefined)
                    translate.y = top;
                $element.css("transform", getTranslateCss(translate))
            };
        var getTranslate = function($element) {
                var transformValue = $element.css("transform"),
                    matrix = transformValue.match(TRANSFORM_MATRIX_REGEX),
                    is3D = matrix && matrix[1];
                if (matrix) {
                    matrix = matrix[2].split(",");
                    if (is3D === "3d")
                        matrix = matrix.slice(12, 15);
                    else {
                        matrix.push(0);
                        matrix = matrix.slice(4, 7)
                    }
                }
                else
                    matrix = [0, 0, 0];
                return {
                        x: parseFloat(matrix[0]),
                        y: parseFloat(matrix[1]),
                        z: parseFloat(matrix[2])
                    }
            };
        var parseTranslate = function(translateString) {
                var result = translateString.match(TRANSLATE_REGEX);
                if (!result || !result[1])
                    return;
                result = result[1].split(",");
                result = {
                    x: parseFloat(result[0]),
                    y: parseFloat(result[1]),
                    z: parseFloat(result[2])
                };
                return result
            };
        var getTranslateCss = function(translate) {
                return "translate3d(" + (translate.x || 0) + "px, " + (translate.y || 0) + "px, " + (translate.z || 0) + "px)"
            };
        DX.translator = {
            move: move,
            locate: locate,
            parseTranslate: parseTranslate,
            getTranslate: getTranslate,
            getTranslateCss: getTranslateCss
        }
    })(jQuery, DevExpress);
    /*! Module core, file devices.js */
    (function($, DX, undefined) {
        var knownUATable = {
                iPhone: "iPhone",
                iPhone5: "iPhone 5",
                iPad: "iPad",
                iPadMini: "iPad Mini",
                androidPhone: "Android Mobile",
                androidTablet: "Android",
                win8: "MSAppHost",
                win8Phone: "Windows Phone 8",
                msSurface: "MSIE ARM Tablet PC",
                desktop: "desktop",
                tizen: "Tizen"
            },
            deviceDefault = {
                phone: false,
                tablet: false,
                android: false,
                ios: false,
                win8: false,
                tizen: false
            },
            desktopDevice = $.extend(deviceDefault, {platform: "desktop"});
        var fromUA = function(ua) {
                var ipad = /ipad/i.test(ua),
                    iphone = /iphone|ipod/i.test(ua),
                    android = /android|silk-accelerated/i.test(ua),
                    win8Phone = /windows phone 8|wpdesktop/i.test(ua),
                    msSurface = /msie(.*)arm(.*)tablet\spc/i.test(ua),
                    win8 = /msapphost/i.test(ua) || win8Phone || msSurface,
                    tizen = /tizen/i.test(ua);
                if (!ipad && !iphone && !android && !win8 && !win8Phone && !msSurface && !tizen)
                    return $.extend({}, desktopDevice);
                var phone = iphone || (android || tizen) && /mobile/i.test(ua) || win8Phone,
                    tablet = !phone && !win8 && !win8Phone,
                    name;
                if (android)
                    name = "android";
                else if (win8)
                    name = "win8";
                else if (tizen)
                    name = "tizen";
                else
                    name = "ios";
                return {
                        phone: phone,
                        tablet: tablet,
                        android: android,
                        tizen: tizen,
                        ios: ipad || iphone,
                        win8: name === "win8",
                        platform: name
                    }
            };
        var getDevice = function(deviceName) {
                var ua;
                if (deviceName) {
                    ua = knownUATable[deviceName];
                    if (!ua)
                        throw Error("Unknown device");
                }
                else
                    ua = navigator.userAgent;
                return fromUA(ua)
            };
        var androidVersion = function(userAgent) {
                userAgent = userAgent || window.navigator.userAgent;
                var matches = /Android (\d\.\d(?:\.\d)?)/.exec(userAgent);
                if (matches && matches.length === 2)
                    return $.map(matches[1].split("."), function(versionPart) {
                            return parseInt(versionPart, 10)
                        });
                return []
            };
        function iosVersion(userAgent) {
            userAgent = userAgent || window.navigator.userAgent;
            if (/iP(hone|od|ad)/.test(userAgent)) {
                var v = userAgent.match(/OS (\d+)_(\d+)_?(\d+)?/);
                return [parseInt(v[1], 10), parseInt(v[2], 10), parseInt(v[3] || 0, 10)]
            }
        }
        var device;
        var getDeviceNameFromSessionStorage = function() {
                return window.sessionStorage && (sessionStorage.getItem("dx-force-device") || sessionStorage.getItem("dx-simulator-device"))
            };
        var getDeviceNameFromWindowScope = function() {
                var result = undefined;
                if (window.top["dx-force-device"])
                    result = window.top["dx-force-device"];
                return result
            };
        var current = function(deviceOrName) {
                if (deviceOrName)
                    if ($.isPlainObject(deviceOrName))
                        device = $.extend(deviceDefault, deviceOrName);
                    else
                        device = getDevice(deviceOrName);
                else {
                    if (!device) {
                        var deviceName = undefined;
                        try {
                            deviceName = getDeviceNameFromWindowScope()
                        }
                        catch(e) {
                            deviceName = getDeviceNameFromSessionStorage()
                        }
                        finally {
                            if (!deviceName)
                                deviceName = getDeviceNameFromSessionStorage()
                        }
                        device = getDevice(deviceName)
                    }
                    return device
                }
            };
        DX.devices = {
            androidVersion: androidVersion,
            iosVersion: iosVersion,
            current: current,
            fromUA: function() {
                return fromUA(navigator.userAgent)
            }
        }
    })(jQuery, DevExpress);
    /*! Module core, file fx.js */
    (function($, DX, undefined) {
        var translator = DX.translator,
            support = DX.support,
            transitionEndEventName = support.transitionEndEventName + ".dxFX";
        var CSS_TRANSITION_EASING_REGEX = /cubic-bezier\((\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\)/,
            SIMULATED_TRANSITIONEND_TIMEOUT_DATA_KEY = "dxSimulatedTransitionTimeoutKey",
            ANIM_DATA_KEY = "dxAnimData",
            TRANSFORM_PROP = "transform",
            FRAME_ANIMATION_STEP_TIME = 1000 / 60;
        var TransitionAnimationStrategy = {
                animate: function($element, config) {
                    var deferred = $.Deferred(),
                        transitionEndFired = $.Deferred(),
                        simulatedTransitionEndFired = $.Deferred();
                    $element.one(transitionEndEventName, function() {
                        transitionEndFired.reject()
                    });
                    $element.data(SIMULATED_TRANSITIONEND_TIMEOUT_DATA_KEY, setTimeout(function() {
                        simulatedTransitionEndFired.reject()
                    }, config.duration + config.delay));
                    $.when(transitionEndFired, simulatedTransitionEndFired).fail($.proxy(function() {
                        this._cleanup($element);
                        deferred.resolveWith($element, [config, $element])
                    }, this));
                    translator.getTranslate($element);
                    $element.css({
                        transitionProperty: "all",
                        transitionDelay: config.delay + "ms",
                        transitionDuration: config.duration + "ms",
                        transitionTimingFunction: config.easing
                    });
                    setProps($element, config.to);
                    if (!config.duration)
                        $element.trigger(transitionEndEventName);
                    return deferred.promise()
                },
                _cleanup: function($element) {
                    $element.css("transition", "none").off(transitionEndEventName);
                    var simulatedEndEventTimer = $element.data(SIMULATED_TRANSITIONEND_TIMEOUT_DATA_KEY);
                    clearTimeout(simulatedEndEventTimer);
                    $element.removeData(SIMULATED_TRANSITIONEND_TIMEOUT_DATA_KEY)
                },
                stop: function($element, jumpToEnd) {
                    var config = $element.data(ANIM_DATA_KEY);
                    if (!config)
                        return;
                    if (jumpToEnd)
                        $element.trigger(transitionEndEventName);
                    else {
                        $.each(config.to, function(key) {
                            $element.css(key, $element.css(key))
                        });
                        this._cleanup($element)
                    }
                }
            };
        var requestAnimationFrame = function() {
                return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback, element) {
                        window.setTimeout(callback, FRAME_ANIMATION_STEP_TIME)
                    }
            }();
        var FrameAnimationStrategy = {
                animate: function($element, config) {
                    var deferred = $.Deferred(),
                        animationData = $element.data(ANIM_DATA_KEY),
                        self = this;
                    if (!animationData)
                        return deferred.reject().promise();
                    $.each(config.to, function(prop) {
                        if (config.from[prop] === undefined)
                            config.from[prop] = self._normalizeValue($element.css(prop))
                    });
                    if (config.to[TRANSFORM_PROP]) {
                        config.from[TRANSFORM_PROP] = self._parseTransform(config.from[TRANSFORM_PROP]);
                        config.to[TRANSFORM_PROP] = self._parseTransform(config.to[TRANSFORM_PROP])
                    }
                    animationData.frameAnimation = {
                        to: config.to,
                        from: config.from,
                        currentValue: config.from,
                        easing: convertTransitionTimingFuncToJQueryEasing(config.easing),
                        duration: config.duration,
                        startTime: (new Date).valueOf(),
                        finish: function() {
                            this.currentValue = this.to;
                            this.draw();
                            deferred.resolve()
                        },
                        draw: function() {
                            var currentValue = $.extend({}, this.currentValue);
                            if (currentValue[TRANSFORM_PROP])
                                currentValue[TRANSFORM_PROP] = $.map(currentValue[TRANSFORM_PROP], function(value, prop) {
                                    if (prop === "translate")
                                        return translator.getTranslateCss(value);
                                    else if (prop === "scale")
                                        return "scale(" + value + ")";
                                    else if (prop.substr(0, prop.length - 1) === "rotate")
                                        return prop + "(" + value + "deg)"
                                }).join(" ");
                            $element.css(currentValue)
                        }
                    };
                    if (config.delay) {
                        animationData.frameAnimation.startTime += config.delay;
                        animationData.frameAnimation.delayTimeout = setTimeout(function() {
                            self._animationStep($element)
                        }, config.delay)
                    }
                    else
                        self._animationStep($element);
                    return deferred.promise()
                },
                _parseTransform: function(transformString) {
                    var result = {};
                    $.each(transformString.match(/(\w|\d)+\([^\)]*\)\s*/g), function(i, part) {
                        var translateData = translator.parseTranslate(part),
                            scaleData = part.match(/scale\((.+?)\)/),
                            rotateData = part.match(/(rotate.)\((.+)deg\)/);
                        if (translateData)
                            result.translate = translateData;
                        if (scaleData && scaleData[1])
                            result.scale = parseFloat(scaleData[1]);
                        if (rotateData && rotateData[1])
                            result[rotateData[1]] = parseFloat(rotateData[2])
                    });
                    return result
                },
                stop: function($element, jumpToEnd) {
                    var animationData = $element.data(ANIM_DATA_KEY),
                        frameAnimation = animationData && animationData.frameAnimation;
                    if (!frameAnimation)
                        return;
                    clearTimeout(frameAnimation.delayTimeout);
                    if (jumpToEnd)
                        frameAnimation.finish()
                },
                _animationStep: function($element) {
                    var animationData = $element.data(ANIM_DATA_KEY),
                        frameAnimation = animationData && animationData.frameAnimation;
                    if (!frameAnimation)
                        return;
                    var now = (new Date).valueOf();
                    if (now >= frameAnimation.startTime + frameAnimation.duration) {
                        frameAnimation.finish();
                        return
                    }
                    frameAnimation.currentValue = this._calcStepValue(frameAnimation, now - frameAnimation.startTime);
                    frameAnimation.draw();
                    requestAnimationFrame($.proxy(function() {
                        this._animationStep($element)
                    }, this))
                },
                _calcStepValue: function(frameAnimation, currentDuration) {
                    var calcValueRecursively = function(from, to) {
                            var result = $.isArray(to) ? [] : {};
                            var calcEasedValue = function(propName) {
                                    var x = currentDuration / frameAnimation.duration,
                                        t = currentDuration,
                                        b = 1 * from[propName],
                                        c = to[propName] - from[propName],
                                        d = frameAnimation.duration;
                                    return $.easing[frameAnimation.easing](x, t, b, c, d)
                                };
                            $.each(to, function(propName, endPropValue) {
                                if (typeof endPropValue === "string" && parseFloat(endPropValue, 10) === false)
                                    return true;
                                result[propName] = typeof endPropValue === "object" ? calcValueRecursively(from[propName], endPropValue) : calcEasedValue(propName)
                            });
                            return result
                        };
                    return calcValueRecursively(frameAnimation.from, frameAnimation.to)
                },
                _normalizeValue: function(value) {
                    var numericValue = parseFloat(value, 10);
                    if (numericValue === false)
                        return value;
                    return numericValue
                }
            };
        var animationStrategies = {
                transition: support.transition ? TransitionAnimationStrategy : FrameAnimationStrategy,
                frame: FrameAnimationStrategy
            };
        var getAnimationStrategy = function(config) {
                return animationStrategies[config && config.strategy || "transition"]
            };
        var TransitionTimingFuncMap = {
                linear: "cubic-bezier(0, 0, 1, 1)",
                ease: "cubic-bezier(0.25, 0.1, 0.25, 1)",
                "ease-in": "cubic-bezier(0.42, 0, 1, 1)",
                "ease-out": "cubic-bezier(0, 0, 0.58, 1)",
                "ease-in-out": "cubic-bezier(0.42, 0, 0.58, 1)"
            };
        var convertTransitionTimingFuncToJQueryEasing = function(cssTransitionEasing) {
                cssTransitionEasing = TransitionTimingFuncMap[cssTransitionEasing] || cssTransitionEasing;
                var bezCoeffs = cssTransitionEasing.match(CSS_TRANSITION_EASING_REGEX);
                if (!bezCoeffs)
                    return "linear";
                bezCoeffs = bezCoeffs.slice(1, 5);
                $.each(bezCoeffs, function(index, value) {
                    bezCoeffs[index] = parseFloat(value)
                });
                var easingName = "cubicbezier_" + bezCoeffs.join("_").replace(/\./g, "p");
                if (!$.isFunction($.easing[easingName])) {
                    var polynomBezier = function(x1, y1, x2, y2) {
                            var Cx = 3 * x1,
                                Bx = 3 * (x2 - x1) - Cx,
                                Ax = 1 - Cx - Bx,
                                Cy = 3 * y1,
                                By = 3 * (y2 - y1) - Cy,
                                Ay = 1 - Cy - By;
                            var bezierX = function(t) {
                                    return t * (Cx + t * (Bx + t * Ax))
                                };
                            var bezierY = function(t) {
                                    return t * (Cy + t * (By + t * Ay))
                                };
                            var findXfor = function(t) {
                                    var x = t,
                                        i = 0,
                                        z;
                                    while (i < 14) {
                                        z = bezierX(x) - t;
                                        if (Math.abs(z) < 1e-3)
                                            break;
                                        x = x - z / derivativeX(x);
                                        i++
                                    }
                                    return x
                                };
                            var derivativeX = function(t) {
                                    return Cx + t * (2 * Bx + t * 3 * Ax)
                                };
                            return function(t) {
                                    return bezierY(findXfor(t))
                                }
                        };
                    $.easing[easingName] = function(x, t, b, c, d) {
                        return c * polynomBezier(bezCoeffs[0], bezCoeffs[1], bezCoeffs[2], bezCoeffs[3])(t / d) + b
                    }
                }
                return easingName
            };
        var baseConfigValidator = function(config, animationType) {
                $.each(["from", "to"], function() {
                    if (!$.isPlainObject(config[this]))
                        throw Error("Animation with the '" + animationType + "' type requires '" + this + "' configuration as an plain object.");
                })
            };
        var CustomAnimationConfigurator = {setup: function($element, config){}};
        var SlideAnimationConfigurator = {
                validateConfig: function(config) {
                    baseConfigValidator(config, "slide")
                },
                setup: function($element, config) {
                    var animStrategy = getAnimationStrategy(config);
                    if (!support.transform3d || animStrategy !== TransitionAnimationStrategy && animStrategy !== FrameAnimationStrategy)
                        return;
                    this._setupConfig($element, config.from);
                    this._setupConfig($element, config.to)
                },
                _setupConfig: function($element, config) {
                    var translate = translator.getTranslate($element),
                        left = config.left,
                        top = config.top;
                    if (left !== undefined) {
                        translate.x = left;
                        delete config.left
                    }
                    if (top !== undefined) {
                        translate.y = top;
                        delete config.top
                    }
                    config[TRANSFORM_PROP] = translator.getTranslateCss(translate)
                }
            };
        var FadeAnimationConfigurator = {setup: function($element, config) {
                    var from = config.from,
                        fromOpacity = $.isPlainObject(from) ? $element.css("opacity") : String(from),
                        toOpacity = String(config.to);
                    config.from = {opacity: fromOpacity};
                    config.to = {opacity: toOpacity}
                }};
        var PopAnimationConfigurator = {
                validateConfig: function(config) {
                    baseConfigValidator(config, "pop")
                },
                setup: function($element, config) {
                    if (!support.transform3d)
                        return;
                    var from = config.from,
                        to = config.to,
                        fromOpacity = "opacity" in from ? from.opacity : $element.css("opacity"),
                        toOpacicy = "opacity" in to ? to.opacity : 1,
                        fromScale = "scale" in from ? from.scale : 0,
                        toScale = "scale" in to ? to.scale : 1;
                    config.from = {opacity: fromOpacity};
                    config.from[TRANSFORM_PROP] = this._getCssTransform(fromScale);
                    config.to = {opacity: toOpacicy};
                    config.to[TRANSFORM_PROP] = this._getCssTransform(toScale)
                },
                _getCssTransform: function(scale) {
                    return "scale(" + scale + ")"
                }
            };
        var animationConfigurators = {
                custom: CustomAnimationConfigurator,
                slide: SlideAnimationConfigurator,
                fade: FadeAnimationConfigurator,
                pop: PopAnimationConfigurator
            };
        var getAnimationConfigurator = function(type) {
                var result = animationConfigurators[type];
                if (!result)
                    throw Error("Unknown animation type \"" + type + "\"");
                return result
            };
        var defaultConfig = {
                type: "custom",
                from: {},
                to: {},
                duration: 400,
                complete: $.noop,
                easing: "ease",
                delay: 0
            };
        var animate = function(element, config) {
                config = $.extend(true, {}, defaultConfig, config);
                var $element = $(element),
                    configurator = getAnimationConfigurator(config.type);
                if ($.isFunction(configurator.validateConfig))
                    configurator.validateConfig(config);
                configurator.setup($element, config);
                stop($element);
                setProps($element, config.from);
                return executeAnimation($element, config).done(config.complete)
            };
        var setProps = function($element, props) {
                $.each(props, function(key, value) {
                    $element.css(key, value)
                })
            };
        var executeAnimation = function($element, config) {
                var deferred = $.Deferred();
                $element.data(ANIM_DATA_KEY, config);
                if (DX.fx.off)
                    config.duration = 0;
                getAnimationStrategy(config).animate($element, config).done(function() {
                    $element.removeData(ANIM_DATA_KEY);
                    deferred.resolveWith(this, [$element, config])
                });
                return deferred.promise()
            };
        var animating = function($element) {
                return !!$element.data(ANIM_DATA_KEY)
            };
        var stop = function(element, jumpToEnd) {
                var $element = $(element);
                getAnimationStrategy($element.data(ANIM_DATA_KEY)).stop($element, jumpToEnd);
                $element.removeData(ANIM_DATA_KEY)
            };
        DX.fx = {
            off: false,
            animationTypes: animationConfigurators,
            animate: animate,
            animating: animating,
            stop: stop
        };
        DX.fx.__internals = {convertTransitionTimingFuncToJQueryEasing: convertTransitionTimingFuncToJQueryEasing}
    })(jQuery, DevExpress);
    /*! Module core, file endpointSelector.js */
    (function($, DX, undefined) {
        var location = window.location,
            DXPROXY_HOST = "dxproxy.devexpress.com:8000",
            WIN_JS = location.protocol === "ms-appx:",
            IS_DXPROXY = location.host === DXPROXY_HOST,
            IS_LOCAL = isLocalHostName(location.hostname);
        function isLocalHostName(url) {
            return /^(localhost$|127\.)/i.test(url)
        }
        var extractProxyAppId = function() {
                return location.pathname.split("/")[1]
            };
        var formatProxyUrl = function(localUrl) {
                var urlData = DX.parseUrl(localUrl);
                if (!isLocalHostName(urlData.hostname))
                    return localUrl;
                return "http://" + DXPROXY_HOST + "/" + extractProxyAppId() + "_" + urlData.port + urlData.pathname + urlData.search
            };
        var EndpointSelector = DX.EndpointSelector = function(config) {
                this.config = config
            };
        EndpointSelector.prototype = {urlFor: function(key) {
                var bag = this.config[key];
                if (!bag)
                    throw Error("Unknown endpoint key");
                if (IS_DXPROXY)
                    return formatProxyUrl(bag.local);
                if (bag.production)
                    if (WIN_JS && !Debug.debuggerEnabled || !WIN_JS && !IS_LOCAL)
                        return bag.production;
                return bag.local
            }}
    })(jQuery, DevExpress);
    /*! Module core, file formatHelper.js */
    (function($, DX, undefined) {
        var utils = DX.utils;
        DX.NumericFormat = {
            currency: 'C',
            fixedpoint: 'N',
            exponential: '',
            percent: 'P',
            decimal: 'D'
        };
        DX.LargeNumberFormatPostfixes = {
            1: 'K',
            2: 'M',
            3: 'B',
            4: 'T'
        };
        var MAX_LARGE_NUMBER_POWER = 4,
            DECIMAL_BASE = 10;
        DX.LargeNumberFormatPowers = {
            largenumber: 'auto',
            thousands: 1,
            millions: 2,
            billions: 3,
            trillions: 4
        };
        DX.DateTimeFormat = {
            longdate: 'D',
            longtime: 'T',
            monthandday: 'M',
            monthandyear: 'Y',
            quarterandyear: 'qq',
            shortdate: 'd',
            shorttime: 't',
            millisecond: 'fff',
            second: 'T',
            minute: 't',
            hour: 't',
            day: 'dd',
            week: 'dd',
            month: 'MMMM',
            quarter: 'qq',
            year: 'yyyy',
            longdatelongtime: 'D',
            shortdateshorttime: 'd'
        };
        DX.formatHelper = {
            romanDigits: ['I', 'II', 'III', 'IV'],
            _addFormatSeparator: function(format1, format2) {
                var separator = ' ';
                if (format2)
                    return format1 + separator + format2;
                return format1
            },
            _getDateTimeFormatPattern: function(dateTimeFormat) {
                return Globalize.findClosestCulture().calendar.patterns[DX.DateTimeFormat[dateTimeFormat.toLowerCase()]]
            },
            _isDateFormatContains: function(format) {
                var result = false;
                $.each(DX.DateTimeFormat, function(key, value) {
                    result = key === format.toLowerCase();
                    return !result
                });
                return result
            },
            getQuarter: function(month) {
                return Math.floor(month / 3)
            },
            getQuarterString: function(date, format) {
                var resultQuarter = '',
                    quarter = this.getQuarter(date.getMonth());
                switch (format) {
                    case'q':
                        resultQuarter = this.romanDigits[quarter];
                        break;
                    case'qq':
                        resultQuarter = 'Q' + this.romanDigits[quarter];
                        break;
                    case'Q':
                        resultQuarter = (quarter + 1).toString();
                        break;
                    case'QQ':
                        resultQuarter = 'Q' + (quarter + 1).toString();
                        break
                }
                return resultQuarter
            },
            getFirstQuarterMonth: function(month) {
                return this.getQuarter(month) * 3
            },
            _formatCustomString: function(value, format) {
                var regExp = /qq|q|QQ|Q/g,
                    quarterFormat,
                    result = '',
                    index = 0;
                while (index < format.length) {
                    quarterFormat = regExp.exec(format);
                    if (!quarterFormat || quarterFormat.index > index)
                        result += Globalize.format(value, format.substring(index, quarterFormat ? quarterFormat.index : format.length));
                    if (quarterFormat) {
                        result += this.getQuarterString(value, quarterFormat[0]);
                        index = quarterFormat.index + quarterFormat[0].length
                    }
                    else
                        index = format.length
                }
                return result
            },
            _parseNumberFormatString: function(format) {
                var formatList,
                    formatObject = {};
                if (!format || typeof format !== 'string')
                    return;
                formatList = format.toLowerCase().split(' ');
                $.each(formatList, function(index, value) {
                    if (value in DX.NumericFormat)
                        formatObject.formatType = value;
                    else if (value in DX.LargeNumberFormatPowers)
                        formatObject.power = DX.LargeNumberFormatPowers[value]
                });
                if (formatObject.power && !formatObject.formatType)
                    formatObject.formatType = 'fixedpoint';
                if (formatObject.formatType)
                    return formatObject
            },
            _calculateNumberPower: function(value, base, minPower, maxPower) {
                var number = Math.abs(value);
                var power = 0;
                if (number > 1)
                    while (number && number >= base && (maxPower === undefined || power < maxPower)) {
                        power++;
                        number = number / base
                    }
                else if (number > 0 && number < 1)
                    while (number < 1 && (minPower === undefined || power > minPower)) {
                        power--;
                        number = number * base
                    }
                return power
            },
            _getNumberByPower: function(number, power, base) {
                var result = number;
                while (power > 0) {
                    result = result / base;
                    power--
                }
                while (power < 0) {
                    result = result * base;
                    power++
                }
                return result
            },
            _formatNumber: function(value, formatObject, precision) {
                var powerPostfix;
                if (formatObject.power === 'auto')
                    formatObject.power = this._calculateNumberPower(value, 1000, 0, MAX_LARGE_NUMBER_POWER);
                if (formatObject.power)
                    value = this._getNumberByPower(value, formatObject.power, 1000);
                powerPostfix = DX.LargeNumberFormatPostfixes[formatObject.power] || '';
                return this._formatNumberCore(value, formatObject.formatType, precision) + powerPostfix
            },
            _formatNumberExponential: function(value, precision) {
                var power = this._calculateNumberPower(value, DECIMAL_BASE),
                    number = this._getNumberByPower(value, power, DECIMAL_BASE),
                    powString;
                precision = precision === undefined ? 1 : precision;
                if (number.toFixed(precision || 0) >= DECIMAL_BASE) {
                    power++;
                    number = number / DECIMAL_BASE
                }
                powString = (power >= 0 ? '+' : '') + power.toString();
                return this._formatNumberCore(number, 'fixedpoint', precision) + 'E' + powString
            },
            _formatNumberCore: function(value, format, precision) {
                if (format === 'exponential')
                    return this._formatNumberExponential(value, precision);
                else
                    return Globalize.format(value, DX.NumericFormat[format] + (utils.isNumber(precision) ? precision : 0))
            },
            _formatDate: function(date, format, formatString) {
                var resultFormat = DX.DateTimeFormat[format.toLowerCase()];
                format = format.toLowerCase();
                if (format === 'quarterandyear')
                    resultFormat = this.getQuarterString(date, resultFormat) + ' yyyy';
                if (format === 'quarter')
                    return this.getQuarterString(date, resultFormat);
                if (format === 'longdatelongtime')
                    return this._formatDate(date, 'longdate') + ' ' + this._formatDate(date, 'longtime');
                if (format === 'shortdateshorttime')
                    return this._formatDate(date, 'shortDate') + ' ' + this._formatDate(date, 'shortTime');
                return Globalize.format(date, resultFormat)
            },
            format: function(value, format, precision) {
                if (format && format.format)
                    if (format.dateType)
                        return this._formatDateEx(value, format);
                    else if (utils.isNumber(value) && isFinite(value))
                        return this._formatNumberEx(value, format);
                return this._format(value, format, precision)
            },
            _format: function(value, format, precision) {
                var numberFormatObject;
                if (!utils.isString(format) || format === '' || !utils.isNumber(value) && !utils.isDate(value))
                    return utils.isDefined(value) ? value.toString() : '';
                numberFormatObject = this._parseNumberFormatString(format);
                if (utils.isNumber(value) && numberFormatObject)
                    return this._formatNumber(value, numberFormatObject, precision);
                if (utils.isDate(value) && this._isDateFormatContains(format))
                    return this._formatDate(value, format);
                if (!numberFormatObject && !this._isDateFormatContains(format))
                    return this._formatCustomString(value, format)
            },
            _formatNumberEx: function(value, formatInfo) {
                var self = this,
                    numericFormatType = DX.NumericFormat[formatInfo.format.toLowerCase()],
                    numberFormat = Globalize.culture().numberFormat,
                    currencyFormat = formatInfo.currencyCulture && Globalize.cultures[formatInfo.currencyCulture] ? Globalize.cultures[formatInfo.currencyCulture].numberFormat.currency : numberFormat.currency,
                    percentFormat = numberFormat.percent,
                    formatSettings = self._getUnitFormatSettings(value, formatInfo),
                    unit = formatSettings.unit,
                    precision = formatSettings.precision,
                    showTrailingZeros = formatSettings.showTrailingZeros,
                    includeGroupSeparator = formatSettings.includeGroupSeparator,
                    groupSymbol = numberFormat[","],
                    floatingSymbol = numberFormat["."],
                    number,
                    isNegative,
                    pattern,
                    currentFormat,
                    regexParts = /n|\$|-|%/g,
                    result = "";
                value = self._applyUnitToValue(value, unit);
                number = Math.abs(value);
                isNegative = value < 0;
                switch (numericFormatType) {
                    case"D":
                        pattern = "n";
                        number = Math[isNegative ? "ceil" : "floor"](number);
                        if (precision > 0) {
                            var str = "" + number;
                            for (var i = str.length; i < precision; i += 1)
                                str = "0" + str;
                            number = str
                        }
                        if (isNegative)
                            number = "-" + number;
                        break;
                    case"N":
                        currentFormat = numberFormat;
                    case"C":
                        currentFormat = currentFormat || currencyFormat;
                    case"P":
                        currentFormat = currentFormat || percentFormat;
                        pattern = isNegative ? currentFormat.pattern[0] : currentFormat.pattern[1] || "n";
                        number = Globalize.format(number * (numericFormatType === "P" ? 100 : 1), "N" + precision);
                        if (!showTrailingZeros)
                            number = self._excludeTrailingZeros(number, floatingSymbol);
                        if (!includeGroupSeparator)
                            number = number.replace(new RegExp('\\' + groupSymbol, 'g'), '');
                        break;
                    default:
                        throw"Illegal numeric format: '" + numericFormatType + "'";
                }
                for (; ; ) {
                    var lastIndex = regexParts.lastIndex,
                        matches = regexParts.exec(pattern);
                    result += pattern.slice(lastIndex, matches ? matches.index : pattern.length);
                    if (matches)
                        switch (matches[0]) {
                            case"-":
                                if (/[1-9]/.test(number))
                                    result += numberFormat["-"];
                                break;
                            case"$":
                                result += currencyFormat.symbol;
                                break;
                            case"%":
                                result += percentFormat.symbol;
                                break;
                            case"n":
                                result += number + unit;
                                break
                        }
                    else
                        break
                }
                return (formatInfo.plus && value > 0 ? "+" : '') + result
            },
            _excludeTrailingZeros: function(strValue, floatingSymbol) {
                var floatingIndex = strValue.indexOf(floatingSymbol),
                    stopIndex,
                    i;
                if (floatingIndex < 0)
                    return strValue;
                stopIndex = strValue.length;
                for (i = stopIndex - 1; i >= floatingIndex && (strValue[i] === '0' || i === floatingIndex); i--)
                    stopIndex--;
                return strValue.substring(0, stopIndex)
            },
            _getUnitFormatSettings: function(value, formatInfo) {
                var unit = formatInfo.unit || '',
                    precision = formatInfo.precision || 0,
                    includeGroupSeparator = formatInfo.includeGroupSeparator || false,
                    showTrailingZeros = formatInfo.showTrailingZeros === undefined ? true : formatInfo.showTrailingZeros,
                    significantDigits = formatInfo.significantDigits || 1,
                    absValue;
                if (unit.toLowerCase() === 'auto') {
                    showTrailingZeros = false;
                    absValue = Math.abs(value);
                    if (significantDigits < 1)
                        significantDigits = 1;
                    if (absValue >= 1000000000) {
                        unit = 'B';
                        absValue /= 1000000000
                    }
                    else if (absValue >= 1000000) {
                        unit = 'M';
                        absValue /= 1000000
                    }
                    else if (absValue >= 1000) {
                        unit = 'K';
                        absValue /= 1000
                    }
                    else
                        unit = '';
                    if (absValue == 0)
                        precision = 0;
                    else if (absValue < 1) {
                        precision = significantDigits;
                        var smallValue = Math.pow(10, -significantDigits);
                        while (absValue < smallValue) {
                            smallValue /= 10;
                            precision++
                        }
                    }
                    else if (absValue >= 100)
                        precision = significantDigits - 3;
                    else if (absValue >= 10)
                        precision = significantDigits - 2;
                    else
                        precision = significantDigits - 1
                }
                if (precision < 0)
                    precision = 0;
                return {
                        unit: unit,
                        precision: precision,
                        showTrailingZeros: showTrailingZeros,
                        includeGroupSeparator: includeGroupSeparator
                    }
            },
            _applyUnitToValue: function(value, unit) {
                if (unit == 'B')
                    return value.toFixed(1) / 1000000000;
                if (unit == 'M')
                    return value / 1000000;
                if (unit == 'K')
                    return value / 1000;
                return value
            },
            _formatDateEx: function(value, formatInfo) {
                var self = this,
                    quarterPrefix = 'Q',
                    format = formatInfo.format,
                    dateType = formatInfo.dateType,
                    calendar = Globalize.culture().calendars.standard,
                    time = undefined,
                    index,
                    dateStr;
                format = format.toLowerCase();
                if (dateType !== 'num' || format === 'dayofweek')
                    switch (format) {
                        case'monthyear':
                            return self._formatDate(value, 'monthandyear');
                        case'quarteryear':
                            return self.getQuarterString(value, 'QQ') + ' ' + value.getFullYear();
                        case'daymonthyear':
                            return self._formatDate(value, dateType + 'Date');
                        case'datehour':
                            time = new Date(value.getTime());
                            time.setMinutes(0);
                            dateStr = dateType === 'timeOnly' ? '' : self._formatDate(value, dateType + 'Date');
                            return dateType === 'timeOnly' ? self._formatDate(time, 'shorttime') : dateStr + ' ' + self._formatDate(time, 'shorttime');
                        case'datehourminute':
                            dateStr = dateType === 'timeOnly' ? '' : self._formatDate(value, dateType + 'Date');
                            return dateType === 'timeOnly' ? self._formatDate(value, 'shorttime') : dateStr + ' ' + self._formatDate(value, 'shorttime');
                        case'datehourminutesecond':
                            dateStr = dateType === 'timeOnly' ? '' : self._formatDate(value, dateType + 'Date');
                            return dateType === 'timeOnly' ? self._formatDate(value, 'longtime') : dateStr + ' ' + self._formatDate(value, 'longtime');
                        case'year':
                            dateStr = value.toString();
                            return dateType === 'abbr' ? dateStr.slice(2, 4) : dateStr;
                        case'quarter':
                            return quarterPrefix + value.toString();
                        case'month':
                            index = value - 1;
                            return dateType === 'abbr' ? calendar.months.namesAbbr[index] : calendar.months.names[index];
                        case'hour':
                            if (dateType === 'long') {
                                time = new Date;
                                time.setHours(value);
                                time.setMinutes(0);
                                return self._formatDate(time, 'shorttime')
                            }
                            else
                                return value.toString();
                        case'dayofweek':
                            index = $.inArray(value, ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']);
                            if (dateType !== 'num')
                                return dateType === 'abbr' ? calendar.days.namesAbbr[index] : calendar.days.names[index];
                            else
                                return ((index - calendar.firstDay + 1 + 7) % 8).toString();
                        default:
                            return value.toString()
                    }
                else
                    return value.toString()
            },
            getTimeFormat: function(showSecond) {
                if (showSecond)
                    return this._getDateTimeFormatPattern('longtime');
                return this._getDateTimeFormatPattern('shorttime')
            },
            getDateFormatByDifferences: function(dateDifferences) {
                var resultFormat = '';
                if (dateDifferences.millisecond)
                    resultFormat = DX.DateTimeFormat.millisecond;
                if (dateDifferences.hour || dateDifferences.minute || dateDifferences.second)
                    resultFormat = this._addFormatSeparator(this.getTimeFormat(dateDifferences.second), resultFormat);
                if (dateDifferences.year && dateDifferences.month && dateDifferences.day)
                    return this._addFormatSeparator(this._getDateTimeFormatPattern('shortdate'), resultFormat);
                if (dateDifferences.year && dateDifferences.month)
                    return DX.DateTimeFormat['monthandyear'];
                if (dateDifferences.year)
                    return DX.DateTimeFormat['year'];
                if (dateDifferences.month && dateDifferences.day)
                    return this._addFormatSeparator(this._getDateTimeFormatPattern('monthandday'), resultFormat);
                if (dateDifferences.month)
                    return DX.DateTimeFormat['month'];
                if (dateDifferences.day)
                    return this._addFormatSeparator('dddd, dd', resultFormat);
                return resultFormat
            },
            getDateFormatByTicks: function(ticks) {
                var resultFormat,
                    maxDif,
                    currentDif,
                    i,
                    dateUnitInterval;
                if (ticks.length > 1) {
                    maxDif = utils.getDatesDifferences(ticks[0], ticks[1]);
                    for (i = 1; i < ticks.length - 1; i++) {
                        currentDif = utils.getDatesDifferences(ticks[i], ticks[i + 1]);
                        if (maxDif.count < currentDif.count)
                            maxDif = currentDif
                    }
                }
                else
                    maxDif = {
                        year: true,
                        month: true,
                        day: true,
                        hour: ticks[0].getHours() > 0,
                        minute: ticks[0].getMinutes() > 0,
                        second: ticks[0].getSeconds() > 0
                    };
                resultFormat = this.getDateFormatByDifferences(maxDif);
                return resultFormat
            },
            getDateFormatByTickInterval: function(startValue, endValue, tickInterval) {
                var resultFormat,
                    dateDifferences,
                    dateUnitInterval,
                    dateDifferencesConverter = {
                        quarter: 'month',
                        week: 'day'
                    },
                    correctDateDifferences = function(dateDifferences, tickInterval, value) {
                        switch (tickInterval) {
                            case'year':
                                dateDifferences.month = value;
                            case'quarter':
                            case'month':
                                dateDifferences.day = value;
                            case'week':
                            case'day':
                                dateDifferences.hour = value;
                            case'hour':
                                dateDifferences.minute = value;
                            case'minute':
                                dateDifferences.second = value;
                            case'second':
                                dateDifferences.millisecond = value
                        }
                    },
                    correctDifferencesByMaxDate = function(differences, minDate, maxDate) {
                        if (!maxDate.getMilliseconds() && maxDate.getSeconds()) {
                            if (maxDate.getSeconds() - minDate.getSeconds() === 1) {
                                differences.millisecond = true;
                                differences.second = false
                            }
                        }
                        else if (!maxDate.getSeconds() && maxDate.getMinutes()) {
                            if (maxDate.getMinutes() - minDate.getMinutes() === 1) {
                                differences.second = true;
                                differences.minute = false
                            }
                        }
                        else if (!maxDate.getMinutes() && maxDate.getHours()) {
                            if (maxDate.getHours() - minDate.getHours() === 1) {
                                differences.minute = true;
                                differences.hour = false
                            }
                        }
                        else if (!maxDate.getHours() && maxDate.getDate() > 1) {
                            if (maxDate.getDate() - minDate.getDate() === 1) {
                                differences.hour = true;
                                differences.day = false
                            }
                        }
                        else if (maxDate.getDate() === 1 && maxDate.getMonth()) {
                            if (maxDate.getMonth() - minDate.getMonth() === 1) {
                                differences.day = true;
                                differences.month = false
                            }
                        }
                        else if (!maxDate.getMonth() && maxDate.getFullYear())
                            if (maxDate.getFullYear() - minDate.getFullYear() === 1) {
                                differences.month = true;
                                differences.year = false
                            }
                    };
                tickInterval = utils.isString(tickInterval) ? tickInterval.toLowerCase() : tickInterval;
                dateDifferences = utils.getDatesDifferences(startValue, endValue);
                if (startValue !== endValue)
                    correctDifferencesByMaxDate(dateDifferences, startValue > endValue ? endValue : startValue, startValue > endValue ? startValue : endValue);
                dateUnitInterval = utils.getDateUnitInterval(dateDifferences);
                correctDateDifferences(dateDifferences, dateUnitInterval, true);
                dateUnitInterval = utils.getDateUnitInterval(tickInterval || 'second');
                correctDateDifferences(dateDifferences, dateUnitInterval, false);
                dateDifferences[dateDifferencesConverter[dateUnitInterval] || dateUnitInterval] = true;
                resultFormat = this.getDateFormatByDifferences(dateDifferences);
                return resultFormat
            }
        }
    })(jQuery, DevExpress);
    /*! Module core, file color.js */
    (function($, DX, undefined) {
        var Class = DX.Class;
        DX.Color = Class.inherit(function() {
            var ctor = function(baseColor) {
                    this.baseColor = baseColor;
                    this.decode()
                };
            var standardColorNames = {
                    aliceblue: 'f0f8ff',
                    antiquewhite: 'faebd7',
                    aqua: '00ffff',
                    aquamarine: '7fffd4',
                    azure: 'f0ffff',
                    beige: 'f5f5dc',
                    bisque: 'ffe4c4',
                    black: '000000',
                    blanchedalmond: 'ffebcd',
                    blue: '0000ff',
                    blueviolet: '8a2be2',
                    brown: 'a52a2a',
                    burlywood: 'deb887',
                    cadetblue: '5f9ea0',
                    chartreuse: '7fff00',
                    chocolate: 'd2691e',
                    coral: 'ff7f50',
                    cornflowerblue: '6495ed',
                    cornsilk: 'fff8dc',
                    crimson: 'dc143c',
                    cyan: '00ffff',
                    darkblue: '00008b',
                    darkcyan: '008b8b',
                    darkgoldenrod: 'b8860b',
                    darkgray: 'a9a9a9',
                    darkgreen: '006400',
                    darkkhaki: 'bdb76b',
                    darkmagenta: '8b008b',
                    darkolivegreen: '556b2f',
                    darkorange: 'ff8c00',
                    darkorchid: '9932cc',
                    darkred: '8b0000',
                    darksalmon: 'e9967a',
                    darkseagreen: '8fbc8f',
                    darkslateblue: '483d8b',
                    darkslategray: '2f4f4f',
                    darkturquoise: '00ced1',
                    darkviolet: '9400d3',
                    deeppink: 'ff1493',
                    deepskyblue: '00bfff',
                    dimgray: '696969',
                    dodgerblue: '1e90ff',
                    feldspar: 'd19275',
                    firebrick: 'b22222',
                    floralwhite: 'fffaf0',
                    forestgreen: '228b22',
                    fuchsia: 'ff00ff',
                    gainsboro: 'dcdcdc',
                    ghostwhite: 'f8f8ff',
                    gold: 'ffd700',
                    goldenrod: 'daa520',
                    gray: '808080',
                    green: '008000',
                    greenyellow: 'adff2f',
                    honeydew: 'f0fff0',
                    hotpink: 'ff69b4',
                    indianred: 'cd5c5c',
                    indigo: '4b0082',
                    ivory: 'fffff0',
                    khaki: 'f0e68c',
                    lavender: 'e6e6fa',
                    lavenderblush: 'fff0f5',
                    lawngreen: '7cfc00',
                    lemonchiffon: 'fffacd',
                    lightblue: 'add8e6',
                    lightcoral: 'f08080',
                    lightcyan: 'e0ffff',
                    lightgoldenrodyellow: 'fafad2',
                    lightgrey: 'd3d3d3',
                    lightgreen: '90ee90',
                    lightpink: 'ffb6c1',
                    lightsalmon: 'ffa07a',
                    lightseagreen: '20b2aa',
                    lightskyblue: '87cefa',
                    lightslateblue: '8470ff',
                    lightslategray: '778899',
                    lightsteelblue: 'b0c4de',
                    lightyellow: 'ffffe0',
                    lime: '00ff00',
                    limegreen: '32cd32',
                    linen: 'faf0e6',
                    magenta: 'ff00ff',
                    maroon: '800000',
                    mediumaquamarine: '66cdaa',
                    mediumblue: '0000cd',
                    mediumorchid: 'ba55d3',
                    mediumpurple: '9370d8',
                    mediumseagreen: '3cb371',
                    mediumslateblue: '7b68ee',
                    mediumspringgreen: '00fa9a',
                    mediumturquoise: '48d1cc',
                    mediumvioletred: 'c71585',
                    midnightblue: '191970',
                    mintcream: 'f5fffa',
                    mistyrose: 'ffe4e1',
                    moccasin: 'ffe4b5',
                    navajowhite: 'ffdead',
                    navy: '000080',
                    oldlace: 'fdf5e6',
                    olive: '808000',
                    olivedrab: '6b8e23',
                    orange: 'ffa500',
                    orangered: 'ff4500',
                    orchid: 'da70d6',
                    palegoldenrod: 'eee8aa',
                    palegreen: '98fb98',
                    paleturquoise: 'afeeee',
                    palevioletred: 'd87093',
                    papayawhip: 'ffefd5',
                    peachpuff: 'ffdab9',
                    peru: 'cd853f',
                    pink: 'ffc0cb',
                    plum: 'dda0dd',
                    powderblue: 'b0e0e6',
                    purple: '800080',
                    red: 'ff0000',
                    rosybrown: 'bc8f8f',
                    royalblue: '4169e1',
                    saddlebrown: '8b4513',
                    salmon: 'fa8072',
                    sandybrown: 'f4a460',
                    seagreen: '2e8b57',
                    seashell: 'fff5ee',
                    sienna: 'a0522d',
                    silver: 'c0c0c0',
                    skyblue: '87ceeb',
                    slateblue: '6a5acd',
                    slategray: '708090',
                    snow: 'fffafa',
                    springgreen: '00ff7f',
                    steelblue: '4682b4',
                    tan: 'd2b48c',
                    teal: '008080',
                    thistle: 'd8bfd8',
                    tomato: 'ff6347',
                    turquoise: '40e0d0',
                    violet: 'ee82ee',
                    violetred: 'd02090',
                    wheat: 'f5deb3',
                    white: 'ffffff',
                    whitesmoke: 'f5f5f5',
                    yellow: 'ffff00',
                    yellowgreen: '9acd32'
                };
            var standardColorTypes = [{
                        re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
                        process: function(colorString) {
                            return [parseInt(colorString[1], 10), parseInt(colorString[2], 10), parseInt(colorString[3], 10)]
                        }
                    }, {
                        re: /^(\w{2})(\w{2})(\w{2})$/,
                        process: function(colorString) {
                            return [parseInt(colorString[1], 16), parseInt(colorString[2], 16), parseInt(colorString[3], 16)]
                        }
                    }, {
                        re: /^(\w{1})(\w{1})(\w{1})$/,
                        process: function(colorString) {
                            return [parseInt(colorString[1] + colorString[1], 16), parseInt(colorString[2] + colorString[2], 16), parseInt(colorString[3] + colorString[3], 16)]
                        }
                    }];
            var decode = function() {
                    var baseColor = this.baseColor;
                    if (baseColor.charAt(0) === '#')
                        baseColor = baseColor.substr(1, 6);
                    baseColor = baseColor.toLowerCase();
                    baseColor = baseColor.replace(/ /g, '');
                    for (var standardColor in standardColorNames)
                        if (standardColorNames.hasOwnProperty(standardColor))
                            if (baseColor === standardColor)
                                baseColor = standardColorNames[standardColor];
                    for (var i = 0; i < standardColorTypes.length; i++) {
                        var re = standardColorTypes[i].re;
                        var colorString = re.exec(baseColor);
                        if (colorString) {
                            var colorRgb = standardColorTypes[i].process(colorString);
                            this.r = colorRgb[0];
                            this.g = colorRgb[1];
                            this.b = colorRgb[2];
                            this.ok = true;
                            break
                        }
                    }
                    this.r = normalize(this.r);
                    this.g = normalize(this.g);
                    this.b = normalize(this.b)
                };
            var normalize = function(colorComponent) {
                    return colorComponent < 0 || isNaN(colorComponent) ? 0 : colorComponent > 255 ? 255 : colorComponent
                };
            var digitToHex = function(n) {
                    var st = n.toString(16);
                    if (st.length === 1)
                        return '0' + st;
                    return st
                };
            var toHexFromRgb = function(r, g, b) {
                    return '#' + digitToHex(r) + digitToHex(g) + digitToHex(b)
                };
            var toHex = function() {
                    return toHexFromRgb(this.r, this.g, this.b)
                };
            var highlight = function(step) {
                    step = step || 10;
                    return toHexFromRgb(normalize(this.r + step), normalize(this.g + step), normalize(this.b + step))
                };
            var darken = function(step) {
                    step = step || 10;
                    return toHexFromRgb(normalize(this.r - step), normalize(this.g - step), normalize(this.b - step))
                };
            return {
                    ctor: ctor,
                    highlight: highlight,
                    darken: darken,
                    decode: decode,
                    toHex: toHex
                }
        }())
    })(jQuery, DevExpress);
    /*! Module core, file data.js */
    (function($, DX, undefined) {
        var HAS_KO = !!window.ko;
        var bracketsToDots = function(expr) {
                return expr.replace(/\[/g, ".").replace(/\]/g, "")
            };
        var unwrapObservable = function(value) {
                if (HAS_KO)
                    return ko.utils.unwrapObservable(value);
                return value
            };
        var isObservable = function(value) {
                return HAS_KO && ko.isObservable(value)
            };
        var assign = function(obj, propName, value) {
                var propValue = obj[propName];
                if (isObservable(propValue))
                    propValue(value);
                else
                    obj[propName] = value
            };
        var compileGetter = function(expr) {
                if (arguments.length > 1)
                    expr = $.makeArray(arguments);
                if (!expr || expr === "this")
                    return function(obj) {
                            return obj
                        };
                if ($.isFunction(expr))
                    return expr;
                if ($.isArray(expr))
                    return combineGetters(expr);
                expr = bracketsToDots(expr);
                var path = expr.split(".");
                return function(obj, options) {
                        options = options || {};
                        var current = unwrapObservable(obj);
                        $.each(path, function() {
                            if (!current)
                                return false;
                            var next = unwrapObservable(current[this]);
                            if ($.isFunction(next) && !options.functionsAsIs)
                                next = next.call(current);
                            current = next
                        });
                        return current
                    }
            };
        var combineGetters = function(getters) {
                var compiledGetters = {};
                $.each(getters, function() {
                    compiledGetters[this] = compileGetter(this)
                });
                return function(obj, options) {
                        var result = {};
                        $.each(compiledGetters, function(name) {
                            var value = this(obj, options),
                                current,
                                path,
                                last,
                                i;
                            if (value === undefined)
                                return;
                            current = result;
                            path = name.split(".");
                            last = path.length - 1;
                            for (i = 0; i < last; i++)
                                current = current[path[i]] = {};
                            current[path[i]] = value
                        });
                        return result
                    }
            };
        var compileSetter = function(expr) {
                if (!expr || expr === "this")
                    throw Error("Cannot assign to self");
                expr = bracketsToDots(expr);
                var pos = expr.lastIndexOf("."),
                    targetGetter = compileGetter(expr.substr(0, pos)),
                    targetExpr = expr.substr(1 + pos);
                return function(obj, value, options) {
                        options = options || {};
                        var target = targetGetter(obj, {functionsAsIs: options.functionsAsIs}),
                            prevTargetValue = target[targetExpr];
                        if (!options.functionsAsIs && $.isFunction(prevTargetValue) && !isObservable(prevTargetValue))
                            target[targetExpr](value);
                        else {
                            prevTargetValue = unwrapObservable(prevTargetValue);
                            if (options.merge && $.isPlainObject(value) && (prevTargetValue === undefined || $.isPlainObject(prevTargetValue))) {
                                if (!prevTargetValue)
                                    assign(target, targetExpr, {});
                                $.extend(true, unwrapObservable(target[targetExpr]), value)
                            }
                            else
                                assign(target, targetExpr, value)
                        }
                    }
            };
        var normalizeBinaryCriterion = function(crit) {
                return [crit[0], crit.length < 3 ? "=" : crit[1].toLowerCase(), crit.length < 2 ? true : crit[crit.length - 1]]
            };
        var normalizeSortingInfo = function(info) {
                if (!$.isArray(info))
                    info = [info];
                return $.map(info, function(i) {
                        return {
                                selector: $.isFunction(i) || typeof i === "string" ? i : i.field || i.selector,
                                desc: !!(i.desc || String(i.dir).charAt(0).toLowerCase() === "d")
                            }
                    })
            };
        var Guid = DX.Class.inherit({
                ctor: function(value) {
                    if (value)
                        value = String(value);
                    this._value = this._normalize(value || this._generate())
                },
                _normalize: function(value) {
                    value = value.replace(/[^a-f0-9]/ig, "").toLowerCase();
                    while (value.length < 32)
                        value += "0";
                    return [value.substr(0, 8), value.substr(8, 4), value.substr(12, 4), value.substr(16, 4), value.substr(20)].join("-")
                },
                _generate: function() {
                    var value = "";
                    for (var i = 0; i < 32; i++)
                        value += Math.round(Math.random() * 16).toString(16);
                    return value
                },
                toString: function() {
                    return this._value
                },
                valueOf: function() {
                    return this._value
                },
                toJSON: function() {
                    return this._value
                }
            });
        var toComparable = function(value, caseSensitive) {
                if (value instanceof Date)
                    return value.getTime();
                if (value instanceof Guid)
                    return value.valueOf();
                if (!caseSensitive && typeof value === "string")
                    return value.toLowerCase();
                return value
            };
        var keysEqual = function(keyExpr, key1, key2) {
                if ($.isArray(keyExpr)) {
                    var names = $.map(key1, function(v, k) {
                            return k
                        }),
                        name;
                    for (var i = 0; i < names.length; i++) {
                        name = names[i];
                        if (toComparable(key1[name], true) != toComparable(key2[name], true))
                            return false
                    }
                    return true
                }
                return toComparable(key1, true) == toComparable(key2, true)
            };
        var BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
        var base64_encode = function(input) {
                if (!$.isArray(input))
                    input = stringToByteArray(String(input));
                var result = "";
                for (var i = 0; i < input.length; i += 3) {
                    var octet1 = input[i],
                        octet2 = input[i + 1],
                        octet3 = input[i + 2];
                    result += $.map([octet1 >> 2, (octet1 & 3) << 4 | octet2 >> 4, isNaN(octet2) ? 64 : (octet2 & 15) << 2 | octet3 >> 6, isNaN(octet3) ? 64 : octet3 & 63], function(item) {
                        return BASE64_CHARS.charAt(item)
                    }).join("")
                }
                return result
            };
        var stringToByteArray = function(str) {
                var bytes = [],
                    code,
                    i;
                for (i = 0; i < str.length; i++) {
                    code = str.charCodeAt(i);
                    if (code < 128)
                        bytes.push(code);
                    else if (code < 2048)
                        bytes.push(192 + (code >> 6), 128 + (code & 63));
                    else if (code < 65536)
                        bytes.push(224 + (code >> 12), 128 + (code >> 6 & 63), 128 + (code & 63));
                    else if (code < 2097152)
                        bytes.push(240 + (code >> 18), 128 + (code >> 12 & 63), 128 + (code >> 6 & 63), 128 + (code & 63))
                }
                return bytes
            };
        var errorMessageFromXhr = function() {
                var textStatusMessages = {
                        timeout: "Network connection timeout",
                        error: "Unspecified network error",
                        parsererror: "Unexpected server response"
                    };
                var textStatusDetails = {
                        timeout: "possible causes: the remote host is not accessible, overloaded or is not included into the domain white-list when being run in the native container",
                        error: "if the remote host is located on another domain, make sure it properly supports cross-origin resource sharing (CORS), or use the JSONP approach instead",
                        parsererror: "the remote host did not respond with valid JSON data"
                    };
                var explainTextStatus = function(textStatus) {
                        var result = textStatusMessages[textStatus];
                        if (!result)
                            return textStatus;
                        result += " (" + textStatusDetails[textStatus] + ")";
                        return result
                    };
                return function(xhr, textStatus) {
                        if (xhr.status < 400)
                            return explainTextStatus(textStatus);
                        return xhr.statusText
                    }
            }();
        var data = DX.data = {
                utils: {
                    compileGetter: compileGetter,
                    compileSetter: compileSetter,
                    normalizeBinaryCriterion: normalizeBinaryCriterion,
                    normalizeSortingInfo: normalizeSortingInfo,
                    toComparable: toComparable,
                    keysEqual: keysEqual,
                    errorMessageFromXhr: errorMessageFromXhr
                },
                Guid: Guid,
                base64_encode: base64_encode,
                queryImpl: {},
                queryAdapters: {},
                query: function() {
                    var impl = $.isArray(arguments[0]) ? "array" : "remote";
                    return data.queryImpl[impl].apply(this, arguments)
                },
                errorHandler: null,
                _handleError: function(error) {
                    if (window.console)
                        console.warn("[DevExpress.data]: " + error);
                    if (data.errorHandler)
                        data.errorHandler(error)
                }
            }
    })(jQuery, DevExpress);
    /*! Module core, file data.query.array.js */
    (function($, DX, undefined) {
        var Class = DX.Class,
            data = DX.data,
            queryImpl = data.queryImpl,
            compileGetter = data.utils.compileGetter,
            toComparable = data.utils.toComparable;
        var Iterator = Class.inherit({
                toArray: function() {
                    var result = [];
                    this.reset();
                    while (this.next())
                        result.push(this.current());
                    return result
                },
                countable: function() {
                    return false
                }
            });
        var ArrayIterator = Iterator.inherit({
                ctor: function(array) {
                    this.array = array;
                    this.index = -1
                },
                next: function() {
                    if (this.index + 1 < this.array.length) {
                        this.index++;
                        return true
                    }
                    return false
                },
                current: function() {
                    return this.array[this.index]
                },
                reset: function() {
                    this.index = -1
                },
                toArray: function() {
                    return this.array.slice(0)
                },
                countable: function() {
                    return true
                },
                count: function() {
                    return this.array.length
                }
            });
        var WrappedIterator = Iterator.inherit({
                ctor: function(iter) {
                    this.iter = iter
                },
                next: function() {
                    return this.iter.next()
                },
                current: function() {
                    return this.iter.current()
                },
                reset: function() {
                    return this.iter.reset()
                }
            });
        var SortIterator = Iterator.inherit({
                ctor: function(iter, getter, desc) {
                    this.iter = iter;
                    this.rules = [{
                            getter: getter,
                            desc: desc
                        }]
                },
                thenBy: function(getter, desc) {
                    var result = new SortIterator(this.sortedIter || this.iter, getter, desc);
                    if (!this.sortedIter)
                        result.rules = this.rules.concat(result.rules);
                    return result
                },
                next: function() {
                    this._ensureSorted();
                    return this.sortedIter.next()
                },
                current: function() {
                    this._ensureSorted();
                    return this.sortedIter.current()
                },
                reset: function() {
                    delete this.sortedIter
                },
                countable: function() {
                    return this.sortedIter || this.iter.countable()
                },
                count: function() {
                    if (this.sortedIter)
                        return this.sortedIter.count();
                    return this.iter.count()
                },
                _ensureSorted: function() {
                    if (this.sortedIter)
                        return;
                    $.each(this.rules, function() {
                        this.getter = compileGetter(this.getter)
                    });
                    this.sortedIter = new ArrayIterator(this.iter.toArray().sort($.proxy(this._compare, this)))
                },
                _compare: function(x, y) {
                    if (x === y)
                        return 0;
                    for (var i = 0, rulesCount = this.rules.length; i < rulesCount; i++) {
                        var rule = this.rules[i],
                            xValue = toComparable(rule.getter(x)),
                            yValue = toComparable(rule.getter(y)),
                            factor = rule.desc ? -1 : 1;
                        if (xValue < yValue)
                            return -factor;
                        if (xValue > yValue)
                            return factor;
                        if (xValue !== yValue)
                            return !xValue ? -factor : factor
                    }
                    return 0
                }
            });
        var compileCriteria = function() {
                var compileGroup = function(crit) {
                        var operands = [],
                            bag = ["return function(d) { return "],
                            index = 0,
                            pushAnd = false;
                        $.each(crit, function() {
                            if ($.isArray(this) || $.isFunction(this)) {
                                if (pushAnd)
                                    bag.push(" && ");
                                operands.push(compileCriteria(this));
                                bag.push("op[", index, "](d)");
                                index++;
                                pushAnd = true
                            }
                            else {
                                bag.push(/and|&/i.test(this) ? " && " : " || ");
                                pushAnd = false
                            }
                        });
                        bag.push(" }");
                        return new Function("op", bag.join(""))(operands)
                    };
                var toString = function(value) {
                        return DX.utils.isDefined(value) ? value.toString() : ''
                    };
                var compileBinary = function(crit) {
                        crit = data.utils.normalizeBinaryCriterion(crit);
                        var getter = compileGetter(crit[0]),
                            op = crit[1],
                            value = crit[2];
                        value = toComparable(value);
                        switch (op.toLowerCase()) {
                            case"=":
                                return function(obj) {
                                        return toComparable(getter(obj)) == value
                                    };
                            case"<>":
                                return function(obj) {
                                        return toComparable(getter(obj)) != value
                                    };
                            case">":
                                return function(obj) {
                                        return toComparable(getter(obj)) > value
                                    };
                            case"<":
                                return function(obj) {
                                        return toComparable(getter(obj)) < value
                                    };
                            case">=":
                                return function(obj) {
                                        return toComparable(getter(obj)) >= value
                                    };
                            case"<=":
                                return function(obj) {
                                        return toComparable(getter(obj)) <= value
                                    };
                            case"startswith":
                                return function(obj) {
                                        return toComparable(toString(getter(obj))).indexOf(value) === 0
                                    };
                            case"endswith":
                                return function(obj) {
                                        var getterValue = toComparable(toString(getter(obj)));
                                        return getterValue.lastIndexOf(value) === getterValue.length - toString(value).length
                                    };
                            case"contains":
                                return function(obj) {
                                        return toComparable(toString(getter(obj))).indexOf(value) > -1
                                    };
                            case"notcontains":
                                return function(obj) {
                                        return toComparable(toString(getter(obj))).indexOf(value) === -1
                                    }
                        }
                    };
                return function(crit) {
                        if ($.isFunction(crit))
                            return crit;
                        if ($.isArray(crit[0]))
                            return compileGroup(crit);
                        return compileBinary(crit)
                    }
            }();
        var FilterIterator = WrappedIterator.inherit({
                ctor: function(iter, criteria) {
                    this.callBase(iter);
                    this.criteria = compileCriteria(criteria)
                },
                next: function() {
                    while (this.iter.next())
                        if (this.criteria(this.current()))
                            return true;
                    return false
                }
            });
        var GroupIterator = Iterator.inherit({
                ctor: function(iter, getter) {
                    this.iter = iter;
                    this.getter = getter
                },
                next: function() {
                    this._ensureGrouped();
                    return this.groupedIter.next()
                },
                current: function() {
                    this._ensureGrouped();
                    return this.groupedIter.current()
                },
                reset: function() {
                    delete this.groupedIter
                },
                countable: function() {
                    return !!this.groupedIter
                },
                count: function() {
                    return this.groupedIter.count()
                },
                _ensureGrouped: function() {
                    if (this.groupedIter)
                        return;
                    var hash = {},
                        keys = [],
                        iter = this.iter,
                        getter = compileGetter(this.getter);
                    iter.reset();
                    while (iter.next()) {
                        var current = iter.current(),
                            key = getter(current);
                        if (key in hash)
                            hash[key].push(current);
                        else {
                            hash[key] = [current];
                            keys.push(key)
                        }
                    }
                    this.groupedIter = new ArrayIterator($.map(keys, function(key) {
                        return {
                                key: key,
                                items: hash[key]
                            }
                    }))
                }
            });
        var SelectIterator = WrappedIterator.inherit({
                ctor: function(iter, getter) {
                    this.callBase(iter);
                    this.getter = compileGetter(getter)
                },
                current: function() {
                    return this.getter(this.callBase())
                },
                countable: function() {
                    return this.iter.countable()
                },
                count: function() {
                    return this.iter.count()
                }
            });
        var SliceIterator = WrappedIterator.inherit({
                ctor: function(iter, skip, take) {
                    this.callBase(iter);
                    this.skip = Math.max(0, skip);
                    this.take = Math.max(0, take);
                    this.pos = 0
                },
                next: function() {
                    if (this.pos >= this.skip + this.take)
                        return false;
                    while (this.pos < this.skip && this.iter.next())
                        this.pos++;
                    this.pos++;
                    return this.iter.next()
                },
                reset: function() {
                    this.callBase();
                    this.pos = 0
                },
                countable: function() {
                    return this.iter.countable()
                },
                count: function() {
                    return Math.min(this.iter.count() - this.skip, this.take)
                }
            });
        queryImpl.array = function(iter, queryOptions) {
            queryOptions = queryOptions || {};
            if (!(iter instanceof Iterator))
                iter = new ArrayIterator(iter);
            var handleError = function(error) {
                    var handler = queryOptions.errorHandler;
                    if (handler)
                        handler(error);
                    data._handleError(error)
                };
            var aggregate = function(seed, step, finalize) {
                    var d = $.Deferred().fail(handleError);
                    try {
                        iter.reset();
                        if (arguments.length < 2) {
                            step = arguments[0];
                            seed = iter.next() ? iter.current() : undefined
                        }
                        var accumulator = seed;
                        while (iter.next())
                            accumulator = step(accumulator, iter.current());
                        d.resolve(finalize ? finalize(accumulator) : accumulator)
                    }
                    catch(x) {
                        d.reject(x)
                    }
                    return d.promise()
                };
            var select = function(getter) {
                    if (!$.isFunction(getter) && !$.isArray(getter))
                        getter = $.makeArray(arguments);
                    return chainQuery(new SelectIterator(iter, getter))
                };
            var selectProp = function(name) {
                    return select(compileGetter(name))
                };
            var chainQuery = function(iter) {
                    return queryImpl.array(iter, queryOptions)
                };
            return {
                    toArray: function() {
                        return iter.toArray()
                    },
                    enumerate: function() {
                        var d = $.Deferred().fail(handleError);
                        try {
                            d.resolve(iter.toArray())
                        }
                        catch(x) {
                            d.reject(x)
                        }
                        return d.promise()
                    },
                    sortBy: function(getter, desc) {
                        return chainQuery(new SortIterator(iter, getter, desc))
                    },
                    thenBy: function(getter, desc) {
                        if (iter instanceof SortIterator)
                            return chainQuery(iter.thenBy(getter, desc));
                        throw Error();
                    },
                    filter: function(criteria) {
                        if (!$.isArray(criteria))
                            criteria = $.makeArray(arguments);
                        return chainQuery(new FilterIterator(iter, criteria))
                    },
                    slice: function(skip, take) {
                        if (take === undefined)
                            take = Number.MAX_VALUE;
                        return chainQuery(new SliceIterator(iter, skip, take))
                    },
                    select: select,
                    groupBy: function(getter, desc) {
                        return chainQuery(new GroupIterator(iter, getter, desc))
                    },
                    aggregate: aggregate,
                    count: function() {
                        if (iter.countable()) {
                            var d = $.Deferred().fail(handleError);
                            try {
                                d.resolve(iter.count())
                            }
                            catch(x) {
                                d.reject(x)
                            }
                            return d.promise()
                        }
                        return aggregate(0, function(count) {
                                return 1 + count
                            })
                    },
                    sum: function(getter) {
                        if (getter)
                            return selectProp(getter).sum();
                        return aggregate(0, function(sum, item) {
                                return sum + item
                            })
                    },
                    min: function(getter) {
                        if (getter)
                            return selectProp(getter).min();
                        return aggregate(function(min, item) {
                                return item < min ? item : min
                            })
                    },
                    max: function(getter) {
                        if (getter)
                            return selectProp(getter).max();
                        return aggregate(function(max, item) {
                                return item > max ? item : max
                            })
                    },
                    avg: function(getter) {
                        if (getter)
                            return selectProp(getter).avg();
                        var count = 0;
                        return aggregate(0, function(sum, item) {
                                count++;
                                return sum + item
                            }, function(sum) {
                                return count ? sum / count : undefined
                            })
                    }
                }
        }
    })(jQuery, DevExpress);
    /*! Module core, file data.query.remote.js */
    (function($, DX, undefined) {
        var data = DX.data,
            queryImpl = data.queryImpl;
        queryImpl.remote = function(url, queryOptions, tasks) {
            tasks = tasks || [];
            queryOptions = queryOptions || {};
            var createTask = function(name, args) {
                    return {
                            name: name,
                            args: args
                        }
                };
            var exec = function(executorTask) {
                    var d = $.Deferred(),
                        adapterFactory,
                        adapter,
                        taskQueue,
                        currentTask;
                    var rejectWithNotify = function(error) {
                            var handler = queryOptions.errorHandler;
                            if (handler)
                                handler(error);
                            data._handleError(error);
                            d.reject(error)
                        };
                    try {
                        adapterFactory = queryOptions.adapter || "odata";
                        if (!$.isFunction(adapterFactory))
                            adapterFactory = data.queryAdapters[adapterFactory];
                        adapter = adapterFactory(queryOptions);
                        taskQueue = [].concat(tasks).concat(executorTask);
                        while (taskQueue.length) {
                            currentTask = taskQueue[0];
                            if (String(currentTask.name) !== "enumerate")
                                if (!adapter[currentTask.name] || adapter[currentTask.name].apply(adapter, currentTask.args) === false)
                                    break;
                            taskQueue.shift()
                        }
                        adapter.exec(url).done(function(result) {
                            if (!taskQueue.length)
                                d.resolve(result);
                            else {
                                var clientChain = queryImpl.array(result, {errorHandler: queryOptions.errorHandler});
                                $.each(taskQueue, function() {
                                    clientChain = clientChain[this.name].apply(clientChain, this.args)
                                });
                                clientChain.done($.proxy(d.resolve, d)).fail($.proxy(d.reject, d))
                            }
                        }).fail(rejectWithNotify)
                    }
                    catch(x) {
                        rejectWithNotify(x)
                    }
                    return d.promise()
                };
            var query = {};
            $.each(["sortBy", "thenBy", "filter", "slice", "select", "groupBy"], function() {
                var name = this;
                query[name] = function() {
                    return queryImpl.remote(url, queryOptions, tasks.concat(createTask(name, arguments)))
                }
            });
            $.each(["count", "min", "max", "sum", "avg", "aggregate", "enumerate"], function() {
                var name = this;
                query[name] = function() {
                    return exec.call(this, createTask(name, arguments))
                }
            });
            return query
        }
    })(jQuery, DevExpress);
    /*! Module core, file data.odata.js */
    (function($, DX, undefined) {
        var data = DX.data,
            Guid = data.Guid;
        var JSON_VERBOSE_MIME_TYPE = "application/json;odata=verbose";
        var ajaxOptionsForRequest = function(request, requestOptions) {
                request = $.extend({
                    method: "get",
                    url: "",
                    params: {},
                    payload: null,
                    headers: {}
                }, request);
                requestOptions = requestOptions || {};
                var beforeSend = requestOptions.beforeSend;
                if (beforeSend)
                    beforeSend(request);
                var method = (request.method || "get").toLowerCase(),
                    isGet = method === "get",
                    useJsonp = isGet && requestOptions.jsonp,
                    params = $.extend({}, request.params),
                    ajaxData = isGet ? params : JSON.stringify(request.payload),
                    qs = !isGet && $.param(params),
                    url = request.url,
                    contentType = !isGet && JSON_VERBOSE_MIME_TYPE;
                if (qs)
                    url += (url.indexOf("?") > -1 ? "&" : "?") + qs;
                if (useJsonp)
                    ajaxData["$format"] = "json";
                return {
                        url: url,
                        data: ajaxData,
                        dataType: useJsonp ? "jsonp" : "json",
                        jsonp: useJsonp && "$callback",
                        type: method,
                        timeout: 30000,
                        headers: request.headers,
                        contentType: contentType,
                        accepts: {json: [JSON_VERBOSE_MIME_TYPE, "text/plain"].join()},
                        xhrFields: {withCredentials: requestOptions.withCredentials}
                    }
            };
        var sendRequest = function(request, requestOptions) {
                var d = $.Deferred();
                $.ajax(ajaxOptionsForRequest(request, requestOptions)).always(function(obj, textStatus) {
                    var tuplet = interpretVerboseJsonFormat(obj, textStatus),
                        error = tuplet.error,
                        data = tuplet.data,
                        nextUrl = tuplet.nextUrl;
                    if (error)
                        d.reject(error);
                    else if (requestOptions.countOnly)
                        d.resolve(tuplet.count);
                    else if (nextUrl)
                        sendRequest({url: nextUrl}, requestOptions).fail($.proxy(d.reject, d)).done(function(nextData) {
                            d.resolve(data.concat(nextData))
                        });
                    else
                        d.resolve(data)
                });
                return d.promise()
            };
        var formatDotNetError = function(errorObj) {
                var message,
                    currentError = errorObj;
                if ("message" in errorObj)
                    if (errorObj.message.value)
                        message = errorObj.message.value;
                    else
                        message = errorObj.message;
                while (currentError = currentError.innererror || currentError.internalexception) {
                    message = currentError.message;
                    if (currentError.internalexception && message.indexOf("inner exception") === -1)
                        break
                }
                return message
            };
        var errorFromResponse = function(obj, textStatus) {
                if (textStatus === "nocontent")
                    return null;
                var httpStatus = 200,
                    message = "Unknown error",
                    innerError,
                    response = obj;
                if (textStatus !== "success") {
                    httpStatus = obj.status;
                    message = data.utils.errorMessageFromXhr(obj, textStatus);
                    try {
                        response = $.parseJSON(obj.responseText)
                    }
                    catch(x) {}
                }
                var errorObj = response && response.error;
                if (errorObj) {
                    message = formatDotNetError(errorObj) || message;
                    if (httpStatus === 200)
                        httpStatus = 500;
                    if (response.error.code)
                        httpStatus = Number(response.error.code);
                    return $.extend(Error(message), {
                            httpStatus: httpStatus,
                            errorDetails: errorObj
                        })
                }
                else if (httpStatus !== 200)
                    return $.extend(Error(message), {httpStatus: httpStatus})
            };
        var interpretVerboseJsonFormat = function(obj, textStatus) {
                var error = errorFromResponse(obj, textStatus);
                if (error)
                    return {error: error};
                if (!$.isPlainObject(obj))
                    return {data: obj};
                var data = obj.d;
                if (!data)
                    return {error: Error("Malformed or unsupported JSON response received")};
                data = data.results || data;
                recognizeDates(data);
                return {
                        data: data,
                        nextUrl: obj.d.__next,
                        count: obj.d.__count
                    }
            };
        var EdmLiteral = DX.Class.inherit({
                ctor: function(value) {
                    this._value = value
                },
                valueOf: function() {
                    return this._value
                }
            });
        var serializeDate = function() {
                var pad = function(part) {
                        part = String(part);
                        if (part.length < 2)
                            part = "0" + part;
                        return part
                    };
                return function(date) {
                        var result = ["datetime'", date.getUTCFullYear(), "-", pad(date.getUTCMonth() + 1), "-", pad(date.getUTCDate())];
                        if (date.getUTCHours() || date.getUTCMinutes() || date.getUTCSeconds() || date.getUTCMilliseconds()) {
                            result.push("T", pad(date.getUTCHours()), ":", pad(date.getUTCMinutes()), ":", pad(date.getUTCSeconds()));
                            if (date.getUTCMilliseconds())
                                result.push(".", date.getUTCMilliseconds())
                        }
                        result.push("'");
                        return result.join("")
                    }
            }();
        var serializePropName = function(propName) {
                if (propName instanceof EdmLiteral)
                    return propName.valueOf();
                return propName.replace(/\./g, "/")
            };
        var serializeValue = function(value) {
                if (value instanceof Date)
                    return serializeDate(value);
                if (value instanceof Guid)
                    return "guid'" + value + "'";
                if (value instanceof EdmLiteral)
                    return value.valueOf();
                if (typeof value === "string")
                    return "'" + value.replace(/'/g, "''") + "'";
                return String(value)
            };
        var serializeKey = function(key) {
                if ($.isPlainObject(key)) {
                    var parts = [];
                    $.each(key, function(k, v) {
                        parts.push(serializePropName(k) + "=" + serializeValue(v))
                    });
                    return parts.join()
                }
                return serializeValue(key)
            };
        var recognizeDates = function(list) {
                $.each(list, function(i, val) {
                    if (val !== null && typeof val === "object")
                        recognizeDates(val);
                    else if (typeof val === "string") {
                        var matches = val.match(/^\/Date\((-?\d+)((\+|-)?(\d+)?)\)\/$/);
                        if (matches)
                            list[i] = new Date(Number(matches[1]) + matches[2] * 60000)
                    }
                })
            };
        var keyConverters = {
                String: function(value) {
                    return value + ""
                },
                Int32: function(value) {
                    return ~~value
                },
                Int64: function(value) {
                    if (value instanceof EdmLiteral)
                        return value;
                    return new EdmLiteral(value + "L")
                },
                Guid: function(value) {
                    if (value instanceof Guid)
                        return value;
                    return new Guid(value)
                }
            };
        var compileCriteria = function() {
                var createBinaryOperationFormatter = function(op) {
                        return function(prop, val, bag) {
                                bag.push(prop, " ", op, " ", val)
                            }
                    };
                var createStringFuncFormatter = function(op, reverse) {
                        return function(prop, val, bag) {
                                if (reverse)
                                    bag.push(op, "(", val, ",", prop, ")");
                                else
                                    bag.push(op, "(", prop, ",", val, ")")
                            }
                    };
                var formatters = {
                        "=": createBinaryOperationFormatter("eq"),
                        "<>": createBinaryOperationFormatter("ne"),
                        ">": createBinaryOperationFormatter("gt"),
                        ">=": createBinaryOperationFormatter("ge"),
                        "<": createBinaryOperationFormatter("lt"),
                        "<=": createBinaryOperationFormatter("le"),
                        startswith: createStringFuncFormatter("startswith"),
                        endswith: createStringFuncFormatter("endswith"),
                        contains: createStringFuncFormatter("substringof", true),
                        notcontains: createStringFuncFormatter("not substringof", true)
                    };
                var compileBinary = function(criteria, bag) {
                        criteria = data.utils.normalizeBinaryCriterion(criteria);
                        formatters[criteria[1]](serializePropName(criteria[0]), serializeValue(criteria[2]), bag)
                    };
                var compileGroup = function(criteria, bag) {
                        var pushAnd = false;
                        $.each(criteria, function() {
                            if ($.isArray(this)) {
                                if (pushAnd)
                                    bag.push(" and ");
                                bag.push("(");
                                compileCore(this, bag);
                                bag.push(")");
                                pushAnd = true
                            }
                            else {
                                bag.push(/and|&/i.test(this) ? " and " : " or ");
                                pushAnd = false
                            }
                        })
                    };
                var compileCore = function(criteria, bag) {
                        if ($.isArray(criteria[0]))
                            compileGroup(criteria, bag);
                        else
                            compileBinary(criteria, bag)
                    };
                return function(criteria) {
                        var bag = [];
                        compileCore(criteria, bag);
                        return bag.join("")
                    }
            }();
        var createODataQueryAdapter = function(queryOptions) {
                var sorting = [],
                    criteria = [],
                    select,
                    skip,
                    take,
                    countQuery;
                var hasSlice = function() {
                        return skip || take !== undefined
                    };
                var sortCore = function(getter, desc, reset) {
                        if (hasSlice() || typeof getter !== "string")
                            return false;
                        if (reset)
                            sorting = [];
                        var rule = serializePropName(getter);
                        if (desc)
                            rule += " desc";
                        sorting.push(rule)
                    };
                var generateExpand = function() {
                        var hash = {};
                        if (queryOptions.expand)
                            $.each($.makeArray(queryOptions.expand), function() {
                                hash[serializePropName(this)] = 1
                            });
                        if (select)
                            $.each(select, function() {
                                var path = this.split(".");
                                if (path.length < 2)
                                    return;
                                path.pop();
                                hash[serializePropName(path.join("."))] = 1
                            });
                        return $.map(hash, function(k, v) {
                                return v
                            }).join() || undefined
                    };
                var requestData = function() {
                        var result = {};
                        if (!countQuery) {
                            if (sorting.length)
                                result["$orderby"] = sorting.join(",");
                            if (skip)
                                result["$skip"] = skip;
                            if (take !== undefined)
                                result["$top"] = take;
                            if (select)
                                result["$select"] = serializePropName(select.join());
                            result["$expand"] = generateExpand()
                        }
                        if (criteria.length)
                            result["$filter"] = compileCriteria(criteria.length < 2 ? criteria[0] : criteria);
                        if (countQuery) {
                            result["$inlinecount"] = "allpages";
                            result["$top"] = 0
                        }
                        return result
                    };
                return {
                        exec: function(url) {
                            return sendRequest({
                                    url: url,
                                    params: $.extend(requestData(), queryOptions && queryOptions.params)
                                }, {
                                    beforeSend: queryOptions.beforeSend,
                                    jsonp: queryOptions.jsonp,
                                    withCredentials: queryOptions.withCredentials,
                                    countOnly: countQuery
                                })
                        },
                        sortBy: function(getter, desc) {
                            return sortCore(getter, desc, true)
                        },
                        thenBy: function(getter, desc) {
                            return sortCore(getter, desc, false)
                        },
                        slice: function(skipCount, takeCount) {
                            if (hasSlice())
                                return false;
                            skip = skipCount;
                            take = takeCount
                        },
                        filter: function(criterion) {
                            if (hasSlice() || $.isFunction(criterion))
                                return false;
                            if (!$.isArray(criterion))
                                criterion = $.makeArray(arguments);
                            if (criteria.length)
                                criteria.push("and");
                            criteria.push(criterion)
                        },
                        select: function(expr) {
                            if (select || $.isFunction(expr))
                                return false;
                            if (!$.isArray(expr))
                                expr = $.makeArray(arguments);
                            select = expr
                        },
                        count: function() {
                            countQuery = true
                        }
                    }
            };
        $.extend(true, data, {
            EdmLiteral: EdmLiteral,
            utils: {odata: {
                    sendRequest: sendRequest,
                    serializePropName: serializePropName,
                    serializeValue: serializeValue,
                    serializeKey: serializeKey,
                    keyConverters: keyConverters
                }},
            queryAdapters: {odata: createODataQueryAdapter}
        })
    })(jQuery, DevExpress);
    /*! Module core, file data.store.abstract.js */
    (function($, DX, undefined) {
        var Class = DX.Class,
            abstract = DX.abstract,
            data = DX.data,
            normalizeSortingInfo = data.utils.normalizeSortingInfo;
        var STORE_CALLBACK_NAMES = ["loading", "loaded", "modifying", "modified", "inserting", "inserted", "updating", "updated", "removing", "removed"];
        var multiLevelGroup = function(query, groupInfo) {
                query = query.groupBy(groupInfo[0].selector);
                if (groupInfo.length > 1)
                    query = query.select(function(g) {
                        return $.extend({}, g, {items: multiLevelGroup(data.query(g.items), groupInfo.slice(1)).toArray()})
                    });
                return query
            };
        data.Store = Class.inherit({
            ctor: function(options) {
                var self = this;
                options = options || {};
                $.each(STORE_CALLBACK_NAMES, function() {
                    var callbacks = self[this] = $.Callbacks();
                    if (this in options)
                        callbacks.add(options[this])
                });
                this._key = options.key;
                this._keyGetter = data.utils.compileGetter(this._key);
                this._errorHandler = options.errorHandler
            },
            customLoadOptions: function() {
                return null
            },
            key: function() {
                return this._key
            },
            keyOf: function(obj) {
                return this._keyGetter(obj)
            },
            _requireKey: function() {
                if (!this._key)
                    throw Error("Key expression is required for this operation");
            },
            load: function(options) {
                var self = this;
                options = options || {};
                this.loading.fire(options);
                return this._loadImpl(options).done(function(result) {
                        self.loaded.fire(result)
                    })
            },
            _loadImpl: function(options) {
                var filter = options.filter,
                    sort = options.sort,
                    select = options.select,
                    group = options.group,
                    skip = options.skip,
                    take = options.take,
                    q = this.createQuery(options);
                if (filter)
                    q = q.filter(filter);
                if (group)
                    group = normalizeSortingInfo(group);
                if (sort) {
                    sort = normalizeSortingInfo(sort);
                    if (group)
                        sort = group.concat(sort);
                    $.each(sort, function(index) {
                        q = q[index ? "thenBy" : "sortBy"](this.selector, this.desc)
                    })
                }
                if (select)
                    q = q.select(select);
                if (group)
                    q = multiLevelGroup(q, group);
                if (take || skip)
                    q = q.slice(skip || 0, take);
                return q.enumerate()
            },
            createQuery: abstract,
            byKey: function(key, extraOptions) {
                return this._addFailHandlers(this._byKeyImpl(key, extraOptions))
            },
            _byKeyImpl: abstract,
            insert: function(values) {
                var self = this;
                self.modifying.fire();
                self.inserting.fire(values);
                return self._addFailHandlers(self._insertImpl(values).done(function(callbackValues, callbackKey) {
                        self.inserted.fire(callbackValues, callbackKey);
                        self.modified.fire()
                    }))
            },
            _insertImpl: abstract,
            update: function(key, values) {
                var self = this;
                self.modifying.fire();
                self.updating.fire(key, values);
                return self._addFailHandlers(self._updateImpl(key, values).done(function(callbackKey, callbackValues) {
                        self.updated.fire(callbackKey, callbackValues);
                        self.modified.fire()
                    }))
            },
            _updateImpl: abstract,
            remove: function(key) {
                var self = this;
                self.modifying.fire();
                self.removing.fire(key);
                return self._addFailHandlers(self._removeImpl(key).done(function(callbackKey) {
                        self.removed.fire(callbackKey);
                        self.modified.fire()
                    }))
            },
            _removeImpl: abstract,
            _addFailHandlers: function(deferred) {
                return deferred.fail(this._errorHandler, data._handleError)
            }
        })
    })(jQuery, DevExpress);
    /*! Module core, file data.store.array.js */
    (function($, DX, undefined) {
        var data = DX.data,
            Guid = data.Guid;
        var trivialPromise = function(_) {
                var d = $.Deferred();
                return d.resolve.apply(d, arguments).promise()
            };
        var rejectedPromise = function(_) {
                var d = $.Deferred();
                return d.reject.apply(d, arguments).promise()
            };
        data.ArrayStore = data.Store.inherit({
            ctor: function(options) {
                if ($.isArray(options))
                    options = {data: options};
                else
                    options = options || {};
                this.callBase(options);
                this._array = options.data || []
            },
            createQuery: function() {
                return data.query(this._array, {errorHandler: this._errorHandler})
            },
            _byKeyImpl: function(key) {
                return trivialPromise(this._array[this._indexByKey(key)])
            },
            _insertImpl: function(values) {
                var keyExpr = this.key(),
                    keyValue,
                    obj = {};
                $.extend(obj, values);
                if (keyExpr) {
                    keyValue = this.keyOf(obj);
                    if (keyValue === undefined || typeof keyValue === "object" && $.isEmptyObject(keyValue)) {
                        if ($.isArray(keyExpr))
                            throw Error("Compound keys cannot be auto-generated");
                        keyValue = obj[keyExpr] = String(new Guid)
                    }
                    else if (this._array[this._indexByKey(keyValue)] !== undefined)
                        return rejectedPromise(Error("Attempt to insert an item with the duplicate key"))
                }
                else
                    keyValue = obj;
                this._array.push(obj);
                return trivialPromise(values, keyValue)
            },
            _updateImpl: function(key, values) {
                var target;
                if (this.key()) {
                    var index = this._indexByKey(key);
                    if (index < 0)
                        return rejectedPromise(Error("Data item not found"));
                    target = this._array[index]
                }
                else
                    target = key;
                $.extend(true, target, values);
                return trivialPromise(key, values)
            },
            _removeImpl: function(key) {
                var index = this._indexByKey(key);
                if (index > -1)
                    this._array.splice(index, 1);
                return trivialPromise(key)
            },
            _indexByKey: function(key) {
                for (var i = 0, arrayLength = this._array.length; i < arrayLength; i++)
                    if (data.utils.keysEqual(this.key(), this._keyGetter(this._array[i]), key))
                        return i;
                return -1
            }
        })
    })(jQuery, DevExpress);
    /*! Module core, file data.store.local.js */
    (function($, DX, undefined) {
        var Class = DX.Class,
            abstract = DX.abstract,
            data = DX.data;
        var LocalStoreBackend = Class.inherit({
                ctor: function(store, storeOptions) {
                    this._store = store;
                    this._dirty = false;
                    var immediate = this._immediate = storeOptions.immediate;
                    var flushInterval = Math.max(100, storeOptions.flushInterval || 10 * 1000);
                    if (!immediate) {
                        var saveProxy = $.proxy(this.save, this);
                        setInterval(saveProxy, flushInterval);
                        $(window).on("beforeunload", saveProxy);
                        if (window.cordova)
                            document.addEventListener("pause", saveProxy, false)
                    }
                },
                notifyChanged: function() {
                    this._dirty = true;
                    if (this._immediate)
                        this.save()
                },
                load: function() {
                    this._store._array = this._loadImpl();
                    this._dirty = false
                },
                save: function() {
                    if (!this._dirty)
                        return;
                    this._saveImpl(this._store._array);
                    this._dirty = false
                },
                _loadImpl: abstract,
                _saveImpl: abstract
            });
        var DomLocalStoreBackend = LocalStoreBackend.inherit({
                ctor: function(store, storeOptions) {
                    this.callBase(store, storeOptions);
                    var name = storeOptions.name;
                    if (!name)
                        throw Error("Name is required");
                    this._key = "dx-data-localStore-" + name
                },
                _loadImpl: function() {
                    var raw = localStorage.getItem(this._key);
                    if (raw)
                        return JSON.parse(raw);
                    return []
                },
                _saveImpl: function(array) {
                    if (!array.length)
                        localStorage.removeItem(this._key);
                    else
                        localStorage.setItem(this._key, JSON.stringify(array))
                }
            });
        var localStoreBackends = {dom: DomLocalStoreBackend};
        data.LocalStore = data.ArrayStore.inherit({
            ctor: function(options) {
                if (typeof options === "string")
                    options = {name: options};
                else
                    options = options || {};
                this.callBase(options);
                this._backend = new localStoreBackends[options.backend || "dom"](this, options);
                this._backend.load()
            },
            clear: function() {
                this._array = [];
                this._backend.notifyChanged()
            },
            _insertImpl: function(values) {
                var b = this._backend;
                return this.callBase(values).done($.proxy(b.notifyChanged, b))
            },
            _updateImpl: function(key, values) {
                var b = this._backend;
                return this.callBase(key, values).done($.proxy(b.notifyChanged, b))
            },
            _removeImpl: function(key) {
                var b = this._backend;
                return this.callBase(key).done($.proxy(b.notifyChanged, b))
            }
        })
    })(jQuery, DevExpress);
    /*! Module core, file data.store.odata.js */
    (function($, DX, undefined) {
        var Class = DX.Class,
            data = DX.data,
            odataUtils = data.utils.odata;
        var escapeServiceOperationParams = function(params) {
                if (!params)
                    return params;
                var result = {};
                $.each(params, function(k, v) {
                    result[k] = odataUtils.serializeValue(v)
                });
                return result
            };
        var convertSimpleKey = function(keyType, keyValue) {
                var converter = odataUtils.keyConverters[keyType];
                if (!converter)
                    throw Error("Unknown key type: " + keyType);
                return converter(keyValue)
            };
        var SharedMethods = {
                _extractServiceOptions: function(options) {
                    options = options || {};
                    this._url = String(options.url).replace(/\/+$/, "");
                    this._beforeSend = options.beforeSend;
                    this._jsonp = options.jsonp;
                    this._withCredentials = options.withCredentials
                },
                _sendRequest: function(url, method, params, payload) {
                    return odataUtils.sendRequest({
                            url: url,
                            method: method,
                            params: params || {},
                            payload: payload
                        }, {
                            beforeSend: this._beforeSend,
                            jsonp: this._jsonp,
                            withCredentials: this._withCredentials
                        })
                }
            };
        var ODataStore = data.Store.inherit({
                ctor: function(options) {
                    this.callBase(options);
                    this._extractServiceOptions(options);
                    this._name = options.name;
                    this._keyType = options.keyType
                },
                customLoadOptions: function() {
                    return ["expand", "customQueryParams"]
                },
                _byKeyImpl: function(key, extraOptions) {
                    var params = {};
                    if (extraOptions)
                        if (extraOptions.expand)
                            params["$expand"] = $.map($.makeArray(extraOptions.expand), odataUtils.serializePropName).join();
                    return this._sendRequest(this._byKeyUrl(key), "GET", params)
                },
                createQuery: function(loadOptions) {
                    loadOptions = loadOptions || {};
                    return data.query(this._url, {
                            beforeSend: this._beforeSend,
                            errorHandler: this._errorHandler,
                            jsonp: this._jsonp,
                            withCredentials: this._withCredentials,
                            params: escapeServiceOperationParams(loadOptions.customQueryParams),
                            expand: loadOptions.expand
                        })
                },
                _insertImpl: function(values) {
                    this._requireKey();
                    var self = this,
                        d = $.Deferred();
                    $.when(this._sendRequest(this._url, "POST", null, values)).done(function(serverResponse) {
                        d.resolve(values, self._keyGetter(serverResponse))
                    }).fail($.proxy(d.reject, d));
                    return d.promise()
                },
                _updateImpl: function(key, values) {
                    var d = $.Deferred();
                    $.when(this._sendRequest(this._byKeyUrl(key), "MERGE", null, values)).done(function() {
                        d.resolve(key, values)
                    }).fail($.proxy(d.reject, d));
                    return d.promise()
                },
                _removeImpl: function(key) {
                    var d = $.Deferred();
                    $.when(this._sendRequest(this._byKeyUrl(key), "DELETE")).done(function() {
                        d.resolve(key)
                    }).fail($.proxy(d.reject, d));
                    return d.promise()
                },
                _byKeyUrl: function(key) {
                    var keyType = this._keyType;
                    if ($.isPlainObject(keyType))
                        $.each(keyType, function(subKeyName, subKeyType) {
                            key[subKeyName] = convertSimpleKey(subKeyType, key[subKeyName])
                        });
                    else if (keyType)
                        key = convertSimpleKey(keyType, key);
                    return this._url + "(" + encodeURIComponent(odataUtils.serializeKey(key)) + ")"
                }
            }).include(SharedMethods);
        var ODataContext = Class.inherit({
                ctor: function(options) {
                    var self = this;
                    self._extractServiceOptions(options);
                    self._errorHandler = options.errorHandler;
                    $.each(options.entities || [], function(entityAlias, entityOptions) {
                        self[entityAlias] = new ODataStore($.extend({}, options, {url: self._url + "/" + encodeURIComponent(entityOptions.name || entityAlias)}, entityOptions))
                    })
                },
                get: function(operationName, params) {
                    return this.invoke(operationName, params, "GET")
                },
                invoke: function(operationName, params, httpMethod) {
                    httpMethod = httpMethod || "POST";
                    var d = $.Deferred();
                    $.when(this._sendRequest(this._url + "/" + encodeURIComponent(operationName), httpMethod, escapeServiceOperationParams(params))).done(function(r) {
                        if (r && operationName in r)
                            r = r[operationName];
                        d.resolve(r)
                    }).fail([this._errorHandler, data._handleError, $.proxy(d.reject, d)]);
                    return d.promise()
                },
                objectLink: function(entityAlias, key) {
                    var store = this[entityAlias];
                    if (!store)
                        throw Error("Unknown entity name or alias: " + entityAlias);
                    return {__metadata: {uri: store._byKeyUrl(key)}}
                }
            }).include(SharedMethods);
        $.extend(data, {
            ODataStore: ODataStore,
            ODataContext: ODataContext
        })
    })(jQuery, DevExpress);
    /*! Module core, file data.store.rest.js */
    (function($, DX, undefined) {
        var data = DX.data;
        function createAjaxFailureHandler(deferred) {
            return function(xhr, textStatus) {
                    if (!xhr || !xhr.getResponseHeader)
                        deferred.reject.apply(deferred, arguments);
                    else
                        deferred.reject(Error(data.utils.errorMessageFromXhr(xhr, textStatus)))
                }
        }
        function operationCustomizerPropName(operationName) {
            return "_customize" + DX.inflector.camelize(operationName, true)
        }
        function pathPropName(operationName) {
            return "_" + operationName + "Path"
        }
        data.RestStore = data.Store.inherit({
            ctor: function(options) {
                var self = this;
                self.callBase(options);
                options = options || {};
                self._url = String(options.url).replace(/\/+$/, "");
                self._jsonp = options.jsonp;
                self._withCredentials = options.withCredentials;
                $.each(["Load", "Insert", "Update", "Remove", "ByKey", "Operation"], function() {
                    var value = options["customize" + this];
                    if (value)
                        self[operationCustomizerPropName(this)] = value
                });
                $.each(["load", "insert", "update", "remove", "byKey"], function() {
                    var value = options[this + "Path"];
                    if (value)
                        self[pathPropName(this)] = value
                })
            },
            _loadImpl: function(options) {
                var d = $.Deferred(),
                    ajaxOptions = {
                        url: this._formatUrlNoKey("load"),
                        type: "GET"
                    };
                $.when(this._createAjax(ajaxOptions, "load", options)).done($.proxy(d.resolve, d)).fail(createAjaxFailureHandler(d));
                return this._addFailHandlers(d.promise())
            },
            createQuery: function() {
                throw Error("Not supported");
            },
            _insertImpl: function(values) {
                var d = $.Deferred(),
                    self = this,
                    ajaxOptions = {
                        url: this._formatUrlNoKey("insert"),
                        type: "POST",
                        contentType: "application/json",
                        data: JSON.stringify(values)
                    };
                $.when(this._createAjax(ajaxOptions, "insert")).done(function(serverResponse) {
                    d.resolve(values, self.key() && self._keyGetter(serverResponse))
                }).fail(createAjaxFailureHandler(d));
                return d.promise()
            },
            _updateImpl: function(key, values) {
                var d = $.Deferred(),
                    ajaxOptions = {
                        url: this._formatUrlWithKey("update", key),
                        type: "PUT",
                        contentType: "application/json",
                        data: JSON.stringify(values)
                    };
                $.when(this._createAjax(ajaxOptions, "update")).done(function() {
                    d.resolve(key, values)
                }).fail(createAjaxFailureHandler(d));
                return d.promise()
            },
            _removeImpl: function(key) {
                var d = $.Deferred(),
                    ajaxOptions = {
                        url: this._formatUrlWithKey("remove", key),
                        type: "DELETE"
                    };
                $.when(this._createAjax(ajaxOptions, "remove")).done(function() {
                    d.resolve(key)
                }).fail(createAjaxFailureHandler(d));
                return d.promise()
            },
            _byKeyImpl: function(key) {
                var d = $.Deferred(),
                    ajaxOptions = {
                        url: this._formatUrlWithKey("byKey", key),
                        type: "GET"
                    };
                $.when(this._createAjax(ajaxOptions, "byKey")).done(function(data) {
                    d.resolve(data)
                }).fail(createAjaxFailureHandler(d));
                return d.promise()
            },
            _createAjax: function(ajaxOptions, operationName, extra) {
                var customizationFunc,
                    customizationResult;
                function isDeferred(obj) {
                    return "done" in obj && "fail" in obj
                }
                if (this._jsonp && ajaxOptions.type === "GET")
                    ajaxOptions.dataType = "jsonp";
                else
                    $.extend(true, ajaxOptions, {xhrFields: {withCredentials: this._withCredentials}});
                customizationFunc = this[operationCustomizerPropName("operation")];
                if (customizationFunc) {
                    customizationResult = customizationFunc(ajaxOptions, operationName, extra);
                    if (customizationResult) {
                        if (isDeferred(customizationResult))
                            return customizationResult;
                        ajaxOptions = customizationResult
                    }
                }
                customizationFunc = this[operationCustomizerPropName(operationName)];
                if (customizationFunc) {
                    customizationResult = customizationFunc(ajaxOptions, extra);
                    if (customizationResult) {
                        if (isDeferred(customizationResult))
                            return customizationResult;
                        ajaxOptions = customizationResult
                    }
                }
                return $.ajax(ajaxOptions)
            },
            _formatUrlNoKey: function(operationName) {
                var url = this._url,
                    path = this[pathPropName(operationName)];
                if (!path)
                    return url;
                if ($.isFunction(path))
                    return path(url);
                return url + "/" + path
            },
            _formatUrlWithKey: function(operationName, key) {
                var url = this._url,
                    path = this[pathPropName(operationName)];
                if (!path)
                    return url + "/" + encodeURIComponent(key);
                if ($.isFunction(path))
                    return path(url, key);
                return url + "/" + path + "/" + encodeURIComponent(key)
            }
        })
    })(jQuery, DevExpress);
    /*! Module core, file data.store.simple.js */
    (function($, DX, undefined) {
        var data = DX.data;
        function operationCustomizerPropName(operationName) {
            return "_customize" + DX.inflector.camelize(operationName, true)
        }
        function pathPropName(operationName) {
            return "_" + operationName + "Path"
        }
        data.SimpleStore = data.Store.inherit({
            ctor: function(options) {
                var self = this;
                self.callBase(options);
                options = options || {};
                self.changed = options.changed;
                self.userLoadCallback = options.load;
                self.userLookupCallback = options.lookup
            },
            _loadImpl: function(loadOptions) {
                if (!this.userLoadCallback)
                    throw new Error('Load callback was not defined');
                var loadOptions2 = {refresh: loadOptions.refresh};
                loadOptions2.searchString = loadOptions.searchString;
                var result = this.userLoadCallback(loadOptions2);
                if (!result)
                    result = (new $.Deferred).resolve([]);
                if ($.isArray(result))
                    result = (new $.Deferred).resolve(result);
                return result
            },
            lookup: function(key, lookupExpression, lookupGetter) {
                if (!this.userLookupCallback)
                    throw new Error('Lookup callback was not defined');
                var result = this.userLookupCallback(key, lookupExpression, lookupGetter);
                if ($.isArray(result))
                    result = result[0];
                if (!result)
                    result = (new $.Deferred).resolve([]);
                if (!result.done)
                    result = (new $.Deferred).resolve(result);
                return result
            }
        })
    })(jQuery, DevExpress);
    /*! Module core, file data.dataSource.js */
    (function($, DX, undefined) {
        var data = DX.data,
            Class = DX.Class;
        var LOCAL_KEY_PROP = "__key__";
        var emptyPromise = $.Deferred().resolve([]).promise();
        var DataSource = Class.inherit({
                ctor: function(options) {
                    options = options || {};
                    var store = options.store;
                    if ($.isArray(store))
                        store = new data.ArrayStore(store);
                    this._store = store;
                    this._storeLoadOptions = this._extractLoadOptions(options);
                    this._mapFunc = options.map;
                    this._postProcessFunc = options.postProcess;
                    this._pageIndex = 0;
                    this._pageSize = options.pageSize !== undefined ? options.pageSize : 20;
                    this._items = [];
                    this._updateMode = options.updateMode || "item";
                    this._isLoaded = false;
                    this._preferSync = options._preferSync;
                    this._paginate = options.paginate;
                    if (this._paginate === undefined)
                        this._paginate = !this._isGrouped();
                    this._isLastPage = !this._paginate;
                    this.changed = $.Callbacks();
                    this.loadError = $.Callbacks();
                    store.updated.add(this._storeUpdatedHandler = $.proxy(this._handleStoreUpdated, this));
                    store.inserted.add(this._storeInsertedHandler = $.proxy(this._handleStoreInserted, this));
                    store.removed.add(this._storeRemovedHandler = $.proxy(this._handleStoreRemoved, this));
                    this._customizeFilters = $.Callbacks()
                },
                dispose: function() {
                    this.changed.empty();
                    this.loadError.empty();
                    this._store.updated.remove(this._storeUpdatedHandler);
                    delete this._storeUpdatedHandler;
                    this._store.inserted.remove(this._storeInsertedHandler);
                    delete this._storeInsertedHandler;
                    this._store.removed.remove(this._storeRemovedHandler);
                    delete this._storeRemovedHandler;
                    delete this._store;
                    this._disposed = true
                },
                _extractLoadOptions: function(options) {
                    var result = {},
                        names = ["sort", "filter", "select", "group"],
                        customNames = this._store.customLoadOptions();
                    if (customNames)
                        names = names.concat(customNames);
                    $.each(names, function() {
                        result[this] = options[this]
                    });
                    return result
                },
                loadOptions: function() {
                    return this._storeLoadOptions
                },
                _accessStoreLoadOption: function(name, value) {
                    var options = this._storeLoadOptions;
                    if (arguments.length < 2)
                        return options[name];
                    options[name] = value;
                    this.reload()
                },
                filter: function(expr) {
                    if (!arguments.length)
                        return this._accessStoreLoadOption("filter");
                    if (expr && !$.isArray(expr))
                        expr = $.makeArray(arguments);
                    this._accessStoreLoadOption("filter", expr)
                },
                clearFilter: function() {
                    this.filter(null)
                },
                sortBy: function(expr) {
                    if (arguments.length > 1)
                        expr = {
                            selector: arguments[0],
                            desc: arguments[1]
                        };
                    this._accessStoreLoadOption("sort", expr)
                },
                clearSort: function() {
                    this.sortBy(null)
                },
                store: function() {
                    return this._store
                },
                key: function() {
                    return this._store && this._store.key()
                },
                _isGrouped: function() {
                    return !!this._storeLoadOptions.group
                },
                _assignPageIndex: function(value) {
                    if (this._pageIndex === value)
                        return;
                    this._pageIndex = value;
                    this.load()
                },
                reload: function(options) {
                    this._pageIndex = 0;
                    this._isLastPage = !this._paginate;
                    return this._loadCore(options)
                },
                load: function(options) {
                    return this._loadCore(options)
                },
                isLoaded: function() {
                    return this._isLoaded
                },
                lookup: function(options) {
                    var d = new $.Deferred,
                        self = this,
                        key = options.key;
                    options.lookupExpression = options.lookupExpression || self.key();
                    if (this._store.lookup)
                        this._store.lookup(key).done(function(item) {
                            if (self._disposed)
                                return;
                            var transformed = self._transformLoadedData(item);
                            d.resolve(transformed[0])
                        });
                    else if (options.lookupExpression && options.lookupExpression === self.key())
                        this._loadSingleByKey(key).done(function(item) {
                            d.resolve(item)
                        });
                    else {
                        var newDataSource = self._store.toDataSource();
                        newDataSource.load({
                            searchString: key,
                            searchMethod: "=",
                            searchField: options.lookupExpression,
                            silent: true
                        }).done(function() {
                            if (self._disposed)
                                return;
                            var items = newDataSource.items();
                            var transformed = self._transformLoadedData(items);
                            d.resolve(transformed[0])
                        }).always(function() {
                            newDataSource.dispose()
                        })
                    }
                    return d
                },
                nextPage: function(append) {
                    append = append === undefined ? true : append;
                    if (this._isLastPage)
                        return emptyPromise;
                    this._pageIndex++;
                    var options = {append: append};
                    $.extend(options, this._searchCondition);
                    return this._loadCore(options)
                },
                _loadCore: function(options) {
                    options = options || {};
                    var self = this,
                        d = $.Deferred(),
                        errorCallback = self.loadError,
                        loadOptions = $.extend(true, {}, self._storeLoadOptions),
                        localFilter;
                    if (!this.userDataSource && (options.searchField || loadOptions.searchFilter)) {
                        if (loadOptions.filter && !$.isArray(loadOptions.filter[0]))
                            loadOptions.filter = [loadOptions.filter];
                        loadOptions.filter = loadOptions.filter || [];
                        if (options.searchField)
                            localFilter = [options.searchField, options.searchMethod || "contains", options.searchString];
                        else
                            localFilter = loadOptions.searchFilter;
                        loadOptions.filter.push(localFilter);
                        self._storeLoadOptions.searchFilter = localFilter
                    }
                    if (this._paginate)
                        if (self._pageSize)
                            $.extend(loadOptions, {
                                skip: self._pageIndex * self._pageSize,
                                take: self._pageSize
                            });
                    $.extend(loadOptions, {
                        refresh: !self._paginate || self._pageIndex === 0,
                        searchString: options.searchString
                    });
                    var loadTask = function() {
                            if (self._disposed)
                                return undefined;
                            return $.when(self._store.load(loadOptions)).done(function(data) {
                                    var processData = function() {
                                            if (self._disposed)
                                                return;
                                            var items = self._items;
                                            data = self._transformLoadedData(data);
                                            if (!options.append)
                                                items.splice(0, items.length);
                                            items.push.apply(items, data);
                                            if (!data.length || !self._paginate || self._pageSize && data.length < self._pageSize)
                                                self._isLastPage = true;
                                            self._isLoaded = true;
                                            if (!options.silent)
                                                self.changed.fire();
                                            d.resolve(data)
                                        };
                                    if (self._preferSync)
                                        processData();
                                    else
                                        DX.utils.executeAsync(processData)
                                }).fail($.proxy(d.reject, d))
                        };
                    if (DataSourceLoadLock.locked())
                        DataSourceLoadLock.addTask(loadTask);
                    else
                        loadTask();
                    return d.promise().fail($.proxy(errorCallback.fire, errorCallback))
                },
                _loadSingleByKey: function(key) {
                    var self = this,
                        d = $.Deferred();
                    if (!self._disposed)
                        $.when(self._store.byKey(key)).done(function(item) {
                            if (self._disposed)
                                return;
                            var transformed = self._transformLoadedData(item);
                            d.resolve(transformed[0])
                        });
                    return d.promise()
                },
                _transformLoadedData: function(data) {
                    var self = this,
                        result;
                    result = $.map($.makeArray(data), function(item, index) {
                        var keyValue = self._store.keyOf(item),
                            transformed;
                        if (self._mapFunc)
                            transformed = self._mapFunc(item, index);
                        else if (typeof item === "object")
                            transformed = $.extend({}, item);
                        else
                            transformed = item;
                        if (typeof item === "object")
                            transformed[LOCAL_KEY_PROP] = keyValue;
                        return transformed
                    });
                    if (self._postProcessFunc)
                        result = self._postProcessFunc(result);
                    return result
                },
                _localIndexByKey: function(key) {
                    var items = this._items,
                        len = items.length,
                        keyExpr = this._store.key(),
                        itemKey;
                    for (var i = 0; i < len; i++) {
                        itemKey = items[i][LOCAL_KEY_PROP];
                        if (data.utils.keysEqual(keyExpr, itemKey, key))
                            return i
                    }
                    return -1
                },
                _handleStoreUpdated: function(key) {
                    var self = this;
                    switch (self._updateMode) {
                        case"full":
                            this.reload();
                            break;
                        case"item":
                            if (self._isGrouped())
                                return;
                            var localIndex = this._localIndexByKey(key);
                            if (localIndex < 0)
                                return;
                            self._loadSingleByKey(key).done(function(item) {
                                self._items.splice(localIndex, 1, item);
                                self.changed.fire()
                            });
                            break
                    }
                },
                _handleStoreInserted: function(_, key) {
                    var self = this;
                    switch (self._updateMode) {
                        case"full":
                            self.reload();
                            break;
                        case"item":
                            if (self._isGrouped())
                                return;
                            self._loadSingleByKey(key).done(function(item) {
                                self._items.push(item);
                                self.changed.fire()
                            });
                            break
                    }
                },
                _handleStoreRemoved: function(key) {
                    var self = this;
                    switch (self._updateMode) {
                        case"full":
                            self.reload();
                            break;
                        case"item":
                            if (self._isGrouped())
                                return;
                            var localIndex = this._localIndexByKey(key);
                            if (localIndex < 0)
                                return;
                            self._items.splice(localIndex, 1);
                            self.changed.fire();
                            break
                    }
                }
            });
        var SimpleDataSource = DataSource.inherit({
                items: function() {
                    return this._items
                },
                pageIndex: function(value) {
                    if (value === undefined)
                        return this._pageIndex;
                    this._assignPageIndex(value)
                },
                isLastPage: function() {
                    return this._isLastPage
                }
            });
        var KoDataSource = DataSource.inherit({
                ctor: function(store, options) {
                    this.callBase(store, options);
                    var pinger = ko.observable();
                    this.changed.add(function() {
                        pinger.notifySubscribers()
                    });
                    this.items = ko.computed(function() {
                        pinger();
                        return this._items
                    }, this);
                    this.pageIndex = ko.computed({
                        read: function() {
                            pinger();
                            return this._pageIndex
                        },
                        write: function(value) {
                            this._assignPageIndex(value)
                        }
                    }, this);
                    this.isLastPage = ko.computed(function() {
                        pinger();
                        return this._isLastPage
                    }, this)
                },
                dispose: function() {
                    this.callBase();
                    this.items.dispose();
                    this.pageIndex.dispose();
                    this.isLastPage.dispose()
                }
            });
        data.Store.redefine({toDataSource: function(options, impl) {
                var dataSource;
                options = $.extend({store: this}, options);
                if ($.isFunction(impl))
                    dataSource = new impl(options);
                else
                    switch (impl) {
                        case"simple":
                            dataSource = new SimpleDataSource(options);
                            break;
                        default:
                            dataSource = new KoDataSource(options)
                    }
                if (dataSource && this.changed && $.isFunction(this.changed.add))
                    this.changed.add(function() {
                        dataSource.reload()
                    });
                if (options.userDataSource)
                    dataSource.userDataSource = options.userDataSource;
                return dataSource
            }});
        var createDataSource = function(dataSourceOptions) {
                var defaultDataSourceType = window.ko ? KoDataSource : SimpleDataSource;
                return new DX.data.SimpleStore(dataSourceOptions).toDataSource({
                        pageSize: null,
                        userDataSource: true
                    }, defaultDataSourceType)
            };
        var DataSourceLoadLock = new function() {
                var delayedLoadTasks,
                    lockCount;
                var obtain = function() {
                        lockCount++
                    };
                var release = function() {
                        lockCount--;
                        if (lockCount < 1) {
                            $.each(delayedLoadTasks, function() {
                                DX.enqueue(this)
                            });
                            delayedLoadTasks = []
                        }
                    };
                var reset = function() {
                        lockCount = 0;
                        delayedLoadTasks = []
                    };
                reset();
                return {
                        obtain: obtain,
                        release: release,
                        reset: reset,
                        locked: function() {
                            return lockCount > 0
                        },
                        addTask: function(task) {
                            delayedLoadTasks.push(task)
                        }
                    }
            };
        $.extend(true, data, {
            DataSource: DataSource,
            KoDataSource: KoDataSource,
            SimpleDataSource: SimpleDataSource,
            createDataSource: createDataSource,
            utils: {DataSourceLoadLock: DataSourceLoadLock}
        })
    })(jQuery, DevExpress);
    /*! Module core, file social.js */
    DevExpress.social = {};
    /*! Module core, file facebook.js */
    (function($, DX, undefined) {
        var social = DX.social;
        var location = window.location,
            navigator = window.navigator,
            encodeURIComponent = window.encodeURIComponent,
            decodeURIComponent = window.decodeURIComponent,
            iosStandaloneMode = navigator.standalone,
            cordovaMode = false;
        if (window.cordova)
            $(document).on("deviceready", function() {
                cordovaMode = true
            });
        var ACCESS_TOKEN_KEY = "dx-facebook-access-token",
            IOS_STANDALONE_STEP1_KEY = "dx-facebook-step1",
            IOS_STANDALONE_STEP2_KEY = "dx-facebook-step2";
        var accessToken = null,
            expires = null,
            connectionChanged = $.Callbacks();
        var pendingLoginRedirectUrl;
        var isConnected = function() {
                return !!accessToken
            };
        var getAccessTokenObject = function() {
                return {
                        accessToken: accessToken,
                        expiresIn: accessToken ? expires : 0
                    }
            };
        var FB = social.Facebook = {
                loginRedirectUrl: "FacebookLoginCallback.html",
                connectionChanged: connectionChanged,
                isConnected: isConnected,
                getAccessTokenObject: getAccessTokenObject,
                jsonp: false
            };
        var login = function(appId, options) {
                options = options || {};
                if (cordovaMode)
                    pendingLoginRedirectUrl = "https://www.facebook.com/connect/login_success.html";
                else
                    pendingLoginRedirectUrl = formatLoginRedirectUrl();
                var scope = (options.permissions || []).join(),
                    url = "https://www.facebook.com/dialog/oauth?display=popup&client_id=" + appId + "&redirect_uri=" + encodeURIComponent(pendingLoginRedirectUrl) + "&scope=" + encodeURIComponent(scope) + "&response_type=token";
                if (iosStandaloneMode)
                    putData(IOS_STANDALONE_STEP1_KEY, location.href);
                if (cordovaMode)
                    startLogin_cordova(url);
                else
                    startLogin_browser(url)
            };
        var formatLoginRedirectUrl = function() {
                var pathSegments = location.pathname.split(/\//g);
                pathSegments.pop();
                pathSegments.push(FB.loginRedirectUrl);
                return location.protocol + "//" + location.host + pathSegments.join("/")
            };
        var startLogin_browser = function(loginUrl) {
                var width = 512,
                    height = 320,
                    left = (screen.width - width) / 2,
                    top = (screen.height - height) / 2;
                window.open(loginUrl, null, "width=" + width + ",height=" + height + ",toolbar=0,scrollbars=0,status=0,resizable=0,menuBar=0,left=" + left + ",top=" + top)
            };
        var startLogin_cordova = function(loginUrl) {
                var ref = window.open(loginUrl, "_blank");
                ref.addEventListener('exit', function(event) {
                    pendingLoginRedirectUrl = null
                });
                ref.addEventListener('loadstop', function(event) {
                    var url = unescape(event.url);
                    if (url.indexOf(pendingLoginRedirectUrl) === 0) {
                        ref.close();
                        _processLoginRedirectUrl(url)
                    }
                })
            };
        var handleLoginRedirect = function() {
                var opener = window.opener;
                if (iosStandaloneMode) {
                    putData(IOS_STANDALONE_STEP2_KEY, location.href);
                    location.href = getData(IOS_STANDALONE_STEP1_KEY)
                }
                else if (opener && opener.DevExpress) {
                    opener.DevExpress.social.Facebook._processLoginRedirectUrl(location.href);
                    window.close()
                }
            };
        var _processLoginRedirectUrl = function(url) {
                var params = parseUrlFragment(url);
                expires = params.expires_in;
                changeToken(params.access_token);
                pendingLoginRedirectUrl = null
            };
        var parseUrlFragment = function(url) {
                var hash = url.split("#")[1];
                if (!hash)
                    return {};
                var pairs = hash.split(/&/g),
                    result = {};
                $.each(pairs, function(i) {
                    var splitPair = this.split("=");
                    result[splitPair[0]] = decodeURIComponent(splitPair[1])
                });
                return result
            };
        var logout = function() {
                changeToken(null)
            };
        var changeToken = function(value) {
                if (value === accessToken)
                    return;
                accessToken = value;
                putData(ACCESS_TOKEN_KEY, value);
                connectionChanged.fire(!!value)
            };
        var api = function(resource, method, params) {
                if (!isConnected())
                    throw Error("Not connected");
                if (typeof method !== "string") {
                    params = method;
                    method = undefined
                }
                method = (method || "get").toLowerCase();
                var d = $.Deferred();
                var args = arguments;
                $.ajax({
                    url: "https://graph.facebook.com/" + resource,
                    type: method,
                    data: $.extend({access_token: accessToken}, params),
                    dataType: FB.jsonp && method === "get" ? "jsonp" : "json"
                }).done(function(response) {
                    response = response || simulateErrorResponse();
                    if (response.error)
                        d.reject(response.error);
                    else
                        d.resolve(response)
                }).fail(function(xhr) {
                    var response;
                    try {
                        response = $.parseJSON(xhr.responseText);
                        var tries = args[3] || 0;
                        if (tries++ < 3 && response.error.code == 190 && response.error.error_subcode == 466) {
                            setTimeout(function() {
                                api(resource, method, params, tries).done(function(result) {
                                    d.resolve(result)
                                }).fail(function(error) {
                                    d.reject(error)
                                })
                            }, 500);
                            return
                        }
                    }
                    catch(x) {
                        response = simulateErrorResponse()
                    }
                    d.reject(response.error)
                });
                return d.promise()
            };
        var simulateErrorResponse = function() {
                return {error: {message: "Unknown error"}}
            };
        var ensureStorageBackend = function() {
                if (!hasStorageBackend())
                    throw Error("HTML5 sessionStorage or jQuery.cookie plugin is required");
            };
        var hasStorageBackend = function() {
                return !!($.cookie || window.sessionStorage)
            };
        var putData = function(key, data) {
                ensureStorageBackend();
                data = JSON.stringify(data);
                if (window.sessionStorage)
                    if (data === null)
                        sess.removeItem(key);
                    else
                        sessionStorage.setItem(key, data);
                else
                    $.cookie(key, data)
            };
        var getData = function(key) {
                ensureStorageBackend();
                try {
                    return JSON.parse(window.sessionStorage ? sessionStorage.getItem(key) : $.cookie(key))
                }
                catch(x) {
                    return null
                }
            };
        if (hasStorageBackend())
            accessToken = getData(ACCESS_TOKEN_KEY);
        if (iosStandaloneMode) {
            var url = getData(IOS_STANDALONE_STEP2_KEY);
            if (url) {
                _processLoginRedirectUrl(url);
                putData(IOS_STANDALONE_STEP1_KEY, null);
                putData(IOS_STANDALONE_STEP2_KEY, null)
            }
        }
        $.extend(FB, {
            login: login,
            logout: logout,
            handleLoginRedirect: handleLoginRedirect,
            _processLoginRedirectUrl: _processLoginRedirectUrl,
            api: api
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.js */
    (function($, DX, undefined) {
        var ui = DX.ui = {};
        var initViewport = function(options) {
                options = $.extend({}, options);
                var inFrame = top != self;
                var device = DX.devices.fromUA();
                var allowZoom = options.allowZoom,
                    allowPan = options.allowPan;
                var metaSelector = "meta[name=viewport]";
                if (!$(metaSelector).length)
                    $("<meta />").attr("name", "viewport").appendTo("head");
                var metaVerbs = ["width=device-width"],
                    msTouchVerbs = [];
                if (allowZoom)
                    msTouchVerbs.push("pinch-zoom");
                else
                    metaVerbs.push("initial-scale=1.0", "maximum-scale=1.0");
                if (allowPan)
                    msTouchVerbs.push("pan-x", "pan-y");
                if (!allowPan && !allowZoom)
                    $("html, body").css("overflow", "hidden");
                else
                    $("html").css("-ms-overflow-style", "-ms-autohiding-scrollbar");
                $(metaSelector).attr("content", metaVerbs.join());
                $("html").css("-ms-touch-action", msTouchVerbs.join(" ") || "none");
                if (DX.support.touch)
                    $(document).off(".dxInitViewport").on("touchmove.dxInitViewport", function(e) {
                        var count = e.originalEvent.touches.length,
                            zoomDisabled = !allowZoom && count > 1,
                            panDisabled = !allowPan && count === 1 && !e.originalEvent.isScrollingEvent;
                        if (zoomDisabled || panDisabled)
                            e.preventDefault()
                    });
                if (navigator.userAgent.match(/IEMobile\/10\.0/)) {
                    $(document.head).append($("<style/>").text("@-ms-viewport{ width:auto!important; user-zoom: fixed; max-zoom: 1; min-zoom: 1; }"));
                    $(window).bind("load resize", function(e) {
                        var TOP_BAR_W = 44,
                            TOP_BAR_H = 21,
                            ADDRESS_BAR_H = 72;
                        var isStandalone = 'Notify' in window.external;
                        var barWidth = isStandalone ? TOP_BAR_W : 0,
                            barHeight = isStandalone ? TOP_BAR_H : ADDRESS_BAR_H;
                        var actualHeight = $(window).width() < $(window).height() ? Math.round(screen.availHeight * (document.body.clientWidth / screen.availWidth)) - barHeight : Math.round(screen.availWidth * (document.body.clientHeight / screen.availHeight)) - barWidth;
                        document.body.style.setProperty("min-height", actualHeight + "px", "important")
                    })
                }
                var hideAddressBar = function() {
                        var ADDRESS_BAR_HEIGHT = 60,
                            isIphone = device.phone,
                            isSafari = !navigator.standalone && /safari/i.test(navigator.userAgent);
                        var doHide = function() {
                                window.scrollTo(0, 1)
                            };
                        var isInput = function($who) {
                                return $who.is(":input")
                            };
                        return function(e) {
                                var height,
                                    $target = $(e.target),
                                    $active = $(document.activeElement),
                                    isTouch = e.type === "touchstart";
                                if (isTouch) {
                                    if (isInput($target))
                                        return;
                                    if (isInput($active))
                                        $active.blur()
                                }
                                else if (isInput($active))
                                    return;
                                if (isIphone && isSafari) {
                                    height = $(window).height() + ADDRESS_BAR_HEIGHT;
                                    if ($(document.body).height() !== height)
                                        $(document.body).height(height)
                                }
                                doHide()
                            }
                    }();
                if (!inFrame && device.ios && DX.devices.iosVersion()[0] < 7) {
                    $(window).on("load resize touchstart", hideAddressBar);
                    $(function() {
                        $(document.body).on("focusout", function() {
                            var fix_Q477825 = window.pageYOffset
                        })
                    })
                }
            };
        var TemplateProvider = DX.Class.inherit({
                getTemplateClass: function(widget) {
                    return Template
                },
                supportDefaultTemplate: function(widget) {
                    return false
                },
                getDefaultTemplate: function(widget) {
                    return null
                }
            });
        var Template = DX.Class.inherit({
                ctor: function(element) {
                    this._template = this._element = $(element)
                },
                render: function(container) {
                    container.append(this._template);
                    return this._template
                },
                dispose: $.noop
            });
        DX.registerActionExecutor({
            designMode: {validate: function(e) {
                    if (DX.designMode && !(e.context instanceof ui.dxScrollable) && !(e.context instanceof ui.dxScrollView))
                        e.canceled = true
                }},
            gesture: {validate: function(e) {
                    var args = e.args,
                        context = e.context,
                        component = args.length && args[0].component,
                        recentGestureOwner = ui.gestureUtils.recentGestureOwner();
                    if (ui.gestureUtils.hasRecent() && !e.allowedForGesture && !($.isFunction(context) && recentGestureOwner instanceof context) && recentGestureOwner !== context && recentGestureOwner !== component)
                        e.canceled = true
                }},
            disabled: {validate: function(e) {
                    if (!e.args.length)
                        return;
                    var element = e.args[0].itemElement || e.args[0].element;
                    if (element && element.is(".dx-state-disabled, .dx-state-disabled *"))
                        e.canceled = true
                }}
        });
        $.extend(ui, {
            TemplateProvider: TemplateProvider,
            Template: Template,
            initViewport: initViewport
        });
        ui.__internals = {Template: Template}
    })(jQuery, DevExpress);
    /*! Module core, file ui.dialog.js */
    (function($, DX, undefined) {
        var ui = DX.ui;
        var DEFAULT_BUTTON = {
                text: "Ok",
                clickAction: function() {
                    return true
                }
            };
        var DX_DIALOG_CLASSNAME = "dx-dialog",
            DX_DIALOG_ROOT_CLASSNAME = DX_DIALOG_CLASSNAME + "-root",
            DX_DIALOG_CONTENT_CLASSNAME = DX_DIALOG_CLASSNAME + "-content",
            DX_DIALOG_MESSAGE_CLASSNAME = DX_DIALOG_CLASSNAME + "-message",
            DX_DIALOG_BUTTONS_CLASSNAME = DX_DIALOG_CLASSNAME + "-buttons",
            DX_DIALOG_BUTTON_CLASSNAME = DX_DIALOG_CLASSNAME + "-button";
        var dialog = function(options) {
                var self = this,
                    result;
                if (!ui.dxPopup)
                    throw new Error("DevExpress.ui.dxPopup required.");
                var deferred = $.Deferred();
                options = $.extend(ui.optionsByDevice(DX.devices.current(), "dxDialog"), options);
                var $holder = $(".dx-viewport");
                var $element = $("<div/>").addClass(DX_DIALOG_CLASSNAME).appendTo($holder);
                var $message = $("<div/>").addClass(DX_DIALOG_MESSAGE_CLASSNAME).html(String(options.message));
                var $buttons = $("<div/>").addClass(DX_DIALOG_BUTTONS_CLASSNAME);
                var popupInstance = $element.dxPopup({
                        title: options.title || self.title,
                        height: "auto",
                        width: function() {
                            var isPortrait = $(window).height() > $(window).width(),
                                key = (isPortrait ? "p" : "l") + "Width";
                            return options.hasOwnProperty(key) ? options[key] : options["width"]
                        }
                    }).data("dxPopup");
                $.each(options.buttons || [DEFAULT_BUTTON], function() {
                    var button = $("<div/>").addClass(DX_DIALOG_BUTTON_CLASSNAME).appendTo($buttons);
                    var action = new DX.Action(this.clickAction, {context: popupInstance});
                    button.dxButton($.extend(this, {clickAction: function() {
                            result = action.execute(arguments);
                            hide()
                        }}))
                });
                popupInstance._element().addClass(DX_DIALOG_ROOT_CLASSNAME);
                popupInstance.content().addClass(DX_DIALOG_CONTENT_CLASSNAME).append($message).append($buttons);
                function show() {
                    popupInstance.show();
                    return deferred.promise()
                }
                function hide(value) {
                    popupInstance.hide().done(function() {
                        popupInstance._element().remove()
                    });
                    deferred.resolve(result || value)
                }
                return {
                        show: show,
                        hide: hide
                    }
            };
        var alert = function(message, title) {
                var dialogInstance,
                    options = $.isPlainObject(message) ? message : {
                        title: title,
                        message: message
                    };
                dialogInstance = ui.dialog.custom(options);
                return dialogInstance.show()
            };
        var confirm = function(message, title) {
                var dialogInstance,
                    options = $.isPlainObject(message) ? message : {
                        title: title,
                        message: message,
                        buttons: [{
                                text: "Yes",
                                clickAction: function() {
                                    return true
                                }
                            }, {
                                text: "No",
                                clickAction: function() {
                                    return false
                                }
                            }]
                    };
                dialogInstance = ui.dialog.custom(options);
                return dialogInstance.show()
            };
        var notify = function(message, type, displayTime) {
                var instance,
                    options = $.isPlainObject(message) ? message : {message: message};
                if (!ui.dxToast) {
                    alert(options.message);
                    return
                }
                if (type)
                    options.type = type;
                if (displayTime)
                    options.displayTime = displayTime;
                instance = $("<div/>").appendTo($(".dx-viewport")).dxToast(options).data("dxToast");
                instance.option("hiddenAction", function(args) {
                    args.element.remove();
                    new DX.Action(options.hiddenAction, {context: args.model}).execute(arguments)
                });
                instance.show()
            };
        $.extend(ui, {
            notify: notify,
            dialog: {
                custom: dialog,
                alert: alert,
                confirm: confirm
            }
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.knockoutIntegration.js */
    (function($, DX, undefined) {
        var ko = window.ko;
        if (!ko)
            return;
        (function checkKnockoutVersion(version) {
            version = version.split(".");
            if (version[0] < 2 || version[0] == 2 && version[1] < 2)
                throw Error("Your version of KnockoutJS is too old. Please upgrade KnockoutJS to 2.2.0 or later.");
        })(ko.version);
        var ui = DX.ui,
            inflector = DX.inflector,
            DATA_BIND_ATTR = "data-bind",
            ANONYMOUS_BINDING_KEY = "unknown",
            ANONYMOUS_OPTION_NAME_FOR_OPTIONS_BAG = "_";
        var LOCKS_DATA_KEY = "dxKoLocks",
            MODEL_TO_OPTIONS_LOCK_NAME = "M2O",
            OPTIONS_TO_MODEL_LOCK_NAME = "O2M",
            CREATED_WITH_KO_DATA_KEY = "dxKoCreation";
        var defaultBindingProvider = ko.bindingProvider.instance,
            parseObjectLiteral = ko.jsonExpressionRewriting.parseObjectLiteral,
            bindingEvaluatorElement = $("<div></div>");
        var isComponentName = function(name) {
                return name in ui && ui[name].subclassOf && ui[name].subclassOf(ui.Component)
            };
        var stripQuotes = function(text) {
                return text.replace(/^['"]|['"]$/g, "")
            };
        var hideComponentBindings = function(element) {
                element = $(element);
                var bindingExpr = element.attr(DATA_BIND_ATTR);
                if (!bindingExpr)
                    return;
                var parsedBindingExpr = parseObjectLiteral(bindingExpr),
                    newBindingFragments = [],
                    found = false;
                $.each(parsedBindingExpr, function() {
                    var componentName = stripQuotes(this.key),
                        hiddenBindingsAttrName = "data-" + inflector.underscore(componentName);
                    if (isComponentName(componentName) && !element.attr(hiddenBindingsAttrName)) {
                        found = true;
                        element.attr(hiddenBindingsAttrName, this.value);
                        newBindingFragments.push({
                            key: componentName,
                            value: "true"
                        })
                    }
                    else
                        newBindingFragments.push(this)
                });
                if (found)
                    element.attr(DATA_BIND_ATTR, $.map(newBindingFragments, function(i) {
                        return i.key + ": " + i.value
                    }).join(", "))
            };
        var PatchedBindingProvider = {
                _original: defaultBindingProvider,
                nodeHasBindings: function(node) {
                    return defaultBindingProvider.nodeHasBindings(node)
                },
                getBindings: function(node, bindingContext) {
                    hideComponentBindings(node);
                    return defaultBindingProvider.getBindings(node, bindingContext)
                }
            };
        var Locks = function() {
                var info = {};
                var currentCount = function(lockName) {
                        return info[lockName] || 0
                    };
                return {
                        obtain: function(lockName) {
                            info[lockName] = currentCount(lockName) + 1
                        },
                        release: function(lockName) {
                            var count = currentCount(lockName);
                            if (count < 1)
                                throw Error("Not locked");
                            if (count === 1)
                                delete info[lockName];
                            else
                                info[lockName] = count - 1
                        },
                        locked: function(lockName) {
                            return currentCount(lockName) > 0
                        }
                    }
            };
        var registerComponentKoBinding = function(componentName) {
                var parseHiddenBindings = function(element) {
                        var bindingString = $.trim(element.attr("data-" + inflector.underscore(componentName))),
                            result,
                            firstItem;
                        if (bindingString.charAt(0) === "{") {
                            result = parseObjectLiteral(bindingString);
                            firstItem = result[0];
                            if (firstItem && ANONYMOUS_BINDING_KEY in firstItem)
                                result = $.trim(firstItem[ANONYMOUS_BINDING_KEY])
                        }
                        else
                            result = bindingString;
                        if (result === "")
                            result = [];
                        return result
                    };
                ko.bindingHandlers[componentName] = {init: function(domNode) {
                        var element = $(domNode),
                            parsedBindings = parseHiddenBindings(element),
                            ctorOptions = {},
                            optionNameToModelMap = {};
                        var evalModelValue = function(optionName, modelValueExpr) {
                                bindingEvaluatorElement.attr(DATA_BIND_ATTR, optionName + ":" + modelValueExpr);
                                try {
                                    return defaultBindingProvider.getBindings(bindingEvaluatorElement[0], ko.contextFor(domNode))[optionName]
                                }
                                finally {
                                    bindingEvaluatorElement.removeAttr(DATA_BIND_ATTR)
                                }
                            };
                        var applyModelValueToOption = function(optionName, modelValue) {
                                var component = element.data(componentName),
                                    locks = element.data(LOCKS_DATA_KEY),
                                    optionValue = ko.utils.unwrapObservable(modelValue);
                                if (!component) {
                                    ctorOptions[optionName] = optionValue;
                                    if (ko.isWriteableObservable(modelValue))
                                        optionNameToModelMap[optionName] = modelValue
                                }
                                else {
                                    if (locks.locked(OPTIONS_TO_MODEL_LOCK_NAME))
                                        return;
                                    locks.obtain(MODEL_TO_OPTIONS_LOCK_NAME);
                                    try {
                                        component.option(optionName, optionValue)
                                    }
                                    finally {
                                        locks.release(MODEL_TO_OPTIONS_LOCK_NAME)
                                    }
                                }
                            };
                        var handleOptionChanged = function(optionName, optionValue) {
                                if (!(optionName in optionNameToModelMap))
                                    return;
                                var element = this._$element,
                                    locks = element.data(LOCKS_DATA_KEY);
                                if (locks.locked(MODEL_TO_OPTIONS_LOCK_NAME))
                                    return;
                                locks.obtain(OPTIONS_TO_MODEL_LOCK_NAME);
                                try {
                                    optionNameToModelMap[optionName](optionValue)
                                }
                                finally {
                                    locks.release(OPTIONS_TO_MODEL_LOCK_NAME)
                                }
                            };
                        ko.utils.domNodeDisposal.addDisposeCallback(domNode, function() {
                            $.each(element.data("dxComponents") || [], function(index, item) {
                                element.data(item)._dispose()
                            })
                        });
                        if (typeof parsedBindings === "string")
                            ko.computed(function() {
                                var cmp = element.data(componentName);
                                if (cmp)
                                    cmp.beginUpdate();
                                $.each(ko.utils.unwrapObservable(evalModelValue(ANONYMOUS_OPTION_NAME_FOR_OPTIONS_BAG, parsedBindings)), applyModelValueToOption);
                                if (cmp)
                                    cmp.endUpdate()
                            }, null, {disposeWhenNodeIsRemoved: domNode});
                        else
                            $.each(parsedBindings, function() {
                                var optionName = stripQuotes($.trim(this.key)),
                                    modelValueExpr = $.trim(this.value);
                                ko.computed(function() {
                                    var modelValue = evalModelValue(optionName, modelValueExpr);
                                    applyModelValueToOption(optionName, modelValue)
                                }, null, {disposeWhenNodeIsRemoved: domNode})
                            });
                        if (ctorOptions) {
                            element.data(CREATED_WITH_KO_DATA_KEY, true);
                            element[componentName](ctorOptions);
                            ctorOptions = null;
                            element.data(LOCKS_DATA_KEY, new Locks);
                            element.data(componentName).optionChanged.add(handleOptionChanged)
                        }
                        return {controlsDescendantBindings: ui[componentName].subclassOf(ui.Widget)}
                    }}
            };
        ko.bindingProvider.instance = PatchedBindingProvider;
        var KoTemplate = ui.Template.inherit({
                ctor: function(element) {
                    this.callBase.apply(this, arguments);
                    this._template = $("<div />").append(element);
                    this._cleanTemplateElement();
                    this._registerKoTemplate()
                },
                _cleanTemplateElement: function() {
                    this._element.each(function() {
                        ko.cleanNode(this)
                    })
                },
                _registerKoTemplate: function() {
                    var template = this._template.get(0);
                    new ko.templateSources.anonymousTemplate(template)['nodes'](template)
                },
                render: function(container, data) {
                    if (!$(container).closest("body").length)
                        throw Error("Attempt to render into container detached from document");
                    data = data !== undefined ? data : ko.dataFor(container.get(0)) || {};
                    var containerBindingContext = ko.contextFor(container[0]);
                    var bindingContext = containerBindingContext ? containerBindingContext.createChildContext(data) : data;
                    var renderBag = $("<div />").appendTo(container);
                    ko.renderTemplate(this._template.get(0), bindingContext, null, renderBag.get(0));
                    var result = renderBag.contents();
                    container.append(result);
                    renderBag.remove();
                    return result
                },
                dispose: function() {
                    this._cleanTemplateElement();
                    this._element.remove();
                    this._template.remove()
                }
            });
        var KoTemplateProvider = ui.TemplateProvider.inherit({
                getTemplateClass: function(widget) {
                    if (this._createdWithKo(widget))
                        return KoTemplate;
                    return this.callBase(widget)
                },
                supportDefaultTemplate: function(widget) {
                    return this._createdWithKo(widget) ? true : this.callBase(widget)
                },
                getDefaultTemplate: function(widget) {
                    if (this._createdWithKo(widget))
                        return defaultKoTemplate(widget.NAME)
                },
                _createdWithKo: function(widget) {
                    return !!widget._element().data(CREATED_WITH_KO_DATA_KEY)
                }
            });
        ko.bindingHandlers.dxAction = {update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
                var $element = $(element);
                var actionSource = ko.utils.unwrapObservable(valueAccessor()),
                    action = new DX.Action(actionSource, {context: element});
                $element.off(".dxActionBinding").on("click.dxActionBinding", function() {
                    action.execute({
                        element: $element,
                        model: viewModel,
                        evaluate: function(expression) {
                            var context = viewModel;
                            if (expression.length > 0 && expression[0] === "$")
                                context = ko.contextFor(element);
                            var getter = DX.data.utils.compileGetter(expression);
                            return getter(context)
                        }
                    })
                })
            }};
        var defaultKoTemplate = function() {
                var cache = {};
                return function(widgetName) {
                        if (!DEFAULT_ITEM_TEMPLATE_GENERATORS[widgetName])
                            widgetName = "base";
                        if (!cache[widgetName]) {
                            var html = DEFAULT_ITEM_TEMPLATE_GENERATORS[widgetName](),
                                markup = DX.utils.createMarkupFromString(html);
                            markup.each(function() {
                                hideComponentBindings($(this))
                            });
                            cache[widgetName] = new KoTemplate(markup)
                        }
                        return cache[widgetName]
                    }
            }();
        var createElementWithBindAttr = function(tagName, bindings, closeTag) {
                closeTag = closeTag === undefined ? true : closeTag;
                var bindAttr = $.map(bindings, function(value, key) {
                        return key + ":" + value
                    }).join(",");
                return "<" + tagName + " data-bind=\"" + bindAttr + "\">" + (closeTag ? "</" + tagName + ">" : "")
            };
        var defaultKoTemplateBasicBindings = {
                visible: "$data.visible === undefined || $data.visible",
                css: "{ 'dx-state-disabled': $data.disabled }"
            };
        var DEFAULT_ITEM_TEMPLATE_GENERATORS = {base: function() {
                    var template = [createElementWithBindAttr("div", defaultKoTemplateBasicBindings, false)],
                        htmlBinding = createElementWithBindAttr("div", {html: "html"}),
                        textBinding = createElementWithBindAttr("div", {text: "text"}),
                        primitiveBinding = createElementWithBindAttr("div", {html: "String($data)"});
                    template.push("<!-- ko if: $data.html -->", htmlBinding, "<!-- /ko -->", "<!-- ko if: !$data.html && $data.text -->", textBinding, "<!-- /ko -->", "<!-- ko ifnot: $.isPlainObject($data) -->", primitiveBinding, "<!-- /ko -->", "</div>");
                    return template.join("")
                }};
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxList = function() {
            var template = DEFAULT_ITEM_TEMPLATE_GENERATORS.base(),
                keyBinding = createElementWithBindAttr("div", {html: "key"});
            template = [template.substring(0, template.length - 6), "<!-- ko if: $data.key -->" + keyBinding + "<!-- /ko -->", "</div>"];
            return template.join("")
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxToolbar = function() {
            var template = DEFAULT_ITEM_TEMPLATE_GENERATORS.base();
            template = [template.substring(0, template.length - 6), "<!-- ko if: $data.widget -->"];
            $.each(["button", "tabs", "dropDownMenu"], function() {
                var bindingName = DX.inflector.camelize(["dx", "-", this].join("")),
                    bindingObj = {};
                bindingObj[bindingName] = "$data.options";
                template.push("<!-- ko if: $data.widget === '", this, "' -->", createElementWithBindAttr("div", bindingObj), "<!-- /ko -->")
            });
            template.push("<!-- /ko -->");
            return template.join("")
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxGallery = function() {
            var template = DEFAULT_ITEM_TEMPLATE_GENERATORS.base(),
                primitiveBinding = createElementWithBindAttr("div", {html: "String($data)"}),
                imgBinding = createElementWithBindAttr("img", {attr: "{ src: String($data) }"}, false);
            template = template.replace(primitiveBinding, imgBinding);
            return template
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxTabs = function() {
            var template = DEFAULT_ITEM_TEMPLATE_GENERATORS.base(),
                baseTextBinding = createElementWithBindAttr("div", {text: "text"}),
                iconBinding = createElementWithBindAttr("span", {
                    attr: "{ 'class': 'dx-icon-' + $data.icon }",
                    css: "{ 'dx-icon': true }"
                }),
                iconSrcBinding = createElementWithBindAttr("img", {
                    attr: "{ src: $data.iconSrc }",
                    css: "{ 'dx-icon': true }"
                }, false),
                textBinding = "<!-- ko if: $data.icon -->" + iconBinding + "<!-- /ko -->" + "<!-- ko if: !$data.icon && $data.iconSrc -->" + iconSrcBinding + "<!-- /ko -->" + "<span class=\"dx-tab-text\" data-bind=\"text: $data.text\"></span>";
            template = template.replace("<!-- ko if: !$data.html && $data.text -->", "<!-- ko if: !$data.html && ($data.text || $data.icon || $data.iconSrc) -->").replace(baseTextBinding, textBinding);
            return template
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxActionSheet = function() {
            return createElementWithBindAttr("div", {dxButton: "{ text: $data.text, clickAction: $data.clickAction, type: $data.type, disabled: !!$data.disabled }"})
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxNavBar = DEFAULT_ITEM_TEMPLATE_GENERATORS.dxTabs;
        $.extend(ui, {
            registerComponentKoBinding: registerComponentKoBinding,
            TemplateProvider: KoTemplateProvider,
            Template: KoTemplate,
            defaultTemplate: defaultKoTemplate
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.gestureUtils.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            support = DX.support,
            TOUCH = support.touch,
            UNLOCK_ACTION_TIMEOUT = 400;
        var gestureUtils = function() {
                var unlockActionTimer = null,
                    gestureStartCallbacks = $.Callbacks(),
                    gestureOwner;
                var notifyGestureStart = function(owner) {
                        gestureOwner = owner || this;
                        clearTimeout(unlockActionTimer);
                        unlockActionTimer = null;
                        gestureStartCallbacks.fire()
                    };
                var notifyGestureEnd = function(owner) {
                        if (unlockActionTimer)
                            return;
                        if (owner && gestureOwner !== owner)
                            return;
                        unlockActionTimer = setTimeout(function() {
                            gestureOwner = undefined;
                            unlockActionTimer = null
                        }, UNLOCK_ACTION_TIMEOUT)
                    };
                var forgetRecentGesture = function(owner) {
                        if (owner && gestureOwner !== owner)
                            return;
                        gestureOwner = undefined;
                        clearTimeout(unlockActionTimer);
                        unlockActionTimer = null
                    };
                var recentGestureOwner = function() {
                        return gestureOwner
                    };
                var hasRecentGesture = function() {
                        return !!gestureOwner
                    };
                var android4nativeBrowser = /^4\.0/.test(DX.devices.androidVersion()) && navigator.userAgent.indexOf("Chrome") === -1;
                var preventHangingCursor = function() {
                        if (TOUCH)
                            if (android4nativeBrowser)
                                androidInputBlur();
                            else if (document.activeElement)
                                document.activeElement.blur()
                    };
                var androidInputBlur = function() {
                        var $specInput = $("<input>").addClass("dx-hidden-input").appendTo("body");
                        setTimeout(function() {
                            $specInput.focus();
                            setTimeout(function() {
                                $specInput.hide();
                                $specInput.remove()
                            }, 100)
                        }, 100)
                    };
                var preventNativeElastic = function(e) {
                        if (TOUCH)
                            e.preventDefault()
                    };
                var needSkipEvent = function(e) {
                        return $(e.target).is("input, textarea, select")
                    };
                return {
                        gestureStartCallbacks: gestureStartCallbacks,
                        preventHangingCursor: preventHangingCursor,
                        preventNativeElastic: preventNativeElastic,
                        needSkipEvent: needSkipEvent,
                        notifyStart: notifyGestureStart,
                        notifyEnd: notifyGestureEnd,
                        hasRecent: hasRecentGesture,
                        recentGestureOwner: recentGestureOwner,
                        forget: forgetRecentGesture
                    }
            }();
        gestureUtils.__internals = {
            UNLOCK_ACTION_TIMEOUT: UNLOCK_ACTION_TIMEOUT,
            setUnlockTimeout: function(timeout) {
                UNLOCK_ACTION_TIMEOUT = timeout
            }
        };
        ui.gestureUtils = gestureUtils
    })(jQuery, DevExpress);
    /*! Module core, file ui.dataHelper.js */
    (function($, DX, undefined) {
        var data = DX.data;
        var DATA_SOURCE_OPTIONS_METHOD = "_dataSourceOptions",
            DATA_SOURCE_CHANGED_METHOD = "_handleDataSourceChanged",
            DATA_SOURCE_LOAD_ERROR_METHOD = "_handleDataSourceLoadError";
        DX.ui.DataHelperMixin = {
            ctor: function() {
                this.disposing.add(function() {
                    this._disposeDataSource()
                })
            },
            _initDataSource: function() {
                var self = this,
                    dataSourceOptions = self.option("dataSource"),
                    dataSource,
                    widgetDataSourceOptions = DATA_SOURCE_OPTIONS_METHOD in this ? this[DATA_SOURCE_OPTIONS_METHOD]() : {},
                    dataSourceType = self._dataSourceType ? self._dataSourceType() : data.SimpleDataSource;
                self._disposeDataSource();
                if (!dataSourceOptions)
                    return;
                if ($.isArray(dataSourceOptions))
                    dataSource = new data.ArrayStore(dataSourceOptions).toDataSource(widgetDataSourceOptions, dataSourceType);
                else if ($.isPlainObject(dataSourceOptions))
                    if ('load' in dataSourceOptions)
                        dataSource = data.createDataSource(dataSourceOptions);
                    else {
                        if (!dataSourceOptions.store && !DX.designMode)
                            throw Error("Please specify 'load' function for the dataSource");
                        dataSource = new dataSourceType($.extend(true, {}, widgetDataSourceOptions, dataSourceOptions))
                    }
                else if (dataSourceOptions instanceof data.DataSource) {
                    self._sharedDataSource = true;
                    dataSource = dataSourceOptions
                }
                else if (dataSourceOptions instanceof data.Store)
                    dataSource = dataSourceOptions.toDataSource(widgetDataSourceOptions, dataSourceType);
                else
                    throw Error("Invalid dataSource option");
                self._dataSource = dataSource;
                dataSource.changed.add(self._dataSourceChangedHandler = function() {
                    self._dataSourceLoading = false;
                    self[DATA_SOURCE_CHANGED_METHOD](dataSource.items())
                });
                if (DATA_SOURCE_LOAD_ERROR_METHOD in self)
                    dataSource.loadError.add(self._dataSourceLoadErrorHandler = $.proxy(self[DATA_SOURCE_LOAD_ERROR_METHOD], self))
            },
            _loadDataSource: function() {
                var ds = this._dataSource;
                if (!ds)
                    return;
                if (ds.isLoaded())
                    this._dataSourceChangedHandler();
                else {
                    this._dataSourceLoading = true;
                    ds.load()
                }
            },
            _disposeDataSource: function() {
                if (!this._dataSource)
                    return;
                if (!this._sharedDataSource)
                    this._dataSource.dispose();
                else {
                    delete this._sharedDataSource;
                    this._dataSource.changed.remove(this._dataSourceChangedHandler);
                    this._dataSource.loadError.remove(this._dataSourceLoadErrorHandler)
                }
                delete this._dataSource;
                delete this._dataSourceChangedHandler;
                delete this._dataSourceLoadErrorHandler
            }
        }
    })(jQuery, DevExpress);
    /*! Module core, file ui.eventHelper.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            gestureUtils = ui.gestureUtils;
        var EventHelper = DX.Class.inherit({
                EVENT_SOURCES_REGEX: {
                    mouse: /^mouse/i,
                    touch: /^touch/i,
                    keyboard: /^key/i
                },
                EVENTS: {
                    click: "click",
                    start: "touchstart mousedown",
                    move: "touchmove mousemove",
                    end: "touchend mouseup",
                    cancel: "touchcancel",
                    wheel: "mousewheel"
                },
                ctor: function(namespace) {
                    this._namespace = namespace
                },
                eventSource: function(e) {
                    var result = "other";
                    $.each(this.EVENT_SOURCES_REGEX, function(key) {
                        if (this.test(e.type)) {
                            result = key;
                            return false
                        }
                    });
                    return result
                },
                isMouseEvent: function(e) {
                    return this.eventSource(e) === "mouse"
                },
                isTouchEvent: function(e) {
                    return this.eventSource(e) === "touch"
                },
                isKeyboardEvent: function() {
                    return this.eventSource(e) === "keyboard"
                },
                eventName: function(type) {
                    var self = this;
                    var events = this.EVENTS[type] || type;
                    events = events.split(/\s+/g);
                    $.each(events, function(index, eventName) {
                        events[index] = eventName + "." + self._namespace
                    });
                    return events.join(" ")
                },
                eventX: function(e) {
                    if (this.isMouseEvent(e))
                        return e.pageX;
                    if (this.isTouchEvent(e))
                        return e.originalEvent.touches[0].pageX
                },
                eventY: function(e) {
                    if (this.isMouseEvent(e))
                        return e.pageY;
                    if (this.isTouchEvent(e))
                        return e.originalEvent.touches[0].pageY
                },
                eventData: function(e) {
                    if (this.isMouseEvent(e))
                        return {
                                x: e.pageX,
                                y: e.pageY,
                                time: e.timeStamp
                            };
                    if (this.isTouchEvent(e)) {
                        var touch = (e.changedTouches || e.originalEvent.changedTouches)[0];
                        return {
                                x: touch.pageX,
                                y: touch.pageY,
                                time: e.timeStamp
                            }
                    }
                },
                eventDelta: function(from, to) {
                    return {
                            x: to.x - from.x,
                            y: to.y - from.y,
                            time: to.time - from.time || 1
                        }
                },
                hasTouches: function(e) {
                    if (this.isMouseEvent(e))
                        return 0;
                    if (this.isTouchEvent(e))
                        return e.originalEvent.touches.length
                },
                needSkipEvent: function(e) {
                    if (this.isMouseEvent(e))
                        return gestureUtils.needSkipEvent(e) || e.which > 1;
                    if (this.isTouchEvent(e))
                        return (e.changedTouches || e.originalEvent.changedTouches).length !== 1
                }
            });
        var MOUSE_EVENT_LOCK_TIMEOUT = 400,
            mouseLocked = false,
            unlockMouseTimer = null;
        DX.registerActionExecutor("ignoreMouseAfterTouch", {validate: function(e) {
                var event = e.args[0];
                if (event && event.jQueryEvent)
                    event = event.jQueryEvent;
                if (!(event instanceof $.Event))
                    return;
                if (EventHelper.prototype.isTouchEvent(event)) {
                    mouseLocked = true;
                    clearTimeout(unlockMouseTimer);
                    unlockMouseTimer = setTimeout(function() {
                        mouseLocked = false
                    }, MOUSE_EVENT_LOCK_TIMEOUT)
                }
                else if (EventHelper.prototype.isMouseEvent(event))
                    if (mouseLocked)
                        e.canceled = true
            }});
        DX.ui.EventHelper = EventHelper
    })(jQuery, DevExpress);
    /*! Module core, file ui.events.js */
    (function($, DX, undefined) {
        var EVENTS_NAME_SPACE = "dxSpecialEvents",
            HOLD_TIMER_DATA_KEY = EVENTS_NAME_SPACE + "HoldTimer";
        var eventHelper = new DX.ui.EventHelper(EVENTS_NAME_SPACE),
            startEventName = eventHelper.eventName("start"),
            endEventName = eventHelper.eventName("end"),
            cancelEventName = eventHelper.eventName("cancel"),
            eventNS = $.event,
            specialNS = eventNS.special;
        var hold = specialNS["dx:hold"] = {
                HOLD_TIMEOUT: 750,
                setup: function(data) {
                    var element = this,
                        $element = $(element);
                    var handleStart = function(e) {
                            if ($element.data(HOLD_TIMER_DATA_KEY))
                                return;
                            $element.data(HOLD_TIMER_DATA_KEY, setTimeout(function() {
                                $element.removeData(HOLD_TIMER_DATA_KEY);
                                eventNS.dispatch.call(element, $.Event("dx:hold", {target: e.target}))
                            }, data && "timeout" in data ? data.timeout : hold.HOLD_TIMEOUT))
                        };
                    var handleEnd = function() {
                            clearTimeout($element.data(HOLD_TIMER_DATA_KEY));
                            $element.removeData(HOLD_TIMER_DATA_KEY)
                        };
                    $element.on(startEventName + ".dxHold", handleStart).on(endEventName + ".dxHold", handleEnd)
                },
                teardown: function() {
                    var $element = $(this);
                    clearTimeout($element.data(HOLD_TIMER_DATA_KEY));
                    $element.removeData(HOLD_TIMER_DATA_KEY).off(".dxHold")
                }
            };
        var MOUSE_EVENT_LOCK_TIMEOUT = 600,
            mouseLocked = false,
            unlockMouseTimer = null;
        var click = specialNS["dx:click"] = {
                TOUCH_BOUNDARY: 10,
                _trackingClick: false,
                _skipNextClick: false,
                _$target: null,
                _startX: 0,
                _startY: 0,
                _touchWasMoved: function(e) {
                    var eventData = eventHelper.eventData(e),
                        boundary = click.TOUCH_BOUNDARY;
                    return Math.abs(eventData.x - click._startX) > boundary || Math.abs(eventData.y - click._startY) > boundary
                },
                _handleStart: function(e) {
                    if (eventHelper.isMouseEvent(e))
                        return;
                    var targetTouches = e.originalEvent.targetTouches,
                        touch = targetTouches[0];
                    if (targetTouches.length > 1)
                        return;
                    click._trackingClick = true;
                    click._$target = $(e.target);
                    click._startX = touch.pageX;
                    click._startY = touch.pageY
                },
                _handleClick: function(e) {
                    if (!click._skipNextClick) {
                        e.type = "dx:click";
                        $(e.currentTarget).trigger(e)
                    }
                    click._skipNextClick = false
                },
                _handleEnd: function(e) {
                    if (eventHelper.isTouchEvent(e)) {
                        mouseLocked = true;
                        clearTimeout(unlockMouseTimer);
                        unlockMouseTimer = setTimeout(function() {
                            mouseLocked = false
                        }, MOUSE_EVENT_LOCK_TIMEOUT)
                    }
                    else if (eventHelper.isMouseEvent(e))
                        if (mouseLocked)
                            click._skipNextClick = true;
                    if (eventHelper.isMouseEvent(e))
                        return;
                    if (click._touchWasMoved(e)) {
                        click._trackingClick = false;
                        click._$target = null
                    }
                    if (!click._trackingClick)
                        return;
                    click._trackingClick = false;
                    click._$target.trigger("dx:click")
                },
                _handleCancel: function() {
                    click._trackingClick = false;
                    click._$target = null
                },
                setup: function() {
                    $(this).on(["click", EVENTS_NAME_SPACE, "dxClick"].join("."), $.proxy(click._handleClick, this)).on(startEventName + ".dxClick", $.proxy(click._handleStart, this)).on(endEventName + ".dxClick", $.proxy(click._handleEnd, this)).on(cancelEventName + ".dxClick", $.proxy(click._handleCancel, this))
                },
                teardown: function() {
                    $(this).off(".dxClick")
                }
            }
    })(jQuery, DevExpress);
    /*! Module core, file ui.component.js */
    (function($, DX, undefined) {
        var COMPONENT_NAMES_DATA_KEY = "dxComponents",
            HAS_KO = !!window.ko,
            ui = DX.ui,
            dataUtils = DX.data.utils,
            DISABLED_STATE_CLASS = "dx-state-disabled";
        var Component = DX.Class.inherit({
                NAME: null,
                _defaultOptions: function() {
                    return {disabled: false}
                },
                ctor: function(element, options) {
                    if (!this.NAME)
                        throw Error("NAME is not specified");
                    this._$element = $(element);
                    this._element().data(this.NAME, this);
                    if (!this._element().data(COMPONENT_NAMES_DATA_KEY))
                        this._element().data(COMPONENT_NAMES_DATA_KEY, []);
                    this._element().data(COMPONENT_NAMES_DATA_KEY).push(this.NAME);
                    this._options = {};
                    this._updateLockCount = 0;
                    this._requireRefresh = false;
                    this._eventHelper = new ui.EventHelper(this.NAME);
                    this.optionChanged = $.Callbacks();
                    this.disposing = $.Callbacks();
                    this.beginUpdate();
                    try {
                        var device = DX.devices.current(),
                            optionsByDevice = ui.optionsByDevice(device, this.NAME) || {},
                            defaultOptions = $.extend(this._defaultOptions(), optionsByDevice);
                        this.option(defaultOptions);
                        this._initOptions(options || {})
                    }
                    finally {
                        this.endUpdate()
                    }
                },
                _initOptions: function(options) {
                    this.option(options)
                },
                _optionValuesEqual: function(name, oldValue, newValue) {
                    oldValue = dataUtils.toComparable(oldValue, true);
                    newValue = dataUtils.toComparable(newValue, true);
                    if (oldValue === null || typeof oldValue !== "object")
                        return oldValue === newValue;
                    return false
                },
                _init: $.noop,
                _render: function() {
                    this._renderDisabledState()
                },
                _clean: $.noop,
                _invalidate: function() {
                    if (!this._updateLockCount)
                        throw Error("Invalidate called outside update transaction");
                    this._requireRefresh = true
                },
                _refresh: function() {
                    this._clean();
                    this._render()
                },
                _dispose: function() {
                    this._clean();
                    this.optionChanged.empty();
                    this.disposing.fireWith(this).empty()
                },
                _renderDisabledState: function() {
                    this._element().toggleClass(DISABLED_STATE_CLASS, this.option("disabled"))
                },
                _createAction: function(actionSource, config) {
                    var self = this;
                    config = $.extend({}, config);
                    var element = config.element || self._element(),
                        model = self._modelByElement(element);
                    config.context = model || self;
                    config.component = self;
                    var action = new DX.Action(actionSource, config);
                    return function(e) {
                            if (!arguments.length)
                                e = {};
                            if (e instanceof $.Event)
                                throw Error("Action must be executed with jQuery.Event like action({ jQueryEvent: event })");
                            if (!$.isPlainObject(e))
                                e = {actionValue: e};
                            return action.execute.call(action, $.extend(e, {
                                    component: self,
                                    element: element,
                                    model: model
                                }))
                        }
                },
                _createActionByOption: function(optionName, config) {
                    if (typeof optionName !== "string")
                        throw Error("Option name type is unexpected");
                    return this._createAction(this.option(optionName), config)
                },
                _modelByElement: function(element) {
                    if (HAS_KO && element.length)
                        return ko.dataFor(element.get(0))
                },
                _optionChanged: function(name, value, prevValue) {
                    if (name === "disabled")
                        this._renderDisabledState();
                    else
                        this._invalidate()
                },
                _element: function() {
                    return this._$element
                },
                instance: function() {
                    return this
                },
                beginUpdate: function() {
                    this._updateLockCount++
                },
                endUpdate: function() {
                    this._updateLockCount--;
                    if (!this._updateLockCount)
                        if (!this._initializing && !this._initialized) {
                            this._initializing = true;
                            try {
                                this._init()
                            }
                            finally {
                                this._initializing = false;
                                this._initialized = true
                            }
                            this._render()
                        }
                        else if (this._requireRefresh) {
                            this._requireRefresh = false;
                            this._refresh()
                        }
                },
                option: function(options) {
                    var self = this,
                        name = options,
                        value = arguments[1];
                    if (arguments.length < 2 && $.type(name) !== "object")
                        return dataUtils.compileGetter(name)(self._options, {functionsAsIs: true});
                    if (typeof name === "string") {
                        options = {};
                        options[name] = value
                    }
                    self.beginUpdate();
                    try {
                        $.each(options, function(name, value) {
                            var prevValue = dataUtils.compileGetter(name)(self._options, {functionsAsIs: true}),
                                topLevelName;
                            if (self._optionValuesEqual(name, prevValue, value))
                                return;
                            dataUtils.compileSetter(name)(self._options, value, {
                                functionsAsIs: true,
                                merge: true
                            });
                            topLevelName = name.split(/[.\[]/)[0];
                            if (self._initialized) {
                                self.optionChanged.fireWith(self, [topLevelName, value, prevValue]);
                                self._optionChanged(topLevelName, value, prevValue)
                            }
                        })
                    }
                    finally {
                        self.endUpdate()
                    }
                }
            });
        var registerComponent = function(name, componentClass) {
                ui[name] = componentClass;
                componentClass.prototype.NAME = name;
                $.fn[name] = function(options) {
                    var isMemberInvoke = typeof options === "string",
                        result = this;
                    if (isMemberInvoke) {
                        var memberName = options,
                            memberArgs = $.makeArray(arguments).slice(1);
                        this.each(function() {
                            var instance = $(this).data(name);
                            if (!instance)
                                throw Error("Component " + name + " has not been initialized on this element");
                            var member = instance[memberName],
                                memberValue = member.apply(instance, memberArgs);
                            if (memberValue !== undefined) {
                                result = memberValue;
                                return false
                            }
                        })
                    }
                    else
                        this.each(function() {
                            var instance = $(this).data(name);
                            if (instance)
                                instance.option(options);
                            else
                                new componentClass(this, options)
                        });
                    return result
                };
                if (HAS_KO)
                    ui.registerComponentKoBinding(name)
            };
        var getComponents = function(element) {
                element = $(element);
                var names = element.data(COMPONENT_NAMES_DATA_KEY);
                if (!names)
                    return [];
                return $.map(names, function(name) {
                        return element.data(name)
                    })
            };
        function cleanComponentsAndKoData(element, andSelf) {
            element.each(function() {
                var all = this.getElementsByTagName ? this.getElementsByTagName("*") : [];
                if (andSelf)
                    all = jQuery.merge([this], all);
                for (var i = 0, item; (item = all[i]) != null; i++) {
                    $.each(getComponents(item), function() {
                        this._dispose()
                    });
                    if (HAS_KO)
                        ko.cleanNode(item)
                }
            })
        }
        var originalEmpty = $.fn.empty;
        $.fn.empty = function() {
            cleanComponentsAndKoData(this, false);
            return originalEmpty.apply(this, arguments)
        };
        var originalRemove = $.fn.remove;
        $.fn.remove = function(selector, keepData) {
            if (!keepData) {
                var subject = this;
                if (selector)
                    subject = subject.filter(selector);
                cleanComponentsAndKoData(subject, true)
            }
            return originalRemove.call(this, selector, keepData)
        };
        var originalHtml = $.fn.html;
        $.fn.html = function(value) {
            if (typeof value === "string")
                cleanComponentsAndKoData(this, false);
            return originalHtml.apply(this, arguments)
        };
        var originalParseHtml = $.parseHTML;
        $.parseHTML = function() {
            return originalParseHtml.apply(this, arguments) || []
        };
        $.extend(ui, {
            registerComponent: registerComponent,
            Component: Component
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.widget.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            UI_FEEDBACK = "UIFeedback",
            UI_FEEDBACK_CLASS = "dx-feedback",
            ACTIVE_STATE_CLASS = "dx-state-active",
            DISABLED_STATE_CLASS = "dx-state-disabled",
            INVISIBLE_STATE_CLASS = "dx-state-invisible",
            FEEDBACK_SHOW_TIMEOUT = 30,
            FEEDBACK_HIDE_TIMEOUT = 400;
        var activeElement,
            eventHelper = new ui.EventHelper(UI_FEEDBACK),
            feedbackLocked = false;
        ui.feedback = {
            lock: function() {
                feedbackLocked = true
            },
            unlock: function() {
                window.setTimeout(function() {
                    feedbackLocked = false
                }, 0)
            }
        };
        ui.Widget = ui.Component.inherit({
            _defaultOptions: function() {
                return $.extend(this.callBase(), {
                        visible: true,
                        activeStateEnabled: true,
                        width: undefined,
                        height: undefined,
                        clickAction: null
                    })
            },
            _init: function() {
                this.callBase();
                this._feedbackShowTimeout = FEEDBACK_SHOW_TIMEOUT
            },
            _render: function() {
                this.callBase();
                this._element().addClass("dx-widget");
                this._toggleVisibility(this.option("visible"));
                this._refreshFeedback();
                this._renderDimensions();
                this._renderClick()
            },
            _dispose: function() {
                this._clearTimers();
                if (activeElement && activeElement.closest(this._element()).length)
                    activeElement = null;
                this._clickAction = null;
                this.callBase()
            },
            _clean: function() {
                this.callBase();
                this._element().empty()
            },
            _clearTimers: function() {
                clearTimeout(this._feedbackHideTimer);
                clearTimeout(this._feedbackShowTimer)
            },
            _toggleVisibility: function(visible) {
                this._element().toggleClass(INVISIBLE_STATE_CLASS, !visible)
            },
            _renderDimensions: function() {
                var width = this.option("width"),
                    height = this.option("height");
                this._element().width(width);
                this._element().height(height)
            },
            _refreshFeedback: function() {
                if (this._feedbackDisabled()) {
                    this._feedbackOff();
                    this._element().removeClass(UI_FEEDBACK_CLASS)
                }
                else
                    this._element().addClass(UI_FEEDBACK_CLASS)
            },
            _renderClick: function() {
                var self = this,
                    eventName = self._eventHelper.eventName("click");
                self._clickAction = self._createActionByOption("clickAction");
                self._element().off(eventName).on(eventName, function(e) {
                    self._clickAction({jQueryEvent: e})
                })
            },
            _feedbackDisabled: function() {
                return !this.option("activeStateEnabled") || this.option("disabled")
            },
            _feedbackOn: function(element, immediate) {
                if (this._feedbackDisabled() || feedbackLocked)
                    return;
                this._clearTimers();
                if (immediate)
                    this._feedbackShow(element);
                else
                    this._feedbackShowTimer = window.setTimeout($.proxy(this._feedbackShow, this, element), this._feedbackShowTimeout);
                this._saveActiveElement()
            },
            _feedbackShow: function(element) {
                var activeStateElement = this._element();
                if (this._activeStateUnit)
                    activeStateElement = $(element).closest(this._activeStateUnit);
                if (!activeStateElement.hasClass(DISABLED_STATE_CLASS))
                    activeStateElement.addClass(ACTIVE_STATE_CLASS)
            },
            _saveActiveElement: function() {
                activeElement = this._element()
            },
            _feedbackOff: function(isGestureStart, immediate) {
                this._clearTimers();
                if (immediate)
                    this._feedbackHide();
                else
                    this._feedbackHideTimer = window.setTimeout($.proxy(this._feedbackHide, this), FEEDBACK_HIDE_TIMEOUT)
            },
            _feedbackHide: function() {
                var activeStateElement = this._element();
                if (this._activeStateUnit)
                    activeStateElement = activeStateElement.find(this._activeStateUnit);
                activeStateElement.removeClass(ACTIVE_STATE_CLASS);
                this._clearActiveElement()
            },
            _clearActiveElement: function() {
                var rootDomElement = this._element().get(0),
                    activeDomElement = activeElement && activeElement.get(0);
                if (activeDomElement && (activeDomElement === rootDomElement || $.contains(rootDomElement, activeDomElement)))
                    activeElement = null
            },
            _optionChanged: function(name, value) {
                switch (name) {
                    case"disabled":
                        this.callBase.apply(this, arguments);
                    case"activeStateEnabled":
                        this._refreshFeedback();
                        break;
                    case"visible":
                        this._toggleVisibility(value);
                        break;
                    case"width":
                    case"height":
                        this._renderDimensions();
                        break;
                    case"clickAction":
                        this._renderClick();
                        break;
                    default:
                        this.callBase.apply(this, arguments)
                }
            }
        });
        var handleStart = function(e, immediate) {
                if (eventHelper.needSkipEvent(e))
                    return;
                if (activeElement)
                    getWidget(activeElement)._feedbackOff(false, true);
                var closestFeedbackElement = $(e.target).closest("." + UI_FEEDBACK_CLASS),
                    widget;
                if (closestFeedbackElement.length) {
                    widget = getWidget(closestFeedbackElement);
                    widget._feedbackOn(e.target, immediate);
                    if (immediate)
                        widget._feedbackOff()
                }
            };
        var handleEnd = function(isGestureStart) {
                if (!activeElement)
                    return;
                getWidget(activeElement)._feedbackOff(isGestureStart)
            };
        var getWidget = function(widgetElement) {
                var result;
                $.each(widgetElement.data("dxComponents"), function(index, componentName) {
                    if (ui[componentName].subclassOf(ui.Widget)) {
                        result = widgetElement.data(componentName);
                        return false
                    }
                });
                return result
            };
        $(function() {
            var startAction = new DX.Action(handleStart);
            $(document).on(eventHelper.eventName("start"), function(e) {
                startAction.execute(e)
            }).on(eventHelper.eventName("end") + " " + eventHelper.eventName("cancel"), function(e) {
                var activeElementClicked = activeElement && $(e.target).closest("." + UI_FEEDBACK_CLASS).get(0) === activeElement.get(0);
                if (!DX.ui.gestureUtils.hasRecent() && activeElementClicked)
                    startAction.execute(e, true);
                handleEnd()
            });
            ui.gestureUtils.gestureStartCallbacks.add(function() {
                handleEnd(true)
            })
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.containerWidget.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            ANONYMOUS_TEMPLATE_NAME = "template";
        var getTemplateOptions = function(element) {
                var options = element.data("options");
                if ($.trim(options).charAt(0) !== "{")
                    options = "{" + options + "}";
                return new Function("return " + options)().dxTemplate
            };
        var ContainerWidget = ui.Widget.inherit({
                _init: function() {
                    this.callBase();
                    this._templateProvider = new ui.TemplateProvider;
                    this._initTemplates()
                },
                _clean: $.noop,
                _initTemplates: function() {
                    var templates = {},
                        templateClass = this._templateProvider.getTemplateClass(this),
                        templateElements = this._element().children("[data-options]");
                    if (templateElements.length)
                        templateElements.each(function(index, element) {
                            element = $(element);
                            var templateOptions = getTemplateOptions(element);
                            if (!templateOptions.name)
                                throw Error("Template name was not specified");
                            templates[templateOptions.name] = new templateClass(element.get(0))
                        });
                    else
                        templates[ANONYMOUS_TEMPLATE_NAME] = new templateClass(this._element().contents());
                    this._templates = templates
                },
                _getTemplate: function(templateName) {
                    var result = this._aquireTemplate.apply(this, arguments);
                    if (!result && this._templateProvider.supportDefaultTemplate(this)) {
                        result = this._templateProvider.getDefaultTemplate(this);
                        if (!result)
                            throw Error("Template \"" + templateName + "\" was not found and no default template specified!");
                    }
                    return result
                },
                _aquireTemplate: function(templateName) {
                    if ($.isFunction(templateName))
                        templateName = templateName.apply(this, $.makeArray(arguments).slice(1));
                    return this._templates[templateName]
                },
                _cleanTemplates: function() {
                    $.each(this._templates, function(templateName, template) {
                        template.dispose()
                    })
                },
                _dispose: function() {
                    this._cleanTemplates();
                    this.callBase()
                }
            });
        ui.ContainerWidget = ContainerWidget
    })(jQuery, DevExpress);
    /*! Module core, file ui.template.js */
    /*! Module core, file ui.collectionContainerWidget.js */
    (function($, DX, undefined) {
        var ui = DX.ui;
        var CollectionContainerWidget = ui.ContainerWidget.inherit({
                _defaultOptions: function() {
                    return $.extend(this.callBase(), {
                            items: [],
                            itemTemplate: "item",
                            itemRender: null,
                            itemClickAction: null,
                            itemRenderedAction: null,
                            noDataText: "No data to display",
                            dataSource: null
                        })
                },
                _init: function() {
                    this.callBase();
                    this._initDataSource();
                    this._loadDataSource()
                },
                _optionChanged: function(name, value, prevValue) {
                    switch (name) {
                        case"dataSource":
                            this._clean();
                            this._initDataSource();
                            this._loadDataSource();
                            return;
                        case"noDataText":
                            this._renderEmptyMessage();
                            return;
                        case"itemRenderedAction":
                            return;
                        default:
                            this.callBase(name, value, prevValue)
                    }
                },
                _clean: function() {
                    this._itemContainer().empty()
                },
                _handleDataSourceChanged: function(items) {
                    this.option("items", items);
                    this._renderEmptyMessage()
                },
                _itemContainer: function() {
                    return this._element()
                },
                _itemClass: DX.abstract,
                _itemSelector: function() {
                    return "." + this._itemClass()
                },
                _itemDataKey: DX.abstract,
                _items: function() {
                    return this._itemContainer().find(this._itemSelector())
                },
                _render: function() {
                    this.callBase();
                    this._attachClickEvent();
                    this._renderItems()
                },
                _renderEmptyMessage: function() {
                    var noDataText = this.option("noDataText"),
                        noDataTextElement = this._element().find(".dx-empty-message"),
                        items = this.option("items"),
                        itemExists = items && items.length;
                    if (!noDataText || itemExists || this._dataSourceLoading)
                        noDataTextElement.remove();
                    else {
                        if (!noDataTextElement.length)
                            noDataTextElement = $("<div />").addClass("dx-empty-message").appendTo(this._itemContainer());
                        noDataTextElement.text(noDataText)
                    }
                },
                _attachClickEvent: function() {
                    var self = this,
                        itemSelector = self._itemSelector();
                    self._itemContainer().off("." + self.NAME, itemSelector).on(self._eventHelper.eventName("click"), itemSelector, $.proxy(self._handleItemClick, self))
                },
                _handleItemClick: function(e) {
                    this._handleItemEvent(e, "itemClickAction")
                },
                _renderItems: function() {
                    var items = this.option("items") || [];
                    if (items.length)
                        $.each(items, $.proxy(this._renderItem, this));
                    else
                        this._renderEmptyMessage()
                },
                _renderItem: function(index, item, container) {
                    container = container || this._itemContainer();
                    var itemRenderer = this.option("itemRender"),
                        itemTemplateName = this.option("itemTemplate"),
                        itemTemplate = this._getTemplate(item.template || itemTemplateName, index, item),
                        itemElement;
                    var renderArgs = {
                            index: index,
                            item: item,
                            container: container
                        };
                    if (itemRenderer)
                        itemElement = this._createItemByRenderer(itemRenderer, renderArgs);
                    else if (itemTemplate)
                        itemElement = this._createItemByTemplate(itemTemplate, renderArgs);
                    else
                        itemElement = this._createItemByRenderer(this._itemRenderDefault, renderArgs);
                    itemElement.addClass(this._itemClass()).data(this._itemDataKey(), item);
                    this._createActionByOption("itemRenderedAction", {
                        element: this._element(),
                        allowedForGesture: true
                    })({
                        itemElement: itemElement,
                        itemData: item
                    });
                    return itemElement
                },
                _createItemByRenderer: function(itemRenderer, renderArgs) {
                    var itemElement = $("<div />").appendTo(renderArgs.container);
                    var rendererResult = itemRenderer.call(this, renderArgs.item, renderArgs.index, itemElement);
                    if (rendererResult && itemElement[0] !== rendererResult[0])
                        itemElement.append(rendererResult);
                    return itemElement
                },
                _createItemByTemplate: function(itemTemplate, renderArgs) {
                    return itemTemplate.render(renderArgs.container, renderArgs.item)
                },
                _itemRenderDefault: function(item, index, itemElement) {
                    if ($.isPlainObject(item)) {
                        if (item.visible !== undefined && !item.visible)
                            itemElement.hide();
                        if (item.disabled)
                            itemElement.addClass("dx-state-disabled");
                        if (item.text)
                            itemElement.text(item.text);
                        if (item.html)
                            itemElement.html(item.html)
                    }
                    else
                        itemElement.html(String(item))
                },
                _handleItemEvent: function(jQueryEvent, handlerOptionName, args) {
                    var itemElement = $(jQueryEvent.target).closest(this._itemSelector());
                    var action = this._createActionByOption(handlerOptionName, {element: this._element()});
                    var actionArgs = $.extend({
                            itemElement: itemElement,
                            itemData: itemElement.data(this._itemDataKey()),
                            jQueryEvent: jQueryEvent
                        }, args);
                    return action(actionArgs)
                }
            }).include(ui.DataHelperMixin);
        ui.CollectionContainerWidget = CollectionContainerWidget
    })(jQuery, DevExpress);
    /*! Module core, file ui.optionsByDevice.js */
    (function($, DX, undefined) {
        DX.ui.optionsByDevice = function(device, componentName) {
            if (componentName === "dxScrollView") {
                var scrollViewOptions = {};
                if (navigator.appName === "Microsoft Internet Explorer")
                    scrollViewOptions.animationStrategy = "transition";
                if (device.platform === "desktop") {
                    scrollViewOptions.scrollByContent = false;
                    scrollViewOptions.showScrollbar = false;
                    return scrollViewOptions
                }
                if (device.platform === "win8")
                    scrollViewOptions.animationStrategy = "transition";
                return scrollViewOptions
            }
            if (componentName === "dxScrollable") {
                var scrollableOptions = {};
                if (navigator.appName === "Microsoft Internet Explorer")
                    scrollableOptions.animationStrategy = "transition";
                if (device.platform === "desktop") {
                    scrollableOptions.scrollByContent = false;
                    scrollableOptions.showScrollbar = false;
                    return scrollableOptions
                }
                if (device.platform === "win8")
                    scrollableOptions.animationStrategy = "transition";
                return scrollableOptions
            }
            if (componentName === "dxList")
                if (device.platform === "desktop")
                    return {
                            scrollingEnabled: false,
                            showScrollbar: false,
                            autoPagingEnabled: false,
                            showNextButton: true
                        };
            if (componentName === "dxPopup")
                if (device.platform === "win8" && !device.phone)
                    return {
                            width: "60%",
                            height: "auto"
                        };
            if (componentName === "dxDialog") {
                if (device.platform === "ios")
                    return {width: 276};
                if (device.platform === "win8" && !device.phone)
                    return {width: "60%"};
                if (device.platform === "android")
                    return {
                            lWidth: "60%",
                            pWidth: "80%"
                        }
            }
            if (componentName === "dxLookup") {
                if (device.platform === "android")
                    return {hideCancelButton: false};
                if (device.platform === "win8" && device.phone)
                    return {
                            hideCancelButton: true,
                            fullScreen: true
                        };
                if (device.platform === "ios" && device.phone)
                    return {fullScreen: true}
            }
            if (componentName === "dxLoadIndicator")
                if (navigator.appName === "Microsoft Internet Explorer" || navigator.appName === "MSAppHost/1.0")
                    return {viaImage: true}
        }
    })(jQuery, DevExpress)
}
if (!DevExpress.MOD_VIZ) {
    /*! Module viz, file namespaces.js */
    (function(DevExpress) {
        DevExpress.viz = {}
    })(DevExpress);
    /*! Module viz, file namespaces.js */
    (function(DevExpress) {
        DevExpress.viz.core = {}
    })(DevExpress);
    /*! Module viz, file tickProvider.js */
    (function($, DX, undefined) {
        var utils = DX.utils,
            core = DX.viz.core;
        var TICKS_COUNT_LIMIT = 2000;
        core.outOfScreen = {
            x: -1000,
            y: -1000
        };
        core.tickIntervalCalculator = {
            _defaultNumberMultipliers: [1, 2, 3, 5],
            _defaultGridSpacingFactor: 30,
            _getNumericTickInterval: function(deltaCoef, numberMultipliers) {
                var factor,
                    result = 0,
                    newResult,
                    hasResult = false,
                    i;
                if (deltaCoef > 1.0)
                    for (factor = 1; !hasResult; factor *= 10)
                        for (i = 0; i < numberMultipliers.length; i++) {
                            result = numberMultipliers[i] * factor;
                            if (deltaCoef <= result) {
                                hasResult = true;
                                break
                            }
                        }
                else if (deltaCoef > 0) {
                    result = 1;
                    for (factor = 0.1; !hasResult; factor /= 10)
                        for (i = numberMultipliers.length - 1; i >= 0; i--) {
                            newResult = numberMultipliers[i] * factor;
                            if (deltaCoef > newResult) {
                                hasResult = true;
                                break
                            }
                            result = newResult
                        }
                }
                return utils.adjustValue(result)
            },
            _getDatetimeTickInterval: function(deltaCoef, numberMultipliers) {
                var datetimeMultipliers = {
                        millisecond: [1, 2, 5, 10, 25, 100, 250, 300, 500],
                        second: [1, 2, 3, 5, 10, 15, 20, 30],
                        minute: [1, 2, 3, 5, 10, 15, 20, 30],
                        hour: [1, 2, 3, 4, 6, 8, 12],
                        day: [1, 2, 3, 5, 7, 10, 14],
                        month: [1, 2, 3, 6]
                    },
                    result = {},
                    factor,
                    key,
                    specificMultipliers,
                    yearsCount,
                    i;
                if (deltaCoef < 1.0)
                    return {milliseconds: 1};
                for (key in datetimeMultipliers)
                    if (datetimeMultipliers.hasOwnProperty(key)) {
                        specificMultipliers = datetimeMultipliers[key];
                        for (i = 0; i < specificMultipliers.length; i++)
                            if (deltaCoef <= utils.convertDateUnitToMilliseconds(key, specificMultipliers[i])) {
                                result[key + 's'] = specificMultipliers[i];
                                return result
                            }
                    }
                for (factor = 1; ; factor *= 10)
                    for (i = 0; i < numberMultipliers.length; i++) {
                        yearsCount = factor * numberMultipliers[i];
                        if (deltaCoef <= utils.convertDateUnitToMilliseconds('year', yearsCount))
                            return {years: yearsCount}
                    }
                return null
            },
            getTickInterval: function(type, businessDelta, screenDelta, gridSpacingFactor, numberMultipliers) {
                var self = this,
                    gridSpacingFactor = gridSpacingFactor || self._defaultGridSpacingFactor,
                    numberMultipliers = numberMultipliers || self._defaultNumberMultipliers,
                    deltaCoef = screenDelta > 0 ? gridSpacingFactor * businessDelta / screenDelta : 0;
                self._testNumberMultipliers = numberMultipliers;
                switch (type) {
                    case'numeric':
                        return self._getNumericTickInterval(deltaCoef, numberMultipliers);
                    case'dateTime':
                        return self._getDatetimeTickInterval(deltaCoef, numberMultipliers)
                }
                return null
            }
        };
        core.minorTickIntervalCalculator = {
            _defaultNumberMultipliers: [2, 4, 5, 8, 10],
            _defaultGridSpacingFactor: 15,
            _getDatetimeTickInterval: function(businessDelta, deltaCoef, numberMultipliers) {
                var result,
                    i;
                for (i = numberMultipliers.length - 1; i >= 0; i--) {
                    this.testResultNumberMultiplier = numberMultipliers[i];
                    result = Math.floor(businessDelta / numberMultipliers[i]);
                    if (deltaCoef <= result)
                        return utils.convertMillisecondsToDateUnits(result)
                }
                return 0
            },
            _getNumericTickInterval: function(businessDelta, deltaCoef, numberMultipliers) {
                var result,
                    i;
                for (i = numberMultipliers.length - 1; i >= 0; i--) {
                    this.testResultNumberMultiplier = numberMultipliers[i];
                    result = businessDelta / numberMultipliers[i];
                    if (deltaCoef <= result)
                        return utils.adjustValue(result)
                }
                return 0
            },
            getTickInterval: function(type, businessDelta, screenDelta, gridSpacingFactor, numberMultipliers) {
                var self = this,
                    gridSpacingFactor = !utils.isDefined(gridSpacingFactor) ? self._defaultGridSpacingFactor : gridSpacingFactor,
                    numberMultipliers = numberMultipliers || self._defaultNumberMultipliers,
                    deltaCoef = gridSpacingFactor * businessDelta / screenDelta;
                switch (type) {
                    case'numeric':
                        return self._getNumericTickInterval(businessDelta, deltaCoef, numberMultipliers);
                    case'dateTime':
                        return self._getDatetimeTickInterval(businessDelta, deltaCoef, numberMultipliers)
                }
                return 0
            }
        };
        core.tickProvider = {
            _areDisplayValuesValid: function(value1, value2, options) {
                var getText = this._getTextFunc(options),
                    svgElement1 = options.renderer.createText(getText(value1), core.outOfScreen.x + options.translator.translateX(value1), core.outOfScreen.y, options.textOptions).append(),
                    svgElement2 = options.renderer.createText(getText(value2), core.outOfScreen.x + options.translator.translateX(value2), core.outOfScreen.y, options.textOptions).append(),
                    bBox1 = svgElement1.getBBox(),
                    bBox2 = svgElement2.getBBox(),
                    result,
                    inverted = options.translator.businessRange.invertX;
                result = !inverted ? bBox1.x + bBox1.width < bBox2.x : bBox2.x + bBox2.width < bBox1.x;
                svgElement1.remove();
                svgElement2.remove();
                return result
            },
            _removeInvalidDatesWithUnitBegining: function(dates, options) {
                if (dates.length <= 1 || !options.setTicksAtUnitBeginning || !utils.isDate(options.min))
                    return;
                if (!this._areDisplayValuesValid(dates[0], dates[1], options))
                    dates.splice(1, 1)
            },
            _getMaxDisplayValue: function(values, options) {
                var maxDisplayValue = null,
                    getText = this._getTextFunc(options),
                    currentDisplayValue,
                    i;
                if (values.length > 0) {
                    maxDisplayValue = getText(values[0]);
                    for (i = 1; i < values.length; i++) {
                        currentDisplayValue = getText(values[i]);
                        if (maxDisplayValue.length < currentDisplayValue.length)
                            maxDisplayValue = currentDisplayValue
                    }
                }
                return maxDisplayValue
            },
            _getValueSize: function(value, options) {
                if (value === null)
                    return 0;
                var svgElement = options.renderer.createText(value, core.outOfScreen.x, core.outOfScreen.y, options.textOptions).append(),
                    result = options.isHorizontal ? svgElement.getBBox().width : svgElement.getBBox().height;
                svgElement.remove();
                return Math.ceil(result)
            },
            _adjustNumericTickValue: function(value, interval, min) {
                return utils.isExponential(value) ? utils.adjustValue(value) : utils.applyPrecisionByMinDelta(min, interval, value)
            },
            _generateStartTick: function(tickInterval, options) {
                var self = this,
                    milliseconds = 0,
                    boundedRule = options.min - options.max < 0,
                    startTick = options.min,
                    isDate = utils.isDate(options.min),
                    currentTickInterval = isDate ? utils.convertDateTickIntervalToMilliseconds(tickInterval) : tickInterval;
                startTick = Math.floor(options.min / currentTickInterval) * currentTickInterval;
                startTick = isDate ? new Date(startTick) : self._adjustNumericTickValue(startTick, currentTickInterval, options.min);
                while (boundedRule === startTick - options.min < 0 && startTick !== options.min)
                    startTick = self._nextTick(startTick, tickInterval, options);
                return startTick
            },
            _nextTick: function(tick, tickInterval, options) {
                var nextTick = utils.addInterval(tick, tickInterval, options.min > options.max);
                if (utils.isNumber(options.min))
                    nextTick = this._adjustNumericTickValue(nextTick, tickInterval, options.min);
                if (utils.isDate(options.min) && options.setTicksAtUnitBeginning)
                    utils.correctDateWithUnitBeginning(nextTick, tickInterval);
                return nextTick
            },
            _addMinorTicks: function(majorTick1, majorTick2, ticksInfo, options, isReverse) {
                var self = this,
                    i,
                    dataType = utils.isDate(majorTick1) ? 'dateTime' : 'numeric',
                    businessDelta,
                    minorTicks = [],
                    interval = 0,
                    minorTickIntervalsCount = options.minorTickCount + 1,
                    intervalsCount,
                    tickInterval;
                options.min = majorTick1;
                options.max = majorTick2;
                if (!utils.isDefined(options.tickInterval)) {
                    businessDelta = Math.abs(options.max - options.min);
                    if (utils.isDefined(options.minorTickCount)) {
                        if (!ticksInfo.majorTicks.autoArrangementStep || ticksInfo.majorTicks.autoArrangementStep <= 1) {
                            intervalsCount = options.minorTickCount + 1;
                            interval = dataType === 'dateTime' ? utils.convertDateTickIntervalToMilliseconds(ticksInfo.majorTickInterval) : ticksInfo.majorTickInterval;
                            minorTickIntervalsCount = Math.round(businessDelta / interval * intervalsCount) || 1
                        }
                        tickInterval = dataType === 'dateTime' ? utils.convertMillisecondsToDateUnits(businessDelta / minorTickIntervalsCount) : businessDelta / minorTickIntervalsCount;
                        if ($.isNumeric(tickInterval))
                            tickInterval = utils.adjustValue(tickInterval)
                    }
                    else if (utils.isDate(majorTick1))
                        tickInterval = core.minorTickIntervalCalculator.getTickInterval(dataType, businessDelta, businessDelta * options.deltaCoef, options.gridSpacingFactor, options.numberMultipliers)
                }
                options = $.extend(true, {}, options, {tickInterval: tickInterval});
                minorTicks = self.getTicks(options);
                if (isReverse)
                    minorTicks.reverse();
                if (minorTicks.length > 0)
                    if (Math.ceil(Math.abs(majorTick2 - minorTicks[minorTicks.length - 1]) * options.deltaCoef) < 2)
                        minorTicks.pop();
                for (i = 0; i < minorTicks.length; i++) {
                    ticksInfo.minorTicks.push(minorTicks[i]);
                    ticksInfo.fullTicks.push(minorTicks[i])
                }
            },
            _addLeftBoudedTicks: function(ticksInfo, min, minorTicksOptions) {
                if (utils.isDefined(min) && ticksInfo.majorTicks[0].valueOf() !== min.valueOf()) {
                    minorTicksOptions.addMinMax.max = true;
                    this._addMinorTicks(ticksInfo.majorTicks[0], min, ticksInfo, minorTicksOptions, true);
                    minorTicksOptions.addMinMax.max = false;
                    if (minorTicksOptions.showCustomBoundaryTicks) {
                        if (ticksInfo.minorTicks.length > 0 && ticksInfo.minorTicks[0].valueOf() === min.valueOf())
                            ticksInfo.minorTicks.shift(min);
                        ticksInfo.customBoundaryTicks.push(min);
                        ticksInfo.fullTicks.unshift(min)
                    }
                }
            },
            _addRightBoudedTicks: function(ticksInfo, max, minorTicksOptions) {
                var lastMajorTick = ticksInfo.majorTicks[ticksInfo.majorTicks.length - 1];
                ticksInfo.fullTicks.push(lastMajorTick);
                if (utils.isDefined(max) && lastMajorTick.valueOf() !== max.valueOf()) {
                    minorTicksOptions.addMinMax.min = false;
                    minorTicksOptions.addMinMax.max = true;
                    this._addMinorTicks(lastMajorTick, max, ticksInfo, minorTicksOptions);
                    if (minorTicksOptions.showCustomBoundaryTicks) {
                        if (ticksInfo.minorTicks.length > 0 && ticksInfo.minorTicks[ticksInfo.minorTicks.length - 1].valueOf() === max.valueOf())
                            ticksInfo.minorTicks.pop(max);
                        ticksInfo.customBoundaryTicks.push(max);
                        ticksInfo.fullTicks.push(max)
                    }
                }
            },
            _correctBoundedTicks: function(min, max, ticks, addMinMax) {
                addMinMax = $.extend({}, {
                    min: true,
                    max: true
                }, addMinMax);
                if (ticks.length > 0) {
                    if (!addMinMax.min && ticks[0].valueOf() === min.valueOf())
                        ticks.shift();
                    if (!addMinMax.max || ticks[ticks.length - 1].valueOf() !== max.valueOf())
                        ticks.pop()
                }
            },
            _initializeMinorTicksOptions: function(dataType, min, max, screenDelta, ticksInfo, options) {
                var self = this,
                    businessDelta,
                    hasMinorsCount = utils.isDefined(options.minorTickCount);
                $.extend(true, options, {
                    addMinMax: {
                        min: false,
                        max: false
                    },
                    deltaCoef: self._getDeltaCoef(screenDelta, min, max)
                }, options);
                options.numberMultipliers = hasMinorsCount ? [options.minorTickCount + 1] : options.numberMultipliers;
                options.gridSpacingFactor = hasMinorsCount ? 0 : options.gridSpacingFactor;
                if (!hasMinorsCount && ticksInfo.majorTicks.length > 1) {
                    businessDelta = Math.abs(ticksInfo.majorTicks[0] - ticksInfo.majorTicks[1]);
                    if (self.needTickIntervalCalculation(businessDelta, ticksInfo.minorTickInterval, options.incidentOccured)) {
                        ticksInfo.minorTickInterval = core.minorTickIntervalCalculator.getTickInterval(dataType, businessDelta, businessDelta * options.deltaCoef, options.gridSpacingFactor, options.numberMultipliers);
                        if (utils.isNumber(min))
                            options.tickInterval = ticksInfo.minorTickInterval;
                        else
                            options.tickInterval = undefined
                    }
                }
            },
            _getDataType: function(value) {
                return utils.isDate(value) ? 'dateTime' : 'numeric'
            },
            _getDeltaCoef: function(screenDelta, max, min) {
                return screenDelta / Math.abs(max - min)
            },
            _initializeMajorTicksOptions: function(dataType, min, max, screenDelta, ticksInfo, options) {
                var businessDelta;
                $.extend(true, options, {
                    min: min,
                    max: max,
                    screenDelta: screenDelta,
                    isHorizontal: true
                });
                if (utils.isDefined(min) && utils.isDefined(max)) {
                    businessDelta = Math.abs(max - min);
                    if (this.needTickIntervalCalculation(businessDelta, ticksInfo.majorTickInterval, options.incidentOccured)) {
                        options.isStartTickGenerated = true;
                        ticksInfo.majorTickInterval = core.tickIntervalCalculator.getTickInterval(dataType, businessDelta, screenDelta, options.gridSpacingFactor, options.numberMultipliers);
                        options.tickInterval = ticksInfo.majorTickInterval
                    }
                }
            },
            _getTextFunc: function(options) {
                return options.getText || function(value) {
                        return value.toString()
                    }
            },
            needTickIntervalCalculation: function(businessDelta, tickInterval, incidentOccured) {
                var date;
                if (utils.isDefined(tickInterval)) {
                    if (!utils.isNumber(tickInterval)) {
                        date = new Date;
                        tickInterval = utils.addInterval(date, tickInterval) - date;
                        if (!tickInterval)
                            return true
                    }
                    if (utils.isNumber(tickInterval))
                        if (tickInterval > 0 && businessDelta / tickInterval > TICKS_COUNT_LIMIT) {
                            if (incidentOccured)
                                incidentOccured('Tick count is too big. So, the tick interval is specified automatically.')
                        }
                        else
                            return false
                }
                return true
            },
            getAutoArrangementStep: function(ticks, options) {
                var self = this,
                    maxDisplayValue = this._getMaxDisplayValue(ticks, options),
                    maxDisplayValueSize = this._getValueSize(maxDisplayValue, options),
                    requiredValuesCount,
                    addedSpacing = options.isHorizontal ? options.textSpacing : 0;
                if (maxDisplayValueSize > 0) {
                    requiredValuesCount = Math.floor((options.screenDelta + options.textSpacing) / (maxDisplayValueSize + addedSpacing));
                    return Math.ceil((options.ticksCount || ticks.length) / requiredValuesCount)
                }
                return 1
            },
            getAutoArrangementTicks: function(ticks, options, step) {
                var self = this,
                    resultTicks = ticks,
                    step = utils.isNumber(step) ? step : self.getAutoArrangementStep(ticks, options),
                    i;
                if (step > 1) {
                    resultTicks = [];
                    for (i = 0; i < ticks.length; i += step)
                        resultTicks.push(ticks[i])
                }
                self._removeInvalidDatesWithUnitBegining(resultTicks, options);
                resultTicks.autoArrangementStep = step;
                return resultTicks
            },
            getTickIntervals: function(min, max, screenDelta, majorTicksOptions, minorTicksOptions) {
                var self = this,
                    i,
                    businessDelta,
                    dataType = self._getDataType(min),
                    ticksInfo = {
                        majorTickInterval: majorTicksOptions.tickInterval,
                        minorTickInterval: minorTicksOptions.tickInterval,
                        majorTicks: []
                    };
                self._initializeMajorTicksOptions(dataType, min, max, screenDelta, ticksInfo, majorTicksOptions);
                if (utils.isDefined(min) && utils.isDefined(max)) {
                    ticksInfo.majorTicks.push(min);
                    ticksInfo.majorTicks.push(self._nextTick(min, ticksInfo.majorTickInterval, {
                        min: min,
                        max: max,
                        setTicksAtUnitBeginning: majorTicksOptions.setTicksAtUnitBeginning
                    }));
                    businessDelta = Math.abs(ticksInfo.majorTicks[0] - ticksInfo.majorTicks[1]);
                    self._initializeMinorTicksOptions(dataType, min, max, screenDelta, ticksInfo, minorTicksOptions)
                }
                return ticksInfo
            },
            getFullTicks: function(min, max, screenDelta, majorTicksOptions, minorTicksOptions) {
                var self = this,
                    i,
                    dataType = self._getDataType(min),
                    ticksInfo = {
                        customBoundaryTicks: [],
                        fullTicks: [],
                        majorTickInterval: majorTicksOptions.tickInterval,
                        majorTicks: [],
                        minorTickInterval: minorTicksOptions.tickInterval,
                        minorTicks: []
                    };
                self._initializeMajorTicksOptions(dataType, min, max, screenDelta, ticksInfo, majorTicksOptions);
                ticksInfo.majorTicks = self.getTicks(majorTicksOptions);
                if (utils.isDefined(min) && utils.isDefined(max) && ticksInfo.majorTicks.length > 0) {
                    if (ticksInfo.majorTicks.autoArrangementStep && ticksInfo.majorTicks.autoArrangementStep > 1 && !utils.isDefined(minorTicksOptions.tickInterval) && !utils.isDefined(minorTicksOptions.minorTickCount))
                        minorTicksOptions.tickInterval = ticksInfo.minorTickInterval = majorTicksOptions.tickInterval;
                    self._initializeMinorTicksOptions(dataType, min, max, screenDelta, ticksInfo, minorTicksOptions);
                    self._addLeftBoudedTicks(ticksInfo, min, minorTicksOptions);
                    for (i = 0; i < ticksInfo.majorTicks.length - 1; i++) {
                        ticksInfo.fullTicks.push(ticksInfo.majorTicks[i]);
                        self._addMinorTicks(ticksInfo.majorTicks[i], ticksInfo.majorTicks[i + 1], ticksInfo, minorTicksOptions)
                    }
                    self._addRightBoudedTicks(ticksInfo, max, minorTicksOptions)
                }
                return ticksInfo
            },
            getTicks: function(options) {
                var self = this,
                    ticks = [],
                    tick,
                    boundedRule = options.max - options.min > 0,
                    leftBound,
                    rightBound,
                    tickInterval,
                    isStartTickGenerated = options.isStartTickGenerated,
                    businessDelta,
                    useTicksAutoArrangement = options.useTicksAutoArrangement;
                if (!utils.isDefined(options.min) || !utils.isDefined(options.max) || isNaN(options.min) || isNaN(options.max)) {
                    ticks = options.isHorizontal ? ['canvas_position_left', 'canvas_position_center', 'canvas_position_right'] : ['canvas_position_bottom', 'canvas_position_middle', 'canvas_position_top'];
                    useTicksAutoArrangement = false;
                    ticks.hideLabels = true
                }
                else {
                    tickInterval = $.isNumeric(options.min) && $.isNumeric(options.max) && !$.isNumeric(options.tickInterval) ? undefined : options.tickInterval;
                    businessDelta = Math.abs(options.max - options.min);
                    if (this.needTickIntervalCalculation(businessDelta, tickInterval, options.incidentOccured)) {
                        isStartTickGenerated = utils.isDefined(isStartTickGenerated) ? isStartTickGenerated : true;
                        tickInterval = core.tickIntervalCalculator.getTickInterval(utils.isDate(options.min) ? 'dateTime' : 'numeric', Math.abs(options.max - options.min), options.screenDelta, options.gridSpacingFactor, options.numberMultipliers)
                    }
                    self.isTestStartTickGenerated = isStartTickGenerated;
                    self.isTestTickInterval = tickInterval;
                    if (tickInterval.valueOf() !== 0 && options.min.valueOf() !== options.max.valueOf()) {
                        tick = isStartTickGenerated ? self._generateStartTick(tickInterval, options) : options.min;
                        do {
                            ticks.push(tick);
                            tick = self._nextTick(tick, tickInterval, options);
                            if (ticks[ticks.length - 1].valueOf() === tick.valueOf())
                                break;
                            leftBound = tick - options.min > 0;
                            rightBound = options.max - tick > 0
                        } while (boundedRule === leftBound && boundedRule === rightBound);
                        ticks.push(tick);
                        self._correctBoundedTicks(options.min, options.max, ticks, options.addMinMax)
                    }
                }
                if (options.beforeTicksAutoArrangement)
                    options.beforeTicksAutoArrangement(ticks);
                return useTicksAutoArrangement ? self.getAutoArrangementTicks(ticks, options) : ticks
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz, file linearTranslator.js */
    (function($, DX, undefined) {
        var utils = DX.utils,
            isNumber = utils.isNumber,
            isDate = utils.isDate,
            isDefined = utils.isDefined,
            round = Math.round;
        DX.viz.core.LinearTranslator = DX.Class.inherit(function() {
            var ctor = function(businessRanges, canvas) {
                    this.canvas = canvas;
                    this.updateBusinessRange(businessRanges)
                };
            var dispose = function() {
                    var _this = this;
                    _this.canvas = null;
                    _this.businessRange.dispose();
                    _this.businessRange = null;
                    _this.categoriesXToPoints = null;
                    _this.categoriesYToPoints = null
                };
            var init = function() {
                    var _this = this,
                        canvas = _this.canvas,
                        range = _this.businessRange,
                        categoriesX = _this.businessRange.categoriesX,
                        categoriesY = _this.businessRange.categoriesY,
                        i,
                        category;
                    _this.width = canvas.width - canvas.left - canvas.right;
                    _this.height = canvas.height - canvas.top - canvas.bottom;
                    if (categoriesX) {
                        _this.categoriesXNumber = categoriesX.length;
                        if (range.stickX)
                            _this.horizontalInterval = _this.width / (_this.categoriesXNumber - 1);
                        else
                            _this.horizontalInterval = _this.width / _this.categoriesXNumber;
                        _this.categoriesXToPoints = makeCategoriesToPoints(categoriesX, _this.businessRange.invertX);
                        _this.translateX = translateCategoryX;
                        _this.getIntervalX = getCategoryIntervalX
                    }
                    else {
                        _this.translateX = translateContinousX;
                        _this.getIntervalX = getContinousIntervalX;
                        if (isNumber(range.minX))
                            _this.untranslateX = untranslateContinousX;
                        else if (isDate(range.minX))
                            _this.untranslateX = untranslateDatetimeX
                    }
                    if (categoriesY) {
                        _this.categoriesYNumber = categoriesY.length;
                        if (range.stickY)
                            _this.verticalInterval = _this.height / (_this.categoriesYNumber - 1);
                        else
                            _this.verticalInterval = _this.height / _this.categoriesYNumber;
                        _this.categoriesYToPoints = makeCategoriesToPoints(categoriesY, _this.businessRange.invertY);
                        _this.translateY = translateCategoryY;
                        _this.getIntervalY = getCategoryIntervalY
                    }
                    else {
                        _this.translateY = translateContinousY;
                        _this.getIntervalY = getContinousIntervalY;
                        if (isNumber(range.minY))
                            _this.untranslateY = untranslateContinousY;
                        else if (isDate(range.minY))
                            _this.untranslateY = untranslateDatetimeY
                    }
                };
            var updateBusinessRange = function(businessRange) {
                    this.businessRange = businessRange;
                    if (businessRange.minVisibleX === undefined)
                        businessRange.minVisibleX = businessRange.minX;
                    if (businessRange.maxVisibleX === undefined)
                        businessRange.maxVisibleX = businessRange.maxX;
                    if (businessRange.minVisibleY === undefined)
                        businessRange.minVisibleY = businessRange.minY;
                    if (businessRange.maxVisibleY === undefined)
                        businessRange.maxVisibleY = businessRange.maxY;
                    this.init()
                };
            var getBusinessRange = function() {
                    return this.businessRange
                };
            var zoomX = function(min, max) {
                    var businessRange = this.businessRange;
                    businessRange.minVisibleX = min;
                    businessRange.maxVisibleX = max;
                    businessRange.applyEqualLimitsMargins();
                    this.init()
                };
            var zoomY = function(min, max) {
                    var businessRange = this.businessRange;
                    businessRange.minVisibleY = min;
                    businessRange.maxVisibleY = max;
                    businessRange.applyEqualLimitsMargins();
                    this.init()
                };
            var translateSpecialCases = function(_this, value, position) {
                    var parsedValue = (value + '').match(/canvas_position_(.*)/),
                        canvas = _this.canvas,
                        range = _this.businessRange;
                    if (parsedValue) {
                        value = parsedValue[1];
                        if (value === 'default') {
                            if (range['minVisible' + position] <= 0 && 0 <= range['maxVisible' + position])
                                return _this['translate' + position](0);
                            if (position === 'X')
                                if (range.invertX)
                                    return canvas.left + _this.width;
                                else
                                    return canvas.left;
                            else if (range.invertY)
                                return canvas.top;
                            else
                                return canvas.top + _this.height
                        }
                        if (position === "X") {
                            if (value === 'left')
                                return canvas.left;
                            if (value === 'center')
                                return canvas.left + _this.width / 2;
                            if (value === 'right')
                                return canvas.left + _this.width
                        }
                        else {
                            if (value === 'bottom')
                                return canvas.top + _this.height;
                            if (value === 'middle')
                                return canvas.top + _this.height / 2;
                            if (value === 'top')
                                return canvas.top
                        }
                    }
                    return null
                };
            var translateContinousX = function(bpX) {
                    var _this = this,
                        ranges = _this.businessRange,
                        canvas = _this.canvas,
                        result;
                    var specialValue = translateSpecialCases(_this, bpX, "X");
                    if (isDefined(specialValue))
                        return specialValue;
                    if (bpX < ranges.minX)
                        return null;
                    if (bpX > ranges.maxX)
                        return null;
                    if (ranges.invertX)
                        result = canvas.left + (1 - (bpX - ranges.minVisibleX) / (ranges.maxVisibleX - ranges.minVisibleX)) * _this.width;
                    else
                        result = canvas.left + (bpX - ranges.minVisibleX) / (ranges.maxVisibleX - ranges.minVisibleX) * _this.width;
                    return round(result)
                };
            var untranslateContinousX = function(posX) {
                    var _this = this,
                        ranges = _this.businessRange,
                        canvas = _this.canvas;
                    if (posX < canvas.left)
                        return null;
                    if (posX > canvas.left + _this.width)
                        return null;
                    if (ranges.invertX)
                        return ranges.minVisibleX + (_this.width - (posX - canvas.left)) * (ranges.maxVisibleX - ranges.minVisibleX) / _this.width;
                    else
                        return ranges.minVisibleX + (posX - canvas.left) * (ranges.maxVisibleX - ranges.minVisibleX) / _this.width
                };
            var untranslateDatetimeX = function(posX) {
                    var _this = this,
                        ranges = _this.businessRange,
                        canvas = _this.canvas;
                    if (posX < canvas.left)
                        return null;
                    if (posX > canvas.left + _this.width)
                        return null;
                    if (ranges.invertX)
                        return new Date(ranges.minVisibleX.valueOf() + (_this.width - (posX - canvas.left)) * (ranges.maxVisibleX - ranges.minVisibleX) / _this.width);
                    else
                        return new Date(ranges.minVisibleX.valueOf() + (posX - canvas.left) * (ranges.maxVisibleX - ranges.minVisibleX) / _this.width)
                };
            var translateContinousY = function(bpY) {
                    var _this = this,
                        ranges = _this.businessRange,
                        canvas = _this.canvas,
                        result;
                    var specialValue = translateSpecialCases(_this, bpY, "Y");
                    if (isDefined(specialValue))
                        return specialValue;
                    if (bpY < ranges.minY)
                        return null;
                    if (bpY > ranges.maxY)
                        return null;
                    if (ranges.invertY)
                        result = canvas.height - canvas.bottom - (1 - (bpY - ranges.minVisibleY) / (ranges.maxVisibleY - ranges.minVisibleY)) * _this.height;
                    else
                        result = canvas.height - canvas.bottom - (bpY - ranges.minVisibleY) / (ranges.maxVisibleY - ranges.minVisibleY) * _this.height;
                    return round(result)
                };
            var untranslateContinousY = function(posY) {
                    var _this = this,
                        ranges = _this.businessRange,
                        canvas = _this.canvas;
                    if (posY < canvas.top)
                        return null;
                    if (posY > canvas.top + _this.height)
                        return null;
                    if (ranges.invertY)
                        return ranges.maxVisibleY - (_this.height - (posY - canvas.top)) * (ranges.maxVisibleY - ranges.minVisibleY) / _this.height;
                    else
                        return ranges.maxVisibleY - (posY - canvas.top) * (ranges.maxVisibleY - ranges.minVisibleY) / _this.height
                };
            var untranslateDatetimeY = function(posY) {
                    var _this = this,
                        ranges = _this.businessRange,
                        canvas = _this.canvas;
                    if (posY < canvas.top)
                        return null;
                    if (posY > canvas.top + _this.height)
                        return null;
                    if (ranges.invertY)
                        return new Date(ranges.maxVisibleY.valueOf() - (_this.height - (posY - canvas.top)) * (ranges.maxVisibleY - ranges.minVisibleY) / _this.height);
                    else
                        return new Date(ranges.maxVisibleY.valueOf() - (posY - canvas.top) * (ranges.maxVisibleY - ranges.minVisibleY) / _this.height)
                };
            var translateCategoryX = function(category) {
                    var _this = this,
                        canvas = _this.canvas,
                        categoryRecord,
                        result = 0;
                    var specialValue = translateSpecialCases(_this, category, "X");
                    if (isDefined(specialValue))
                        return specialValue;
                    categoryRecord = _this.categoriesXToPoints[category];
                    if (!categoryRecord)
                        return 0;
                    if (_this.businessRange.stickX)
                        result = canvas.left + _this.horizontalInterval * categoryRecord.index;
                    else
                        result = canvas.left + _this.horizontalInterval * (categoryRecord.index + 0.5);
                    return round(result)
                };
            var getCategoryIntervalX = function() {
                    return this.horizontalInterval
                };
            var translateCategoryY = function(category) {
                    var _this = this,
                        canvas = _this.canvas,
                        categoryRecord,
                        result = 0;
                    var specialValue = translateSpecialCases(_this, category, "Y");
                    if (isDefined(specialValue))
                        return specialValue;
                    categoryRecord = _this.categoriesYToPoints[category];
                    if (!categoryRecord)
                        return 0;
                    if (_this.businessRange.stickY)
                        result = canvas.top + _this.verticalInterval * categoryRecord.index;
                    else
                        result = canvas.top + _this.verticalInterval * (categoryRecord.index + 0.5);
                    return round(result)
                };
            var getCategoryIntervalY = function() {
                    return this.verticalInterval
                };
            var getContinousIntervalX = function() {
                    var _this = this,
                        result = 0;
                    if (_this.businessRange.intervalX !== undefined)
                        result = _this.width * _this.businessRange.intervalX / (_this.businessRange.maxVisibleX - _this.businessRange.minVisibleX);
                    return round(result)
                };
            var getContinousIntervalY = function() {
                    var _this = this,
                        result = 0;
                    if (_this.businessRange.intervalY !== undefined)
                        result = _this.height * _this.businessRange.intervalY / (_this.businessRange.maxVisibleY - _this.businessRange.minVisibleY);
                    return round(result)
                };
            var getBusinessVisibleArea = function() {
                    var range = this.businessRange,
                        visibleArea = {};
                    visibleArea.minX = range.minVisibleX;
                    visibleArea.maxX = range.maxVisibleX;
                    visibleArea.minY = range.minVisibleY;
                    visibleArea.maxY = range.maxVisibleY;
                    if (range.categoriesX) {
                        visibleArea.categoriesX = range.categoriesX;
                        visibleArea.minCategoryXPos = 0;
                        visibleArea.maxCategoryXPos = visibleArea.minCategoryXPos + visibleArea.categoriesX.length - 1
                    }
                    if (range.categoriesY) {
                        visibleArea.categoriesY = range.categoriesY;
                        visibleArea.minCategoryYPos = 0;
                        visibleArea.maxCategoryYPos = visibleArea.minCategoryYPos + visibleArea.categoriesY.length - 1
                    }
                    return visibleArea
                };
            var getCanvasVisibleArea = function() {
                    var canvas = this.canvas;
                    return {
                            minX: canvas.left,
                            maxX: canvas.width - canvas.right,
                            minY: canvas.top,
                            maxY: canvas.height - canvas.bottom
                        }
                };
            var makeCategoriesToPoints = function(categories, invert) {
                    var categoriesToPoints = {},
                        category,
                        i;
                    if (invert)
                        for (i = categories.length - 1; i >= 0; i--) {
                            category = categories[categories.length - 1 - i];
                            categoriesToPoints[category] = {
                                name: category,
                                index: i
                            }
                        }
                    else
                        for (i = 0; i < categories.length; i++) {
                            category = categories[i];
                            categoriesToPoints[category] = {
                                name: category,
                                index: i
                            }
                        }
                    return categoriesToPoints
                };
            var prototypeObject = {
                    ctor: ctor,
                    dispose: dispose,
                    init: init,
                    getCanvasVisibleArea: getCanvasVisibleArea,
                    getBusinessVisibleArea: getBusinessVisibleArea,
                    updateBusinessRange: updateBusinessRange,
                    getBusinessRange: getBusinessRange,
                    zoomX: zoomX,
                    zoomY: zoomY
                };
            prototypeObject.translateCategoryX = translateCategoryX;
            prototypeObject.translateCategoryY = translateCategoryY;
            prototypeObject.getCategoryIntervalX = getCategoryIntervalX;
            prototypeObject.getCategoryIntervalY = getCategoryIntervalY;
            prototypeObject.translateContinousX = translateContinousX;
            prototypeObject.translateContinousY = translateContinousY;
            prototypeObject.getContinousIntervalX = getContinousIntervalX;
            prototypeObject.getContinousIntervalY = getContinousIntervalY;
            prototypeObject.untranslateContinousX = untranslateContinousX;
            prototypeObject.untranslateContinousY = untranslateContinousY;
            prototypeObject.untranslateDatetimeX = untranslateDatetimeX;
            prototypeObject.untranslateDatetimeY = untranslateDatetimeY;
            return prototypeObject
        }())
    })(jQuery, DevExpress);
    /*! Module viz, file translator1D.js */
    (function(DX, undefined) {
        var NaN = window.NaN,
            Number = window.Number;
        DX.viz.core.Translator1D = DX.Class.inherit({
            ctor: function(domainStart, domainEnd, codomainStart, codomainEnd) {
                DX.utils.debug.assertParam(domainStart, 'domainStart was not passed');
                DX.utils.debug.assertParam(domainEnd, 'domainEnd was not passed');
                DX.utils.debug.assertParam(codomainStart, 'codomainStart was not passed');
                DX.utils.debug.assertParam(codomainEnd, 'codomainEnd was not passed');
                var self = this;
                self._domainStart = Number(domainStart);
                self._domainEnd = Number(domainEnd);
                self._codomainStart = Number(codomainStart);
                self._codomainEnd = Number(codomainEnd);
                self._domainDelta = self._domainEnd - self._domainStart;
                self._codomainDelta = self._codomainEnd - self._codomainStart
            },
            getDomainStart: function() {
                return this._domainStart
            },
            getDomainEnd: function() {
                return this._domainEnd
            },
            getCodomainStart: function() {
                return this._codomainStart
            },
            getCodomainEnd: function() {
                return this._codomainEnd
            },
            getDomainRange: function() {
                return this._domainDelta
            },
            getCodomainRange: function() {
                return this._codomainDelta
            },
            translate: function(value) {
                var self = this,
                    ratio = (value - self._domainStart) / self._domainDelta;
                return 0 <= ratio && ratio <= 1 ? self._codomainStart + ratio * self._codomainDelta : NaN
            },
            adjust: function(value) {
                var self = this,
                    ratio = (value - self._domainStart) / self._domainDelta,
                    result = NaN;
                if (ratio < 0)
                    result = self._domainStart;
                else if (ratio > 1)
                    result = self._domainEnd;
                else if (0 <= ratio && ratio <= 1)
                    result = Number(value);
                return result
            }
        })
    })(DevExpress);
    /*! Module viz, file rectangle.js */
    (function(DX, undefined) {
        var isFinite = window.isFinite;
        DX.viz.core.Rectangle = DX.Class.inherit({
            ctor: function(options) {
                var self = this;
                options = options || {};
                self.left = Number(options.left) || 0;
                self.right = Number(options.right) || 0;
                self.top = Number(options.top) || 0;
                self.bottom = Number(options.bottom) || 0
            },
            width: function() {
                return this.right - this.left
            },
            height: function() {
                return this.bottom - this.top
            },
            horizontalMiddle: function() {
                return (this.left + this.right) / 2
            },
            verticalMiddle: function() {
                return (this.top + this.bottom) / 2
            },
            raw: function() {
                var self = this;
                return {
                        left: self.left,
                        top: self.top,
                        right: self.right,
                        bottom: self.bottom
                    }
            },
            clone: function() {
                return new this.constructor(this.raw())
            },
            move: function(dx, dy) {
                var result = this.clone();
                if (isFinite(dx) && isFinite(dy)) {
                    result.left += Number(dx);
                    result.right += Number(dx);
                    result.top += Number(dy);
                    result.bottom += Number(dy)
                }
                return result
            },
            inflate: function(dx, dy) {
                var result = this.clone();
                if (isFinite(dx) && isFinite(dy)) {
                    result.left -= Number(dx);
                    result.right += Number(dx);
                    result.top -= Number(dy);
                    result.bottom += Number(dy)
                }
                return result
            },
            scale: function(factor) {
                var self = this;
                if (factor > 0)
                    return self.inflate(self.width() * (factor - 1) / 2, self.height() * (factor - 1) / 2);
                return self.clone()
            }
        })
    })(DevExpress);
    /*! Module viz, file themes.js */
    (function($, DX, undefined) {
        var core = DX.viz.core,
            viz = DX.viz;
        core.findTheme = function(themeName) {
            var themes = viz.themes,
                theme,
                themeId;
            for (themeId = 0; themeId < themes.length; themeId++) {
                theme = themes[themeId];
                if (theme.name === themeName)
                    return theme
            }
        };
        core.registerTheme = function(theme, basedOnThemeName) {
            var baseTheme,
                extendedTheme;
            if (!theme || !theme.name || core.findTheme(theme.name))
                return;
            if (basedOnThemeName) {
                baseTheme = core.findTheme(basedOnThemeName);
                if (baseTheme) {
                    extendedTheme = $.extend(true, {}, baseTheme, theme);
                    viz.themes.push(extendedTheme)
                }
            }
            else
                viz.themes.push(theme)
        }
    })(jQuery, DevExpress);
    /*! Module viz, file palette.js */
    (function($, DX, undefined) {
        var core = DX.viz.core;
        core.palettes = {
            'default': ['#5F8B95', '#BA4D51', '#AF8A53', '#955F71', '#859666', '#7E688C'],
            'Harmony Light': ['#FCB65E', '#679EC5', '#AD79CE', '#A6C567', '#E18E92', '#DDED6E', '#B7ABEA', '#A8E7E3'],
            'Soft Pastel': ['#7CBAB4', '#92C7E2', '#75B5D6', '#B78C9B', '#F2CA84', '#A7CA74']
        };
        core.findPalette = function(paletteName) {
            return core.palettes[paletteName]
        };
        core.registerPalette = function(paletteName, palette) {
            return core.palettes[paletteName] = palette
        };
        function RingBuf(buf) {
            var ind = 0;
            this.next = function() {
                var res = buf[ind++];
                if (ind == buf.length)
                    this.reset();
                return res
            };
            this.reset = function() {
                ind = 0
            }
        }
        core.Palette = DX.Class.inherit({
            ctor: function(palette, stepHighlight) {
                var self = this;
                self.currentColor = 0;
                self.stepHighlight = stepHighlight || 0;
                if ($.isArray(palette))
                    self.originalPalette = palette;
                else {
                    self.originalPalette = core.findPalette(palette);
                    if (!self.originalPalette)
                        self.originalPalette = core.palettes['default']
                }
                self.palette = self.originalPalette.slice(0);
                self.paletteActions = new RingBuf(['highlight', 'highlight', 'darken', 'darken'])
            },
            dispose: function() {
                this.originalPalette = null;
                this.palette = null;
                this.paletteActions = null
            },
            getNextColor: function() {
                var self = this,
                    palette = self.palette,
                    color = palette[self.currentColor],
                    action;
                self.currentColor++;
                if (self.currentColor >= palette.length) {
                    self.currentColor = 0;
                    if (self.stepHighlight) {
                        action = self.paletteActions.next();
                        for (var i = 0; i < palette.length; i++)
                            palette[i] = new DX.Color(palette[i])[action](self.stepHighlight)
                    }
                }
                return color
            },
            reset: function() {
                this.currentColor = 0;
                this.palette = this.originalPalette.slice(0);
                this.paletteActions.reset()
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file baseThemeManager.js */
    (function($, DX, undefined) {
        var viz = DX.viz,
            core = viz.core;
        var findThemeOrDefault = function(themeName) {
                return core.findTheme(themeName) || viz.themes[0]
            };
        core.BaseThemeManager = DX.Class.inherit({
            ctor: function(userTheme, themeGroupName) {
                userTheme = userTheme || {};
                var _this = this,
                    themeName = typeof userTheme === 'string' ? userTheme : userTheme.name,
                    theme = findThemeOrDefault(themeName);
                _this.font = $.extend(true, {}, theme.font, userTheme.font || {});
                if (themeGroupName && theme)
                    $.each(themeGroupName.split('.'), function() {
                        theme = theme[this]
                    });
                _this.theme = $.extend(true, {}, theme || {}, typeof userTheme === 'string' ? {} : userTheme)
            },
            dispose: function() {
                this.font = null;
                this.theme = null
            },
            initializeFont: function(fontOptions) {
                $.extend(fontOptions, this.font, $.extend({}, fontOptions))
            },
            applyTheme: function(theme, userOptions) {
                return $.extend(true, {}, theme, userOptions || {})
            },
            getTheme: function() {
                return this.theme
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file textCloud.js */
    (function(DX, undefined) {
        var min = Math.min;
        DX.viz.core.TextCloud = DX.Class.inherit(function() {
            var DEFAULT_OPTIONS = {
                    horMargin: 8,
                    verMargin: 4,
                    tailLength: 10
                };
            var COEFFICIENTS_MAP = {};
            COEFFICIENTS_MAP['right-bottom'] = COEFFICIENTS_MAP['rb'] = [0, -1, -1, 0, 0, 1, 1, 0];
            COEFFICIENTS_MAP['bottom-right'] = COEFFICIENTS_MAP['br'] = [-1, 0, 0, -1, 1, 0, 0, 1];
            COEFFICIENTS_MAP['left-bottom'] = COEFFICIENTS_MAP['lb'] = [0, -1, 1, 0, 0, 1, -1, 0];
            COEFFICIENTS_MAP['bottom-left'] = COEFFICIENTS_MAP['bl'] = [1, 0, 0, -1, -1, 0, 0, 1];
            COEFFICIENTS_MAP['left-top'] = COEFFICIENTS_MAP['lt'] = [0, 1, 1, 0, 0, -1, -1, 0];
            COEFFICIENTS_MAP['top-left'] = COEFFICIENTS_MAP['tl'] = [1, 0, 0, 1, -1, 0, 0, -1];
            COEFFICIENTS_MAP['right-top'] = COEFFICIENTS_MAP['rt'] = [0, 1, -1, 0, 0, -1, 1, 0];
            COEFFICIENTS_MAP['top-right'] = COEFFICIENTS_MAP['tr'] = [-1, 0, 0, 1, 1, 0, 0, -1];
            return {
                    setup: function(options) {
                        var self = this,
                            ops = $.extend({}, DEFAULT_OPTIONS, options),
                            x = ops.x,
                            y = ops.y,
                            type = COEFFICIENTS_MAP[ops.type],
                            cloudWidth = ops.textWidth + 2 * ops.horMargin,
                            cloudHeight = ops.textHeight + 2 * ops.verMargin,
                            tailWidth = ops.tailLength,
                            tailHeight = tailWidth,
                            cx = x,
                            cy = y;
                        if (type[0] & 1)
                            tailHeight = min(tailHeight, cloudHeight / 3);
                        else
                            tailWidth = min(tailWidth, cloudWidth / 3);
                        self._points = [x, y, x += type[0] * (cloudWidth + tailWidth), y += type[1] * (cloudHeight + tailHeight), x += type[2] * cloudWidth, y += type[3] * cloudHeight, x += type[4] * cloudWidth, y += type[5] * cloudHeight, x += type[6] * (cloudWidth - tailWidth), y += type[7] * (cloudHeight - tailHeight)];
                        self._cx = cx + type[0] * tailWidth + (type[0] + type[2]) * cloudWidth / 2;
                        self._cy = cy + type[1] * tailHeight + (type[1] + type[3]) * cloudHeight / 2;
                        self._cloudWidth = cloudWidth;
                        self._cloudHeight = cloudHeight;
                        self._tailLength = ops.tailLength;
                        return self
                    },
                    points: function() {
                        return this._points.slice(0)
                    },
                    cx: function() {
                        return this._cx
                    },
                    cy: function() {
                        return this._cy
                    },
                    width: function() {
                        return this._cloudWidth
                    },
                    height: function() {
                        return this._cloudHeight
                    },
                    tailLength: function() {
                        return this._tailLength
                    }
                }
        }())
    })(DevExpress);
    /*! Module viz, file parseUtils.js */
    (function($, DX) {
        var viz = DX.viz,
            core = viz.core,
            Class = DX.Class,
            isDefined = DX.utils.isDefined;
        var parseUtils = Class.inherit({
                ctor: function(options) {
                    options = options || {};
                    this._incidentOccured = $.isFunction(options.incidentOccured) ? options.incidentOccured : $.noop
                },
                correctValueType: function(type) {
                    return type === 'numeric' || type === 'datetime' || type === 'string' ? type : ''
                },
                _parsers: {
                    string: function(val) {
                        return isDefined(val) ? '' + val : val
                    },
                    numeric: function(val) {
                        if (!isDefined(val))
                            return val;
                        var parsedVal = Number(val);
                        if (isNaN(parsedVal))
                            parsedVal = undefined;
                        return parsedVal
                    },
                    datetime: function(val) {
                        if (!isDefined(val))
                            return val;
                        var parsedVal,
                            numVal = Number(val);
                        if (!isNaN(numVal))
                            parsedVal = new Date(numVal);
                        else
                            parsedVal = new Date(val);
                        if (isNaN(Number(parsedVal)))
                            parsedVal = undefined;
                        return parsedVal
                    }
                },
                getParser: function(valueType, entity) {
                    var self = this,
                        parser,
                        message = 'valueType is unknown.';
                    if (entity)
                        message = 'The type specified as the valueType property of the ' + entity + ' configuration object is unknown.';
                    valueType = self.correctValueType(valueType);
                    parser = self._parsers[valueType];
                    if (!parser)
                        this._incidentOccured.call(null, message);
                    return parser || $.noop
                }
            });
        core.ParseUtils = parseUtils
    })(jQuery, DevExpress);
    /*! Module viz, file default.js */
    (function($, DX, undefined) {
        DX.viz.themes = DX.viz.themes || [];
        DX.viz.themes.push({
            name: 'default',
            font: {
                color: '#808080',
                opacity: 0.75,
                family: "'SegoeUI', 'Segoe UI', 'HelveticaNeue', 'Helvetica Neue', 'Trebuchet MS', Verdana",
                weight: 400,
                size: 12,
                cursor: 'default'
            },
            chart: {
                containerBackgroundColor: '#FFFFFF',
                defaultPalette: 'default',
                commonSeriesSettings: {
                    border: {
                        visible: false,
                        width: 2
                    },
                    hoverMode: 'excludePoints',
                    selectionMode: 'includePoints',
                    hoverStyle: {
                        hatching: 'none',
                        border: {
                            visible: false,
                            width: 3
                        }
                    },
                    selectionStyle: {
                        hatching: 'right',
                        border: {
                            visible: false,
                            width: 3
                        }
                    },
                    point: {
                        visible: true,
                        symbol: 'circle',
                        size: 6,
                        border: {
                            visible: false,
                            width: 1
                        },
                        hoverMode: 'onlyPoint',
                        selectionMode: 'onlyPoint',
                        hoverStyle: {
                            border: {
                                visible: true,
                                width: 4
                            },
                            size: 6
                        },
                        selectionStyle: {
                            border: {
                                visible: true,
                                width: 4
                            },
                            size: 6
                        }
                    },
                    label: {
                        font: {
                            color: '#FFFFFF',
                            opacity: 1
                        },
                        border: {
                            visible: false,
                            width: 1,
                            color: '#808080',
                            dashStyle: 'solid'
                        },
                        connector: {
                            visible: false,
                            width: 1
                        }
                    },
                    scatter: {},
                    line: {
                        width: 2,
                        dashStyle: 'solid',
                        hoverStyle: {width: 3},
                        selectionStyle: {width: 3}
                    },
                    stackedline: {
                        width: 2,
                        dashStyle: 'solid',
                        hoverStyle: {width: 3},
                        selectionStyle: {width: 3}
                    },
                    fullstackedline: {
                        width: 2,
                        dashStyle: 'solid',
                        hoverStyle: {width: 3},
                        selectionStyle: {width: 3}
                    },
                    stepline: {
                        width: 2,
                        dashStyle: 'solid',
                        hoverStyle: {width: 3},
                        selectionStyle: {width: 3}
                    },
                    area: {point: {visible: false}},
                    stackedarea: {point: {visible: false}},
                    fullstackedarea: {point: {visible: false}},
                    steparea: {
                        border: {
                            visible: true,
                            width: 2
                        },
                        point: {visible: false},
                        hoverStyle: {border: {
                                visible: true,
                                width: 3
                            }},
                        selectionStyle: {border: {
                                visible: true,
                                width: 3
                            }}
                    },
                    spline: {
                        width: 2,
                        hoverStyle: {width: 3},
                        selectionStyle: {width: 3}
                    },
                    splinearea: {point: {visible: false}},
                    bar: {cornerRadius: 0},
                    stackedbar: {cornerRadius: 0},
                    fullstackedbar: {cornerRadius: 0},
                    rangebar: {cornerRadius: 0},
                    rangearea: {point: {visible: false}},
                    rangesplinearea: {point: {visible: false}},
                    pie: {
                        border: {
                            visible: false,
                            width: 2,
                            color: '#FFFFFF'
                        },
                        hoverStyle: {border: {
                                visible: true,
                                width: 3,
                                color: '#FFFFFF'
                            }},
                        selectionStyle: {border: {
                                visible: true,
                                width: 3,
                                color: '#FFFFFF'
                            }}
                    },
                    doughnut: {innerRadius: 0.5},
                    candlestick: {
                        width: 1,
                        innerColor: '#ffffff',
                        reduction: {color: '#FF0000'},
                        hoverStyle: {width: 3},
                        selectionStyle: {width: 3}
                    },
                    stock: {
                        width: 1,
                        reduction: {color: '#FF0000'},
                        hoverStyle: {width: 3},
                        selectionStyle: {width: 3}
                    }
                },
                legend: {
                    verticalAlignment: 'top',
                    horizontalAlignment: 'right',
                    position: 'outside',
                    font: {color: '#808080'},
                    visible: true,
                    customizeText: undefined,
                    itemTextPosition: undefined,
                    margin: 20,
                    equalColumnWidth: false,
                    markerSize: 12,
                    backgroundColor: undefined,
                    border: {
                        visible: false,
                        width: 1,
                        color: '#808080',
                        cornerRadius: 0,
                        opacity: 0.35,
                        dashStyle: 'solid'
                    },
                    paddingLeftRight: 20,
                    paddingTopBottom: 15,
                    columnCount: 0,
                    rowCount: 0,
                    columnItemSpacing: 20,
                    rowItemSpacing: 8
                },
                tooltip: {
                    enabled: false,
                    font: {
                        family: "'SegoeUI-Light', 'Segoe UI Light', 'HelveticaNeue-Light', 'Helvetica Neue Light', 'SegoeUI', 'Segoe UI', 'HelveticaNeue', 'Helvetica Neue', 'Trebuchet MS', Verdana",
                        weight: 200,
                        size: 26,
                        color: '#ffffff'
                    },
                    arrowLength: 10,
                    paddingLeftRight: 22,
                    paddingTopBottom: 6,
                    format: '',
                    argumentFormat: '',
                    precision: 0,
                    argumentPrecision: 0,
                    percentPrecision: 0,
                    customizeText: undefined
                },
                title: {font: {
                        family: "'SegoeUI-Light', 'Segoe UI Light', 'HelveticaNeue-Light', 'Helvetica Neue Light', 'SegoeUI', 'Segoe UI', 'HelveticaNeue', 'Helvetica Neue', 'Trebuchet MS', Verdana",
                        weight: 200,
                        color: '#232323',
                        size: 28,
                        opacity: 1
                    }},
                commonAxisSettings: {
                    discreteAxisDivisionMode: 'betweenLabels',
                    visible: false,
                    color: '#808080',
                    opacity: 0.35,
                    width: 1,
                    multipleAxesSpacing: 5,
                    label: {
                        visible: true,
                        staggered: false,
                        staggeringSpacing: 5,
                        overlappingBehavior: {
                            mode: 'enlargeTickInterval',
                            rotationAngle: 90,
                            staggeringSpacing: 5
                        },
                        precision: 0,
                        format: '',
                        customizeText: undefined,
                        indentFromAxis: 10
                    },
                    grid: {
                        visible: false,
                        color: '#808080',
                        opacity: 0.35,
                        width: 1
                    },
                    tick: {
                        visible: false,
                        color: '#808080',
                        opacity: 0.35
                    },
                    title: {
                        font: {size: 16},
                        margin: 10
                    },
                    stripStyle: {
                        paddingLeftRight: 10,
                        paddingTopBottom: 5
                    }
                },
                horizontalAxis: {
                    isHorizontal: true,
                    position: 'bottom',
                    axisDivisionFactor: 50,
                    label: {alignment: "center"},
                    stripStyle: {label: {
                            horizontalAlignment: 'center',
                            verticalAlignment: 'top'
                        }}
                },
                verticalAxis: {
                    isHorizontal: false,
                    position: 'left',
                    axisDivisionFactor: 30,
                    label: {alignment: "right"},
                    stripStyle: {label: {
                            horizontalAlignment: 'left',
                            verticalAlignment: 'center'
                        }}
                },
                argumentAxisStyle: {},
                valueAxisStyle: {grid: {visible: true}},
                commonPaneSettings: {border: {
                        color: '#808080',
                        opacity: 0.35,
                        width: 1
                    }}
            },
            gauge: {
                area: {
                    radius: 120,
                    fromAngle: 225,
                    toAngle: 315,
                    formatText: undefined
                },
                range: {
                    type: 'multicolor',
                    sizes: {length: 5},
                    colors: ['#00FF00', '#FFFF00', '#FF0000']
                },
                scale: {
                    type: 'TODO',
                    tick: {
                        sizes: {
                            length: 5,
                            width: 2
                        },
                        color: '#BFBFBF'
                    },
                    text: {
                        indent: 10,
                        color: '#7F7F7F',
                        font: {
                            family: "'SegoeUI', 'Segoe UI', 'HelveticaNeue', 'Helvetica Neue', 'Trebuchet MS', Verdana",
                            weight: 400,
                            size: 12
                        }
                    }
                },
                needle: {
                    type: 'line',
                    sizes: {width: 3},
                    color: '#BFBFBF'
                },
                marker: {
                    type: 'triangle',
                    sizes: {
                        length: 12,
                        width: 10
                    },
                    color: '#679EC5'
                }
            },
            rangeSelector: {
                containerBackgroundColor: 'white',
                scale: {
                    label: {
                        topIndent: 7,
                        font: {size: 11}
                    },
                    tick: {
                        width: 1,
                        color: 'black',
                        opacity: 0.1
                    },
                    marker: {
                        separatorHeight: 33,
                        topIndent: 10,
                        textLeftIndent: 7,
                        textTopIndent: 11
                    }
                },
                sliderMarker: {
                    padding: 7,
                    pointerSize: 6,
                    color: '#9B9B9B',
                    invalidRangeColor: 'red',
                    font: {
                        color: 'white',
                        size: 11
                    }
                },
                sliderHandle: {
                    width: 1,
                    color: 'black',
                    opacity: 0.1
                },
                shutter: {
                    color: undefined,
                    opacity: 0.75
                },
                background: {color: "#C0BAE1"},
                chart: {
                    containerBackgroundColor: undefined,
                    defaultPalette: 'default',
                    commonSeriesSettings: {
                        border: {
                            visible: false,
                            width: 1
                        },
                        hoverStyle: {border: {}},
                        selectionStyle: {border: {}},
                        point: {
                            visible: false,
                            symbol: 'circle',
                            border: {
                                visible: false,
                                width: 1
                            },
                            size: 6,
                            hoverStyle: {border: {}},
                            selectionStyle: {border: {}}
                        },
                        line: {width: 2},
                        stackedline: {width: 2},
                        fullstackedline: {width: 2},
                        area: {},
                        stackedarea: {},
                        fullstackedarea: {},
                        spline: {width: 2},
                        splinearea: {},
                        bar: {cornerRadius: 0},
                        stackedbar: {cornerRadius: 0},
                        fullstackedbar: {cornerRadius: 0},
                        rangebar: {cornerRadius: 0},
                        rangearea: {},
                        rangesplinearea: {},
                        pie: {},
                        candlestick: {
                            width: 1,
                            innerColor: '#ffffff',
                            reduction: {color: '#FF0000'}
                        },
                        stock: {
                            width: 1,
                            reduction: {color: '#FF0000'}
                        }
                    }
                }
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file namespaces.js */
    (function(DevExpress) {
        DevExpress.viz.renderers = {}
    })(DevExpress);
    /*! Module viz, file svgRenderer.js */
    (function($, DX) {
        var renderers = DX.viz.renderers,
            utils = DX.utils,
            Class = DX.Class,
            doc = document,
            easingFunctions,
            MAX_PIXEL_COUNT = 10000000000;
        (function() {
            var jStep = $.fx.step,
                fxProto = $.fx.prototype,
                baseCur = fxProto['cur'],
                baseD = jStep['d'],
                baseRotate = jStep['rotate'],
                baseTranslate = jStep['translate'],
                getNextAnimStep;
            getNextAnimStep = function(elem, pos, start, end, unit) {
                var easing = elem.renderer.animOptions.easing;
                return easingFunctions[easing || 'easeOutCubic'](pos, start, end) + (unit == '%' ? '%' : '')
            };
            fxProto['cur'] = function() {
                var fx = this,
                    prop = fx.prop;
                if (fx.elem instanceof BaseSvgElement) {
                    if (prop === 'svgheight' || prop === 'svgwidth')
                        prop = prop.substr(3);
                    return $(fx.elem.element).attr(prop)
                }
                return baseCur.apply(fx, arguments)
            };
            $.each(['x', 'y', 'cx', 'cy', 'r', 'rx', 'ry', 'strokeWidth'], function(i, prop) {
                var propName = DX.inflector.camelize(prop),
                    elem,
                    baseFn = jStep[propName];
                jStep[propName] = function(fx) {
                    var elem = fx.elem,
                        animProp;
                    if (!(elem instanceof BaseSvgElement)) {
                        baseFn ? baseFn.apply(this, arguments) : 0;
                        return
                    }
                    animProp = {sharpEdges: false};
                    animProp[fx.prop] = getNextAnimStep(elem, fx.pos, fx.start, fx.end, fx.unit);
                    elem.applySettings(animProp)
                }
            });
            $.each(['width', 'height'], function(i, prop) {
                var propName = 'svg' + prop,
                    elem;
                jStep[propName] = function(fx) {
                    var elem = fx.elem,
                        animProp = fx.prop.substr(3),
                        animParams;
                    animParams = {sharpEdges: false};
                    animParams[animProp] = getNextAnimStep(elem, fx.pos, fx.start || 0, fx.end || 0, fx.unit);
                    elem.applySettings(animParams)
                }
            });
            jStep['d'] = function(fx) {
                var elem = fx.elem,
                    fromSegments,
                    toSegments,
                    diff,
                    slice,
                    end;
                if (!(elem instanceof BaseSvgElement)) {
                    baseD ? baseD.apply(this, arguments) : 0;
                    return
                }
                if (!fx.initialized) {
                    fromSegments = elem.fromSegments || [];
                    toSegments = elem.segments || [];
                    if (fromSegments.length == 0)
                        fromSegments = [].concat(toSegments);
                    diff = toSegments.length - fromSegments.length;
                    if (diff > 0) {
                        slice = [].concat(fromSegments).splice(fromSegments.length - diff, diff);
                        fromSegments = fromSegments.concat(slice)
                    }
                    else if (diff < 0) {
                        slice = [].concat(toSegments).splice(toSegments.length + diff, -diff);
                        toSegments = toSegments.concat(slice)
                    }
                    fx.start = fromSegments;
                    fx.end = toSegments;
                    fx.initialized = true
                }
                end = fx.pos === 1 ? fx.end : $.map(fx.start, function(fromSeg, i) {
                    var toSeg = fx.end[i],
                        seg;
                    seg = $.map(fromSeg, function(fromEl, j) {
                        var toEl;
                        if (!$.isNumeric(fromEl))
                            return fromEl;
                        toEl = toSeg[j];
                        return getNextAnimStep(elem, fx.pos, fromEl, toEl)
                    });
                    return [seg]
                });
                elem.applySettings({d: $.map(end, function(seg, i) {
                        return seg.join(' ')
                    }).join(' ')})
            };
            jStep['rotate'] = function(fx) {
                var elem = fx.elem,
                    params,
                    curTransform,
                    angle;
                if (!(elem instanceof BaseSvgElement)) {
                    baseRotate ? baseRotate.apply(this, arguments) : 0;
                    return
                }
                if (!fx.initialized) {
                    params = fx.end;
                    curTransform = elem.transformation || {};
                    fx.start = curTransform.rotateAngle || 0,
                    fx.end = params.angle || 0,
                    fx.x = params.x || 0,
                    fx.y = params.y || 0;
                    fx.initialized = true
                }
                angle = getNextAnimStep(elem, fx.pos, fx.start, fx.end);
                elem.applySettings({rotate: [angle, fx.x, fx.y]})
            };
            jStep['translate'] = function(fx) {
                var elem = fx.elem,
                    params,
                    curTransform,
                    newX,
                    newY;
                if (!(elem instanceof BaseSvgElement)) {
                    baseTranslate ? baseTranslate.apply(this, arguments) : 0;
                    return
                }
                if (!fx.initialized) {
                    params = fx.end;
                    curTransform = elem.transformation || {};
                    fx.startX = curTransform.translateX || 0,
                    fx.startY = curTransform.translateY || 0,
                    fx.endX = params.x || 0,
                    fx.endY = params.y || 0;
                    fx.initialized = true
                }
                newX = getNextAnimStep(elem, fx.pos, fx.startX, fx.endX);
                newY = getNextAnimStep(elem, fx.pos, fx.startY, fx.endY);
                elem.applySettings({
                    translateX: newX,
                    translateY: newY
                })
            }
        })();
        easingFunctions = {
            easeOutCubic: function(pos, start, end) {
                return pos === 1 ? end : (1 - Math.pow(1 - pos, 3)) * (end - start) + +start
            },
            linear: function(pos, start, end) {
                return pos === 1 ? end : pos * (end - start) + +start
            }
        };
        var BaseSvgElement = Class.inherit({
                ctor: function baseSvgElementCtor(renderer, name, params) {
                    this.renderer = renderer;
                    this.element = this.createElement(name);
                    this.$element = $(this.element);
                    this.$this = $(this);
                    this.applySettings($.extend({}, this.defaultSettings(), params));
                    this.__passedParams = params
                },
                defaultSettings: $.noop,
                createElement: function(nodeName) {
                    this._nodeName = nodeName;
                    return doc.createElementNS('http://www.w3.org/2000/svg', nodeName)
                },
                dispose: function() {
                    this.off();
                    this.remove();
                    this.renderer = null;
                    this.element = null;
                    this.settings = null;
                    this.$element = null;
                    this.transformation = null;
                    this.$this = null;
                    this.__passedParams = null;
                    this.__appliedSettings = null;
                    this.__appliedStyle = null
                },
                append: function(svgElement) {
                    var toElement = svgElement || this.renderer.getRoot();
                    toElement.element.appendChild(this.element);
                    return this
                },
                toBackground: function() {
                    this.element.parentNode && this.element.parentNode.insertBefore(this.element, this.element.parentNode.firstChild);
                    return this
                },
                toForeground: function() {
                    this.element.parentNode && this.element.parentNode.appendChild(this.element);
                    return this
                },
                addClass: function(className) {
                    var classAttribute = this.$element.attr('class'),
                        classNameIndex,
                        classNames;
                    if (className) {
                        if (classAttribute) {
                            classNames = classAttribute.split(' ');
                            classNameIndex = $.inArray(className, classNames);
                            if (classNameIndex === -1)
                                classAttribute += ' ' + className
                        }
                        else
                            classAttribute = className;
                        this.$element.attr('class', classAttribute)
                    }
                    return this.$element
                },
                removeClass: function(className) {
                    var classAttribute = this.$element.attr('class'),
                        classNames,
                        indexDeleteElement,
                        resultClassNames = '',
                        i;
                    if (classAttribute && className) {
                        classNames = classAttribute.split(' ');
                        indexDeleteElement = $.inArray(className, classNames);
                        if (indexDeleteElement !== -1) {
                            for (i = 0; i < classNames.length; i++)
                                if (i !== indexDeleteElement)
                                    resultClassNames += classNames[i] + ' ';
                            this.$element.attr('class', resultClassNames.replace(/ $/, ''))
                        }
                    }
                    return this.$element
                },
                applySettings: function(settings) {
                    var normalized;
                    this.settings = $.extend(this.settings || {}, settings || {});
                    this.adjustSettings();
                    normalized = this._normalizeSettings(this.settings);
                    this.applyStyle(this._style);
                    this._applyAttributes(normalized);
                    return this
                },
                _applyAttributes: function(settings) {
                    this.$element.attr(settings);
                    this.__appliedSettings = settings
                },
                adjustSettings: function(){},
                applyStyle: function(style) {
                    this.$element.css(style || {});
                    this.__appliedStyle = style || {};
                    return this
                },
                trigger: function(event, data) {
                    this.$element.trigger(event, data)
                },
                on: function(events, data, handler) {
                    this.$element.on.apply(this.$element, arguments);
                    return this
                },
                data: function(data) {
                    this.$element.data(data);
                    return this
                },
                removeData: function() {
                    this.$element.removeData();
                    return this
                },
                off: function(events) {
                    this.$element.off(events);
                    return this
                },
                getBBox: function() {
                    var self = this,
                        bBox,
                        element = this.element,
                        transformation = self.transformation,
                        rotateAngle = transformation.rotateAngle || 0,
                        rotateX = transformation.rotateX || 0,
                        rotateY = transformation.rotateY || 0,
                        mabs = Math.abs,
                        mmin = Math.min;
                    function bBox(el) {
                        var ret = {};
                        try {
                            if (!$.isFunction(el.getBBox))
                                throw{};
                            else
                                ret = el.getBBox()
                        }
                        catch(e) {
                            ret = {
                                x: 0,
                                y: 0,
                                width: el.offsetWidth || 0,
                                height: el.offsetHeight || 0
                            }
                        }
                        return ret
                    }
                    bBox = $.extend({}, bBox(element));
                    if (rotateAngle) {
                        var cossin = utils.getCosAndSin(rotateAngle),
                            sin = cossin.sin.toFixed(3),
                            cos = cossin.cos.toFixed(3),
                            ltx = bBox.x - rotateX,
                            lty = bBox.y - rotateY,
                            rtx = bBox.x + bBox.width - rotateX,
                            rty = bBox.y - rotateY,
                            lbx = bBox.x - rotateX,
                            lby = bBox.y + bBox.height - rotateY,
                            rbx = bBox.x + bBox.width - rotateX,
                            rby = bBox.y + bBox.height - rotateY,
                            w,
                            h;
                        w = mabs(bBox.height * sin) + mabs(bBox.width * cos);
                        h = mabs(bBox.height * cos) + mabs(bBox.width * sin);
                        bBox.x = mmin(ltx * cos - lty * sin + rotateX, rtx * cos - rty * sin + rotateX, lbx * cos - lby * sin + rotateX, rbx * cos - rby * sin + rotateX);
                        bBox.y = mmin(ltx * sin + lty * cos + rotateY, rtx * sin + rty * cos + rotateY, lbx * sin + lby * cos + rotateY, rbx * sin + rby * cos + rotateY);
                        bBox.width = w;
                        bBox.height = h
                    }
                    return self._normalizeBBox(bBox)
                },
                _normalizeBBox: function(bBox) {
                    var ceil = Math.ceil,
                        floor = Math.floor,
                        $isNumeric = $.isNumeric,
                        rxl = floor(bBox.x),
                        ryt = floor(bBox.y),
                        rxr = ceil(bBox.width + bBox.x),
                        ryb = ceil(bBox.height + bBox.y),
                        width,
                        height;
                    bBox.x = $isNumeric(rxl) && rxl < MAX_PIXEL_COUNT && rxl > -MAX_PIXEL_COUNT ? rxl : 0;
                    bBox.y = $isNumeric(ryt) && ryt < MAX_PIXEL_COUNT && ryt > -MAX_PIXEL_COUNT ? ryt : 0;
                    width = rxr - rxl;
                    height = ryb - ryt;
                    bBox.width = $isNumeric(width) && width < MAX_PIXEL_COUNT && width > -MAX_PIXEL_COUNT ? width : 0;
                    bBox.height = $isNumeric(height) && height < MAX_PIXEL_COUNT && height > -MAX_PIXEL_COUNT ? height : 0;
                    bBox.isEmpty = !bBox.x && !bBox.y && !bBox.width && !bBox.height;
                    return bBox
                },
                clear: function(selector) {
                    selector ? this.$element.find(selector).remove() : this.$element.empty()
                },
                detach: function() {
                    this.$element.detach()
                },
                animate: function(params, options, complete) {
                    options = options || {};
                    if (this.renderer.animOptions.enabled) {
                        $.each(['height', 'width'], function(_, propName) {
                            if (propName in params) {
                                params['svg' + propName] = params[propName];
                                delete params[propName]
                            }
                        });
                        this.$this.stop();
                        if (complete)
                            $.extend(options, {complete: complete});
                        this.$this.animate(params, $.extend({duration: this.renderer.animOptions.duration}, options))
                    }
                    else {
                        if (params.translate) {
                            if ('x' in params.translate)
                                params.translateX = params.translate.x;
                            if ('y' in params.translate)
                                params.translateY = params.translate.y;
                            delete params.translate
                        }
                        if (options && options.step) {
                            options.step.call(this, undefined, {pos: 1});
                            options.complete && options.complete.call(this)
                        }
                        else
                            this.applySettings(params)
                    }
                },
                stopAnimation: function() {
                    var self = this;
                    self.renderer.animOptions.enabled && self.$this.stop();
                    return self
                },
                show: function(animate) {
                    if (animate && this.renderer.animOptions.enabled)
                        this.$element.show(this.renderer.animOptions.duration);
                    else
                        this.$element.show()
                },
                hide: function(animate) {
                    if (animate && this.renderer.animOptions.enabled)
                        this.$element.hide(this.renderer.animOptions.duration);
                    else
                        this.$element.hide()
                },
                move: function(x, y, animate, animOptions) {
                    x = x || 0,
                    y = y || 0;
                    animOptions = animOptions || {};
                    if (!animate)
                        this.applySettings({
                            translateX: x,
                            translateY: y
                        });
                    else
                        this.animate({translate: {
                                x: x,
                                y: y
                            }}, animOptions)
                },
                rotate: function(angle, x, y, animate, animOptions) {
                    angle = angle || 0;
                    x = x || 0;
                    y = y || 0;
                    animOptions = animOptions || {};
                    if (!animate)
                        this.applySettings({rotate: [angle, x, y]});
                    else
                        this.animate({rotate: {
                                angle: angle,
                                x: x,
                                y: y
                            }}, animOptions)
                },
                remove: function() {
                    this.$element.remove()
                },
                _normalizeSettings: function(settings) {
                    var key,
                        style,
                        firstChar,
                        styleName,
                        prop,
                        value,
                        normalized = {},
                        fontSetting;
                    for (key in settings) {
                        prop = key,
                        value = settings[prop];
                        if (prop === 'align') {
                            prop = 'text-anchor';
                            value = {
                                left: 'start',
                                center: 'middle',
                                right: 'end'
                            }[value]
                        }
                        else if (prop === 'font') {
                            style = this['_style'] = this['_style'] || {};
                            if (!$.isPlainObject(value))
                                continue;
                            $.each(value, function(fontSetting) {
                                switch (fontSetting) {
                                    case'color':
                                        styleName = 'fill';
                                        break;
                                    case'opacity':
                                        styleName = 'fillOpacity';
                                        break;
                                    case'cursor':
                                        styleName = fontSetting;
                                        break;
                                    default:
                                        firstChar = fontSetting.charAt(0);
                                        styleName = 'font' + fontSetting.replace(firstChar, firstChar.toUpperCase())
                                }
                                style[styleName] = value[fontSetting]
                            });
                            continue
                        }
                        else if (prop === 'dashStyle') {
                            prop = 'stroke-dasharray';
                            value = value.toLowerCase();
                            value = value === 'solid' ? 'none' : value.replace(/longdash/g, '8,3,').replace(/dash/g, '4,3,').replace(/dot/g, '1,3,').replace(/,$/, '').split(',');
                            if (value !== 'none')
                                value = $.map(value, function(p) {
                                    return +p * (settings.strokeWidth || 1)
                                }).join(',')
                        }
                        else if (/^(linecap|linejoin)$/i.test(prop))
                            prop = 'stroke-' + prop;
                        else if (/^(translateX|translateY|rotate|scale)$/i.test(prop)) {
                            this['_' + prop] = value;
                            continue
                        }
                        else if (prop === 'clipId') {
                            prop = 'clip-path';
                            value = 'url(#' + value + ')'
                        }
                        else if (prop === 'style') {
                            this['_style'] = this['_style'] || {};
                            $.extend(true, this['_style'], value);
                            continue
                        }
                        else if (prop === 'text')
                            continue;
                        else if (prop === 'segments')
                            continue;
                        else
                            prop = DX.inflector.dasherize(prop);
                        normalized[prop] = value
                    }
                    return this._applyTransformation(normalized)
                },
                _applyTransformation: function(settings) {
                    this.transformation = {
                        translateX: this._translateX,
                        translateY: this._translateY,
                        rotateAngle: 0,
                        rotateX: 0,
                        rotateY: 0
                    };
                    var tr = this.transformation,
                        rotate = this._rotate,
                        scale = this._scale,
                        transformations = [];
                    if (utils.isDefined(tr.translateX) || utils.isDefined(tr.translateY))
                        transformations.push('translate(' + (tr.translateX || 0) + ',' + (tr.translateY || 0) + ')');
                    if (utils.isDefined(rotate)) {
                        if (utils.isNumber(rotate)) {
                            tr.rotateAngle = rotate;
                            tr.rotateX = settings.x || 0;
                            tr.rotateY = settings.y || 0
                        }
                        else if ($.isArray(rotate)) {
                            tr.rotateAngle = rotate[0] || 0;
                            tr.rotateX = rotate[1] || 0;
                            tr.rotateY = rotate[2] || 0
                        }
                        else if (utils.isObject(rotate)) {
                            tr.rotateAngle = rotate.angle || 0;
                            tr.rotateX = rotate.x || 0;
                            tr.rotateY = rotate.y || 0
                        }
                        transformations.push('rotate(' + tr.rotateAngle + ',' + tr.rotateX + ',' + tr.rotateY + ')')
                    }
                    if (utils.isDefined(scale))
                        transformations.push('scale(' + (scale || 0) + ',' + (scale || 0) + ')');
                    if (transformations.length)
                        settings.transform = transformations.join(' ');
                    return settings
                }
            });
        var RootSvgElement = BaseSvgElement.inherit({
                defaultSettings: function() {
                    return {
                            width: 0,
                            height: 0,
                            style: {'-webkit-tap-highlight-color': 'rgba(0, 0, 0, 0)'},
                            xmlns: 'http://www.w3.org/2000/svg',
                            'xmlns:xlink': 'http://www.w3.org/1999/xlink',
                            version: '1.1',
                            stroke: 'none',
                            strokeWidth: 0,
                            fill: 'none'
                        }
                },
                ctor: function(renderer, params) {
                    this.callBase(renderer, 'svg', params)
                }
            });
        var RectSvgBaseElement = {
                defaultSettings: function() {
                    return {
                            x: 0,
                            y: 0,
                            width: 0,
                            height: 0
                        }
                },
                adjustSettings: function() {
                    if (!utils.isDefined(this.settings.sharpEdges) || this.settings.sharpEdges) {
                        this.sharpEdges();
                        delete this.settings.sharpEdges
                    }
                },
                prepareSettings: function(settings) {
                    var prevStrokeWidth = this.settings ? Number(this.settings.strokeWidth) || 0 : 0,
                        newStrokeWidth,
                        maxStrokeWidth,
                        strokeWidthChanged = false;
                    if (utils.isDefined(settings.width))
                        this._realWidth = Number(settings.width);
                    if (utils.isDefined(settings.height))
                        this._realHeight = Number(settings.height);
                    if (utils.isDefined(settings.x))
                        this._realX = Number(settings.x);
                    if (utils.isDefined(settings.y))
                        this._realY = Number(settings.y);
                    if (utils.isDefined(settings.strokeWidth))
                        this._realStrokeWidth = Number(settings.strokeWidth);
                    this._realStrokeWidth = this._realStrokeWidth || this.defaultSettings().strokeWidth || 0;
                    maxStrokeWidth = ~~((this._realWidth < this._realHeight ? this._realWidth : this._realHeight) / 2);
                    newStrokeWidth = this._realStrokeWidth < maxStrokeWidth ? this._realStrokeWidth : maxStrokeWidth;
                    if (newStrokeWidth !== prevStrokeWidth) {
                        strokeWidthChanged = true;
                        settings.sharpEdges = true;
                        newStrokeWidth > 0 && (settings.strokeWidth = newStrokeWidth)
                    }
                    (utils.isDefined(settings.x) || strokeWidthChanged) && (settings.x = this._realX + newStrokeWidth / 2);
                    (utils.isDefined(settings.y) || strokeWidthChanged) && (settings.y = this._realY + newStrokeWidth / 2);
                    (utils.isDefined(settings.width) || strokeWidthChanged) && (settings.width = this._realWidth - newStrokeWidth);
                    (utils.isDefined(settings.height) || strokeWidthChanged) && (settings.height = this._realHeight - newStrokeWidth)
                },
                applySettings: function(settings) {
                    var settings = $.extend(true, {}, settings);
                    this.prepareSettings(settings);
                    this.callBase(settings)
                },
                sharpEdges: function() {
                    var strokeWidth = Math.round(this.settings.strokeWidth || 0),
                        correction = strokeWidth % 2 / 2;
                    this.settings.x = Math.floor(this.settings.x - correction || 0) + correction;
                    this.settings.y = Math.floor(this.settings.y - correction || 0) + correction;
                    this.settings.width = Math.floor(this.settings.width || 0);
                    this.settings.height = Math.floor(this.settings.height || 0);
                    this.settings.strokeWidth > 0 && (this.settings.strokeWidth = strokeWidth)
                }
            };
        var ImageSvgElement = BaseSvgElement.inherit(RectSvgBaseElement).inherit({
                ctor: function(renderer, params, href, location) {
                    var locationToPreserveAspectRatioMap = {
                            full: 'none',
                            lefttop: 'xMinYMin',
                            leftcenter: 'xMinYMid',
                            leftbottom: 'xMinYMax',
                            centertop: 'xMidYMin',
                            center: 'xMidYMid',
                            centerbottom: 'xMidYMax',
                            righttop: 'xMaxYMin',
                            rightcenter: 'xMaxYMid',
                            rightbottom: 'xMaxYMax'
                        };
                    this.href = utils.isDefined(href) ? href : '';
                    this.preserveAspectRatio = locationToPreserveAspectRatioMap[(location || '').toLowerCase()];
                    this.preserveAspectRatio = this.preserveAspectRatio || 'none';
                    this.callBase(renderer, 'image', params)
                },
                adjustSettings: function() {
                    this.callBase();
                    this.element.setAttributeNS('http://www.w3.org/1999/xlink', 'href', this.href);
                    if (this.preserveAspectRatio)
                        this.element.setAttribute('preserveAspectRatio', this.preserveAspectRatio)
                }
            });
        var RectSvgElement = BaseSvgElement.inherit(RectSvgBaseElement).inherit({
                defaultSettings: function() {
                    return {
                            x: 0,
                            y: 0,
                            width: 0,
                            height: 0,
                            rx: 0,
                            ry: 0
                        }
                },
                ctor: function(renderer, params) {
                    this.callBase(renderer, 'rect', params)
                }
            });
        var PathSvgElement = BaseSvgElement.inherit({
                defaultSettings: function() {
                    return {points: {
                                x: 0,
                                y: 0
                            }}
                },
                getNodeName: function() {
                    return 'path'
                },
                getPathAttributeName: function() {
                    return 'd'
                },
                ctor: function(renderer, params) {
                    this.callBase(renderer, this.getNodeName(), params)
                },
                dispose: function() {
                    this.segments = null;
                    this.fromSegments = null;
                    this.callBase()
                },
                adjustSettings: function() {
                    this.prepareSegments(this.settings)
                },
                applySettings: function(settings) {
                    var settings = settings || {};
                    if (this.settings && settings.strokeWidth && this.settings.strokeWidth !== settings.strokeWidth)
                        settings.sharpEdges = true;
                    this.callBase(settings)
                },
                prepareSegments: function(params) {
                    if ('points' in params) {
                        var points = params.points,
                            firstElem = points[0],
                            close = this.closePath || params.closePath,
                            segments = [],
                            i;
                        if (utils.isObject(firstElem))
                            segments = $.map(points, function(pt, i) {
                                if (!i)
                                    return [['M', pt.x, pt.y]];
                                return [['L', pt.x, pt.y]]
                            });
                        else if (utils.isNumber(firstElem))
                            for (i = 0; i < points.length; i += 2) {
                                if (!i) {
                                    segments = [['M', points[i] || 0, points[i + 1] || 0]];
                                    continue
                                }
                                segments.push(['L', points[i] || 0, points[i + 1] || 0])
                            }
                        else
                            segments = [['M', 0, 0]];
                        if (close)
                            segments.push(['Z']);
                        this.segments = segments;
                        delete params.points;
                        delete params.closePath;
                        params.sharpEdges = true
                    }
                    if (params.sharpEdges) {
                        this.sharpEdges();
                        this.combinePathParams(params);
                        delete params.sharpEdges
                    }
                },
                customizeSegments: function(segments) {
                    return segments
                },
                combinePathParams: function(params) {
                    var path;
                    this.segments = this.customizeSegments(this.segments);
                    if (this.segments) {
                        path = $.map(this.segments, function(seg, i) {
                            return seg.join(' ')
                        });
                        path = path.join(' ');
                        params[this.getPathAttributeName()] = path
                    }
                },
                animate: function(params, options) {
                    var callBase = this.callBase;
                    if (!('points' in params))
                        return this.callBase(params, options);
                    this.fromSegments = this.segments;
                    this.prepareSegments(params);
                    if (this.renderer.animOptions.enabled)
                        $.extend(params, {d: 1});
                    this.callBase = callBase;
                    this.callBase(params, options)
                },
                sharpEdges: function() {
                    var self = this,
                        segLength = self.segments.length,
                        i = 0,
                        curSeg,
                        nextSeg,
                        curX,
                        curY,
                        nextX,
                        nextY,
                        curXIdx,
                        curYIdx,
                        nextXIdx,
                        nextYIdx,
                        strokeWidth = Math.round(self.settings.strokeWidth || 0),
                        correction = strokeWidth % 2 / 2;
                    for (i; i < segLength - 1; i++) {
                        curSeg = self.segments[i];
                        nextSeg = self.segments[i + 1];
                        if (nextSeg[0] === 'Z' && i)
                            nextSeg = self.segments[0];
                        switch (curSeg[0]) {
                            case'M':
                            case'L':
                                curXIdx = 1;
                                curYIdx = 2;
                                break;
                            case'C':
                                curXIdx = 5;
                                curYIdx = 6;
                                break;
                            case'A':
                                curXIdx = 6;
                                curYIdx = 7;
                                break;
                            case'Z':
                                continue
                        }
                        switch (nextSeg[0]) {
                            case'M':
                            case'L':
                                nextXIdx = 1;
                                nextYIdx = 2;
                                break;
                            case'C':
                                nextXIdx = 5;
                                nextYIdx = 6;
                                break;
                            case'A':
                                nextXIdx = 6;
                                nextYIdx = 7;
                                break;
                            case'Z':
                                continue
                        }
                        curX = Math.floor(curSeg[curXIdx]);
                        curY = Math.floor(curSeg[curYIdx]);
                        nextX = nextSeg[nextXIdx] = Math.floor(nextSeg[nextXIdx]);
                        nextY = nextSeg[nextYIdx] = Math.floor(nextSeg[nextYIdx]);
                        curSeg[curXIdx] = i == 0 ? curX : curSeg[curXIdx];
                        curSeg[curYIdx] = i == 0 ? curY : curSeg[curYIdx];
                        if (curX == nextX) {
                            curSeg[curXIdx] = curX + correction;
                            nextSeg[nextXIdx] = nextX + correction
                        }
                        if (curY == nextY) {
                            curSeg[curYIdx] = curY + correction;
                            nextSeg[nextYIdx] = nextY + correction
                        }
                    }
                }
            });
        var SegmentRectSvgElement = PathSvgElement.inherit(RectSvgBaseElement).inherit({
                defaultSettings: function() {
                    return $.extend(true, {}, this.callBase(), {segments: {
                                top: true,
                                bottom: true,
                                left: true,
                                right: true
                            }})
                },
                prepareSegments: function() {
                    var self = this,
                        settings = self.settings,
                        left = settings.x,
                        right = left + settings.width,
                        top = settings.y,
                        bottom = top + settings.height,
                        segments = [],
                        segmentSequence,
                        visiblyOpt = 0,
                        prevSegmentVisibility = 0;
                    var allSegment = {
                            top: [['M', left, top], ['L', right, top]],
                            right: [['M', right, top], ['L', right, bottom]],
                            bottom: [['M', right, bottom], ['L', left, bottom]],
                            left: [['M', left, bottom], ['L', left, top]]
                        };
                    $.each(allSegment, function(seg, _) {
                        var visibility = !!self.settings.segments[seg];
                        visiblyOpt = visiblyOpt * 2 + ~~visibility
                    });
                    switch (visiblyOpt) {
                        case(13):
                        case(9):
                            segmentSequence = ['left', 'top', 'right', 'bottom'];
                            break;
                        case(11):
                            segmentSequence = ['bottom', 'left', 'top', 'right'];
                            break;
                        default:
                            segmentSequence = ['top', 'right', 'bottom', 'left']
                    }
                    $.each(segmentSequence, function(_, seg) {
                        var segmentVisibility = !!self.settings.segments[seg];
                        if (segmentVisibility)
                            $.each(allSegment[seg].slice(prevSegmentVisibility), function(_, segment) {
                                segments.push(segment)
                            });
                        prevSegmentVisibility = ~~segmentVisibility
                    });
                    visiblyOpt == 15 && segments.push(['Z']);
                    this.segments = segments.length ? segments : [['M', 0, 0], ['Z']];
                    this.combinePathParams(settings)
                },
                adjustSettings: function() {
                    this.callBase();
                    this.prepareSegments()
                },
                applySettings: function(settings) {
                    var segments = this.settings && this.settings.segments || this.defaultSettings().segments;
                    settings.segments = $.extend(true, {}, segments || {}, settings.segments);
                    this.callBase(settings)
                }
            });
        var AreaSvgElement = PathSvgElement.inherit({
                defaultSettings: function() {
                    return {points: {
                                x: 0,
                                y: 0
                            }}
                },
                ctor: function(renderer, params) {
                    this.closePath = true;
                    this.callBase(renderer, params)
                }
            });
        var BezierSvgElement = PathSvgElement.inherit({
                defaultSettings: function() {
                    return {points: {
                                x: 0,
                                y: 0
                            }}
                },
                prepareSegments: function(params) {
                    if (!('points' in params))
                        return;
                    var points = params.points,
                        firstElem = points[0],
                        close = this.closePath || params.closePath,
                        segments = [],
                        seg = [],
                        i,
                        x,
                        y;
                    var cnt = 0;
                    if (utils.isObject(firstElem)) {
                        for (i = 0; i < points.length; i++) {
                            x = points[i].x;
                            y = points[i].y;
                            if (!i) {
                                segments = [['M', x, y]];
                                continue
                            }
                            if ((i - 1) % 3 == 0) {
                                if (seg.length > 0)
                                    segments.push(seg);
                                seg = ['C', x, y];
                                continue
                            }
                            seg.push(x);
                            seg.push(y)
                        }
                        if (seg.length > 0)
                            segments.push(seg)
                    }
                    else if (utils.isNumber(firstElem)) {
                        for (i = 0; i < points.length; i += 2) {
                            x = points[i];
                            y = points[i + 1];
                            if (!i) {
                                segments = [['M', x, y || 0]];
                                continue
                            }
                            if ((i - 2) % 6 == 0) {
                                if (seg.length > 0)
                                    segments.push(seg);
                                seg = ['C', x, y || 0];
                                continue
                            }
                            seg.push(x);
                            seg.push(y || 0)
                        }
                        if (seg.length > 0)
                            segments.push(seg)
                    }
                    else
                        segments = [['M', 0, 0]];
                    if (close)
                        segments.push(['Z']);
                    this.segments = segments;
                    delete params.points;
                    delete params.closePath;
                    this.combinePathParams(params)
                }
            });
        var BezierAreaSvgElement = BezierSvgElement.inherit({
                defaultSettings: function() {
                    return {points: {
                                x: 0,
                                y: 0
                            }}
                },
                ctor: function(renderer, params) {
                    this.closePath = true;
                    this.callBase(renderer, params)
                }
            });
        var ArcSvgElement = PathSvgElement.inherit({
                defaultSettings: function() {
                    return {
                            x: 0,
                            y: 0,
                            linejoin: 'round'
                        }
                },
                createArcSegments: function(x, y, innerR, outerR, startAngle, endAngle) {
                    var longFlag = Math.abs(endAngle - startAngle) > Math.PI ? '1' : '0',
                        xOuterStart = x + outerR * Math.cos(startAngle),
                        yOuterStart = y - outerR * Math.sin(startAngle),
                        xOuterEnd = x + outerR * Math.cos(endAngle),
                        yOuterEnd = y - outerR * Math.sin(endAngle),
                        xInnerStart = x + innerR * Math.cos(endAngle),
                        yInnerStart = y - innerR * Math.sin(endAngle),
                        xInnerEnd = x + innerR * Math.cos(startAngle),
                        yInnerEnd = y - innerR * Math.sin(startAngle);
                    return [['M', xOuterStart, yOuterStart], ['A', outerR, outerR, 0, longFlag, 0, xOuterEnd, yOuterEnd], ['L', xInnerStart, yInnerStart], ['A', innerR, innerR, 0, longFlag, 1, xInnerEnd, yInnerEnd], ['Z']]
                },
                prepareSegments: function(params) {
                    if (!('x' in params) && !('y' in params) && !('outerRadius' in params) && !('innerRadius' in params) && !('startAngle' in params) && !('endAngle' in params))
                        return;
                    var x = utils.isNumber(params.x) ? Number(params.x) : 0,
                        y = utils.isNumber(params.y) ? Number(params.y) : 0,
                        outerR = utils.isNumber(params.outerRadius) ? Number(params.outerRadius) : 0,
                        innerR = utils.isNumber(params.innerRadius) ? Number(params.innerRadius) : 0,
                        startAngle = utils.isNumber(params.startAngle) ? Number(params.startAngle) : 0,
                        endAngle = utils.isNumber(params.endAngle) ? Number(params.endAngle) : 360;
                    this.segments = [['M', 0, 0], ['Z']];
                    if (outerR || innerR) {
                        var tmp = Math.min(outerR, innerR);
                        outerR = Math.max(outerR, innerR);
                        innerR = tmp;
                        if (Math.round(startAngle) != Math.round(endAngle)) {
                            if (Math.abs(endAngle - startAngle) % 360 == 0)
                                endAngle -= 0.0001;
                            if (startAngle > 360)
                                startAngle = startAngle % 360;
                            if (endAngle > 360)
                                endAngle = endAngle % 360;
                            if (startAngle > endAngle)
                                startAngle -= 360;
                            startAngle = startAngle * Math.PI / 180;
                            endAngle = endAngle * Math.PI / 180;
                            this.segments = this.createArcSegments(x, y, innerR, outerR, startAngle, endAngle)
                        }
                    }
                    delete params.x;
                    delete params.y;
                    delete params.outerRadius;
                    delete params.innerRadius;
                    delete params.startAngle;
                    delete params.endAngle;
                    this.combinePathParams(params)
                }
            });
        var CircleSvgElement = BaseSvgElement.inherit({
                defaultSettings: function() {
                    return {
                            cx: 0,
                            cy: 0,
                            r: 0
                        }
                },
                ctor: function(renderer, params) {
                    this.callBase(renderer, 'circle', params)
                }
            });
        var TextSvgElement = BaseSvgElement.inherit({
                defaultSettings: function() {
                    return {
                            x: 0,
                            y: 0
                        }
                },
                ctor: function(renderer, params) {
                    this.tspans = [];
                    this.callBase(renderer, 'text', params)
                },
                dispose: function() {
                    this.tspans = null;
                    this.callBase()
                },
                updateText: function(text) {
                    if (!utils.isDefined(text))
                        text = '';
                    this.applySettings({text: text})
                },
                adjustSettings: function() {
                    if (!('text' in this.settings)) {
                        this.changeX();
                        return
                    }
                    this._createElementWithText(this.settings.text)
                },
                changeX: function() {
                    for (var i = 0; i < this.tspans.length; i++)
                        if (this.tspans[i].settings.x != undefined)
                            this.tspans[i].applySettings({x: this.settings.x})
                },
                _createElementWithText: function(text) {
                    var div,
                        i;
                    this.clear();
                    text = text.toString().replace(/\r/g, "");
                    text = text.replace(/\n/g, "<br/>");
                    div = doc.createElement("div");
                    div.innerHTML = text;
                    div.params = {style: {}};
                    this._orderText(div)
                },
                clear: function() {
                    this.callBase();
                    this.tspans = []
                },
                _orderText: function(node) {
                    var textArray = [],
                        defaultFontSize = (this.settings.font ? this.settings.font.size : 12) || 12;
                    var order = function(strCount, node, textArray) {
                            var params = {style: {}},
                                textArray = textArray || [];
                            node.params = node.params || {};
                            if (node.parentNode && node.nodeName != "#text")
                                if (node.parentNode.params)
                                    for (var i in node.parentNode.params)
                                        node.params[i] = node.parentNode.params[i];
                            switch (node.tagName) {
                                case"B" || "STRONG":
                                    node.params.fontWeight = "bold";
                                    break;
                                case"I" || "EM":
                                    node.params.fontStyle = "italic";
                                    break;
                                case"U":
                                    node.params.textDecoration = "underline";
                                    break;
                                case"BR":
                                    strCount++;
                                    break
                            }
                            if (node.style) {
                                if (node.style.fontSize)
                                    node.params.fontSize = node.style.fontSize.split('p')[0] || node.params.fontSize;
                                node.params.fill = node.style.color || node.params.fill;
                                node.params.fontStyle = node.style.fontStyle || node.params.fontStyle;
                                node.params.fontWeight = node.style.fontWeight || node.params.fontWeight;
                                node.params.textDecoration = node.style.textDecoration || node.params.textDecoration
                            }
                            var childnum = node.childNodes.length;
                            var count = 0;
                            while (count != childnum)
                                strCount = order(strCount, node.childNodes[count++], textArray);
                            if (node.wholeText != undefined) {
                                params.fill = node.parentNode.params.fill;
                                params.text = node.wholeText,
                                node.parentNode.params.fontSize && (params.style.fontSize = node.parentNode.params.fontSize);
                                node.parentNode.params.fontStyle && (params.style.fontStyle = node.parentNode.params.fontStyle);
                                node.parentNode.params.fontWeight && (params.style.fontWeight = node.parentNode.params.fontWeight);
                                node.parentNode.params.textDecoration && (params.style.textDecoration = node.parentNode.params.textDecoration);
                                textArray.push({
                                    params: params,
                                    line: strCount
                                })
                            }
                            return strCount
                        };
                    order(0, node, textArray);
                    for (var txt = 0; txt < textArray.length; txt++) {
                        if (txt != 0)
                            if (textArray[txt].line != textArray[txt - 1].line) {
                                textArray[txt].params.dy = textArray[txt].params.fontSize || defaultFontSize;
                                textArray[txt].params.x = this.settings.x
                            }
                            else {
                                textArray[txt].params.dy = 0;
                                textArray[txt].params.dx = 0
                            }
                        else {
                            textArray[txt].params.x = this.settings.x;
                            textArray[txt].params.dy = 0
                        }
                        var tspan = new TspanSvgElement(this.renderer, textArray[txt].params);
                        tspan.append(this);
                        this.tspans.push(tspan)
                    }
                }
            });
        var TspanSvgElement = BaseSvgElement.inherit({ctor: function(renderer, params) {
                    var text = params.text || '';
                    delete params.text;
                    this.callBase(renderer, 'tspan', params);
                    this.element.appendChild(doc.createTextNode(text))
                }});
        var GroupSvgElement = BaseSvgElement.inherit({
                ctor: function(renderer, params) {
                    this.callBase(renderer, 'g', params)
                },
                update: $.noop
            });
        var PatternSvgElement = BaseSvgElement.inherit({
                ctor: function(renderer, params) {
                    this.__patternParams = $.extend({}, params);
                    var id = utils.getNextPatternId(),
                        color = params.color;
                    this.callBase(renderer, 'pattern', {
                        id: id,
                        width: 6,
                        height: 6
                    });
                    this.element.setAttribute('patternUnits', 'userSpaceOnUse');
                    this._lines = [];
                    if (params.hatching === 'right') {
                        this._lines.push(renderer.createLine(0, 0, 1, 1, {
                            strokeWidth: 1,
                            stroke: color,
                            opacity: 0.8
                        }).append(this));
                        this._lines.push(renderer.createLine(5, 5, 6, 6, {
                            strokeWidth: 1,
                            stroke: color,
                            opacity: 0.8
                        }).append(this));
                        this._lines.push(renderer.createLine(0, 6, 6, 0, {
                            strokeWidth: 2,
                            stroke: color
                        }).append(this))
                    }
                    else if (params.hatching === 'left') {
                        this._lines.push(renderer.createLine(5, 1, 6, 0, {
                            strokeWidth: 1,
                            stroke: color,
                            opacity: 0.8
                        }).append(this));
                        this._lines.push(renderer.createLine(0, 6, 1, 5, {
                            strokeWidth: 1,
                            stroke: color,
                            opacity: 0.8
                        }).append(this));
                        this._lines.push(renderer.createLine(0, 0, 6, 6, {
                            strokeWidth: 2,
                            stroke: color
                        }).append(this))
                    }
                    this.id = 'url(#' + id + ')'
                },
                append: function() {
                    return this.callBase(this.renderer.defsSvg)
                },
                clear: function() {
                    this.callBase();
                    this._lines = []
                },
                dispose: function() {
                    this._lines = null;
                    this.callBase()
                }
            });
        var ClipRectSvgElement = BaseSvgElement.inherit({
                ctor: function(renderer, params) {
                    this.__clipRectParams = $.extend({}, params);
                    var x = params.x,
                        y = params.y,
                        w = params.w,
                        h = params.h,
                        id = utils.getNextClipId();
                    delete params.x;
                    delete params.y;
                    delete params.w;
                    delete params.h;
                    this.callBase(renderer, 'clipPath', {id: id});
                    this.id = id;
                    this._rect = renderer.createRect(x, y, w, h, 0, params);
                    this._rect.append(this)
                },
                append: function() {
                    return this.callBase(this.renderer.defsSvg)
                },
                updateRectangle: function(settings) {
                    this._rect.applySettings(settings)
                },
                dispose: function() {
                    this._rect = null;
                    this.callBase()
                }
            });
        renderers.SvgRenderer = Class.inherit({
            ctor: function(options) {
                options = options || {};
                this._setAnimationOptions(options.animation || {});
                this.cssClass = options.cssClass || '';
                this.recreateCanvas(options.width, options.height)
            },
            dispose: function() {
                this.killContainer();
                this.animOptions = null
            },
            _setAnimationOptions: function(options) {
                this.animOptions = {
                    enabled: true,
                    duration: 1000,
                    easing: 'easeOutCubic'
                };
                if ('enabled' in options)
                    this.animOptions.enabled = options.enabled;
                if ('duration' in options)
                    this.animOptions.duration = options.duration;
                if ('easing' in options && easingFunctions[options.easing])
                    this.animOptions.easing = options.easing
            },
            updateAnimationOptions: function(newOptions) {
                this._setAnimationOptions($.extend(this.animOptions || {}, newOptions))
            },
            killContainer: function() {
                this.svgRoot && (this.svgRoot.remove(), this.svgRoot = null);
                this.defsSvg && (this.defsSvg.remove(), this.defsSvg = null);
                this.drawn = null
            },
            recreateCanvas: function(width, height, cssClass) {
                if (width > 0 && height > 0) {
                    if (!this.svgRoot) {
                        this.cssClass = cssClass || this.cssClass;
                        this.svgRoot = new RootSvgElement(this, {
                            width: width,
                            height: height,
                            'class': this.cssClass
                        })
                    }
                    else
                        this.svgRoot.applySettings({
                            width: width,
                            height: height
                        });
                    this.defsSvg && this.defsSvg.clear("pattern")
                }
            },
            resize: function(width, height) {
                var root = this.getRoot();
                root && width > 0 && height > 0 && root.applySettings({
                    width: width,
                    height: height
                })
            },
            getRoot: function() {
                return this.svgRoot
            },
            isInitialized: function() {
                return !!this.svgRoot
            },
            draw: function(container) {
                if (!container || this.drawn)
                    return;
                container.appendChild(this.getRoot().element);
                this.drawn = true
            },
            updateParams: function(params, options) {
                if (options && options.strokeWidth)
                    params.strokeWidth = options.strokeWidth
            },
            createRect: function(x, y, w, h, r, options) {
                var params = {
                        x: x,
                        y: y,
                        width: w,
                        height: h,
                        rx: r,
                        ry: r
                    };
                if (options && !options.inh)
                    $.extend(params, options);
                this.updateParams(params, options);
                return new RectSvgElement(this, params)
            },
            createSegmentRect: function(x, y, w, h, r, segments, options) {
                var params = $.extend({}, options || {}, {
                        x: x,
                        y: y,
                        width: w,
                        height: h,
                        rx: r,
                        ry: r,
                        segments: segments
                    });
                return new SegmentRectSvgElement(this, params)
            },
            createClipRect: function(x, y, w, h) {
                var attr = {
                        x: x,
                        y: y,
                        w: w,
                        h: h,
                        fill: 'none',
                        stroke: 'none',
                        strokeWidth: 0
                    };
                if (!this.defsSvg) {
                    this.defsSvg = new BaseSvgElement(this, 'defs');
                    this.defsSvg.append()
                }
                return new ClipRectSvgElement(this, attr)
            },
            createPattern: function(color, hatching) {
                hatching = (hatching || '').toLowerCase();
                if (hatching !== 'right' && hatching !== 'left')
                    return {
                            id: color,
                            append: function() {
                                return this
                            },
                            clear: function(){},
                            dispose: function(){}
                        };
                if (!this.defsSvg) {
                    this.defsSvg = new BaseSvgElement(this, 'defs');
                    this.defsSvg.append()
                }
                return new PatternSvgElement(this, {
                        hatching: hatching,
                        color: color
                    })
            },
            createImage: function(x, y, w, h, href, options) {
                var params = $.extend({}, options || {}, {
                        x: x,
                        y: y,
                        width: w,
                        height: h
                    });
                return new ImageSvgElement(this, params, href, params.location)
            },
            createLine: function(x1, y1, x2, y2, options) {
                var params = {points: [x1, y1, x2, y2]};
                if (options && !options.inh)
                    $.extend(params, options);
                this.updateParams(params, options);
                return new PathSvgElement(this, params)
            },
            createPath: function(points, options) {
                var params = {points: points};
                if (options && !options.inh)
                    $.extend(params, options);
                this.updateParams(params, options);
                return new PathSvgElement(this, params)
            },
            createBezierPath: function(points, options) {
                var params = {points: points};
                if (options && !options.inh)
                    $.extend(params, options);
                this.updateParams(params, options);
                return new BezierSvgElement(this, params)
            },
            createArea: function(points, options) {
                var params = {points: points};
                if (options && !options.inh)
                    $.extend(params, options);
                this.updateParams(params, options);
                return new AreaSvgElement(this, params)
            },
            createBezierArea: function(points, options) {
                var params = {points: points};
                if (options && !options.inh)
                    $.extend(params, options);
                this.updateParams(params, options);
                return new BezierAreaSvgElement(this, params)
            },
            createCircle: function(x, y, r, options) {
                var params = {
                        cx: x,
                        cy: y,
                        r: r
                    };
                if (options && !options.inh)
                    $.extend(params, options);
                return new CircleSvgElement(this, params)
            },
            createArc: function(x, y, outerRadius, innerRadius, startAngle, endAngle, options) {
                var params = {
                        x: x,
                        y: y,
                        outerRadius: outerRadius,
                        innerRadius: innerRadius,
                        startAngle: startAngle,
                        endAngle: endAngle
                    };
                if (options && !options.inh)
                    $.extend(params, options);
                this.updateParams(params, options);
                return new ArcSvgElement(this, params)
            },
            createText: function(text, x, y, options) {
                var params = {
                        x: x,
                        y: y,
                        text: text
                    };
                if (options && !options.inh)
                    $.extend(params, options);
                return new TextSvgElement(this, params)
            },
            createGroup: function(options) {
                return new GroupSvgElement(this, options)
            }
        });
        renderers._svgRendererInternals = {
            BaseSvgElement: BaseSvgElement,
            RootSvgElement: RootSvgElement,
            RectSvgElement: RectSvgElement,
            ImageSvgElement: ImageSvgElement,
            PathSvgElement: PathSvgElement,
            AreaSvgElement: AreaSvgElement,
            BezierSvgElement: BezierSvgElement,
            BezierAreaSvgElement: BezierAreaSvgElement,
            CircleSvgElement: CircleSvgElement,
            TextSvgElement: TextSvgElement,
            TspanSvgElement: TspanSvgElement,
            GroupSvgElement: GroupSvgElement,
            ArcSvgElement: ArcSvgElement,
            RectSvgBaseElement: RectSvgBaseElement,
            SegmentRectSvgElement: SegmentRectSvgElement,
            ClipRectSvgElement: ClipRectSvgElement,
            PatternSvgElement: PatternSvgElement
        }
    })(jQuery, DevExpress);
    /*! Module viz, file vmlRenderer.js */
    (function($, DX) {
        var renderers = DX.viz.renderers,
            utils = DX.utils,
            doc = document,
            svgRendererInternals = renderers._svgRendererInternals;
        var defaultVmlSettings = {
                x: 0,
                y: 0,
                width: 1,
                height: 1,
                position: 'absolute'
            };
        var extendDefaultVmlOptions = function(customOptions, baseOptions) {
                return $.extend(true, baseOptions || {}, defaultVmlSettings, customOptions)
            };
        var parseRotateParameter = function(rotate, defaultX, defaultY) {
                var rotateObject;
                if (utils.isDefined(rotate))
                    if (utils.isNumber(rotate))
                        rotateObject = {
                            angle: rotate,
                            x: defaultX || 0,
                            y: defaultY || 0
                        };
                    else if ($.isArray(rotate))
                        rotateObject = {
                            angle: rotate[0] || 0,
                            x: rotate[1] || 0,
                            y: rotate[2] || 0
                        };
                    else if (utils.isObject(rotate))
                        rotateObject = {
                            angle: rotate.angle || 0,
                            x: rotate.x || 0,
                            y: rotate.y || 0
                        };
                return rotateObject
            };
        var applySubElementAttribute = function(vmlElement, params, name) {
                var element = vmlElement.element,
                    subElement,
                    value = params[name];
                if (name === 'opacity' || name === 'fillOpacity')
                    if (element.fill)
                        element.fill.opacity = value >= 0.002 ? value : 0.002;
                    else {
                        subElement = doc.createElement('vml:fill');
                        element.appendChild(subElement);
                        subElement.opacity = value >= 0.002 ? value : 0.002;
                        subElement.className = 'vml';
                        if (params.fillcolor)
                            subElement.color = params.fillcolor
                    }
                if (name === 'joinStyle')
                    if (element.stroke)
                        element.stroke.joinStyle = value;
                    else {
                        subElement = doc.createElement('vml:stroke');
                        vmlElement.element.appendChild(subElement);
                        subElement.className = 'vml';
                        subElement.joinStyle = value
                    }
                if (name === 'opacity' || name === 'strokeOpacity')
                    if (element.stroke)
                        element.stroke.opacity = value >= 0.002 ? value : 0.002;
                    else {
                        subElement = doc.createElement('vml:stroke');
                        vmlElement.element.appendChild(subElement);
                        subElement.className = 'vml';
                        subElement.opacity = value >= 0.002 ? value : 0.002;
                        if (params.strokecolor)
                            subElement.color = params.strokecolor
                    }
                if (name === 'dashstyle')
                    if (element.stroke)
                        element.stroke.dashstyle = value;
                    else {
                        subElement = doc.createElement('vml:stroke');
                        vmlElement.element.appendChild(subElement);
                        subElement.className = 'vml';
                        subElement.dashstyle = value
                    }
            };
        var getBoundingClientRect = function(element) {
                var i,
                    resultRect,
                    rect,
                    tagName = element.tagName.toLowerCase(),
                    points,
                    value,
                    halfStrokeWidth;
                if (tagName === 'div') {
                    if (element.childNodes.length > 0) {
                        resultRect = {};
                        for (i = 0; i < element.childNodes.length; i++) {
                            rect = getBoundingClientRect(element.childNodes[i]);
                            if (!rect)
                                continue;
                            resultRect.left = resultRect.left === undefined || rect.left < resultRect.left ? rect.left : resultRect.left;
                            resultRect.top = resultRect.top === undefined || rect.top < resultRect.top ? rect.top : resultRect.top;
                            resultRect.right = resultRect.right === undefined || rect.right > resultRect.right ? rect.right : resultRect.right;
                            resultRect.bottom = resultRect.bottom === undefined || rect.bottom > resultRect.bottom ? rect.bottom : resultRect.bottom
                        }
                    }
                }
                else if (tagName === 'shape' || tagName === 'vml:shape') {
                    points = (element.path.value || element.path).match(/[-0-9]+/g);
                    resultRect = {};
                    rect = element.getBoundingClientRect();
                    for (i = 0; i < points.length; i++) {
                        value = parseInt(points[i]);
                        if (i % 2) {
                            resultRect.top = resultRect.top === undefined || value < resultRect.top ? value : resultRect.top;
                            resultRect.bottom = resultRect.bottom === undefined || value > resultRect.bottom ? value : resultRect.bottom
                        }
                        else {
                            resultRect.left = resultRect.left === undefined || value < resultRect.left ? value : resultRect.left;
                            resultRect.right = resultRect.right === undefined || value > resultRect.right ? value : resultRect.right
                        }
                    }
                    resultRect.left = resultRect.left || 0;
                    resultRect.top = resultRect.top || 0;
                    resultRect.right = resultRect.right || 0;
                    resultRect.bottom = resultRect.bottom || 0;
                    if (rect.right - rect.left <= 1 && rect.top - rect.bottom <= 1) {
                        resultRect.right = resultRect.right + rect.left;
                        resultRect.bottom = resultRect.bottom + rect.top;
                        resultRect.left = resultRect.left + rect.left;
                        resultRect.top = resultRect.top + rect.top
                    }
                    else {
                        resultRect.right = resultRect.right - resultRect.left + rect.left;
                        resultRect.bottom = resultRect.bottom - resultRect.top + rect.top;
                        resultRect.left = rect.left;
                        resultRect.top = rect.top
                    }
                    halfStrokeWidth = Math.ceil(parseFloat(element.strokeweight) / 2);
                    if (halfStrokeWidth && halfStrokeWidth > 1) {
                        resultRect.left -= halfStrokeWidth;
                        resultRect.top -= halfStrokeWidth;
                        resultRect.right += halfStrokeWidth;
                        resultRect.bottom += halfStrokeWidth
                    }
                }
                else
                    resultRect = element.getBoundingClientRect();
                return resultRect
            };
        var BaseVmlElement = {
                isVml: function() {
                    return true
                },
                dispose: function() {
                    this.childElements = null;
                    this._style = null;
                    this.callBase()
                },
                defaultSettings: function(customOptions) {
                    return extendDefaultVmlOptions(customOptions, this.callBase ? this.callBase() : {})
                },
                createElement: function(nodeName) {
                    this._nodeName = nodeName;
                    this.childElements = [];
                    if (this.isVml()) {
                        var result = doc.createElement('vml:' + nodeName);
                        result.className = 'vml';
                        return result
                    }
                    else
                        return doc.createElement(nodeName)
                },
                clear: function() {
                    this.callBase();
                    this.childElements = []
                },
                _fillAttributesFromCurrentStyle: function(attributes) {
                    var element = this.element,
                        backgroundColor,
                        root = this.renderer.getRoot(),
                        defaultColor = root && root.element.currentStyle && root.element.currentStyle.color;
                    if (this.isVml() && element.style && element.currentStyle) {
                        if (element.style.backgroundColor === 'transparent')
                            element.style.backgroundColor = '';
                        if (element.currentStyle.backgroundColor !== 'transparent') {
                            backgroundColor = element.currentStyle.backgroundColor;
                            if (!(this instanceof RectVmlElement))
                                element.style.backgroundColor = 'transparent';
                            attributes.filled = 't';
                            attributes.fillcolor = backgroundColor;
                            if (element.currentStyle.opacity) {
                                element.style.filter = 'alpha(opacity=' + element.currentStyle.opacity * 100 + ')';
                                delete attributes.opacity;
                                delete attributes.fillOpacity
                            }
                        }
                        if (defaultColor && element.currentStyle.color !== defaultColor) {
                            attributes.stroked = 't';
                            attributes.strokecolor = this.element.currentStyle.color;
                            if (element.currentStyle.opacity)
                                attributes.strokeOpacity = element.currentStyle.opacity
                        }
                    }
                },
                _applyAttributes: function(params) {
                    var name,
                        value;
                    if (params && params.arcsize !== undefined) {
                        try {
                            this.element.setAttribute('arcsize', params.arcsize)
                        }
                        catch(e) {}
                        this.__appliedSettings = {arcsize: params.arcsize};
                        delete params.arcsize
                    }
                    if (!this._isAppended) {
                        this._delayedAttributes = params;
                        if (utils.isDefined(params['class']))
                            if (!this.isVml())
                                this.element.className = params['class']
                    }
                    else {
                        params = params || this._delayedAttributes;
                        if (params) {
                            this._fillAttributesFromCurrentStyle(params);
                            for (name in params) {
                                value = params[name];
                                if (name === 'opacity' || name === 'fillOpacity' || name === 'strokeOpacity' || name === 'dashstyle' || name === 'joinStyle')
                                    applySubElementAttribute(this, params, name);
                                else if (name === 'class')
                                    if (this.isVml())
                                        this.element.className = 'vml ' + value;
                                    else
                                        this.element.className = value;
                                else
                                    this.element[name] = value
                            }
                            this.__appliedSettings = params;
                            delete this._delayedAttributes
                        }
                    }
                },
                appendComplete: function() {
                    this._isAppended = true;
                    this._applyAttributes();
                    $.each(this.childElements, function(_, child) {
                        child.appendComplete()
                    })
                },
                append: function(element) {
                    var root = this.renderer.getRoot(),
                        toElement = element || root;
                    if (toElement) {
                        toElement.element.appendChild(this.element);
                        toElement.childElements.push(this)
                    }
                    if (toElement === root || toElement._isAppended)
                        this.appendComplete();
                    return this
                },
                _normalizeSettings: function(settings) {
                    var key,
                        style = {},
                        normalized = {},
                        clipRect,
                        pos,
                        prop,
                        value,
                        styleName,
                        firstChar,
                        cssProperties = ['position', 'display', 'visibility', 'filter', 'margin', 'marginTop', 'marginLeft', 'marginRight', 'marginBottom', 'whiteSpace', 'clip'];
                    for (key in settings) {
                        prop = key;
                        value = settings[prop];
                        if (prop === 'x' || prop === 'translateX') {
                            pos = settings.x || 0;
                            if (settings.translateX)
                                pos += settings.translateX;
                            style.left = pos + 'px'
                        }
                        else if (prop === 'y' || prop === 'translateY') {
                            pos = settings.y || 0;
                            if (settings.translateY)
                                pos += settings.translateY;
                            style.top = pos + 'px'
                        }
                        else if (prop === 'width')
                            style.width = value + 'px';
                        else if (prop === 'height')
                            style.height = value + 'px';
                        else if (prop === 'align')
                            style.textAlign = value;
                        else if ($.inArray(prop, cssProperties) != -1)
                            style[prop] = value;
                        else if (prop === 'fill') {
                            if (this.isVml()) {
                                normalized.filled = value === 'none' ? 'f' : 't';
                                normalized.fillcolor = value
                            }
                        }
                        else if (prop === 'opacity')
                            normalized.opacity = value < 0.002 ? '99f' : value;
                        else if (prop === 'stroke') {
                            normalized.stroked = value === 'none' ? 'f' : 't';
                            normalized.strokecolor = value
                        }
                        else if (prop === 'strokeWidth')
                            normalized.strokeweight = value + 'px';
                        else if (prop === 'lineJoin')
                            normalized.joinStyle = value;
                        else if (prop === 'font') {
                            if (!$.isPlainObject(value))
                                continue;
                            $.each(value, function(fontSettingName) {
                                switch (fontSettingName) {
                                    case'color':
                                    case'cursor':
                                        styleName = fontSettingName;
                                        break;
                                    case'opacity':
                                        styleName = 'opacity';
                                        break;
                                    default:
                                        firstChar = fontSettingName.charAt(0);
                                        styleName = 'font' + fontSettingName.replace(firstChar, firstChar.toUpperCase())
                                }
                                style[styleName] = value[fontSettingName]
                            })
                        }
                        else if (prop === 'style')
                            $.extend(true, style, value);
                        else if (prop === 'rotate')
                            this['_rotate'] = value;
                        else if (prop === 'dashStyle') {
                            value = value.toLowerCase();
                            if (value !== 'solid')
                                normalized.dashstyle = value
                        }
                        else if (prop === 'clipId') {
                            clipRect = this.renderer.getClipRect(value, this);
                            if (clipRect) {
                                var width = clipRect.width,
                                    height = clipRect.height,
                                    x = clipRect.x,
                                    y = clipRect.y,
                                    clipWidth = width + x,
                                    clipHeight = height + y;
                                style.width = clipRect.cSize.width;
                                style.height = clipRect.cSize.height;
                                style.clip = "rect(" + y + "px, " + clipWidth + "px, " + clipHeight + "px, " + x + "px)"
                            }
                        }
                        else if (prop === 'segments')
                            continue;
                        else
                            normalized[prop] = value
                    }
                    this['_style'] = style;
                    return normalized
                },
                _getBBox: function() {
                    var width,
                        height,
                        rect,
                        parentRect,
                        x = 0,
                        y = 0,
                        element = this.element,
                        parent;
                    try {
                        rect = getBoundingClientRect(element);
                        width = rect.right - rect.left;
                        height = rect.bottom - rect.top;
                        parent = this.element.parentNode || this.renderer.getRoot().element;
                        parentRect = parent.getBoundingClientRect();
                        x = rect.left - parentRect.left;
                        y = rect.top - parentRect.top;
                        if (element.tagName.toLowerCase() === 'div') {
                            x = x - parseInt(element.style.left, 10);
                            y = y - parseInt(element.style.top, 10)
                        }
                    }
                    catch(e) {
                        width = element.offsetWidth || 0;
                        height = element.offsetHeight || 0
                    }
                    return {
                            x: x,
                            y: y,
                            width: width,
                            height: height,
                            isEmpty: !x && !y && !width && !height
                        }
                },
                getBBox: function() {
                    return this._getBBox()
                },
                sharpEdges: function(){}
            };
        var convertSvgPathCommandToVml = function(command) {
                switch (command) {
                    case'M':
                        return 'm';
                    case'L':
                        return 'l';
                    case'Z':
                        return 'x e'
                }
                return command
            };
        var BasePathVmlElement = {
                defaultSettings: function() {
                    return $.extend(this.callBase(), {
                            coordsize: '1,1',
                            fill: 'none',
                            strokecolor: 'black',
                            stroked: 't'
                        })
                },
                getNodeName: function() {
                    return 'shape'
                },
                getPathAttributeName: function() {
                    return 'path'
                },
                customizeSegments: function(segments) {
                    var result = segments;
                    if (segments)
                        result = $.map(segments, function(s, i) {
                            var pos,
                                segmentArray = [],
                                command = convertSvgPathCommandToVml(s[0]);
                            segmentArray.push(command);
                            for (pos = 1; pos < s.length; pos++)
                                segmentArray.push(Math.floor(s[pos]));
                            return [segmentArray]
                        });
                    return result
                }
            };
        var RootVmlElement = svgRendererInternals.BaseSvgElement.inherit(BaseVmlElement).inherit({
                isVml: function() {
                    return false
                },
                defaultSettings: function() {
                    return {
                            width: 0,
                            height: 0,
                            position: 'relative',
                            display: 'inline-block',
                            overflow: 'hidden'
                        }
                },
                ctor: function(renderer, params) {
                    this.callBase(renderer, 'div', params)
                }
            });
        var ImageVmlElement = svgRendererInternals.BaseSvgElement.inherit(svgRendererInternals.RectSvgBaseElement).inherit(BaseVmlElement).inherit({
                ctor: function(renderer, params) {
                    this.callBase(renderer, 'image', params)
                },
                defaultSettings: function() {
                    return $.extend(this.callBase(), {strokeWidth: 0})
                },
                adjustSettings: function() {
                    this.callBase();
                    if (this.settings.href) {
                        this.settings.src = this.settings.href;
                        delete this.settings.href
                    }
                }
            });
        var RectVmlElement = svgRendererInternals.BaseSvgElement.inherit(svgRendererInternals.RectSvgBaseElement).inherit(BaseVmlElement).inherit({
                defaultSettings: function() {
                    return extendDefaultVmlOptions({
                            stroked: 'f',
                            strokeWidth: 0,
                            rx: 0,
                            ry: 0
                        })
                },
                recreateElement: function(name) {
                    this._nodeName = name;
                    var parent = this.$element.parent()[0];
                    if (parent) {
                        var $oldElement = this.$element;
                        this.element = this.createElement(name);
                        this.$element = $(this.element);
                        this.$element.insertBefore($oldElement);
                        $oldElement.remove()
                    }
                    else {
                        this.element = this.createElement(name);
                        this.$element = $(this.element)
                    }
                    this.applySettings()
                },
                _adjustArcSize: function() {
                    var settings = this.settings;
                    var rx = settings.rx || 0,
                        ry = settings.ry || 0,
                        width = settings.width,
                        height = settings.height,
                        r,
                        halfsize,
                        arcsize;
                    if (settings.rx !== undefined || settings.ry !== undefined) {
                        r = Math.max(rx, ry);
                        halfsize = Math.max(width, height) / 2;
                        arcsize = r / halfsize;
                        settings.arcsize = arcsize;
                        if ($.isNumeric(arcsize) && arcsize != 0)
                            this._nodeName !== 'roundrect' && this.recreateElement('roundrect');
                        else
                            this._nodeName === 'roundrect' && this.recreateElement('rect');
                        delete settings.rx;
                        delete settings.ry
                    }
                },
                _adjustRotation: function() {
                    var settings = this.settings;
                    var rotate = this.settings.rotate,
                        rotateAngle,
                        radianAngle,
                        cos,
                        sin,
                        rotateX,
                        rotateY,
                        marginTop,
                        marginLeft,
                        cx,
                        cy,
                        rotateObject;
                    rotateObject = parseRotateParameter(rotate, settings.x, settings.y);
                    if (rotateObject) {
                        rotateAngle = rotateObject.angle;
                        rotateX = rotateObject.x;
                        rotateY = rotateObject.y;
                        radianAngle = rotateAngle * Math.PI / 180.0;
                        cos = Math.cos(radianAngle);
                        sin = Math.sin(radianAngle);
                        cx = settings.x + (settings.translateX || 0) + settings.width / 2;
                        cy = settings.y + (settings.translateY || 0) + settings.height / 2;
                        marginLeft = (cx - rotateX) * cos - (cy - rotateY) * sin + rotateX - cx;
                        marginTop = (cx - rotateX) * sin + (cy - rotateY) * cos + rotateY - cy;
                        this.settings.marginLeft = Math.round(marginLeft) + 'px';
                        this.settings.marginTop = Math.round(marginTop) + 'px';
                        this.settings.rotation = rotateAngle
                    }
                },
                adjustSettings: function() {
                    this.callBase();
                    this._adjustArcSize();
                    this._adjustRotation()
                },
                ctor: function(renderer, params) {
                    this.callBase(renderer, 'rect', params)
                }
            });
        var PathVmlElement = svgRendererInternals.PathSvgElement.inherit(BaseVmlElement).inherit(BasePathVmlElement).inherit({prepareSegments: function(settings) {
                    var rotate = settings.rotate,
                        rotateAngle,
                        rotateX,
                        rotateY,
                        oldSegments,
                        radianAngle,
                        cos,
                        sin,
                        x,
                        y,
                        rotatedX,
                        rotatedY,
                        rotateObject;
                    this.callBase(settings);
                    oldSegments = this.segments;
                    rotateObject = parseRotateParameter(rotate, settings.x, settings.y);
                    if (rotateObject) {
                        rotateAngle = rotateObject.angle;
                        rotateX = rotateObject.x;
                        rotateY = rotateObject.y;
                        if (this.segments) {
                            radianAngle = rotateAngle * Math.PI / 180.0;
                            cos = Math.cos(radianAngle);
                            sin = Math.sin(radianAngle);
                            this.segments = $.map(this.segments, function(s, i) {
                                if (s.length === 3) {
                                    x = s[1],
                                    y = s[2];
                                    rotatedX = (x - rotateX) * cos - (y - rotateY) * sin + rotateX;
                                    rotatedY = (x - rotateX) * sin + (y - rotateY) * cos + rotateY;
                                    return [[s[0], Math.floor(rotatedX), Math.floor(rotatedY)]]
                                }
                                else
                                    return [s]
                            });
                            this.combinePathParams(settings);
                            this.segments = oldSegments
                        }
                    }
                }});
        var AreaVmlElement = PathVmlElement.inherit({
                defaultSettings: function() {
                    var baseOptions = this.callBase();
                    return extendDefaultVmlOptions({
                            points: {
                                x: 0,
                                y: 0
                            },
                            fill: 'black',
                            stroke: 'none'
                        }, baseOptions)
                },
                ctor: function(renderer, params) {
                    this.closePath = true;
                    this.callBase(renderer, params)
                }
            });
        var SegmentRectVmlElement = svgRendererInternals.SegmentRectSvgElement.inherit(BaseVmlElement).inherit(BasePathVmlElement).inherit({
                defaultSettings: function() {
                    var settings = this.callBase();
                    settings.lineJoin = 'miter';
                    delete settings.fill;
                    delete settings.stroke;
                    delete settings.strokecolor;
                    delete settings.stroked;
                    return settings
                },
                prepareSegments: function() {
                    this.callBase();
                    this.segments = this.customizeSegments(this.segments);
                    this.settings.x = 0;
                    this.settings.y = 0;
                    this.settings.width = 1;
                    this.settings.height = 1
                },
                applySettings: function(settings) {
                    var x = settings.x,
                        y = settings.y,
                        w = settings.width,
                        h = settings.height;
                    this.callBase(settings);
                    this.settings.x = x;
                    this.settings.y = y;
                    this.settings.width = w;
                    this.settings.height = h
                }
            });
        var BezierVmlElement = svgRendererInternals.BezierSvgElement.inherit(BaseVmlElement).inherit(BasePathVmlElement);
        var BezierAreaVmlElement = BezierVmlElement.inherit({
                defaultSettings: function() {
                    var baseOptions = this.callBase();
                    return extendDefaultVmlOptions({
                            points: {
                                x: 0,
                                y: 0
                            },
                            fill: 'black',
                            stroke: 'none'
                        }, baseOptions)
                },
                ctor: function(renderer, params) {
                    this.closePath = true;
                    this.callBase(renderer, params)
                }
            });
        var ArcVmlElement = svgRendererInternals.ArcSvgElement.inherit(BaseVmlElement).inherit(BasePathVmlElement).inherit({createArcSegments: function(x, y, innerR, outerR, startAngle, endAngle) {
                    var xOuterStart = x + outerR * Math.cos(startAngle),
                        yOuterStart = y - outerR * Math.sin(startAngle),
                        xOuterEnd = x + outerR * Math.cos(endAngle),
                        yOuterEnd = y - outerR * Math.sin(endAngle),
                        xInnerStart = x + innerR * Math.cos(endAngle),
                        yInnerStart = y - innerR * Math.sin(endAngle),
                        xInnerEnd = x + innerR * Math.cos(startAngle),
                        yInnerEnd = y - innerR * Math.sin(startAngle);
                    return [['wr', x - innerR, y - innerR, x + innerR, y + innerR, xInnerStart, yInnerStart, xInnerEnd, yInnerEnd], ['at', x - outerR, y - outerR, x + outerR, y + outerR, xOuterStart, yOuterStart, xOuterEnd, yOuterEnd], ['x e']]
                }});
        var CircleVmlElement = svgRendererInternals.BaseSvgElement.inherit(BaseVmlElement).inherit({
                defaultSettings: function() {
                    return extendDefaultVmlOptions({
                            cx: 0,
                            cy: 0,
                            r: 0
                        })
                },
                applySettings: function(settings) {
                    settings.cx = settings.cx || settings.x;
                    settings.cy = settings.cy || settings.y;
                    return this.callBase(settings)
                },
                adjustSettings: function() {
                    var r,
                        cx,
                        cy;
                    if (this.settings.cx !== undefined || this.settings.cy !== undefined || this.settings.r !== undefined) {
                        r = 'r' in this.settings ? this.settings.r : this.settings.width / 2;
                        cx = 'cx' in this.settings ? this.settings.cx : this.settings.x + this.settings.width / 2;
                        cy = 'cy' in this.settings ? this.settings.cy : this.settings.y + this.settings.width / 2;
                        this.settings.x = cx - r;
                        this.settings.y = cy - r;
                        this.settings.width = this.settings.height = r * 2;
                        delete this.settings.cx;
                        delete this.settings.cy;
                        delete this.settings.r
                    }
                },
                ctor: function(renderer, params) {
                    this.callBase(renderer, 'oval', params)
                }
            });
        var TextVmlElement = svgRendererInternals.BaseSvgElement.inherit(BaseVmlElement).inherit({
                isVml: function() {
                    return false
                },
                defaultSettings: function() {
                    return {
                            x: 0,
                            y: 0,
                            position: 'absolute',
                            whiteSpace: 'nowrap'
                        }
                },
                ctor: function(renderer, params) {
                    this.callBase(renderer, 'span', params)
                },
                adjustSettings: function() {
                    var text;
                    if ('text' in this.settings) {
                        text = utils.isDefined(this.settings.text) ? this.settings.text : '';
                        text = text.toString().replace(/\r/g, "");
                        text = text.replace(/\n/g, "<br/>");
                        $(this.element).html(text);
                        delete this.settings.text
                    }
                },
                updateText: function(text) {
                    this.applySettings({text: utils.isDefined(text) ? text : ''})
                },
                _applyAttributes: function(settings) {
                    this.callBase(settings);
                    var settings = this.settings,
                        rotate = this.settings.rotate,
                        rotateAngle = 0,
                        rotateX,
                        rotateY,
                        cos = 1,
                        sin = 0,
                        osin = 0,
                        ocos = 1,
                        angle,
                        otg,
                        rad,
                        y = this.settings.y + (this.settings.translateY || 0),
                        x = this.settings.x + (this.settings.translateX || 0),
                        align = this.settings.align,
                        bBox = this.getBBox(),
                        style = this._style || {},
                        marginLeft = 0,
                        marginTop = 0,
                        fontHeightOffset,
                        alignMultiplier,
                        rotateObject,
                        textWidth,
                        textHeight;
                    if (this._oldRotate && !bBox.isEmpty) {
                        rad = this._oldRotate.angle * Math.PI / 180.0;
                        osin = Math.sin(rad);
                        ocos = Math.cos(rad);
                        if ((this._oldRotate.angle | 0) % 90 !== 0)
                            if ((this._oldRotate.angle | 0) % 45 === 0)
                                textWidth = bBox.width,
                                textHeight = bBox.height;
                            else {
                                otg = Math.abs(Math.tan(rad));
                                var b = (bBox.width - bBox.height * otg) / (1 - otg * otg);
                                var a = bBox.width - b;
                                textHeight = Math.abs(a / osin);
                                textWidth = Math.abs(b / ocos)
                            }
                        else {
                            textHeight = Math.abs(bBox.height * ocos - bBox.width * osin);
                            textWidth = Math.abs(bBox.width * ocos - bBox.height * osin)
                        }
                    }
                    else
                        textWidth = bBox.width,
                        textHeight = bBox.height;
                    this.__textWidth = textWidth;
                    this.__textHeight = textHeight;
                    if (textHeight || textWidth) {
                        rotateObject = parseRotateParameter(rotate, x, y);
                        this._oldRotate = rotateObject;
                        if (rotateObject) {
                            rotateAngle = rotateObject.angle;
                            rotateX = rotateObject.x;
                            rotateY = rotateObject.y;
                            if (Math.abs(rotateAngle) > 360)
                                rotateAngle = rotateAngle % 360;
                            if (rotateAngle < 0)
                                rotateAngle = rotateAngle + 360;
                            if (rotateAngle) {
                                rad = rotateAngle * Math.PI / 180.0;
                                cos = Math.cos(rad);
                                sin = Math.sin(rad);
                                style.filter = 'progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand", M11 = ' + cos.toFixed(5) + ', M12 = ' + (-sin).toFixed(5) + ', M21 = ' + sin.toFixed(5) + ', M22 = ' + cos.toFixed(5) + ')'
                            }
                            else {
                                style.filter = '';
                                this._oldRotate = null
                            }
                            marginLeft = (x - rotateX) * (cos - 1) - (y - rotateY) * sin;
                            marginTop = (x - rotateX) * sin + (y - rotateY) * (cos - 1)
                        }
                        fontHeightOffset = textHeight * (0.55 + 0.45 / 2);
                        if (rotateAngle < 90) {
                            marginTop -= fontHeightOffset * cos;
                            marginLeft -= (textHeight - fontHeightOffset) * sin
                        }
                        else if (rotateAngle < 180) {
                            marginTop += (textHeight - fontHeightOffset) * cos;
                            marginLeft += textWidth * cos - (textHeight - fontHeightOffset) * sin
                        }
                        else if (rotateAngle < 270) {
                            marginTop += (textHeight - fontHeightOffset) * cos + textWidth * sin;
                            marginLeft += textWidth * cos + fontHeightOffset * sin
                        }
                        else {
                            marginTop += textWidth * sin - fontHeightOffset * cos;
                            marginLeft += fontHeightOffset * sin
                        }
                        alignMultiplier = {
                            center: 0.5,
                            right: 1
                        }[align];
                        if (alignMultiplier) {
                            marginLeft -= textWidth * alignMultiplier * cos;
                            marginTop -= textWidth * alignMultiplier * sin
                        }
                        style.marginLeft = Math.round(marginLeft) + 'px';
                        style.marginTop = Math.round(marginTop) + 'px'
                    }
                    if (settings.fill && settings.fill !== 'none')
                        style.color = settings.fill;
                    if (settings.opacity)
                        this.element.style.filter = 'alpha(opacity=' + settings.opacity * 100 + ')';
                    this.applyStyle(style)
                }
            });
        var GroupVmlElement = svgRendererInternals.BaseSvgElement.inherit(BaseVmlElement).inherit({
                isVml: function() {
                    return false
                },
                defaultSettings: function() {
                    return {
                            x: 0,
                            y: 0,
                            position: 'absolute'
                        }
                },
                ctor: function(renderer, params) {
                    this.callBase(renderer, 'div', params)
                },
                applySettings: function(settings) {
                    var callBase = this.callBase,
                        rotate;
                    settings = settings || {};
                    rotate = settings.rotate;
                    if (rotate) {
                        if (utils.isNumber(rotate))
                            rotate = [rotate, settings.x || 0, settings.y || 0];
                        $.each(this.childElements, function(_, child) {
                            child.applySettings({rotate: rotate})
                        })
                    }
                    delete settings.rotate;
                    settings.x = 0;
                    settings.y = 0;
                    this.callBase = callBase;
                    return this.callBase(settings)
                },
                getBBox: function() {
                    return this._getBBox()
                },
                update: function() {
                    if (this.settings.clipId) {
                        var bbox = this.getBBox();
                        this.applyStyle({
                            left: bbox.x + (this.settings.translateX || 0),
                            right: bbox.y + (this.settings.translateY || 0),
                            width: bbox.width,
                            height: bbox.height
                        })
                    }
                }
            });
        renderers.VmlRenderer = renderers.SvgRenderer.inherit({
            ctor: function(options) {
                options = options || {};
                options.animation = {enabled: false};
                if (document.namespaces && !document.namespaces.vml) {
                    document.namespaces.add('vml', 'urn:schemas-microsoft-com:vml');
                    document.createStyleSheet().addRule('.vml', 'behavior: url(#default#VML); display: inline-block;')
                }
                this._clipRects = {};
                this.cssClass = options.cssClass || '';
                this.callBase(options)
            },
            dispose: function() {
                this.callBase();
                this._clipRects = null;
                this._size = null
            },
            updateAnimationOptions: $.noop,
            recreateCanvas: function(width, height, cssClass) {
                if (width > 0 && height > 0) {
                    this._size = {
                        width: width,
                        height: height
                    };
                    if (!this.svgRoot) {
                        this.cssClass = cssClass || this.cssClass;
                        this.svgRoot = new RootVmlElement(this, {
                            width: width,
                            height: height,
                            'class': this.cssClass
                        })
                    }
                    else
                        this.svgRoot.applySettings({
                            width: width,
                            height: height
                        });
                    this.defsSvg && this.defsSvg.clear()
                }
            },
            _getSize: function() {
                return this._size || {}
            },
            createRect: function(x, y, w, h, r, options) {
                var params = $.extend(true, {}, options || {}, {
                        x: x,
                        y: y,
                        width: w,
                        height: h,
                        rx: r,
                        ry: r
                    });
                return new RectVmlElement(this, params)
            },
            createSegmentRect: function(x, y, w, h, r, segments, options) {
                var params = $.extend({}, options || {}, {
                        x: x,
                        y: y,
                        width: w,
                        height: h,
                        rx: r,
                        ry: r,
                        segments: segments
                    });
                return new SegmentRectVmlElement(this, params)
            },
            createClipRect: function(x, y, width, height) {
                var clipId = utils.getNextClipId(),
                    elements = [],
                    clipRect = {
                        id: clipId,
                        x: x,
                        y: y,
                        width: width,
                        height: height,
                        cSize: this._getSize(),
                        addElement: function(element) {
                            var hasElement = false;
                            $.each(elements, function() {
                                if (this === element) {
                                    hasElement = true;
                                    return false
                                }
                            });
                            if (!hasElement)
                                elements.push(element)
                        },
                        append: function() {
                            return this
                        },
                        remove: function(){},
                        dispose: function(){},
                        updateRectangle: function(settings) {
                            if ('x' in settings)
                                this.x = settings.x;
                            if ('translateX' in settings)
                                this.x += settings.translateX;
                            if ('y' in settings)
                                this.y = settings.y;
                            if ('translateY' in settings)
                                this.y += settings.translateY;
                            if ('width' in settings)
                                this.width = settings.width;
                            if ('height' in settings)
                                this.height = settings.height;
                            $.each(elements, function() {
                                this.applySettings({clipId: clipId})
                            });
                            return this
                        }
                    };
                this._clipRects[clipId] = clipRect;
                return clipRect
            },
            getClipRect: function(clipId, element) {
                var clipRect = this._clipRects[clipId];
                if (clipRect && element)
                    clipRect.addElement(element);
                return this._clipRects[clipId]
            },
            createImage: function(x, y, w, h, href, options) {
                var params = $.extend(true, {}, options || {}, {
                        x: x,
                        y: y,
                        width: w,
                        height: h,
                        href: href
                    });
                return new ImageVmlElement(this, params)
            },
            createLine: function(x1, y1, x2, y2, options) {
                var params = $.extend(true, {}, options || {}, {points: [x1, y1, x2, y2]});
                return new PathVmlElement(this, params)
            },
            createPath: function(points, options) {
                var params = $.extend(true, {}, options || {}, {points: points});
                return new PathVmlElement(this, params)
            },
            createBezierPath: function(points, options) {
                var params = $.extend(true, {}, options || {}, {points: points});
                return new BezierVmlElement(this, params)
            },
            createArea: function(points, options) {
                var params = $.extend(true, {}, options || {}, {points: points});
                return new AreaVmlElement(this, params)
            },
            createBezierArea: function(points, options) {
                var params = $.extend(true, {}, options || {}, {points: points});
                return new BezierAreaVmlElement(this, params)
            },
            createCircle: function(x, y, r, options) {
                var params = $.extend(true, {}, options || {}, {
                        cx: x,
                        cy: y,
                        r: r
                    });
                return new CircleVmlElement(this, params)
            },
            createArc: function(x, y, outerRadius, innerRadius, startAngle, endAngle, options) {
                var params = $.extend(true, {}, options || {}, {
                        x: x,
                        y: y,
                        outerRadius: outerRadius,
                        innerRadius: innerRadius,
                        startAngle: startAngle,
                        endAngle: endAngle
                    });
                return new ArcVmlElement(this, params)
            },
            createText: function(text, x, y, options) {
                var params = $.extend(true, {}, options || {}, {
                        x: x,
                        y: y,
                        text: text
                    });
                return new TextVmlElement(this, params)
            },
            createGroup: function(options) {
                return new GroupVmlElement(this, options)
            },
            createPattern: function(color) {
                return {
                        id: color,
                        append: function() {
                            return this
                        },
                        clear: function(){},
                        dispose: function(){}
                    }
            }
        });
        renderers.__vmlRendererInternals = {
            RootVmlElement: RootVmlElement,
            RectVmlElement: RectVmlElement,
            ImageVmlElement: ImageVmlElement,
            PathVmlElement: PathVmlElement,
            AreaVmlElement: AreaVmlElement,
            BezierVmlElement: BezierVmlElement,
            BezierAreaVmlElement: BezierAreaVmlElement,
            CircleVmlElement: CircleVmlElement,
            TextVmlElement: TextVmlElement,
            GroupVmlElement: GroupVmlElement,
            ArcVmlElement: ArcVmlElement,
            SegmentRectVmlElement: SegmentRectVmlElement
        }
    })(jQuery, DevExpress);
    /*! Module viz, file renderer.js */
    (function($, DX) {
        function supportSVG() {
            return !!document.createElementNS && !!document.createElementNS('http://www.w3.org/2000/svg', "svg").createSVGRect
        }
        var renderers = DX.viz.renderers,
            browser = DX.browser;
        if (browser.msie && browser.version < 9 && !supportSVG())
            renderers.Renderer = renderers.VmlRenderer;
        else
            renderers.Renderer = renderers.SvgRenderer
    })(jQuery, DevExpress);
    /*! Module viz, file namespaces.js */
    (function(DevExpress) {
        DevExpress.viz.charts = {series: {}}
    })(DevExpress);
    /*! Module viz, file range.js */
    (function($, DX, undefined) {
        var isDefinedUtils = DX.utils.isDefined,
            isDateUtils = DX.utils.isDate;
        var NUMBER_EQUALITY_CORRECTION = 1,
            DATETIME_EQUALITY_CORRECTION = 60000;
        DX.viz.charts.Range = DX.Class.inherit(function() {
            var ctor = function(range) {
                    range && $.extend(this, range)
                };
            var dispose = function() {
                    this.categoriesY = null;
                    this.categoriesX = null
                };
            var otherLessThan = function(thisValue, otherValue) {
                    return otherValue < thisValue
                };
            var otherGreaterThan = function(thisValue, otherValue) {
                    return otherValue > thisValue
                };
            var compareAndReplace = function(thisValue, otherValue, setValue, compare) {
                    var thisValueDefined = thisValue !== undefined,
                        otherValueDefined = otherValue !== undefined;
                    if (thisValueDefined) {
                        if (otherValueDefined && compare(thisValue, otherValue))
                            setValue(otherValue)
                    }
                    else if (otherValueDefined)
                        setValue(otherValue)
                };
            var getBoundRange = function(otherRange) {
                    getBoundRangeX.call(this, otherRange);
                    getBoundRangeY.call(this, otherRange);
                    return this
                };
            var getBoundRangeY = function(otherRange) {
                    var self = this,
                        categoriesY = self.categoriesY,
                        otherCategoriesY = otherRange.categoriesY,
                        i;
                    var setIndentByPriority = function(prefix) {
                            var priorityRelation = (self[prefix + 'Priority'] || 0) - (otherRange[prefix + 'Priority'] || 0);
                            if ((self[prefix] || 0) < otherRange[prefix] && priorityRelation === 0 || priorityRelation < 0) {
                                self[prefix] = otherRange[prefix];
                                self[prefix + 'Priority'] = otherRange[prefix + 'Priority']
                            }
                        };
                    self.invertY = self.invertY || otherRange.invertY;
                    self.stickY = self.stickY || otherRange.stickY;
                    self.keepValueMarginsY = self.keepValueMarginsY || otherRange.keepValueMarginsY;
                    compareAndReplace(self.minY, otherRange.minY, function(value) {
                        self.minY = value
                    }, otherLessThan);
                    compareAndReplace(self.intervalY, otherRange.intervalY, function(value) {
                        self.intervalY = value
                    }, otherLessThan);
                    compareAndReplace(self.maxY, otherRange.maxY, function(value) {
                        self.maxY = value
                    }, otherGreaterThan);
                    compareAndReplace(self.minVisibleY, otherRange.minVisibleY, function(value) {
                        self.minVisibleY = value
                    }, otherLessThan);
                    compareAndReplace(self.maxVisibleY, otherRange.maxVisibleY, function(value) {
                        self.maxVisibleY = value
                    }, otherGreaterThan);
                    setIndentByPriority('minValueMarginY');
                    setIndentByPriority('maxValueMarginY');
                    if (categoriesY === undefined)
                        self.categoriesY = otherCategoriesY;
                    else if (otherCategoriesY && otherCategoriesY.length)
                        for (i = 0; i < otherCategoriesY.length; i++)
                            if ($.inArray(otherCategoriesY[i], categoriesY) === -1)
                                categoriesY.push(otherCategoriesY[i]);
                    return this
                };
            var getBoundRangeX = function(otherRange) {
                    var self = this,
                        categoriesX = self.categoriesX,
                        otherCategoriesX = otherRange.categoriesX,
                        i;
                    var setIndentByPriority = function(prefix) {
                            var priorityRelation = (self[prefix + 'Priority'] || 0) - (otherRange[prefix + 'Priority'] || 0);
                            if ((self[prefix] || 0) < otherRange[prefix] && priorityRelation === 0 || priorityRelation < 0) {
                                self[prefix] = otherRange[prefix];
                                self[prefix + 'Priority'] = otherRange[prefix + 'Priority']
                            }
                        };
                    self.invertX = self.invertX || otherRange.invertX;
                    self.stickX = self.stickX || otherRange.stickX;
                    self.keepValueMarginsX = self.keepValueMarginsX || otherRange.keepValueMarginsX;
                    compareAndReplace(self.minX, otherRange.minX, function(value) {
                        self.minX = value
                    }, otherLessThan);
                    compareAndReplace(self.intervalX, otherRange.intervalX, function(value) {
                        self.intervalX = value
                    }, otherLessThan);
                    compareAndReplace(self.maxX, otherRange.maxX, function(value) {
                        self.maxX = value
                    }, otherGreaterThan);
                    compareAndReplace(self.minVisibleX, otherRange.minVisibleX, function(value) {
                        self.minVisibleX = value
                    }, otherLessThan);
                    compareAndReplace(self.maxVisibleX, otherRange.maxVisibleX, function(value) {
                        self.maxVisibleX = value
                    }, otherGreaterThan);
                    setIndentByPriority('minValueMarginX');
                    setIndentByPriority('maxValueMarginX');
                    if (categoriesX === undefined)
                        self.categoriesX = otherCategoriesX;
                    else if (otherCategoriesX && otherCategoriesX.length)
                        for (i = 0; i < otherCategoriesX.length; i++)
                            if ($.inArray(otherCategoriesX[i], categoriesX) === -1)
                                categoriesX.push(otherCategoriesX[i]);
                    return this
                };
            var isDefined = function() {
                    return isDefinedX.call(this) || isDefinedY.call(this)
                };
            var isDefinedX = function() {
                    return isDefinedUtils(this.minX) && isDefinedUtils(this.maxX) || isDefinedUtils(this.categoriesX)
                };
            var isDefinedY = function() {
                    return isDefinedUtils(this.minY) && isDefinedUtils(this.maxY) || isDefinedUtils(this.categoriesY)
                };
            var setStubData = function(dataType) {
                    setStubDataX.call(this, dataType);
                    setStubDataY.call(this, dataType)
                };
            var setStubDataX = function(dataType) {
                    var year = (new Date).getYear() - 1;
                    var STUB_RANGE_MIN = dataType === 'datetime' ? new Date(year, 0, 1) : 0,
                        STUB_RANGE_MAX = dataType === 'datetime' ? new Date(year, 11, 31) : 10;
                    $.extend(this, {
                        minX: STUB_RANGE_MIN,
                        maxX: STUB_RANGE_MAX,
                        stubDataX: true
                    })
                };
            var setStubDataY = function(dataType) {
                    var year = (new Date).getYear() - 1;
                    var STUB_RANGE_MIN = dataType === 'datetime' ? new Date(year, 0, 1) : 0,
                        STUB_RANGE_MAX = dataType === 'datetime' ? new Date(year, 11, 31) : 10;
                    $.extend(this, {
                        minY: STUB_RANGE_MIN,
                        maxY: STUB_RANGE_MAX,
                        stubDataY: true
                    })
                };
            var correctValueMarginsToZeroIfNeeded = function(self) {
                    var lengthX,
                        lengthY,
                        xDateTime = isDateUtils(self.maxX) || isDateUtils(self.minX),
                        yDateTime = isDateUtils(self.maxY) || isDateUtils(self.minY);
                    if (isDefinedUtils(self.maxX) && isDefinedUtils(self.minX))
                        lengthX = self.maxX - self.minX;
                    if (isDefinedUtils(self.maxY) && isDefinedUtils(self.minY))
                        lengthY = self.maxY - self.minY;
                    if (lengthY && !yDateTime && !self.keepValueMarginsY) {
                        if (self.minY <= 0 && self.maxY <= 0 && self.maxValueMarginY && self.maxValueMarginY > self.maxY / (self.minY - self.maxY)) {
                            self.maxValueMarginY = 0;
                            self.maxY = 0
                        }
                        if (self.minY >= 0 && self.maxY >= 0 && self.minValueMarginY && self.minValueMarginY > self.minY / (self.maxY - self.minY)) {
                            self.minValueMarginY = 0;
                            self.minY = 0
                        }
                    }
                    if (lengthX && !xDateTime && !self.keepValueMarginsX) {
                        if (self.minX <= 0 && self.maxX <= 0 && self.maxValueMarginX && self.maxValueMarginX > self.maxX / (self.minX - self.maxX)) {
                            self.maxValueMarginX = 0;
                            self.maxX = 0
                        }
                        if (self.minX >= 0 && self.maxX >= 0 && self.minValueMarginX && self.minValueMarginX > self.minX / (self.maxX - self.minX)) {
                            self.minValueMarginX = 0;
                            self.minX = 0
                        }
                    }
                };
            var applyValueMargins = function() {
                    var self = this,
                        lengthX,
                        lengthY,
                        lengthVisibleX,
                        lengthVisibleY,
                        xDateTime = isDateUtils(self.maxX) || isDateUtils(self.minX),
                        yDateTime = isDateUtils(self.maxY) || isDateUtils(self.minY);
                    correctValueMarginsToZeroIfNeeded(self);
                    if (isDefinedUtils(self.maxX) && isDefinedUtils(self.minX))
                        lengthX = self.maxX - self.minX;
                    if (isDefinedUtils(self.maxY) && isDefinedUtils(self.minY))
                        lengthY = self.maxY - self.minY;
                    if (!isDefinedUtils(self.minVisibleX) || self.minVisibleX < self.minX || self.minVisibleX > self.maxX)
                        self.minVisibleX = self.minX;
                    if (!isDefinedUtils(self.maxVisibleX) || self.maxVisibleX < self.minX || self.maxVisibleX > self.maxX)
                        self.maxVisibleX = self.maxX;
                    if (!isDefinedUtils(self.minVisibleY) || self.minVisibleY < self.minY || self.minVisibleY > self.maxY)
                        self.minVisibleY = self.minY;
                    if (!isDefinedUtils(self.maxVisibleY) || self.maxVisibleY < self.minY || self.maxVisibleY > self.maxY)
                        self.maxVisibleY = self.maxY;
                    lengthVisibleX = self.maxVisibleX - self.minVisibleX;
                    lengthVisibleY = self.maxVisibleY - self.minVisibleY;
                    if (isDefinedUtils(self.minX) && self.minValueMarginX)
                        if (xDateTime)
                            self.minX = new Date(self.minX.valueOf() - lengthX * self.minValueMarginX);
                        else
                            self.minX -= lengthX * self.minValueMarginX;
                    if (isDefinedUtils(self.minVisibleX) && self.minValueMarginX)
                        if (xDateTime)
                            self.minVisibleX = new Date(self.minVisibleX.valueOf() - lengthVisibleX * self.minValueMarginX);
                        else
                            self.minVisibleX -= lengthVisibleX * self.minValueMarginX;
                    if (isDefinedUtils(self.maxX) && self.maxValueMarginX)
                        if (xDateTime)
                            self.maxX = new Date(self.maxX.valueOf() + lengthX * self.maxValueMarginX);
                        else
                            self.maxX += lengthX * self.maxValueMarginX;
                    if (isDefinedUtils(self.maxVisibleX) && self.maxValueMarginX)
                        if (xDateTime)
                            self.maxVisibleX = new Date(self.maxVisibleX.valueOf() + lengthVisibleX * self.maxValueMarginX);
                        else
                            self.maxVisibleX += lengthVisibleX * self.maxValueMarginX;
                    if (isDefinedUtils(self.minY) && self.minValueMarginY)
                        if (yDateTime)
                            self.minY = new Date(self.minY.valueOf() - lengthY * self.minValueMarginY);
                        else
                            self.minY -= lengthY * self.minValueMarginY;
                    if (isDefinedUtils(self.minVisibleY) && self.minValueMarginY)
                        if (yDateTime)
                            self.minVisibleY = new Date(self.minVisibleY.valueOf() - lengthVisibleY * self.minValueMarginY);
                        else
                            self.minVisibleY -= lengthVisibleY * self.minValueMarginY;
                    if (isDefinedUtils(self.maxY) && self.maxValueMarginY)
                        if (yDateTime)
                            self.maxY = new Date(self.maxY.valueOf() + lengthY * self.maxValueMarginY);
                        else
                            self.maxY += lengthY * self.maxValueMarginY;
                    if (isDefinedUtils(self.maxVisibleY) && self.maxValueMarginY)
                        if (yDateTime)
                            self.maxVisibleY = new Date(self.maxVisibleY.valueOf() + lengthVisibleY * self.maxValueMarginY);
                        else
                            self.maxVisibleY += lengthVisibleY * self.maxValueMarginY;
                    self.applyEqualLimitsMargins()
                };
            var applyEqualLimitsMargins = function() {
                    var self = this,
                        xDateTime = isDateUtils(self.maxX) || isDateUtils(self.minX),
                        yDateTime = isDateUtils(self.maxY) || isDateUtils(self.minY);
                    if (isDefinedUtils(self.minX) && isDefinedUtils(self.maxX) && self.minX.valueOf() === self.maxX.valueOf())
                        if (xDateTime) {
                            self.minX = new Date(self.minX.valueOf() - DATETIME_EQUALITY_CORRECTION);
                            self.maxX = new Date(self.maxX.valueOf() + DATETIME_EQUALITY_CORRECTION)
                        }
                        else {
                            self.minX = self.minX - NUMBER_EQUALITY_CORRECTION;
                            self.maxX = self.maxX + NUMBER_EQUALITY_CORRECTION
                        }
                    if (isDefinedUtils(self.minVisibleX) && isDefinedUtils(self.maxVisibleX) && self.minVisibleX.valueOf() === self.maxVisibleX.valueOf())
                        if (xDateTime) {
                            self.minVisibleX = self.minVisibleX.valueOf() - DATETIME_EQUALITY_CORRECTION < self.minX.valueOf() ? self.minX : new Date(self.minVisibleX.valueOf() - DATETIME_EQUALITY_CORRECTION);
                            self.maxVisibleX = self.maxVisibleX.valueOf() + DATETIME_EQUALITY_CORRECTION > self.maxX.valueOf() ? self.maxX : new Date(self.maxVisibleX.valueOf() + DATETIME_EQUALITY_CORRECTION)
                        }
                        else {
                            self.minVisibleX = self.minVisibleX - NUMBER_EQUALITY_CORRECTION < self.minX ? self.minX : self.minVisibleX - NUMBER_EQUALITY_CORRECTION;
                            self.maxVisibleX = self.maxVisibleX + NUMBER_EQUALITY_CORRECTION > self.maxX ? self.maxX : self.maxVisibleX + NUMBER_EQUALITY_CORRECTION
                        }
                    if (isDefinedUtils(self.minY) && isDefinedUtils(self.maxY) && self.minY.valueOf() === self.maxY.valueOf())
                        if (yDateTime) {
                            self.minY = new Date(self.minY.valueOf() - DATETIME_EQUALITY_CORRECTION);
                            self.maxY = new Date(self.maxY.valueOf() + DATETIME_EQUALITY_CORRECTION)
                        }
                        else {
                            self.minY = self.minY === 0 ? self.minY : self.minY - NUMBER_EQUALITY_CORRECTION;
                            self.maxY = self.maxY + NUMBER_EQUALITY_CORRECTION
                        }
                    if (isDefinedUtils(self.minVisibleY) && isDefinedUtils(self.maxVisibleY) && self.minVisibleY.valueOf() === self.maxVisibleY.valueOf())
                        if (yDateTime) {
                            self.minVisibleY = self.minVisibleY.valueOf() - DATETIME_EQUALITY_CORRECTION < self.minY.valueOf() ? self.minY : new Date(self.minVisibleY.valueOf() - DATETIME_EQUALITY_CORRECTION);
                            self.maxVisibleY = self.maxVisibleY.valueOf() + DATETIME_EQUALITY_CORRECTION > self.maxY.valueOf() ? self.maxY : new Date(self.maxVisibleY.valueOf() + DATETIME_EQUALITY_CORRECTION)
                        }
                        else {
                            if (self.minVisibleY !== 0)
                                self.minVisibleY = self.minVisibleY - NUMBER_EQUALITY_CORRECTION < self.minY ? self.minY : self.minVisibleY - NUMBER_EQUALITY_CORRECTION;
                            self.maxVisibleY = self.maxVisibleY + NUMBER_EQUALITY_CORRECTION > self.maxY ? self.maxY : self.maxVisibleY + NUMBER_EQUALITY_CORRECTION
                        }
                };
            return {
                    ctor: ctor,
                    dispose: dispose,
                    getBoundRange: getBoundRange,
                    getBoundRangeX: getBoundRangeX,
                    getBoundRangeY: getBoundRangeY,
                    isDefined: isDefined,
                    isDefinedX: isDefinedX,
                    isDefinedY: isDefinedY,
                    setStubData: setStubData,
                    setStubDataX: setStubDataX,
                    setStubDataY: setStubDataY,
                    applyValueMargins: applyValueMargins,
                    applyEqualLimitsMargins: applyEqualLimitsMargins
                }
        }())
    })(jQuery, DevExpress);
    /*! Module viz, file legend.js */
    (function($, DX, undefined) {
        DX.viz.charts.Legend = DX.Class.inherit({
            ctor: function(userOptions, group, trackerGroup) {
                this.legendGroup = group;
                this.trackerGroup = trackerGroup;
                this._init(userOptions)
            },
            update: function(userOptions) {
                this._init(userOptions)
            },
            dispose: function() {
                var _this = this;
                $.each(_this.trackers || [], function(_, tracker) {
                    tracker.removeData()
                });
                _this.trackers = null;
                _this.labelFormatObject = null;
                _this.seriesGroups = null;
                _this.insideLegendGroup = null;
                _this.legendGroup = null;
                _this.trackerGroup = null;
                _this.renderer = null;
                _this.series = null;
                _this.options = null
            },
            _init: function(options) {
                var debug = DX.utils.debug;
                debug.assertParam(options.visible, 'Visibility was not passed');
                debug.assertParam(options.renderer, 'renderer was not passed');
                debug.assertParam(options.margin, 'margin was not passed');
                debug.assertParam(options.markerSize, 'markerSize was not passed');
                debug.assertParam(options.font.color, 'fontColor was not passed');
                debug.assertParam(options.font.family, 'fontFamily was not passed');
                debug.assertParam(options.font.size, 'fontSize was not passed');
                debug.assertParam(options.paddingLeftRight, 'paddingLeftRight was not passed');
                debug.assertParam(options.paddingTopBottom, 'paddingTopBottom was not passed');
                debug.assertParam(options.columnItemSpacing, 'columnItemSpacing was not passed');
                debug.assertParam(options.rowItemSpacing, 'rowItemSpacing was not passed');
                debug.assertParam(options.equalColumnWidth, 'equalColumnWidth was not passed');
                var i,
                    series = [];
                this.renderer = options.renderer;
                options.renderer = null;
                options.horizontalAlignment = (options.horizontalAlignment || '').toLowerCase();
                if (options.horizontalAlignment !== 'center' && options.horizontalAlignment !== 'right' && options.horizontalAlignment !== 'left')
                    options.horizontalAlignment = 'right';
                options.verticalAlignment = (options.verticalAlignment || '').toLowerCase();
                if (options.verticalAlignment !== 'top' && options.verticalAlignment !== 'bottom') {
                    if (options.horizontalAlignment === 'center')
                        options.verticalAlignment = 'bottom';
                    if (options.horizontalAlignment === 'right' || options.horizontalAlignment === 'left')
                        options.verticalAlignment = 'top'
                }
                options.layout = (options.layout || '').toLowerCase();
                if (options.layout !== 'horizontal' && options.layout !== 'vertical') {
                    if (options.horizontalAlignment === 'center')
                        options.layout = 'horizontal';
                    if (options.horizontalAlignment === 'right' || options.horizontalAlignment === 'left')
                        options.layout = 'vertical'
                }
                options.position = (options.position || '').toLowerCase();
                if (options.position !== 'outside' && options.position !== 'inside')
                    options.position = 'outside';
                options.hoverMode = (options.hoverMode || '').toLowerCase();
                options.customizeText = $.isFunction(options.customizeText) ? options.customizeText : function() {
                    return this.seriesName
                };
                this.series = $.map(options.series || [], function(series) {
                    if (series.options.showInLegend)
                        return series;
                    return null
                });
                options.series = null;
                this.options = options;
                this.__initialized = true
            },
            formatLabel: function(options) {
                return options.customizeText.call(this, this)
            },
            draw: function() {
                var self = this,
                    renderer = self.renderer,
                    options = self.options,
                    series = self.series || {},
                    x = 0,
                    y = 0,
                    seriesGroups = [],
                    i,
                    j,
                    label,
                    marker,
                    singleSeriesGroup,
                    markerSize = options.markerSize,
                    isHorizontal = options.layout === 'horizontal',
                    box,
                    labelBox,
                    cols = options.columnCount,
                    rows = options.rowCount,
                    horisontalTextPosition,
                    background,
                    equalColumnWidth = options.equalColumnWidth,
                    trackers = [],
                    labelText,
                    data,
                    legendBox,
                    autoEdit = false,
                    canvas = self.canvas,
                    backgroundSettings,
                    borderVisible = options.border.visible && options.border.width && options.border.color && options.border.color !== 'none';
                if (!(options.visible && series && series.length))
                    return;
                this.createClipRect();
                if (this.legendGroup) {
                    this.legendGroup.clear();
                    this.trackerGroup.clear();
                    this.legendGroup.move(0, 0);
                    this.trackerGroup.move(0, 0);
                    this.clipRect && this.legendGroup.applySettings({clipId: this.clipRect.id})
                }
                if (this.insideLegendGroup) {
                    this.insideLegendGroup.detach();
                    this.insideLegendGroup.remove();
                    this.insideLegendGroup = null
                }
                if (options.position === 'inside' || options.backgroundColor || borderVisible)
                    background = renderer.createRect(0, 0, 0, 0, 0, {
                        fill: options.backgroundColor || (options.position === 'inside' ? options.containerBackgroundColor : 'none'),
                        'class': 'dxc-border'
                    }).append(this.legendGroup);
                this.insideLegendGroup = renderer.createGroup().append(this.legendGroup);
                for (i = 0; i < series.length; i++) {
                    singleSeriesGroup = renderer.createGroup({'class': 'dxc-item'});
                    singleSeriesGroup.append(this.insideLegendGroup);
                    marker = renderer.createRect(x, y, markerSize, markerSize, 0, {
                        fill: series[i].styles.themeColor,
                        'class': series[i].className
                    }).append(singleSeriesGroup);
                    box = marker.getBBox();
                    if (!options.itemTextPosition)
                        horisontalTextPosition = !isHorizontal;
                    else
                        horisontalTextPosition = options.itemTextPosition === 'right';
                    self.labelFormatObject = {
                        seriesName: series[i].name,
                        seriesNumber: series[i].index,
                        seriesColor: series[i].styles.themeColor
                    };
                    labelText = self.formatLabel.call(self.labelFormatObject, options);
                    label = renderer.createText(labelText, horisontalTextPosition ? x + box.width + 7 : x, horisontalTextPosition ? y : y + box.height + 2, {
                        font: options.font,
                        align: !horisontalTextPosition ? 'center' : 'left'
                    }).append(singleSeriesGroup);
                    labelBox = label.getBBox();
                    if (horisontalTextPosition)
                        label.move(0, ~~(box.y + box.height / 2 - (labelBox.y + labelBox.height / 2)));
                    else
                        label.move(~~(box.x + box.width / 2 - (labelBox.x + labelBox.width / 2)), box.y + box.height + 2 - labelBox.y);
                    trackers.push(renderer.createRect(0, 0, 0, 0, 0, {
                        stroke: 'none',
                        fill: 'grey',
                        opacity: 0.0001,
                        inh: true
                    }));
                    seriesGroups.push(singleSeriesGroup)
                }
                if (cols && !rows)
                    rows = Math.ceil(series.length / cols);
                else if (!cols && rows)
                    cols = Math.ceil(series.length / rows);
                else if (cols && rows) {
                    if (isHorizontal && cols < Math.ceil(series.length / rows))
                        cols = Math.ceil(series.length / rows);
                    else if (!isHorizontal && rows < Math.ceil(series.length / cols))
                        rows = Math.ceil(series.length / cols)
                }
                else {
                    autoEdit = true;
                    if (isHorizontal) {
                        rows = 1;
                        cols = series.length
                    }
                    else {
                        cols = 1;
                        rows = series.length
                    }
                }
                data = self.getDataRowsColumns(seriesGroups, cols, rows);
                self.moveItems(data, seriesGroups, this.insideLegendGroup, horisontalTextPosition, trackers);
                if (autoEdit && rows === 1) {
                    legendBox = this.insideLegendGroup.getBBox();
                    while (legendBox.width > canvas.width - canvas.right - canvas.left && cols > 1) {
                        cols = Math.ceil(cols / 2);
                        rows = Math.ceil(series.length / cols);
                        data = self.getDataRowsColumns(seriesGroups, cols, rows);
                        self.moveItems(data, seriesGroups, this.insideLegendGroup, horisontalTextPosition, trackers);
                        legendBox = this.insideLegendGroup.getBBox()
                    }
                }
                else if (autoEdit && cols === 1) {
                    legendBox = this.insideLegendGroup.getBBox();
                    while (legendBox.height > canvas.height - canvas.top - canvas.bottom && rows > 1) {
                        rows = Math.ceil(rows / 2);
                        cols = Math.ceil(series.length / rows);
                        data = self.getDataRowsColumns(seriesGroups, cols, rows);
                        self.moveItems(data, seriesGroups, this.insideLegendGroup, horisontalTextPosition, trackers);
                        legendBox = this.insideLegendGroup.getBBox()
                    }
                }
                if (background) {
                    legendBox = this.legendGroup.getBBox();
                    backgroundSettings = {
                        x: Math.round(legendBox.x),
                        y: Math.round(legendBox.y),
                        width: Math.round(legendBox.width) + 2 * options.paddingLeftRight,
                        height: Math.round(legendBox.height) + 2 * options.paddingTopBottom
                    };
                    if (borderVisible) {
                        backgroundSettings.strokeWidth = options.border.width;
                        backgroundSettings.stroke = options.border.color;
                        backgroundSettings.strokeOpacity = options.border.opacity;
                        backgroundSettings.dashStyle = options.border.dashStyle;
                        backgroundSettings.rx = options.border.cornerRadius || 0;
                        backgroundSettings.ry = options.border.cornerRadius || 0
                    }
                    background.applySettings(backgroundSettings);
                    self.insideLegendGroup.move(options.paddingLeftRight, options.paddingTopBottom);
                    $.each(trackers, function(_, tracker) {
                        tracker.move(options.paddingLeftRight, options.paddingTopBottom)
                    })
                }
                self.seriesGroups = seriesGroups;
                self.trackers = trackers;
                self.drawTrackers()
            },
            drawTrackers: function() {
                var _this = this;
                $.each(_this.trackers || [], function(i, tracker) {
                    tracker.data({
                        series: _this.series[i],
                        mode: _this.options.hoverMode
                    });
                    tracker.append(_this.trackerGroup)
                })
            },
            getDataRowsColumns: function(seriesGroups, cols, rows) {
                var self = this,
                    i,
                    j,
                    options = self.options,
                    equalColumnWidth = options.equalColumnWidth,
                    series = self.series || {},
                    maxWidthPerColumn = [],
                    maxWidthColumn = 0,
                    maxHeightRow = 0,
                    group,
                    box;
                for (i = 0; i < cols; i++)
                    maxWidthPerColumn[i] = 0;
                for (i = 0; i < rows; i++)
                    for (j = 0; j < cols; j++) {
                        if (rows < cols)
                            group = seriesGroups[i * cols + j];
                        else
                            group = seriesGroups[i + j * rows];
                        if (!group)
                            break;
                        box = group.getBBox();
                        if (maxHeightRow < box.height)
                            maxHeightRow = box.height;
                        if (!equalColumnWidth) {
                            if (maxWidthPerColumn[j] < box.width)
                                maxWidthPerColumn[j] = box.width
                        }
                        else if (maxWidthColumn < box.width)
                            maxWidthColumn = box.width
                    }
                return {
                        rows: rows,
                        cols: cols,
                        maxWidthPerColumn: maxWidthPerColumn,
                        maxWidthColumn: maxWidthColumn,
                        maxHeightRow: maxHeightRow
                    }
            },
            moveItems: function(data, seriesGroups, insideLegendGroup, horisontalTextPosition, trackers) {
                var self = this,
                    i,
                    j,
                    rows,
                    cols,
                    number,
                    group,
                    box,
                    xShift = 0,
                    yShift = 0,
                    widthColumn,
                    options = self.options,
                    xPadding = options.columnItemSpacing,
                    yPadding = options.rowItemSpacing,
                    equalColumnWidth = options.equalColumnWidth,
                    renderer = self.renderer,
                    maxWidthPerColumn = [],
                    maxWidthColumn = 0,
                    maxHeightRow = 0;
                rows = data.rows;
                cols = data.cols;
                maxHeightRow = data.maxHeightRow;
                maxWidthColumn = data.maxWidthColumn;
                maxWidthPerColumn = data.maxWidthPerColumn;
                for (i = 0; i < rows; i++) {
                    for (j = 0; j < cols; j++) {
                        if (rows < cols)
                            number = i * cols + j;
                        else
                            number = i + j * rows;
                        group = seriesGroups[number];
                        if (!group)
                            break;
                        box = group.getBBox();
                        widthColumn = !equalColumnWidth ? maxWidthPerColumn[j] : maxWidthColumn;
                        if (horisontalTextPosition) {
                            group.move(xShift - box.x, yShift);
                            trackers[number].applySettings({
                                x: xShift - xPadding / 2,
                                y: yShift + box.y - yPadding / 2,
                                height: maxHeightRow + yPadding,
                                width: widthColumn + xPadding
                            })
                        }
                        else {
                            group.move(xShift - box.x - box.width / 2 + widthColumn / 2, yShift);
                            trackers[number].applySettings({
                                x: xShift - xPadding / 2,
                                y: yShift + box.y - yPadding / 2,
                                height: maxHeightRow + yPadding,
                                width: widthColumn + xPadding
                            })
                        }
                        xShift = xShift + widthColumn + xPadding
                    }
                    yShift = yShift + maxHeightRow + yPadding;
                    xShift = 0
                }
            },
            getBoundingRect: function() {
                if (this.legendGroup)
                    return this.legendGroup.getBBox();
                return {}
            },
            toForeground: function() {
                this.legendGroup && this.legendGroup.toForeground()
            },
            createClipRect: function() {
                var canvas = this.canvas;
                if (canvas)
                    if (!this.clipRect)
                        this.clipRect = this.renderer.createClipRect(canvas.left, canvas.top, canvas.width - canvas.left - canvas.right, canvas.height - canvas.top - canvas.bottom).append();
                    else
                        this.clipRect.updateRectangle({
                            x: canvas.left,
                            y: canvas.top,
                            width: canvas.width - canvas.left - canvas.right,
                            height: canvas.height - canvas.top - canvas.bottom
                        })
            },
            updateClip: function(settings) {
                this.clipRect && this.clipRect.updateRectangle({
                    translateX: -settings.translateX,
                    translateY: -settings.translateY
                });
                this.legendGroup.update()
            },
            shift: function(x, y) {
                var settings = {};
                x && (settings.translateX = x);
                y && (settings.translateY = y);
                this.legendGroup.applySettings(settings);
                this.trackerGroup.applySettings(settings);
                this.updateClip(settings)
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file tooltip.js */
    (function($, DX, undefined) {
        var formatHelper = DX.formatHelper;
        DX.viz.charts.Tooltip = DX.Class.inherit({
            ctor: function(options, group) {
                this.style = {visibility: 'hidden'};
                this.textStyle = {
                    align: 'center',
                    visibility: 'hidden'
                };
                this.tooltipGroup = group;
                this._reinit(options)
            },
            dispose: function() {
                this.shadow = null;
                this.cloud = null;
                this.text = null;
                this.tooltipGroup = null;
                this.options = null;
                this.style = null;
                this.textStyle = null;
                this.renderer = null
            },
            update: function(options) {
                this._reinit(options)
            },
            _reinit: function(options) {
                options = options || {};
                this.renderer = options.renderer || this.renderer;
                this.customColor = options.color || this.customColor;
                this.textStyle.font = options.font || this.textStyle.font;
                this.canvasWidth = options.canvasWidth || this.canvasWidth;
                this.canvasHeight = options.canvasHeight || this.canvasHeight;
                delete options.renderer;
                delete options.font;
                this.options = $.extend(true, {}, this.options || {}, options)
            },
            formatValueTooltip: function(options) {
                return formatHelper.format(this.value, options.format, options.precision)
            },
            formatTooltip: function(options) {
                this.argumentText = formatHelper.format(this.argument, options.argumentFormat, options.argumentPrecision);
                if (this.percent !== undefined)
                    this.percentText = formatHelper.format(this.percent, 'percent', options.percentPrecision);
                return options.customizeText ? options.customizeText.call(this, this) : this.valueText
            },
            _getData: function() {
                var SHADOW_OFFSET = 4,
                    x = this.x,
                    y = this.y,
                    xt = x,
                    yt = y,
                    i,
                    align = 'center',
                    pointsOfShadow = [],
                    points = [],
                    bbox = this.text.getBBox(),
                    paddingLeftRight = this.options.paddingLeftRight,
                    paddingTopBottom = this.options.paddingTopBottom,
                    arrowLength = this.options.arrowLength > 0 ? this.options.arrowLength : 0,
                    cloudWidth = bbox.width + paddingLeftRight * 2,
                    cloudHeight = bbox.height + paddingTopBottom * 2,
                    updatedText;
                updatedText = this._checkWidthText(cloudWidth, cloudHeight);
                if (updatedText) {
                    bbox = updatedText.bbox;
                    cloudWidth = updatedText.cloudWidth;
                    cloudHeight = updatedText.cloudHeight;
                    paddingLeftRight = updatedText.paddingLeftRight;
                    paddingTopBottom = updatedText.paddingTopBottom
                }
                if (cloudWidth / 2 > x) {
                    points = this._setArrowLeft(cloudWidth, cloudHeight, bbox, arrowLength, x, y);
                    align = 'left';
                    xt += paddingLeftRight
                }
                else if (x + cloudWidth / 2 > this.canvasWidth) {
                    points = this._setArrowRight(cloudWidth, cloudHeight, bbox, arrowLength, x, y);
                    align = 'right';
                    xt -= paddingLeftRight
                }
                else
                    points = this._setArrowCenter(cloudWidth, cloudHeight, bbox, arrowLength, x, y);
                if (cloudHeight + arrowLength < y)
                    yt -= arrowLength + cloudHeight / 2 - bbox.height / 2 + this.tooltipOffset;
                else
                    yt += arrowLength + cloudHeight / 2 + bbox.height / 2 + this.tooltipOffset;
                $.extend(pointsOfShadow, points);
                for (i = 1; i < pointsOfShadow.length; i += 2)
                    if (cloudHeight + arrowLength < y)
                        pointsOfShadow[i] += SHADOW_OFFSET;
                    else
                        pointsOfShadow[i] -= SHADOW_OFFSET;
                if (arrowLength > 0) {
                    if (cloudHeight + arrowLength < y)
                        pointsOfShadow[1] += 2;
                    else
                        pointsOfShadow[1] -= 2;
                    if (cloudWidth / 2 > x)
                        pointsOfShadow[2] += 2;
                    else if (x + cloudWidth / 2 > this.canvasWidth)
                        pointsOfShadow[pointsOfShadow.length - 2] -= 2;
                    else {
                        pointsOfShadow[2] += 2;
                        pointsOfShadow[pointsOfShadow.length - 2] -= 2
                    }
                }
                return {
                        points: points,
                        text: {
                            x: xt,
                            y: yt,
                            align: align
                        },
                        pointsOfShadow: pointsOfShadow
                    }
            },
            _updateTooltip: function() {
                var box,
                    data,
                    scale;
                this.text.updateText(this.tooltipText);
                data = this._getData();
                this.shadow.applySettings({points: data.pointsOfShadow});
                this.cloud.applySettings({
                    points: data.points,
                    fill: this.style.fill,
                    'class': this.className
                });
                this.text.applySettings({y: data.text.y});
                box = this.text.getBBox();
                this.text.applySettings({
                    x: data.text.x,
                    y: data.text.y - (box.y + box.height - data.text.y),
                    align: data.text.align
                });
                box = this.tooltipGroup.getBBox();
                if (box.y + box.height > this.canvasHeight) {
                    scale = (this.canvasHeight - box.y) / box.height;
                    this.tooltipGroup.applySettings({
                        scale: scale,
                        translateX: this.x * (1 - scale),
                        translateY: this.y * (1 - scale)
                    })
                }
            },
            draw: function() {
                if (!this.shadow) {
                    this.shadow = this.renderer.createPath({}, {
                        fill: '#000000',
                        stroke: 'none',
                        visibility: 'hidden',
                        opacity: 0.1
                    });
                    this.cloud = this.renderer.createArea({}, this.style);
                    this.text = this.renderer.createText('0', 0, 0, this.textStyle)
                }
                this.shadow.append(this.tooltipGroup);
                this.cloud.append(this.tooltipGroup);
                this.text.append(this.tooltipGroup)
            },
            show: function() {
                this.cloud.applySettings({visibility: "visible"});
                this.text.applySettings({visibility: "visible"});
                this.shadow.applySettings({visibility: "visible"})
            },
            hide: function() {
                this.cloud.applySettings({visibility: 'hidden'});
                this.text.applySettings({visibility: 'hidden'});
                this.shadow.applySettings({visibility: "hidden"})
            },
            move: function(x, y, offset, text, color, className) {
                this.x = x;
                this.y = y;
                this.tooltipOffset = offset;
                this.tooltipText = text;
                this.style.fill = this.customColor || color;
                this.className = className;
                this._updateTooltip()
            },
            _setArrowCenter: function(cloudWidth, cloudHeight, bbox, arrowLength, x, y) {
                var verticalInvert = false,
                    points = [],
                    xc = x,
                    yc = y,
                    arrowWidth = 20;
                if (cloudHeight + arrowLength < y)
                    yc -= this.tooltipOffset;
                else {
                    yc += this.tooltipOffset;
                    verticalInvert = true
                }
                points = [xc, yc];
                if (!verticalInvert)
                    yc -= arrowLength;
                else
                    yc += arrowLength;
                xc += arrowWidth / 2;
                points.push(xc, yc);
                xc += cloudWidth / 2 - arrowWidth / 2;
                points.push(xc, yc);
                if (verticalInvert)
                    yc += cloudHeight;
                else
                    yc -= cloudHeight;
                points.push(xc, yc);
                xc -= cloudWidth;
                points.push(xc, yc);
                if (verticalInvert)
                    yc -= cloudHeight;
                else
                    yc += cloudHeight;
                points.push(xc, yc);
                xc += cloudWidth / 2 - arrowWidth / 2;
                points.push(xc, yc);
                return points
            },
            _setArrowLeft: function(cloudWidth, cloudHeight, bbox, arrowLength, x, y) {
                var verticalInvert = false,
                    points = [],
                    xc = x,
                    yc = y,
                    arrowWidth = 20;
                if (cloudHeight + arrowLength < y)
                    yc -= this.tooltipOffset;
                else {
                    yc += this.tooltipOffset;
                    verticalInvert = true
                }
                points = [xc, yc];
                if (!verticalInvert)
                    yc -= arrowLength;
                else
                    yc += arrowLength;
                xc += arrowWidth;
                points.push(xc, yc);
                xc += cloudWidth - arrowWidth;
                points.push(xc, yc);
                if (verticalInvert)
                    yc += cloudHeight;
                else
                    yc -= cloudHeight;
                points.push(xc, yc);
                xc -= cloudWidth;
                points.push(xc, yc);
                if (verticalInvert)
                    yc -= cloudHeight + arrowLength;
                else
                    yc += cloudHeight + arrowLength;
                points.push(xc, yc);
                return points
            },
            _setArrowRight: function(cloudWidth, cloudHeight, bbox, arrowLength, x, y) {
                var verticalInvert = false,
                    points = [],
                    xc = x,
                    yc = y,
                    arrowWidth = 20;
                if (cloudHeight + arrowLength < y)
                    yc -= this.tooltipOffset;
                else {
                    yc += this.tooltipOffset;
                    verticalInvert = true
                }
                points = [xc, yc];
                if (!verticalInvert)
                    yc -= arrowLength + cloudHeight;
                else
                    yc += arrowLength + cloudHeight;
                points.push(xc, yc);
                xc -= cloudWidth;
                points.push(xc, yc);
                if (verticalInvert)
                    yc -= cloudHeight;
                else
                    yc += cloudHeight;
                points.push(xc, yc);
                xc += cloudWidth - arrowWidth;
                points.push(xc, yc);
                if (verticalInvert)
                    yc -= arrowLength;
                else
                    yc += arrowLength;
                xc += arrowWidth;
                points.push(xc, yc);
                return points
            },
            _checkWidthText: function(cloudWidth, cloudHeight) {
                var x = this.x,
                    y = this.y,
                    text = this.tooltipText,
                    index,
                    paddingLeftRight = this.options.paddingLeftRight,
                    paddingTopBottom = this.options.paddingTopBottom,
                    textLength,
                    maxTooltipWidth,
                    remainLength,
                    newIndex,
                    bbox = this.text.getBBox();
                if (cloudWidth < x || x + cloudWidth < this.canvasWidth || cloudWidth / 2 < x && x + cloudWidth / 2 < this.canvasWidth)
                    return false;
                if (text.indexOf("<br/>") === -1 && text.indexOf(" ") !== -1) {
                    maxTooltipWidth = Math.max(x, this.canvasWidth - x, 2 * Math.min(x, this.canvasWidth - x));
                    textLength = text.length * maxTooltipWidth / bbox.width;
                    index = text.substr(0, ~~textLength).lastIndexOf(" ");
                    if (index === -1)
                        index = text.substr(0).indexOf(" ");
                    remainLength = text.substr(index + 1).length;
                    this.tooltipText = text.substr(0, index) + "<br/>";
                    while (textLength <= remainLength) {
                        newIndex = text.substr(index + 1, ~~textLength).lastIndexOf(" ");
                        if (newIndex === -1)
                            newIndex = text.substr(index + 1).indexOf(" ");
                        if (newIndex !== -1) {
                            this.tooltipText += text.substr(index + 1, newIndex) + "<br/>";
                            remainLength = text.substr(index + 1 + newIndex).length;
                            index += newIndex + 1
                        }
                        else
                            break
                    }
                    this.tooltipText += text.substr(index + 1);
                    this.text.updateText(this.tooltipText);
                    bbox = this.text.getBBox();
                    cloudWidth = bbox.width + paddingLeftRight * 2;
                    cloudHeight = bbox.height + paddingTopBottom * 2
                }
                if (cloudWidth > x && x + cloudWidth > this.canvasWidth && (cloudWidth / 2 > x || x + cloudWidth / 2 > this.canvasWidth)) {
                    paddingLeftRight = 5;
                    paddingTopBottom = 5;
                    cloudWidth = bbox.width + 2 * paddingLeftRight;
                    cloudHeight = bbox.height + 2 * paddingTopBottom
                }
                return {
                        bbox: bbox,
                        cloudWidth: cloudWidth,
                        cloudHeight: cloudHeight,
                        paddingTopBottom: paddingTopBottom,
                        paddingLeftRight: paddingLeftRight
                    }
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file chartTitle.js */
    (function($, DX, undefined) {
        var isDefined = DX.utils.isDefined,
            endsWith = function(value, pattern) {
                return value.substr(value.length - pattern.length) === pattern
            },
            startsWith = function(value, pattern) {
                return value.indexOf(pattern) === 0
            };
        DX.viz.charts.ChartTitle = DX.Class.inherit({
            ctor: function(renderer, canvas, options, group) {
                var _this = this;
                _this._init(canvas, options);
                _this.renderer = renderer;
                _this.clipRect = _this.createClipRect();
                _this.titleGroup = group;
                _this.titleGroup && _this.clipRect && _this.titleGroup.applySettings({clipId: _this.clipRect.id})
            },
            dispose: function() {
                var _this = this;
                _this.renderer = null;
                _this.clipRect = null;
                _this.title = null;
                _this.innerTitleGroup = null;
                _this.titleGroup = null;
                _this.options = null;
                _this.canvas = null
            },
            update: function(canvas, options) {
                this._init(canvas, options)
            },
            _init: function(canvas, options) {
                var _this = this;
                if (options) {
                    _this._parseAlignments(options);
                    _this.horizontalAlignment = options.horizontalAlignment;
                    _this.verticalAlignment = options.verticalAlignment;
                    _this.options = options
                }
                _this.canvas = canvas || _this.canvas
            },
            _parseAlignments: function(options) {
                if (isDefined(options.position) && !(isDefined(options.verticalAlignment) && isDefined(options.horizontalAlignment))) {
                    options.position = options.position.toLowerCase();
                    options.verticalAlignment = endsWith(options.position, 'top') ? 'top' : 'bottom';
                    options.horizontalAlignment = startsWith(options.position, 'left') ? 'left' : startsWith(options.position, 'center') && 'center' || 'right';
                    return
                }
                options.verticalAlignment = (options.verticalAlignment || '').toLowerCase();
                options.horizontalAlignment = (options.horizontalAlignment || '').toLowerCase();
                if (options.verticalAlignment !== 'top' && options.verticalAlignment !== 'bottom')
                    options.verticalAlignment = 'top';
                if (options.horizontalAlignment !== 'left' && options.horizontalAlignment !== 'center' && options.horizontalAlignment !== 'right')
                    options.horizontalAlignment = 'center'
            },
            render: function() {
                var _this = this,
                    titleOptions = _this.options,
                    renderer = _this.renderer,
                    attr;
                if (!titleOptions.text)
                    return;
                if (!_this.innerTitleGroup)
                    _this.innerTitleGroup = renderer.createGroup();
                else
                    _this.innerTitleGroup.clear();
                _this.innerTitleGroup.append(_this.titleGroup);
                attr = {
                    font: titleOptions.font,
                    align: _this.horizontalAlignment,
                    style: titleOptions.fontStyle
                };
                _this.title = renderer.createText(titleOptions.text, _this.canvas.left, _this.canvas.top, attr).append(_this.innerTitleGroup);
                _this.title.text = titleOptions.text;
                _this.correctTitleLength()
            },
            correctTitleLength: function() {
                var _this = this,
                    canvas = _this.canvas,
                    text = _this.title.text,
                    updateText,
                    lineLength,
                    canvasWidth = canvas.width - canvas.right - canvas.left,
                    box = _this.getBoundingRect();
                if (canvasWidth > box.width || text.indexOf("<br/>") != -1)
                    return;
                lineLength = text.length * canvasWidth / box.width;
                updateText = text.substr(0, ~~lineLength - 1 - 3) + "...";
                _this.title.updateText(updateText);
                _this.title.text = updateText
            },
            getBoundingRect: function() {
                var options = this.options,
                    box;
                if (!this.innerTitleGroup)
                    return {
                            width: 0,
                            height: 0,
                            x: 0,
                            y: 0
                        };
                box = this.innerTitleGroup.getBBox();
                if (isDefined(options.placeholderSize))
                    box.height = options.placeholderSize;
                return box
            },
            shift: function(x, y) {
                this.innerTitleGroup.move(x, y)
            },
            createClipRect: function() {
                if (isDefined(this.options.placeholderSize))
                    return this.renderer.createClipRect(0, 0, 0, 0)
            },
            setClipRectSettings: function() {
                var canvas = this.canvas,
                    verticalAlignment = this.verticalAlignment,
                    clipRect = this.clipRect;
                if (clipRect) {
                    clipRect.append();
                    if (verticalAlignment === 'top')
                        clipRect.updateRectangle({
                            x: 0,
                            y: 0,
                            width: canvas.width,
                            height: canvas.top
                        });
                    else if (verticalAlignment === 'bottom')
                        clipRect.updateRectangle({
                            x: 0,
                            y: canvas.height - canvas.bottom,
                            width: canvas.width,
                            height: canvas.bottom
                        })
                }
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file axis.js */
    (function($, DX, undefined) {
        var utils = DX.utils,
            mathAbs = Math.abs,
            AXIS_VALUE_MARGIN_PRIORITY = 100,
            DEFAULT_AXIS_LABEL_SPACING = 5,
            AXIS_STAGGER_OVERLAPPING_KOEF = 2,
            MAX_GRID_BORDER_ADHENSION = 4,
            CANVAS_POSITION_PREFIX = 'canvas_position_',
            CANVAS_POSITION_BOTTOM = 'canvas_position_bottom',
            CANVAS_POSITION_TOP = 'canvas_position_top',
            CANVAS_POSITION_LEFT = 'canvas_position_left',
            CANVAS_POSITION_RIGHT = 'canvas_position_right';
        DX.viz.charts.AXIS_STAGGER_OVERLAPPING_KOEF = AXIS_STAGGER_OVERLAPPING_KOEF;
        DX.viz.charts.Axis = DX.Class.inherit(function() {
            var ctor = function(renderer, options) {
                    var debug = DX.utils.debug;
                    debug.assertParam(renderer, 'renderer was not passed');
                    debug.assertParam(options.label, 'label was not passed');
                    debug.assertParam(options.tick, 'tick was not passed');
                    debug.assertParam(options.grid, 'grid was not passed');
                    debug.assertParam(options.title, 'title was not passed');
                    debug.assert(options.axisDivisionFactor, 'axisDivisionFactor was not passed');
                    debug.assert(options.stripStyle, 'stripStyle was not passed');
                    debug.assert(options.position, 'position was not passed');
                    debug.assertParam(options.isHorizontal, 'isHorizontal was not passed');
                    this.renderer = renderer;
                    this.init(options);
                    this._$axis = $(this)
                };
            var dispose = function() {
                    var _this = this;
                    _this._axisElementsGroup && _this._axisElementsGroup.dispose();
                    $.each(_this.labels || [], function(_, label) {
                        label.removeData()
                    });
                    _this._$axis = null;
                    _this.labels = null;
                    _this.title = null;
                    _this.stripLabels = null;
                    _this.stripRects = null;
                    _this._axisStripGroup = null;
                    _this._axisLineGroup = null;
                    _this._axisElementsGroup = null;
                    _this._axisGridGroup = null;
                    _this._axisGroup = null;
                    _this.axesContainerGroup = null;
                    _this.stripsGroup = null;
                    _this.renderer = null;
                    _this.translator = null;
                    _this.options = null;
                    _this.textOptions = null;
                    _this._tickValues = null;
                    _this._fullTickValues = null;
                    _this._fullTickPositions = null
                };
            var init = function(options) {
                    var categories = options.categories,
                        labelOptions = options.label;
                    options.hoverMode = options.hoverMode ? options.hoverMode.toLowerCase() : 'none';
                    this.hasLabelFormat = labelOptions.format !== '' && utils.isDefined(labelOptions.format);
                    this.options = options;
                    this.staggered = labelOptions.staggered;
                    labelOptions.minSpacing = utils.isDefined(labelOptions.minSpacing) ? labelOptions.minSpacing : DEFAULT_AXIS_LABEL_SPACING;
                    this._testStaggeringSpacing = labelOptions.staggeringSpacing;
                    processCustomOptions(options);
                    if (categories) {
                        this.labelsNumber = categories.length;
                        this.ticksNumber = this.labelsNumber
                    }
                    options.range = {
                        min: options.min,
                        max: options.max,
                        categories: options.categories && options.categories.slice(0)
                    };
                    this.pane = options.pane;
                    this.textOptions = {
                        align: labelOptions.alignment,
                        font: labelOptions.font,
                        opacity: labelOptions.opacity,
                        style: labelOptions.style
                    }
                };
            var updateTranslatorInterval = function(self) {
                    var i,
                        tickValues,
                        options = self.options,
                        businessRange = self.translator.getBusinessRange(),
                        interval;
                    if (businessRange && businessRange.getBoundRange && !options.categories) {
                        tickValues = self.getTickValues();
                        for (i = 0; i < tickValues.length - 1; i++) {
                            interval = mathAbs(tickValues[i] - tickValues[i + 1]);
                            if (options.isHorizontal)
                                businessRange.getBoundRange({intervalX: interval});
                            else
                                businessRange.getBoundRange({intervalY: interval})
                        }
                    }
                };
            var updateRotationAngle = function(self) {
                    var options = self.options,
                        rotationAngle,
                        labelOptions = options.label;
                    if (!options.isHorizontal || !labelOptions || !utils.isDefined(labelOptions.overlappingBehavior))
                        return;
                    switch (labelOptions.overlappingBehavior.mode) {
                        case'enlargeTickInterval':
                        case'stagger':
                            rotationAngle = null;
                            break;
                        case'rotate':
                            rotationAngle = labelOptions.overlappingBehavior.rotationAngle;
                            break;
                        default:
                            rotationAngle = labelOptions.rotationAngle
                    }
                    if (!labelOptions.userAlignment)
                        self.textOptions.align = rotationAngle ? 'left' : 'center';
                    self.textOptions.rotate = rotationAngle
                };
            var getStaggeringSpacing = function(self) {
                    var self = this,
                        labelOptions = self.options.label;
                    if (labelOptions) {
                        if (!self.staggered && self.isStaggerOverlapping)
                            return labelOptions.overlappingBehavior.staggeringSpacing;
                        return labelOptions.staggeringSpacing
                    }
                    return 0
                };
            var setTranslator = function(translator) {
                    var debug = DX.utils.debug;
                    debug.assertParam(translator, 'translator was not passed');
                    this.translator = translator;
                    this.needsLabelAdjustment = false;
                    this.resetTicks();
                    updateTranslatorInterval(this)
                };
            var resetTicks = function() {
                    this._tickValues = this._tickPositions = this._fullTickValues = this._fullTickPositions = null
                };
            var setRange = function(range) {
                    var debug = DX.utils.debug;
                    debug.assertParam(range, 'range was not passed');
                    var self = this,
                        options = self.options;
                    if (options.isHorizontal) {
                        options.min = range.minVisibleX;
                        options.max = range.maxVisibleX;
                        options.categories = range.categoriesX;
                        options.stubData = range.stubDataX
                    }
                    else {
                        options.min = range.minVisibleY;
                        options.max = range.maxVisibleY;
                        options.categories = range.categoriesY;
                        options.stubData = range.stubDataY
                    }
                    self.needsLabelAdjustment = false;
                    this.resetTicks()
                };
            var processCustomOptions = function(options) {
                    var label = options.label,
                        left = 'left',
                        right = 'right',
                        top = 'top',
                        bottom = 'bottom';
                    if (options.isHorizontal) {
                        if (!(options.position === bottom || options.position === top))
                            options.position = bottom
                    }
                    else if (!(options.position === left || options.position === right))
                        options.position = left;
                    if (options.position === right) {
                        label.indentFromAxis *= -1;
                        if (!label.userAlignment)
                            label.alignment = left
                    }
                    if (options.position === top)
                        label.indentFromAxis *= -1;
                    if (label.rotationAngle && options.isHorizontal)
                        if (!label.userAlignment)
                            label.alignment = left
                };
            var getXAxisPosition = function(self) {
                    var delta = 0;
                    if (self.delta)
                        delta = self.delta[self.options.position] || 0;
                    return self.translator.translateX(CANVAS_POSITION_PREFIX + self.options.position) + delta
                };
            var getYAxisPosition = function(self) {
                    var delta = 0;
                    if (self.delta)
                        delta = self.delta[self.options.position] || 0;
                    return self.translator.translateY(CANVAS_POSITION_PREFIX + self.options.position) + delta
                };
            var drawAxis = function drawAxis(self, group) {
                    var translator = self.translator,
                        options = self.options,
                        lineOptions = options,
                        axisAttr = {
                            strokeWidth: lineOptions.width,
                            stroke: lineOptions.color,
                            strokeOpacity: lineOptions.opacity
                        },
                        axis,
                        axisPosition = self.axisPosition,
                        start,
                        end;
                    if (!lineOptions.visible)
                        return;
                    if (self.options.isHorizontal) {
                        if (options.categories) {
                            start = translator.translateX(CANVAS_POSITION_LEFT);
                            end = translator.translateX(CANVAS_POSITION_RIGHT)
                        }
                        else {
                            start = translator.translateX(options.min);
                            end = translator.translateX(options.max)
                        }
                        axis = self.renderer.createLine(start, axisPosition, end, axisPosition, axisAttr)
                    }
                    else {
                        if (options.categories) {
                            start = translator.translateY(CANVAS_POSITION_TOP);
                            end = translator.translateY(CANVAS_POSITION_BOTTOM)
                        }
                        else {
                            start = translator.translateY(options.min);
                            end = translator.translateY(options.max)
                        }
                        axis = self.renderer.createLine(axisPosition, start, axisPosition, end, axisAttr)
                    }
                    axis.append(group)
                };
            var getTickValues = function() {
                    var self = this,
                        options = self.options,
                        tickProvider = options.tickProvider,
                        translator = self.translator,
                        labelOptions = options.label,
                        categories = options.categories,
                        step,
                        ticksOptions,
                        overlappingBehavior = labelOptions.overlappingBehavior,
                        getPosition = options.isHorizontal ? self.translator.translateX : self.translator.translateY,
                        correctedScreenDelta;
                    ticksOptions = getTicksOptions(self, options, getPosition, categories);
                    if (!self._tickValues) {
                        self.textOptions.rotate = labelOptions.rotationAngle;
                        self.textOptions.align = labelOptions.alignment;
                        self._fullTickValues = self._tickValues = $.isArray(categories) ? categories : tickProvider.getTicks(ticksOptions);
                        this._needProcessOverlapping = true
                    }
                    if (self.options.stubData) {
                        self._testSkippedFormattingAndOverlapping = true;
                        return self._tickValues
                    }
                    if ((utils.isDate(options.min) || utils.isDate(categories && categories[0])) && !this.hasLabelFormat)
                        labelOptions.format = DX.formatHelper.getDateFormatByTicks(self._tickValues);
                    correctedScreenDelta = self._tickValues && self._tickValues.length ? getPosition.call(self.translator, self._tickValues[self._tickValues.length - 1]) - getPosition.call(self.translator, self._tickValues[0]) : null;
                    if (correctedScreenDelta) {
                        ticksOptions.screenDelta = mathAbs(correctedScreenDelta);
                        ticksOptions.ticksCount = self._tickValues.length - 1
                    }
                    else
                        ticksOptions.ticksCount = self._tickValues.length;
                    if (this._needProcessOverlapping && overlappingBehavior && overlappingBehavior.mode !== 'ignore') {
                        if (overlappingBehavior.mode === 'stagger')
                            ticksOptions.screenDelta *= AXIS_STAGGER_OVERLAPPING_KOEF;
                        step = tickProvider.getAutoArrangementStep(self._tickValues, ticksOptions);
                        self._testTKScreenDelta = ticksOptions.screenDelta;
                        self._testIsAutoArrangement = Boolean(step - 1);
                        self._autoArrangementStep = step;
                        if (step > 1) {
                            self.staggered = false;
                            updateRotationAngle(self);
                            step = tickProvider.getAutoArrangementStep(self._tickValues, ticksOptions);
                            self._tickValues = step > 1 ? tickProvider.getAutoArrangementTicks(self._tickValues, ticksOptions, step) : self._tickValues
                        }
                        else {
                            self.staggered = labelOptions.staggered;
                            self.staggeringSpacing = labelOptions.staggeringSpacing
                        }
                        this._needProcessOverlapping = false;
                        tickProvider._removeInvalidDatesWithUnitBegining(self._tickValues, ticksOptions)
                    }
                    if (!$.isArray(categories))
                        self._fullTickValues = self._tickValues;
                    return self._tickValues
                };
            var setTickValues = function(tickValues) {
                    this.resetTicks();
                    this._fullTickValues = this._tickValues = tickValues;
                    if (tickValues)
                        this._needProcessOverlapping = true
                };
            var getTicksOptions = function(self, options, getPosition, categories) {
                    var bpRange = options.isHorizontal ? [CANVAS_POSITION_LEFT, CANVAS_POSITION_RIGHT] : [CANVAS_POSITION_BOTTOM, CANVAS_POSITION_TOP],
                        screenDelta = mathAbs(getPosition.call(self.translator, bpRange[1]) - getPosition.call(self.translator, bpRange[0])),
                        digitPosition = utils.getSignificantDigitPosition(mathAbs(options.max - options.min) / screenDelta),
                        correctingValue,
                        min = options.min,
                        max = options.max;
                    if (utils.isNumber(min)) {
                        min = utils.roundValue(options.min, digitPosition);
                        if (min < options.min) {
                            correctingValue = Math.pow(10, -digitPosition);
                            min = utils.applyPrecisionByMinDelta(min, correctingValue, min + correctingValue)
                        }
                        if (min > max)
                            min = options.min
                    }
                    if (categories && categories.length > 0) {
                        min = categories[0];
                        max = categories[categories.length - 1]
                    }
                    return {
                            min: min,
                            max: max,
                            textOptions: self.textOptions,
                            getText: function(value) {
                                return formatLabel(value, options.label)
                            },
                            renderer: self.renderer,
                            textSpacing: self.options.label.minSpacing,
                            translator: self.translator,
                            tickInterval: self.options.stubData ? null : options.tickInterval,
                            screenDelta: screenDelta,
                            gridSpacingFactor: options.axisDivisionFactor,
                            isHorizontal: options.isHorizontal,
                            setTicksAtUnitBeginning: options.setTicksAtUnitBeginning,
                            incidentOccured: options.incidentOccured
                        }
                };
            var prepareLabelsToDraw = function prepareLabelsToDraw(self) {
                    var options = self.options,
                        ticksValues,
                        ticks = [],
                        getPosition,
                        i;
                    if (options.isHorizontal)
                        getPosition = self.translator.translateX;
                    else
                        getPosition = self.translator.translateY;
                    ticksValues = self.getTickValues();
                    if (ticksValues.hideLabels || options.stubData)
                        ticks.hideLabels = true;
                    for (i = 0; i < ticksValues.length; i++)
                        ticks.push({
                            text: ticksValues[i],
                            pos: getPosition.call(self.translator, ticksValues[i])
                        });
                    return ticks
                };
            var correctTicksPosition = function(self, ticks) {
                    var options = self.options,
                        translator = self.translator,
                        tickDelta,
                        i;
                    if (options.categories && (options.discreteAxisDivisionMode !== 'crossLabels' || !options.discreteAxisDivisionMode)) {
                        if (options.isHorizontal) {
                            tickDelta = translator.getIntervalX() / 2;
                            if (!options.valueMarginsEnabled)
                                ticks = ticks.slice(0, ticks.length - 1)
                        }
                        else {
                            tickDelta = -translator.getIntervalY() / 2;
                            if (!options.valueMarginsEnabled)
                                ticks = ticks.slice(1, ticks.length)
                        }
                        for (i = 0; i < ticks.length; i++)
                            ticks[i].pos = ticks[i].pos + tickDelta
                    }
                    return ticks
                };
            var prepareFullTicksToDraw = function prepareFullTicksToDraw(self) {
                    var options = self.options,
                        ticksValues = self._fullTickValues,
                        ticks = [],
                        getPosition = options.isHorizontal ? self.translator.translateX : self.translator.translateY,
                        i;
                    if (!self._fullTickPositions) {
                        if (!ticksValues) {
                            self.getTickValues();
                            ticksValues = self._fullTickValues || []
                        }
                        for (i = 0; i < ticksValues.length; i++)
                            ticks.push({pos: getPosition.call(self.translator, ticksValues[i])});
                        self._fullTickPositions = correctTicksPosition(self, ticks)
                    }
                    return self._fullTickPositions
                };
            var drawTicks = function drawTicks(self, group) {
                    var renderer = self.renderer,
                        options = self.options,
                        ticksOptions = options.tick,
                        categories = options.categories,
                        tickDelta = options.discreteAxisDivisionMode === 'crossLabels' ? 0 : 0.5,
                        i,
                        defaultTickLength = 8,
                        attr = {
                            strokeWidth: 1,
                            stroke: ticksOptions.color,
                            strokeOpacity: ticksOptions.opacity
                        },
                        currentTickConstant,
                        axisPosition = self.axisPosition,
                        tickPositionStart,
                        tickPositionEnd,
                        tick,
                        ticksToDraw;
                    if (!ticksOptions.visible)
                        return;
                    ticksToDraw = prepareFullTicksToDraw(self);
                    if (self.options.isHorizontal)
                        for (i = 0; i < ticksToDraw.length; i++) {
                            tick = ticksToDraw[i];
                            renderer.createLine(tick.pos, axisPosition - defaultTickLength / 2, tick.pos, axisPosition + defaultTickLength / 2, attr).append(group)
                        }
                    else
                        for (i = 0; i < ticksToDraw.length; i++) {
                            tick = ticksToDraw[i];
                            renderer.createLine(axisPosition - defaultTickLength / 2, tick.pos, axisPosition + defaultTickLength / 2, tick.pos, attr).append(group)
                        }
                };
            var formatLabel = function formatLabel(value, options) {
                    var formatObject = {
                            value: value,
                            valueText: DX.formatHelper.format(value, options.format, options.precision) || ''
                        };
                    return options.customizeText ? options.customizeText.call(formatObject, formatObject) : formatObject.valueText
                };
            var setPercentLabelFormat = function() {
                    var labelOptions = this.options.label;
                    if (!labelOptions.format)
                        labelOptions.format = 'percent'
                };
            var createTextForVerticalLabels = function(text, y, x, textOptions) {
                    return this.createText(text, x, y, textOptions)
                };
            var drawLabels = function drawLabels(self, group) {
                    var i,
                        options = self.options,
                        categories = options.categories,
                        renderer = self.renderer,
                        axisPosition = self.axisPosition,
                        labelOptions = options.label,
                        labelOffset = labelOptions.indentFromAxis,
                        labelsToDraw,
                        labelPoint,
                        label,
                        labels = [],
                        createText = options.isHorizontal ? renderer.createText : createTextForVerticalLabels,
                        currentLabelConst = options.isHorizontal ? axisPosition + labelOffset : axisPosition - labelOffset,
                        text;
                    if (!labelOptions.visible)
                        return;
                    labelsToDraw = prepareLabelsToDraw(self);
                    if (labelsToDraw.length === 0 || labelsToDraw.hideLabels)
                        return true;
                    for (i = 0; i < labelsToDraw.length; i++) {
                        labelPoint = labelsToDraw[i];
                        text = formatLabel(labelPoint.text, labelOptions);
                        if (utils.isDefined(text) && text !== '') {
                            label = createText.call(renderer, text, labelPoint.pos, currentLabelConst, self.textOptions);
                            labels.push(label);
                            label.append(group);
                            label.data({argument: labelPoint.text})
                        }
                    }
                    self.labels = labels
                };
            var getMultipleAxesSpacing = function() {
                    return this.options.multipleAxesSpacing || 0
                };
            var drawTitle = function drawTitle(self, group) {
                    var i,
                        options = self.options,
                        renderer = self.renderer,
                        axisPosition = self.axisPosition,
                        titleOptions = options.title,
                        margin = titleOptions.margin,
                        title,
                        attr = {
                            font: titleOptions.font,
                            opacity: titleOptions.opacity,
                            align: 'center',
                            'class': 'dx-chart-axis-title'
                        };
                    if (!titleOptions.text)
                        return;
                    if (self.options.isHorizontal)
                        if (self.options.position === 'bottom')
                            title = renderer.createText(titleOptions.text, self.translator.canvas.left + self.translator.width / 2, axisPosition, attr);
                        else
                            title = renderer.createText(titleOptions.text, self.translator.canvas.left + self.translator.width / 2, axisPosition, attr);
                    else if (self.options.position === 'left') {
                        attr.rotate = 270;
                        title = renderer.createText(titleOptions.text, axisPosition, self.translator.canvas.top + self.translator.height / 2, attr)
                    }
                    else {
                        attr.rotate = 90;
                        title = renderer.createText(titleOptions.text, axisPosition, self.translator.canvas.top + self.translator.height / 2, attr)
                    }
                    title.append(group);
                    self.title = title
                };
            var drawGrid = function drawGrid(self, group, borderOptions) {
                    var renderer = self.renderer,
                        options = self.options,
                        gridOptions = options.grid,
                        categories = options.categories,
                        translator = self.translator,
                        tickDelta = options.discreteAxisDivisionMode === 'crossLabels' ? 0 : 0.5,
                        positionsToDraw,
                        i,
                        attr = {
                            strokeWidth: gridOptions.width,
                            stroke: gridOptions.color,
                            strokeOpacity: gridOptions.opacity
                        },
                        currentTickConstant,
                        axisPosition = self.axisPosition,
                        positionFrom,
                        positionTo,
                        tick,
                        firstBorderLinePosition,
                        lastBorderLinePosition,
                        borderOptions = borderOptions || {visible: false};
                    if (!gridOptions.visible)
                        return;
                    positionsToDraw = prepareFullTicksToDraw(self);
                    if (self.options.isHorizontal) {
                        positionFrom = translator.translateY(CANVAS_POSITION_BOTTOM);
                        positionTo = translator.translateY(CANVAS_POSITION_TOP);
                        firstBorderLinePosition = borderOptions.visible && borderOptions.left ? translator.translateX(CANVAS_POSITION_LEFT) : undefined;
                        lastBorderLinePosition = borderOptions.visible && borderOptions.right ? translator.translateX(CANVAS_POSITION_RIGHT) : undefined;
                        for (i = 0; i < positionsToDraw.length; i++) {
                            tick = positionsToDraw[i];
                            if (mathAbs(tick.pos - firstBorderLinePosition) < MAX_GRID_BORDER_ADHENSION || mathAbs(tick.pos - lastBorderLinePosition) < MAX_GRID_BORDER_ADHENSION)
                                continue;
                            renderer.createLine(tick.pos, positionFrom, tick.pos, positionTo, attr).append(group)
                        }
                    }
                    else {
                        positionFrom = translator.translateX(CANVAS_POSITION_LEFT);
                        positionTo = translator.translateX(CANVAS_POSITION_RIGHT);
                        firstBorderLinePosition = borderOptions.visible && borderOptions.top ? translator.translateY(CANVAS_POSITION_TOP) : undefined;
                        lastBorderLinePosition = borderOptions.visible && borderOptions.bottom ? translator.translateY(CANVAS_POSITION_BOTTOM) : undefined;
                        for (i = 0; i < positionsToDraw.length; i++) {
                            tick = positionsToDraw[i];
                            if (mathAbs(tick.pos - firstBorderLinePosition) < MAX_GRID_BORDER_ADHENSION || mathAbs(tick.pos - lastBorderLinePosition) < MAX_GRID_BORDER_ADHENSION)
                                continue;
                            renderer.createLine(positionFrom, tick.pos, positionTo, tick.pos, attr).append(group)
                        }
                    }
                };
            var drawStrip = function drawStrip(self, group) {
                    var renderer = self.renderer,
                        options = self.options,
                        stripData = options.strips,
                        translator = self.translator,
                        i,
                        stripLabels = [],
                        stripRects = [],
                        rect,
                        stripOptions,
                        positionFrom,
                        positionTo,
                        stripPos;
                    if (options.stubData)
                        return;
                    var getPos = function(startV, endV, isHorizontal, range) {
                            var isContinous = isHorizontal ? !!(range.minVisibleX || range.maxVisibleX) : !!(range.minVisibleY || range.maxVisibleY),
                                cateories = (isHorizontal ? range.categoriesX : range.categoriesY) || [],
                                translate = isHorizontal ? function(val) {
                                    return translator.translateX(val)
                                } : function(val) {
                                    return translator.translateY(val)
                                },
                                invert = isHorizontal ? !!range.invertX : range.invertY,
                                defaultPos = isHorizontal ? [CANVAS_POSITION_LEFT, CANVAS_POSITION_RIGHT] : [CANVAS_POSITION_BOTTOM, CANVAS_POSITION_TOP],
                                pos,
                                start = translate(startV),
                                end = translate(endV),
                                min = isHorizontal ? range.minVisibleX : range.maxVisibleY,
                                max = isHorizontal ? range.maxVisibleX : range.maxVisibleY;
                            invert && defaultPos.reverse();
                            if (!isContinous && ($.inArray(startV, cateories) === -1 || $.inArray(endV, cateories) === -1))
                                return {
                                        stripFrom: 0,
                                        stripTo: 0
                                    };
                            if (!utils.isDefined(start) && isContinous)
                                start = startV < min ? translate(defaultPos[0]) : translate(defaultPos[1]);
                            if (!utils.isDefined(end) && isContinous)
                                end = endV < min ? translate(defaultPos[0]) : translate(defaultPos[1]);
                            return start < end ? {
                                    stripFrom: start,
                                    stripTo: end
                                } : {
                                    stripFrom: end,
                                    stripTo: start
                                }
                        };
                    if (self.options.isHorizontal) {
                        positionFrom = translator.translateY(CANVAS_POSITION_BOTTOM);
                        positionTo = translator.translateY(CANVAS_POSITION_TOP);
                        for (i = 0; i < stripData.length; i++) {
                            stripOptions = stripData[i];
                            if (stripOptions.startValue !== undefined && stripOptions.endValue !== undefined && stripOptions.color !== undefined) {
                                stripPos = getPos(stripOptions.startValue, stripOptions.endValue, true, translator.businessRange);
                                if (stripPos.stripTo - stripPos.stripFrom === 0)
                                    continue;
                                rect = renderer.createRect(stripPos.stripFrom, positionTo, stripPos.stripTo - stripPos.stripFrom, positionFrom - positionTo, 0, {fill: stripOptions.color});
                                rect.append(group);
                                stripRects.push(rect);
                                if (stripOptions.label && stripOptions.label.text)
                                    stripLabels.push(drawStripLabel(self, stripOptions.label, stripPos.stripFrom, stripPos.stripTo, group));
                                else
                                    stripLabels.push(null)
                            }
                        }
                    }
                    else {
                        positionFrom = translator.translateX(CANVAS_POSITION_LEFT);
                        positionTo = translator.translateX(CANVAS_POSITION_RIGHT);
                        for (i = 0; i < stripData.length; i++) {
                            stripOptions = stripData[i];
                            if (stripOptions.startValue !== undefined && stripOptions.endValue !== undefined && stripOptions.color !== undefined) {
                                stripPos = getPos(stripOptions.startValue, stripOptions.endValue, false, translator.businessRange);
                                if (stripPos.stripTo - stripPos.stripFrom === 0)
                                    continue;
                                rect = renderer.createRect(positionFrom, stripPos.stripFrom, positionTo - positionFrom, stripPos.stripTo - stripPos.stripFrom, 0, {fill: stripOptions.color});
                                rect.append(group);
                                stripRects.push(rect);
                                if (stripOptions.label && stripOptions.label.text)
                                    stripLabels.push(drawStripLabel(self, stripOptions.label, stripPos.stripFrom, stripPos.stripTo, group));
                                else
                                    stripLabels.push(null)
                            }
                        }
                    }
                    self.stripLabels = stripLabels;
                    self.stripRects = stripRects
                };
            var drawStripLabel = function drawStripLabel(self, labelOptions, stripFrom, stripTo, group) {
                    var renderer = self.renderer,
                        text = labelOptions.text,
                        canvas = self.translator.canvas,
                        attr = {
                            align: self.options.isHorizontal ? 'center' : 'left',
                            font: labelOptions.font || self.options.label.font
                        },
                        label,
                        x,
                        y;
                    if (self.options.isHorizontal) {
                        if (labelOptions.horizontalAlignment === 'center') {
                            x = stripFrom + (stripTo - stripFrom) / 2;
                            attr.align = 'center'
                        }
                        else if (labelOptions.horizontalAlignment === 'left') {
                            x = stripFrom;
                            attr.align = 'left'
                        }
                        else if (labelOptions.horizontalAlignment === 'right') {
                            x = stripTo;
                            attr.align = 'right'
                        }
                        if (labelOptions.verticalAlignment === 'top')
                            y = canvas.top;
                        else if (labelOptions.verticalAlignment === 'center')
                            y = (canvas.height - canvas.top - canvas.bottom) / 2 + canvas.top;
                        else if (labelOptions.verticalAlignment === 'bottom')
                            y = canvas.height - canvas.bottom
                    }
                    else {
                        if (labelOptions.horizontalAlignment === 'center') {
                            x = (canvas.width - canvas.left - canvas.right) / 2 + canvas.left;
                            attr.align = 'center'
                        }
                        else if (labelOptions.horizontalAlignment === 'left') {
                            x = canvas.left;
                            attr.align = 'left'
                        }
                        else if (labelOptions.horizontalAlignment === 'right') {
                            x = canvas.width - canvas.right;
                            attr.align = 'right'
                        }
                        if (labelOptions.verticalAlignment === 'top')
                            y = stripFrom;
                        else if (labelOptions.verticalAlignment === 'center')
                            y = stripTo + (stripFrom - stripTo) / 2;
                        else if (labelOptions.verticalAlignment === 'bottom')
                            y = stripTo
                    }
                    label = renderer.createText(text, x, y, attr);
                    label.append(group);
                    return label
                };
            var initAxisPositions = function(self) {
                    if (self.options.isHorizontal)
                        self.axisPosition = getYAxisPosition(self);
                    else
                        self.axisPosition = getXAxisPosition(self)
                };
            var checkNeedsLabelAdjustment = function(self, labels) {
                    var i,
                        labelOptions = self.options.label,
                        boxLeft,
                        boxRight,
                        labelLeft,
                        labelRight,
                        needsLabelAdjustment = !!self.staggered;
                    labels = self.options.inverted ? labels.slice(0).reverse() : labels;
                    if (!self.options.isHorizontal)
                        needsLabelAdjustment = false;
                    else if (labelOptions.overlappingBehavior && labelOptions.overlappingBehavior.mode === 'stagger')
                        for (i = 1; i < labels.length; i++) {
                            labelLeft = labels[i - 1];
                            labelRight = labels[i];
                            boxLeft = labelLeft.getBBox();
                            boxRight = labelRight.getBBox();
                            if (boxRight.x < boxLeft.x + boxLeft.width + labelOptions.minSpacing) {
                                self.isStaggerOverlapping = true;
                                needsLabelAdjustment = true
                            }
                        }
                    self.needsLabelAdjustment = self.needsLabelAdjustment || needsLabelAdjustment;
                    return self.needsLabelAdjustment
                };
            var adjustLabels = function(self) {
                    var options = self.options,
                        labels = self.labels,
                        labelOptions = options.label,
                        label,
                        labelHeight,
                        isNeedLabelAdjustment,
                        staggeringSpacing,
                        i,
                        box;
                    if (!options.label.visible || !labels || !labels.length)
                        return;
                    for (i = 0; i < labels.length; i++) {
                        label = labels[i];
                        box = label.getBBox();
                        if (options.isHorizontal && options.position === 'bottom')
                            label.applySettings({y: 2 * label.settings.y - box.y});
                        else if (!options.isHorizontal && (options.position === 'left' || options.position === 'right'))
                            label.applySettings({y: label.settings.y + ~~(label.settings.y - box.y - box.height / 2)});
                        else if (options.isHorizontal && options.position === 'top')
                            label.applySettings({y: 2 * label.settings.y - box.y - box.height})
                    }
                    isNeedLabelAdjustment = checkNeedsLabelAdjustment(self, labels);
                    self._testIsNeedLabelAdjustment = isNeedLabelAdjustment;
                    if (isNeedLabelAdjustment) {
                        labelHeight = 0;
                        for (i = 0; i < labels.length; i = i + 2) {
                            label = labels[i];
                            box = label.getBBox();
                            if (box.height > labelHeight)
                                labelHeight = box.height
                        }
                        staggeringSpacing = self.getStaggeringSpacing(self);
                        self._testStaggeringSpacing = staggeringSpacing;
                        labelHeight = Math.round(labelHeight) + staggeringSpacing;
                        for (i = 1; i < labels.length; i = i + 2) {
                            label = labels[i];
                            if (options.position === 'bottom')
                                label.move(0, labelHeight);
                            else if (options.position === 'top')
                                label.move(0, -labelHeight)
                        }
                        for (i = 0; i < labels.length; i++)
                            labels[i].rotate(0)
                    }
                };
            var adjustStripLabels = function(self) {
                    var options = self.options,
                        labelOptions,
                        labels = self.stripLabels,
                        rects = self.stripRects,
                        rect,
                        label,
                        i,
                        box,
                        rectBox,
                        stripOptions,
                        x,
                        y;
                    if (labels === undefined && rects === undefined)
                        return;
                    for (i = 0; i < labels.length; i++) {
                        x = y = 0;
                        stripOptions = options.strips[i];
                        labelOptions = stripOptions.label;
                        label = labels[i];
                        if (label !== null) {
                            rect = rects[i];
                            box = label.getBBox();
                            rectBox = rect.getBBox();
                            if (labelOptions.horizontalAlignment === 'left')
                                x += stripOptions.paddingLeftRight;
                            else if (labelOptions.horizontalAlignment === 'right')
                                x -= stripOptions.paddingLeftRight;
                            if (labelOptions.verticalAlignment === 'top')
                                y += rectBox.y - box.y + stripOptions.paddingTopBottom;
                            else if (labelOptions.verticalAlignment === 'center')
                                y += rectBox.y + rectBox.height / 2 - box.y - box.height / 2;
                            else if (labelOptions.verticalAlignment === 'bottom')
                                y -= stripOptions.paddingTopBottom;
                            label.move(x, y)
                        }
                    }
                };
            var adjustTitle = function(self, group) {
                    var options = self.options,
                        axisPosition = self.axisPosition,
                        boxGroup,
                        boxTitle,
                        title = self.title;
                    if (!title)
                        return;
                    boxTitle = title.getBBox();
                    boxGroup = group.getBBox();
                    if (self.options.isHorizontal)
                        if (self.options.position === 'bottom')
                            title.move(0, boxGroup.y + boxGroup.height - boxTitle.y + options.title.margin);
                        else
                            title.move(0, boxGroup.y - boxTitle.y - boxTitle.height - options.title.margin);
                    else if (self.options.position === 'left')
                        title.move(boxGroup.x - boxTitle.x - boxTitle.width - options.title.margin, 0);
                    else
                        title.move(boxGroup.x + boxGroup.width - boxTitle.x + options.title.margin, 0)
                };
            var draw = function(externalOptions) {
                    var _this = this,
                        cssClass = _this.options.isHorizontal ? 'dxc-h-axis' : 'dxc-v-axis',
                        stripClass = _this.options.isHorizontal ? 'dxc-h-strips' : 'dxc-v-strips',
                        axisClipRectID = _this.clipRectID && _this.options.placeholderSize ? _this.clipRectID : undefined;
                    externalOptions = externalOptions || {};
                    var debug = DX.utils.debug;
                    debug.assertParam(this.translator, 'translator was not set before Draw call');
                    if (_this._axisGroup) {
                        _this._axisGroup.detach();
                        _this._axisStripGroup.detach();
                        _this._axisGridGroup.clear();
                        _this._axisElementsGroup.clear();
                        _this._axisLineGroup.clear();
                        _this._axisStripGroup.clear()
                    }
                    else {
                        _this._axisGroup = _this.renderer.createGroup({
                            'class': cssClass,
                            clipId: axisClipRectID
                        });
                        _this._axisStripGroup = _this.renderer.createGroup({'class': stripClass});
                        _this._axisGridGroup = _this.renderer.createGroup({'class': 'dxc-grid'}).append(_this._axisGroup);
                        _this._axisElementsGroup = _this.renderer.createGroup({'class': 'dxc-elements'}).append(_this._axisGroup);
                        _this._axisLineGroup = _this.renderer.createGroup({'class': 'dxc-line'}).append(_this._axisGroup)
                    }
                    initAxisPositions(_this);
                    if (!_this._virtual) {
                        drawAxis(_this, _this._axisLineGroup);
                        drawTicks(_this, _this._axisLineGroup);
                        drawLabels(_this, _this._axisElementsGroup);
                        if (_this.options.title.text)
                            drawTitle(_this, _this._axisElementsGroup)
                    }
                    if (_this.options.strips)
                        drawStrip(_this, _this._axisStripGroup);
                    drawGrid(_this, _this._axisGridGroup, externalOptions.borderOptions);
                    _this._axisStripGroup.append(_this.stripsGroup);
                    _this._axisGroup.append(_this.axesContainerGroup);
                    adjustLabels(_this);
                    adjustStripLabels(_this);
                    adjustTitle(_this, _this._axisElementsGroup)
                };
            var getBoundingRect = function() {
                    var box = this._axisElementsGroup.getBBox(),
                        lineBox = this._axisLineGroup.getBBox(),
                        placeholderSize = this.options.placeholderSize,
                        start,
                        isHorizontal = this.options.isHorizontal,
                        coord = isHorizontal && 'y' || 'x',
                        side = isHorizontal && 'height' || 'width',
                        positionCondition = this.options.position === (isHorizontal && 'bottom' || 'right');
                    if (!(box.x || box.y || box.width || box.height))
                        return box;
                    start = lineBox[coord] || this.axisPosition;
                    if (positionCondition) {
                        box[side] = placeholderSize || box[side] - (start - box[coord]);
                        box[coord] = start
                    }
                    else
                        box[side] = placeholderSize || lineBox[side] + start - box[coord];
                    return box
                };
            var shift = function(x, y) {
                    var settings = {};
                    if (x)
                        settings.translateX = x;
                    if (y)
                        settings.translateY = y;
                    this._axisGroup.applySettings(settings)
                };
            var applyClipRectForStrips = function(clipId) {
                    this._axisStripGroup.applySettings({clipId: clipId})
                };
            var getRangeData = function() {
                    var options = this.options,
                        range = {};
                    var addValueMarginToRange = function(prefix, dim) {
                            if (options['valueMarginsEnabled']) {
                                if (utils.isDefined(options[prefix])) {
                                    range[prefix + dim] = options[prefix];
                                    range[prefix + dim + 'Priority'] = AXIS_VALUE_MARGIN_PRIORITY
                                }
                            }
                            else {
                                range[prefix + dim] = 0;
                                range[prefix + dim + 'Priority'] = AXIS_VALUE_MARGIN_PRIORITY
                            }
                        };
                    if (options.isHorizontal) {
                        range.minX = options.range.min;
                        range.maxX = options.range.max;
                        range.minVisibleX = options.range.min;
                        range.maxVisibleX = options.range.max;
                        addValueMarginToRange('minValueMargin', 'X');
                        addValueMarginToRange('maxValueMargin', 'X');
                        range.invertX = options.inverted;
                        range.stickX = !options.valueMarginsEnabled;
                        range.categoriesX = options.range.categories
                    }
                    else {
                        range.minY = options.range.min;
                        range.maxY = options.range.max;
                        range.minVisibleY = options.range.min;
                        range.maxVisibleY = options.range.max;
                        range.invertY = options.inverted || options.type === 'discrete' && options.oppositeDirectionYAxis;
                        range.stickY = !options.valueMarginsEnabled;
                        addValueMarginToRange('minValueMargin', 'Y');
                        addValueMarginToRange('maxValueMargin', 'Y');
                        range.categoriesY = options.range.categories
                    }
                    return range
                };
            var on = function(events, data, handler) {
                    this._$axis && this._$axis.on(events, data, handler);
                    return this
                };
            var off = function(events) {
                    this._$axis && this._$axis.off(events);
                    return this
                };
            var prototypeObject = {
                    ctor: ctor,
                    dispose: dispose,
                    init: init,
                    resetTicks: resetTicks,
                    getStaggeringSpacing: getStaggeringSpacing,
                    setTranslator: setTranslator,
                    getTickValues: getTickValues,
                    setTickValues: setTickValues,
                    getRangeData: getRangeData,
                    getMultipleAxesSpacing: getMultipleAxesSpacing,
                    setRange: setRange,
                    setPercentLabelFormat: setPercentLabelFormat,
                    draw: draw,
                    getBoundingRect: getBoundingRect,
                    shift: shift,
                    on: on,
                    off: off,
                    applyClipRectForStrips: applyClipRectForStrips
                };
            prototypeObject.getTicksOptions = getTicksOptions;
            prototypeObject.drawAxis = drawAxis;
            prototypeObject.drawTicks = drawTicks;
            prototypeObject.drawGrid = drawGrid;
            prototypeObject.drawStrip = drawStrip;
            prototypeObject.drawLabels = drawLabels;
            prototypeObject.adjustLabels = adjustLabels;
            prototypeObject.adjustStripLabels = adjustStripLabels;
            prototypeObject.drawTitle = drawTitle;
            prototypeObject.adjustTitle = adjustTitle;
            prototypeObject.checkNeedsLabelAdjustment = checkNeedsLabelAdjustment;
            prototypeObject.initAxisPositions = initAxisPositions;
            return prototypeObject
        }())
    })(jQuery, DevExpress);
    /*! Module viz, file baseChart.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            charts = DX.viz.charts,
            utils = DX.utils,
            dataUtils = DX.data.utils,
            REDRAW_DELAY = 100,
            resizeRedrawOptions = {animate: false},
            ACTIONS_BY_PRIORITY = ['processAxesOption', 'reinit', '_reinitDataSource', '_handleDataSourceChanged', 'force_render'];
        charts.BaseChart = ui.Component.inherit({
            _defaultOptions: function() {
                return {
                        done: $.noop,
                        drawn: $.noop,
                        redrawOnResize: true,
                        incidentOccured: $.noop,
                        margin: {
                            left: 0,
                            top: 0,
                            right: 0,
                            bottom: 0
                        },
                        size: {
                            width: undefined,
                            height: undefined
                        },
                        title: {text: null},
                        legend: {hoverMode: 'includePoints'},
                        animation: {
                            enabled: true,
                            duration: 1000,
                            easing: 'easeOutCubic',
                            maxPointCountSupported: 300,
                            asyncSeriesRendering: true,
                            asyncTrackersRendering: true,
                            trackerRenderingDelay: 1200
                        },
                        seriesSelectionMode: 'single',
                        pointSelectionMode: 'single',
                        seriesClick: $.noop,
                        pointClick: $.noop,
                        argumentAxisClick: $.noop,
                        seriesHover: $.noop,
                        pointHover: $.noop,
                        seriesSelected: $.noop,
                        pointSelected: $.noop
                    }
            },
            _init: function() {
                var _this = this;
                _this._saveUserCanvas();
                _this._initRenderer();
                _this._createHtmlStructure();
                _this._needHandleRenderComplete = true;
                _this.layoutManager = charts.factory.createChartLayoutManager();
                _this._reinit()
            },
            _reinit: function() {
                var _this = this;
                _this.layoutManager.update(_this);
                if (_this.option('redrawOnResize') && window) {
                    if (!_this._resizeHandlerCallback) {
                        _this._resizeHandlerCallback = _this._resizeHandler();
                        utils.windowResizeCallbacks.add(_this._resizeHandlerCallback)
                    }
                }
                else {
                    utils.windowResizeCallbacks.remove(_this._resizeHandlerCallback);
                    delete _this._resizeHandlerCallback
                }
                if (!$.isFunction(_this.option('incidentOccured'))) {
                    utils.debug.assert(false, 'Function should be passed as "incidentOccured" callback');
                    _this.option('incidentOccured', $.noop)
                }
                if (_this.option('incidentOccured') === $.noop)
                    _this.option('incidentOccured', utils.logger.warn);
                _this._createTracker();
                _this._reinitDataSource()
            },
            _createHtmlStructure: function() {
                var _this = this,
                    renderer = _this.renderer;
                _this._panesBackgroundGroup = renderer.createGroup({'class': 'dxc-background'});
                _this._titleGroup = renderer.createGroup({'class': 'dxc-title'});
                _this._legendGroup = renderer.createGroup({'class': 'dxc-legend'});
                _this._stripsGroup = renderer.createGroup({'class': 'dxc-strips-group'});
                _this._axesGroup = renderer.createGroup({'class': 'dxc-axes-group'});
                _this._panesBorderGroup = renderer.createGroup({'class': 'dxc-border'});
                _this._seriesGroup = renderer.createGroup({'class': 'dxc-series-group'});
                _this._labelsGroup = renderer.createGroup({'class': 'dxc-labels-group'});
                _this._tooltipGroup = renderer.createGroup({'class': 'dxc-tooltip'});
                _this._trackerGroup = renderer.createGroup({
                    'class': 'dxc-trackers',
                    opacity: 0.0001
                });
                _this._seriesTrackerGroup = renderer.createGroup({'class': 'dxc-series-trackers'}).append(_this._trackerGroup);
                _this._markerTrackerGroup = renderer.createGroup({
                    'class': 'dxc-markers-trackers',
                    stroke: 'none',
                    fill: 'grey'
                }).append(_this._trackerGroup);
                _this._legendTrackerGroup = renderer.createGroup({
                    'class': 'dxc-legend-trackers',
                    stroke: 'none',
                    fill: 'grey'
                }).append(_this._trackerGroup)
            },
            _cleanHtmlStructure: function() {
                var _this = this;
                _this._legendGroup.detach();
                _this._stripsGroup.detach();
                _this._axesGroup.detach();
                _this._seriesGroup.detach();
                _this._labelsGroup.detach();
                _this._trackerGroup.detach();
                _this._panesBackgroundGroup.clear();
                _this._titleGroup.clear();
                _this._legendGroup.clear();
                _this._stripsGroup.clear();
                _this._axesGroup.clear();
                _this._panesBorderGroup.clear();
                _this._seriesGroup.clear();
                _this._labelsGroup.clear();
                _this._tooltipGroup.clear();
                _this._seriesTrackerGroup.clear();
                _this._markerTrackerGroup.clear();
                _this._legendTrackerGroup.clear()
            },
            _disposeObjectsInArray: function(propName) {
                $.each(this[propName] || [], function(_, item) {
                    item && item.dispose()
                });
                this[propName] = null
            },
            _dispose: function() {
                var _this = this,
                    disposeObject = function(propName) {
                        _this[propName] && _this[propName].dispose(),
                        _this[propName] = null
                    },
                    disposeObjectsInArray = this._disposeObjectsInArray;
                clearTimeout(_this.delayedRedraw);
                if (_this._resizeHandlerCallback) {
                    _this._resizeHandlerCallback.stop();
                    utils.windowResizeCallbacks.remove(_this._resizeHandlerCallback);
                    _this._resizeHandlerCallback = null
                }
                _this.callBase();
                disposeObjectsInArray.call(_this, "businessRanges");
                disposeObjectsInArray.call(_this, "translators");
                disposeObjectsInArray.call(_this, "series");
                disposeObject("layoutManager");
                disposeObject("themeManager");
                disposeObject("renderer");
                disposeObject("tracker");
                disposeObject("tooltip");
                disposeObject("chartTitle");
                _this.paneAxis = null;
                _this._userOptions = null;
                _this.dirtyCanvas = null;
                _this.canvas = null;
                _this._legendGroup.detach();
                _this._stripsGroup.detach();
                _this._axesGroup.detach();
                _this._seriesGroup.detach();
                _this._labelsGroup.detach();
                _this._trackerGroup.detach();
                disposeObject("canvasClipRect");
                disposeObject("_panesBackgroundGroup");
                disposeObject("_titleGroup");
                disposeObject("_legendGroup");
                disposeObject("_stripsGroup");
                disposeObject("_axesGroup");
                disposeObject("_panesBorderGroup");
                disposeObject("_seriesGroup");
                disposeObject("_labelsGroup");
                disposeObject("_tooltipGroup");
                disposeObject("_seriesTrackerGroup");
                disposeObject("_markerTrackerGroup");
                disposeObject("_legendTrackerGroup");
                disposeObject("_trackerGroup")
            },
            _clean: function _clean() {
                var _this = this;
                _this._stopAnimation();
                _this._cleanHtmlStructure();
                _this.callBase();
                _this._saveDirtyCanvas()
            },
            _initRenderer: function _initRenderer() {
                if (this.renderer)
                    return;
                var _this = this,
                    animationOptions = _this.option('animation');
                animationOptions = animationOptions === true ? _this._defaultOptions().animation : animationOptions;
                _this.renderer = charts.factory.createRenderer({
                    animation: animationOptions,
                    cssClass: 'dxc dxc-chart'
                })
            },
            _initSeries: function() {
                var _this = this;
                _this.series = _this.series || _this._populateSeries()
            },
            _reinitDataSource: function() {
                this._initDataSource();
                this._loadDataSource()
            },
            _initOptions: function(options) {
                var _this = this,
                    changedTitle;
                _this._optionsInitializing = true;
                changedTitle = _this._processTitleOption(options.title, _this.option('title'));
                if (changedTitle)
                    options.title = changedTitle;
                _this._userOptions = options;
                _this._processAxesOption(options);
                _this._createThemeManager(options);
                _this.option(_this.themeManager.applyChartTheme(options));
                delete _this._userOptions.userCommonAxisSettings
            },
            _processTitleOption: function(title, oldTitle) {
                if (utils.isString(title)) {
                    var text = title;
                    title = oldTitle;
                    title.text = text;
                    return title
                }
            },
            _processAxesOption: function(options) {
                var argumentAxesOptions = $.isArray(options.argumentAxis) ? options.argumentAxis : [options.argumentAxis],
                    valueAxesOptions = $.isArray(options.valueAxis) ? options.valueAxis : [options.valueAxis],
                    checkOptions = function(axesOptions) {
                        var axisOptions,
                            text,
                            i = 0;
                        for (i = 0; i < axesOptions.length; i++) {
                            axisOptions = axesOptions[i];
                            if (axisOptions && axisOptions.title)
                                if (utils.isString(axisOptions.title)) {
                                    text = axisOptions.title;
                                    axisOptions.title = {};
                                    axisOptions.title.text = text
                                }
                            if (axisOptions && axisOptions.label) {
                                if (axisOptions.label.alignment)
                                    axisOptions.label['userAlignment'] = true;
                                if (utils.isString(axisOptions.label.overlappingBehavior))
                                    axisOptions.label.overlappingBehavior = {mode: axisOptions.label.overlappingBehavior};
                                if (!axisOptions.label.overlappingBehavior || !axisOptions.label.overlappingBehavior.mode) {
                                    axisOptions.label.overlappingBehavior = axisOptions.label.overlappingBehavior || {};
                                    if (axisOptions.label.rotationAngle) {
                                        axisOptions.label.overlappingBehavior.mode = 'rotate';
                                        if (!axisOptions.label.overlappingBehavior.rotationAngle)
                                            axisOptions.label.overlappingBehavior.rotationAngle = axisOptions.label.rotationAngle
                                    }
                                    if (axisOptions.label.staggered) {
                                        axisOptions.label.overlappingBehavior.mode = 'stagger';
                                        if (!axisOptions.label.overlappingBehavior.staggeringSpacing)
                                            axisOptions.label.overlappingBehavior.staggeringSpacing = axisOptions.label.staggeringSpacing
                                    }
                                }
                            }
                        }
                    };
                options.userCommonAxisSettings = this._userOptions.commonAxisSettings;
                checkOptions([options.commonAxisSettings]);
                checkOptions(argumentAxesOptions);
                checkOptions(valueAxesOptions)
            },
            _saveUserCanvas: function() {
                var canvas = this.option('size');
                if (canvas.width !== undefined)
                    canvas.userWidth = canvas.width;
                if (canvas.height !== undefined)
                    canvas.userHeight = canvas.height
            },
            _saveDirtyCanvas: function() {
                this.dirtyCanvas = this._calculateCanvas()
            },
            _resizeHandler: function() {
                var _this = this;
                return utils.createResizeHandler(function() {
                        _this._render(resizeRedrawOptions)
                    })
            },
            _createThemeManager: function(options) {
                options = options || {};
                var _this = this;
                _this.themeManager && _this.themeManager.dispose();
                _this.themeManager = charts.factory.createThemeManager({
                    theme: options.theme,
                    palette: options.palette
                })
            },
            _calculateCanvas: function() {
                var _this = this,
                    canvas = _this.option('size'),
                    container = _this._element();
                if (!utils.isDefined(canvas.userWidth)) {
                    canvas.width = container.width();
                    if (!canvas.width)
                        canvas.width = 400
                }
                if (!utils.isDefined(canvas.userHeight)) {
                    canvas.height = container.height();
                    if (!canvas.height)
                        canvas.height = 400
                }
                return $.extend({}, canvas, _this.option('margin'))
            },
            _createTracker: function() {
                var _this = this,
                    rotated = _this.option('rotated'),
                    tooltipOptions = _this.option('tooltip') || {};
                if (_this.tracker)
                    _this.tracker.dispose();
                _this.tracker = charts.factory.createTracker({
                    series: _this.series,
                    valueAxis: rotated ? _this.horizontalAxes : _this.verticalAxes,
                    argumentAxis: rotated ? _this.verticalAxes : _this.horizontalAxes,
                    seriesSelectionMode: _this.option('seriesSelectionMode'),
                    pointSelectionMode: _this.option('pointSelectionMode'),
                    tooltipShown: _this.option('tooltipShown'),
                    tooltipHidden: _this.option('tooltipHidden'),
                    markerTrackerGroup: _this._markerTrackerGroup,
                    seriesTrackerGroup: _this._seriesTrackerGroup,
                    legendGroup: _this._legendTrackerGroup,
                    seriesGroup: _this._seriesGroup,
                    tooltipEnabled: tooltipOptions.enabled,
                    events: {
                        seriesClick: _this.option('seriesClick'),
                        pointClick: _this.option('pointClick'),
                        argumentAxisClick: _this.option('argumentAxisClick'),
                        seriesHover: _this.option('seriesHover'),
                        seriesSelected: _this.option('seriesSelected'),
                        pointHover: _this.option('pointHover'),
                        pointSelected: _this.option('pointSelected')
                    }
                })
            },
            _updateTracker: function() {
                var _this = this,
                    rotated = _this.option('rotated');
                if (!_this.tracker)
                    _this._createTracker();
                else
                    _this.tracker._reinit({
                        series: _this.series,
                        valueAxis: rotated ? _this.horizontalAxes : _this.verticalAxes,
                        argumentAxis: rotated ? _this.verticalAxes : _this.horizontalAxes
                    })
            },
            _render: function(drawOptions) {
                this._optionsInitializing = false;
                var _this = this,
                    renderer = _this.renderer,
                    translators = _this.translators,
                    updatedCanvas = _this.canvas,
                    container = this._element(),
                    currentDirtyCanvas = _this._calculateCanvas(),
                    oldDirtyCanvas = _this.dirtyCanvas;
                drawOptions = drawOptions || {recreateCanvas: true};
                drawOptions.recreateCanvas = drawOptions.recreateCanvas || !renderer.isInitialized();
                if (!drawOptions.force && oldDirtyCanvas && oldDirtyCanvas.width === currentDirtyCanvas.width && oldDirtyCanvas.height === currentDirtyCanvas.height && !_this.hiddenContainer) {
                    _this.stopRedraw = true;
                    return
                }
                clearTimeout(_this.delayedRedraw);
                if (drawOptions.recreateCanvas)
                    updatedCanvas = _this._calculateCanvas();
                if (updatedCanvas.width && updatedCanvas.height && container.is(':visible'))
                    _this.hiddenContainer = false;
                else {
                    _this.option('incidentOccured')('Chart can not be drawn as container is not visible');
                    _this.hiddenContainer = true;
                    _this.stopRedraw = true;
                    renderer.killContainer();
                    return
                }
                if (drawOptions.recreateCanvas) {
                    _this.canvas = updatedCanvas;
                    renderer.recreateCanvas(_this.canvas.width, _this.canvas.height);
                    renderer.draw(_this._element()[0]);
                    _this._createCanvasClipRect();
                    if (translators)
                        translators.length = 0
                }
                _this.layoutManager.update(_this);
                _this._cleanGroups(drawOptions);
                _this._saveDirtyCanvas()
            },
            _cleanGroups: function(drawOptions) {
                var _this = this;
                _this._stripsGroup.detach();
                _this._axesGroup.detach();
                _this._seriesGroup.detach();
                _this._labelsGroup.detach();
                _this._trackerGroup.detach();
                _this._tooltipGroup.detach();
                if (!drawOptions || drawOptions.drawLegend) {
                    _this._legendGroup.detach();
                    _this._legendGroup.clear()
                }
                _this._stripsGroup.clear();
                _this._axesGroup.clear();
                _this._seriesGroup.clear();
                _this._labelsGroup.clear();
                _this._tooltipGroup.clear();
                _this._seriesTrackerGroup.clear();
                _this._markerTrackerGroup.clear();
                _this._legendTrackerGroup.clear()
            },
            _drawTitle: function() {
                var _this = this;
                if (_this.chartTitle)
                    _this.chartTitle.update(_this.canvas, _this.option('title'));
                else
                    _this.chartTitle = charts.factory.createTitle(_this.renderer, _this.canvas, _this.option('title'), _this._titleGroup);
                _this.chartTitle.render()
            },
            _createTooltip: function() {
                var _this = this,
                    tooltipCoords,
                    point = _this.tracker.pointAtShownTooltip,
                    tooltipOptions = $.extend(true, {
                        renderer: _this.renderer,
                        canvasWidth: _this.canvas.width,
                        canvasHeight: _this.canvas.height
                    }, _this.option('tooltip') || {});
                if (!$.isFunction(tooltipOptions.customizeText) && utils.isDefined(tooltipOptions.customizeText)) {
                    _this.option('incidentOccured').call(null, 'customizeText can not be applied as it is not a function');
                    tooltipOptions.customizeText = undefined
                }
                if (_this.tooltip)
                    _this.tooltip.update(tooltipOptions);
                else
                    _this.tooltip = charts.factory.createTooltip(tooltipOptions, _this._tooltipGroup);
                _this.tooltip.draw();
                _this.tracker.tooltip = _this.tooltip;
                if (point) {
                    tooltipCoords = point.getTooltipCoords();
                    _this.tooltip.move(~~tooltipCoords.x, ~~tooltipCoords.y, tooltipCoords.offset, _this.tooltip.tooltipText, _this.tooltip.style.fill, _this.tooltip.className)
                }
            },
            _prepareDrawOptions: function(drawOptions) {
                var animationOptions = this.option('animation'),
                    options;
                animationOptions = animationOptions === true ? this._defaultOptions().animation : animationOptions;
                options = $.extend({}, {
                    force: false,
                    adjustAxes: true,
                    drawLegend: true,
                    drawTitle: true,
                    adjustSeriesLabels: true,
                    animate: animationOptions.enabled,
                    animationPointsLimit: animationOptions.maxPointCountSupported,
                    asyncSeriesRendering: animationOptions.asyncSeriesRendering,
                    asyncTrackersRendering: animationOptions.asyncTrackersRendering,
                    trackerRenderingDelay: animationOptions.trackerRenderingDelay
                }, drawOptions);
                if (!utils.isDefined(options.recreateCanvas))
                    options.recreateCanvas = !(!options.adjustAxes || !options.drawLegend || !options.drawTitle);
                return options
            },
            _processRefreshData: function(newRefreshAction) {
                var _this = this,
                    currentRefreshActionPosition = $.inArray(_this._currentRefreshData, ACTIONS_BY_PRIORITY),
                    newRefreshActionPosition = $.inArray(newRefreshAction, ACTIONS_BY_PRIORITY);
                if (!_this._currentRefreshData || currentRefreshActionPosition >= 0 && newRefreshActionPosition < currentRefreshActionPosition)
                    _this._currentRefreshData = newRefreshAction
            },
            _disposeSeries: function() {
                var _this = this;
                _this.tracker._clean();
                $.each(_this.series || [], function(_, series) {
                    series.dispose()
                });
                _this.series = null;
                $.each(_this.seriesFamilies || [], function(_, family) {
                    family.dispose()
                });
                _this.seriesFamilies = null
            },
            _optionValuesEqual: function(name, oldValue, newValue) {
                if (name === 'valueAxis' || name === 'argumentAxis' || name === 'commonAxisSettings' || name === 'userCommonAxisSettings')
                    if (oldValue && newValue)
                        if (utils.isArray(newValue) && !utils.isArray(oldValue)) {
                            oldValue.strips = null;
                            oldValue.categories = null
                        }
                        else if (!utils.isArray(newValue) && !utils.isArray(oldValue)) {
                            newValue.strips && (oldValue.strips = null);
                            newValue.categories && (oldValue.categories = null)
                        }
                return this.callBase.apply(this, arguments)
            },
            _optionChanged: function(name, value, prevValue) {
                var _this = this,
                    changedTitle;
                if (!_this._optionsInitializing) {
                    _this._optionValuesEqual(name, _this._userOptions[name], value);
                    dataUtils.compileSetter(name)(_this._userOptions, value, {
                        functionsAsIs: true,
                        merge: true
                    })
                }
                if (name == 'animation') {
                    _this.renderer.updateAnimationOptions(value);
                    return
                }
                clearTimeout(_this.delayedRedraw);
                switch (name) {
                    case'dataSource':
                        _this._needHandleRenderComplete = true;
                        _this._processRefreshData('_reinitDataSource');
                        break;
                    case'palette':
                        _this.themeManager.updatePalette(value);
                        _this._disposeSeries();
                        _this._needHandleRenderComplete = true;
                        _this._processRefreshData('_handleDataSourceChanged');
                        break;
                    case'series':
                    case'commonSeriesSettings':
                    case'backgroundColor':
                        _this._disposeSeries();
                        _this._needHandleRenderComplete = true;
                        _this._processRefreshData('_handleDataSourceChanged');
                        break;
                    case'legend':
                    case'seriesTemplate':
                        _this._processRefreshData('_handleDataSourceChanged');
                        break;
                    case'title':
                        changedTitle = _this._processTitleOption(value, prevValue);
                        if (changedTitle) {
                            _this.option('title', prevValue);
                            return
                        }
                        _this._processRefreshData('force_render');
                        break;
                    case'valueAxis':
                    case'argumentAxis':
                    case'commonAxisSettings':
                        _this._needHandleRenderComplete = true;
                        _this._processRefreshData('processAxesOption');
                        _this._disposeSeries();
                        _this.paneAxis = {};
                        break;
                    case'panes':
                    case'defaultPane':
                        _this._disposeSeries();
                        _this.paneAxis = {};
                        _this._needHandleRenderComplete = true;
                        _this._processRefreshData('reinit');
                        break;
                    case'size':
                        _this._saveUserCanvas();
                        _this._processRefreshData('force_render');
                        break;
                    case'theme':
                        _this._initOptions(_this._userOptions);
                        _this._processRefreshData('reinit');
                        break;
                    default:
                        _this._processRefreshData('reinit')
                }
                _this.callBase.apply(_this, arguments)
            },
            _refresh: function() {
                var _this = this;
                _this._clean();
                if (_this._currentRefreshData) {
                    switch (_this._currentRefreshData) {
                        case'force_render':
                            _this._render({force: true});
                            break;
                        case'processAxesOption':
                            _this._processAxesOption(_this._options);
                            _this._reinit(true);
                            break;
                        case'reinit':
                            _this._reinit(true);
                            break;
                        default:
                            _this[_this._currentRefreshData] && _this[_this._currentRefreshData]()
                    }
                    delete _this._currentRefreshData
                }
                else
                    _this._render({force: true})
            },
            _dataSourceOptions: function() {
                return {
                        paginate: false,
                        _preferSync: true
                    }
            },
            _createCanvasClipRect: function() {
                var _this = this,
                    canvas = _this.canvas;
                if (!_this.canvasClipRect)
                    _this.canvasClipRect = _this.renderer.createClipRect(canvas.left, canvas.top, canvas.width - canvas.left - canvas.right, canvas.height - canvas.top - canvas.bottom).append();
                else
                    _this.canvasClipRect.updateRectangle({
                        x: canvas.left,
                        y: canvas.top,
                        width: canvas.width - canvas.left - canvas.right,
                        height: canvas.height - canvas.top - canvas.bottom
                    })
            },
            _getCanvasClipRectID: function() {
                return this.canvasClipRect.id
            },
            _handleDataSourceChanged: function() {
                this._dataSpecificInit(true)
            },
            _dataSpecificInit: function(needRedraw) {
                var _this = this;
                _this._initSeries();
                _this._repopulateSeries();
                _this._handleSeriesPopulated(needRedraw)
            },
            _processSeriesTemplate: function() {
                var _this = this,
                    seriesTemplate = _this.option('seriesTemplate'),
                    customizeSeries = utils.isFunction(seriesTemplate.customizeSeries) ? seriesTemplate.customizeSeries : $.noop,
                    nameField = seriesTemplate.nameField || 'series',
                    dataSource = _this._dataSource;
                if (!dataSource)
                    return;
                var generatedSeries = {},
                    seriesOrder = [],
                    items = dataSource.items(),
                    series;
                for (var i = 0, length = items.length; i < length; i++) {
                    var data = items[i];
                    series = generatedSeries[data[nameField]];
                    if (!series) {
                        series = generatedSeries[data[nameField]] = {
                            name: data[nameField],
                            data: []
                        };
                        seriesOrder.push(series.name)
                    }
                    series.data.push(data)
                }
                _this._templatedSeries = $.map(seriesOrder, function(orderedName) {
                    var group = generatedSeries[orderedName],
                        seriesOptions = customizeSeries.call(null, group.name);
                    return $.extend(group, seriesOptions)
                });
                _this._populateSeries();
                delete _this._templatedSeries
            },
            _processSingleSeries: function(){},
            _repopulateSeries: function() {
                var _this = this,
                    data = _this._dataSource && _this._dataSource.items(),
                    seriesTemplate = _this.option('seriesTemplate');
                _this.themeManager.resetPalette();
                if (_this._dataSource && seriesTemplate)
                    _this._processSeriesTemplate();
                else
                    data && $.each(_this.series, function(_, singleSeries) {
                        singleSeries.reinitData(data);
                        _this._processSingleSeries(singleSeries, singleSeries.userOptions)
                    })
            },
            _handleRenderComplete: function() {
                var _this = this,
                    userHandle = _this.option('done'),
                    allSeriesInited = true;
                if (_this._needHandleRenderComplete) {
                    $.each(_this.series, function(_, s) {
                        allSeriesInited = allSeriesInited && s.canRenderCompleteHandle()
                    });
                    if (allSeriesInited) {
                        $.isFunction(userHandle) && userHandle.call(_this);
                        _this._needHandleRenderComplete = false
                    }
                }
            },
            _stopAnimation: function() {
                $.each(this.series || [], function(_, series) {
                    series.stopAnimation()
                })
            },
            getAllSeries: function getAllSeries() {
                return this.series.slice()
            },
            getSeriesByName: function getSeriesByName(name) {
                var found = null;
                $.each(this.series, function(i, singleSeries) {
                    if (singleSeries.name === name) {
                        found = singleSeries;
                        return false
                    }
                });
                return found
            },
            getSeriesByPos: function getSeriesByPos(pos) {
                return this.series[pos]
            },
            getSelectedSeries: function getSelectedSeries() {
                return null
            },
            clearSelection: function clearSelection() {
                this.tracker.clearSelection()
            },
            hideTooltip: function() {
                this.tracker._hideTooltip(null, true)
            },
            render: function(renderOptions) {
                this._render(renderOptions)
            }
        }).include(ui.DataHelperMixin)
    })(jQuery, DevExpress);
    /*! Module viz, file chart.js */
    (function($, DX, undefined) {
        var charts = DX.viz.charts,
            utils = DX.utils,
            MAX_ADJUSTMENT_ATTEMPTS = 5,
            DEFAULT_PANE_NAME = 'default',
            DEFAULT_AXIS_NAME = 'defaultAxisName',
            DEFAULT_BUSINESS_RANGE_VALUE_MARGIN = 0.1;
        charts.Chart = charts.BaseChart.inherit({
            _defaultOptions: function() {
                return $.extend(true, this.callBase(), {
                        commonSeriesSettings: {
                            type: 'line',
                            maxLabelCount: undefined,
                            stack: 'default',
                            label: {
                                visible: false,
                                alignment: 'center',
                                rotationAngle: 0,
                                horizontalOffset: 0,
                                verticalOffset: 0,
                                radialOffset: 0,
                                format: '',
                                argumentFormat: '',
                                precision: 0,
                                argumentPrecision: 0,
                                percentPrecision: 0,
                                customizeText: undefined,
                                position: 'outside',
                                connector: {
                                    visible: false,
                                    width: 0
                                }
                            }
                        },
                        defaultPane: DEFAULT_PANE_NAME,
                        adjustOnZoom: true,
                        rotated: false,
                        synchronizeMultiAxes: true,
                        equalBarWidth: true,
                        commonPaneSettings: {
                            backgroundColor: 'none',
                            border: {
                                visible: false,
                                top: true,
                                bottom: true,
                                left: true,
                                right: true,
                                dashStyle: 'solid'
                            }
                        },
                        panes: [{
                                name: DEFAULT_PANE_NAME,
                                border: {}
                            }],
                        commonAxisSettings: {
                            tickInterval: undefined,
                            setTicksAtUnitBeginning: true,
                            valueMarginsEnabled: true,
                            placeholderSize: null
                        }
                    })
            },
            _dispose: function() {
                var _this = this,
                    disposeObjectsInArray = this._disposeObjectsInArray;
                _this.callBase();
                _this.panes = null;
                _this.legend.dispose(),
                _this.legend = null;
                disposeObjectsInArray.call(_this, "panesBackground");
                disposeObjectsInArray.call(_this, "panesClipRects");
                disposeObjectsInArray.call(_this, "horizontalAxes");
                disposeObjectsInArray.call(_this, "verticalAxes");
                disposeObjectsInArray.call(_this, "seriesFamilies");
                $.each(_this._paneTrackerGroups || [], function(_, groups) {
                    groups.paneSeriesGroup.dispose();
                    groups.paneMarkerGroup.dispose()
                });
                _this._paneTrackerGroups = null
            },
            _init: function() {
                this.paneAxis = {};
                this.callBase()
            },
            _reinit: function(needRedraw) {
                var _this = this;
                _this._disposeObjectsInArray("translators");
                _this.translators = [];
                _this.panes = _this._createPanes();
                _this._populateAxes();
                _this.callBase();
                delete _this._seriesInitializing;
                if (!_this.series)
                    _this._dataSpecificInit();
                else
                    _this._correctValueAxes();
                needRedraw && _this._render({force: true})
            },
            _correctBusinessRange: function(range, tickInterval, field, setTicksAtUnitBeginning) {
                var min = 'min' + field,
                    max = 'max' + field;
                if (!tickInterval || !utils.isDefined(range[min]) || !utils.isDefined(range[max]))
                    return false;
                var tickIntervalRange = {},
                    originInterval = tickInterval;
                tickInterval = $.isNumeric(tickInterval) ? tickInterval : utils.convertDateTickIntervalToMilliseconds(tickInterval);
                if (tickInterval >= Math.abs(range[max] - range[min])) {
                    if (utils.isDate(range[min])) {
                        if (!$.isNumeric(originInterval)) {
                            tickIntervalRange[min] = utils.addInterval(range[min], originInterval, true);
                            tickIntervalRange[max] = utils.addInterval(range[max], originInterval, false)
                        }
                        else {
                            tickIntervalRange[min] = new Date(range[min].valueOf() - tickInterval);
                            tickIntervalRange[max] = new Date(range[max].valueOf() + tickInterval)
                        }
                        if (setTicksAtUnitBeginning) {
                            utils.correctDateWithUnitBeginning(tickIntervalRange[max], originInterval);
                            utils.correctDateWithUnitBeginning(tickIntervalRange[min], originInterval)
                        }
                    }
                    else {
                        tickIntervalRange[min] = range[min] - tickInterval;
                        tickIntervalRange[max] = range[max] + tickInterval
                    }
                    range.getBoundRange(tickIntervalRange);
                    return true
                }
                return false
            },
            _populateBusinessRange: function(visibleArea) {
                var _this = this,
                    panes = _this.panes,
                    businessRanges = [],
                    range,
                    i,
                    rotated = _this.option('rotated'),
                    singleSeriesRange,
                    valAxes = rotated ? _this.horizontalAxes : _this.verticalAxes,
                    argAxes = rotated ? _this.verticalAxes : _this.horizontalAxes,
                    valueField = rotated && 'X' || 'Y',
                    argumentField = rotated && 'Y' || 'X',
                    valueBoundRange = 'getBoundRange' + valueField,
                    argumentBoundRange = 'getBoundRange' + argumentField,
                    businessLength,
                    paneList = $.map(panes, function(pane) {
                        return pane.name
                    }),
                    series = _this.series,
                    argumentTickInterval,
                    setTicksAtUnitBeginning;
                _this._disposeObjectsInArray("businessRanges");
                var hideGridsOnNonFirstValueAxisForPane = function(paneName) {
                        var axesForPane = [],
                            firstShownAxis;
                        $.each(valAxes, function(_, axis) {
                            if (axis.pane === paneName)
                                axesForPane.push(axis)
                        });
                        if (axesForPane.length > 1 && _this.option('synchronizeMultiAxes'))
                            $.each(axesForPane, function(_, axis) {
                                var gridOpt = axis.options.grid;
                                if (firstShownAxis && gridOpt && gridOpt.visible)
                                    gridOpt.visible = false;
                                else
                                    firstShownAxis = firstShownAxis ? firstShownAxis : gridOpt && gridOpt.visible
                            })
                    };
                var paneAxis = _this.paneAxis;
                var argRange = new charts.Range;
                var getFirstAxisNameForPane = function(axes, paneName) {
                        var result;
                        for (var i = 0; i < axes.length; i++)
                            if (axes[i].pane === paneName) {
                                result = axes[i].name;
                                break
                            }
                        if (!result)
                            result = valAxes[0].name;
                        return result
                    };
                $.each(series, function(i, particularSeries) {
                    particularSeries.axis = particularSeries.axis || getFirstAxisNameForPane(valAxes, particularSeries.pane);
                    if (particularSeries.axis) {
                        paneAxis[particularSeries.pane] = paneAxis[particularSeries.pane] || {};
                        paneAxis[particularSeries.pane][particularSeries.axis] = true
                    }
                });
                $.each(valAxes, function(_, axis) {
                    if (axis.name && axis.pane && $.inArray(axis.pane, paneList) != -1) {
                        paneAxis[axis.pane] = paneAxis[axis.pane] || {};
                        paneAxis[axis.pane][axis.name] = true
                    }
                });
                _this._correctValueAxes();
                $.each(paneAxis, function(paneName, pane) {
                    hideGridsOnNonFirstValueAxisForPane(paneName);
                    $.each(pane, function(axisName, _) {
                        var seriesForRange = [],
                            valueAxesForRange = [],
                            argumentAxesForRange = [],
                            valRange = new charts.Range({
                                pane: paneName,
                                axis: axisName,
                                minValueMarginX: DEFAULT_BUSINESS_RANGE_VALUE_MARGIN,
                                maxValueMarginX: DEFAULT_BUSINESS_RANGE_VALUE_MARGIN,
                                minValueMarginY: DEFAULT_BUSINESS_RANGE_VALUE_MARGIN,
                                maxValueMarginY: DEFAULT_BUSINESS_RANGE_VALUE_MARGIN
                            }),
                            valueType;
                        $.each(series, function(_, particularSeries) {
                            if (particularSeries.pane === paneName && particularSeries.axis === axisName)
                                seriesForRange.push(particularSeries)
                        });
                        $.each(argAxes, function(_, axis) {
                            argumentAxesForRange.push(axis)
                        });
                        $.each(valAxes, function(_, axis) {
                            if (axis.pane === paneName && axis.name === axisName)
                                valueAxesForRange.push(axis)
                        });
                        $.each(argumentAxesForRange, function(_, axis) {
                            axis.options.type = seriesForRange && seriesForRange.length ? seriesForRange[0].options.argumentAxisType : null;
                            argRange = argRange[argumentBoundRange](axis.getRangeData());
                            argumentTickInterval = axis.options.tickInterval;
                            setTicksAtUnitBeginning = axis.options.setTicksAtUnitBeginning
                        });
                        $.each(valueAxesForRange, function(_, axis) {
                            axis.options.type = seriesForRange && seriesForRange.length ? seriesForRange[0].options.valueAxisType : null;
                            var axisRange = new charts.Range(axis.getRangeData());
                            axisRange.applyEqualLimitsMargins();
                            valueType = valueType || axis.options.valueType === 'datetime' ? 'datetime' : undefined;
                            valRange = valRange[valueBoundRange](axisRange)
                        });
                        for (i = 0; i < seriesForRange.length; i++) {
                            singleSeriesRange = seriesForRange[i].getRangeData(visibleArea);
                            valRange = valRange[valueBoundRange](singleSeriesRange);
                            argRange = argRange[argumentBoundRange](singleSeriesRange)
                        }
                        if (!valRange['isDefined' + valueField]())
                            valRange['setStubData' + valueField](valueType);
                        businessRanges.push(valRange)
                    })
                });
                if (!argRange['isDefined' + argumentField]())
                    argRange['setStubData' + argumentField](argAxes[0].options.argumentType);
                var bussinesRangeCorrectedWithTickInterval = _this._correctBusinessRange(argRange, argumentTickInterval, argumentField, setTicksAtUnitBeginning);
                $.each(businessRanges, function(_, range) {
                    range = range.getBoundRange(argRange);
                    !bussinesRangeCorrectedWithTickInterval && range.applyValueMargins();
                    range['stubData' + argumentField] = argRange['stubData' + argumentField];
                    if (!range.isDefined())
                        range.setStubData()
                });
                _this.businessRanges = businessRanges
            },
            _createPanes: function() {
                var _this = this,
                    panes = _this.option('panes'),
                    bottomPaneName;
                $.each(_this.panesClipRects || [], function(i, clipRect) {
                    clipRect.remove()
                });
                _this.panesClipRects = [];
                _this.defaultPane = _this.option('defaultPane');
                panes = $.isArray(panes) ? panes : panes ? [panes] : [];
                if (!_this._doesPaneExists(panes, _this.defaultPane) && panes.length > 0) {
                    bottomPaneName = panes[panes.length - 1].name;
                    _this.option('incidentOccured')('Pane "' + _this.defaultPane + '" does not exist. Use pane "' + bottomPaneName + '" instead');
                    _this.defaultPane = bottomPaneName
                }
                if (_this.option('rotated'))
                    panes = panes.reverse();
                return panes
            },
            _doesPaneExists: function(panes, paneName) {
                var found = false;
                $.each(panes, function(_, pane) {
                    if (pane.name === paneName) {
                        found = true;
                        return false
                    }
                });
                return found
            },
            _populateSeries: function() {
                var _this = this,
                    hasSeriesTemplate = !!_this.option('seriesTemplate'),
                    series = hasSeriesTemplate ? _this._templatedSeries : _this.option('series'),
                    allSeriesOptions = $.isArray(series) ? series : series ? [series] : [],
                    argumentAxisOptions = _this.option('argumentAxis'),
                    valueAxisOptions = _this.option('valueAxis'),
                    themeManager = _this.themeManager,
                    data,
                    particularSeriesOptions,
                    commonSeriesSettings = _this.option('commonSeriesSettings'),
                    userCommonSeriesSettings = _this._userOptions.commonSeriesSettings,
                    particularSeries,
                    rotated = _this.option('rotated'),
                    incidentOccured = _this.option('incidentOccured'),
                    i,
                    paneList = $.map(_this.panes, function(pane) {
                        return pane.name
                    }),
                    paneName,
                    paneIndex;
                $.each(_this._paneTrackerGroups || [], function(_, groups) {
                    groups.paneSeriesGroup.remove();
                    groups.paneMarkerGroup.remove()
                });
                _this._paneTrackerGroups = [];
                $.each(_this.panes, function(_, pane) {
                    var paneSeriesTrackerGroup = _this.renderer.createGroup({'class': 'dxc-pane-tracker'}),
                        paneMarkerTrackerGroup = _this.renderer.createGroup({'class': 'dxc-pane-tracker'});
                    _this._paneTrackerGroups.push({
                        paneSeriesGroup: paneSeriesTrackerGroup,
                        paneMarkerGroup: paneMarkerTrackerGroup
                    })
                });
                _this._disposeSeries();
                _this.series = [];
                themeManager.resetPalette();
                commonSeriesSettings.containerBackgroundColor = _this.option('containerBackgroundColor');
                for (i = 0; i < allSeriesOptions.length; i++) {
                    particularSeriesOptions = allSeriesOptions[i];
                    if (particularSeriesOptions.type && !utils.isString(particularSeriesOptions.type))
                        particularSeriesOptions.type = '';
                    data = particularSeriesOptions.data;
                    particularSeriesOptions.data = null;
                    particularSeriesOptions.rotated = rotated;
                    if (argumentAxisOptions) {
                        particularSeriesOptions.argumentCategories = argumentAxisOptions.categories;
                        particularSeriesOptions.argumentAxisType = argumentAxisOptions.type;
                        particularSeriesOptions.argumentType = argumentAxisOptions.argumentType
                    }
                    if (valueAxisOptions)
                        if (utils.isArray(valueAxisOptions))
                            $.each(valueAxisOptions, function(iter, options) {
                                if (!particularSeriesOptions.axis && !iter || particularSeriesOptions.axis === options.name) {
                                    particularSeriesOptions.valueCategories = options.categories;
                                    particularSeriesOptions.valueAxisType = options.type;
                                    particularSeriesOptions.valueType = options.valueType
                                }
                            });
                        else {
                            particularSeriesOptions.valueCategories = valueAxisOptions.categories;
                            particularSeriesOptions.valueAxisType = valueAxisOptions.type;
                            particularSeriesOptions.valueType = valueAxisOptions.valueType
                        }
                    particularSeriesOptions.incidentOccured = incidentOccured;
                    if (!particularSeriesOptions.name)
                        particularSeriesOptions.name = 'Series ' + (i + 1).toString();
                    var seriesTheme = themeManager.applyNextSeriesTheme(particularSeriesOptions, commonSeriesSettings, userCommonSeriesSettings);
                    seriesTheme.pane = seriesTheme.pane || _this.defaultPane;
                    paneName = seriesTheme.pane;
                    paneIndex = _this._getPaneIndex(paneName);
                    if ($.inArray(paneName, paneList) === -1)
                        continue;
                    seriesTheme.seriesGroup = _this._seriesGroup;
                    seriesTheme.seriesLabelsGroup = _this._labelsGroup;
                    seriesTheme.seriesTrackerGroup = _this._paneTrackerGroups[paneIndex].paneSeriesGroup;
                    seriesTheme.markerTrackerGroup = _this._paneTrackerGroups[paneIndex].paneMarkerGroup;
                    particularSeries = charts.factory.createSeries(seriesTheme.type, _this.renderer, data, seriesTheme);
                    if (!particularSeries)
                        incidentOccured.call(null, 'Unknown series type requested: ' + seriesTheme.type);
                    else {
                        particularSeries.index = i;
                        _this.series.push(particularSeries)
                    }
                    particularSeriesOptions.data = data
                }
                return _this.series
            },
            _createValueAxis: function(axisOptions, rotated, tickProvider) {
                var _this = this,
                    axis;
                axisOptions = $.extend({
                    isHorizontal: rotated,
                    tickProvider: tickProvider,
                    incidentOccured: _this.option('incidentOccured')
                }, axisOptions);
                axisOptions = $.extend(true, {}, _this.option('commonAxisSettings'), _this.option(rotated ? 'horizontalAxis' : 'verticalAxis'), _this.option('valueAxisStyle'), _this.option('userCommonAxisSettings'), _this.option('valueAxis'), axisOptions);
                if (axisOptions.strips)
                    $.each(axisOptions.strips, function(i, strips) {
                        axisOptions.strips[i] = $.extend(true, {}, axisOptions.stripStyle, axisOptions.strips[i])
                    });
                axis = charts.factory.createAxis(_this.renderer, axisOptions);
                axis.name = axisOptions.name;
                axis.pane = axis.pane || axisOptions.pane;
                axis.priority = axisOptions.priority;
                return axis
            },
            _disposeAxes: function() {
                var _this = this;
                $.each(_this.horizontalAxes || [], function(_, axis) {
                    axis.dispose()
                });
                $.each(_this.verticalAxes || [], function(_, axis) {
                    axis.dispose()
                });
                _this.horizontalAxes = null;
                _this.verticalAxes = null
            },
            _populateAxes: function() {
                var _this = this,
                    horizontalAxes = [],
                    verticalAxes = [],
                    panes = _this.panes,
                    rotated = _this.option('rotated'),
                    themeManager = _this.themeManager,
                    valueAxisOptions = _this.option('valueAxis') || {},
                    argumentOption = _this.option('argumentAxis') || {},
                    argumentAxesOptions = $.isArray(argumentOption) ? argumentOption : [argumentOption],
                    valueAxesOptions = $.isArray(valueAxisOptions) ? valueAxisOptions : [valueAxisOptions],
                    i,
                    axis,
                    axisNames = [],
                    axisOptions,
                    tickProvider = charts.factory.getAxisTickProvider(),
                    paneWithNonVirtualAxis;
                _this._disposeAxes();
                var createArgumentAxis = function(axisOptions, virtual) {
                        axisOptions = $.extend(true, {
                            isHorizontal: !rotated,
                            tickProvider: tickProvider,
                            pane: _this.defaultPane,
                            incidentOccured: _this.option('incidentOccured')
                        }, axisOptions);
                        axisOptions = $.extend(true, {}, _this.option('commonAxisSettings'), _this.option(rotated ? 'verticalAxis' : 'horizontalAxis'), _this.option('argumentAxisStyle'), _this.option('userCommonAxisSettings'), _this.option('argumentAxis'), axisOptions);
                        if (axisOptions.strips)
                            $.each(axisOptions.strips, function(i, strips) {
                                axisOptions.strips[i] = $.extend(true, {}, axisOptions.stripStyle, axisOptions.strips[i])
                            });
                        axis = charts.factory.createAxis(_this.renderer, axisOptions);
                        axis._virtual = virtual;
                        if (axisOptions.isHorizontal)
                            horizontalAxes.push(axis);
                        else
                            verticalAxes.push(axis)
                    };
                if (rotated)
                    paneWithNonVirtualAxis = argumentAxesOptions[0].position === 'right' ? panes[panes.length - 1].name : panes[0].name;
                else
                    paneWithNonVirtualAxis = argumentAxesOptions[0].position === 'top' ? panes[0].name : panes[panes.length - 1].name;
                $.each(panes, function(_, pane) {
                    var paneName = pane.name,
                        virtual = paneName != paneWithNonVirtualAxis;
                    var axisOptions = $.extend(true, {}, {pane: paneName}, argumentAxesOptions[0]);
                    createArgumentAxis(axisOptions, virtual)
                });
                var createValueAxis = function(axisOptions) {
                        var axis = _this._createValueAxis(axisOptions, rotated, tickProvider);
                        if (rotated)
                            horizontalAxes.push(axis);
                        else
                            verticalAxes.push(axis)
                    };
                var valueAxesCounter = 0;
                var getNextAxisName = function() {
                        return DEFAULT_AXIS_NAME + valueAxesCounter++
                    };
                var unique = function(array) {
                        var values = {},
                            i,
                            len = array.length;
                        for (i = 0; i < len; i++)
                            values[array[i]] = true;
                        return $.map(values, function(_, key) {
                                return key
                            })
                    };
                $.each(valueAxesOptions, function(priority, axisOptions) {
                    var axisPanes = [],
                        name = axisOptions.name;
                    if (name && $.inArray(name, axisNames) != -1) {
                        _this.option('incidentOccured').call(null, 'The valueAxis configuration array contains axes with the same name.');
                        return
                    }
                    name && axisNames.push(name);
                    if (axisOptions.pane)
                        axisPanes.push(axisOptions.pane);
                    if (axisOptions.panes && axisOptions.panes.length)
                        axisPanes = axisPanes.concat(axisOptions.panes.slice(0));
                    axisPanes = unique(axisPanes);
                    if (!axisPanes.length)
                        axisPanes.push(undefined);
                    $.each(axisPanes, function(_, pane) {
                        createValueAxis($.extend(true, {}, axisOptions, {
                            name: name || getNextAxisName(),
                            pane: pane,
                            priority: priority
                        }))
                    })
                });
                _this.horizontalAxes = horizontalAxes;
                _this.verticalAxes = verticalAxes
            },
            _correctValueAxes: function() {
                var _this = this,
                    rotated = _this.option('rotated'),
                    themeManager = _this.themeManager,
                    valueAxisOptions = _this.option('valueAxis') || {},
                    valueAxesOptions = $.isArray(valueAxisOptions) ? valueAxisOptions : [valueAxisOptions],
                    tickProvider = charts.factory.getAxisTickProvider(),
                    valueAxes = (rotated ? _this.horizontalAxes : _this.verticalAxes) || [],
                    defaultAxisName = valueAxes[0].name,
                    paneAxis = _this.paneAxis || {},
                    panes = _this.panes,
                    i,
                    neededAxis = {};
                var getPaneForAxis = function(axisNameWithoutPane) {
                        var result;
                        $.each(_this.paneAxis, function(paneName, pane) {
                            $.each(pane, function(axisName, _) {
                                if (axisNameWithoutPane == axisName) {
                                    result = paneName;
                                    return false
                                }
                            })
                        });
                        return result
                    };
                var axesWithoutPanes = $.map(valueAxes, function(axis) {
                        if (axis.pane)
                            return null;
                        return axis
                    });
                $.each(axesWithoutPanes, function(_, axis) {
                    axis.pane = getPaneForAxis(axis.name);
                    if (!axis.pane) {
                        axis.pane = _this.defaultPane;
                        paneAxis[axis.pane] = paneAxis[axis.pane] || {};
                        paneAxis[axis.pane][axis.name] = true
                    }
                    axis.options.pane = axis.pane
                });
                for (i = 0; i < panes.length; i++)
                    if (!paneAxis[panes[i].name]) {
                        paneAxis[panes[i].name] = {};
                        paneAxis[panes[i].name][defaultAxisName] = true
                    }
                var findAxisOptions = function(axisName) {
                        var result,
                            axInd;
                        for (axInd = 0; axInd < valueAxesOptions.length; axInd++)
                            if (valueAxesOptions[axInd].name == axisName) {
                                result = valueAxisOptions[axInd];
                                result.priority = axInd;
                                break
                            }
                        if (!result)
                            for (axInd = 0; axInd < valueAxes.length; axInd++)
                                if (valueAxes[axInd].name == axisName) {
                                    result = valueAxes[axInd].options;
                                    result.priority = valueAxes[axInd].priority;
                                    break
                                }
                        if (!result) {
                            _this.option('incidentOccured').call(null, 'Value axis with name "' + axisName + '" does not exist. It was created.');
                            result = {
                                name: axisName,
                                priority: valueAxes.length
                            }
                        }
                        return result
                    };
                var findAxis = function(paneName, axisName) {
                        var axis;
                        for (i = 0; i < valueAxes.length; i++) {
                            axis = valueAxes[i];
                            if (axis.name === axisName && axis.pane === paneName)
                                return axis
                        }
                    };
                $.each(_this.paneAxis, function(paneName, axisNames) {
                    $.each(axisNames, function(axisName, _) {
                        neededAxis[axisName + '-' + paneName] = true;
                        if (!findAxis(paneName, axisName)) {
                            var axisOptions = findAxisOptions(axisName);
                            if (axisOptions)
                                valueAxes.push(_this._createValueAxis($.extend(true, {}, axisOptions, {
                                    pane: paneName,
                                    name: axisName
                                }), rotated, tickProvider))
                        }
                    })
                });
                valueAxes = $.grep(valueAxes, function(elem) {
                    return !!neededAxis[elem.name + '-' + elem.pane]
                });
                valueAxes.sort(function(a, b) {
                    return a.priority - b.priority
                });
                rotated ? _this.horizontalAxes = valueAxes : _this.verticalAxes = valueAxes
            },
            _processSeriesFamilies: function() {
                var _this = this,
                    types = [],
                    families = [],
                    paneSeries,
                    rotated = _this.option('rotated');
                if (_this.seriesFamilies && _this.seriesFamilies.length) {
                    $.each(_this.seriesFamilies, function(_, family) {
                        family.adjustSeriesValues()
                    });
                    return
                }
                $.each(_this.series, function(_, item) {
                    if ($.inArray(item.type, types) === -1)
                        types.push(item.type)
                });
                $.each(_this.panes, function(_, pane) {
                    paneSeries = [];
                    $.each(_this.series, function(_, oneSeries) {
                        if (oneSeries.pane === pane.name)
                            paneSeries.push(oneSeries)
                    });
                    $.each(types, function(_, type) {
                        var family = charts.factory.createSeriesFamily({
                                type: type,
                                pane: pane.name,
                                rotated: rotated,
                                equalBarWidth: _this.option('equalBarWidth')
                            });
                        family.add(paneSeries);
                        family.adjustSeriesValues();
                        families.push(family)
                    })
                });
                _this.seriesFamilies = families
            },
            _createLegend: function() {
                var _this = this,
                    legendOptions = $.extend(true, {
                        renderer: _this.renderer,
                        series: _this.series,
                        containerBackgroundColor: _this.option('commonSeriesSettings').containerBackgroundColor
                    }, _this.option('legend'));
                if (_this.legend)
                    _this.legend.update(legendOptions);
                else
                    _this.legend = charts.factory.createLegend(legendOptions, _this._legendGroup, _this._legendTrackerGroup)
            },
            _createTranslator: function(range, canvas) {
                return new DX.viz.core.LinearTranslator(range, canvas)
            },
            _createPanesBorderOptions: function() {
                var commonBorderOptions = this.option('commonPaneSettings').border,
                    panesBorderOptions = {};
                $.each(this.panes, function(_, pane) {
                    var borderOptions = $.extend(true, {}, commonBorderOptions, pane.border);
                    panesBorderOptions[pane.name] = borderOptions
                });
                return panesBorderOptions
            },
            _render: function(drawOptions) {
                var _this = this,
                    renderer = _this.renderer,
                    translators = _this.translators,
                    rotated = _this.option('rotated'),
                    i,
                    layoutManager = _this.layoutManager,
                    titleOptions = _this.option('title'),
                    adjustmentCounter = 0,
                    paneName,
                    multiAxesSynchronizer = new charts.MultiAxesSynchronizer,
                    panesBorderOptions = _this._createPanesBorderOptions();
                var updateAxesPerPane = function(_this, axes) {
                        var translator,
                            axis,
                            axisName;
                        for (i = 0; i < axes.length; i++) {
                            axis = axes[i];
                            paneName = axis.pane;
                            axisName = axis.name;
                            translator = _this._getTranslator(paneName, axisName);
                            if (translator) {
                                translator.init();
                                axis.setRange(translator.getBusinessRange());
                                axis.setTranslator(translator)
                            }
                        }
                    };
                var drawSeries = function drawSeries() {
                        var particularSeries;
                        $.each(_this.seriesFamilies || [], function(_, seriesFamily) {
                            var translator = _this._getTranslator(seriesFamily.pane);
                            seriesFamily.updateSeriesValues(translator);
                            seriesFamily.adjustSeriesDimensions(translator)
                        });
                        for (i = 0; i < _this.series.length; i++) {
                            particularSeries = _this.series[i];
                            particularSeries.elementsClipRectID = _this._getElementsClipRectID(_this.series[i].pane);
                            particularSeries.markersClipRectID = _this._getMarkersClipRectID(_this.series[i].pane);
                            particularSeries.adjustSeriesLabels = drawOptions.adjustSeriesLabels;
                            particularSeries.draw(_this._getTranslator(particularSeries.pane, particularSeries.axis));
                            if (drawOptions.animate && particularSeries.getPoints().length <= drawOptions.animationPointsLimit)
                                particularSeries.animate()
                        }
                        if (drawOptions.drawLegend && _this.legend && _this.legend.options.position === 'inside') {
                            _this.legend.canvas = _this.canvas;
                            _this._legendGroup.append();
                            _this._tooltipGroup.append();
                            _this.legend.draw();
                            layoutManager.applyLegendLayout()
                        }
                        else
                            _this.legend.options.position == 'inside' && _this.legend.toForeground();
                        _this.option('drawn')();
                        var drawChartTrackers = function drawChartTrackers() {
                                $.each(_this._paneTrackerGroups || [], function(_, groups) {
                                    groups.paneSeriesGroup.clear();
                                    groups.paneMarkerGroup.clear()
                                });
                                for (i = 0; i < _this.series.length; i++)
                                    _this.series[i].drawTrackers();
                                _this.legend && _this.legend.drawTrackers();
                                _this.tracker._prepare();
                                $.each(_this._paneTrackerGroups, function(index, paneGroups) {
                                    var borderVisible = _this._getPaneBorderVisibility(index),
                                        clipId = _this.panesClipRects[index].id;
                                    paneGroups.paneSeriesGroup.applySettings({clipId: clipId});
                                    if (borderVisible)
                                        paneGroups.paneMarkerGroup.applySettings({clipId: clipId});
                                    paneGroups.paneSeriesGroup.append(_this._seriesTrackerGroup);
                                    paneGroups.paneMarkerGroup.append(_this._markerTrackerGroup)
                                });
                                _this._trackerGroup.append();
                                _this._handleRenderComplete()
                            };
                        _this._createTooltip();
                        if (drawOptions.asyncTrackersRendering)
                            _this.delayedRedraw = setTimeout(drawChartTrackers, drawOptions.trackerRenderingDelay);
                        else
                            drawChartTrackers()
                    };
                drawOptions = _this._prepareDrawOptions(drawOptions);
                _this.callBase(drawOptions);
                if (_this.stopRedraw) {
                    _this.stopRedraw = false;
                    return
                }
                _this._createPanesBackground();
                if (titleOptions.text && drawOptions.drawTitle) {
                    _this._titleGroup.append();
                    _this._drawTitle();
                    layoutManager.applyTitleLayout()
                }
                if (drawOptions.drawLegend && _this.legend && _this.legend.options.position === 'outside') {
                    _this.legend.canvas = _this.canvas;
                    _this._legendGroup.append();
                    _this.legend.draw();
                    layoutManager.applyLegendLayout();
                    if (layoutManager.isCanvasExceeded(false)) {
                        _this.option('incidentOccured')('Container is too small to draw chart with current settings');
                        _this._clean();
                        return
                    }
                }
                _this._setPanesClipRectPadding(panesBorderOptions, rotated);
                if (drawOptions.recreateCanvas) {
                    layoutManager.createPanesCanvases();
                    $.each(_this.paneAxis, function(paneName, pane) {
                        $.each(pane, function(axisName, _) {
                            var translator = _this._createTranslator(new charts.Range(_this._getBusinessRange(paneName, axisName)), _this._getCanvasForPane(paneName));
                            translator.pane = paneName;
                            translator.axis = axisName;
                            translators.push(translator)
                        })
                    })
                }
                else
                    $.each(translators, function(_, translator) {
                        translator.updateBusinessRange(new charts.Range(_this._getBusinessRange(translator.pane, translator.axis)));
                        delete translator._originalBusinessRange;
                        translator.init()
                    });
                updateAxesPerPane(_this, _this.horizontalAxes);
                updateAxesPerPane(_this, _this.verticalAxes);
                _this._stripsGroup.append();
                _this._axesGroup.append();
                do {
                    for (i = 0; i < _this.horizontalAxes.length; i++)
                        _this.horizontalAxes[i].resetTicks();
                    for (i = 0; i < _this.verticalAxes.length; i++)
                        _this.verticalAxes[i].resetTicks();
                    if (_this.option('synchronizeMultiAxes'))
                        multiAxesSynchronizer.synchronize(rotated ? _this.horizontalAxes : _this.verticalAxes, rotated);
                    for (i = 0; i < _this.horizontalAxes.length; i++) {
                        _this.horizontalAxes[i].clipRectID = _this._getCanvasClipRectID();
                        _this.horizontalAxes[i].stripsGroup = _this._stripsGroup;
                        _this.horizontalAxes[i].axesContainerGroup = _this._axesGroup;
                        _this.horizontalAxes[i].draw({borderOptions: panesBorderOptions[_this.horizontalAxes[i].pane]})
                    }
                    layoutManager.requireAxesRedraw = false;
                    if (drawOptions.adjustAxes) {
                        layoutManager.applyHorizontalAxesLayout();
                        $.each(translators, function(_, translator) {
                            translator.init()
                        })
                    }
                    for (i = 0; i < _this.verticalAxes.length; i++) {
                        _this.verticalAxes[i].clipRectID = _this._getCanvasClipRectID();
                        _this.verticalAxes[i].stripsGroup = _this._stripsGroup;
                        _this.verticalAxes[i].axesContainerGroup = _this._axesGroup;
                        _this.verticalAxes[i].draw({borderOptions: panesBorderOptions[_this.verticalAxes[i].pane]})
                    }
                    if (drawOptions.adjustAxes) {
                        layoutManager.applyVerticalAxesLayout();
                        $.each(translators, function(_, translator) {
                            translator.init()
                        })
                    }
                    adjustmentCounter = adjustmentCounter + 1;
                    if (layoutManager.isCanvasExceeded(true)) {
                        _this.option('incidentOccured')('Container is too small to draw chart with current settings');
                        _this._clean();
                        _this.__axisAdjustmentsCount = adjustmentCounter;
                        return
                    }
                } while (layoutManager.requireAxesRedraw && adjustmentCounter < MAX_ADJUSTMENT_ATTEMPTS);
                _this.__axisAdjustmentsCount = adjustmentCounter;
                if (_this.chartTitle)
                    _this.chartTitle.setClipRectSettings();
                _this._drawPanesBorders(panesBorderOptions);
                _this._createClipRectsForPanes();
                for (i = 0; i < _this.horizontalAxes.length; i++)
                    _this.horizontalAxes[i].applyClipRectForStrips(_this._getElementsClipRectID(_this.horizontalAxes[i].pane));
                for (i = 0; i < _this.verticalAxes.length; i++)
                    _this.verticalAxes[i].applyClipRectForStrips(_this._getElementsClipRectID(_this.verticalAxes[i].pane));
                _this._fillPanesBackground();
                _this._seriesGroup.append();
                _this._labelsGroup.append();
                _this._tooltipGroup.append();
                if (drawOptions.asyncSeriesRendering)
                    _this.delayedRedraw = setTimeout(drawSeries, 25);
                else
                    drawSeries()
            },
            _isInBarTypes: function(type) {
                return type.slice(-3) === 'bar' ? true : false
            },
            _setPanesClipRectPadding: function(panesBorderOptions, rotated) {
                var _this = this,
                    allPanesHaveBorder = true,
                    firstPaneHasBorder = panesBorderOptions[_this.panes[0].name].visible,
                    lastPaneHasBorder = panesBorderOptions[_this.panes[_this.panes.length - 1].name].visible,
                    position = '';
                $.each(_this.panes, function(_, pane) {
                    allPanesHaveBorder = allPanesHaveBorder && !!panesBorderOptions[pane.name].visible
                });
                $.each(_this.horizontalAxes, function(_, axis) {
                    position += axis.options.position
                });
                $.each(_this.verticalAxes, function(_, axis) {
                    position += axis.options.position
                })
            },
            _createPanesBackground: function() {
                var _this = this,
                    defaultBackgroundColor = _this.option('commonPaneSettings').backgroundColor,
                    backgroundColor,
                    renderer = _this.renderer,
                    rect,
                    i,
                    rects = [];
                _this._panesBackgroundGroup && _this._panesBackgroundGroup.clear();
                for (i = 0; i < _this.panes.length; i++) {
                    backgroundColor = _this.panes[i].backgroundColor || defaultBackgroundColor;
                    if (!backgroundColor || backgroundColor === 'none') {
                        rects.push(null);
                        continue
                    }
                    rect = renderer.createRect(0, 0, 0, 0, 0, {
                        fill: backgroundColor,
                        strokeWidth: 0
                    }).append(_this._panesBackgroundGroup);
                    rects.push(rect)
                }
                _this.panesBackground = rects;
                _this._panesBackgroundGroup.append()
            },
            _fillPanesBackground: function() {
                var _this = this,
                    bc;
                $.each(_this.panes, function(i, pane) {
                    bc = pane.borderCoords;
                    if (_this.panesBackground[i] != null)
                        _this.panesBackground[i].applySettings({
                            x: bc.left,
                            y: bc.top,
                            width: bc.width,
                            height: bc.height
                        })
                })
            },
            _calcPaneBorderCoords: function(pane, rotated) {
                var canvas = pane.canvas,
                    bc = pane.borderCoords = pane.borderCoords || {};
                bc.left = canvas.left;
                bc.top = canvas.top;
                bc.right = canvas.width - canvas.right;
                bc.bottom = canvas.height - canvas.bottom;
                bc.width = bc.right - bc.left;
                bc.height = bc.bottom - bc.top
            },
            _drawPanesBorders: function(panesBorderOptions) {
                var _this = this,
                    rotated = _this.option('rotated');
                _this._panesBorderGroup && (_this._panesBorderGroup.detach(), _this._panesBorderGroup.clear());
                $.each(_this.panes, function(i, pane) {
                    var bc,
                        borderOptions = panesBorderOptions[pane.name],
                        attr = {
                            fill: 'none',
                            stroke: borderOptions.color,
                            strokeOpacity: borderOptions.opacity,
                            strokeWidth: borderOptions.width,
                            dashStyle: borderOptions.dashStyle
                        };
                    _this._calcPaneBorderCoords(pane, rotated);
                    if (!borderOptions.visible)
                        return;
                    bc = pane.borderCoords;
                    _this.renderer.createSegmentRect(bc.left, bc.top, bc.width, bc.height, 0, borderOptions, attr).append(_this._panesBorderGroup)
                });
                _this._panesBorderGroup.append()
            },
            _createClipRectsForPanes: function() {
                var _this = this;
                $.each(_this.panes, function(i, pane) {
                    var bc = pane.borderCoords,
                        clipRect = _this.panesClipRects[i];
                    if (!clipRect) {
                        clipRect = _this.renderer.createClipRect(bc.left, bc.top, bc.width, bc.height).append();
                        _this.panesClipRects.push(clipRect)
                    }
                    else
                        clipRect.updateRectangle({
                            x: bc.left,
                            y: bc.top,
                            width: bc.width,
                            height: bc.height
                        })
                })
            },
            _getPaneIndex: function(paneName) {
                var paneIndex;
                $.each(this.panes, function(index, pane) {
                    if (pane.name === paneName) {
                        paneIndex = index;
                        return false
                    }
                });
                return paneIndex
            },
            _getPaneBorderVisibility: function(paneIndex) {
                var commonPaneBorderVisible = this.option('commonPaneSettings').border.visible,
                    pane = this.panes[paneIndex] || {},
                    paneBorder = pane.border || {};
                return 'visible' in paneBorder ? paneBorder.visible : commonPaneBorderVisible
            },
            _getElementsClipRectID: function(paneName) {
                return this.panesClipRects[this._getPaneIndex(paneName)].id
            },
            _getMarkersClipRectID: function(paneName) {
                var _this = this,
                    paneIndex = _this._getPaneIndex(paneName),
                    borderVisible = _this._getPaneBorderVisibility(paneIndex);
                if (borderVisible)
                    return _this._getElementsClipRectID(paneName);
                else
                    return undefined
            },
            _getTranslator: function(paneName, axisName) {
                var translators = this.translators,
                    translatorsNumber = translators.length,
                    foundTranslator = null,
                    i;
                for (i = 0; i < translatorsNumber; i++)
                    if (translators[i].pane === paneName && translators[i].axis === axisName) {
                        foundTranslator = translators[i];
                        break
                    }
                if (!foundTranslator)
                    for (i = 0; i < translatorsNumber; i++)
                        if (translators[i].pane === paneName) {
                            foundTranslator = translators[i];
                            break
                        }
                return foundTranslator
            },
            _getCanvasForPane: function(paneName) {
                var panes = this.panes,
                    panesNumber = panes.length,
                    i;
                for (i = 0; i < panesNumber; i++)
                    if (panes[i].name === paneName)
                        return panes[i].canvas
            },
            _getBusinessRange: function(paneName, axisName) {
                var ranges = this.businessRanges || [],
                    rangesNumber = ranges.length,
                    foundRange,
                    i;
                for (i = 0; i < rangesNumber; i++)
                    if (ranges[i].pane === paneName && ranges[i].axis === axisName) {
                        foundRange = ranges[i];
                        break
                    }
                if (!foundRange)
                    for (i = 0; i < rangesNumber; i++)
                        if (ranges[i].pane === paneName) {
                            foundRange = ranges[i];
                            break
                        }
                return foundRange
            },
            _handleSeriesPopulated: function(needRedraw) {
                var _this = this;
                _this._processSeriesFamilies();
                _this._createLegend();
                _this._populateBusinessRange();
                _this._processValueAxisFormat();
                _this._updateTracker();
                needRedraw && _this._render({force: true})
            },
            _processValueAxisFormat: function() {
                var _this = this,
                    valueAxes = _this.option('rotated') ? _this.horizontalAxes : _this.verticalAxes,
                    axesWithFullStackedFormat = [];
                $.each(_this.series, function() {
                    if (this.isFullStackedSeries() && $.inArray(this.axis, axesWithFullStackedFormat) === -1)
                        axesWithFullStackedFormat.push(this.axis)
                });
                $.each(valueAxes, function() {
                    if ($.inArray(this.name, axesWithFullStackedFormat) !== -1)
                        this.setPercentLabelFormat()
                })
            },
            zoomArgument: function(min, max) {
                var _this = this;
                if (_this.option('adjustOnZoom'))
                    _this._populateBusinessRange({
                        minArg: min,
                        maxArg: max
                    });
                $.each(_this.paneAxis, function(paneName, pane) {
                    $.each(pane, function(axisName, _) {
                        var translator = _this._getTranslator(paneName, axisName);
                        var range = _this._getBusinessRange(paneName, axisName);
                        translator.updateBusinessRange(range);
                        if (min || max) {
                            if (_this._options.rotated)
                                translator.zoomY(min, max);
                            else
                                translator.zoomX(min, max);
                            translator.init()
                        }
                    })
                });
                _this._render({
                    force: true,
                    drawTitle: false,
                    drawLegend: false,
                    adjustAxes: false,
                    animate: false,
                    adjustSeriesLabels: false,
                    asyncSeriesRendering: false
                })
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file pieChart.js */
    (function($, DX, undefined) {
        var charts = DX.viz.charts,
            utils = DX.utils,
            PANE_CLIP_RECT_PADDING = 12;
        charts.PieChart = charts.BaseChart.inherit({
            _defaultOptions: function() {
                return $.extend(true, this.callBase(), {
                        commonSeriesSettings: {
                            type: 'pie',
                            pie: {label: {percentPrecision: 0}}
                        },
                        legend: {hoverMode: 'markPoint'}
                    })
            },
            _reinit: function(needRedraw) {
                var _this = this;
                _this.callBase();
                if (!_this.series)
                    _this._dataSpecificInit();
                needRedraw && _this._render({force: true})
            },
            _populateBusinessRange: function() {
                var businessRanges = [],
                    series = this.series,
                    singleSeries = series[0],
                    range,
                    singleSeriesRange;
                this._disposeObjectsInArray("businessRanges");
                if (singleSeries) {
                    range = new charts.Range({series: singleSeries});
                    singleSeriesRange = singleSeries.getRangeData();
                    range = range.getBoundRange(singleSeriesRange);
                    if (!range.isDefined())
                        range.setStubData();
                    businessRanges.push(range)
                }
                this.businessRanges = businessRanges
            },
            _createTranslator: function(range, canvas) {
                return new DevExpress.viz.core.Translator1D(range.minY, range.maxY, 360 - 0.0001, 0)
            },
            _populateSeries: function() {
                var _this = this,
                    renderer = _this.renderer,
                    hasSeriesTemplate = !!_this.option('seriesTemplate'),
                    seriesOptions = hasSeriesTemplate ? _this._templatedSeries : _this.option('series'),
                    allSeriesOptions = $.isArray(seriesOptions) ? seriesOptions : seriesOptions ? [seriesOptions] : [],
                    themeManager = _this.themeManager,
                    data,
                    particularSeriesOptions,
                    particularSeries,
                    seriesTheme,
                    seriesType,
                    commonSeriesSettings = _this.option('commonSeriesSettings'),
                    userCommonSeriesSettings = _this._userOptions.commonSeriesSettings,
                    incidentOccured = _this.option('incidentOccured');
                _this._disposeSeries();
                _this.series = [];
                themeManager.resetPalette();
                if (allSeriesOptions.length) {
                    particularSeriesOptions = allSeriesOptions[0];
                    if (particularSeriesOptions.type && !utils.isString(particularSeriesOptions.type))
                        particularSeriesOptions.type = '';
                    data = particularSeriesOptions.data;
                    particularSeriesOptions.data = null;
                    particularSeriesOptions.incidentOccured = incidentOccured;
                    seriesTheme = themeManager.applyPieSeriesTheme(particularSeriesOptions, commonSeriesSettings, userCommonSeriesSettings);
                    seriesTheme.seriesGroup = _this._seriesGroup;
                    seriesTheme.trackerGroup = _this._trackerGroup;
                    seriesTheme.seriesLabelsGroup = _this._labelsGroup;
                    seriesTheme.seriesTrackerGroup = _this._seriesTrackerGroup;
                    seriesTheme.markerTrackerGroup = _this._markerTrackerGroup;
                    seriesType = seriesTheme.type !== undefined ? seriesTheme.type : _this.option('commonSeriesSettings').type;
                    particularSeries = charts.factory.createSeries(seriesType, renderer, data, seriesTheme);
                    if (!particularSeries)
                        incidentOccured.call(null, 'Unknown series type requested: ' + seriesType);
                    else {
                        _this._processSingleSeries(particularSeries, particularSeries.userOptions);
                        _this.series.push(particularSeries)
                    }
                    particularSeriesOptions.data = data
                }
                return _this.series
            },
            _processSingleSeries: function(singleSeries, options) {
                var _this = this,
                    commonSeriesSettings = _this.option('commonSeriesSettings'),
                    points,
                    seriesGroup = options.seriesGroup,
                    trackerGroup = options.trackerGroup,
                    seriesTrackerGroup = options.seriesTrackerGroup,
                    markerTrackerGroup = options.markerTrackerGroup,
                    seriesLabelsGroup = options.seriesLabelsGroup;
                singleSeries.arrangePoints();
                points = singleSeries && singleSeries.getPoints() || [];
                options.seriesGroup = null;
                options.trackerGroup = null;
                options.seriesTrackerGroup = null;
                options.markerTrackerGroup = null;
                options.seriesLabelsGroup = null;
                for (var j = 0; j < points.length; j++) {
                    var theme = _this.themeManager.applyNextPieSegmentTheme(options, commonSeriesSettings);
                    var convertedTheme = singleSeries.parseStyleOptions(theme);
                    points[j].setOptions(convertedTheme.point);
                    points[j].index = j
                }
                options.seriesGroup = seriesGroup;
                options.trackerGroup = trackerGroup;
                options.seriesTrackerGroup = seriesTrackerGroup;
                options.markerTrackerGroup = markerTrackerGroup;
                options.seriesLabelsGroup = seriesLabelsGroup
            },
            _handleSeriesPopulated: function(needRedraw) {
                var _this = this;
                _this._populateBusinessRange();
                _this._createLegend();
                _this._updateTracker();
                needRedraw && _this._render({
                    force: true,
                    recreateCanvas: true
                })
            },
            _createLegend: function() {
                var _this = this,
                    legendOptions = $.extend(true, {
                        renderer: _this.renderer,
                        series: $.map(_this.series[0] ? _this.series[0].getPoints() : [], function(item) {
                            item.name = item.argument;
                            item.options.showInLegend = true,
                            item.styles = {themeColor: item.options.attributes.fill};
                            return item
                        })
                    }, _this.option('legend'));
                if (legendOptions.position !== 'outside')
                    legendOptions.position = 'outside';
                _this.legend = charts.factory.createLegend(legendOptions, _this._legendGroup, _this._legendTrackerGroup)
            },
            _setPaddings: function(side) {
                var _this = this,
                    originalSide = 'original' + side,
                    sideLowCase = side.toLowerCase(),
                    delta = PANE_CLIP_RECT_PADDING - _this.canvas[sideLowCase];
                if (delta > 0) {
                    _this.canvas[originalSide] += delta;
                    _this.canvas[sideLowCase] += delta
                }
            },
            _render: function(drawOptions) {
                var _this = this,
                    titleOptions = _this.option('title'),
                    layoutManager = _this.layoutManager;
                drawOptions = _this._prepareDrawOptions(drawOptions);
                _this.callBase(drawOptions);
                if (_this.stopRedraw) {
                    _this.stopRedraw = false;
                    return
                }
                if (titleOptions.text && drawOptions.drawTitle) {
                    _this._titleGroup.append();
                    _this._drawTitle();
                    layoutManager.applyTitleLayout()
                }
                if (drawOptions.drawLegend && _this.legend) {
                    _this.legend.canvas = _this.canvas;
                    _this._legendGroup.append();
                    _this.legend.draw();
                    layoutManager.applyLegendLayout()
                }
                if (layoutManager.isCanvasExceeded(false)) {
                    _this.option('incidentOccured')('Container is too small to draw chart with current settings');
                    _this._clean();
                    return
                }
                if (_this.chartTitle)
                    _this.chartTitle.setClipRectSettings();
                _this._setPaddings('Bottom');
                _this._setPaddings('Top');
                _this._setPaddings('Left');
                _this._setPaddings('Right');
                if (_this.series && _this.series[0]) {
                    if (!layoutManager.applyPieChartSeriesLayout()) {
                        _this.option('incidentOccured')('Container is too small to draw chart with current settings');
                        _this._clean();
                        return
                    }
                    _this._seriesGroup.append();
                    _this._labelsGroup.append();
                    _this.series[0].canvas = _this.canvas;
                    _this.series[0].draw(_this._createTranslator(_this.businessRanges[0], _this.canvas));
                    if (_this.series[0].redraw) {
                        _this._seriesGroup.detach();
                        _this._trackerGroup.detach();
                        _this._labelsGroup.detach();
                        _this._seriesGroup.clear();
                        _this._labelsGroup.clear();
                        _this._seriesGroup.append();
                        _this._labelsGroup.append();
                        layoutManager.applyPieChartSeriesLayout();
                        _this.series[0].draw(_this._createTranslator(_this.businessRanges[0], _this.canvas))
                    }
                    _this.series[0].animate();
                    _this._tooltipGroup.append();
                    _this._trackerGroup.append();
                    _this._createTooltip();
                    _this.series[0].drawTrackers();
                    _this.tracker._prepare('pieChart')
                }
                _this._handleRenderComplete()
            },
            getSeries: function getSeries() {
                return this.series && this.series[0]
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file themeManager.js */
    (function($, DX, undefined) {
        var viz = DX.viz,
            Palette = viz.core.Palette,
            isArray = DX.utils.isArray;
        var BORDER_COLOR_HIGHLIGHTING = 120,
            HOVER_COLOR_HIGHLIGHTING = 20,
            HOVER_BORDER_COLOR_HIGHLIGHTING = 20,
            POINT_DARKENING = 20,
            POINT_BORDER_DARKENING = 30,
            POINT_HOVER_BORDER_DARKENING = 20,
            HIGHLIGHTING_STEP = 50;
        viz.charts.ThemeManager = viz.core.BaseThemeManager.inherit(function() {
            var ctor = function(options, themeGroupName) {
                    var _this = this;
                    options = options || {};
                    _this.callBase(options.theme, themeGroupName || 'chart');
                    _this.palette = new Palette(options.palette || _this.theme.defaultPalette, HIGHLIGHTING_STEP);
                    _this.init()
                };
            var dispose = function() {
                    this.palette.dispose();
                    this.palette = null;
                    this.callBase()
                };
            var init = function() {
                    var _this = this;
                    _this.theme.legend = _this.theme.legend || {};
                    _this.theme.legend.font = _this.theme.legend.font || {};
                    _this.initializeFont(_this.theme.legend.font);
                    initDefaultSeriesTheme(_this);
                    initAxisTheme(_this);
                    _this.theme.title = _this.theme.title || {};
                    _this.theme.title.font = _this.theme.title.font || {};
                    _this.initializeFont(_this.theme.title.font);
                    _this.theme.tooltip = _this.theme.tooltip || {};
                    _this.theme.tooltip.font = _this.theme.tooltip.font || {};
                    _this.initializeFont(_this.theme.tooltip.font)
                };
            var initDefaultSeriesTheme = function(self) {
                    var theme = self.theme,
                        commonSeriesSettings = theme.commonSeriesSettings,
                        fontOptions = theme.font,
                        pointTheme;
                    commonSeriesSettings.point = commonSeriesSettings.point || {};
                    commonSeriesSettings.containerBackgroundColor = commonSeriesSettings.containerBackgroundColor || theme.containerBackgroundColor;
                    commonSeriesSettings.label = commonSeriesSettings.label || {};
                    self.initializeFont(commonSeriesSettings.label.font)
                };
            var initAxisTheme = function(self) {
                    var theme = self.theme,
                        axisTheme = theme.commonAxisSettings,
                        fontOptions = theme.font,
                        titleTheme,
                        labelTheme;
                    if (axisTheme) {
                        axisTheme.label = axisTheme.label || {};
                        axisTheme.grid = axisTheme.grid || {};
                        axisTheme.ticks = axisTheme.ticks || {};
                        axisTheme.line = axisTheme.line || {};
                        axisTheme.title = axisTheme.title || {};
                        axisTheme.label.font = axisTheme.label.font || {};
                        self.initializeFont(axisTheme.label.font);
                        axisTheme.title.font = axisTheme.title.font || {};
                        self.initializeFont(axisTheme.title.font)
                    }
                };
            var applyChartTheme = function(userOptions) {
                    var self = this,
                        refs = {
                            dataSource: userOptions.dataSource,
                            series: userOptions.series
                        },
                        result;
                    delete userOptions.dataSource;
                    delete userOptions.series;
                    if (userOptions.valueAxis && isArray(userOptions.valueAxis) && !userOptions.valueAxis.length || $.isEmptyObject(userOptions.valueAxis))
                        delete userOptions.valueAxis;
                    if (userOptions.panes && isArray(userOptions.panes) && !userOptions.panes.length || $.isEmptyObject(userOptions.panes))
                        delete userOptions.panes;
                    result = self.applyTheme(self.theme, userOptions);
                    result.dataSource = refs.dataSource;
                    result.series = refs.series;
                    userOptions.series = refs.series;
                    return result
                };
            var applyNextSeriesTheme = function(userOptions, commonSeriesSettings, userCommonSeriesSettings) {
                    var debug = DX.utils.debug;
                    debug.assertParam(userOptions, 'User options were not passed');
                    if (commonSeriesSettings) {
                        debug.assertParam(commonSeriesSettings.hoverStyle, 'hoverStyle option was not passed');
                        debug.assertParam(commonSeriesSettings.selectionStyle, 'selectionStyle option was not passed');
                        debug.assertParam(commonSeriesSettings.point, 'point option was not passed');
                        debug.assertParam(commonSeriesSettings.point.hoverStyle, 'point.hoverStyle option was not passed');
                        debug.assertParam(commonSeriesSettings.point.selectionStyle, 'point.selectionStyle option was not passed')
                    }
                    var self = this,
                        mergedSettings = $.extend(true, {}, commonSeriesSettings || self.theme.commonSeriesSettings),
                        mergedUserSettings = $.extend(true, {}, userCommonSeriesSettings || {}),
                        seriesType = ((userOptions.type || mergedSettings.type || '') + '').toLowerCase(),
                        isAreaOrBar = ~seriesType.indexOf('area') || ~seriesType.indexOf('bar');
                    mergedUserSettings = $.extend(true, mergedUserSettings, mergedUserSettings[seriesType]);
                    mergedSettings = $.extend(true, mergedSettings, mergedSettings[seriesType], mergedUserSettings);
                    userOptions = userOptions || {};
                    var mainColor = new DX.Color(userOptions.color || mergedUserSettings.color || self.palette.getNextColor());
                    mergedSettings.color = mainColor.toHex();
                    mergedSettings.border.color = mergedSettings.border.color || mainColor.toHex();
                    mergedSettings.hoverStyle.color = mergedSettings.hoverStyle.color || isAreaOrBar && mainColor.highlight(HOVER_COLOR_HIGHLIGHTING) || mainColor.toHex();
                    mergedSettings.hoverStyle.border.color = mergedSettings.hoverStyle.border.color || mainColor.toHex();
                    mergedSettings.selectionStyle.color = mergedSettings.selectionStyle.color || isAreaOrBar && mainColor.highlight(HOVER_COLOR_HIGHLIGHTING) || mainColor.toHex();
                    mergedSettings.selectionStyle.border.color = mergedSettings.selectionStyle.border.color || mainColor.toHex();
                    mergedSettings.point.color = mergedSettings.point.color || mainColor.toHex();
                    mergedSettings.point.border.color = mergedSettings.point.border.color || mainColor.toHex();
                    mergedSettings.point.hoverStyle.color = mergedSettings.point.hoverStyle.color || mergedSettings.containerBackgroundColor;
                    mergedSettings.point.hoverStyle.border.color = mergedSettings.point.hoverStyle.border.color || mainColor.toHex();
                    mergedSettings.point.selectionStyle.color = mergedSettings.point.selectionStyle.color || mergedSettings.containerBackgroundColor;
                    mergedSettings.point.selectionStyle.border.color = mergedSettings.point.selectionStyle.border.color || mainColor.toHex();
                    return self.applyTheme(mergedSettings, userOptions)
                };
            var applyPieSeriesTheme = function applyPieSeriesTheme(userOptions, commonSeriesSettings, userCommonSeriesSettings) {
                    var self = this,
                        commonSettings = commonSeriesSettings || self.theme.commonSeriesSettings || {},
                        seriesType = (userOptions.type || commonSettings.type || '').toLowerCase();
                    if (seriesType && seriesType !== 'pie')
                        commonSettings[seriesType] = $.extend(true, {}, commonSettings[seriesType], commonSettings.pie);
                    userCommonSeriesSettings = userCommonSeriesSettings || {};
                    userOptions = userOptions || {};
                    userOptions = $.extend(true, {}, commonSettings, commonSettings[seriesType], userCommonSeriesSettings, userCommonSeriesSettings[seriesType], userOptions);
                    return userOptions
                };
            var applyNextPieSegmentTheme = function applyNextPieSegmentTheme(userOptions, commonSeriesSettings) {
                    var self = this,
                        commonSettings = commonSeriesSettings || self.theme.commonSeriesSettings || {},
                        mergedSettings = $.extend(true, {}, commonSettings.pie),
                        seriesType = userOptions.type || mergedSettings.type || '';
                    userOptions = userOptions || {};
                    var mainColor = new DX.Color(userOptions.color || self.palette.getNextColor());
                    mergedSettings.color = mainColor.toHex();
                    mergedSettings.border.color = mergedSettings.border.color || mainColor.toHex();
                    mergedSettings.hoverStyle.color = mergedSettings.hoverStyle.color || mainColor.highlight(20);
                    mergedSettings.hoverStyle.border.color = mergedSettings.hoverStyle.border.color || mainColor.toHex();
                    mergedSettings.selectionStyle.color = mergedSettings.selectionStyle.color || mainColor.highlight(20);
                    mergedSettings.selectionStyle.border.color = mergedSettings.selectionStyle.border.color || mainColor.toHex();
                    return self.applyTheme(mergedSettings, userOptions)
                };
            var resetPalette = function() {
                    this.palette.reset()
                };
            var updatePalette = function(palette) {
                    this.palette = new Palette(palette || this.theme.defaultPalette, HIGHLIGHTING_STEP)
                };
            return {
                    ctor: ctor,
                    dispose: dispose,
                    init: init,
                    applyChartTheme: applyChartTheme,
                    applyNextSeriesTheme: applyNextSeriesTheme,
                    applyPieSeriesTheme: applyPieSeriesTheme,
                    applyNextPieSegmentTheme: applyNextPieSegmentTheme,
                    resetPalette: resetPalette,
                    updatePalette: updatePalette
                }
        }())
    })(jQuery, DevExpress);
    /*! Module viz, file layoutManager.js */
    (function($, DX, undefined) {
        var isNumber = DX.utils.isNumber,
            round = Math.round;
        DX.viz.charts.LayoutManager = DX.Class.inherit(function() {
            var update = function(chart) {
                    this.chart = chart;
                    setCanvasValues(chart && chart.canvas)
                };
            var dispose = function() {
                    this.chart = null
                };
            var setCanvasValues = function(canvas) {
                    if (canvas) {
                        canvas.originalTop = canvas.top;
                        canvas.originalBottom = canvas.bottom;
                        canvas.originalLeft = canvas.left;
                        canvas.originalRight = canvas.right
                    }
                };
            var createPanesCanvases = function() {
                    var debug = DX.utils.debug;
                    $.each(this.chart.panes, function(i, item) {
                        debug.assert(item, 'pane is null object');
                        debug.assert(item.name, 'Pane does not have name')
                    });
                    var chart = this.chart,
                        canvas = chart.canvas,
                        panes = chart.panes,
                        pane,
                        i,
                        panesNumber = panes.length,
                        paneSpaceHeight = canvas.height - canvas.top - canvas.bottom,
                        paneSpaceWidth = canvas.width - canvas.left - canvas.right,
                        weightSum = 0,
                        oneWeightHeight,
                        oneWeightWidth,
                        padding = panes.padding || 10,
                        distributedTopSpace = 0,
                        distributedLeftSpace = 0;
                    for (i = 0; i < panesNumber; i++) {
                        pane = panes[i];
                        pane.weight = pane.weight || 1;
                        weightSum = weightSum + pane.weight
                    }
                    oneWeightHeight = (paneSpaceHeight - padding * (panesNumber - 1)) / weightSum;
                    oneWeightWidth = (paneSpaceWidth - padding * (panesNumber - 1)) / weightSum;
                    if (!chart.option('rotated'))
                        for (i = 0; i < panesNumber; i++) {
                            pane = panes[i];
                            pane.calcHeight = round(pane.weight * oneWeightHeight);
                            pane.canvas = $.extend({}, canvas);
                            pane.canvas.top = pane.canvas.originalTop = canvas.top + distributedTopSpace;
                            pane.canvas.bottom = pane.canvas.originalBottom = canvas.bottom + (paneSpaceHeight - pane.calcHeight - distributedTopSpace);
                            distributedTopSpace = distributedTopSpace + pane.calcHeight + padding
                        }
                    else
                        for (i = 0; i < panesNumber; i++) {
                            pane = panes[i];
                            pane.calcWidth = round(pane.weight * oneWeightWidth);
                            pane.canvas = $.extend({}, canvas);
                            pane.canvas.left = pane.canvas.originalLeft = canvas.left + distributedLeftSpace;
                            pane.canvas.right = pane.canvas.originalRight = canvas.right + (paneSpaceWidth - pane.calcWidth - distributedLeftSpace);
                            distributedLeftSpace = distributedLeftSpace + pane.calcWidth + padding
                        }
                };
            var applyTitleLayout = function() {
                    var chart = this.chart,
                        canvas = chart.canvas,
                        title = chart.chartTitle,
                        box,
                        horizontalPadding = 15,
                        verticalPadding = 10,
                        shiftX,
                        shiftY;
                    if (!title)
                        return;
                    box = title.getBoundingRect();
                    switch (title.horizontalAlignment) {
                        case'left':
                            shiftX = round(horizontalPadding + canvas.left);
                            break;
                        case'center':
                            shiftX = round((canvas.width - canvas.left - canvas.right - box.width) / 2 + canvas.left) - box.x;
                            break;
                        case'right':
                            shiftX = round(canvas.width - canvas.right - box.x - box.width - horizontalPadding);
                            break
                    }
                    if (title.verticalAlignment === 'top') {
                        shiftY = round(canvas.top - box.y);
                        canvas.top = canvas.top + box.height + verticalPadding
                    }
                    else {
                        shiftY = round(canvas.height - canvas.bottom - box.height - box.y);
                        canvas.bottom = canvas.bottom + box.height + verticalPadding
                    }
                    title.shift(shiftX, shiftY);
                    setCanvasValues(canvas)
                };
            var adjustTitleLayout = function adjustTitleLayout() {
                    var chart = this.chart,
                        canvas = chart.canvas,
                        title = chart.chartTitle,
                        horizontalPadding = 15,
                        box,
                        shiftX,
                        shiftY = title.innerTitleGroup.settings.translateY || 0;
                    title.canvas = canvas;
                    title.correctTitleLength();
                    box = title.getBoundingRect();
                    switch (title.horizontalAlignment) {
                        case'left':
                            shiftX = round(horizontalPadding + canvas.left);
                            break;
                        case'center':
                            shiftX = round((canvas.width - canvas.right - canvas.left - box.width) / 2 + canvas.left - box.x);
                            break;
                        case'right':
                            shiftX = round(canvas.width - canvas.right - box.x - box.width - horizontalPadding);
                            break
                    }
                    title.shift(shiftX, shiftY)
                };
            var applyLegendLayout = function applyLegendLayout() {
                    var _this = this,
                        chart = _this.chart,
                        canvas = chart.canvas,
                        legend = chart.legend,
                        title = chart.chartTitle,
                        panes = chart.panes,
                        options = legend.options,
                        rect = legend.getBoundingRect(),
                        verticalPadding = 10,
                        horizontalPadding = 10,
                        shiftX,
                        shiftY;
                    if (!options.visible)
                        return;
                    if (!isNumber(rect.width) || !isNumber(rect.height))
                        return;
                    if (options.position === 'outside') {
                        switch (options.horizontalAlignment) {
                            case'left':
                                shiftX = round(canvas.left - rect.x + horizontalPadding);
                                canvas.left = canvas.left + rect.width + options.margin + horizontalPadding;
                                if (title)
                                    _this.adjustTitleLayout();
                                break;
                            case'center':
                                shiftX = round((canvas.width - canvas.left - canvas.right - rect.width) / 2 + canvas.left - rect.x);
                                break;
                            case'right':
                                shiftX = round(canvas.width - canvas.right - rect.width - rect.x - horizontalPadding);
                                canvas.right = canvas.right + rect.width + options.margin + horizontalPadding;
                                if (title)
                                    _this.adjustTitleLayout();
                                break
                        }
                        switch (options.verticalAlignment) {
                            case'top':
                                shiftY = round(verticalPadding + canvas.top - rect.y);
                                if (options.horizontalAlignment === 'center')
                                    canvas.top = canvas.top + rect.height + options.margin + verticalPadding;
                                break;
                            case'bottom':
                                shiftY = round(canvas.height - rect.height - canvas.bottom - verticalPadding - rect.y);
                                if (options.horizontalAlignment === 'center')
                                    canvas.bottom = canvas.bottom + rect.height + options.margin + verticalPadding;
                                break
                        }
                        legend.shift(shiftX, shiftY);
                        setCanvasValues(canvas)
                    }
                    else {
                        canvas = $.extend(true, {}, panes[0].canvas);
                        canvas.bottom = panes[panes.length - 1].canvas.bottom;
                        canvas.right = panes[panes.length - 1].canvas.right;
                        switch (options.horizontalAlignment) {
                            case'left':
                                shiftX = round(canvas.left - rect.x + options.margin);
                                break;
                            case'center':
                                shiftX = round((canvas.width - canvas.left - canvas.right - rect.width) / 2 + canvas.left - rect.x);
                                break;
                            case'right':
                                shiftX = round(canvas.width - canvas.right - rect.width - rect.x - options.margin);
                                break
                        }
                        switch (options.verticalAlignment) {
                            case'top':
                                shiftY = round(canvas.top - rect.y + options.margin);
                                break;
                            case'bottom':
                                shiftY = round(canvas.height - rect.height - canvas.bottom - options.margin - rect.y);
                                break
                        }
                        legend.shift(shiftX, shiftY)
                    }
                };
            var applyPieChartSeriesLayout = function() {
                    var chart = this.chart,
                        canvas = chart.canvas,
                        singleSeries = chart.series[0] || {},
                        paneSpaceHeight = canvas.height - canvas.top - canvas.bottom,
                        paneSpaceWidth = canvas.width - canvas.left - canvas.right,
                        min = paneSpaceWidth < paneSpaceHeight ? paneSpaceWidth : paneSpaceHeight,
                        accessibleRadius,
                        outerRadius = singleSeries.outerRadius,
                        innerRadius = singleSeries.type === 'pie' ? 0 : singleSeries.innerRadius || 0;
                    if (!(singleSeries && singleSeries.correctPosition))
                        return;
                    if (singleSeries.type !== 'pie')
                        if (!isNumber(innerRadius))
                            innerRadius = 0.5;
                        else {
                            innerRadius = Number(innerRadius);
                            if (innerRadius < 0.2)
                                innerRadius = 0.2;
                            if (innerRadius > 0.8)
                                innerRadius = 0.8
                        }
                    if (min < singleSeries.labelSpace)
                        return false;
                    accessibleRadius = outerRadius || (min - singleSeries.labelSpace - singleSeries.hoverSpace) / 2;
                    singleSeries.correctPosition({
                        centerX: round(paneSpaceWidth / 2 + canvas.left),
                        centerY: round(paneSpaceHeight / 2 + canvas.top),
                        radiusInner: round(accessibleRadius * innerRadius),
                        radiusOuter: round(accessibleRadius)
                    });
                    return true
                };
            var isValidBox = function isValidBox(box) {
                    return !!(box.x || box.y || box.width || box.height)
                };
            var correctDeltaMarginValue = function(panes, canvasesGrid, marginSides) {
                    var axisPanePosition,
                        canvasCell,
                        canvas,
                        deltaSide,
                        requireAxesRedraw;
                    $.each(panes, function(_, pane) {
                        axisPanePosition = getPanePosition(canvasesGrid, pane.name);
                        canvasCell = canvasesGrid[axisPanePosition.row][axisPanePosition.col];
                        canvas = canvasCell.canvas;
                        $.each(marginSides, function(_, side) {
                            deltaSide = 'delta' + side;
                            canvasCell[deltaSide] = Math.max(canvasCell[deltaSide] - (canvas[side.toLowerCase()] - canvas['original' + side]), 0);
                            if (canvasCell[deltaSide] > 0)
                                requireAxesRedraw = true
                        })
                    });
                    return requireAxesRedraw
                };
            var applyVerticalAxesLayout = function() {
                    var _this = this,
                        chart = _this.chart,
                        axes = chart.verticalAxes,
                        canvas,
                        axisPanePosition,
                        axisPosition,
                        canvasesGrid,
                        canvasCell,
                        box,
                        delta,
                        axis,
                        axisWidth,
                        commonAxisWidht = 0,
                        direction,
                        directionMultiplier,
                        i;
                    canvasesGrid = distributeCanvases(_this, chart.panes);
                    for (i = 0; i < axes.length; i++) {
                        axis = axes[i];
                        axisPosition = axis.options.position || 'left';
                        axis.delta = {};
                        box = axis.getBoundingRect();
                        if (!isValidBox(box))
                            continue;
                        axisPanePosition = getPanePosition(canvasesGrid, axes[i].pane);
                        canvasCell = canvasesGrid[axisPanePosition.row][axisPanePosition.col];
                        canvas = canvasCell.canvas;
                        if (axisPosition == 'right') {
                            direction = 'deltaRight';
                            directionMultiplier = 1
                        }
                        else {
                            direction = 'deltaLeft';
                            directionMultiplier = -1
                        }
                        axisWidth = box.width;
                        if (!axis.delta[axisPosition] && canvasCell[direction] > 0)
                            canvasCell[direction] += axes[i].getMultipleAxesSpacing();
                        axes[i].delta[axisPosition] = axes[i].delta[axisPosition] || 0;
                        axes[i].delta[axisPosition] += canvasCell[direction] * directionMultiplier;
                        canvasCell[direction] += axisWidth;
                        delta = box.y + box.height - (canvas.height - canvas.originalBottom);
                        if (delta > 0) {
                            _this.requireAxesRedraw = true;
                            canvasCell.deltaBottom += delta
                        }
                        delta = canvas.originalTop - box.y;
                        if (delta > 0) {
                            _this.requireAxesRedraw = true;
                            canvasCell.deltaTop += delta
                        }
                    }
                    _this.requireAxesRedraw = correctDeltaMarginValue(chart.panes, canvasesGrid, ['Left', 'Right']) || _this.requireAxesRedraw;
                    applyFoundExceedings(canvasesGrid)
                };
            var applyHorizontalAxesLayout = function() {
                    var _this = this,
                        chart = _this.chart,
                        panes = chart.panes,
                        axes = chart.horizontalAxes,
                        canvas,
                        axisPanePosition,
                        canvasesGrid,
                        canvasCell,
                        box,
                        delta,
                        axis,
                        axisHeight,
                        direction,
                        directionMultiplier,
                        axisPosition,
                        i;
                    canvasesGrid = distributeCanvases(_this, panes);
                    for (i = axes.length - 1; i >= 0; i--) {
                        axis = axes[i];
                        axisPosition = axis.options.position || 'bottom';
                        axes[i].delta = {};
                        box = axes[i].getBoundingRect();
                        if (!isValidBox(box))
                            continue;
                        axisPanePosition = getPanePosition(canvasesGrid, axes[i].pane);
                        canvasCell = canvasesGrid[axisPanePosition.row][axisPanePosition.col];
                        canvas = canvasCell.canvas;
                        if (axisPosition == 'top') {
                            direction = 'deltaTop';
                            directionMultiplier = -1
                        }
                        else {
                            direction = 'deltaBottom';
                            directionMultiplier = 1
                        }
                        axisHeight = box.height;
                        if (!axis.delta[axisPosition] && canvasCell[direction] > 0)
                            canvasCell[direction] += axes[i].getMultipleAxesSpacing();
                        axes[i].delta[axisPosition] = axes[i].delta[axisPosition] || 0;
                        axes[i].delta[axisPosition] += canvasCell[direction] * directionMultiplier;
                        canvasCell[direction] += axisHeight;
                        delta = canvas.originalLeft - box.x;
                        if (delta > 0) {
                            _this.requireAxesRedraw = true;
                            canvasCell.deltaLeft += delta
                        }
                        delta = box.x + box.width - (canvas.width - canvas.originalRight);
                        if (delta > 0) {
                            _this.requireAxesRedraw = true;
                            canvasCell.deltaRight = delta
                        }
                    }
                    _this.requireAxesRedraw = correctDeltaMarginValue(panes, canvasesGrid, ['Bottom', 'Top']) || _this.requireAxesRedraw;
                    applyFoundExceedings(canvasesGrid)
                };
            var distributeCanvases = function distributeCanvases(_this, panes) {
                    var panesLength = panes.length,
                        i,
                        j,
                        canvasesGrid = [],
                        canvasesRow = [],
                        rotated = _this.chart.option('rotated');
                    for (i = 0; i < panesLength; i++) {
                        if (!rotated)
                            canvasesRow = [];
                        canvasesRow.push({
                            canvas: panes[i].canvas,
                            pane: panes[i].name,
                            deltaLeft: 0,
                            deltaRight: 0,
                            deltaTop: 0,
                            deltaBottom: 0
                        });
                        !rotated && canvasesGrid.push(canvasesRow)
                    }
                    rotated && canvasesGrid.push(canvasesRow);
                    return canvasesGrid
                };
            var getPanePosition = function getPanePosition(canvasesGrid, pane) {
                    var row,
                        col;
                    for (row = 0; row < canvasesGrid.length; row++)
                        for (col = 0; col < canvasesGrid[row].length; col++)
                            if (canvasesGrid[row][col].pane === pane)
                                return {
                                        row: row,
                                        col: col
                                    }
                };
            var changeRowCanvas = function changeRowCanvas(canvasesGrid, row, callback) {
                    var col;
                    for (col = 0; col < canvasesGrid[row].length; col++)
                        callback(canvasesGrid[row][col].canvas)
                };
            var changeColumnCanvas = function changeRowCanvas(canvasesGrid, col, callback) {
                    var row;
                    for (row = 0; row < canvasesGrid.length; row++)
                        callback(canvasesGrid[row][col].canvas)
                };
            var applyFoundExceedings = function applyFoundExceedings(canvasesGrid) {
                    var col,
                        row,
                        canvasesRow,
                        maxLeft = 0,
                        maxRight = 0,
                        maxTop = 0,
                        maxBottom = 0,
                        maxColNumber = 0;
                    for (row = 0; row < canvasesGrid.length; row++) {
                        maxTop = 0;
                        maxBottom = 0;
                        canvasesRow = canvasesGrid[row];
                        if (canvasesRow.length > maxColNumber)
                            maxColNumber = canvasesRow.length;
                        for (col = 0; col < canvasesRow.length; col++) {
                            if (canvasesRow[col] && canvasesRow[col].deltaTop > maxTop)
                                maxTop = canvasesRow[col].deltaTop;
                            if (canvasesRow[col] && canvasesRow[col].deltaBottom > maxBottom)
                                maxBottom = canvasesRow[col].deltaBottom
                        }
                        if (maxTop)
                            changeRowCanvas(canvasesGrid, row, function(canvas) {
                                canvas.top += maxTop
                            });
                        if (maxBottom)
                            changeRowCanvas(canvasesGrid, row, function(canvas) {
                                canvas.bottom += maxBottom
                            })
                    }
                    for (col = 0; col < maxColNumber; col++) {
                        maxLeft = 0;
                        maxRight = 0;
                        for (row = 0; row < canvasesGrid.length; row++) {
                            canvasesRow = canvasesGrid[row];
                            if (canvasesRow[col] && canvasesRow[col].deltaLeft > maxLeft)
                                maxLeft = canvasesRow[col].deltaLeft;
                            if (canvasesRow[col] && canvasesRow[col].deltaRight > maxRight)
                                maxRight = canvasesRow[col].deltaRight
                        }
                        if (maxLeft)
                            changeColumnCanvas(canvasesGrid, col, function(canvas) {
                                canvas.left += maxLeft
                            });
                        if (maxRight)
                            changeColumnCanvas(canvasesGrid, col, function(canvas) {
                                canvas.right += maxRight
                            })
                    }
                };
            var isSingleCanvasExceeded = function isSingleCanvasExceeded(canvas) {
                    if (canvas.left > canvas.width - canvas.right || canvas.right > canvas.width - canvas.left || canvas.top > canvas.height - canvas.bottom || canvas.bottom > canvas.height - canvas.top)
                        return true
                };
            var isCanvasExceeded = function isCanvasExceeded(includePanes) {
                    var chart = this.chart,
                        paneCanvasesExceed = false;
                    if (isSingleCanvasExceeded(chart.canvas))
                        return true;
                    if (includePanes)
                        $.each(chart && chart.panes || {}, function(_, pane) {
                            if (pane.canvas && isSingleCanvasExceeded(pane.canvas)) {
                                paneCanvasesExceed = true;
                                return false
                            }
                        });
                    return paneCanvasesExceed
                };
            return {
                    update: update,
                    createPanesCanvases: createPanesCanvases,
                    applyLegendLayout: applyLegendLayout,
                    applyTitleLayout: applyTitleLayout,
                    adjustTitleLayout: adjustTitleLayout,
                    applyVerticalAxesLayout: applyVerticalAxesLayout,
                    applyHorizontalAxesLayout: applyHorizontalAxesLayout,
                    applyPieChartSeriesLayout: applyPieChartSeriesLayout,
                    isCanvasExceeded: isCanvasExceeded,
                    dispose: dispose
                }
        }())
    })(jQuery, DevExpress);
    /*! Module viz, file multiAxesSynchronizer.js */
    (function($, DX, undefined) {
        var charts = DX.viz.charts,
            utils = DX.utils;
        charts.MultiAxesSynchronizer = DX.Class.inherit(function() {
            var getValueAxesPerPanes = function(valueAxes) {
                    var result = {};
                    $.each(valueAxes, function() {
                        if (!result[this.pane])
                            result[this.pane] = [];
                        result[this.pane].push(this)
                    });
                    return result
                };
            var restoreOriginalBusinessRange = function(axis) {
                    var businessRange;
                    if (!axis.translator._originalBusinessRange)
                        axis.translator._originalBusinessRange = new charts.Range(axis.translator.getBusinessRange());
                    else {
                        businessRange = new charts.Range(axis.translator._originalBusinessRange);
                        axis.translator.updateBusinessRange(businessRange);
                        axis.setRange(businessRange)
                    }
                };
            var populateAxesInfo = function(axes, rotated) {
                    var axesInfo = [];
                    $.each(axes, function() {
                        var tickValues,
                            minValue,
                            maxValue,
                            inverted,
                            axisInfo,
                            businessRange,
                            stubData = rotated && 'stubDataX' || 'stubDataY';
                        restoreOriginalBusinessRange(this);
                        tickValues = this.getTickValues();
                        if (tickValues && tickValues.length > 0 && utils.isNumber(tickValues[0]) && this.options.type !== 'discrete') {
                            businessRange = this.translator.getBusinessRange();
                            minValue = rotated ? businessRange.minVisibleX : businessRange.minVisibleY;
                            maxValue = rotated ? businessRange.maxVisibleX : businessRange.maxVisibleY;
                            inverted = rotated ? businessRange.invertX : businessRange.invertY;
                            axisInfo = {
                                axis: this,
                                tickValues: tickValues,
                                minValue: minValue,
                                oldMinValue: minValue,
                                maxValue: maxValue,
                                oldMaxValue: maxValue,
                                inverted: inverted,
                                synchronizedValue: this.options.synchronizedValue
                            };
                            if (businessRange[stubData]) {
                                axisInfo.stubData = true;
                                axisInfo.tickInterval = axisInfo.axis.options.tickInterval
                            }
                            if (!axisInfo.tickInterval && tickValues.length > 1)
                                axisInfo.tickInterval = tickValues[1] - tickValues[0];
                            axesInfo.push(axisInfo)
                        }
                    });
                    return axesInfo
                };
            var updateTickValues = function(axesInfo) {
                    var maxTicksCount = 0,
                        ticksMultiplier,
                        ticksCount,
                        additionalStartTicksCount = 0;
                    $.each(axesInfo, function() {
                        maxTicksCount = Math.max(maxTicksCount, this.tickValues.length)
                    });
                    $.each(axesInfo, function() {
                        if (utils.isDefined(this.synchronizedValue)) {
                            this.baseTickValue = this.synchronizedValue;
                            this.invertedBaseTickValue = this.synchronizedValue;
                            this.tickValues = [this.baseTickValue]
                        }
                        else {
                            if (this.tickValues.length > 1 && this.tickInterval) {
                                ticksMultiplier = Math.floor((maxTicksCount + 1) / this.tickValues.length);
                                ticksCount = ticksMultiplier > 1 ? Math.floor((maxTicksCount + 1) / ticksMultiplier) : maxTicksCount;
                                additionalStartTicksCount = Math.floor((ticksCount - this.tickValues.length) / 2);
                                while (additionalStartTicksCount > 0 && this.tickValues[0] !== 0) {
                                    this.tickValues.unshift(utils.adjustValue(this.tickValues[0] - this.tickInterval));
                                    additionalStartTicksCount--
                                }
                                while (this.tickValues.length < ticksCount)
                                    this.tickValues.push(utils.adjustValue(this.tickValues[this.tickValues.length - 1] + this.tickInterval));
                                this.tickInterval = this.tickInterval / ticksMultiplier
                            }
                            this.baseTickValue = this.tickValues[0];
                            this.invertedBaseTickValue = this.tickValues[this.tickValues.length - 1]
                        }
                    })
                };
            var getAxisRange = function(axisInfo) {
                    return axisInfo.maxValue - axisInfo.minValue
                };
            var getMainAxisInfo = function(axesInfo) {
                    var i;
                    for (i = 0; i < axesInfo.length; i++)
                        if (!axesInfo[i].stubData)
                            return axesInfo[i];
                    return null
                };
            var correctMinMaxValues = function(axesInfo) {
                    var mainAxisInfo = getMainAxisInfo(axesInfo);
                    $.each(axesInfo, function() {
                        var scale,
                            move,
                            mainAxisBaseValueOffset;
                        if (this !== mainAxisInfo) {
                            if (mainAxisInfo.tickInterval && this.tickInterval) {
                                if (this.stubData && utils.isDefined(this.synchronizedValue)) {
                                    this.oldMinValue = this.minValue = this.baseTickValue - (mainAxisInfo.baseTickValue - mainAxisInfo.minValue) / mainAxisInfo.tickInterval * this.tickInterval;
                                    this.oldMaxValue = this.maxValue = this.baseTickValue - (mainAxisInfo.baseTickValue - mainAxisInfo.maxValue) / mainAxisInfo.tickInterval * this.tickInterval;
                                    this.stubData = false
                                }
                                scale = mainAxisInfo.tickInterval / getAxisRange(mainAxisInfo) / this.tickInterval * getAxisRange(this);
                                this.maxValue = this.minValue + getAxisRange(this) / scale
                            }
                            if (mainAxisInfo.inverted && !this.inverted || !mainAxisInfo.inverted && this.inverted)
                                mainAxisBaseValueOffset = mainAxisInfo.maxValue - mainAxisInfo.invertedBaseTickValue;
                            else
                                mainAxisBaseValueOffset = mainAxisInfo.baseTickValue - mainAxisInfo.minValue;
                            move = (mainAxisBaseValueOffset / getAxisRange(mainAxisInfo) - (this.baseTickValue - this.minValue) / getAxisRange(this)) * getAxisRange(this);
                            this.minValue -= move;
                            this.maxValue -= move
                        }
                    })
                };
            var calculatePaddings = function(axesInfo) {
                    var minPadding,
                        maxPadding,
                        startPadding = 0,
                        endPadding = 0;
                    $.each(axesInfo, function() {
                        minPadding = this.minValue > this.oldMinValue ? (this.minValue - this.oldMinValue) / getAxisRange(this) : 0;
                        maxPadding = this.maxValue < this.oldMaxValue ? (this.oldMaxValue - this.maxValue) / getAxisRange(this) : 0;
                        if (this.inverted) {
                            startPadding = Math.max(startPadding, maxPadding);
                            endPadding = Math.max(endPadding, minPadding)
                        }
                        else {
                            startPadding = Math.max(startPadding, minPadding);
                            endPadding = Math.max(endPadding, maxPadding)
                        }
                    });
                    return {
                            start: startPadding,
                            end: endPadding
                        }
                };
            var correctMinMaxValuesByPaddings = function(axesInfo, paddings) {
                    var range;
                    $.each(axesInfo, function() {
                        range = getAxisRange(this);
                        if (this.inverted) {
                            this.minValue -= paddings.end * range;
                            this.maxValue += paddings.start * range
                        }
                        else {
                            this.minValue -= paddings.start * range;
                            this.maxValue += paddings.end * range
                        }
                        this.minValue = Math.min(this.minValue, utils.adjustValue(this.minValue));
                        this.maxValue = Math.max(this.maxValue, utils.adjustValue(this.maxValue))
                    })
                };
            var updateTickValuesIfSyncronizedValueUsed = function(axesInfo) {
                    var hasSyncronizedValue = false;
                    $.each(axesInfo, function() {
                        hasSyncronizedValue = hasSyncronizedValue || utils.isDefined(this.synchronizedValue)
                    });
                    $.each(axesInfo, function() {
                        var lastTickValue;
                        if (hasSyncronizedValue && this.tickInterval) {
                            while (this.tickValues[0] - this.tickInterval >= this.minValue)
                                this.tickValues.unshift(utils.adjustValue(this.tickValues[0] - this.tickInterval));
                            lastTickValue = this.tickValues[this.tickValues.length - 1];
                            while ((lastTickValue = lastTickValue + this.tickInterval) <= this.maxValue)
                                this.tickValues.push(utils.adjustValue(lastTickValue))
                        }
                        while (this.tickValues[0] < this.minValue)
                            this.tickValues.shift();
                        while (this.tickValues[this.tickValues.length - 1] > this.maxValue)
                            this.tickValues.pop()
                    })
                };
            var applyMinMaxValues = function(axesInfo, rotated) {
                    var axis,
                        range,
                        stubData = rotated && 'stubDataX' || 'stubDataY';
                    $.each(axesInfo, function() {
                        axis = this.axis;
                        range = axis.translator.getBusinessRange();
                        if (rotated) {
                            if (range.minX === range.minVisibleX)
                                range.minX = this.minValue;
                            if (range.maxX === range.maxVisibleX)
                                range.maxX = this.maxValue;
                            range.minVisibleX = this.minValue;
                            range.maxVisibleX = this.maxValue
                        }
                        else {
                            if (range.minY === range.minVisibleY)
                                range.minY = this.minValue;
                            if (range.maxY === range.maxVisibleY)
                                range.maxY = this.maxValue;
                            range.minVisibleY = this.minValue;
                            range.maxVisibleY = this.maxValue
                        }
                        if (utils.isDefined(this.stubData))
                            range[stubData] = this.stubData;
                        if (range.minY > range.minVisibleY)
                            range.minY = range.minVisibleY;
                        if (range.maxY < range.maxVisibleY)
                            range.maxY = range.maxVisibleY;
                        if (range.minX > range.minVisibleX)
                            range.minX = range.minVisibleX;
                        if (range.maxX < range.maxVisibleX)
                            range.maxX = range.maxVisibleX;
                        axis.translator.updateBusinessRange(range);
                        axis.setRange(range);
                        axis.setTickValues(this.tickValues)
                    })
                };
            return {synchronize: function(valueAxes, rotated) {
                        var valueAxesPerPanes;
                        valueAxesPerPanes = getValueAxesPerPanes(valueAxes);
                        $.each(valueAxesPerPanes, function(i, axes) {
                            var axesInfo,
                                paddings;
                            if (axes.length > 1) {
                                axesInfo = populateAxesInfo(axes, rotated);
                                if (axesInfo.length === 0 || !getMainAxisInfo(axesInfo))
                                    return;
                                updateTickValues(axesInfo);
                                correctMinMaxValues(axesInfo);
                                paddings = calculatePaddings(axesInfo);
                                correctMinMaxValuesByPaddings(axesInfo, paddings);
                                updateTickValuesIfSyncronizedValueUsed(axesInfo);
                                applyMinMaxValues(axesInfo, rotated)
                            }
                        })
                    }}
        }())
    })(jQuery, DevExpress);
    /*! Module viz, file seriesConsts.js */
    (function(DX) {
        DX.viz.charts.series.consts = {
            events: {
                mouseover: 'mouseover',
                mouseout: 'mouseout',
                mousemove: 'mousemove',
                touchstart: 'touchstart',
                touchmove: 'touchmove',
                touchend: 'touchend',
                mousedown: 'mousedown',
                mouseup: 'mouseup',
                click: 'click',
                selectSeries: 'selectseries',
                deselectSeries: 'deselectseries',
                selectPoint: 'selectpoint',
                deselectPoint: 'deselectpoint',
                showPointTooltip: 'showpointtooltip',
                hidePointTooltip: 'hidepointtooltip'
            },
            states: {
                hover: 'hover',
                normal: 'normal',
                selected: 'selected',
                normalMark: 0,
                hoverMark: 1,
                selectedMark: 2
            }
        }
    })(DevExpress);
    /*! Module viz, file basePoint.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            eventsConsts = series.consts.events,
            statesConsts = series.consts.states,
            utils = DX.utils,
            formatHelper = DX.formatHelper,
            CANVAS_POSITION_DEFAULT = 'canvas_position_default';
        series.BasePoint = DX.Class.inherit({
            ctor: function(data) {
                var debug = DX.utils.debug;
                debug.assertParam(data, 'data was not passed');
                debug.assertParam(data.options, 'options were not passed');
                this.LABEL_BACKGROUND_PADDING_X = 8;
                this.LABEL_BACKGROUND_PADDING_Y = 4;
                this.LABEL_OFFSET = 10;
                this.rotated = !!data.rotated;
                if (data.options.label && data.options.label.position && data.options.label.position !== 'outside' && data.options.label.position !== 'inside')
                    data.options.label.position = 'outside';
                this.options = data.options;
                this.series = data.series;
                this.value = this.initialValue = data.value;
                this.argument = this.initialArgument = data.argument;
                this.originalValue = data.originalValue;
                this.originalArgument = data.originalArgument;
                this.minValue = CANVAS_POSITION_DEFAULT;
                this.labelFormatObject = {
                    argument: this.initialArgument,
                    value: this.initialValue,
                    seriesName: this.options.seriesName,
                    originalValue: this.originalValue,
                    originalArgument: this.originalArgument
                };
                this.tag = data.tag;
                this.pointClassName = data.pointClassName || ''
            },
            dispose: function() {
                var _this = this;
                _this.off();
                _this.trackerGraphic && _this.trackerGraphic.removeData();
                _this.graphic = null;
                _this.trackerGraphic = null;
                _this.hoverPattern = null;
                _this.selectedPattern = null;
                _this.label = null;
                _this.labelBackground = null;
                _this.connector = null;
                _this.insideLabelGroup = null;
                _this.labelGroup = null;
                _this.points = null;
                _this.translator = null;
                _this.options = null;
                _this.series = null;
                _this.tag = null;
                _this.labelFormatObject = null
            },
            formatLabel: function(options) {
                this.valueText = formatHelper.format(this.value, options.format, options.precision);
                this.argumentText = formatHelper.format(this.argument, options.argumentFormat, options.argumentPrecision);
                if (this.percent !== undefined)
                    this.percentText = formatHelper.format(this.percent, 'percent', options.percentPrecision);
                return options.customizeText ? options.customizeText.call(this, this) : this.valueText
            },
            setOptions: function(options) {
                this.options = options
            },
            translate: function(translator) {
                this.translator = translator = translator || this.translator;
                if (!this.translator || !this.hasValue())
                    return;
                if (!this.rotated) {
                    this.y = translator.translateY(this.value);
                    this.minY = translator.translateY(this.minValue);
                    this.x = translator.translateX(this.argument);
                    this.defaultY = translator.translateY(CANVAS_POSITION_DEFAULT)
                }
                else {
                    this.y = translator.translateY(this.argument);
                    this.x = translator.translateX(this.value);
                    this.minX = translator.translateX(this.minValue);
                    this.defaultX = translator.translateX(CANVAS_POSITION_DEFAULT)
                }
                this._calculateVisibility(this.x, this.y, 0, 0);
                this.prepareStatesOptions()
            },
            _calculateVisibility: function(x, y, width, height) {
                var visibleArea;
                if (this.translator && this.translator.getCanvasVisibleArea) {
                    visibleArea = this.translator.getCanvasVisibleArea() || {};
                    if (visibleArea.minX > x + (width || 0) || visibleArea.maxX < x || visibleArea.minY > y + (height || 0) || visibleArea.maxY < y)
                        this.visible = false;
                    else
                        this.visible = true
                }
            },
            correctValue: function(correction) {
                this.value += correction;
                if (!utils.isNumber(this.minValue))
                    this.minValue = correction;
                else
                    this.minValue += correction;
                this.translate()
            },
            setPercentValue: function(total, fullStacked) {
                var valuePercent = this.value / total || 0,
                    minValuePercent;
                if (utils.isNumber(this.minValue)) {
                    minValuePercent = this.minValue / total || 0;
                    this.labelFormatObject.percent = valuePercent - minValuePercent
                }
                else
                    this.labelFormatObject.percent = valuePercent;
                this.labelFormatObject.total = total;
                if (fullStacked) {
                    this.value = valuePercent;
                    this.minValue = !minValuePercent ? this.minValue : minValuePercent;
                    this.translate()
                }
            },
            getCoords: function(min) {
                if (!min)
                    return {
                            x: this.x,
                            y: this.y
                        };
                if (!this.rotated)
                    return {
                            x: this.x,
                            y: this.minY
                        };
                return {
                        x: this.minX,
                        y: this.y
                    }
            },
            getDefaultCoords: function() {
                return !this.rotated ? {
                        x: this.x,
                        y: this.defaultY
                    } : {
                        x: this.defaultX,
                        y: this.y
                    }
            },
            getTooltipCoords: function() {
                if (this.graphic)
                    return {
                            x: this.x,
                            y: this.y,
                            offset: this.graphic.getBBox().height / 2
                        };
                else
                    return {
                            x: this.x,
                            y: this.y,
                            offset: 0
                        }
            },
            isInVisibleArea: function() {
                return this.visible
            },
            drawMarker: function(renderer, group) {
                if (!this.hasValue())
                    return;
                var radius = this.options.attributes.r,
                    states = this.options.states.normal,
                    marker,
                    bbox;
                switch (this.options.symbol) {
                    case'circle':
                        marker = renderer.createCircle(this.x, this.y, radius, this.options.attributes).append(group);
                        break;
                    case'square':
                    case'polygon':
                    case'triangle':
                    case'cross':
                        marker = renderer.createArea(this.points, this.options.attributes).append(group);
                        break
                }
                this.graphic = marker;
                switch (this.state) {
                    case statesConsts.selected:
                        this.series.setPointSelectedState(this);
                        break;
                    case statesConsts.hover:
                        this.series.setPointHoverState(this);
                        break;
                    default:
                        this.state = statesConsts.normal;
                        this.fullState = statesConsts.normalMark
                }
            },
            _trackerAttrs: {
                stroke: 'none',
                fill: 'grey',
                opacity: 0.0001,
                inh: true
            },
            storeTrackerR: function() {
                var navigator = window.navigator,
                    touchSupport = 'ontouchstart' in window || navigator.msPointerEnabled && navigator.msMaxTouchPoints || navigator.pointerEnabled && navigator.maxTouchPoints,
                    minTrackerSize = touchSupport ? 20 : 6;
                this.options.trackerR = this.options.attributes.r < minTrackerSize ? minTrackerSize : this.options.attributes.r;
                return this.options.trackerR
            },
            drawTrackerMarker: function(renderer, trackerGroup) {
                if (!this.hasValue())
                    return;
                this.trackerGraphic = renderer.createCircle(this.x, this.y, this.options.trackerR || this.storeTrackerR(), this._trackerAttrs).append(trackerGroup);
                this.trackerGraphic.data({point: this})
            },
            select: function() {
                this.series.selectPoint(this)
            },
            clearSelection: function() {
                this.series.deselectPoint(this)
            },
            _populatePointShape: function(target, radius) {
                var self = this,
                    floorHalfRadius,
                    ceilHalfRadius;
                if (self.options.symbol === 'square')
                    target.points = [{
                            x: self.x - radius,
                            y: self.y - radius
                        }, {
                            x: self.x + radius,
                            y: self.y - radius
                        }, {
                            x: self.x + radius,
                            y: self.y + radius
                        }, {
                            x: self.x - radius,
                            y: self.y + radius
                        }, {
                            x: self.x - radius,
                            y: self.y - radius
                        }];
                if (self.options.symbol === 'polygon')
                    target.points = [{
                            x: self.x - radius,
                            y: self.y
                        }, {
                            x: self.x,
                            y: self.y - radius
                        }, {
                            x: self.x + radius,
                            y: self.y
                        }, {
                            x: self.x,
                            y: self.y + radius
                        }, {
                            x: self.x - radius,
                            y: self.y
                        }];
                if (self.options.symbol === 'triangle')
                    target.points = [{
                            x: self.x - radius,
                            y: self.y - radius
                        }, {
                            x: self.x + radius,
                            y: self.y - radius
                        }, {
                            x: self.x,
                            y: self.y + radius
                        }, {
                            x: self.x - radius,
                            y: self.y - radius
                        }];
                if (self.options.symbol === 'cross') {
                    floorHalfRadius = Math.floor(radius / 2);
                    ceilHalfRadius = Math.ceil(radius / 2);
                    target.points = [{
                            x: self.x - radius,
                            y: self.y - floorHalfRadius
                        }, {
                            x: self.x - floorHalfRadius,
                            y: self.y - radius
                        }, {
                            x: self.x,
                            y: self.y - ceilHalfRadius
                        }, {
                            x: self.x + floorHalfRadius,
                            y: self.y - radius
                        }, {
                            x: self.x + radius,
                            y: self.y - floorHalfRadius
                        }, {
                            x: self.x + ceilHalfRadius,
                            y: self.y
                        }, {
                            x: self.x + radius,
                            y: self.y + floorHalfRadius
                        }, {
                            x: self.x + floorHalfRadius,
                            y: self.y + radius
                        }, {
                            x: self.x,
                            y: self.y + ceilHalfRadius
                        }, {
                            x: self.x - floorHalfRadius,
                            y: self.y + radius
                        }, {
                            x: self.x - radius,
                            y: self.y + floorHalfRadius
                        }, {
                            x: self.x - ceilHalfRadius,
                            y: self.y
                        }]
                }
            },
            prepareStatesOptions: function() {
                var self = this;
                if (self.options.states && self.options.states.normal)
                    self._populatePointShape(self, self.options.states.normal.r)
            },
            applyNormalStyle: function() {
                if (this.graphic) {
                    this._populatePointShape(this.options.states.normal, this.options.states.normal.r);
                    this.graphic.applySettings(this.options.states.normal)
                }
                return this
            },
            applyHoverStyle: function() {
                if (this.graphic) {
                    this._populatePointShape(this.options.states.hover, this.options.states.hover.r);
                    this.graphic.applySettings(this.options.states.hover);
                    this.graphic.toForeground();
                    this.graphic.addClass('dx-chart-hovered-point')
                }
                return this
            },
            applySelectionStyle: function() {
                if (this.graphic) {
                    this._populatePointShape(this.options.states.selected, this.options.states.selected.r);
                    this.graphic.applySettings(this.options.states.selected);
                    this.graphic.toForeground();
                    this.graphic.addClass('dx-chart-selected-point')
                }
                return this
            },
            setHoverState: function() {
                this.series.setPointHoverState(this)
            },
            releaseHoverState: function() {
                this.series.releasePointHoverState(this);
                if (this.graphic) {
                    this.graphic.removeClass('dx-chart-hovered-point');
                    this.state !== 'selected' && this.graphic.toBackground()
                }
            },
            setSelectedState: function() {
                this.series.setPointSelectedState(this)
            },
            releaseSelectedState: function() {
                this.series.releasePointSelectedState(this);
                if (this.graphic)
                    this.graphic.removeClass('dx-chart-selected-point')
            },
            showTooltip: function() {
                this.series.showPointTooltip(this)
            },
            hideTooltip: function() {
                this.series.hidePointTooltip(this)
            },
            on: function(events, data, handler) {
                $(this).on(events, data, handler);
                return this
            },
            off: function(events) {
                $(this).off(events);
                return this
            },
            correctLabel: function() {
                this.correctBackgroundPosition();
                this.rotateLabel();
                this.correctLabelPosition()
            },
            drawLabel: function(renderer, group) {
                if (!this.hasValue())
                    return;
                if (!utils.isDefined(this.labelFormatObject.value))
                    return;
                var labelOptions = this.options.label,
                    labelText = this.formatLabel.call(this.labelFormatObject, labelOptions);
                if (!utils.isDefined(labelText))
                    return;
                this.labelGroup = renderer.createGroup().append(group);
                if (this.options.label.connector && this.options.label.connector.strokeWidth)
                    this.connector = renderer.createPath([], labelOptions.connector).append(this.labelGroup);
                this.insideLabelGroup = renderer.createGroup().append(this.labelGroup);
                labelOptions.background['class'] = this.pointClassName;
                if (labelOptions.background.fill && labelOptions.background.fill !== 'none' || labelOptions.background.strokeWidth && labelOptions.background.stroke && labelOptions.background.stroke !== 'none')
                    this.labelBackground = renderer.createRect(this.x, this.y, 0, 0, 0, labelOptions.background).append(this.insideLabelGroup);
                this.label = renderer.createText(labelText, this.x, this.y, labelOptions.attributes).append(this.insideLabelGroup);
                this.correctLabel();
                this.correctConnectorPosition()
            },
            rotateLabel: function() {
                var bbox = this.insideLabelGroup.getBBox(),
                    labelOptions = this.options.label;
                this.insideLabelGroup.applySettings({
                    x: bbox.x + bbox.width / 2,
                    y: bbox.y + bbox.height / 2,
                    rotate: labelOptions.rotationAngle
                })
            },
            getGraphicSettings: function() {
                return {
                        x: this.graphic.settings.x || 0,
                        y: this.graphic.settings.y || 0,
                        height: this.graphic.settings.height || 0,
                        width: this.graphic.settings.width || 0
                    }
            },
            correctLabelPosition: function() {
                var bbox = this.insideLabelGroup.getBBox(),
                    bboxgraphic = this.graphic ? this.graphic.getBBox() : {
                        x: this.x,
                        y: this.y,
                        height: 0,
                        width: 0
                    },
                    x = 0,
                    y = 0;
                if (bboxgraphic.isEmpty)
                    bboxgraphic = {
                        x: this.x,
                        y: this.y,
                        height: 0,
                        width: 0
                    };
                if (!this.rotated)
                    if (this.initialValue > 0 || this.series.isFullStackedSeries())
                        y += bboxgraphic.y - bbox.y - bbox.height - this.LABEL_OFFSET;
                    else
                        y += bboxgraphic.y + bboxgraphic.height - bbox.y + this.LABEL_OFFSET;
                else {
                    y += bboxgraphic.y - bbox.y - bbox.height / 2 + bboxgraphic.height / 2;
                    if (this.initialValue > 0 || this.series.isFullStackedSeries())
                        x += bboxgraphic.x + bboxgraphic.width - bbox.x + this.LABEL_OFFSET;
                    else
                        x += bboxgraphic.x - bbox.x - bbox.width - this.LABEL_OFFSET
                }
                x += this.options.label.horizontalOffset;
                y += this.options.label.verticalOffset;
                this.checkLabelPosition({
                    x: bbox.x + x,
                    y: bbox.y + y,
                    height: bbox.height,
                    width: bbox.width
                }, x, y)
            },
            checkLabelPosition: function(bbox, x, y) {
                var bboxgraphic = this.graphic ? this.graphic.getBBox() : {
                        x: this.x,
                        y: this.y,
                        height: 0,
                        width: 0
                    },
                    visibleArea = this.translator.getCanvasVisibleArea();
                if (bboxgraphic.isEmpty)
                    bboxgraphic = {
                        x: this.x,
                        y: this.y,
                        height: 0,
                        width: 0
                    };
                if (!this.rotated)
                    if (visibleArea.minX <= bboxgraphic.x + bboxgraphic.width && visibleArea.maxX >= bboxgraphic.x) {
                        if (visibleArea.minX > bbox.x && this.adjustSeriesLabels)
                            x += visibleArea.minX - bbox.x;
                        if (visibleArea.maxX < bbox.x + bbox.width && this.adjustSeriesLabels)
                            x -= bbox.x + bbox.width - visibleArea.maxX;
                        if (visibleArea.minY > bbox.y)
                            y += bboxgraphic.y + bboxgraphic.height - bbox.y + this.LABEL_OFFSET;
                        if (visibleArea.maxY < bbox.y + bbox.height)
                            y -= bbox.y + bbox.height - bboxgraphic.y + this.LABEL_OFFSET
                    }
                if (this.rotated)
                    if (visibleArea.minY <= bboxgraphic.y + bboxgraphic.height && visibleArea.maxY >= bboxgraphic.y) {
                        if (visibleArea.minX > bbox.x)
                            x += bboxgraphic.x + bboxgraphic.width - bbox.x + this.LABEL_OFFSET;
                        if (visibleArea.maxX < bbox.x + bbox.width)
                            x -= bbox.x + bbox.width - bboxgraphic.x + this.LABEL_OFFSET;
                        if (visibleArea.minY > bbox.y && this.adjustSeriesLabels)
                            y += visibleArea.minY - bbox.y;
                        if (visibleArea.maxY < bbox.y + bbox.height && this.adjustSeriesLabels)
                            y -= bbox.y + bbox.height - visibleArea.maxY
                    }
                this.insideLabelGroup.move(~~x, ~~y)
            },
            correctBackgroundPosition: function() {
                if (!this.labelBackground)
                    return;
                var bbox = this.label.getBBox(),
                    x = bbox.x - this.LABEL_BACKGROUND_PADDING_X,
                    y = bbox.y - this.LABEL_BACKGROUND_PADDING_Y,
                    width = bbox.width + 2 * this.LABEL_BACKGROUND_PADDING_X,
                    height = bbox.height + 2 * this.LABEL_BACKGROUND_PADDING_Y;
                this.labelBackground.applySettings({
                    x: x,
                    y: y,
                    width: width,
                    height: height
                })
            },
            correctConnectorPosition: function(bboxgraphic) {
                var bbox = this.insideLabelGroup.getBBox(),
                    bboxgraphic = bboxgraphic || (this.graphic ? this.graphic.getBBox() : {
                        x: this.x,
                        y: this.y,
                        height: 0,
                        width: 0
                    }),
                    x1,
                    x2,
                    y1,
                    y2,
                    centerLabelY,
                    centerLabelX;
                if (!this.connector)
                    return;
                if (bboxgraphic.isEmpty)
                    bboxgraphic = {
                        x: this.x,
                        y: this.y,
                        height: 0,
                        width: 0
                    };
                bbox.x = bbox.x + (this.insideLabelGroup.settings.translateX || 0);
                bbox.y = bbox.y + (this.insideLabelGroup.settings.translateY || 0);
                centerLabelY = this.labelBackground ? bbox.y + bbox.height / 2 : null;
                centerLabelX = this.labelBackground ? bbox.x + bbox.width / 2 : null;
                if (!this.rotated) {
                    if ((centerLabelY || bbox.y + bbox.height) < bboxgraphic.y) {
                        y1 = centerLabelY || bbox.y + bbox.height;
                        y2 = bboxgraphic.y
                    }
                    else if ((centerLabelY || bbox.y) > bboxgraphic.y + bboxgraphic.height) {
                        y1 = centerLabelY || bbox.y;
                        y2 = bboxgraphic.y + bboxgraphic.height
                    }
                    else
                        return;
                    x1 = Math.round(bbox.x + bbox.width / 2);
                    if (x1 > bboxgraphic.x + bboxgraphic.width)
                        x2 = bboxgraphic.x + bboxgraphic.width;
                    else if (x1 < bboxgraphic.x)
                        x2 = bboxgraphic.x;
                    else
                        x2 = x1
                }
                else {
                    if ((centerLabelX || bbox.x) > bboxgraphic.x + bboxgraphic.width) {
                        x1 = centerLabelX || bbox.x;
                        x2 = bboxgraphic.x + bboxgraphic.width
                    }
                    else if ((centerLabelX || bbox.x + bbox.width) < bboxgraphic.x) {
                        x1 = centerLabelX || bbox.x + bbox.width;
                        x2 = bboxgraphic.x
                    }
                    else
                        return;
                    y1 = Math.round(bbox.y + bbox.height / 2);
                    if (y1 > bboxgraphic.y + bboxgraphic.height)
                        y2 = bboxgraphic.y + bboxgraphic.height;
                    else if (y1 < bboxgraphic.y)
                        y2 = bboxgraphic.y;
                    else
                        y2 = y1
                }
                this.connector.applySettings({points: [x1, y1, x2, y2]})
            },
            getColor: function() {
                return this.options.attributes.fill
            },
            getTooltipFormatObject: function(tooltip) {
                var value = tooltip.formatValueTooltip.call({value: this.initialValue}, tooltip.options);
                return $.extend({}, this.labelFormatObject, {
                        point: this,
                        valueText: value
                    })
            },
            animate: function() {
                var self = this,
                    graphic = self.graphic;
                if (!graphic || !self.translator)
                    return;
                if (!self.rotated)
                    graphic.move(0, self.defaultY - self.y);
                else
                    graphic.move(self.defaultX - self.x, 0);
                graphic.move(0, 0, true)
            },
            stopAnimation: function() {
                var graphic = this.graphic;
                graphic && graphic.stopAnimation()
            },
            hasValue: function() {
                return this.initialValue !== null
            },
            getClassName: function() {
                return this.pointClassName
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file barPoint.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            statesConsts = series.consts.states,
            CANVAS_POSITION_DEFAULT = 'canvas_position_default',
            isDefined = DX.utils.isDefined;
        var truncateCoord = function(coord, minBounce, maxBounce) {
                if (coord < minBounce)
                    return minBounce;
                if (coord > maxBounce)
                    return maxBounce;
                return coord
            };
        series.BarPoint = series.BasePoint.inherit({
            translate: function(translator) {
                var canvasVisibleArea,
                    minX,
                    minY,
                    y,
                    x;
                this.translator = translator = translator || this.translator;
                if (!this.translator || !this.hasValue())
                    return;
                canvasVisibleArea = translator.getCanvasVisibleArea() || {};
                if (!this.rotated) {
                    this.x = translator.translateX(this.argument) + (this.xCorrection || 0);
                    y = translator.translateY(this.value);
                    this.minY = isDefined(this.minY) ? this.minY : Infinity;
                    minY = translator.translateY(this.minValue);
                    this.height = Math.abs(minY - y);
                    this._calculateVisibility(this.x, Math.min(y, this.minY), 0, this.height);
                    y = truncateCoord(y, canvasVisibleArea.minY, canvasVisibleArea.maxY);
                    minY = truncateCoord(minY, canvasVisibleArea.minY, canvasVisibleArea.maxY);
                    this.height = Math.abs(minY - y);
                    this.y = Math.min(y, minY) + (this.yCorrection || 0);
                    this.minY = minY + (this.yCorrection || 0);
                    this.defaultY = translator.translateY(CANVAS_POSITION_DEFAULT)
                }
                else {
                    this.y = translator.translateY(this.argument) + (this.yCorrection || 0);
                    x = translator.translateX(this.value);
                    this.minX = isDefined(this.minX) ? this.minX : Infinity;
                    minX = translator.translateX(this.minValue);
                    this.width = Math.abs(x - minX);
                    this._calculateVisibility(Math.min(x, minX), this.y, this.width, 0);
                    x = truncateCoord(x, canvasVisibleArea.minX, canvasVisibleArea.maxX);
                    minX = truncateCoord(minX, canvasVisibleArea.minX, canvasVisibleArea.maxX);
                    this.minX = minX + (this.minXCorrection || 0);
                    this.width = Math.abs(x - minX);
                    this.x = Math.min(minX, x) + (this.xCorrection || 0);
                    this.defaultX = translator.translateX(CANVAS_POSITION_DEFAULT)
                }
            },
            getTooltipCoords: function() {
                var self = this,
                    x = self.x + self.width / 2,
                    y = self.y + self.height / 2;
                return {
                        x: x,
                        y: y,
                        offset: 0
                    }
            },
            correctCoordinates: function(correctOptions) {
                var correction = correctOptions.offset - Math.round(correctOptions.width / 2);
                if (!this.rotated) {
                    this.width = correctOptions.width;
                    this.xCorrection = correction;
                    this.minXCorrection = correction
                }
                else {
                    this.height = correctOptions.width;
                    this.yCorrection = correction;
                    this.minYCorrection = correction
                }
            },
            drawMarker: function(renderer, group) {
                var attributes;
                if (!this.hasValue())
                    return;
                switch (this.state) {
                    case statesConsts.hover:
                        attributes = this.options.states.hover;
                        break;
                    case statesConsts.selected:
                        attributes = this.options.states.selected;
                        break;
                    default:
                        attributes = this.options.attributes;
                        this.state = statesConsts.normal;
                        this.fullState = statesConsts.normalMark
                }
                this.graphic = renderer.createRect(this.x, this.y, this.width, this.height, attributes.r, attributes).append(group)
            },
            drawTrackerMarker: function(renderer, trackerGroup) {
                if (!this.hasValue())
                    return;
                var _this = this,
                    y = _this.y,
                    height = _this.height,
                    x = _this.x,
                    width = _this.width;
                if (_this.rotated) {
                    if (width === 1) {
                        width = 9;
                        x -= 4
                    }
                }
                else if (height === 1) {
                    height = 9;
                    y -= 4
                }
                this.trackerGraphic = renderer.createRect(x, y, width, height, _this.options.attributes.r, _this._trackerAttrs).append(trackerGroup);
                this.trackerGraphic.data({point: _this})
            },
            correctConnectorPosition: function() {
                this.callBase(this.getBboxGraphic())
            },
            drawLabel: function(renderer, group) {
                if (!this.hasValue() || !this.options.label.showForZeroValues && !this.labelFormatObject.value)
                    return;
                else
                    this.callBase(renderer, group)
            },
            getBboxGraphic: function() {
                var bboxgraphic = this.graphic && this.graphic.getBBox(),
                    deltaX,
                    deltaY;
                if (bboxgraphic.isEmpty)
                    bboxgraphic = this.getGraphicSettings();
                deltaX = bboxgraphic.x - this.x;
                deltaY = bboxgraphic.y - this.y;
                bboxgraphic.x -= deltaX;
                bboxgraphic.y -= deltaY;
                bboxgraphic.width += 2 * deltaX;
                bboxgraphic.height += 2 * deltaY;
                return bboxgraphic
            },
            correctLabelPosition: function() {
                var bbox = this.insideLabelGroup.getBBox(),
                    bboxgraphic = this.getBboxGraphic(),
                    businessRange = this.translator.getBusinessRange(),
                    isDiscreteValue = this.series.options.valueAxisType === 'discrete',
                    isTop = !isDiscreteValue && (this.initialValue >= 0 && !businessRange.invertY || this.initialValue < 0 && businessRange.invertY) || isDiscreteValue && !businessRange.invertY || this.series.isFullStackedSeries(),
                    isLeft = !isDiscreteValue && (this.initialValue >= 0 && !businessRange.invertX || this.initialValue < 0 && businessRange.invertX) || isDiscreteValue && !businessRange.invertX || this.series.isFullStackedSeries(),
                    x = 0,
                    y = 0;
                if (this.initialValue === 0 && this.series.isFullStackedSeries())
                    if (!this.rotated) {
                        x += bboxgraphic.width / 2;
                        y += this.defaultY - bbox.y - bbox.height - this.LABEL_OFFSET
                    }
                    else {
                        y += bboxgraphic.y - bbox.y - bbox.height / 2 + bboxgraphic.height / 2;
                        x += this.defaultX - bbox.x + this.LABEL_OFFSET
                    }
                else if (this.options.label.position === 'outside')
                    if (!this.rotated) {
                        x += bboxgraphic.width / 2;
                        if (isTop)
                            y += bboxgraphic.y - bbox.y - bbox.height - this.LABEL_OFFSET;
                        else
                            y += bboxgraphic.y + bboxgraphic.height - bbox.y + this.LABEL_OFFSET
                    }
                    else {
                        y += bboxgraphic.y - bbox.y - bbox.height / 2 + bboxgraphic.height / 2;
                        if (isLeft)
                            x += bboxgraphic.x + bboxgraphic.width - bbox.x + this.LABEL_OFFSET;
                        else
                            x += bboxgraphic.x - bbox.x - bbox.width - this.LABEL_OFFSET
                    }
                else if (this.options.label.position === 'inside')
                    if (!this.rotated) {
                        x += bboxgraphic.width / 2;
                        if (isTop)
                            y += bboxgraphic.y - bbox.y - bbox.height + this.LABEL_OFFSET + bbox.height;
                        else
                            y += bboxgraphic.y + bboxgraphic.height - bbox.y - this.LABEL_OFFSET - bbox.height
                    }
                    else {
                        y += bboxgraphic.y - bbox.y - bbox.height / 2 + bboxgraphic.height / 2;
                        if (isLeft)
                            x += bboxgraphic.x + bboxgraphic.width - bbox.x - bbox.width - this.LABEL_OFFSET;
                        else
                            x += bboxgraphic.x - bbox.x + this.LABEL_OFFSET
                    }
                x += this.options.label.horizontalOffset;
                y += this.options.label.verticalOffset;
                this.checkLabelPosition({
                    x: bbox.x + x,
                    y: bbox.y + y,
                    height: bbox.height,
                    width: bbox.width
                }, x, y, bboxgraphic)
            },
            checkLabelPosition: function(bbox, x, y, bboxgraphic) {
                var bboxgraphic = bboxgraphic || this.graphic.getBBox(),
                    visibleArea = this.translator.getCanvasVisibleArea();
                if (bboxgraphic.isEmpty)
                    bboxgraphic = this.getGraphicSettings();
                if (visibleArea.minX <= bboxgraphic.x + bboxgraphic.width && visibleArea.maxX >= bboxgraphic.x && visibleArea.minY <= bboxgraphic.y + bboxgraphic.height && visibleArea.maxY >= bboxgraphic.y) {
                    if (!this.rotated) {
                        if (visibleArea.minX > bbox.x && this.adjustSeriesLabels)
                            x += visibleArea.minX - bbox.x;
                        if (visibleArea.maxX < bbox.x + bbox.width && this.adjustSeriesLabels)
                            x -= bbox.x + bbox.width - visibleArea.maxX;
                        if (visibleArea.minY > bbox.y)
                            y += visibleArea.minY - bbox.y;
                        if (visibleArea.maxY < bbox.y + bbox.height)
                            y -= bbox.y + bbox.height - visibleArea.maxY
                    }
                    if (this.rotated) {
                        if (visibleArea.minX > bbox.x)
                            x += visibleArea.minX - bbox.x;
                        if (visibleArea.maxX < bbox.x + bbox.width)
                            x -= bbox.x + bbox.width - visibleArea.maxX;
                        if (visibleArea.minY > bbox.y && this.adjustSeriesLabels)
                            y += visibleArea.minY - bbox.y;
                        if (visibleArea.maxY < bbox.y + bbox.height && this.adjustSeriesLabels)
                            y -= bbox.y + bbox.height - visibleArea.maxY
                    }
                }
                this.insideLabelGroup.move(~~x, ~~y)
            },
            animate: function() {
                var _this = this,
                    graphic = _this.graphic;
                if (!graphic || !_this.translator)
                    return;
                if (!_this.rotated) {
                    graphic.applySettings({
                        height: 0,
                        y: _this.defaultY,
                        sharpEdges: false
                    });
                    graphic.animate({
                        height: _this.height,
                        y: _this.y
                    })
                }
                else {
                    graphic.applySettings({
                        width: 0,
                        x: _this.defaultX,
                        sharpEdges: false
                    });
                    graphic.animate({
                        width: _this.width,
                        x: _this.x
                    })
                }
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file ohlcPoint.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            utils = DX.utils,
            statesConsts = series.consts.states,
            formatHelper = DX.formatHelper;
        series.OhlcPoint = series.BasePoint.inherit({
            ctor: function(data) {
                var debug = DX.utils.debug;
                debug.assertParam(data, 'data was not passed');
                debug.assertParam(data.options, 'options were not passed');
                this.LABEL_BACKGROUND_PADDING_X = 8;
                this.LABEL_BACKGROUND_PADDING_Y = 4;
                this.LABEL_OFFSET = 10;
                this.argument = this.initialArgument = data.argument;
                this.openValue = data.openValue;
                this.highValue = data.highValue;
                this.lowValue = data.lowValue;
                this.closeValue = data.closeValue;
                this.value = this.initialValue = data.reductionValue;
                this.originalOpenValue = data.originalOpenValue;
                this.originalCloseValue = data.originalCloseValue;
                this.originalLowValue = data.originalLowValue;
                this.originalHighValue = data.originalHighValue;
                this.originalArgument = data.originalArgument;
                this.tag = data.tag;
                this.options = data.options;
                this.options.attributes && (this.options.attributes.inh = false);
                this.series = data.series;
                this.rotated = !!(this.series && this.series.options && this.series.options.rotated || false);
                this.labelFormatObject = {
                    openValue: this.openValue,
                    highValue: this.highValue,
                    lowValue: this.lowValue,
                    closeValue: this.closeValue,
                    reductionValue: this.initialValue,
                    argument: this.initialArgument,
                    value: this.initialValue,
                    seriesName: this.options.seriesName,
                    originalOpenValue: this.originalOpenValue,
                    originalCloseValue: this.originalCloseValue,
                    originalLowValue: this.originalLowValue,
                    originalHighValue: this.originalHighValue,
                    originalArgument: this.originalArgument
                };
                this.pointClassName = data.pointClassName || ''
            },
            formatLabel: function(options) {
                this.openValueText = formatHelper.format(this.openValue, options.format, options.precision);
                this.highValueText = formatHelper.format(this.highValue, options.format, options.precision);
                this.lowValueText = formatHelper.format(this.lowValue, options.format, options.precision);
                this.closeValueText = formatHelper.format(this.closeValue, options.format, options.precision);
                this.reductionValueText = formatHelper.format(this.reductionValue, options.format, options.precision);
                this.valueText = formatHelper.format(this.value, options.format, options.precision);
                this.argumentText = formatHelper.format(this.argument, options.argumentFormat, options.argumentPrecision);
                return options.customizeText ? options.customizeText.call(this, this) : this.valueText
            },
            translate: function(translator) {
                var _this = this,
                    rotated = _this.rotated,
                    translateArg = rotated ? 'translateY' : 'translateX',
                    translateVal = rotated ? 'translateX' : 'translateY',
                    height;
                _this.translator = translator = translator || _this.translator;
                if (!_this.translator || !_this.hasValue())
                    return;
                _this.x = translator[translateArg](_this.argument) + (_this.xCorrection || 0);
                _this.openY = translator[translateVal](_this.openValue);
                _this.highY = translator[translateVal](_this.highValue);
                _this.lowY = translator[translateVal](_this.lowValue);
                _this.closeY = translator[translateVal](_this.closeValue);
                height = Math.abs(_this.lowY - _this.highY);
                if (!_this.rotated)
                    _this._calculateVisibility(_this.x - _this.width / 2, Math.min(_this.lowY, _this.highY), _this.width, height);
                else
                    _this._calculateVisibility(Math.min(_this.lowY, _this.highY), _this.x - _this.width / 2, height, _this.width)
            },
            correctCoordinates: function(correctOptions) {
                var minWidth = 1 + 2 * this.options.attributes.lineWidth,
                    maxWidth = 10;
                this.width = correctOptions.width < minWidth ? minWidth : correctOptions.width > maxWidth ? maxWidth : correctOptions.width;
                this.xCorrection = correctOptions.offset
            },
            drawMarker: function(renderer, group) {
                if (!this.hasValue())
                    return;
                var _this = this,
                    attributes,
                    rotated = _this.rotated,
                    createPoint = rotated ? function(x, y) {
                        return {
                                x: y,
                                y: x
                            }
                    } : function(x, y) {
                        return {
                                x: x,
                                y: y
                            }
                    };
                switch (_this.state) {
                    case statesConsts.selected:
                        attributes = _this.options.states.selected;
                        break;
                    case statesConsts.hover:
                        attributes = _this.options.states.hover;
                        break;
                    default:
                        attributes = _this.options.attributes;
                        _this.state = statesConsts.normal;
                        _this.fullState = statesConsts.normalMark
                }
                if (_this.openValue > _this.closeValue)
                    _this.graphic = renderer.createArea([createPoint(_this.x, _this.highY), createPoint(_this.x, _this.openY), createPoint(_this.x + _this.width / 2, _this.openY), createPoint(_this.x + _this.width / 2, _this.closeY), createPoint(_this.x, _this.closeY), createPoint(_this.x, _this.lowY), createPoint(_this.x, _this.closeY), createPoint(_this.x - _this.width / 2, _this.closeY), createPoint(_this.x - _this.width / 2, _this.openY), createPoint(_this.x, _this.openY)], attributes).append(group);
                else if (_this.openValue < _this.closeValue)
                    _this.graphic = renderer.createArea([createPoint(_this.x, _this.highY), createPoint(_this.x, _this.closeY), createPoint(_this.x + _this.width / 2, _this.closeY), createPoint(_this.x + _this.width / 2, _this.openY), createPoint(_this.x, _this.openY), createPoint(_this.x, _this.lowY), createPoint(_this.x, _this.openY), createPoint(_this.x - _this.width / 2, _this.openY), createPoint(_this.x - _this.width / 2, _this.closeY), createPoint(_this.x, _this.closeY)], attributes).append(group);
                else if (_this.openValue === _this.closeValue)
                    _this.graphic = renderer.createArea([createPoint(_this.x, _this.highY), createPoint(_this.x, _this.lowY), createPoint(_this.x, _this.closeY), createPoint(_this.x - _this.width / 2, _this.closeY), createPoint(_this.x + _this.width / 2, _this.closeY), createPoint(_this.x, _this.closeY)], attributes).append(group)
            },
            drawTrackerMarker: function(renderer, trackerGroup) {
                if (!this.hasValue())
                    return;
                var _this = this,
                    highY = _this.highY,
                    lowY = _this.lowY,
                    rotated = _this.rotated,
                    math = Math,
                    x,
                    y,
                    width,
                    height;
                if (highY === lowY) {
                    highY = !rotated ? highY - 2 : highY + 2;
                    lowY = !rotated ? lowY + 2 : lowY - 2
                }
                if (!rotated) {
                    x = _this.x - _this.width / 2;
                    y = math.min(lowY, highY);
                    width = _this.width;
                    height = math.abs(lowY - highY)
                }
                else {
                    x = math.min(lowY, highY);
                    y = _this.x - _this.width / 2;
                    width = math.abs(lowY - highY);
                    height = _this.width
                }
                _this.trackerGraphic = renderer.createRect(x, y, width, height, 0, _this._trackerAttrs).append(trackerGroup);
                _this.trackerGraphic.data({point: _this})
            },
            animate: function(){},
            drawLabel: function(renderer, group) {
                if (!this.hasValue())
                    return;
                if (!utils.isDefined(this.labelFormatObject.value))
                    return;
                var labelOptions = this.options.label,
                    labelText = this.formatLabel.call(this.labelFormatObject, labelOptions),
                    rotated = this.rotated;
                if (!utils.isDefined(labelText))
                    return;
                this.labelGroup = renderer.createGroup().append(group);
                this.insideLabelGroup = renderer.createGroup().append(this.labelGroup);
                labelOptions.background['class'] = this.pointClassName;
                if (labelOptions.background.fill && labelOptions.background.fill !== 'none' || labelOptions.background.strokeWidth && labelOptions.background.stroke && labelOptions.background.stroke !== 'none') {
                    labelOptions.background.fill = this.options.attributes.stroke;
                    this.labelBackground = rotated ? renderer.createRect(this.highY, this.x, 0, 0, 0, labelOptions.background).append(this.insideLabelGroup) : renderer.createRect(this.x, this.highY, 0, 0, 0, labelOptions.background).append(this.insideLabelGroup)
                }
                this.label = rotated ? renderer.createText(labelText, this.highY, this.x, labelOptions.attributes).append(this.insideLabelGroup) : renderer.createText(labelText, this.x, this.highY, labelOptions.attributes).append(this.insideLabelGroup);
                this.correctBackgroundPosition();
                this.rotateLabel();
                this.correctLabelPosition()
            },
            correctLabelPosition: function() {
                var bbox = this.insideLabelGroup.getBBox(),
                    bboxgraphic = this.graphic.getBBox(),
                    rotated = this.rotated,
                    x = 0,
                    y = 0;
                if (!rotated)
                    y += bboxgraphic.y - bbox.y - bbox.height - this.LABEL_OFFSET;
                else
                    x += bboxgraphic.x - bbox.x + bboxgraphic.width + this.LABEL_OFFSET;
                x += this.options.label.horizontalOffset;
                y += this.options.label.verticalOffset;
                this.checkLabelPosition({
                    x: bbox.x + x,
                    y: bbox.y + y,
                    height: bbox.height,
                    width: bbox.width
                }, x, y)
            },
            checkLabelPosition: function(bbox, x, y) {
                var visibleArea = this.translator.getCanvasVisibleArea(),
                    bboxgraphic = this.graphic.getBBox();
                if (visibleArea.minX <= bboxgraphic.x + bboxgraphic.width && visibleArea.maxX >= bboxgraphic.x) {
                    if (visibleArea.minX > bbox.x && this.adjustSeriesLabels)
                        x += visibleArea.minX - bbox.x;
                    if (visibleArea.maxX < bbox.x + bbox.width && this.adjustSeriesLabels)
                        x -= bbox.x + bbox.width - visibleArea.maxX;
                    if (visibleArea.minY > bbox.y)
                        y += visibleArea.minY - bbox.y;
                    if (visibleArea.maxY < bbox.y + bbox.height)
                        y -= bbox.y + bbox.height - visibleArea.maxY
                }
                this.insideLabelGroup.move(~~x, ~~y)
            },
            getTooltipCoords: function() {
                var x,
                    y,
                    min,
                    max,
                    math = Math,
                    minValue = math.min(this.lowY, this.highY),
                    maxValue = math.max(this.lowY, this.highY),
                    visibleArea = this.translator.getCanvasVisibleArea();
                if (this.graphic) {
                    if (!this.rotated) {
                        min = math.max(visibleArea.minY, minValue);
                        max = math.min(visibleArea.maxY, maxValue);
                        x = this.x;
                        y = min + (max - min) / 2
                    }
                    else {
                        min = math.max(visibleArea.minX, minValue);
                        max = math.min(visibleArea.maxX, maxValue);
                        y = this.x;
                        x = min + (max - min) / 2
                    }
                    return {
                            x: x,
                            y: y,
                            offset: 0
                        }
                }
            },
            getTooltipFormatObject: function(tooltip) {
                var highValue = tooltip.formatValueTooltip.call({value: this.highValue}, tooltip.options),
                    openValue = tooltip.formatValueTooltip.call({value: this.openValue}, tooltip.options),
                    closeValue = tooltip.formatValueTooltip.call({value: this.closeValue}, tooltip.options),
                    lowValue = tooltip.formatValueTooltip.call({value: this.lowValue}, tooltip.options);
                return $.extend({}, this.labelFormatObject, {
                        valueText: 'h: ' + highValue + ' o: ' + openValue + ' c: ' + closeValue + ' l: ' + lowValue,
                        highValueText: highValue,
                        openValueText: openValue,
                        closeValueText: closeValue,
                        lowValueText: lowValue,
                        point: this
                    })
            },
            getColor: function() {
                return this.options.attributes.stroke
            },
            hasValue: function() {
                return this.openValue !== null && this.closeValue !== null && this.highValue !== null && this.lowValue !== null
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file stockPoint.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            statesConsts = series.consts.states,
            OhlcPoint = series.OhlcPoint;
        series.StockPoint = series.OhlcPoint.inherit({
            correctCoordinates: function(correctOptions) {
                var minWidth = 2 + this.options.attributes.lineWidth,
                    maxWidth = 10;
                this.width = correctOptions.width < minWidth ? minWidth : correctOptions.width > maxWidth ? maxWidth : correctOptions.width;
                this.xCorrection = correctOptions.offset
            },
            drawMarker: function(renderer, group) {
                var _this = this,
                    attributes,
                    rotated = _this.rotated,
                    createPoint = rotated ? function(x, y) {
                        return {
                                x: y,
                                y: x
                            }
                    } : function(x, y) {
                        return {
                                x: x,
                                y: y
                            }
                    };
                if (!_this.hasValue())
                    return;
                switch (_this.state) {
                    case statesConsts.selected:
                        attributes = _this.options.states.selected;
                        break;
                    case statesConsts.hover:
                        attributes = _this.options.states.hover;
                        break;
                    default:
                        attributes = _this.options.attributes;
                        _this.state = statesConsts.normal;
                        _this.fullState = statesConsts.normalMark
                }
                _this.graphic = renderer.createPath([createPoint(_this.x, _this.highY), createPoint(_this.x, _this.openY), createPoint(_this.x - _this.width / 2, _this.openY), createPoint(_this.x, _this.openY), createPoint(_this.x, _this.closeY), createPoint(_this.x + _this.width / 2, _this.closeY), createPoint(_this.x, _this.closeY), createPoint(_this.x, _this.lowY)], attributes).append(group)
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file rangePoint.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            utils = DX.utils,
            eventsConsts = series.consts.events,
            statesConsts = series.consts.states;
        series.RangePoint = series.BasePoint.inherit({
            ctor: function(data) {
                this.callBase(data);
                this.minValue = this.initialMinValue = data.minValue !== undefined ? data.minValue : 'default';
                this.originalMinValue = data.originalMinValue;
                this.minLabelFormatObject = {
                    argument: this.initialArgument,
                    value: this.initialMinValue,
                    seriesName: this.options.seriesName,
                    originalMinValue: this.originalMinValue,
                    originalArgument: this.originalArgument
                }
            },
            dispose: function() {
                var _this = this;
                _this.minLabel = null;
                _this.minLabelBackground = null;
                _this.minConnector = null;
                _this.insideMinLabelGroup = null;
                _this.minLabelGroup = null;
                _this.maxLabel = null;
                _this.maxLabelBackground = null;
                _this.maxConnector = null;
                _this.insideMaxLabelGroup = null;
                _this.maxLabelGroup = null;
                _this.topPoints = null;
                _this.bottomPoints = null;
                _this.minLabelFormatObject = null;
                _this.callBase()
            },
            getTooltipCoords: function() {
                var x,
                    y,
                    min,
                    max,
                    minValue,
                    visibleArea = this.translator.getCanvasVisibleArea();
                if (!this.rotated) {
                    minValue = Math.min(this.y, this.minY);
                    x = this.x;
                    min = visibleArea.minY > minValue ? visibleArea.minY : minValue;
                    max = visibleArea.maxY < minValue + this.height ? visibleArea.maxY : minValue + this.height;
                    y = min + (max - min) / 2
                }
                else {
                    minValue = Math.min(this.x, this.minX);
                    y = this.y;
                    min = visibleArea.minX > minValue ? visibleArea.minX : minValue;
                    max = visibleArea.maxX < minValue + this.width ? visibleArea.maxX : minValue + this.width;
                    x = min + (max - min) / 2
                }
                return {
                        x: x,
                        y: y,
                        offset: 0
                    }
            },
            translate: function(translator) {
                this.minX = this.minY = translator.translateY(this.minValue);
                this.callBase(translator);
                if (!this.rotated) {
                    this.height = Math.abs(this.minY - this.y);
                    this.width = 0
                }
                else {
                    this.width = Math.abs(this.x - this.minX);
                    this.height = 0
                }
            },
            isInVisibleArea: function() {
                var minArgument = Math.min(this.minX, this.x) || this.x,
                    maxArgument = Math.max(this.minX, this.x) || this.x,
                    maxValue = Math.max(this.minY, this.y) || this.y,
                    minValue = Math.min(this.minY, this.y) || this.y,
                    notVisibleBothMarkersRight,
                    notVisibleBothMarkersLeft,
                    notVisibleBothMarkersBottom,
                    notVisibleBothMarkersTop,
                    visibleTopMarker = true,
                    visibleBottomMarker = true,
                    visibleRangeArea = true,
                    visibleArea;
                if (this.translator && this.translator.getCanvasVisibleArea) {
                    visibleArea = this.translator.getCanvasVisibleArea();
                    notVisibleBothMarkersRight = visibleArea.maxX < minArgument && visibleArea.maxX < maxArgument;
                    notVisibleBothMarkersLeft = visibleArea.minX > minArgument && visibleArea.minX > maxArgument;
                    notVisibleBothMarkersTop = visibleArea.minY > minValue && visibleArea.minY > maxValue;
                    notVisibleBothMarkersBottom = visibleArea.maxY < minValue && visibleArea.maxY < maxValue;
                    if (notVisibleBothMarkersTop || notVisibleBothMarkersBottom || notVisibleBothMarkersRight || notVisibleBothMarkersLeft)
                        visibleTopMarker = visibleBottomMarker = visibleRangeArea = false;
                    else if (!this.rotated) {
                        visibleTopMarker = visibleArea.minY < minValue && visibleArea.maxY > minValue;
                        visibleBottomMarker = visibleArea.minY < maxValue && visibleArea.maxY > maxValue
                    }
                    else {
                        visibleBottomMarker = visibleArea.minX < minArgument && visibleArea.maxX > minArgument;
                        visibleTopMarker = visibleArea.minX < maxArgument && visibleArea.maxX > maxArgument
                    }
                }
                this.visibleTopMarker = visibleTopMarker;
                this.visibleBottomMarker = visibleBottomMarker;
                this.visibleRangeArea = visibleRangeArea;
                return visibleRangeArea
            },
            drawMarker: function(renderer, group) {
                if (!this.hasValue())
                    return;
                var radius = this.options.attributes.r,
                    topMarker,
                    x,
                    y,
                    bottomMarker,
                    markerGroup = renderer.createGroup().append(group);
                switch (this.options.symbol) {
                    case'circle':
                        if (!this.rotated) {
                            x = this.x;
                            y = Math.min(this.y, this.minY)
                        }
                        else {
                            x = Math.min(this.x, this.minX);
                            y = this.y
                        }
                        topMarker = this.visibleTopMarker ? renderer.createCircle(x + this.width, y, radius, this.options.attributes).append(markerGroup) : null;
                        bottomMarker = this.visibleBottomMarker ? renderer.createCircle(x, y + this.height, radius, this.options.attributes).append(markerGroup) : null;
                        break;
                    case'square':
                    case'polygon':
                    case'triangle':
                    case'cross':
                        topMarker = this.visibleTopMarker ? renderer.createArea(this.topPoints, this.options.attributes).append(markerGroup) : null;
                        bottomMarker = this.visibleBottomMarker ? renderer.createArea(this.bottomPoints, this.options.attributes).append(markerGroup) : null;
                        break
                }
                this.graphic = markerGroup;
                this.graphic.topMarker = topMarker;
                this.graphic.bottomMarker = bottomMarker;
                switch (this.state) {
                    case statesConsts.selected:
                        this.series.setPointSelectedState(this);
                        break;
                    case statesConsts.hover:
                        this.series.setPointHoverState(this);
                        break;
                    default:
                        this.state = statesConsts.normal;
                        this.fullState = statesConsts.normalMark
                }
            },
            _populatePointShape: function(target, radius) {
                var self = this,
                    floorHalfRadius,
                    ceilHalfRadius,
                    topX,
                    topY,
                    bottomX,
                    bottomY;
                if (!this.rotated) {
                    topX = bottomX = self.x;
                    topY = Math.min(self.y, self.minY);
                    bottomY = Math.max(self.y, self.minY)
                }
                else {
                    topX = Math.max(self.x, self.minX);
                    bottomX = Math.min(self.x, self.minX);
                    topY = bottomY = self.y
                }
                if (self.options.symbol === 'square') {
                    target.topPoints = [{
                            x: topX - radius,
                            y: topY - radius
                        }, {
                            x: topX + radius,
                            y: topY - radius
                        }, {
                            x: topX + radius,
                            y: topY + radius
                        }, {
                            x: topX - radius,
                            y: topY + radius
                        }, {
                            x: topX - radius,
                            y: topY - radius
                        }];
                    target.bottomPoints = [{
                            x: bottomX - radius,
                            y: bottomY - radius
                        }, {
                            x: bottomX + radius,
                            y: bottomY - radius
                        }, {
                            x: bottomX + radius,
                            y: bottomY + radius
                        }, {
                            x: bottomX - radius,
                            y: bottomY + radius
                        }, {
                            x: bottomX - radius,
                            y: bottomY - radius
                        }]
                }
                if (self.options.symbol === 'polygon') {
                    target.topPoints = [{
                            x: topX - radius,
                            y: topY
                        }, {
                            x: topX,
                            y: topY - radius
                        }, {
                            x: topX + radius,
                            y: topY
                        }, {
                            x: topX,
                            y: topY + radius
                        }, {
                            x: topX - radius,
                            y: topY
                        }];
                    target.bottomPoints = [{
                            x: bottomX - radius,
                            y: bottomY
                        }, {
                            x: bottomX,
                            y: bottomY - radius
                        }, {
                            x: bottomX + radius,
                            y: bottomY
                        }, {
                            x: bottomX,
                            y: bottomY + radius
                        }, {
                            x: bottomX - radius,
                            y: bottomY
                        }]
                }
                if (self.options.symbol === 'triangle') {
                    target.topPoints = [{
                            x: topX - radius,
                            y: topY - radius
                        }, {
                            x: topX + radius,
                            y: topY - radius
                        }, {
                            x: topX,
                            y: topY + radius
                        }, {
                            x: topX - radius,
                            y: topY - radius
                        }];
                    target.bottomPoints = [{
                            x: bottomX - radius,
                            y: bottomY - radius
                        }, {
                            x: bottomX + radius,
                            y: bottomY - radius
                        }, {
                            x: bottomX,
                            y: bottomY + radius
                        }, {
                            x: bottomX - radius,
                            y: bottomY - radius
                        }]
                }
                if (self.options.symbol === 'cross') {
                    floorHalfRadius = Math.floor(radius / 2);
                    ceilHalfRadius = Math.ceil(radius / 2);
                    target.topPoints = [{
                            x: topX - radius,
                            y: topY - floorHalfRadius
                        }, {
                            x: topX - floorHalfRadius,
                            y: topY - radius
                        }, {
                            x: topX,
                            y: topY - ceilHalfRadius
                        }, {
                            x: topX + floorHalfRadius,
                            y: topY - radius
                        }, {
                            x: topX + radius,
                            y: topY - floorHalfRadius
                        }, {
                            x: topX + ceilHalfRadius,
                            y: topY
                        }, {
                            x: topX + radius,
                            y: topY + floorHalfRadius
                        }, {
                            x: topX + floorHalfRadius,
                            y: topY + radius
                        }, {
                            x: topX,
                            y: topY + ceilHalfRadius
                        }, {
                            x: topX - floorHalfRadius,
                            y: topY + radius
                        }, {
                            x: topX - radius,
                            y: topY + floorHalfRadius
                        }, {
                            x: topX - ceilHalfRadius,
                            y: topY
                        }];
                    target.bottomPoints = [{
                            x: bottomX - radius,
                            y: bottomY - floorHalfRadius
                        }, {
                            x: bottomX - floorHalfRadius,
                            y: bottomY - radius
                        }, {
                            x: bottomX,
                            y: bottomY - ceilHalfRadius
                        }, {
                            x: bottomX + floorHalfRadius,
                            y: bottomY - radius
                        }, {
                            x: bottomX + radius,
                            y: bottomY - floorHalfRadius
                        }, {
                            x: bottomX + ceilHalfRadius,
                            y: bottomY
                        }, {
                            x: bottomX + radius,
                            y: bottomY + floorHalfRadius
                        }, {
                            x: bottomX + floorHalfRadius,
                            y: bottomY + radius
                        }, {
                            x: bottomX,
                            y: bottomY + ceilHalfRadius
                        }, {
                            x: bottomX - floorHalfRadius,
                            y: bottomY + radius
                        }, {
                            x: bottomX - radius,
                            y: bottomY + floorHalfRadius
                        }, {
                            x: bottomX - ceilHalfRadius,
                            y: bottomY
                        }]
                }
            },
            drawTrackerMarker: function(renderer, trackerGroup) {
                if (!this.hasValue())
                    return;
                var _this = this,
                    options = _this.options,
                    radius = options.trackerR || _this.storeTrackerR(),
                    x,
                    y;
                if (!_this.rotated) {
                    x = _this.x - radius;
                    y = Math.min(_this.y, _this.minY) - radius
                }
                else {
                    x = Math.min(_this.x, _this.minX) - radius;
                    y = _this.y - radius
                }
                _this.trackerGraphic = renderer.createRect(x, y, _this.width + 2 * radius, _this.height + 2 * radius, 0, _this._trackerAttrs).append(trackerGroup);
                _this.trackerGraphic.data({point: _this})
            },
            applyStyle: function(style) {
                if (this.graphic) {
                    this._populatePointShape(style, style.r);
                    if (this.graphic.topMarker)
                        this.graphic.topMarker.applySettings(style.topPoints ? {
                            points: style.topPoints,
                            style: style
                        } : style);
                    if (this.graphic.bottomMarker)
                        this.graphic.bottomMarker.applySettings(style.bottomPoints ? {
                            points: style.bottomPoints,
                            style: style
                        } : style)
                }
            },
            applyNormalStyle: function() {
                this.applyStyle(this.options.states.normal);
                return this.callBase()
            },
            applyHoverStyle: function() {
                this.applyStyle(this.options.states.hover);
                return this.callBase()
            },
            applySelectionStyle: function() {
                this.applyStyle(this.options.states.selected);
                return this.callBase()
            },
            drawLabel: function(renderer, group) {
                if (!this.hasValue())
                    return;
                if (!utils.isDefined(this.labelFormatObject.value) || !utils.isDefined(this.minLabelFormatObject.value))
                    return;
                var labelOptions = this.options.label,
                    maxLabelText = this.formatLabel.call(this.labelFormatObject, labelOptions),
                    minLabelText = this.formatLabel.call(this.minLabelFormatObject, labelOptions),
                    businessRange = this.translator.getBusinessRange(),
                    isDiscreteValue = this.series.options.valueAxisType === 'discrete',
                    notInverted = isDiscreteValue && (!businessRange.invertY && !this.rotated || businessRange.invertX && this.rotated) || !isDiscreteValue && this.value > this.minValue && (!businessRange.invertY && !this.rotated || !businessRange.invertX && this.rotated);
                if (!utils.isDefined(maxLabelText) || !utils.isDefined(minLabelText))
                    return;
                this.labelGroup = renderer.createGroup().append(group);
                if (this.options.label.connector && this.options.label.connector.strokeWidth) {
                    if (this.visibleTopMarker)
                        this.maxConnector = renderer.createLine(0, 0, 0, 0, this.options.label.connector).append(this.labelGroup);
                    if (this.visibleBottomMarker)
                        this.minConnector = renderer.createLine(0, 0, 0, 0, this.options.label.connector).append(this.labelGroup)
                }
                this.maxLabelGroup = renderer.createGroup().append(this.labelGroup);
                this.insideMaxLabelGroup = renderer.createGroup().append(this.maxLabelGroup);
                this.minLabelGroup = renderer.createGroup().append(this.labelGroup);
                this.insideMinLabelGroup = renderer.createGroup().append(this.minLabelGroup);
                if (labelOptions.background.fill && labelOptions.background.fill !== 'none' || labelOptions.background.strokeWidth && labelOptions.background.stroke && labelOptions.background.stroke !== 'none') {
                    this.maxLabelBackground = renderer.createRect(this.x, this.y, 0, 0, 0, labelOptions.background).append(this.insideMaxLabelGroup);
                    this.minLabelBackground = renderer.createRect(this.x, this.y, 0, 0, 0, labelOptions.background).append(this.insideMinLabelGroup)
                }
                this.maxLabel = renderer.createText(notInverted ? maxLabelText : minLabelText, this.x, this.y, labelOptions.attributes).append(this.insideMaxLabelGroup);
                this.minLabel = renderer.createText(notInverted ? minLabelText : maxLabelText, this.x, this.y, labelOptions.attributes).append(this.insideMinLabelGroup);
                this.correctLabel();
                this.correctConnectorPosition(this.maxLabelGroup.getBBox(), this.maxConnector);
                this.correctConnectorPosition(this.minLabelGroup.getBBox(), this.minConnector)
            },
            rotateLabel: function() {
                var bboxmax = this.insideMaxLabelGroup.getBBox(),
                    bboxmin = this.insideMinLabelGroup.getBBox(),
                    labelOptions = this.options.label;
                this.insideMaxLabelGroup.applySettings({
                    x: bboxmax.x + bboxmax.width / 2,
                    y: bboxmax.y + bboxmax.height / 2,
                    rotate: labelOptions.rotationAngle
                });
                this.insideMinLabelGroup.applySettings({
                    x: bboxmin.x + bboxmin.width / 2,
                    y: bboxmin.y + bboxmin.height / 2,
                    rotate: labelOptions.rotationAngle
                })
            },
            correctLabelPosition: function() {
                var maxbbox = this.insideMaxLabelGroup.getBBox(),
                    minbbox = this.insideMinLabelGroup.getBBox(),
                    topBBoxgraphic = this.graphic && this.graphic.topMarker ? this.graphic.topMarker.getBBox() : {
                        x: this.rotated ? Math.max(this.x, this.minX) : this.x,
                        y: !this.rotated ? Math.min(this.y, this.minY) : this.y,
                        height: 0,
                        width: 0
                    },
                    bottomBBoxgraphic = this.graphic && this.graphic.bottomMarker ? this.graphic.bottomMarker.getBBox() : {
                        x: this.rotated ? Math.min(this.x, this.minX) : this.x,
                        y: !this.rotated ? Math.max(this.y, this.minY) : this.y,
                        height: 0,
                        width: 0
                    },
                    x1 = 0,
                    y1 = 0,
                    x2 = 0,
                    y2 = 0;
                if (this.options.label.position === 'outside')
                    if (!this.rotated) {
                        y1 += topBBoxgraphic.y - maxbbox.y - maxbbox.height - this.LABEL_OFFSET;
                        y2 += bottomBBoxgraphic.y + bottomBBoxgraphic.height - minbbox.y + this.LABEL_OFFSET
                    }
                    else {
                        y1 = y2 += topBBoxgraphic.y - maxbbox.y - maxbbox.height / 2 + topBBoxgraphic.height / 2;
                        x1 += topBBoxgraphic.x + topBBoxgraphic.width - maxbbox.x + this.LABEL_OFFSET;
                        x2 += bottomBBoxgraphic.x - minbbox.x - minbbox.width - this.LABEL_OFFSET
                    }
                else if (this.options.label.position === 'inside')
                    if (!this.rotated) {
                        y1 += topBBoxgraphic.y + topBBoxgraphic.height - maxbbox.y + this.LABEL_OFFSET;
                        y2 += bottomBBoxgraphic.y - minbbox.y - minbbox.height - this.LABEL_OFFSET
                    }
                    else {
                        y1 = y2 += topBBoxgraphic.y - maxbbox.y - maxbbox.height / 2 + topBBoxgraphic.height / 2;
                        x1 += topBBoxgraphic.x - maxbbox.x - maxbbox.width - this.LABEL_OFFSET;
                        x2 += bottomBBoxgraphic.x + bottomBBoxgraphic.width - minbbox.x + this.LABEL_OFFSET
                    }
                x1 += this.options.label.horizontalOffset;
                y1 += this.options.label.verticalOffset;
                x2 += this.options.label.horizontalOffset;
                y2 += this.options.label.verticalOffset;
                this.checkLabelPosition(x1, y1, x2, y2)
            },
            checkLabelPosition: function(x1, y1, x2, y2) {
                var maxgroupbbox = this.insideMaxLabelGroup.getBBox(),
                    mingroupbbox = this.insideMinLabelGroup.getBBox(),
                    newMaxbbox = {},
                    newMinbbox = {},
                    topBBoxgraphic = this.graphic && this.graphic.topMarker ? this.graphic.topMarker.getBBox() : {
                        x: this.rotated ? Math.max(this.x, this.minX) : this.x,
                        y: !this.rotated ? Math.min(this.y, this.minY) : this.y,
                        height: 0,
                        width: 0
                    },
                    bottomBBoxgraphic = this.graphic && this.graphic.bottomMarker ? this.graphic.bottomMarker.getBBox() : {
                        x: this.rotated ? Math.min(this.x, this.minX) : this.x,
                        y: !this.rotated ? Math.max(this.y, this.minY) : this.y,
                        height: 0,
                        width: 0
                    },
                    maxX = maxgroupbbox.x + x1,
                    maxY = maxgroupbbox.y + y1,
                    minX = mingroupbbox.x + x2,
                    minY = mingroupbbox.y + y2;
                var visibleArea = this.translator.getCanvasVisibleArea();
                if (this.visibleRangeArea) {
                    if (!this.rotated) {
                        if (visibleArea.minX > maxX && this.adjustSeriesLabels)
                            x1 += visibleArea.minX - maxX;
                        if (visibleArea.minX > minX && this.adjustSeriesLabels)
                            x2 += visibleArea.minX - minX;
                        if (visibleArea.maxX < maxX + maxgroupbbox.width && this.adjustSeriesLabels)
                            x1 -= maxX + maxgroupbbox.width - visibleArea.maxX;
                        if (visibleArea.maxX < minX + mingroupbbox.width && this.adjustSeriesLabels)
                            x2 -= minX + mingroupbbox.width - visibleArea.maxX;
                        if (visibleArea.minY > maxY)
                            y1 += visibleArea.minY - maxY;
                        if (visibleArea.maxY < minY + mingroupbbox.height)
                            y2 -= minY + mingroupbbox.height - visibleArea.maxY;
                        newMaxbbox.y = maxgroupbbox.y + y1;
                        newMinbbox.y = mingroupbbox.y + y2;
                        if (newMaxbbox.y + maxgroupbbox.height > newMinbbox.y) {
                            y1 -= (newMaxbbox.y + maxgroupbbox.height - newMinbbox.y) / 2;
                            y2 += (newMaxbbox.y + maxgroupbbox.height - newMinbbox.y) / 2;
                            newMaxbbox.y = maxgroupbbox.y + y1;
                            newMinbbox.y = mingroupbbox.y + y2;
                            if (visibleArea.minY > newMaxbbox.y) {
                                y2 += visibleArea.minY - newMaxbbox.y;
                                y1 += visibleArea.minY - newMaxbbox.y
                            }
                            else if (visibleArea.maxY < newMinbbox.y + mingroupbbox.height) {
                                y1 -= newMinbbox.y + mingroupbbox.height - visibleArea.maxY;
                                y2 -= newMinbbox.y + mingroupbbox.height - visibleArea.maxY
                            }
                        }
                    }
                    if (this.rotated) {
                        if (visibleArea.minX > minX)
                            x2 += visibleArea.minX - minX;
                        if (visibleArea.maxX < maxX + maxgroupbbox.width)
                            x1 -= maxX + maxgroupbbox.width - visibleArea.maxX;
                        if (visibleArea.minY > minY && this.adjustSeriesLabels)
                            y2 += visibleArea.minY - minY;
                        if (visibleArea.minY > maxY && this.adjustSeriesLabels)
                            y1 += visibleArea.minY - maxY;
                        if (visibleArea.maxY < minY + mingroupbbox.height && this.adjustSeriesLabels)
                            y2 -= minY + mingroupbbox.height - visibleArea.maxY;
                        if (visibleArea.maxY < maxY + maxgroupbbox.height && this.adjustSeriesLabels)
                            y1 -= maxY + maxgroupbbox.height - visibleArea.maxY;
                        newMaxbbox.x = maxgroupbbox.x + x1;
                        newMinbbox.x = mingroupbbox.x + x2;
                        if (newMaxbbox.x < newMinbbox.x + mingroupbbox.width) {
                            x1 += (newMinbbox.x + mingroupbbox.width - newMaxbbox.x) / 2;
                            x2 -= (newMinbbox.x + mingroupbbox.width - newMaxbbox.x) / 2;
                            newMaxbbox.x = maxgroupbbox.x + x1;
                            newMinbbox.x = mingroupbbox.x + x2;
                            if (visibleArea.minX > newMinbbox.x) {
                                x2 += visibleArea.minX - newMinbbox.x;
                                x1 += visibleArea.minX - newMinbbox.x
                            }
                            else if (visibleArea.maxX < newMaxbbox.x + maxgroupbbox.width) {
                                x1 -= newMaxbbox.x + maxgroupbbox.width - visibleArea.maxX;
                                x2 -= newMaxbbox.x + maxgroupbbox.width - visibleArea.maxX
                            }
                        }
                    }
                }
                this.insideMaxLabelGroup.move(~~x1, ~~y1);
                this.insideMinLabelGroup.move(~~x2, ~~y2)
            },
            correctBackgroundPosition: function() {
                if (!this.maxLabelBackground || !this.minLabelBackground)
                    return;
                var maxbbox = this.maxLabel.getBBox(),
                    minbbox = this.minLabel.getBBox(),
                    x1 = maxbbox.x - this.LABEL_BACKGROUND_PADDING_X,
                    x2 = minbbox.x - this.LABEL_BACKGROUND_PADDING_X,
                    y1 = maxbbox.y - this.LABEL_BACKGROUND_PADDING_Y,
                    y2 = minbbox.y - this.LABEL_BACKGROUND_PADDING_Y,
                    width1 = maxbbox.width + 2 * this.LABEL_BACKGROUND_PADDING_X,
                    width2 = minbbox.width + 2 * this.LABEL_BACKGROUND_PADDING_X,
                    height1 = maxbbox.height + 2 * this.LABEL_BACKGROUND_PADDING_Y,
                    height2 = minbbox.height + 2 * this.LABEL_BACKGROUND_PADDING_Y;
                this.maxLabelBackground.applySettings({
                    x: x1,
                    y: y1,
                    width: width1,
                    height: height1
                });
                this.minLabelBackground.applySettings({
                    x: x2,
                    y: y2,
                    width: width2,
                    height: height2
                })
            },
            correctConnectorPosition: function(bbox, connector) {
                if (!connector)
                    return;
                var bboxgraphic = this.graphic ? this.graphic.getBBox() : {
                        x: this.rotated ? Math.min(this.x, this.minX) : this.x,
                        y: !this.rotated ? Math.min(this.y, this.minY) : this.y,
                        height: this.height,
                        width: this.width
                    },
                    centerLabelY = this.maxLabelBackground || this.minLabelBackground ? bbox.y + bbox.height / 2 : null,
                    centerLabelX = this.maxLabelBackground || this.minLabelBackground ? bbox.x + bbox.width / 2 : null,
                    x1,
                    x2,
                    y1,
                    y2;
                if (!this.rotated) {
                    if ((centerLabelY || bbox.y + bbox.height) < bboxgraphic.y) {
                        y1 = centerLabelY || bbox.y + bbox.height;
                        y2 = bboxgraphic.y
                    }
                    else if ((centerLabelY || bbox.y) > bboxgraphic.y + bboxgraphic.height) {
                        y1 = centerLabelY || bbox.y;
                        y2 = bboxgraphic.y + bboxgraphic.height
                    }
                    else
                        return false;
                    x1 = Math.round(bbox.x + bbox.width / 2);
                    if (x1 > bboxgraphic.x + bboxgraphic.width)
                        x2 = bboxgraphic.x + bboxgraphic.width;
                    else if (x1 < bboxgraphic.x)
                        x2 = bboxgraphic.x;
                    else
                        x2 = x1
                }
                else {
                    if ((centerLabelX || bbox.x) > bboxgraphic.x + bboxgraphic.width) {
                        x1 = centerLabelX || bbox.x;
                        x2 = bboxgraphic.x + bboxgraphic.width
                    }
                    else if ((centerLabelX || bbox.x + bbox.width) < bboxgraphic.x) {
                        x1 = centerLabelX || bbox.x + bbox.width;
                        x2 = bboxgraphic.x
                    }
                    else
                        return false;
                    y1 = Math.round(bbox.y + bbox.height / 2);
                    if (y1 > bboxgraphic.y + bboxgraphic.height)
                        y2 = bboxgraphic.y + bboxgraphic.height;
                    else if (y1 < bboxgraphic.y)
                        y2 = bboxgraphic.y;
                    else
                        y2 = y1
                }
                connector.applySettings({points: [x1, y1, x2, y2]})
            },
            getTooltipFormatObject: function(tooltip) {
                var minValue = tooltip.formatValueTooltip.call({value: this.initialMinValue}, tooltip.options),
                    value = tooltip.formatValueTooltip.call({value: this.initialValue}, tooltip.options);
                return {
                        argument: this.initialArgument,
                        valueText: minValue + ' - ' + value,
                        rangeValue1Text: minValue,
                        rangeValue2Text: value,
                        rangeValue1: this.initialMinValue,
                        rangeValue2: this.initialValue,
                        seriesName: this.options.seriesName,
                        point: this,
                        originalMinValue: this.originalMinValue,
                        originalValue: this.originalValue,
                        originalArgument: this.originalArgument
                    }
            },
            animate: function() {
                var _this = this,
                    graphic = _this.graphic;
                if (!graphic || !_this.translator)
                    return;
                if (!_this.rotated) {
                    if (graphic.topMarker)
                        graphic.topMarker.move(0, _this.defaultY - Math.min(_this.minY, _this.y));
                    if (graphic.bottomMarker)
                        graphic.bottomMarker.move(0, _this.defaultY - Math.max(_this.minY, _this.y))
                }
                else {
                    if (graphic.topMarker)
                        graphic.topMarker.move(_this.defaultX - Math.max(_this.minX, _this.x), 0);
                    if (graphic.bottomMarker)
                        graphic.bottomMarker.move(_this.defaultX - Math.min(_this.minX, _this.x), 0)
                }
                if (graphic.topMarker)
                    graphic.topMarker.move(0, 0, true);
                if (graphic.bottomMarker)
                    graphic.bottomMarker.move(0, 0, true)
            },
            stopAnimation: function() {
                var graphic = this.graphic,
                    marker;
                this.callBase();
                if (!graphic)
                    return;
                marker = graphic.topMarker;
                if (marker)
                    marker.stopAnimation();
                marker = graphic.bottomMarker;
                if (marker)
                    marker.stopAnimation()
            },
            hasValue: function() {
                return this.initialValue !== null && this.initialMinValue !== null
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file rangeBarPoint.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            BarPoint = series.BarPoint,
            utils = DX.utils;
        series.RangeBarPoint = series.BarPoint.inherit({
            ctor: function(data) {
                this.callBase(data);
                this.minValue = this.initialMinValue = data.minValue !== undefined ? data.minValue : 'default';
                this.originalMinValue = data.originalMinValue;
                this.minLabelFormatObject = {
                    argument: this.initialArgument,
                    value: this.initialMinValue,
                    seriesName: this.options.seriesName,
                    originalMinValue: this.originalMinValue,
                    originalArgument: this.originalArgument
                }
            },
            dispose: function() {
                var _this = this;
                _this.minLabel = null;
                _this.minLabelBackground = null;
                _this.minConnector = null;
                _this.insideMinLabelGroup = null;
                _this.minLabelGroup = null;
                _this.maxLabel = null;
                _this.maxLabelBackground = null;
                _this.maxConnector = null;
                _this.insideMaxLabelGroup = null;
                _this.maxLabelGroup = null;
                _this.minLabelFormatObject = null;
                _this.callBase()
            },
            translate: function(translator) {
                if (!this.hasValue())
                    return;
                this.callBase(translator);
                if (this.rotated)
                    this.width = this.width || 1;
                else
                    this.height = this.height || 1
            },
            drawLabel: function(renderer, group) {
                if (!this.hasValue() && (!utils.isDefined(this.labelFormatObject.value) || !utils.isDefined(this.minLabelFormatObject.value)))
                    return;
                var labelOptions = this.options.label,
                    maxLabelText = this.formatLabel.call(this.labelFormatObject, labelOptions),
                    minLabelText = this.formatLabel.call(this.minLabelFormatObject, labelOptions),
                    businessRange = this.translator.getBusinessRange(),
                    isDiscreteValue = this.series.options.valueAxisType === 'discrete',
                    notInverted = isDiscreteValue && (!businessRange.invertY && !this.rotated || businessRange.invertX && this.rotated) || !isDiscreteValue && this.value > this.minValue && (!businessRange.invertY && !this.rotated || !businessRange.invertX && this.rotated);
                if (!utils.isDefined(maxLabelText) || !utils.isDefined(minLabelText))
                    return;
                this.labelGroup = renderer.createGroup().append(group);
                if (this.options.label.connector && this.options.label.connector.strokeWidth) {
                    this.maxConnector = renderer.createLine(0, 0, 0, 0, this.options.label.connector).append(this.labelGroup);
                    this.minConnector = renderer.createLine(0, 0, 0, 0, this.options.label.connector).append(this.labelGroup)
                }
                this.maxLabelGroup = renderer.createGroup().append(this.labelGroup);
                this.insideMaxLabelGroup = renderer.createGroup().append(this.maxLabelGroup);
                this.minLabelGroup = renderer.createGroup().append(this.labelGroup);
                this.insideMinLabelGroup = renderer.createGroup().append(this.minLabelGroup);
                if (labelOptions.background.fill && labelOptions.background.fill !== 'none' || labelOptions.background.strokeWidth && labelOptions.background.stroke && labelOptions.background.stroke !== 'none') {
                    this.maxLabelBackground = renderer.createRect(this.x, this.y, 0, 0, 0, labelOptions.background).append(this.insideMaxLabelGroup);
                    this.minLabelBackground = renderer.createRect(this.x, this.y, 0, 0, 0, labelOptions.background).append(this.insideMinLabelGroup)
                }
                this.maxLabel = renderer.createText(notInverted ? maxLabelText : minLabelText, this.x, this.y, labelOptions.attributes).append(this.insideMaxLabelGroup);
                this.minLabel = renderer.createText(notInverted ? minLabelText : maxLabelText, this.x, this.y, labelOptions.attributes).append(this.insideMinLabelGroup);
                this.correctLabel();
                this.correctConnectorPosition(this.maxLabelGroup.getBBox(), this.maxConnector);
                this.correctConnectorPosition(this.minLabelGroup.getBBox(), this.minConnector)
            },
            rotateLabel: function() {
                var bboxmax = this.insideMaxLabelGroup.getBBox(),
                    bboxmin = this.insideMinLabelGroup.getBBox(),
                    labelOptions = this.options.label;
                this.insideMaxLabelGroup.applySettings({
                    x: bboxmax.x + bboxmax.width / 2,
                    y: bboxmax.y + bboxmax.height / 2,
                    rotate: labelOptions.rotationAngle
                });
                this.insideMinLabelGroup.applySettings({
                    x: bboxmin.x + bboxmin.width / 2,
                    y: bboxmin.y + bboxmin.height / 2,
                    rotate: labelOptions.rotationAngle
                })
            },
            correctLabelPosition: function() {
                var maxbbox = this.insideMaxLabelGroup.getBBox(),
                    minbbox = this.insideMinLabelGroup.getBBox(),
                    bboxgraphic = this.graphic.getBBox(),
                    x1 = 0,
                    y1 = 0,
                    x2 = 0,
                    y2 = 0;
                if (bboxgraphic.isEmpty)
                    bboxgraphic = this.getGraphicSettings();
                if (this.options.label.position === 'outside')
                    if (!this.rotated) {
                        x1 = x2 += bboxgraphic.width / 2;
                        y1 += bboxgraphic.y - maxbbox.y - maxbbox.height - this.LABEL_OFFSET;
                        y2 += bboxgraphic.y + bboxgraphic.height - minbbox.y + this.LABEL_OFFSET
                    }
                    else {
                        y1 = y2 += bboxgraphic.y - maxbbox.y - maxbbox.height / 2 + bboxgraphic.height / 2;
                        x1 += bboxgraphic.x + bboxgraphic.width - maxbbox.x + this.LABEL_OFFSET;
                        x2 += bboxgraphic.x - minbbox.x - minbbox.width - this.LABEL_OFFSET
                    }
                else if (this.options.label.position === 'inside')
                    if (!this.rotated) {
                        x1 = x2 += bboxgraphic.width / 2;
                        y1 += bboxgraphic.y - maxbbox.y + this.LABEL_OFFSET;
                        y2 += bboxgraphic.y + bboxgraphic.height - minbbox.y - minbbox.height - this.LABEL_OFFSET
                    }
                    else {
                        y1 = y2 += bboxgraphic.y - maxbbox.y - maxbbox.height / 2 + bboxgraphic.height / 2;
                        x1 += bboxgraphic.x + bboxgraphic.width - maxbbox.x - maxbbox.width - this.LABEL_OFFSET;
                        x2 += bboxgraphic.x - minbbox.x + this.LABEL_OFFSET
                    }
                x1 += this.options.label.horizontalOffset;
                y1 += this.options.label.verticalOffset;
                x2 += this.options.label.horizontalOffset;
                y2 += this.options.label.verticalOffset;
                this.checkLabelPosition(x1, y1, x2, y2)
            },
            checkLabelPosition: function(x1, y1, x2, y2) {
                var maxgroupbbox = this.insideMaxLabelGroup.getBBox(),
                    mingroupbbox = this.insideMinLabelGroup.getBBox(),
                    newMaxbbox = {},
                    newMinbbox = {},
                    bboxgraphic = this.graphic.getBBox(),
                    maxX = maxgroupbbox.x + x1,
                    maxY = maxgroupbbox.y + y1,
                    minX = mingroupbbox.x + x2,
                    minY = mingroupbbox.y + y2;
                var visibleArea = this.translator.getCanvasVisibleArea();
                if (visibleArea.minX <= bboxgraphic.x + bboxgraphic.width && visibleArea.maxX >= bboxgraphic.x && visibleArea.minY <= bboxgraphic.y + bboxgraphic.height && visibleArea.maxY >= bboxgraphic.y) {
                    if (!this.rotated) {
                        if (visibleArea.minX > maxX && this.adjustSeriesLabels)
                            x1 += visibleArea.minX - maxX;
                        if (visibleArea.minX > minX && this.adjustSeriesLabels)
                            x2 += visibleArea.minX - minX;
                        if (visibleArea.maxX < maxX + maxgroupbbox.width && this.adjustSeriesLabels)
                            x1 -= maxX + maxgroupbbox.width - visibleArea.maxX;
                        if (visibleArea.maxX < minX + mingroupbbox.width && this.adjustSeriesLabels)
                            x2 -= minX + mingroupbbox.width - visibleArea.maxX;
                        if (visibleArea.minY > maxY)
                            y1 += visibleArea.minY - maxY;
                        if (visibleArea.maxY < minY + mingroupbbox.height)
                            y2 -= minY + mingroupbbox.height - visibleArea.maxY;
                        newMaxbbox.y = maxgroupbbox.y + y1;
                        newMinbbox.y = mingroupbbox.y + y2;
                        if (newMaxbbox.y + maxgroupbbox.height > newMinbbox.y) {
                            y1 -= (newMaxbbox.y + maxgroupbbox.height - newMinbbox.y) / 2;
                            y2 += (newMaxbbox.y + maxgroupbbox.height - newMinbbox.y) / 2;
                            newMaxbbox.y = maxgroupbbox.y + y1;
                            newMinbbox.y = mingroupbbox.y + y2;
                            if (visibleArea.minY > newMaxbbox.y) {
                                y2 += visibleArea.minY - newMaxbbox.y;
                                y1 += visibleArea.minY - newMaxbbox.y
                            }
                            else if (visibleArea.maxY < newMinbbox.y + mingroupbbox.height) {
                                y1 -= newMinbbox.y + mingroupbbox.height - visibleArea.maxY;
                                y2 -= newMinbbox.y + mingroupbbox.height - visibleArea.maxY
                            }
                        }
                    }
                    if (this.rotated) {
                        if (visibleArea.minX > minX)
                            x2 += visibleArea.minX - minX;
                        if (visibleArea.maxX < maxX + maxgroupbbox.width)
                            x1 -= maxX + maxgroupbbox.width - visibleArea.maxX;
                        if (visibleArea.minY > minY && this.adjustSeriesLabels)
                            y2 += visibleArea.minY - minY;
                        if (visibleArea.minY > maxY && this.adjustSeriesLabels)
                            y1 += visibleArea.minY - maxY;
                        if (visibleArea.maxY < minY + mingroupbbox.height && this.adjustSeriesLabels)
                            y2 -= minY + mingroupbbox.height - visibleArea.maxY;
                        if (visibleArea.maxY < maxY + maxgroupbbox.height && this.adjustSeriesLabels)
                            y1 -= maxY + maxgroupbbox.height - visibleArea.maxY;
                        newMaxbbox.x = maxgroupbbox.x + x1;
                        newMinbbox.x = mingroupbbox.x + x2;
                        if (newMaxbbox.x < newMinbbox.x + mingroupbbox.width) {
                            x1 += (newMinbbox.x + mingroupbbox.width - newMaxbbox.x) / 2;
                            x2 -= (newMinbbox.x + mingroupbbox.width - newMaxbbox.x) / 2;
                            newMaxbbox.x = maxgroupbbox.x + x1;
                            newMinbbox.x = mingroupbbox.x + x2;
                            if (visibleArea.minX > newMinbbox.x) {
                                x2 += visibleArea.minX - newMinbbox.x;
                                x1 += visibleArea.minX - newMinbbox.x
                            }
                            else if (visibleArea.maxX < newMaxbbox.x + maxgroupbbox.width) {
                                x1 -= newMaxbbox.x + maxgroupbbox.width - visibleArea.maxX;
                                x2 -= newMaxbbox.x + maxgroupbbox.width - visibleArea.maxX
                            }
                        }
                    }
                }
                this.insideMaxLabelGroup.move(~~x1, ~~y1);
                this.insideMinLabelGroup.move(~~x2, ~~y2)
            },
            correctBackgroundPosition: function() {
                if (!this.maxLabelBackground || !this.minLabelBackground)
                    return;
                var maxbbox = this.maxLabel.getBBox(),
                    minbbox = this.minLabel.getBBox(),
                    x1 = maxbbox.x - this.LABEL_BACKGROUND_PADDING_X,
                    x2 = minbbox.x - this.LABEL_BACKGROUND_PADDING_X,
                    y1 = maxbbox.y - this.LABEL_BACKGROUND_PADDING_Y,
                    y2 = minbbox.y - this.LABEL_BACKGROUND_PADDING_Y,
                    width1 = maxbbox.width + 2 * this.LABEL_BACKGROUND_PADDING_X,
                    width2 = minbbox.width + 2 * this.LABEL_BACKGROUND_PADDING_X,
                    height1 = maxbbox.height + 2 * this.LABEL_BACKGROUND_PADDING_Y,
                    height2 = minbbox.height + 2 * this.LABEL_BACKGROUND_PADDING_Y;
                this.maxLabelBackground.applySettings({
                    x: x1,
                    y: y1,
                    width: width1,
                    height: height1
                });
                this.minLabelBackground.applySettings({
                    x: x2,
                    y: y2,
                    width: width2,
                    height: height2
                })
            },
            correctConnectorPosition: function(bbox, connector) {
                if (!connector)
                    return;
                var bboxgraphic = this.graphic.getBBox(),
                    x1,
                    x2,
                    y1,
                    y2,
                    centerLabelY = this.maxLabelBackground || this.minLabelBackground ? bbox.y + bbox.height / 2 : null,
                    centerLabelX = this.maxLabelBackground || this.minLabelBackground ? bbox.x + bbox.width / 2 : null;
                if (bboxgraphic.isEmpty)
                    bboxgraphic = this.getGraphicSettings();
                if (!this.rotated) {
                    if ((centerLabelY || bbox.y + bbox.height) < bboxgraphic.y) {
                        y1 = centerLabelY || bbox.y + bbox.height;
                        y2 = bboxgraphic.y
                    }
                    else if ((centerLabelY || bbox.y) > bboxgraphic.y + bboxgraphic.height) {
                        y1 = centerLabelY || bbox.y;
                        y2 = bboxgraphic.y + bboxgraphic.height
                    }
                    else
                        return false;
                    x1 = Math.round(bbox.x + bbox.width / 2);
                    if (x1 > bboxgraphic.x + bboxgraphic.width)
                        x2 = bboxgraphic.x + bboxgraphic.width;
                    else if (x1 < bboxgraphic.x)
                        x2 = bboxgraphic.x;
                    else
                        x2 = x1
                }
                else {
                    if ((centerLabelX || bbox.x) > bboxgraphic.x + bboxgraphic.width) {
                        x1 = centerLabelX || bbox.x;
                        x2 = bboxgraphic.x + bboxgraphic.width
                    }
                    else if ((centerLabelX || bbox.x + bbox.width) < bboxgraphic.x) {
                        x1 = centerLabelX || bbox.x + bbox.width;
                        x2 = bboxgraphic.x
                    }
                    else
                        return false;
                    y1 = Math.round(bbox.y + bbox.height / 2);
                    if (y1 > bboxgraphic.y + bboxgraphic.height)
                        y2 = bboxgraphic.y + bboxgraphic.height;
                    else if (y1 < bboxgraphic.y)
                        y2 = bboxgraphic.y;
                    else
                        y2 = y1
                }
                connector.applySettings({points: [x1, y1, x2, y2]})
            },
            getTooltipFormatObject: function(tooltip) {
                var minValue = tooltip.formatValueTooltip.call({value: this.initialMinValue}, tooltip.options),
                    value = tooltip.formatValueTooltip.call({value: this.initialValue}, tooltip.options);
                return {
                        argument: this.initialArgument,
                        valueText: minValue + ' - ' + value,
                        rangeValue1Text: minValue,
                        rangeValue2Text: value,
                        rangeValue1: this.initialMinValue,
                        rangeValue2: this.initialValue,
                        seriesName: this.options.seriesName,
                        point: this,
                        originalMinValue: this.originalMinValue,
                        originalValue: this.originalValue,
                        originalArgument: this.originalArgument
                    }
            },
            hasValue: function() {
                return this.initialValue !== null && this.initialMinValue !== null
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file piePoint.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            statesConsts = series.consts.states,
            round = Math.round,
            getCosAndSin = DX.utils.getCosAndSin;
        series.PiePoint = series.BasePoint.inherit({
            ctor: function(data) {
                this.centerX = 300;
                this.centerY = 150;
                this.radiusOuter = 120;
                this.radiusInner = 0;
                this.INDENT_FROM_PIE = 30;
                this.CONNECTOR_LENGTH = 20;
                this.setLabelEllipsis = false;
                this.callBase(data);
                this.minValue = 0;
                this.tag = data.tag;
                this._pieTrackerAttrs = $.extend({}, this._trackerAttrs, {
                    inh: false,
                    fill: 'grey'
                })
            },
            translate: function(translator) {
                var self = this;
                self.translator = translator = translator || self.translator;
                if (!self.translator)
                    return;
                self.fromAngle = translator.translate(self.minValue);
                self.toAngle = translator.translate(self.value);
                self.middleAngle = translator.translate((self.value - self.minValue) / 2 + self.minValue)
            },
            correctValue: function(correction, percent) {
                var self = this;
                self.value += correction;
                self.minValue += correction;
                self.percent = percent;
                self.labelFormatObject.percent = percent
            },
            getTooltipCoords: function() {
                var angleFunctions = getCosAndSin(this.middleAngle);
                return {
                        x: this.centerX + (this.radiusInner + (this.radiusOuter - this.radiusInner) / 2) * angleFunctions.cos,
                        y: this.centerY - (this.radiusInner + (this.radiusOuter - this.radiusInner) / 2) * angleFunctions.sin,
                        offset: 0
                    }
            },
            correctPosition: function(correction) {
                var self = this;
                self.radiusInner = correction.radiusInner;
                self.radiusOuter = correction.radiusOuter;
                self.centerX = correction.centerX;
                self.centerY = correction.centerY
            },
            drawMarker: function(renderer, group) {
                this.options.attributes.inh = false;
                this.graphic = renderer.createArc(this.centerX, this.centerY, this.radiusOuter, this.radiusInner, this.toAngle, this.fromAngle, this.options.attributes).append(group);
                switch (this.state) {
                    case statesConsts.selected:
                        this.series.setPointSelectedState(this);
                        break;
                    case statesConsts.hover:
                        this.series.setPointHoverState(this);
                        break;
                    default:
                        this.state = statesConsts.normal;
                        this.fullState = statesConsts.normalMark
                }
            },
            drawTrackerMarker: function(renderer, trackerGroup) {
                this.trackerGraphic = renderer.createArc(this.centerX, this.centerY, this.radiusOuter, this.radiusInner, this.toAngle, this.fromAngle, this._pieTrackerAttrs).append(trackerGroup);
                this.trackerGraphic.data({point: this})
            },
            correctLabel: function() {
                this.correctLabelPosition();
                this.checkEllipsis();
                this.correctBackgroundPosition();
                this.rotateLabel();
                this.checkLabelPosition()
            },
            correctLabelPosition: function() {
                var bbox = this.label.getBBox(),
                    labelOptions = this.options.label,
                    angleFunctions = getCosAndSin(this.middleAngle),
                    align = 'center',
                    rad = this.radiusOuter + labelOptions.radialOffset,
                    x,
                    y;
                switch (labelOptions.position) {
                    case'outside':
                        rad += this.INDENT_FROM_PIE;
                        if (angleFunctions.cos > 0.1)
                            align = 'left';
                        else if (angleFunctions.cos < -0.1)
                            align = 'right';
                        x = this.centerX + rad * angleFunctions.cos;
                        break;
                    case'inside':
                        rad -= this.INDENT_FROM_PIE;
                        x = this.centerX + rad * angleFunctions.cos;
                        break;
                    case'columns':
                        rad += this.CONNECTOR_LENGTH;
                        if (angleFunctions.cos > 0) {
                            align = 'right';
                            x = this.series.canvas.width - this.series.canvas.right
                        }
                        else if (angleFunctions.cos < 0) {
                            align = 'left';
                            x = this.series.canvas.left
                        }
                        break
                }
                y = round(this.label.settings.y + this.centerY - rad * angleFunctions.sin - bbox.y - bbox.height / 2);
                this.label.applySettings({
                    x: x,
                    y: y,
                    align: align
                })
            },
            correctConnectorPosition: function() {
                if (this.options.label.position === 'inside')
                    return;
                if (!this.connector)
                    return;
                var angleFunctions = getCosAndSin(round(this.middleAngle)),
                    attributes = this.series.styles.attributes,
                    borderWidth = this.series.userOptions.containerBackgroundColor === attributes.stroke ? ~~(attributes.strokeWidth / 2) : ~~(-attributes.strokeWidth / 2),
                    rad = this.radiusOuter,
                    x1 = round(this.centerX + (rad - borderWidth) * angleFunctions.cos),
                    y1 = round(this.centerY - (rad - borderWidth) * angleFunctions.sin),
                    x2,
                    y2,
                    x3,
                    y3,
                    box,
                    labelOptions = this.options.label,
                    connector;
                x2 = round(this.centerX + (rad + labelOptions.radialOffset + this.CONNECTOR_LENGTH) * angleFunctions.cos);
                if (labelOptions.position === 'outside') {
                    y2 = round(this.centerY - (rad + labelOptions.radialOffset + this.CONNECTOR_LENGTH) * angleFunctions.sin);
                    this.connector.applySettings({points: [x1, y1, x2, y2]})
                }
                if (labelOptions.position === 'columns') {
                    box = this.insideLabelGroup.getBBox();
                    box.x = box.x + (this.insideLabelGroup.settings.translateX || 0);
                    box.y = box.y + (this.insideLabelGroup.settings.translateY || 0);
                    y2 = box.y + box.height / 2;
                    if (this.labelBackground)
                        x3 = box.x + box.width / 2;
                    else if (angleFunctions.cos < 0)
                        x3 = box.x + box.width;
                    else if (angleFunctions.cos > 0)
                        x3 = box.x;
                    y3 = y2;
                    this.connector.applySettings({points: [{
                                x: x1,
                                y: y1
                            }, {
                                x: x2,
                                y: y2
                            }, {
                                x: x3,
                                y: y3
                            }]})
                }
            },
            rotateLabel: function() {
                var labelOptions = this.options.label,
                    rad = this.radiusOuter + labelOptions.radialOffset,
                    angleFunctions = getCosAndSin(this.middleAngle),
                    x,
                    y,
                    box = this.insideLabelGroup.getBBox();
                switch (labelOptions.position) {
                    case'outside':
                        x = this.centerX + (rad + labelOptions.radialOffset + this.CONNECTOR_LENGTH) * angleFunctions.cos;
                        y = this.centerY - (rad + labelOptions.radialOffset + this.CONNECTOR_LENGTH) * angleFunctions.sin;
                        break;
                    case'inside':
                        x = box.x + box.width / 2;
                        y = box.y + box.height / 2;
                        break;
                    case'columns':
                        x = box.x + box.width / 2;
                        y = box.y + box.height / 2;
                        break
                }
                this.insideLabelGroup.applySettings({
                    x: x,
                    y: y,
                    rotate: labelOptions.rotationAngle
                })
            },
            checkEllipsis: function() {
                var self = this,
                    i,
                    LABEL_OFFSET = 10,
                    labelBox,
                    text,
                    textLength = 0,
                    linesLength = [],
                    numLastSpan = [],
                    maxLength,
                    numSpan,
                    index,
                    x,
                    y,
                    width,
                    rotationAngleFunction = getCosAndSin(self.options.label.rotationAngle),
                    canvas = self.series.canvas,
                    labelOptions = this.options.label,
                    angleFunctions = getCosAndSin(this.middleAngle),
                    borderX = this.centerX + (this.radiusOuter + this.CONNECTOR_LENGTH) * angleFunctions.cos;
                if (!self.label.tspans || !self.setLabelEllipsis)
                    return;
                labelBox = self.label.getBBox();
                x = labelBox.x + labelBox.width < self.centerX ? labelBox.x + labelBox.width : labelBox.x;
                y = labelBox.y + labelBox.height / 2;
                width = labelBox.x + labelBox.width < self.centerX ? -labelBox.width : labelBox.width;
                if (y + width * rotationAngleFunction.sin > canvas.height - canvas.bottom + LABEL_OFFSET || y + width * rotationAngleFunction.sin < canvas.top - LABEL_OFFSET || x + width * rotationAngleFunction.cos < canvas.left - LABEL_OFFSET || x + width * rotationAngleFunction.cos > canvas.width - canvas.right + LABEL_OFFSET || labelOptions.position === 'columns' && (angleFunctions.cos < 0 && borderX < x || angleFunctions.cos > 0 && borderX > x))
                    for (i = 0; i < self.label.tspans.length; i++) {
                        textLength += self.label.tspans[i].element.getNumberOfChars();
                        if (!self.label.tspans[i + 1] || self.label.tspans[i + 1].settings.dy > 0) {
                            linesLength.push(textLength);
                            numLastSpan.push(i);
                            textLength = 0
                        }
                    }
                while (y + width * rotationAngleFunction.sin > canvas.height - canvas.bottom + LABEL_OFFSET || y + width * rotationAngleFunction.sin < canvas.top - LABEL_OFFSET || x + width * rotationAngleFunction.cos < canvas.left - LABEL_OFFSET || x + width * rotationAngleFunction.cos > canvas.width - canvas.right + LABEL_OFFSET || labelOptions.position === 'columns' && (angleFunctions.cos < 0 && borderX < x || angleFunctions.cos > 0 && borderX > x)) {
                    maxLength = Math.max.apply(null, linesLength);
                    if (maxLength === 0)
                        break;
                    index = $.inArray(maxLength, linesLength);
                    numSpan = numLastSpan[index];
                    if (self.label.tspans[numSpan].element.textContent === "...") {
                        if (self.label.tspans[numSpan].settings.dy > 0 || !self.label.tspans[numSpan - 1])
                            linesLength[index] = 0;
                        else if (self.label.tspans[numSpan - 1]) {
                            self.label.tspans[numSpan].element.textContent = '';
                            numLastSpan[index] -= 1;
                            self.label.tspans[numSpan - 1].element.textContent += "..."
                        }
                    }
                    else {
                        text = self.label.tspans[numSpan].element.textContent;
                        text = text.substr(0, text.length - 1 - 3) + "...";
                        self.label.tspans[numSpan].element.textContent = text;
                        linesLength[index] -= 1
                    }
                    labelBox = self.label.getBBox();
                    x = labelBox.x + labelBox.width < self.centerX ? labelBox.x + labelBox.width : labelBox.x;
                    y = labelBox.y + labelBox.height / 2;
                    width = labelBox.x + labelBox.width < self.centerX ? -labelBox.width : labelBox.width
                }
            },
            checkLabelPosition: function() {
                var self = this,
                    groupBox = self.insideLabelGroup.getBBox(),
                    canvas = self.series.canvas;
                if (groupBox.y + groupBox.height > canvas.height - canvas.bottom)
                    self.insideLabelGroup.move(0, canvas.height - groupBox.y - groupBox.height - canvas.bottom);
                else if (groupBox.y < canvas.top)
                    self.insideLabelGroup.move(0, canvas.top - groupBox.y);
                if (groupBox.x + groupBox.width > canvas.width - canvas.right)
                    self.insideLabelGroup.move(canvas.width - canvas.right - groupBox.x - groupBox.width, 0);
                else if (groupBox.x < canvas.left)
                    self.insideLabelGroup.move(canvas.left - groupBox.x, 0)
            },
            animate: function(){},
            isInVisibleArea: function() {
                return true
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file pointFactory.js */
    (function($, DX) {
        var series = DX.viz.charts.series;
        series.pointFactory = {createPoint: function(seriesType, pointOptions) {
                seriesType = (seriesType || '').toLowerCase();
                switch (seriesType) {
                    case'line':
                        return new series.BasePoint(pointOptions);
                    case'stackedline':
                        return new series.BasePoint(pointOptions);
                    case'fullstackedline':
                        return new series.BasePoint(pointOptions);
                    case'area':
                        return new series.BasePoint(pointOptions);
                    case'stackedarea':
                        return new series.BasePoint(pointOptions);
                    case'fullstackedarea':
                        return new series.BasePoint(pointOptions);
                    case'bar':
                        return new series.BarPoint(pointOptions);
                    case'stackedbar':
                        return new series.BarPoint(pointOptions);
                    case'fullstackedbar':
                        return new series.BarPoint(pointOptions);
                    case'spline':
                        return new series.BasePoint(pointOptions);
                    case'splinearea':
                        return new series.BasePoint(pointOptions);
                    case'scatter':
                        return new series.BasePoint(pointOptions);
                    case'candlestick':
                        return new series.OhlcPoint(pointOptions);
                    case'stock':
                        return new series.StockPoint(pointOptions);
                    case'rangearea':
                        return new series.RangePoint(pointOptions);
                    case'rangesplinearea':
                        return new series.RangePoint(pointOptions);
                    case'rangebar':
                        return new series.RangeBarPoint(pointOptions);
                    case'pie':
                        return new series.PiePoint(pointOptions);
                    case'doughnut':
                        return new series.PiePoint(pointOptions);
                    case'stepline':
                        return new series.BasePoint(pointOptions);
                    case'steparea':
                        return new series.BasePoint(pointOptions);
                    default:
                        return null
                }
            }}
    })(jQuery, DevExpress);
    /*! Module viz, file baseSeries.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            eventsConsts = series.consts.events,
            statesConsts = series.consts.states,
            utils = DX.utils,
            ParseUtils = DX.viz.core.ParseUtils,
            SERIES_VALUE_MARGIN_PRIORITY = 20,
            FULLSTACKED_SERIES_VALUE_MARGIN_PRIORITY = 15,
            SERIES_LABEL_VALUE_MARGIN = 0.3,
            ALL_SERIES_POINTS_MODE = 'allseriespoints',
            INCLUDE_POINTS_MODE = 'includepoints',
            HOVER_CHECK = 0,
            SELECTION_CHECK = 1,
            BAR_ZERO_VALUE_MARGIN_PRIORITY = 20;
        series.BaseSeries = DX.Class.inherit({
            ctor: function(renderer, data, options, isRangeSeries) {
                this.type = options.specificType || 'unknown';
                this.isRangeSeries = isRangeSeries;
                this.renderer = renderer;
                this._rawData = data || [];
                this._parseOptions(options);
                this._parsedUserOptions = $.extend(true, {}, options);
                this._parseInputData(this._rawData);
                this.userOptions = options;
                this.tag = options.tag
            },
            dispose: function() {
                var _this = this;
                _this.off();
                $.each(_this.points || [], function(_, point) {
                    point.dispose()
                });
                _this.points = null;
                $.each(_this.trackerElements || [], function(_, tracker) {
                    tracker.removeData()
                });
                _this.trackerElements = null;
                _this.hoverPattern = null;
                _this.selectedPattern = null;
                _this.seriesGroup = null;
                _this.pointsByArgument = null;
                _this.segments = null;
                _this.preparedSegments = null;
                _this.renderer = null;
                _this._rawData = null;
                _this._parsedUserOptions = null;
                _this.options = null;
                _this.userOptions = null;
                _this.tag = null;
                _this._validationResult = null;
                _this.rangeData = null;
                _this.translator = null;
                _this.styles = null;
                _this._parseUtils = null
            },
            _checkValue: function(params) {
                if (!utils.isDefined(params.value)) {
                    this._validationResult.error = this._errorMessages.missingFieldMessage(params.field);
                    this.options.incidentOccured.call(null, this._errorMessages.missingFieldMessage(params.field));
                    return false
                }
                if (utils.isString(params.value)) {
                    params.axisType = 'discrete';
                    params.type = 'string'
                }
                else if (utils.isDate(params.value)) {
                    params.axisType = params.axisType || 'continuous';
                    params.type = 'datetime'
                }
                else if (utils.isNumber(params.value)) {
                    params.axisType = params.axisType || 'continuous';
                    params.type = 'numeric'
                }
                else {
                    this._validationResult.error = this._errorMessages.unsupportedFieldMessage(params.field);
                    this.options.incidentOccured.call(null, this._errorMessages.unsupportedFieldMessage(params.field));
                    return false
                }
                return true
            },
            _correctAxisType: function(axisType, categories) {
                return axisType && (axisType === 'discrete' || axisType === 'continuous') ? axisType : categories && categories.length ? 'discrete' : ''
            },
            reinitData: function(data) {
                this._parseInputData(data)
            },
            _errorMessages: {
                missingFieldMessage: function(field) {
                    return "Data source does not contain the '" + field + "' field."
                },
                unsupportedFieldMessage: function(field) {
                    return "The '" + field + "' field contains data of unsupported type."
                },
                incorrectDataMessage: function() {
                    return "Data source contains unsupported data."
                },
                incompatibleTypesDataMessage: function(unit) {
                    if (unit === 'argument')
                        return "The agrument type and argument axis type are incompatible.";
                    return "The value type and value axis type are incompatible."
                },
                dataItemMissingMessage: function(entity) {
                    if (entity === 'argument')
                        return "An argument is missed in the specified data.";
                    return "A value is missed in the specified data."
                },
                numericParsingMessage: function(entity) {
                    return "A point's " + entity + " cannot be parsed to a correct numeric value."
                },
                dateParsingMessage: function(entity) {
                    return "A point's " + entity + " cannot be parsed to a correct date."
                }
            },
            getRangeData: function(visibleRange) {
                if (this._validationResult.error)
                    return {};
                var self = this,
                    options = self.options,
                    argumentCategories = options.argumentCategories,
                    discreteArgumentAxis = options.argumentAxisType === 'discrete',
                    argumentType = options.argumentType,
                    valueCategories = options.valueCategories,
                    discreteValueAxis = options.valueAxisType === 'discrete',
                    valueType = options.valueType,
                    rangeData = {
                        visibleValCategories: [],
                        categoriesVal: [],
                        categoriesArg: []
                    },
                    points = self.points,
                    pointsLength = points && points.length,
                    lastVisibleIndex,
                    intervalVal,
                    intervalArg;
                function addToVisibleVal(val) {
                    if (discreteValueAxis) {
                        if ($.inArray(val, rangeData.visibleValCategories) === -1)
                            rangeData.visibleValCategories.push(val)
                    }
                    else {
                        if (val < rangeData.minVisibleVal || !utils.isDefined(rangeData.minVisibleVal))
                            rangeData.minVisibleVal = val;
                        if (val > rangeData.maxVisibleVal || !utils.isDefined(rangeData.maxVisibleVal))
                            rangeData.maxVisibleVal = val
                    }
                }
                var processArgument = function(arg, prevArg) {
                        var interval;
                        if (arg < rangeData.minArg || !utils.isDefined(rangeData.minArg))
                            rangeData.minArg = arg;
                        if (arg > rangeData.maxArg || !utils.isDefined(rangeData.maxArg))
                            rangeData.maxArg = arg;
                        if (utils.isDefined(prevArg))
                            interval = Math.abs(arg - prevArg);
                        if (utils.isDefined(interval) && (interval < rangeData.minIntervalArg || !utils.isDefined(rangeData.minIntervalArg)))
                            rangeData.minIntervalArg = interval
                    };
                var processValue = function(val, minVal, prevVal, prevMinVal) {
                        var interval;
                        if (val < rangeData.minVal || !utils.isDefined(rangeData.minVal))
                            rangeData.minVal = val;
                        if (val > rangeData.maxVal || !utils.isDefined(rangeData.maxVal))
                            rangeData.maxVal = val;
                        if (self.isRangeSeries) {
                            if (minVal < rangeData.minVal || !utils.isDefined(rangeData.minVal))
                                rangeData.minVal = minVal;
                            if (minVal > rangeData.maxVal || !utils.isDefined(rangeData.maxVal))
                                rangeData.maxVal = minVal
                        }
                        if (utils.isDefined(prevVal))
                            interval = Math.abs(val - prevVal);
                        if (self.isRangeSeries && utils.isDefined(prevMinVal))
                            interval = Math.min(interval, Math.abs(minVal - prevMinVal));
                        if (utils.isDefined(interval) && (interval < rangeData.minIntervalVal || !utils.isDefined(rangeData.minIntervalVal)))
                            rangeData.minIntervalVal = interval
                    };
                function unique(array, field) {
                    var values = {};
                    return $.map(array, function(item) {
                            var value = item[field];
                            var result = !values[value] ? value : null;
                            values[value] = true;
                            return result
                        })
                }
                if (discreteArgumentAxis) {
                    rangeData.categoriesArg = unique(points, 'argument');
                    processArgument = $.noop
                }
                if (discreteValueAxis) {
                    rangeData.categoriesVal = unique(points, 'value');
                    processValue = $.noop
                }
                if (pointsLength) {
                    $.each(points, function(i, point) {
                        var prevPoint,
                            val = point.value,
                            minVal = point.minValue,
                            arg = point.argument,
                            prevVal,
                            prevMinVal,
                            prevArg;
                        if (i !== 0) {
                            prevPoint = points[i - 1];
                            prevVal = prevPoint.value;
                            prevMinVal = prevPoint.minValue;
                            prevArg = prevPoint.argument
                        }
                        if (point.hasValue())
                            processValue(val, minVal, prevVal, prevMinVal);
                        processArgument(arg, prevArg);
                        if (discreteArgumentAxis || !visibleRange || arg < visibleRange.minArg || arg > visibleRange.maxArg)
                            return;
                        if (!utils.isDefined(rangeData.minVisibleVal) && i)
                            if (prevPoint.hasValue()) {
                                addToVisibleVal(prevVal);
                                if (self.isRangeSeries)
                                    addToVisibleVal(prevMinVal)
                            }
                        if (point.hasValue()) {
                            lastVisibleIndex = i;
                            addToVisibleVal(val);
                            if (self.isRangeSeries)
                                addToVisibleVal(minVal)
                        }
                    });
                    if (utils.isDefined(lastVisibleIndex) && lastVisibleIndex < pointsLength - 1)
                        if (points[lastVisibleIndex + 1].hasValue()) {
                            addToVisibleVal(points[lastVisibleIndex + 1].value);
                            if (self.isRangeSeries)
                                addToVisibleVal(points[lastVisibleIndex + 1].minValue)
                        }
                    if (!self.options.rotated) {
                        if (utils.isDefined(rangeData.minVal)) {
                            rangeData.minY = rangeData.minVal;
                            rangeData.maxY = rangeData.maxVal;
                            rangeData.intervalY = undefined
                        }
                        if (utils.isDefined(rangeData.minArg)) {
                            rangeData.minX = rangeData.minArg;
                            rangeData.maxX = rangeData.maxArg;
                            rangeData.intervalX = rangeData.minIntervalArg
                        }
                        if (rangeData.categoriesArg.length)
                            rangeData.categoriesX = rangeData.categoriesArg.slice(0);
                        if (rangeData.categoriesVal.length)
                            rangeData.categoriesY = rangeData.categoriesVal.slice(0);
                        if (rangeData.visibleValCategories.length)
                            rangeData.visibleCategoriesY = rangeData.visibleValCategories.slice(0);
                        rangeData.minVisibleY = rangeData.minVisibleVal;
                        rangeData.maxVisibleY = rangeData.maxVisibleVal
                    }
                    else {
                        if (utils.isDefined(rangeData.minVal)) {
                            rangeData.minX = rangeData.minVal;
                            rangeData.maxX = rangeData.maxVal;
                            rangeData.intervalX = undefined
                        }
                        if (utils.isDefined(rangeData.minArg)) {
                            rangeData.minY = rangeData.minArg;
                            rangeData.maxY = rangeData.maxArg;
                            rangeData.intervalY = rangeData.minIntervalArg
                        }
                        if (rangeData.categoriesArg.length)
                            rangeData.categoriesY = rangeData.categoriesArg.slice(0);
                        if (rangeData.categoriesVal.length)
                            rangeData.categoriesX = rangeData.categoriesVal.slice(0);
                        if (rangeData.visibleValCategories.length)
                            rangeData.visibleCategoriesX = rangeData.visibleValCategories.slice(0);
                        rangeData.minVisibleX = rangeData.minVisibleVal;
                        rangeData.maxVisibleX = rangeData.maxVisibleVal
                    }
                }
                delete rangeData.minArg;
                delete rangeData.maxArg;
                delete rangeData.minVal;
                delete rangeData.maxVal;
                delete rangeData.minIntervalArg;
                delete rangeData.minIntervalVal;
                delete rangeData.minVisibleVal;
                delete rangeData.maxVisibleVal;
                delete rangeData.visibleValCategories;
                delete rangeData.categoriesArg;
                delete rangeData.categoriesVal;
                rangeData = this.addLabelPaddingsToRange(rangeData);
                rangeData = this.processRangeForFullStackedSeries(rangeData);
                this.rangeData = rangeData;
                rangeData = this.getRangeMinValue(rangeData);
                return rangeData
            },
            getRangeMinValue: function(range) {
                if (this.type.slice(-3) === "bar" || this.type.slice(-4) === "area") {
                    if (!range)
                        return range;
                    if (this.isRangeSeries)
                        return range;
                    if (!this.options.rotated)
                        range.keepValueMarginsX = true;
                    else
                        range.keepValueMarginsY = true;
                    if (range.minY !== undefined && !this.options.rotated) {
                        range.minY = range.minY > 0 ? 0 : range.minY;
                        this.setZeroPadding(range, range.minY, 'minValueMarginY');
                        range.maxY = range.maxY < 0 ? 0 : range.maxY;
                        if (range.maxY === 0 || range.maxY > 0 && range.minY < 0) {
                            range.minValueMarginY = range.maxValueMarginY;
                            range.minValueMarginYPriority = range.maxValueMarginYPriority
                        }
                        this.setZeroPadding(range, range.maxY, 'maxValueMarginY')
                    }
                    else if (range.minX !== undefined && this.options.rotated) {
                        range.minX = range.minX > 0 ? 0 : range.minX;
                        this.setZeroPadding(range, range.minX, 'minValueMarginX');
                        range.maxX = range.maxX < 0 ? 0 : range.maxX;
                        if (range.maxX === 0 || range.maxX > 0 && range.minX < 0) {
                            range.minValueMarginX = range.maxValueMarginX;
                            range.minValueMarginXPriority = range.maxValueMarginXPriority
                        }
                        this.setZeroPadding(range, range.maxX, 'maxValueMarginX')
                    }
                }
                return range
            },
            setZeroPadding: function(range, val, prefix) {
                if (val === 0)
                    this.setPadding(range, prefix, 0, BAR_ZERO_VALUE_MARGIN_PRIORITY)
            },
            setPadding: function(range, prefix, val, priority) {
                range[prefix] = val;
                range[prefix + 'Priority'] = priority
            },
            addLabelPaddingsToRange: function(rangeData) {
                var series = this;
                if (series.areLabelsVisible() && series.styles.point.label.position !== 'inside')
                    if (!series.options.rotated) {
                        this.setPadding(rangeData, 'maxValueMarginY', SERIES_LABEL_VALUE_MARGIN, SERIES_VALUE_MARGIN_PRIORITY);
                        if (series.isRangeSeries)
                            this.setPadding(rangeData, 'minValueMarginY', SERIES_LABEL_VALUE_MARGIN, SERIES_VALUE_MARGIN_PRIORITY)
                    }
                    else {
                        this.setPadding(rangeData, 'maxValueMarginX', SERIES_LABEL_VALUE_MARGIN, SERIES_VALUE_MARGIN_PRIORITY);
                        if (series.isRangeSeries)
                            this.setPadding(rangeData, 'minValueMarginX', SERIES_LABEL_VALUE_MARGIN, SERIES_VALUE_MARGIN_PRIORITY)
                    }
                return rangeData
            },
            isFullStackedSeries: function() {
                return this.type.indexOf('fullstacked') === 0
            },
            isStackedSeries: function() {
                return this.type.indexOf('stacked') === 0
            },
            processRangeForFullStackedSeries: function(rangeData) {
                var self = this,
                    indentName,
                    isRangeEmpty = $.isEmptyObject(rangeData);
                if (self.isFullStackedSeries())
                    if (!self.options.rotated) {
                        self.setPadding(rangeData, 'minValueMarginY', 0, FULLSTACKED_SERIES_VALUE_MARGIN_PRIORITY);
                        self.setPadding(rangeData, 'maxValueMarginY', 0, FULLSTACKED_SERIES_VALUE_MARGIN_PRIORITY);
                        !isRangeEmpty && (rangeData.minY = 0)
                    }
                    else {
                        self.setPadding(rangeData, 'minValueMarginX', 0, FULLSTACKED_SERIES_VALUE_MARGIN_PRIORITY);
                        self.setPadding(rangeData, 'maxValueMarginX', 0, FULLSTACKED_SERIES_VALUE_MARGIN_PRIORITY);
                        !isRangeEmpty && (rangeData.minX = 0)
                    }
                return rangeData
            },
            draw: function(translator) {
                var seriesContainerOptions = {'class': 'dxc-series'},
                    seriesElementsOptions = {'class': 'dxc-elements'},
                    seriesMarkersOptions = $.extend({'class': 'dxc-markers'}, this.styles.point.states.normal),
                    labelsGroupOptions = {'class': 'dxc-series-labels'},
                    seriesElementsGroup,
                    seriesMarkersGroup,
                    labelsGroup;
                if (!translator) {
                    throw new Error('Translator was not initialized before call Series Draw()');
                    return
                }
                this.translator = translator;
                this._translateCoors();
                if (this.elementsClipRectID) {
                    seriesElementsOptions.clipId = this.elementsClipRectID;
                    labelsGroupOptions.clipId = this.elementsClipRectID
                }
                if (this.markersClipRectID)
                    seriesMarkersOptions.clipId = this.markersClipRectID;
                if (!this.seriesGroup) {
                    this.seriesGroup = this.renderer.createGroup(seriesContainerOptions);
                    seriesElementsGroup = this.renderer.createGroup(seriesElementsOptions).append(this.seriesGroup);
                    seriesMarkersGroup = this.renderer.createGroup(seriesMarkersOptions).append(this.seriesGroup)
                }
                else {
                    this.seriesGroup.clear();
                    seriesElementsGroup = this.renderer.createGroup(seriesElementsOptions).append(this.seriesGroup);
                    seriesMarkersGroup = this.renderer.createGroup(seriesMarkersOptions).append(this.seriesGroup)
                }
                this.seriesGroup.append(this.options.seriesGroup);
                labelsGroup = this.renderer.createGroup(labelsGroupOptions).append(this.options.seriesLabelsGroup);
                if (!this.hoverPatternColor) {
                    this.hoverPatternColor = this.styles.states.hover.fill;
                    this.selectedPatternColor = this.styles.states.selected.fill
                }
                this.createPatterns();
                this.drawSeriesData(seriesElementsGroup, seriesMarkersGroup, labelsGroup);
                switch (this.state) {
                    case statesConsts.selected:
                        this.setSelectedState(this.lastSelectionMode);
                        break;
                    case statesConsts.hover:
                        this.setHoverState(this.lastHoverdMode);
                        break;
                    default:
                        this.state = statesConsts.normal;
                        this.fullState = statesConsts.normalMark
                }
                return this
            },
            createPatterns: function() {
                if (!this.hoverPattern) {
                    this.hoverPattern = this.renderer.createPattern(this.hoverPatternColor, this.styles.states.hover.hatching);
                    this.selectedPattern = this.renderer.createPattern(this.selectedPatternColor, this.styles.states.selected.hatching)
                }
                this.hoverPattern.append();
                this.selectedPattern.append()
            },
            drawSeriesData: function(seriesElementsGroup, seriesMarkersGroup, labelsGroup) {
                if (this.hoverPattern) {
                    this.styles.states.hover.fill = this.hoverPattern.id;
                    this.styles.states.selected.fill = this.selectedPattern.id
                }
                this.drawPoints(seriesMarkersGroup, labelsGroup);
                return this
            },
            drawPoints: function(group, labelsGroup) {
                var series = this,
                    pointVisible = series.styles.point.visible,
                    labelVisible = series.areLabelsVisible();
                $.each(series.points, function drawPointMarker(i, point) {
                    point.adjustSeriesLabels = series.adjustSeriesLabels;
                    if (!point.isInVisibleArea(point.x, point.y, point.width || 0, point.height || 0))
                        return;
                    pointVisible && point.drawMarker(series.renderer, group);
                    labelVisible && point.drawLabel(series.renderer, labelsGroup)
                })
            },
            drawTrackers: function() {
                this.drawPointTrackers()
            },
            drawPointTrackers: function() {
                var series = this,
                    trackersVisible = !series._suppressTrackers;
                $.each(series.points, function drawPointTracker(i, point) {
                    if (!point.isInVisibleArea(point.x, point.y, point.width || 0, point.height || 0))
                        return;
                    trackersVisible && point.drawTrackerMarker(series.renderer, series.options.markerTrackerGroup)
                })
            },
            areLabelsVisible: function() {
                var series = this;
                return series.styles.point.label.visible && (!utils.isDefined(series.styles.maxLabelCount) || series.points.length <= series.styles.maxLabelCount)
            },
            getPoints: function() {
                return this.points
            },
            select: function() {
                this.options.seriesGroup && this.options.seriesGroup.trigger(new $.Event(eventsConsts.selectSeries, {target: this}), this.options.selectionMode);
                this.seriesGroup && this.seriesGroup.toForeground();
                if (this.trackerElements && this.trackerElements.length)
                    $.each(this.trackerElements, function(_, element) {
                        element.toBackground()
                    })
            },
            clearSelection: function clearSelection() {
                this.options.seriesGroup && this.options.seriesGroup.trigger(new $.Event(eventsConsts.deselectSeries, {target: this}), this.options.selectionMode)
            },
            selectPoint: function(point) {
                this.options.seriesGroup && this.options.seriesGroup.trigger(new $.Event(eventsConsts.selectPoint), point)
            },
            deselectPoint: function(point) {
                this.options.seriesGroup && this.options.seriesGroup.trigger(new $.Event(eventsConsts.deselectPoint), point)
            },
            showPointTooltip: function(point) {
                this.options.seriesGroup && this.options.seriesGroup.trigger(new $.Event(eventsConsts.showPointTooltip), point)
            },
            hidePointTooltip: function(point) {
                this.options.seriesGroup && this.options.seriesGroup.trigger(new $.Event(eventsConsts.hidePointTooltip), point)
            },
            getAllPoints: function() {
                return this.points.slice()
            },
            getPointByPos: function(pos) {
                return this.points && this.points[pos]
            },
            getPointByArg: function(arg) {
                return this.pointsByArgument[arg.valueOf()] || null
            },
            _execAnimateAction: function(nameMethod) {
                if (this.styles.point.visible && this.segments)
                    $.each(this.segments, function(_, segment) {
                        $.each(segment, function(_, pt) {
                            pt[nameMethod] && pt[nameMethod]()
                        })
                    })
            },
            animate: function() {
                this._execAnimateAction('animate')
            },
            stopAnimation: function() {
                this._execAnimateAction('stopAnimation')
            },
            on: function(events, data, handler) {
                $(this).on(events, data, handler);
                return this
            },
            off: function(events) {
                $(this).off(events);
                return this
            },
            applyNormalStyle: function(mode) {
                if (mode === ALL_SERIES_POINTS_MODE || mode === INCLUDE_POINTS_MODE)
                    $.each(this.segments, function(_, segment) {
                        $.each(segment, function(_, pt) {
                            if (!(pt.fullState & statesConsts.selectedMark))
                                pt.applyNormalStyle()
                        })
                    })
            },
            applyHoverStyle: function(mode) {
                if (mode === ALL_SERIES_POINTS_MODE || mode === INCLUDE_POINTS_MODE)
                    $.each(this.segments, function(_, segment) {
                        $.each(segment, function(_, pt) {
                            if (!(pt.fullState & statesConsts.selectedMark))
                                pt.applyHoverStyle()
                        })
                    })
            },
            applySelectionStyle: function(mode) {
                if (mode === ALL_SERIES_POINTS_MODE || mode === INCLUDE_POINTS_MODE)
                    $.each(this.segments, function(_, segment) {
                        $.each(segment, function(_, pt) {
                            if (!(pt.fullState & statesConsts.selectedMark))
                                pt.applySelectionStyle()
                        })
                    })
            },
            setHoverState: function(mode) {
                this.fullState = this.fullState | statesConsts.hoverMark;
                mode = mode || this.options.hoverMode;
                this.lastHoverMode = mode;
                if (!this._checkBehavior(mode, HOVER_CHECK))
                    return;
                this.state = statesConsts.hover;
                this.applyHoverStyle(mode)
            },
            releaseHoverState: function() {
                var mode = this.lastHoverMode || this.options.hoverMode;
                this.fullState = this.fullState & ~statesConsts.hoverMark;
                delete this.lastHoverMode;
                if (!this._checkBehavior(mode, HOVER_CHECK))
                    return;
                this.state = statesConsts.normal;
                this.applyNormalStyle(mode)
            },
            setSelectedState: function(mode) {
                this.state = statesConsts.selected;
                this.fullState = this.fullState | statesConsts.selectedMark;
                this.lastSelectionMode = mode;
                if (!this._checkBehavior(mode, SELECTION_CHECK))
                    return;
                if (this.lastHoverMode === ALL_SERIES_POINTS_MODE || this.lastHoverMode === INCLUDE_POINTS_MODE)
                    this.applyNormalStyle(INCLUDE_POINTS_MODE);
                mode = mode || this.options.selectionMode;
                this.applySelectionStyle(mode)
            },
            releaseSelectedState: function() {
                var mode = this.lastSelectionMode || this.options.selectionMode;
                this.fullState = this.fullState & ~statesConsts.selectedMark;
                if (!this._checkBehavior(mode, SELECTION_CHECK))
                    return;
                if (this.fullState & statesConsts.hoverMark) {
                    this.state = statesConsts.hover;
                    if ((mode === INCLUDE_POINTS_MODE || mode === ALL_SERIES_POINTS_MODE) && (this.lastHoverMode !== INCLUDE_POINTS_MODE || this.lastHoverMode === ALL_SERIES_POINTS_MODE))
                        this.applyNormalStyle(mode);
                    this.applyHoverStyle(this.lastHoverMode)
                }
                else {
                    this.state = statesConsts.normal;
                    this.applyNormalStyle(mode)
                }
                delete this.lastSelectionMode
            },
            _checkBehavior: function(mode, behavior) {
                if (mode === 'none')
                    return false;
                switch (behavior) {
                    case HOVER_CHECK:
                        if (!(this.fullState & statesConsts.selectedMark) || this.options.selectionMode === 'none')
                            return true;
                        return false;
                    case SELECTION_CHECK:
                        return true
                }
                return false
            },
            setPointHoverState: function(point) {
                point.fullState = point.fullState | statesConsts.hoverMark;
                if (!(this.fullState & statesConsts.selectedMark && (this.lastSelectionMode === ALL_SERIES_POINTS_MODE || this.lastSelectionMode === INCLUDE_POINTS_MODE)) && !(point.fullState & statesConsts.selectedMark)) {
                    point.state = statesConsts.hover;
                    point.applyHoverStyle()
                }
            },
            releasePointHoverState: function(point) {
                point.fullState = point.fullState & ~statesConsts.hoverMark;
                if (!(this.fullState & statesConsts.selectedMark && (this.lastSelectionMode === ALL_SERIES_POINTS_MODE || this.lastSelectionMode === INCLUDE_POINTS_MODE)) && !(point.fullState & statesConsts.selectedMark)) {
                    point.state = statesConsts.normal;
                    if (!(this.fullState & statesConsts.hoverMark && (this.lastSelectionMode === ALL_SERIES_POINTS_MODE || this.lastSelectionMode === INCLUDE_POINTS_MODE)))
                        point.applyNormalStyle()
                }
            },
            setPointSelectedState: function(point) {
                point.state = statesConsts.selected;
                point.fullState = point.fullState | statesConsts.selectedMark;
                point.applySelectionStyle()
            },
            releasePointSelectedState: function(point) {
                point.state = statesConsts.normal;
                point.fullState = point.fullState & ~statesConsts.selectedMark;
                if (this.fullState & statesConsts.hoverMark && (this.lastHoverMode === ALL_SERIES_POINTS_MODE || this.lastHoverMode === INCLUDE_POINTS_MODE) || point.fullState & statesConsts.hoverMark) {
                    point.applyHoverStyle();
                    if (point.fullState & statesConsts.hoverMark)
                        point.state = statesConsts.hover
                }
                else if (this.fullState & statesConsts.selectedMark && (this.lastSelectionMode === ALL_SERIES_POINTS_MODE || this.lastSelectionMode === INCLUDE_POINTS_MODE))
                    point.applySelectionStyle();
                else
                    point.applyNormalStyle()
            },
            _translateCoors: function() {
                var _this = this,
                    tr = _this.translator;
                $.each(_this.points, function(_, p) {
                    p.translate(tr)
                })
            },
            _checkAndPrepareInputData: function(data, argumentField, valueFields) {
                this._checkInputData(data, argumentField, valueFields);
                return this._validationResult.error ? null : this._prepareInputData(data, argumentField, valueFields)
            },
            _checkInputData: function(data, argumentField, valueFields) {
                this._validationResult = {error: null};
                this._parseUtils = new ParseUtils({incidentOccured: this.options.incidentOccured});
                var self = this,
                    dataLen = data.length,
                    i,
                    argFound,
                    valFound,
                    val1Found,
                    val2Found,
                    curPoint,
                    firstItem = data[0],
                    checkParams = {};
                if (!dataLen)
                    return;
                if ($.type(firstItem) !== 'object') {
                    self._validationResult.error = self._errorMessages.incorrectDataMessage();
                    self.options.incidentOccured.call(null, self._errorMessages.incorrectDataMessage());
                    return
                }
                self._checkArgumentAxisParams(data, argumentField);
                if (self._validationResult.error)
                    return;
                self._checkValueAxisParams(data, valueFields)
            },
            _checkArgumentAxisParams: function(data, argumentField) {
                var self = this,
                    options = self.options,
                    userOptions = self._parsedUserOptions,
                    argumentCategories = userOptions.argumentCategories,
                    argumentAxisType = self._correctAxisType(userOptions.argumentAxisType, userOptions.argumentCategories),
                    argumentType = self._parseUtils.correctValueType(userOptions.argumentType),
                    i,
                    argFound,
                    curPoint,
                    checkParams = {};
                argumentField = argumentField || options.argumentField || 'arg';
                options.userArgumentType = argumentType;
                options.userArgumentAxisType = argumentAxisType;
                switch (argumentType.toLowerCase()) {
                    case'numeric':
                    case'datetime':
                        if (!argumentAxisType) {
                            options.argumentAxisType = argumentAxisType = 'continuous';
                            options.argumentType = argumentType
                        }
                        else {
                            options.argumentAxisType = argumentAxisType;
                            options.argumentType = argumentType
                        }
                        return;
                    case'string':
                        if (argumentAxisType && argumentAxisType !== 'discrete') {
                            self._validationResult.error = self._errorMessages.incompatibleTypesDataMessage('argument');
                            self.options.incidentOccured.call(null, self._errorMessages.incompatibleTypesDataMessage('argument'))
                        }
                        options.argumentAxisType = argumentAxisType = 'discrete';
                        options.argumentType = argumentType;
                        return;
                    default:
                        break
                }
                for (i = 0; i < data.length; i++) {
                    curPoint = data[i];
                    if (self._isTypeSupported(curPoint[argumentField])) {
                        argFound = curPoint[argumentField];
                        break
                    }
                }
                checkParams.value = argFound;
                checkParams.field = argumentField;
                checkParams.axisType = argumentAxisType;
                checkParams.type = argumentType;
                if (self._checkValue(checkParams)) {
                    options.argumentAxisType = checkParams.axisType;
                    options.argumentType = checkParams.type
                }
                else
                    return
            },
            _checkValueAxisParams: function(data, valueFields) {
                var self = this,
                    options = self.options,
                    userOptions = self._parsedUserOptions,
                    valueField = options.valueField || 'val',
                    rangeValue1Field = options.rangeValue1Field || 'val1',
                    rangeValue2Field = options.rangeValue2Field || 'val2',
                    valueCategories = userOptions.valueCategories,
                    valueAxisType = self._correctAxisType(userOptions.valueAxisType, userOptions.valueCategories),
                    valueType = self._parseUtils.correctValueType(userOptions.valueType),
                    i,
                    j,
                    valFound = {},
                    val1Found,
                    val2Found,
                    curPoint,
                    checkParams = {},
                    foundedValueFields;
                valueFields = valueFields || [];
                if (!valueFields.length)
                    valueFields = self.isRangeSeries ? [rangeValue1Field, rangeValue2Field] : [valueField];
                options.userValueType = valueType;
                options.userValueAxisType = valueAxisType;
                switch (valueType.toLowerCase()) {
                    case'numeric':
                    case'datetime':
                        if (!valueAxisType) {
                            options.valueAxisType = valueAxisType = 'continuous';
                            options.valueType = valueType
                        }
                        else {
                            options.valueAxisType = valueAxisType;
                            options.valueType = valueType
                        }
                        return;
                    case'string':
                        if (valueAxisType && valueAxisType !== 'discrete') {
                            self._validationResult.error = self._errorMessages.incompatibleTypesDataMessage('value');
                            self.options.incidentOccured.call(null, self._errorMessages.incompatibleTypesDataMessage('value'))
                        }
                        options.valueAxisType = valueAxisType = 'discrete';
                        options.valueType = valueType;
                        return;
                    default:
                        break
                }
                checkParams.axisType = valueAxisType;
                checkParams.type = valueType;
                for (i = 0; i < data.length; i++) {
                    var allFieldsFound = true;
                    curPoint = data[i];
                    for (j = 0; j < valueFields.length; j++)
                        if (self._isTypeSupported(curPoint[valueFields[j]]))
                            valFound[valueFields[j]] = curPoint[valueFields[j]];
                    $.each(valueFields, function(i, field) {
                        return allFieldsFound = field in valFound
                    });
                    if (allFieldsFound)
                        break
                }
                for (i = 0; i < valueFields.length; i++) {
                    checkParams.value = valFound[valueFields[i]];
                    checkParams.field = valueFields[i];
                    if (!self._checkValue(checkParams))
                        return
                }
                options.valueAxisType = checkParams.axisType;
                options.valueType = checkParams.type
            },
            _prepareInputData: function(data, argumentField, valueFields) {
                var self = this,
                    options = self.options,
                    argumentCategories = options.argumentCategories,
                    argumentAxisType = options.argumentAxisType,
                    argumentType = options.argumentType,
                    errorMessages = self._errorMessages,
                    incidentOccured = self.options.incidentOccured,
                    valueField = options.valueField || 'val',
                    rangeValue1Field = options.rangeValue1Field || 'val1',
                    rangeValue2Field = options.rangeValue2Field || 'val2',
                    valueCategories = options.valueCategories,
                    valueAxisType = options.valueAxisType,
                    userValueType = options.userValueType,
                    userArgumentType = options.userArgumentType,
                    userValueAxisType = options.userValueAxisType,
                    userArgumentAxisType = options.userArgumentAxisType,
                    valueType = options.valueType,
                    tagField = options.tagField || 'tag',
                    query = DX.data.query,
                    argumentParser = $.noop,
                    valueParser = $.noop,
                    prepData = [];
                argumentField = argumentField || options.argumentField || 'arg';
                valueFields = valueFields || [];
                if (!valueFields.length)
                    valueFields = self.isRangeSeries ? [rangeValue1Field, rangeValue2Field] : [valueField];
                if (!data.length)
                    return prepData;
                function categorySort() {
                    var length = argumentCategories.length,
                        oIdx = length,
                        i,
                        sortHash = {};
                    for (i = 0; i < length; i++)
                        sortHash[argumentCategories[i]] = i;
                    return function(a, b) {
                            var argA = a[argumentField],
                                argB = b[argumentField],
                                aRank = sortHash[argA],
                                bRank = sortHash[argB];
                            if (!utils.isDefined(aRank))
                                aRank = oIdx;
                            if (!utils.isDefined(bRank))
                                bRank = oIdx;
                            return aRank - bRank
                        }
                }
                function argumentSort(a, b) {
                    return a[argumentField] - b[argumentField]
                }
                var getParser = function(entity, valueType, nullsNotAllowed) {
                        var parser = self._parseUtils.getParser(valueType.toLowerCase(), entity + 'Axis'),
                            parsingMessage;
                        switch (valueType.toLowerCase()) {
                            case'numeric':
                                parsingMessage = errorMessages.numericParsingMessage;
                                break;
                            case'datetime':
                                parsingMessage = errorMessages.dateParsingMessage;
                                break;
                            default:
                                parsingMessage = $.noop
                        }
                        return function(val) {
                                var parsedVal;
                                if (nullsNotAllowed && !utils.isDefined(val) || val === undefined) {
                                    incidentOccured.call(null, errorMessages.dataItemMissingMessage(entity));
                                    return undefined
                                }
                                if (val === null)
                                    return null;
                                parsedVal = parser(val);
                                if (!utils.isDefined(parsedVal))
                                    incidentOccured.call(null, parsingMessage(entity));
                                return parsedVal
                            }
                    };
                var parseArgument = getParser('argument', argumentType, true);
                var parseValue = getParser('value', valueType);
                prepData = $.map(data, function(src) {
                    var arg = userArgumentAxisType === 'discrete' && !userArgumentType ? src[argumentField] : parseArgument(src[argumentField]),
                        resultDataItem = {tag: src[tagField]},
                        val,
                        i;
                    if (!utils.isDefined(arg))
                        return null;
                    resultDataItem[argumentField] = arg;
                    resultDataItem['original' + argumentField] = src[argumentField];
                    for (i = 0; i < valueFields.length; i++) {
                        val = userValueAxisType === 'discrete' && !userValueType ? src[valueFields[i]] : parseValue(src[valueFields[i]]);
                        if (val === undefined)
                            return null;
                        resultDataItem[valueFields[i]] = val;
                        resultDataItem['original' + valueFields[i]] = src[valueFields[i]]
                    }
                    return resultDataItem
                });
                if (argumentAxisType === 'discrete' && argumentCategories && argumentCategories.length)
                    prepData.sort(categorySort());
                else if (argumentAxisType !== 'discrete')
                    prepData.sort(argumentSort);
                return prepData
            },
            _parseInputData: function(data) {
                var self = this,
                    createPoint = series.pointFactory.createPoint,
                    rotated = self.options.rotated,
                    pointStyles = self.styles.point,
                    prepData,
                    i = 0,
                    curPoint,
                    point,
                    valueField,
                    rangeValue1Field,
                    rangeValue2Field,
                    options = self.options,
                    argumentField = argumentField || options.argumentField || 'arg',
                    tagField = options.tagField || 'tag';
                if (data && data.length)
                    this._canRenderCompleteHandle = true;
                self.points = [];
                self.pointsByArgument = {};
                self.segments = [];
                prepData = self._checkAndPrepareInputData(data);
                if (!prepData || self._validationResult.error)
                    return;
                if (!self.isRangeSeries) {
                    valueField = options.valueField || 'val';
                    for (; i < prepData.length; i++) {
                        curPoint = prepData[i];
                        point = createPoint(self.type, {
                            value: curPoint[valueField],
                            argument: curPoint[argumentField],
                            originalValue: curPoint['original' + valueField],
                            originalArgument: curPoint['original' + argumentField],
                            rotated: rotated,
                            options: pointStyles,
                            tag: curPoint.tag,
                            series: self
                        });
                        self.points.push(point);
                        self.pointsByArgument[point.argument.valueOf()] = self.pointsByArgument[point.argument.valueOf()] || point
                    }
                }
                else {
                    rangeValue1Field = options.rangeValue1Field || 'val1';
                    rangeValue2Field = options.rangeValue2Field || 'val2';
                    for (; i < prepData.length; i++) {
                        curPoint = prepData[i];
                        point = createPoint(self.type, {
                            minValue: curPoint[rangeValue1Field],
                            value: curPoint[rangeValue2Field],
                            argument: curPoint[argumentField],
                            originalMinValue: curPoint['original' + rangeValue1Field],
                            originalValue: curPoint['original' + rangeValue2Field],
                            originalArgument: curPoint['original' + argumentField],
                            rotated: rotated,
                            options: pointStyles,
                            tag: curPoint.tag,
                            series: self
                        });
                        self.pointsByArgument[point.argument] = self.pointsByArgument[point.argument] || point;
                        self.points.push(point)
                    }
                }
                this._segmenting()
            },
            _segmenting: function() {
                var self = this,
                    segment = [];
                $.each(this.points, function(_, point) {
                    if (point.hasValue())
                        segment.push(point);
                    else if (segment.length !== 0) {
                        self.segments.push(segment);
                        segment = []
                    }
                });
                if (segment.length)
                    this.segments.push(segment)
            },
            _parseOptions: function(options) {
                this.options = {
                    incidentOccured: options.incidentOccured,
                    rotated: !!options.rotated,
                    seriesGroup: options.seriesGroup,
                    seriesLabelsGroup: options.seriesLabelsGroup,
                    seriesTrackerGroup: options.seriesTrackerGroup,
                    markerTrackerGroup: options.markerTrackerGroup,
                    argumentCategories: options.argumentCategories,
                    argumentAxisType: options.argumentAxisType,
                    argumentType: options.argumentType,
                    argumentField: options.argumentField,
                    valueCategories: options.valueCategories,
                    valueAxisType: options.valueAxisType,
                    valueType: options.valueType,
                    valueField: options.valueField,
                    rangeValue1Field: options.rangeValue1Field,
                    rangeValue2Field: options.rangeValue2Field,
                    tagField: options.tagField,
                    selectionMode: (options.selectionMode || '').toLowerCase(),
                    hoverMode: (options.hoverMode || '').toLowerCase(),
                    showInLegend: options.showInLegend !== undefined ? options.showInLegend : true
                };
                if (!$.isFunction(this.options.incidentOccured))
                    this.options.incidentOccured = $.noop;
                this.name = options.name;
                this.axis = options.axis;
                this.pane = options.pane;
                this.styles = this.parseStyleOptions(options);
                if (this.adjustOptions)
                    this.adjustOptions()
            },
            parseStyleOptions: function(options) {
                var combinedOptions = $.extend(true, {}, this.getDefaultStyleOptions(), options);
                var normalState = {
                        strokeWidth: combinedOptions.border.visible ? combinedOptions.border.width || 0 : 0,
                        stroke: combinedOptions.border.visible && combinedOptions.border.width ? combinedOptions.border.color : 'none',
                        fill: combinedOptions.color,
                        dashStyle: combinedOptions.dashStyle,
                        lineWidth: combinedOptions.width,
                        r: combinedOptions.cornerRadius
                    };
                var hoverState = {
                        strokeWidth: combinedOptions.hoverStyle.border.visible ? combinedOptions.hoverStyle.border.width || 0 : 0,
                        stroke: combinedOptions.hoverStyle.border.visible && combinedOptions.hoverStyle.border.width ? combinedOptions.hoverStyle.border.color : 'none',
                        fill: combinedOptions.hoverStyle.color,
                        dashStyle: combinedOptions.hoverStyle.dashStyle || combinedOptions.dashStyle,
                        lineWidth: combinedOptions.hoverStyle.width,
                        hatching: combinedOptions.hoverStyle.hatching
                    };
                var selectedState = {
                        strokeWidth: combinedOptions.selectionStyle.border.visible ? combinedOptions.selectionStyle.border.width || 0 : 0,
                        stroke: combinedOptions.selectionStyle.border.visible && combinedOptions.selectionStyle.border.width ? combinedOptions.selectionStyle.border.color : 'none',
                        fill: combinedOptions.selectionStyle.color,
                        dashStyle: combinedOptions.selectionStyle.dashStyle || combinedOptions.dashStyle,
                        lineWidth: combinedOptions.selectionStyle.width,
                        hatching: combinedOptions.selectionStyle.hatching
                    };
                var attr = {};
                $.each(['align', 'translateX', 'translateY', 'rotate', 'linejoin', 'linecap', 'opacity', 'style'], function(i, val) {
                    if (combinedOptions[val])
                        attr[val] = combinedOptions[val]
                });
                var attributes = $.extend(true, {}, normalState, attr);
                var pointNormalState = {
                        strokeWidth: combinedOptions.point.border.visible ? combinedOptions.point.border.width || 0 : 0,
                        stroke: combinedOptions.point.border.visible && combinedOptions.point.border.width ? combinedOptions.point.border.color : 'none',
                        fill: combinedOptions.point.color,
                        r: combinedOptions.point.size + (combinedOptions.point.border.visible && combinedOptions.point.size !== 0 ? ~~(combinedOptions.point.border.width / 2) || 0 : 0),
                        inh: true
                    };
                var pointHoverState = {
                        strokeWidth: combinedOptions.point.hoverStyle.border.visible ? combinedOptions.point.hoverStyle.border.width || 0 : 0,
                        stroke: combinedOptions.point.hoverStyle.border.visible && combinedOptions.point.hoverStyle.border.width ? combinedOptions.point.hoverStyle.border.color : 'none',
                        fill: combinedOptions.point.hoverStyle.color,
                        r: combinedOptions.point.hoverStyle.size + (combinedOptions.point.hoverStyle.border.visible && combinedOptions.point.hoverStyle.size !== 0 ? ~~(combinedOptions.point.hoverStyle.border.width / 2) || 0 : 0)
                    };
                var pointSelectedState = {
                        strokeWidth: combinedOptions.point.selectionStyle.border.visible ? combinedOptions.point.selectionStyle.border.width || 0 : 0,
                        stroke: combinedOptions.point.selectionStyle.border.visible && combinedOptions.point.selectionStyle.border.width ? combinedOptions.point.selectionStyle.border.color : 'none',
                        fill: combinedOptions.point.selectionStyle.color,
                        r: combinedOptions.point.selectionStyle.size + (combinedOptions.point.selectionStyle.border.visible && combinedOptions.point.selectionStyle.size !== 0 ? ~~(combinedOptions.point.selectionStyle.border.width / 2) || 0 : 0)
                    };
                var pointAttr = {};
                $.each(['align', 'translateX', 'translateY', 'rotate', 'linejoin', 'linecap', 'style'], function(i, val) {
                    if (val in combinedOptions.point)
                        pointAttr[val] = combinedOptions.point[val]
                });
                var pointAttributes = $.extend(true, {}, pointNormalState, pointAttr);
                var labelAttributes = {
                        align: combinedOptions.label.alignment,
                        font: {
                            color: combinedOptions.label.backgroundColor === 'none' && combinedOptions.label.font.color.toLowerCase() === '#ffffff' && combinedOptions.label.position !== 'inside' ? combinedOptions.color : combinedOptions.label.font.color,
                            family: combinedOptions.label.font.family,
                            weight: combinedOptions.label.font.weight,
                            size: combinedOptions.label.font.size,
                            opacity: combinedOptions.label.font.opacity
                        },
                        style: combinedOptions.label.style
                    };
                var backgroundAttr = {
                        fill: combinedOptions.label.backgroundColor || combinedOptions.color,
                        strokeWidth: combinedOptions.label.border.visible ? combinedOptions.label.border.width || 0 : 0,
                        stroke: combinedOptions.label.border.visible && combinedOptions.label.border.width ? combinedOptions.label.border.color : 'none',
                        dashStyle: combinedOptions.label.border.dashStyle
                    };
                var connectorAttr = {
                        stroke: combinedOptions.label.connector.visible && combinedOptions.label.connector.width ? combinedOptions.label.connector.color || combinedOptions.color : 'none',
                        strokeWidth: combinedOptions.label.connector.visible ? combinedOptions.label.connector.width || 0 : 0
                    };
                return {
                        themeColor: combinedOptions.color,
                        attributes: attributes,
                        maxLabelCount: combinedOptions.maxLabelCount,
                        minSegmentSize: combinedOptions.minSegmentSize,
                        minBarSize: combinedOptions.minBarSize,
                        reduction: {
                            color: combinedOptions.reduction.color,
                            level: combinedOptions.reduction.level,
                            innerColor: combinedOptions.innerColor
                        },
                        states: {
                            normal: normalState,
                            hover: hoverState,
                            selected: selectedState
                        },
                        point: {
                            visible: combinedOptions.point.visible,
                            symbol: combinedOptions.point.symbol,
                            minShownBarSize: combinedOptions.point.minShownBarSize,
                            attributes: pointAttributes,
                            seriesName: combinedOptions.point.seriesName,
                            selectionMode: (combinedOptions.point.selectionMode || '').toLowerCase(),
                            hoverMode: (combinedOptions.point.hoverMode || '').toLowerCase(),
                            states: {
                                normal: pointNormalState,
                                hover: pointHoverState,
                                selected: pointSelectedState
                            },
                            label: {
                                format: combinedOptions.label.format,
                                argumentFormat: combinedOptions.label.argumentFormat,
                                precision: combinedOptions.label.precision,
                                argumentPrecision: combinedOptions.label.argumentPrecision,
                                percentPrecision: combinedOptions.label.percentPrecision,
                                customizeText: $.isFunction(combinedOptions.label.customizeText) ? combinedOptions.label.customizeText : undefined,
                                attributes: labelAttributes,
                                visible: combinedOptions.label.font.size !== 0 ? combinedOptions.label.visible : false,
                                showForZeroValues: combinedOptions.label.showForZeroValues,
                                horizontalOffset: combinedOptions.label.horizontalOffset,
                                verticalOffset: combinedOptions.label.verticalOffset,
                                radialOffset: combinedOptions.label.radialOffset,
                                background: backgroundAttr,
                                position: combinedOptions.label.position,
                                connector: connectorAttr,
                                rotationAngle: combinedOptions.label.rotationAngle
                            }
                        }
                    }
            },
            canRenderCompleteHandle: function() {
                var result = this._canRenderCompleteHandle;
                delete this._canRenderCompleteHandle;
                return !!result
            },
            _isTypeSupported: function(data) {
                return utils.isString(data) || utils.isNumber(data) || utils.isDate(data)
            },
            getDefaultStyleOptions: function() {
                return {
                        color: '#000000',
                        border: {
                            visible: false,
                            width: 1,
                            color: '#000000'
                        },
                        width: 2,
                        dashStyle: 'solid',
                        cornerRadius: 0,
                        innerColor: '#ffffff',
                        reduction: {color: '#FF0000'},
                        maxLabelCount: undefined,
                        minBarSize: undefined,
                        minSegmentSize: undefined,
                        point: {
                            visible: true,
                            symbol: 'circle',
                            color: '#000000',
                            size: 6,
                            seriesName: this.name,
                            border: {
                                visible: false,
                                width: 1,
                                color: '#000000'
                            },
                            hoverStyle: {
                                color: '#000000',
                                border: {
                                    visible: true,
                                    width: 2,
                                    color: '#ffffff'
                                },
                                size: 6
                            },
                            selectionStyle: {
                                color: '#000000',
                                border: {
                                    visible: true,
                                    width: 2,
                                    color: '#ffffff'
                                },
                                size: 6
                            }
                        },
                        label: {
                            visible: false,
                            showForZeroValues: true,
                            alignment: 'center',
                            font: {
                                family: "'SegoeUI', 'Segoe UI', 'HelveticaNeue', 'Helvetica Neue', 'Trebuchet MS', Verdana",
                                weight: 400,
                                color: '#ffffff',
                                size: 14
                            },
                            rotationAngle: 0,
                            horizontalOffset: 0,
                            verticalOffset: 0,
                            radialOffset: 0,
                            format: '',
                            argumentFormat: '',
                            precision: 0,
                            argumentPrecision: 0,
                            position: 'outside',
                            connector: {
                                visible: false,
                                width: 1
                            },
                            border: {
                                visible: false,
                                width: 1,
                                color: '#808080',
                                dashStyle: 'solid'
                            }
                        },
                        hoverStyle: {
                            hatching: 'none',
                            color: '#000000',
                            border: {
                                visible: false,
                                width: 1,
                                color: '#000000'
                            },
                            width: 3
                        },
                        selectionStyle: {
                            hatching: 'right',
                            color: '#000000',
                            border: {
                                visible: false,
                                width: 1,
                                color: '#000000'
                            },
                            width: 3
                        }
                    }
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file lineSeries.js */
    (function($, DX) {
        var series = DX.viz.charts.series;
        series.LineSeries = series.BaseSeries.inherit({
            ctor: function(renderer, data, options, isRangeSeries) {
                options.specificType = options.specificType || 'line';
                this.callBase(renderer, data, options, isRangeSeries);
                this.paths = this.paths || []
            },
            dispose: function() {
                this.paths = null;
                this.callBase()
            },
            drawSegment: function(segment, attributes) {
                return this.renderer.createPath(segment, attributes)
            },
            drawSeriesData: function(seriesElementsGroup, seriesMarkersGroup, labelsGroup) {
                var self = this;
                self.preparedSegments = [];
                self.paths = [];
                if (!self.points.length)
                    return;
                $.each(this.segments, function(index) {
                    self.prepareSegments(index)
                });
                if (self.styles.attributes.strokeWidth > 0)
                    $.each(self.preparedSegments, function(_, segment) {
                        self.paths.push(self.drawSegment(segment, self.styles.attributes).append(seriesElementsGroup))
                    });
                self.callBase(seriesElementsGroup, seriesMarkersGroup, labelsGroup)
            },
            prepareSegments: function(index) {
                this.preparedSegments = this.preparedSegments || [];
                this.preparedSegments[index] = this.segments[index]
            },
            drawTrackers: function() {
                var self = this,
                    styles = this.styles,
                    strokeWidth;
                self.callBase();
                if (!self.preparedSegments) {
                    self.preparedSegments = [];
                    $.each(self.segments, function(index) {
                        self.prepareSegments(index)
                    })
                }
                if (this._suppressTrackers)
                    return;
                strokeWidth = styles.attributes.strokeWidth < 20 ? 20 : styles.attributes.strokeWidth;
                self.trackerElements = [];
                $.each(this.preparedSegments, function(_, segment) {
                    var tracker = self.drawSegment(segment, {
                            strokeWidth: strokeWidth,
                            stroke: 'grey',
                            opacity: 0.0001
                        }).append(self.options.seriesTrackerGroup);
                    self.trackerElements.push(tracker);
                    tracker.data({series: self})
                });
                return this
            },
            applyNormalStyle: function(mode) {
                var self = this;
                if (this.paths) {
                    $.each(this.paths, function(_, path) {
                        path.applySettings(self.styles.states.normal)
                    });
                    return self.callBase(mode)
                }
            },
            applyHoverStyle: function(mode) {
                var self = this;
                if (this.paths) {
                    $.each(this.paths, function(_, path) {
                        path.applySettings(self.styles.states.hover)
                    });
                    return self.callBase(mode)
                }
            },
            applySelectionStyle: function(mode) {
                var self = this;
                if (this.paths) {
                    $.each(this.paths, function(_, path) {
                        if (path)
                            path.applySettings(self.styles.states.selected)
                    });
                    return self.callBase(mode)
                }
            },
            animate: function() {
                this.callBase();
                this.animatePath()
            },
            stopAnimation: function() {
                var segments = this.preparedSegments;
                this.callBase();
                if (this.paths)
                    $.each(this.paths, function(i, path) {
                        path.stopAnimation()
                    })
            },
            animatePath: function() {
                var self = this,
                    segments = self.preparedSegments;
                if (segments && segments.length && self.paths)
                    $.each(self.paths, function(i, path) {
                        var fromPoints = self.getZeroPathPoints(i);
                        path.applySettings({points: fromPoints});
                        path.animate({points: segments[i]})
                    })
            },
            getZeroPathPoints: function(i) {
                return $.map(this.preparedSegments[i], function(pt) {
                        return pt.getDefaultCoords()
                    })
            },
            adjustOptions: function() {
                var styles = this.styles,
                    attributes = styles.attributes,
                    hover = styles.states.hover,
                    selected = styles.states.selected,
                    normal = styles.states.normal;
                attributes.stroke = attributes.fill;
                attributes.fill = 'none';
                attributes.strokeWidth = attributes.lineWidth;
                normal.stroke = normal.fill;
                normal.fill = 'none';
                normal.strokeWidth = normal.lineWidth;
                hover.stroke = hover.fill;
                hover.fill = 'none';
                hover.strokeWidth = hover.lineWidth;
                selected.stroke = selected.fill;
                selected.fill = 'none';
                selected.strokeWidth = selected.lineWidth
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file areaSeries.js */
    (function($, DX) {
        var series = DX.viz.charts.series;
        series.AreaSeries = series.LineSeries.inherit({
            ctor: function(renderer, data, options, isRangeSeries) {
                this.type = options.specificType = options.specificType || 'area';
                this.callBase(renderer, data, options, isRangeSeries);
                this.areas = this.areas || [];
                this.areaSegments = this.areaSegments || []
            },
            dispose: function() {
                var _this = this;
                _this.areas = null;
                _this.areaSegments = null;
                _this.paths = null;
                _this.callBase()
            },
            drawSeriesData: function(seriesElementsGroup, seriesMarkersGroup, labelsGroup) {
                var self = this;
                self.resetLineColors();
                if (self.isStackedSeries() || self.isFullStackedSeries())
                    self.seriesGroup.toBackground();
                self.areas = [];
                if (!self.points.length)
                    return;
                self.paths = [];
                $.each(this.segments, function(index) {
                    self.prepareSegments(index)
                });
                $.each(self.preparedSegments, function(index, segment) {
                    self.prepareAreaPoints(index);
                    if (self.areaSegments[index].length === 2) {
                        var stickArea = self.drawSegment(self.areaSegments[index], self.styles.stick).append(seriesElementsGroup);
                        stickArea.stick = true;
                        self.areas.push(stickArea);
                        return
                    }
                    self.areas.push(self.renderer.createArea(self.areaSegments[index], self.styles.area).append(seriesElementsGroup))
                });
                if (self.styles.attributes.strokeWidth > 0 || self.styles.states.hover.strokeWidth > 0 || self.styles.states.selected.strokeWidth > 0)
                    $.each(self.preparedSegments, function(_, segment) {
                        self.paths.push(self.drawSegment(segment, self.styles.attributes).append(seriesElementsGroup))
                    });
                self.drawPoints(seriesMarkersGroup, labelsGroup);
                if (self.hoverPattern) {
                    self.styles.area.states.hover.fill = self.hoverPattern.id;
                    self.styles.area.states.selected.fill = self.selectedPattern.id;
                    self.styles.states.hover.fill = 'none';
                    self.styles.states.selected.fill = 'none'
                }
                return self
            },
            resetLineColors: function() {
                var styles = this.styles,
                    attributes = styles.attributes,
                    states = styles.states,
                    hover = states.hover,
                    selected = states.selected,
                    normal = states.normal;
                attributes.fill = 'none';
                delete attributes.lineWidth;
                normal.fill = 'none';
                delete normal.lineWidth;
                hover.fill = 'none';
                delete hover.lineWidth;
                selected.fill = 'none';
                delete selected.lineWidth
            },
            drawTrackers: function() {
                var self = this;
                if (this._suppressTrackers)
                    return;
                self.drawPointTrackers();
                self.trackerElements = [];
                $.each(this.areaSegments, function(_, segment) {
                    var tracker;
                    if (segment.length === 2)
                        tracker = self.drawSegment(segment, {
                            strokeWidth: 20,
                            stroke: 'grey',
                            opacity: 0.0001
                        }).append(self.options.seriesTrackerGroup);
                    else
                        tracker = self.renderer.createArea(segment, {
                            strokeWidth: 0,
                            fill: 'grey',
                            opacity: 0.0001
                        }).append(self.options.seriesTrackerGroup);
                    self.trackerElements.push(tracker);
                    tracker.data({series: self})
                });
                return series
            },
            prepareAreaPoints: function(index) {
                var segments = this.preparedSegments;
                var fwPoints = $.map(segments[index], function(pt) {
                        return pt.getCoords()
                    });
                var bwPoints = $.map(segments[index].slice().reverse(), function(pt) {
                        return pt.getCoords(true)
                    });
                this.areaSegments[index] = fwPoints.concat(bwPoints)
            },
            applyStyle: function(mode, style) {
                var self = this;
                if (this.areas)
                    $.each(this.areas, function(_, area) {
                        if (!area.stick)
                            area.applySettings(self.styles.area.states[style]);
                        else
                            area.applySettings(self.styles.stick.states[style])
                    })
            },
            applyNormalStyle: function(mode) {
                this.applyStyle(mode, 'normal');
                return this.callBase(mode)
            },
            applyHoverStyle: function(mode) {
                this.applyStyle(mode, 'hover');
                return this.callBase(mode)
            },
            applySelectionStyle: function(mode) {
                this.applyStyle(mode, 'selected');
                return this.callBase(mode)
            },
            animate: function() {
                var self = this;
                self.callBase();
                if (self.preparedSegments && self.preparedSegments.length && self.areas)
                    $.each(self.areas, function(i, area) {
                        var fromPoints = self.getZeroAreaPoints(i);
                        area.applySettings({points: fromPoints});
                        area.animate({points: self.areaSegments[i]})
                    })
            },
            stopAnimation: function() {
                var self = this;
                self.callBase();
                if (self.preparedSegments && self.preparedSegments.length && self.areas)
                    $.each(self.areas, function(_, area) {
                        area.stopAnimation()
                    })
            },
            getZeroAreaPoints: function(i) {
                var fwPoints,
                    bwPoints,
                    segments = this.preparedSegments;
                fwPoints = $.map(segments[i], function(pt) {
                    return pt.getDefaultCoords()
                });
                bwPoints = $.map(segments[i].slice().reverse(), function(pt) {
                    return pt.getDefaultCoords()
                });
                return fwPoints.concat(bwPoints)
            },
            adjustOptions: function() {
                var styles = this.styles,
                    attributes = styles.attributes,
                    states = styles.states,
                    hover = states.hover,
                    selected = states.selected,
                    normal = states.normal,
                    areaNormal = {},
                    areaHover = {},
                    areaSelected = {},
                    stickNormal = {},
                    stickHover = {},
                    stickSelected = {},
                    opacity;
                opacity = 'opacity' in attributes ? attributes.opacity : 0.5;
                areaNormal = {
                    fill: normal.fill,
                    stroke: 'none',
                    strokeWidth: 0,
                    opacity: opacity
                };
                areaHover = {
                    fill: hover.fill,
                    stroke: 'none',
                    strokeWidth: 0,
                    opacity: opacity
                };
                areaSelected = {
                    fill: selected.fill,
                    stroke: 'none',
                    strokeWidth: 0,
                    opacity: opacity
                };
                stickNormal = {
                    fill: 'none',
                    stroke: normal.fill,
                    strokeWidth: 1,
                    opacity: opacity
                };
                stickHover = {
                    fill: 'none',
                    stroke: hover.fill,
                    strokeWidth: 1,
                    opacity: opacity
                };
                stickSelected = {
                    fill: 'none',
                    stroke: selected.fill,
                    strokeWidth: 1,
                    opacity: opacity
                };
                styles.area = {
                    fill: attributes.fill,
                    stroke: 'none',
                    strokeWidth: 0,
                    opacity: opacity,
                    states: {
                        normal: areaNormal,
                        hover: areaHover,
                        selected: areaSelected
                    }
                };
                styles.stick = {
                    fill: 'none',
                    stroke: attributes.fill,
                    strokeWidth: 1,
                    opacity: opacity,
                    states: {
                        normal: stickNormal,
                        hover: stickHover,
                        selected: stickSelected
                    }
                }
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file barSeries.js */
    (function($, DX) {
        var series = DX.viz.charts.series;
        series.BarSeries = series.BaseSeries.inherit({
            ctor: function(renderer, data, options, isRangeSeries) {
                options.specificType = options.specificType || 'bar';
                this.callBase(renderer, data, options, isRangeSeries);
                this.stackName = options.stack || 'default'
            },
            getStackName: function() {
                if (this.type === 'stackedbar' || this.type === 'fullstackedbar')
                    return this.stackName;
                return null
            },
            drawSeriesData: function(seriesElementsGroup, seriesMarkersGroup, labelsGroup) {
                var series = this;
                if (series.points.length && series.hoverPattern) {
                    series.styles.point.states.hover.fill = series.hoverPattern.id;
                    series.styles.point.states.selected.fill = series.selectedPattern.id
                }
                return this.callBase(seriesElementsGroup, seriesMarkersGroup, labelsGroup)
            },
            adjustOptions: function() {
                var styles = this.styles,
                    options = this.options,
                    attributes = styles.attributes,
                    hover = styles.states.hover,
                    selected = styles.states.selected,
                    normal = styles.states.normal,
                    pointAttributes = styles.point.attributes,
                    pointHover = styles.point.states.hover,
                    pointSelected = styles.point.states.selected,
                    pointNormal = styles.point.states.normal,
                    hoverMode = options.hoverMode,
                    selectionMode = options.selectionMode,
                    func = function(mode) {
                        if (!mode)
                            return false;
                        switch (mode.toLowerCase()) {
                            case"allseriespoints":
                            case"allargumentpoints":
                            case"none":
                                return true
                        }
                    };
                $.extend(true, pointAttributes, attributes);
                $.extend(true, pointHover, hover);
                $.extend(true, pointSelected, selected);
                $.extend(true, pointNormal, normal);
                pointHover.r = pointSelected.r = pointNormal.r = pointAttributes.r;
                styles.point.hoverMode = func(hoverMode) && hoverMode;
                styles.point.selectionMode = func(selectionMode) && selectionMode;
                styles.point.visible = true
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file candleStickSeries.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            isDefined = DX.utils.isDefined;
        series.CandleStickSeries = series.BaseSeries.inherit({
            ctor: function(renderer, data, options) {
                options.specificType = options.specificType || 'candlestick';
                this.callBase(renderer, data, options)
            },
            dispose: function() {
                var _this = this;
                _this.hoverPatternReduction = null;
                _this.selectedPatternReduction = null;
                _this.callBase()
            },
            getRangeData: function() {
                var self = this,
                    options = self.options,
                    rotated = options.rotated,
                    valAxis = rotated ? 'X' : 'Y',
                    argAxis = rotated ? 'Y' : 'X',
                    points = self.points,
                    vals = [],
                    args = [];
                var compareNumeric = function(a, b) {
                        return a - b
                    };
                $.each(this.points, function(i, val) {
                    isDefined(val.argument) && args.push(val.argument);
                    if (val.hasValue()) {
                        vals.push(val.highValue);
                        vals.push(val.lowValue)
                    }
                });
                self.rangeData = {};
                var processArgument = function(arg, prevArg) {
                        var interval;
                        if (isDefined(prevArg))
                            interval = Math.abs(arg - prevArg);
                        if (isDefined(interval) && (interval < self.rangeData.intervalX || !isDefined(self.rangeData.intervalX)))
                            self.rangeData.intervalX = interval
                    };
                if (vals.length) {
                    vals.sort(compareNumeric);
                    self.rangeData['max' + valAxis] = vals[vals.length - 1];
                    self.rangeData['min' + valAxis] = vals[0];
                    $.each(points, function(i, point) {
                        var prevPoint,
                            arg = point.argument,
                            prevArg;
                        if (i !== 0) {
                            prevPoint = points[i - 1];
                            prevArg = prevPoint.argument
                        }
                        processArgument(arg, prevArg)
                    })
                }
                if (args.length && !(options.argumentAxisType === 'discrete')) {
                    args.sort(compareNumeric);
                    self.rangeData['min' + argAxis] = args[0];
                    self.rangeData['max' + argAxis] = args[args.length - 1]
                }
                else
                    self.rangeData['categories' + argAxis] = args;
                return this.rangeData
            },
            _parseInputData: function(data) {
                var self = this,
                    level,
                    pointFactory = series.pointFactory,
                    argumentField = this.options.argumentField || 'date',
                    openValueField = this.options.openValueField || 'open',
                    highValueField = this.options.highValueField || 'high',
                    lowValueField = this.options.lowValueField || 'low',
                    closeValueField = this.options.closeValueField || 'close',
                    tagField = this.options.tagField || 'tag',
                    pointStyles = this.styles.point,
                    reductionColor = this.styles.reduction.color,
                    innerColor = this.styles.reduction.innerColor,
                    prepData,
                    prevLevelValue,
                    className;
                this.points = [];
                this.segments = [];
                if (!data.length)
                    return;
                prepData = self._checkAndPrepareInputData(data, argumentField, [openValueField, highValueField, lowValueField, closeValueField]);
                self._validationResult = {
                    inputNotations: 0,
                    error: null
                };
                switch ((this.styles.reduction.level || '').toLowerCase()) {
                    case'open':
                        level = openValueField;
                        break;
                    case'high':
                        level = highValueField;
                        break;
                    case'low':
                        level = lowValueField;
                        break;
                    default:
                        level = closeValueField;
                        break
                }
                self.pointsByArgument = {};
                this.points = $.map(prepData, function(val, i) {
                    var pointStylesReduct = $.extend(true, {}, pointStyles || {}),
                        point;
                    className = 'dx-candle-default';
                    if (val[openValueField] !== null && val[highValueField] !== null && val[lowValueField] !== null & val[closeValueField] !== null) {
                        if (i != 0)
                            if (prevLevelValue != null && val[level] < prevLevelValue) {
                                pointStylesReduct.attributes.fill = pointStylesReduct.states.normal.fill = pointStylesReduct.states.hover.fill = pointStylesReduct.states.selected.fill = reductionColor;
                                pointStylesReduct.attributes.stroke = pointStylesReduct.states.normal.stroke = pointStylesReduct.states.hover.stroke = pointStylesReduct.states.selected.stroke = reductionColor;
                                className = 'dx-candle-reduction'
                            }
                        prevLevelValue = val[level];
                        if (val[openValueField] < val[closeValueField]) {
                            pointStylesReduct.attributes.fill = pointStylesReduct.states.normal.fill = pointStylesReduct.states.hover.fill = pointStylesReduct.states.selected.fill = innerColor;
                            className = (className ? className : '') + ' dx-candle-positive'
                        }
                    }
                    pointStylesReduct.attributes['class'] = className;
                    self.className = 'dx-candle-default';
                    point = pointFactory.createPoint(self.type, {
                        openValue: val[openValueField],
                        pointClassName: className,
                        highValue: val[highValueField],
                        lowValue: val[lowValueField],
                        closeValue: val[closeValueField],
                        argument: val[argumentField],
                        originalOpenValue: val['original' + openValueField],
                        originalHighValue: val['original' + highValueField],
                        originalLowValue: val['original' + lowValueField],
                        originalCloseValue: val['original' + closeValueField],
                        originalArgument: val['original' + argumentField],
                        options: pointStylesReduct,
                        tag: val.tag,
                        reductionValue: val[level],
                        series: self
                    });
                    self.pointsByArgument[point.argument.valueOf()] = self.pointsByArgument[point.argument.valueOf()] || point;
                    return point
                });
                this._segmenting()
            },
            _parseOptions: function(options) {
                this.callBase(options);
                $.extend(true, this.options, {
                    openValueField: options.openValueField,
                    closeValueField: options.closeValueField,
                    highValueField: options.highValueField,
                    lowValueField: options.lowValueField
                })
            },
            drawSeriesData: function(seriesElementsGroup, seriesMarkersGroup, labelsGroup) {
                var self = this;
                $.each(self.points, function(i, point) {
                    switch (point.pointClassName) {
                        case'dx-candle-reduction':
                            point.options.states.hover.fill = self.hoverPatternReduction.id;
                            point.options.states.selected.fill = self.selectedPatternReduction.id;
                            point.options.states.hover.stroke = self.hoverPatternReduction.id;
                            point.options.states.selected.stroke = self.selectedPatternReduction.id;
                            break;
                        case'dx-candle-default':
                            point.options.states.hover.fill = self.hoverPattern.id;
                            point.options.states.selected.fill = self.selectedPattern.id;
                            point.options.states.hover.stroke = self.hoverPattern.id;
                            point.options.states.selected.stroke = self.selectedPattern.id;
                            break;
                        case'dx-candle-reduction dx-candle-positive':
                            point.options.states.hover.stroke = self.hoverPatternReduction.id;
                            point.options.states.selected.stroke = self.selectedPatternReduction.id;
                            break;
                        default:
                            point.options.states.hover.stroke = self.hoverPattern.id;
                            point.options.states.selected.stroke = self.selectedPattern.id;
                            break
                    }
                });
                this.callBase(seriesElementsGroup, seriesMarkersGroup, labelsGroup);
                return this
            },
            createPatterns: function() {
                var self = this,
                    hover = self.styles.states.hover,
                    selected = self.styles.states.selected,
                    normal = self.styles.states.normal,
                    reductionColor = self.styles.reduction.color,
                    renderer = self.renderer;
                self.callBase();
                if (!self.patternColorReduction)
                    self.patternColorReduction = reductionColor;
                if (!self.hoverPatternReduction) {
                    self.hoverPatternReduction = renderer.createPattern(normal.fill === hover.fill ? self.patternColorReduction : hover.fill, hover.hatching);
                    self.selectedPatternReduction = renderer.createPattern(normal.fill === selected.fill ? self.patternColorReduction : selected.fill, selected.hatching)
                }
                self.hoverPatternReduction.append();
                self.selectedPatternReduction.append()
            },
            adjustOptions: function() {
                var styles = this.styles,
                    options = this.options,
                    attributes = styles.attributes,
                    hover = styles.states.hover,
                    selected = styles.states.selected,
                    normal = styles.states.normal,
                    pointAttributes = styles.point.attributes,
                    pointHover = styles.point.states.hover,
                    pointSelected = styles.point.states.selected,
                    pointNormal = styles.point.states.normal,
                    hoverMode = options.hoverMode,
                    selectionMode = options.selectionMode,
                    func = function(mode) {
                        if (!mode)
                            return false;
                        switch (mode.toLowerCase()) {
                            case"allseriespoints":
                            case"allargumentpoints":
                            case"none":
                                return true
                        }
                    };
                attributes.stroke = attributes.fill;
                attributes.strokeWidth = attributes.lineWidth;
                normal.stroke = normal.fill;
                normal.strokeWidth = normal.lineWidth;
                hover.stroke = hover.fill;
                hover.strokeWidth = hover.lineWidth;
                selected.stroke = selected.fill;
                selected.strokeWidth = selected.lineWidth;
                $.extend(true, pointAttributes, attributes);
                $.extend(true, pointHover, hover);
                $.extend(true, pointSelected, selected);
                $.extend(true, pointNormal, normal);
                pointHover.r = pointSelected.r = pointNormal.r = pointAttributes.r = 0;
                styles.point.hoverMode = func(hoverMode) && hoverMode;
                styles.point.selectionMode = func(selectionMode) && selectionMode;
                styles.point.visible = true
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file splineSeries.js */
    (function($, DX) {
        var series = DX.viz.charts.series;
        series.SplineSeries = series.LineSeries.inherit({
            ctor: function(renderer, data, options, isRangeSeries) {
                options.specificType = options.specificType || 'spline';
                this.callBase(renderer, data, options, isRangeSeries)
            },
            drawSegment: function(segment, attributes) {
                return this.renderer.createBezierPath(segment, attributes)
            },
            prepareSegments: function(index) {
                var self = this,
                    bezierPoints = [],
                    pointsCopy = self.segments[index];
                self.preparedSegments = self.preparedSegments || [];
                var checkExtr = function(otherPointCoord, pointCoord, controlCoord) {
                        return otherPointCoord > pointCoord && controlCoord > otherPointCoord || otherPointCoord < pointCoord && controlCoord < otherPointCoord ? otherPointCoord : controlCoord
                    };
                var clonePoint = function(point, newX, newY) {
                        var p = DX.utils.clone(point);
                        p.x = newX;
                        p.y = newY;
                        return p
                    };
                if (pointsCopy.length !== 1)
                    $.each(pointsCopy, function(i, curPoint) {
                        var leftControlX,
                            leftControlY,
                            rightControlX,
                            rightControlY,
                            prevPoint,
                            nextPoint,
                            xCur,
                            yCur,
                            x1,
                            x2,
                            y1,
                            y2,
                            delta,
                            lambda = 0.5,
                            curIsExtremum,
                            leftPoint,
                            rightPoint,
                            a,
                            b,
                            c,
                            xc,
                            yc,
                            shift;
                        if (!i) {
                            bezierPoints.push(curPoint);
                            bezierPoints.push(curPoint);
                            return
                        }
                        prevPoint = pointsCopy[i - 1];
                        if (i < pointsCopy.length - 1) {
                            nextPoint = pointsCopy[i + 1];
                            xCur = curPoint.x;
                            yCur = curPoint.y;
                            x1 = prevPoint.x;
                            x2 = nextPoint.x;
                            y1 = prevPoint.y;
                            y2 = nextPoint.y;
                            curIsExtremum = !!(!self.options.rotated && (yCur <= prevPoint.y && yCur <= nextPoint.y || yCur >= prevPoint.y && yCur >= nextPoint.y) || self.options.rotated && (xCur <= prevPoint.x && xCur <= nextPoint.x || xCur >= prevPoint.x && xCur >= nextPoint.x));
                            if (curIsExtremum)
                                if (!self.options.rotated) {
                                    rightControlY = leftControlY = yCur;
                                    rightControlX = (xCur + nextPoint.x) / 2;
                                    leftControlX = (xCur + prevPoint.x) / 2
                                }
                                else {
                                    rightControlX = leftControlX = xCur;
                                    rightControlY = (yCur + nextPoint.y) / 2;
                                    leftControlY = (yCur + prevPoint.y) / 2
                                }
                            else {
                                a = y2 - y1;
                                b = x1 - x2;
                                c = y1 * x2 - x1 * y2;
                                if (!self.options.rotated) {
                                    xc = xCur;
                                    yc = -1 * (a * xc + c) / b;
                                    shift = yc - yCur || 0;
                                    y1 -= shift;
                                    y2 -= shift
                                }
                                else {
                                    yc = yCur;
                                    xc = -1 * (b * yc + c) / a;
                                    shift = xc - xCur || 0;
                                    x1 -= shift;
                                    x2 -= shift
                                }
                                rightControlX = (xCur + lambda * x2) / (1 + lambda);
                                rightControlY = (yCur + lambda * y2) / (1 + lambda);
                                leftControlX = (xCur + lambda * x1) / (1 + lambda);
                                leftControlY = (yCur + lambda * y1) / (1 + lambda)
                            }
                            if (!self.options.rotated) {
                                leftControlY = checkExtr(prevPoint.y, yCur, leftControlY);
                                rightControlY = checkExtr(nextPoint.y, yCur, rightControlY)
                            }
                            else {
                                leftControlX = checkExtr(prevPoint.x, xCur, leftControlX);
                                rightControlX = checkExtr(nextPoint.x, xCur, rightControlX)
                            }
                            leftPoint = clonePoint(curPoint, leftControlX, leftControlY);
                            rightPoint = clonePoint(curPoint, rightControlX, rightControlY);
                            bezierPoints.push(leftPoint, curPoint, rightPoint)
                        }
                        else {
                            bezierPoints.push(curPoint, curPoint);
                            return
                        }
                    });
                else
                    bezierPoints.push(pointsCopy[0]);
                self.preparedSegments[index] = bezierPoints
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file splineAreaSeries.js */
    (function($, DX) {
        var series = DX.viz.charts.series;
        series.SplineAreaSeries = series.SplineSeries.inherit({
            ctor: function(renderer, data, options, isRangeSeries) {
                options.specificType = options.specificType || 'splinearea';
                this.callBase(renderer, data, options, isRangeSeries);
                this.areas = this.areas || [];
                this.areaSegments = this.areaSegments || []
            },
            dispose: function() {
                var _this = this;
                _this.areas = null;
                _this.areaSegments = null;
                _this.paths = null;
                _this.callBase()
            },
            drawSeriesData: function(seriesElementsGroup, seriesMarkersGroup, labelsGroup) {
                if (!this.points.length)
                    return;
                var self = this;
                if (!this.points.length)
                    return;
                this.resetLineColors();
                $.each(this.segments, function(index) {
                    self.prepareSegments(index)
                });
                this.areas = [];
                $.each(self.preparedSegments, function(index, segment) {
                    self.prepareBezierAreaPoints(index);
                    self.areas.push(self.renderer.createBezierArea(self.areaSegments[index], self.styles.area).append(seriesElementsGroup))
                });
                if (self.styles.attributes.strokeWidth > 0 || self.styles.states.hover.strokeWidth > 0 || self.styles.states.selected.strokeWidth > 0)
                    $.each(self.preparedSegments, function(_, segment) {
                        self.paths.push(self.drawSegment(segment, self.styles.attributes).append(seriesElementsGroup))
                    });
                self.drawPoints(seriesMarkersGroup, labelsGroup);
                if (self.hoverPattern) {
                    self.styles.area.states.hover.fill = self.hoverPattern.id;
                    self.styles.area.states.selected.fill = self.selectedPattern.id;
                    self.styles.states.hover.fill = 'none';
                    self.styles.states.selected.fill = 'none'
                }
                return self
            },
            resetLineColors: function() {
                var styles = this.styles,
                    attributes = styles.attributes,
                    states = styles.states,
                    hover = states.hover,
                    selected = states.selected,
                    normal = states.normal;
                attributes.fill = 'none';
                delete attributes.lineWidth;
                normal.fill = 'none';
                delete normal.lineWidth;
                hover.fill = 'none';
                delete hover.lineWidth;
                selected.fill = 'none';
                delete selected.lineWidth
            },
            drawTrackers: function() {
                var self = this;
                if (this._suppressTrackers)
                    return;
                self.drawPointTrackers();
                self.trackerElements = [];
                $.each(this.areaSegments, function(_, segment) {
                    var tracker = self.renderer.createBezierArea(segment, {
                            strokeWidth: 0,
                            fill: 'grey',
                            opacity: 0.0001
                        }).append(self.options.seriesTrackerGroup);
                    self.trackerElements.push(tracker);
                    tracker.data({series: self})
                });
                return series
            },
            prepareBezierAreaPoints: function(index) {
                var segments = this.preparedSegments;
                var fwPoints = $.map(segments[index], function(pt) {
                        return pt.getCoords()
                    });
                var bwPoints = $.map(segments[index].slice().reverse(), function(pt) {
                        return pt.getCoords(true)
                    });
                var lastFwPoint = fwPoints[fwPoints.length - 1];
                var firstBwPoint = bwPoints[0];
                this.areaSegments[index] = fwPoints.concat({
                    x: lastFwPoint.x,
                    y: lastFwPoint.y
                }, {
                    x: firstBwPoint.x,
                    y: firstBwPoint.y
                }, bwPoints)
            },
            applyNormalStyle: function(mode) {
                var self = this;
                if (this.areas)
                    $.each(this.areas, function(_, area) {
                        area.applySettings(self.styles.area.states.normal)
                    });
                return this.callBase(mode)
            },
            applyHoverStyle: function(mode) {
                var self = this;
                if (this.areas)
                    $.each(this.areas, function(_, area) {
                        area.applySettings(self.styles.area.states.hover)
                    });
                return this.callBase(mode)
            },
            applySelectionStyle: function(mode) {
                var self = this;
                if (this.areas)
                    $.each(this.areas, function(_, area) {
                        area.applySettings(self.styles.area.states.selected)
                    });
                return this.callBase(mode)
            },
            animate: function() {
                var self = this;
                this.callBase();
                if (this.preparedSegments && this.preparedSegments.length && this.areas)
                    $.each(this.areas, function(i, area) {
                        var fromPoints = self.getZeroAreaPoints(i);
                        area.applySettings({points: fromPoints});
                        area.animate({points: self.areaSegments[i]})
                    })
            },
            stopAnimation: function() {
                var self = this;
                self.callBase();
                if (self.preparedSegments && self.preparedSegments.length && self.areas)
                    $.each(self.areas, function(_, area) {
                        area.stopAnimation()
                    })
            },
            getZeroAreaPoints: function(i) {
                var fwPoints = $.map(this.preparedSegments[i], function(pt) {
                        return pt.getDefaultCoords()
                    });
                var bwPoints = $.map(this.preparedSegments[i].slice().reverse(), function(pt) {
                        return pt.getDefaultCoords()
                    });
                var lastFwPoint = fwPoints[fwPoints.length - 1];
                var firstBwPoint = bwPoints[0];
                return fwPoints.concat({
                        x: lastFwPoint.x,
                        y: lastFwPoint.y
                    }, {
                        x: firstBwPoint.x,
                        y: firstBwPoint.y
                    }, bwPoints)
            },
            adjustOptions: function() {
                var styles = this.styles,
                    attributes = styles.attributes,
                    states = styles.states,
                    hover = states.hover,
                    selected = states.selected,
                    normal = states.normal,
                    areaNormal = {},
                    areaHover = {},
                    areaSelected = {},
                    opacity;
                opacity = 'opacity' in attributes ? attributes.opacity : 0.5;
                areaNormal = {
                    fill: normal.fill,
                    stroke: 'none',
                    strokeWidth: 0,
                    opacity: opacity
                };
                areaHover = {
                    fill: hover.fill,
                    stroke: 'none',
                    strokeWidth: 0,
                    opacity: opacity
                };
                areaSelected = {
                    fill: selected.fill,
                    stroke: 'none',
                    strokeWidth: 0,
                    opacity: opacity
                };
                styles.area = {
                    fill: attributes.fill,
                    stroke: 'none',
                    strokeWidth: 0,
                    opacity: opacity,
                    states: {
                        normal: areaNormal,
                        hover: areaHover,
                        selected: areaSelected
                    }
                }
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file pieSeries.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            HOVERING_SPACING = 20,
            LABEL_SPACING = 80;
        series.PieSeries = series.BaseSeries.inherit({
            ctor: function(renderer, data, options) {
                options.specificType = options.specificType || 'pie';
                this.callBase(renderer, data, options);
                this.labelSpace = this.styles.point.label.visible ? LABEL_SPACING : 0;
                this.hoverSpace = 0 && this.styles.point.states.enableHover ? HOVERING_SPACING : 0;
                this.innerRadius = this.type === 'pie' ? 0 : options.innerRadius;
                this.outerRadius = options.radius;
                this.redraw = false
            },
            arrangePoints: function() {
                var series = this,
                    minSegmentSize = series.styles.minSegmentSize,
                    points,
                    pointsLength,
                    correction = 0,
                    translator = this.translator,
                    total = 0,
                    percent,
                    i,
                    totalDegreesMinValues = 0,
                    isClockWise = series.options.segmentsDirection !== 'anticlockwise';
                series.points = $.map(series.points, function(point) {
                    if (point.value === null || point.value < 0 || point.value === 0 && !minSegmentSize)
                        return null;
                    return point
                });
                points = series.points;
                pointsLength = points.length;
                for (i = 0; i < pointsLength; i++)
                    total += points[i].value;
                if (total === 0) {
                    total = pointsLength;
                    $.each(series.points, function(i, point) {
                        point.value = 1
                    })
                }
                $.each(points, function(i, point) {
                    if (minSegmentSize && point.value < minSegmentSize * total / 360)
                        totalDegreesMinValues += minSegmentSize
                });
                $.each(isClockWise ? points : points.concat([]).reverse(), function(i, point) {
                    var val = point.value,
                        updatedZeroValue;
                    if (minSegmentSize) {
                        var minShownValue = minSegmentSize * total / (360 - totalDegreesMinValues);
                        if (val < minShownValue) {
                            updatedZeroValue = minShownValue;
                            point.value = updatedZeroValue
                        }
                    }
                    percent = val / total;
                    point.correctValue(correction, percent);
                    correction = correction + (updatedZeroValue || val)
                })
            },
            createPatterns: function(){},
            drawSeriesData: function(seriesElementsGroup, seriesMarkersGroup, labelsGroup) {
                var self = this,
                    labelSpace,
                    bbox,
                    paneSpaceHeight,
                    paneSpaceWidth,
                    min;
                $.each(self.points, function(i, point) {
                    if (!point.hoverPatternColor) {
                        point.hoverPatternColor = point.options.states.hover.fill;
                        point.selectedPatternColor = point.options.states.selected.fill
                    }
                    if (!point.hoverPattern) {
                        point.hoverPattern = self.renderer.createPattern(point.hoverPatternColor, point.options.states.hover.hatching).append();
                        point.selectedPattern = self.renderer.createPattern(point.selectedPatternColor, point.options.states.selected.hatching).append()
                    }
                    point.hoverPattern.append();
                    point.selectedPattern.append();
                    point.options.states.hover.fill = point.hoverPattern.id;
                    point.options.states.selected.fill = point.selectedPattern.id
                });
                this.callBase(seriesElementsGroup, seriesMarkersGroup, labelsGroup);
                if (self.styles.point.label.visible) {
                    labelSpace = 0;
                    if (self.styles.point.label.position === 'columns') {
                        $.each(self.points, function(i, point) {
                            point.setLabelEllipsis = true;
                            bbox = point.insideLabelGroup.getBBox();
                            labelSpace = Math.max(bbox.width + point.INDENT_FROM_PIE + point.options.label.radialOffset, labelSpace)
                        });
                        self.redraw = true;
                        paneSpaceHeight = self.canvas.height - self.canvas.top - self.canvas.bottom;
                        paneSpaceWidth = self.canvas.width - self.canvas.left - self.canvas.right;
                        min = paneSpaceWidth < paneSpaceHeight ? paneSpaceWidth : paneSpaceHeight;
                        if (labelSpace > min / 2 - labelSpace)
                            self.labelSpace = min / 2;
                        else
                            self.labelSpace = 2 * labelSpace
                    }
                    else
                        $.each(self.points, function(i, point) {
                            point.setLabelEllipsis = true;
                            point.correctLabel()
                        })
                }
                return this
            },
            correctPosition: function(correction) {
                var debug = DX.utils.debug;
                debug.assert(correction, 'correction was not passed');
                debug.assertParam(correction.centerX, 'correction.centerX was not passed');
                debug.assertParam(correction.centerY, 'correction.centerY was not passed');
                debug.assertParam(correction.radiusInner, 'correction.radiusInner was not passed');
                debug.assertParam(correction.radiusOuter, 'correction.radiusOuter was not passed');
                $.each(this.points, function(_, point) {
                    point.correctPosition(correction)
                })
            },
            getRangeData: function() {
                var range = this.callBase();
                if (!range)
                    return range;
                if (range.minY !== undefined) {
                    range.minY = range.minY > 0 ? 0 : range.minY;
                    range.maxY = range.maxY < 0 ? 0 : range.maxY
                }
                return range
            },
            parseStyleOptions: function(options) {
                if (options.label && options.label.position && options.label.position !== 'outside' && options.label.position !== 'inside' && options.label.position !== 'columns')
                    options.label.position = 'outside';
                if (options.label.position && options.label.position === 'columns')
                    options.label.connector.visible = true;
                this.options.segmentsDirection = options.segmentsDirection || 'clockwise';
                this.styles = this.callBase(options);
                this.adjustOptions();
                return this.styles
            },
            adjustOptions: function() {
                var styles = this.styles,
                    options = this.options,
                    attributes = styles.attributes,
                    hover = styles.states.hover,
                    selected = styles.states.selected,
                    normal = styles.states.normal,
                    pointAttributes = styles.point.attributes,
                    pointHover = styles.point.states.hover,
                    pointSelected = styles.point.states.selected,
                    pointNormal = styles.point.states.normal,
                    hoverMode = options.hoverMode,
                    selectionMode = options.selectionMode,
                    func = function(mode) {
                        if (!mode)
                            return false;
                        switch (mode.toLowerCase()) {
                            case"none":
                                return true
                        }
                    };
                $.extend(true, pointAttributes, attributes);
                $.extend(true, pointHover, hover);
                $.extend(true, pointSelected, selected);
                $.extend(true, pointNormal, normal);
                pointHover.r = pointSelected.r = pointNormal.r = pointAttributes.r;
                styles.point.hoverMode = func(hoverMode) && hoverMode;
                styles.point.selectionMode = func(selectionMode) && selectionMode;
                styles.point.visible = true
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file otherSeries.js */
    (function($, DX) {
        var series = DX.viz.charts.series;
        series.RangeAreaSeries = series.AreaSeries.inherit({ctor: function(renderer, data, options) {
                options.specificType = options.specificType || 'rangearea';
                this.callBase(renderer, data, options, true)
            }});
        series.RangeBarSeries = series.BarSeries.inherit({ctor: function(renderer, data, options) {
                options.specificType = options.specificType || 'rangebar';
                this.callBase(renderer, data, options, true)
            }});
        series.RangeSplineAreaSeries = series.SplineAreaSeries.inherit({ctor: function(renderer, data, options) {
                options.specificType = options.specificType || 'rangesplinearea';
                this.callBase(renderer, data, options, true)
            }});
        series.ScatterSeries = series.BaseSeries.inherit({ctor: function(renderer, data, options) {
                options.specificType = options.specificType || 'scatter';
                this.callBase(renderer, data, options)
            }});
        series.StockSeries = series.CandleStickSeries.inherit({
            ctor: function(renderer, data, options) {
                options.specificType = options.specificType || 'stock';
                this.callBase(renderer, data, options)
            },
            drawSeriesData: function(seriesElementsGroup, seriesMarkersGroup, labelsGroup) {
                var self = this,
                    hoverStroke = self.styles.states.hover.stroke,
                    selectedStroke = self.styles.states.selected.stroke,
                    normalStroke = self.styles.states.normal.stroke,
                    reductionColor = self.styles.reduction.color;
                $.each(self.points, function(i, point) {
                    switch (point.pointClassName) {
                        case'dx-candle-reduction':
                        case'dx-candle-reduction dx-candle-positive':
                            point.options.states.hover.stroke = normalStroke === hoverStroke ? reductionColor : hoverStroke;
                            point.options.states.selected.stroke = normalStroke === selectedStroke ? reductionColor : selectedStroke;
                            break;
                        default:
                            point.options.states.hover.stroke = hoverStroke;
                            point.options.states.selected.stroke = selectedStroke;
                            break
                    }
                });
                self.drawPoints(seriesMarkersGroup, labelsGroup);
                return this
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file stepSeries.js */
    (function($, DX) {
        var series = DX.viz.charts.series;
        var prepareSegments = function(index) {
                var self = this,
                    segmentPoint = [];
                self.preparedSegments = self.preparedSegments || [];
                $.each(self.segments[index], function(i, pt) {
                    var stepY;
                    if (!i) {
                        segmentPoint.push(pt);
                        return
                    }
                    stepY = segmentPoint[segmentPoint.length - 1].y;
                    if (stepY !== pt.y) {
                        var point = DX.utils.clone(pt);
                        point.y = stepY;
                        segmentPoint.push(point)
                    }
                    segmentPoint.push(pt)
                });
                self.preparedSegments[index] = segmentPoint
            };
        series.StepLineSeries = series.LineSeries.inherit({
            ctor: function(renderer, data, options, isRangeSeries) {
                this.type = options.specificType = options.specificType || 'stepline';
                this.callBase(renderer, data, options, isRangeSeries)
            },
            prepareSegments: prepareSegments
        });
        series.StepAreaSeries = series.AreaSeries.inherit({
            ctor: function(renderer, data, options, isRangeSeries) {
                this.type = options.specificType = options.specificType || 'steparea';
                this.callBase(renderer, data, options, isRangeSeries)
            },
            prepareSegments: prepareSegments
        })
    })(jQuery, DevExpress);
    /*! Module viz, file seriesFamily.js */
    (function($, DX, undefined) {
        DX.viz.charts.series.SeriesFamily = DX.Class.inherit(function() {
            var ctor = function(options) {
                    var debug = DX.utils.debug;
                    debug.assert(options.type, 'type was not passed or empty');
                    var self = this,
                        stubFunction = $.noop;
                    $.extend(self, options);
                    self.type = self.type.toLowerCase();
                    self.series = [];
                    switch (self.type) {
                        case'bar':
                            self.adjustSeriesDimensions = adjustBarSeriesDimensions;
                            self.adjustSeriesValues = stubFunction;
                            self.updateSeriesValues = updateBarSeriesValues;
                            break;
                        case'rangebar':
                            self.adjustSeriesDimensions = adjustBarSeriesDimensions;
                            self.adjustSeriesValues = stubFunction;
                            self.updateSeriesValues = stubFunction;
                            break;
                        case'fullstackedbar':
                            self.fullStacked = true;
                            self.adjustSeriesDimensions = adjustStackedBarSeriesDimensions;
                            self.adjustSeriesValues = adjustStackedSeriesValues;
                            self.updateSeriesValues = updateStackedSeriesValues;
                            break;
                        case'stackedbar':
                            self.adjustSeriesDimensions = adjustStackedBarSeriesDimensions;
                            self.adjustSeriesValues = adjustStackedSeriesValues;
                            self.updateSeriesValues = updateStackedSeriesValues;
                            break;
                        case'fullstackedarea':
                        case'fullstackedline':
                            self.fullStacked = true;
                            self.adjustSeriesDimensions = stubFunction;
                            self.adjustSeriesValues = adjustStackedSeriesValues;
                            self.updateSeriesValues = stubFunction;
                            break;
                        case'stackedarea':
                        case'stackedline':
                            self.adjustSeriesDimensions = stubFunction;
                            self.adjustSeriesValues = adjustStackedSeriesValues;
                            self.updateSeriesValues = stubFunction;
                            break;
                        case'candlestick':
                        case'stock':
                            self.adjustSeriesDimensions = adjuistCandlestickSeriesDimensions;
                            self.adjustSeriesValues = stubFunction;
                            self.updateSeriesValues = stubFunction;
                            break;
                            self.updateSeriesValues = stubFunction;
                        default:
                            self.adjustSeriesDimensions = stubFunction;
                            self.adjustSeriesValues = stubFunction;
                            self.updateSeriesValues = stubFunction;
                            break
                    }
                };
            var dispose = function() {
                    this.series = null;
                    this.translator = null
                };
            var add = function(series) {
                    var self = this,
                        singleSeries,
                        i;
                    if (!$.isArray(series))
                        series = [series];
                    for (i = 0; i < series.length; i++) {
                        singleSeries = series[i];
                        if (singleSeries.type.toLowerCase() === self.type)
                            self.series.push(singleSeries)
                    }
                };
            var adjustBarSeriesDimensionsCore = function(series, interval, stackCount, equalBarWidth, seriesStackIndexCallback) {
                    var spacing,
                        width,
                        maxWidth,
                        middleIndex,
                        stackIndex,
                        i,
                        point,
                        points,
                        seriesOffset,
                        stackName,
                        argumentsKeeper = {},
                        stackKeepers = {},
                        stacksWithArgument,
                        count,
                        round = Math.round;
                    if (equalBarWidth) {
                        width = equalBarWidth.width && equalBarWidth.width < 0 ? 0 : equalBarWidth.width;
                        spacing = equalBarWidth.spacing && equalBarWidth.spacing < 0 ? 0 : equalBarWidth.spacing;
                        if (width && !spacing)
                            if (stackCount > 1) {
                                spacing = round((interval * 0.7 - width * stackCount) / (stackCount - 1));
                                if (spacing < 1)
                                    spacing = 1
                            }
                            else
                                spacing = 0;
                        else if (spacing && !width) {
                            width = round((interval * 0.7 - spacing * (stackCount - 1)) / stackCount);
                            if (width < 2)
                                width = 2
                        }
                        else if (!spacing && !width) {
                            if (stackCount > 1) {
                                spacing = round(interval * 0.7 / stackCount * 0.2);
                                if (spacing < 1)
                                    spacing = 1
                            }
                            else
                                spacing = 0;
                            width = round((interval * 0.7 - spacing * (stackCount - 1)) / stackCount);
                            if (width < 2)
                                width = 2
                        }
                        if (width * stackCount + spacing * (stackCount - 1) > interval) {
                            spacing = round((interval * 0.7 - width * stackCount) / (stackCount - 1));
                            if (spacing < 1) {
                                spacing = 1;
                                maxWidth = round((interval * 0.7 - spacing * (stackCount - 1)) / stackCount)
                            }
                        }
                        middleIndex = stackCount / 2;
                        for (i = 0; i < series.length; i++) {
                            stackIndex = seriesStackIndexCallback(i);
                            points = series[i].getPoints();
                            seriesOffset = (stackIndex - middleIndex + 0.5) * (maxWidth || width) - (middleIndex - stackIndex - 0.5) * spacing;
                            $.each(points, function(_, point) {
                                point.correctCoordinates({
                                    width: width,
                                    offset: seriesOffset
                                })
                            })
                        }
                    }
                    else {
                        $.each(series, function(i, singleSeries) {
                            stackName = singleSeries.getStackName && singleSeries.getStackName();
                            stackName = stackName || i.toString();
                            if (!stackKeepers[stackName])
                                stackKeepers[stackName] = [];
                            stackKeepers[stackName].push(singleSeries)
                        });
                        $.each(series, function(i, singleSeries) {
                            $.each(singleSeries.getPoints(), function(_, point) {
                                var argument = point.argument;
                                if (!argumentsKeeper.hasOwnProperty(argument))
                                    argumentsKeeper[argument] = 1
                            })
                        });
                        for (var argument in argumentsKeeper) {
                            if (!argumentsKeeper.hasOwnProperty(argument))
                                continue;
                            stacksWithArgument = [];
                            $.each(stackKeepers, function(stackName, seriesInStack) {
                                $.each(seriesInStack, function(i, singleSeries) {
                                    point = singleSeries.getPointByArg(argument);
                                    if (point && point.value) {
                                        stacksWithArgument.push(stackName);
                                        return false
                                    }
                                })
                            });
                            count = stacksWithArgument.length;
                            spacing = round(interval * 0.7 / count * 0.2);
                            if (spacing < 1)
                                spacing = 1;
                            width = round((interval * 0.7 - spacing * (count - 1)) / count);
                            if (width < 2)
                                width = 2;
                            middleIndex = count / 2;
                            $.each(stackKeepers, function(stackName, seriesInStack) {
                                stackIndex = $.inArray(stackName, stacksWithArgument);
                                if (stackIndex === -1)
                                    return;
                                seriesOffset = (stackIndex - middleIndex + 0.5) * width - (middleIndex - stackIndex - 0.5) * spacing;
                                $.each(seriesInStack, function(i, singleSeries) {
                                    var point = singleSeries.getPointByArg(argument);
                                    if (point && point.value)
                                        point.correctCoordinates({
                                            width: width,
                                            offset: seriesOffset
                                        })
                                })
                            })
                        }
                    }
                };
            var adjustBarSeriesDimensions = function(translator) {
                    var debug = DX.utils.debug;
                    debug.assert(translator, 'translator was not passed or empty');
                    var self = this,
                        series = self.series,
                        equalBarWidth = self.equalBarWidth,
                        interval;
                    self.translator = translator;
                    interval = setInterval(self);
                    adjustBarSeriesDimensionsCore(series, interval, series.length, equalBarWidth, function(seriesIndex) {
                        return seriesIndex
                    })
                };
            var adjustStackedBarSeriesDimensions = function(translator) {
                    var debug = DX.utils.debug;
                    debug.assert(translator, 'translator was not passed or empty');
                    var self = this,
                        interval,
                        series = self.series,
                        stackIndexes = {},
                        stackCount = 0,
                        equalBarWidth = self.equalBarWidth;
                    $.each(series, function() {
                        var stackName = this.getStackName();
                        if (!stackIndexes.hasOwnProperty(stackName))
                            stackIndexes[stackName] = stackCount++
                    });
                    self.translator = translator;
                    interval = setInterval(self);
                    adjustBarSeriesDimensionsCore(series, interval, stackCount, equalBarWidth, function(seriesIndex) {
                        return stackIndexes[series[seriesIndex].getStackName()]
                    })
                };
            var adjustStackedSeriesValues = function() {
                    var self = this,
                        series = self.series,
                        stackKeepers = {
                            positive: {},
                            negative: {}
                        };
                    $.each(series, function(_, singleSeries) {
                        var points = singleSeries.getPoints();
                        $.each(points, function(index, point) {
                            var value = point.value,
                                argument = point.argument,
                                stackName = singleSeries.getStackName ? singleSeries.getStackName() : 'default',
                                valueType = value >= 0 ? 'positive' : 'negative',
                                currentStack;
                            stackKeepers[valueType][stackName] = stackKeepers[valueType][stackName] || {};
                            currentStack = stackKeepers[valueType][stackName];
                            if (currentStack[argument.valueOf()]) {
                                points[index].correctValue(currentStack[argument.valueOf()]);
                                currentStack[argument.valueOf()] += value
                            }
                            else
                                currentStack[argument.valueOf()] = value
                        })
                    });
                    setPercentStackedValues(series, stackKeepers, self.fullStacked)
                };
            var setPercentStackedValues = function(series, stackKeepers, fullStacked) {
                    $.each(series, function(_, singleSeries) {
                        var points = singleSeries.getPoints();
                        $.each(points, function(index, point) {
                            var value = point.value,
                                stackName = singleSeries.getStackName ? singleSeries.getStackName() : 'default',
                                valueType = value >= 0 ? 'positive' : 'negative',
                                currentStack;
                            stackKeepers[valueType][stackName] = stackKeepers[valueType][stackName] || {};
                            currentStack = stackKeepers[valueType][stackName];
                            points[index].setPercentValue(currentStack[point.argument.valueOf()], fullStacked)
                        })
                    })
                };
            var getMinShownBusinessValue = function(self, translator, minBarSize) {
                    var rotated = self.rotated,
                        canvas = translator.getCanvasVisibleArea();
                    if (minBarSize && !rotated)
                        return Math.abs(translator.untranslateY(canvas.minY) - translator.untranslateY(canvas.minY + minBarSize));
                    else if (minBarSize && rotated)
                        return Math.abs(translator.untranslateX(canvas.minX) - translator.untranslateX(canvas.minX + minBarSize))
                };
            var updateStackedSeriesValues = function(translator) {
                    var self = this,
                        series = self.series,
                        stackKeepers = {
                            positive: {},
                            negative: {}
                        };
                    $.each(series, function(_, singleSeries) {
                        var points = singleSeries.getPoints(),
                            minBarSize = singleSeries.styles && singleSeries.styles.minBarSize;
                        $.each(points, function(index, point) {
                            var value = point.value,
                                minValue = point.minValue,
                                argument = point.argument,
                                updateValue,
                                pointSize,
                                minShownBusinessValue,
                                stackName = singleSeries.getStackName ? singleSeries.getStackName() : 'default',
                                valueType = value >= 0 ? 'positive' : 'negative',
                                currentStack;
                            minShownBusinessValue = getMinShownBusinessValue(self, translator, minBarSize);
                            stackKeepers[valueType][stackName] = stackKeepers[valueType][stackName] || {};
                            currentStack = stackKeepers[valueType][stackName];
                            if (currentStack[argument.valueOf()]) {
                                pointSize = Math.abs(minValue - value);
                                if (minShownBusinessValue && pointSize < minShownBusinessValue && pointSize !== 0)
                                    updateValue = minShownBusinessValue;
                                else
                                    updateValue = Math.abs(value - minValue);
                                points[index].minValue = currentStack[argument.valueOf()];
                                points[index].value = currentStack[argument.valueOf()] + updateValue;
                                currentStack[argument.valueOf()] += updateValue
                            }
                            else {
                                pointSize = value;
                                if (minShownBusinessValue && pointSize < minShownBusinessValue && pointSize !== 0)
                                    updateValue = minShownBusinessValue;
                                else
                                    updateValue = value;
                                points[index].value = updateValue;
                                currentStack[argument.valueOf()] = updateValue
                            }
                        })
                    });
                    if (self.fullStacked)
                        updateFullStackedSeriesValues(series, stackKeepers)
                };
            var updateFullStackedSeriesValues = function(series, stackKeepers) {
                    $.each(series, function(_, singleSeries) {
                        var stackName = singleSeries.getStackName ? singleSeries.getStackName() : 'default',
                            points = singleSeries.getPoints();
                        $.each(points, function(index, point) {
                            var value = point.value,
                                argument = point.argument,
                                valueType = value >= 0 ? 'positive' : 'negative',
                                currentStack;
                            stackKeepers[valueType][stackName] = stackKeepers[valueType][stackName] || {};
                            currentStack = stackKeepers[valueType][stackName];
                            points[index].value = points[index].value / currentStack[argument.valueOf()] || 0;
                            if (DX.utils.isNumber(points[index].minValue))
                                points[index].minValue = points[index].minValue / currentStack[argument.valueOf()] || 0
                        })
                    })
                };
            var updateBarSeriesValues = function(translator) {
                    var self = this,
                        series = self.series,
                        rotated = self.rotated,
                        canvas = translator.getCanvasVisibleArea();
                    $.each(series, function(_, singleSeries) {
                        var points = singleSeries.getPoints(),
                            minBarSize = singleSeries.styles && singleSeries.styles.minBarSize;
                        $.each(points, function(index, point) {
                            var value = point.value,
                                updateValue,
                                pointSize,
                                minShownBusinessValue;
                            minShownBusinessValue = getMinShownBusinessValue(self, translator, minBarSize);
                            pointSize = Math.abs(value);
                            if (minShownBusinessValue && pointSize < minShownBusinessValue && pointSize !== 0)
                                updateValue = value > 0 ? minShownBusinessValue : -minShownBusinessValue;
                            else
                                updateValue = value;
                            points[index].value = updateValue
                        })
                    })
                };
            var adjuistCandlestickSeriesDimensions = function(translator) {
                    var debug = DX.utils.debug;
                    debug.assert(translator, 'translator was not passed or empty');
                    var self = this,
                        series = self.series,
                        interval;
                    self.translator = translator;
                    interval = setInterval(self);
                    adjustBarSeriesDimensionsCore(series, interval, series.length, true, function(seriesIndex) {
                        return seriesIndex
                    })
                };
            var setInterval = function(self) {
                    if (!self.rotated)
                        self.interval = self.translator.getIntervalX();
                    else
                        self.interval = self.translator.getIntervalY();
                    return self.interval
                };
            return {
                    ctor: ctor,
                    dispose: dispose,
                    add: add
                }
        }())
    })(jQuery, DevExpress);
    /*! Module viz, file factory.js */
    (function($, DX) {
        var charts = DX.viz.charts,
            series = charts.series,
            renderers = DX.viz.renderers;
        charts.factory = function() {
            var createSeries = function(seriesType, renderer, data, options) {
                    options = options || {};
                    options.specificType = null;
                    seriesType = (String(seriesType) || '').toLowerCase();
                    switch (seriesType.toLowerCase()) {
                        case'line':
                            return new series.LineSeries(renderer, data, options);
                        case'fullstackedline':
                            options.specificType = 'fullstackedline';
                            return new series.LineSeries(renderer, data, options);
                        case'stackedline':
                            options.specificType = 'stackedline';
                            return new series.LineSeries(renderer, data, options);
                        case'area':
                            return new series.AreaSeries(renderer, data, options);
                        case'fullstackedarea':
                            options.specificType = 'fullstackedarea';
                            return new series.AreaSeries(renderer, data, options);
                        case'stackedarea':
                            options.specificType = 'stackedarea';
                            return new series.AreaSeries(renderer, data, options);
                        case'bar':
                            return new series.BarSeries(renderer, data, options);
                        case'fullstackedbar':
                            options.specificType = 'fullstackedbar';
                            return new series.BarSeries(renderer, data, options);
                        case'stackedbar':
                            options.specificType = 'stackedbar';
                            return new series.BarSeries(renderer, data, options);
                        case'spline':
                            return new series.SplineSeries(renderer, data, options);
                        case'splinearea':
                            return new series.SplineAreaSeries(renderer, data, options);
                        case'scatter':
                            return new series.ScatterSeries(renderer, data, options);
                        case'candlestick':
                            return new series.CandleStickSeries(renderer, data, options);
                        case'stock':
                            return new series.StockSeries(renderer, data, options);
                        case'rangearea':
                            return new series.RangeAreaSeries(renderer, data, options);
                        case'rangebar':
                            return new series.RangeBarSeries(renderer, data, options);
                        case'pie':
                            return new series.PieSeries(renderer, data, options);
                        case'doughnut':
                        case'donut':
                            options.specificType = 'doughnut';
                            return new series.PieSeries(renderer, data, options);
                        case'stepline':
                            return new series.StepLineSeries(renderer, data, options);
                        case'steparea':
                            return new series.StepAreaSeries(renderer, data, options);
                        default:
                            return null
                    }
                };
            var createSeriesFamily = function(options) {
                    return new series.SeriesFamily(options)
                };
            var createAxis = function(renderer, options) {
                    return new charts.Axis(renderer, options)
                };
            var createRenderer = function(options) {
                    return new renderers.Renderer(options)
                };
            var createThemeManager = function(options, groupName) {
                    return new charts.ThemeManager(options, groupName)
                };
            var createLegend = function(options, group, trackerGroup) {
                    return new charts.Legend(options, group, trackerGroup)
                };
            var createTooltip = function(options, group) {
                    return new charts.Tooltip(options, group)
                };
            var createTracker = function(options) {
                    return new charts.Tracker(options)
                };
            var createTitle = function(renderer, canvas, options, group) {
                    return new charts.ChartTitle(renderer, canvas, options, group)
                };
            var createChartLayoutManager = function() {
                    return new charts.LayoutManager
                };
            var getAxisTickProvider = function() {
                    return DX.viz.core.tickProvider
                };
            return {
                    createSeries: createSeries,
                    createSeriesFamily: createSeriesFamily,
                    createAxis: createAxis,
                    getAxisTickProvider: getAxisTickProvider,
                    createRenderer: createRenderer,
                    createThemeManager: createThemeManager,
                    createLegend: createLegend,
                    createTooltip: createTooltip,
                    createTracker: createTracker,
                    createChartLayoutManager: createChartLayoutManager,
                    createTitle: createTitle
                }
        }()
    })(jQuery, DevExpress);
    /*! Module viz, file tracker.js */
    (function($, DX) {
        var charts = DX.viz.charts,
            eventsConsts = charts.series.consts.events,
            utils = DX.utils,
            isFunction = utils.isFunction,
            isDefined = utils.isDefined,
            MULTIPLE_MODE = 'multiple',
            SINGLE_MODE = 'single',
            ALL_ARGUMENTS_POINTS_MODE = 'allargumentpoints',
            ALL_SERIES_POINTS_MODE = 'allseriespoints',
            msPointerEnabled = window.navigator.msPointerEnabled && window.navigator.msMaxTouchPoints || window.navigator.pointerEnabled && window.navigator.maxTouchPoints || null,
            MOUSE_EVENT_LOCK_TIMEOUT = 1000,
            CLICK_EVENT_LOCK_TIMEOUT = 600,
            TOOLTIP_HOLD_TIMEOUT = 400,
            NONE_MODE = 'none';
        charts.Tracker = DX.Class.inherit({
            ctor: function(options) {
                var _this = this;
                options.events = options.events || {};
                _this._reinit(options);
                _this.pointSelectionMode = _this._prepareMode(options.pointSelectionMode);
                _this.seriesSelectionMode = _this._prepareMode(options.seriesSelectionMode);
                _this.hoverStartDelay = 100;
                _this.hoverHoldDelay = 200;
                _this.sensitivity = 7;
                if (_this.pointSelectionMode === MULTIPLE_MODE) {
                    _this._releaseSelectedPoint = _this._releaseSelectedPointMultiMode;
                    _this.selectedPoint = []
                }
                else
                    _this._releaseSelectedPoint = _this._releaseSelectedPointSingleMode;
                if (_this.seriesSelectionMode === MULTIPLE_MODE) {
                    _this._releaseSelectedSeries = _this._releaseSelectedSeriesMultiMode;
                    _this.selectedSeries = []
                }
                else
                    _this._releaseSelectedSeries = _this._releaseSelectedSeriesSingleMode;
                _this.tooltipEnabled = options.tooltipEnabled;
                _this.tooltipShown = options.tooltipShown;
                _this.tooltipHidden = options.tooltipHidden;
                _this.seriesClick = options.events.seriesClick;
                _this.pointClick = options.events.pointClick;
                _this.argumentAxisClick = options.events.argumentAxisClick;
                _this.seriesHover = options.events.seriesHover;
                _this.seriesSelected = options.events.seriesSelected;
                _this.pointHover = options.events.pointHover;
                _this.pointSelected = options.events.pointSelected;
                _this.seriesTrackerGroup = options.seriesTrackerGroup;
                _this.markerTrackerGroup = options.markerTrackerGroup;
                _this.seriesGroup = options.seriesGroup;
                _this.legendGroup = options.legendGroup;
                _this.seriesGroup.on(eventsConsts.selectSeries, {tracker: _this}, _this._selectSeries);
                _this.seriesGroup.on(eventsConsts.deselectSeries, {tracker: _this}, _this._deselectSeries);
                _this.seriesGroup.on(eventsConsts.selectPoint, {tracker: _this}, _this._selectPoint);
                _this.seriesGroup.on(eventsConsts.deselectPoint, {tracker: _this}, _this._deselectPoint);
                _this.seriesGroup.on(eventsConsts.showPointTooltip, {tracker: _this}, _this._showPointTooltip);
                _this.seriesGroup.on(eventsConsts.hidePointTooltip, {tracker: _this}, _this._hidePointTooltip)
            },
            _clean: function() {
                var _this = this;
                _this.selectedPoint = _this.pointSelectionMode === MULTIPLE_MODE ? [] : null;
                _this.selectedSeries = _this.seriesSelectionMode === MULTIPLE_MODE ? [] : null;
                _this.hoveredPoint = null;
                _this.hoveredSeries = null;
                _this._hideTooltip(_this.pointAtShownTooltip);
                clearTimeout(_this.tooltipHoldTimeout);
                clearTimeout(_this.hoverStartTimeOut);
                clearTimeout(_this.hoverHoldTimeOut)
            },
            _reinit: function(options) {
                options = options || {};
                this.storedSeries = options.series || [];
                this.argumentAxis = options.argumentAxis || [];
                this._clean()
            },
            dispose: function() {
                var _this = this;
                clearTimeout(_this.tooltipHoldTimeout);
                clearTimeout(_this.hoverStartTimeOut);
                clearTimeout(_this.hoverHoldTimeOut);
                clearTimeout(_this.unlockMouseTimer);
                clearTimeout(_this.lockClickTimer);
                $.each(_this.argumentAxis, function(_, axis) {
                    axis._axisElementsGroup && axis._axisElementsGroup.off()
                });
                _this.seriesTrackerGroup.off();
                _this.markerTrackerGroup.off();
                _this.legendGroup.off();
                _this.seriesGroup.off();
                _this.argumentAxis = null;
                _this.seriesTrackerGroup = null;
                _this.markerTrackerGroup = null;
                _this.legendGroup = null;
                _this.seriesGroup = null;
                _this.selectedPoint = null;
                _this.selectedSeries = null;
                _this.hoveredSeries = null;
                _this.hoveredPoint = null;
                _this.storedSeries = null;
                _this.argumentAxis = null;
                _this.hoveredObject = null;
                _this.pointAtShownTooltip = null
            },
            _prepareMode: function(mode) {
                mode = (mode || '').toLowerCase();
                return mode = mode !== SINGLE_MODE && mode !== MULTIPLE_MODE ? SINGLE_MODE : mode
            },
            _prepare: function(typeChart) {
                var _this = this;
                $.each(_this.argumentAxis, function(_, axis) {
                    _this._eventHandler(axis._axisElementsGroup, {
                        parser: _this._getOptionsAxis,
                        condition: _this._axisCondition,
                        execute: _this._axisEvent
                    }, {
                        tracker: _this,
                        axis: axis
                    })
                });
                _this._eventHandler(_this.seriesTrackerGroup, {
                    parser: _this._getOptionsPointSeries,
                    condition: _this._seriesCondition,
                    execute: _this._seriesEvent
                }, {tracker: _this});
                _this._eventHandler(_this.markerTrackerGroup, {
                    parser: _this._getOptionsPointSeries,
                    condition: _this._pointCondition,
                    execute: _this._pointEvent
                }, {tracker: _this});
                if (typeChart === 'pieChart')
                    _this._eventHandler(_this.legendGroup, {
                        parser: _this._getOptionsPointSeries,
                        condition: _this._pointCondition,
                        execute: _this._pointEvent
                    }, {tracker: _this});
                else
                    _this._eventHandler(_this.legendGroup, {
                        parser: _this._getOptionsPointSeries,
                        condition: _this._seriesCondition,
                        execute: _this._seriesEvent
                    }, {tracker: _this})
            },
            _eventHandler: function(group, handlers, data) {
                var prepareHandlers = this._designerHandlers(handlers);
                group.off(".dxc-tracker");
                group.on(prepareHandlers, data)
            },
            _designerHandlers: function(handler) {
                var handlers = {},
                    parser = handler.parser,
                    condition = handler.condition,
                    execute = handler.execute,
                    designerHandle = function(eventType, func) {
                        if (condition && condition[eventType] === null)
                            return;
                        handlers[eventType + ".dxc-tracker"] = function(event) {
                            var options = parser ? parser(event) : event;
                            if (!options)
                                return;
                            if (condition && condition[eventType] && condition[eventType].call)
                                condition[eventType].apply(null, options.concat([func]));
                            else
                                func.apply(null, options)
                        }
                    };
                $.each(execute, designerHandle);
                return handlers
            },
            _getOptionsPointSeries: function(event) {
                var object = $(event.target).data('point') || $(event.target).data('series'),
                    self = event.data.tracker,
                    mode = object && ($(event.target).data('mode') || object.options.hoverMode);
                if (event.type === 'mousemove')
                    return [self, event.pageX, event.pageY];
                if (!object)
                    return null;
                return [self, object, mode]
            },
            _getOptionsAxis: function(event) {
                var self = event.data.tracker,
                    axis = event.data.axis,
                    mode = axis.options.hoverMode,
                    argument;
                if (event.target.tagName === "tspan")
                    argument = $(event.target).parent().data('argument');
                else
                    argument = $(event.target).data('argument');
                if (event.type === 'mousemove')
                    return [self, event.pageX, event.pageY];
                if (!axis)
                    return null;
                return [self, axis, mode, argument]
            },
            _pointEvent: {
                mouseover: function(self, point, mode) {
                    if (self.mouseLocked)
                        return;
                    self._setHoveredPoint(point, mode);
                    if (self.tooltipEnabled)
                        self._showTooltip(self.tooltip, point);
                    $(point).trigger('testmousehoverpoint')
                },
                mouseout: function(self, point, mode) {
                    if (self.mouseLocked)
                        return;
                    self._clearHover(self);
                    $(point).trigger('testmouseoutpoint')
                },
                mousemove: function(self, pageX, pageY) {
                    self._getCurCoords(self, pageX, pageY)
                },
                touchstart: function(self, point, mode) {
                    self.showHoldTooltip = false;
                    self._mouseLock(self);
                    if (self.tooltipEnabled)
                        self.tooltipHoldTimeout = setTimeout(function() {
                            self.showHoldTooltip = true;
                            self._showTooltip(self.tooltip, point);
                            $(point).trigger('testHoldTooltip')
                        }, TOOLTIP_HOLD_TIMEOUT)
                },
                touchend: function(self, point, mode) {
                    if (!self.showHoldTooltip)
                        self._pointClick(self, point, true);
                    clearTimeout(self.tooltipHoldTimeout);
                    self._clickLock(self);
                    self._clearHover(self)
                },
                click: function(self, point) {
                    self._pointClick(self, point, false)
                },
                mousedown: function(self, point, mode) {
                    self._pointEvent.touchstart(self, point, mode)
                },
                mouseup: function(self, point, mode) {
                    self._pointEvent.touchend(self, point, mode)
                }
            },
            _pointCondition: {
                mouseover: function(self, point, mode, func) {
                    if (mode === ALL_ARGUMENTS_POINTS_MODE && self.hoveredPoint && self.hoveredPoint.argument === point.argument) {
                        self.hoverHoldTimeOut = clearTimeout(self.hoverHoldTimeOut);
                        self.hoveredObject = point;
                        func(self, point, mode);
                        $(point).trigger('testHoverHoldTimeOutCleared');
                        return
                    }
                    self._setHover(self, point, mode, func)
                },
                mouseout: function(self, point, mode, func) {
                    self._releaseHover(self, point, mode, func)
                },
                touchstart: !msPointerEnabled,
                touchend: !msPointerEnabled,
                mousedown: msPointerEnabled,
                mouseup: msPointerEnabled
            },
            _seriesEvent: {
                mouseover: function(self, series, mode) {
                    if (self.mouseLocked)
                        return;
                    self._setHoveredSeries(series, mode);
                    $(series).trigger('testmousehoverseries')
                },
                mouseout: function(self, series, mode) {
                    self._clearHover(self);
                    $(series).trigger('testmouseoutseries')
                },
                mousemove: function(self, pageX, pageY) {
                    self._getCurCoords(self, pageX, pageY)
                },
                touchstart: function(self) {
                    self._mouseLock(self)
                },
                touchend: function(self, series) {
                    self._seriesClick(self, series, true);
                    self._clickLock(self)
                },
                click: function(self, series) {
                    self._seriesClick(self, series, false)
                },
                mousedown: function(self, point, mode) {
                    self._seriesEvent.touchstart(self, point, mode)
                },
                mouseup: function(self, point, mode) {
                    self._seriesEvent.touchend(self, point, mode)
                }
            },
            _seriesCondition: {
                mouseover: function(self, series, mode, func) {
                    self._setHover(self, series, mode, func)
                },
                mouseout: function(self, series, mode, func) {
                    self._releaseHover(self, series, mode, func)
                },
                touchstart: !msPointerEnabled,
                touchend: !msPointerEnabled,
                mousedown: msPointerEnabled,
                mouseup: msPointerEnabled
            },
            _axisEvent: {
                mouseover: function(self, axis, argument) {
                    if (self.mouseLocked || isDefined(self.hoveredArgument) && self.hoveredArgument === argument)
                        return;
                    self._clearHover(self);
                    if (isDefined(self.hoveredArgument))
                        self._toAllArgumentPoints(self.hoveredArgument, 'releasePointHoverState');
                    self._toAllArgumentPoints(argument, 'setPointHoverState');
                    self.hoveredArgument = argument;
                    $(axis).trigger('testmousehoveraxis')
                },
                mouseout: function(self, axis) {
                    if (self.mouseLocked || !isDefined(self.hoveredArgument))
                        return;
                    self._toAllArgumentPoints(self.hoveredArgument, 'releasePointHoverState');
                    self.hoveredArgument = null;
                    $(axis).trigger('testmouseoutaxis')
                },
                mousemove: function(self, pageX, pageY) {
                    self._getCurCoords(self, pageX, pageY)
                },
                touchstart: function(self) {
                    self._mouseLock(self)
                },
                touchend: function(self, axis, mode, argument) {
                    self._argumentAxisClick(self, axis, argument, true);
                    self._clearHover(self);
                    self._clickLock(self)
                },
                click: function(self, axis, mode, argument) {
                    self._clearHover(self);
                    self._argumentAxisClick(self, axis, argument, false);
                    self._clickLock(self)
                },
                mousedown: function(self) {
                    self._axisEvent.touchstart(self, point, mode)
                },
                mouseup: function(self, axis, mode, argument) {
                    self._axisEvent.touchend(self, axis, mode, argument)
                }
            },
            _axisCondition: {
                mouseover: function(self, axis, mode, argument, func) {
                    if (mode === ALL_ARGUMENTS_POINTS_MODE)
                        self._setHover(self, axis, argument, func)
                },
                mouseout: function(self, axis, mode, argument, func) {
                    self._releaseHover(self, axis, argument, func)
                },
                touchstart: !msPointerEnabled,
                touchend: !msPointerEnabled,
                mousedown: msPointerEnabled,
                mouseup: msPointerEnabled
            },
            _setHover: function(self, object, mode, func) {
                if (object === self.hoveredObject) {
                    self.hoverHoldTimeOut = clearTimeout(self.hoverHoldTimeOut);
                    if (mode === object.lastHoverMode)
                        return
                }
                if (self.mouseLocked)
                    return;
                self.hoverStartTimeOut = setTimeout(function() {
                    self._compareCoords(object, self, mode, func)
                }, self.hoverStartDelay)
            },
            _releaseHover: function(self, object, mode, func) {
                if (self.mouseLocked)
                    return;
                self.hoverStartTimeOut = clearTimeout(self.hoverStartTimeOut);
                if (object === self.hoveredObject)
                    self.hoverHoldTimeOut = setTimeout(function() {
                        self.hoveredObject = null;
                        func(self, object, mode)
                    }, self.hoverHoldDelay)
            },
            _compareCoords: function(point, self, mode, func) {
                clearTimeout(self.hoverStartTimeOut);
                if (Math.abs(self.pX - self.cX) + Math.abs(self.pY - self.cY) < self.sensitivity) {
                    if (self.mouseLocked)
                        return;
                    clearTimeout(self.hoverHoldTimeOut);
                    self.hoveredObject = point;
                    func(self, point, mode)
                }
                else {
                    self.pX = self.cX;
                    self.pY = self.cY;
                    self.hoverStartTimeOut = setTimeout(function() {
                        self._compareCoords(point, self, mode, func)
                    }, self.hoverStartDelay)
                }
            },
            _seriesClick: function(self, series, touchEvent) {
                if (self.lockClick && !touchEvent)
                    return;
                self.seriesClick && self.seriesClick.call && self.seriesClick.call(series, series)
            },
            _pointClick: function(self, point, touchEvent) {
                var series = point.series;
                if (self.lockClick && !touchEvent)
                    return;
                if (self.pointClick && self.pointClick.call && self.pointClick != $.noop) {
                    self.pointClick.call(point, point);
                    return
                }
                self.seriesClick && self.seriesClick.call && self.seriesClick.call(series, series);
                return
            },
            _argumentAxisClick: function(self, axis, argument, touchEvent) {
                if (self.lockClick && !touchEvent)
                    return;
                self.argumentAxisClick && self.argumentAxisClick.call && self.argumentAxisClick.call(axis, axis, argument)
            },
            _selectSeries: function(event, mode) {
                event.data.tracker._setSelectedSeries(event.target, mode)
            },
            _deselectSeries: function(event, mode) {
                event.data.tracker._releaseSelectedSeries(event.target, mode)
            },
            _selectPoint: function(event, point) {
                event.data.tracker._setSelectedPoint(point)
            },
            _deselectPoint: function(event, point) {
                event.data.tracker._releaseSelectedPoint(point)
            },
            _showPointTooltip: function(event, point) {
                var self = event.data.tracker;
                self._showTooltip(self.tooltip, point)
            },
            _hidePointTooltip: function(event, point) {
                event.data.tracker._hideTooltip(point)
            },
            _hideTooltip: function(point) {
                var tooltip = this && this.tooltip;
                if (!tooltip || point && this.pointAtShownTooltip !== point)
                    return;
                point = point || this.pointAtShownTooltip;
                tooltip.hide();
                this.pointAtShownTooltip && isFunction(this.tooltipHidden) && this.tooltipHidden.call(point, point);
                this.pointAtShownTooltip = null
            },
            _showTooltip: function(tooltip, point) {
                var tooltipFormatObject = point.getTooltipFormatObject(tooltip);
                if (!isDefined(tooltipFormatObject.valueText))
                    return;
                this.pointAtShownTooltip && this._hideTooltip(this.pointAtShownTooltip);
                var tooltipCoords = point.getTooltipCoords();
                var tooltipText = tooltip.formatTooltip.call(tooltipFormatObject, tooltip.options);
                if (!isDefined(tooltipText) || !isDefined(tooltipCoords.x) || !isDefined(tooltipCoords.y) || !tooltip)
                    return;
                tooltip.show();
                tooltip.move(~~tooltipCoords.x, ~~tooltipCoords.y, tooltipCoords.offset, tooltipText, point.getColor(), point.getClassName());
                !this.pointAtShownTooltip && isFunction(this.tooltipShown) && this.tooltipShown.call(point, point);
                this.pointAtShownTooltip = point
            },
            _setHoveredSeries: function(series, mode) {
                var self = this;
                if (mode !== NONE_MODE && self.hoveredSeries !== series || series.lastHoverMode !== mode) {
                    self._clearHover(self);
                    self.hoveredSeries = series;
                    series.setHoverState(mode);
                    self.seriesHover && self.seriesHover.call && self.seriesHover.call(series, series)
                }
                if (mode === NONE_MODE)
                    $(series).trigger('NoneMode')
            },
            _setSelectedSeries: function(series, mode) {
                var self = this,
                    seriesContain = false;
                if (this.seriesSelectionMode === MULTIPLE_MODE)
                    $.each(self.selectedSeries, function(_, sr) {
                        if (sr == series) {
                            seriesContain = true;
                            return false
                        }
                    });
                else if (self.selectedSeries == series)
                    seriesContain = true;
                if (!seriesContain || series.lastSelectionMode !== mode) {
                    if (self.seriesSelectionMode === SINGLE_MODE) {
                        this._releaseSelectedSeries();
                        self.selectedSeries = series
                    }
                    else
                        self.selectedSeries.push(series);
                    series.setSelectedState(mode);
                    self.seriesSelected && self.seriesSelected.call && self.seriesSelected.call(series, series)
                }
            },
            _setHoveredPoint: function(point, mode) {
                var self = this;
                var debug = DX.utils.debug;
                debug.assert(point.series, 'series was not assigned to point or empty');
                if (self.hoveredPoint === point && !point.series)
                    return;
                self._clearHover(self);
                self.hoveredPoint = point;
                self._setHoverStylePointWithMode(point, 'setPointHoverState', mode || point.options.hoverMode);
                self.pointHover && self.pointHover.call && self.pointHover.call(point, point)
            },
            _toAllArgumentPoints: function(argument, func) {
                $.each(this.storedSeries, function(_, series) {
                    var neighborPoint = series.getPointByArg(argument);
                    if (neighborPoint)
                        series[func](neighborPoint)
                })
            },
            _setHoverStylePointWithMode: function(point, func, mode) {
                switch (mode) {
                    case ALL_ARGUMENTS_POINTS_MODE:
                        this._toAllArgumentPoints(point.argument, func);
                        break;
                    case ALL_SERIES_POINTS_MODE:
                        $.each(point.series.points, function(_, point) {
                            point.series[func](point)
                        });
                        break;
                    case NONE_MODE:
                        break;
                    default:
                        point.series[func](point)
                }
            },
            _setSelectedPoint: function(point) {
                var self = this,
                    pointContain = false;
                if (this.pointSelectionMode === MULTIPLE_MODE) {
                    $.each(self.selectedPoint, function(_, pt) {
                        if (pt == point) {
                            pointContain = true;
                            return false
                        }
                    });
                    !pointContain && self.selectedPoint.push(point)
                }
                else if (self.selectedPoint !== point) {
                    this._releaseSelectedPoint();
                    self.selectedPoint = point
                }
                else
                    pointContain = true;
                if (!pointContain) {
                    self._setHoverStylePointWithMode(point, 'setPointSelectedState', point.options.selectionMode);
                    self.pointSelected && self.pointSelected.call && self.pointSelected.call(point, point)
                }
            },
            _releaseHoveredSeries: function() {
                if (!this.hoveredSeries)
                    return;
                this.hoveredSeries.releaseHoverState();
                this.hoveredSeries = null
            },
            _releaseSelectedSeriesMultiMode: function(series) {
                if (!this.selectedSeries)
                    return;
                series.releaseSelectedState();
                this.selectedSeries = $.map(this.selectedSeries, function(sr) {
                    if (sr !== series)
                        return sr
                })
            },
            _releaseSelectedSeriesSingleMode: function() {
                if (!this.selectedSeries)
                    return;
                this.selectedSeries.releaseSelectedState();
                this.selectedSeries = null
            },
            _releaseHoveredPoint: function() {
                var self = this,
                    point = self.hoveredPoint;
                if (self.tooltipEnabled && !self.showHoldTooltip)
                    self._hideTooltip(point);
                if (!point)
                    return;
                if (point.options.hoverMode === ALL_SERIES_POINTS_MODE)
                    $.each(point.series.points, function(_, point) {
                        point.series.releasePointHoverState(point)
                    });
                else if (point.options.hoverMode === ALL_ARGUMENTS_POINTS_MODE)
                    self._toAllArgumentPoints(point.argument, 'releasePointHoverState');
                else
                    point.releaseHoverState();
                self.hoveredPoint = null
            },
            _releaseSelectedPointMultiMode: function(point) {
                var self = this,
                    points = self.selectedPoint;
                if (!points)
                    return;
                self._setHoverStylePointWithMode(point, 'releasePointSelectedState', point.options.selectionMode);
                this.selectedPoint = $.map(this.selectedPoint, function(pt) {
                    if (pt !== point)
                        return pt
                })
            },
            _releaseSelectedPointSingleMode: function() {
                var self = this,
                    point = self.selectedPoint;
                if (!point)
                    return;
                self._setHoverStylePointWithMode(point, 'releasePointSelectedState', point.options.selectionMode);
                this.selectedPoint = null
            },
            clearSelection: function() {
                var self = this;
                if (this.pointSelectionMode === SINGLE_MODE)
                    this._releaseSelectedPoint();
                else
                    $.each(this.selectedPoint, function(_, point) {
                        self._releaseSelectedPoint(point)
                    });
                if (this.seriesSelectionMode === SINGLE_MODE)
                    this._releaseSelectedSeries();
                else
                    $.each(this.selectedSeries, function(_, series) {
                        self._releaseSelectedSeries(series)
                    })
            },
            _mouseLock: function(tracker) {
                if (tracker.unlockMouseTimer)
                    clearTimeout(tracker.unlockMouseTimer);
                tracker.mouseLocked = true;
                tracker.unlockMouseTimer = setTimeout(function() {
                    tracker.mouseLocked = false
                }, MOUSE_EVENT_LOCK_TIMEOUT)
            },
            _clickLock: function(tracker) {
                tracker.lockClick = true;
                if (tracker.lockClickTimer)
                    clearTimeout(tracker.lockClickTimer);
                tracker.lockClickTimer = setTimeout(function() {
                    tracker.lockClick = false
                }, CLICK_EVENT_LOCK_TIMEOUT)
            },
            _getCurCoords: function(self, pageX, pageY) {
                self.cX = pageX;
                self.cY = pageY
            },
            _clearHover: function(self) {
                self._releaseHoveredSeries();
                self._releaseHoveredPoint()
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file namespaces.js */
    (function(DX) {
        DX.viz.gauges = {__internals: {
                circularNeedles: {},
                circularMarkers: {},
                linearNeedles: {},
                linearMarkers: {}
            }};
        DX.viz.gauges.__tests = {}
    })(DevExpress);
    /*! Module viz, file factory.js */
    (function(DX, undefined) {
        var gauges = DX.viz.gauges,
            renderers = DX.viz.renderers,
            internals = gauges.__internals,
            circularNeedles = internals.circularNeedles,
            circularMarkers = internals.circularMarkers,
            linearNeedles = internals.linearNeedles,
            linearMarkers = internals.linearMarkers;
        var isString = DX.utils.isString;
        gauges.__factory = {
            createTranslator: function(fromAngle, toAngle, fromValue, toValue) {
                return new DX.viz.core.Translator1D(fromValue, toValue, fromAngle, toAngle)
            },
            createRenderer: function(options) {
                return new renderers.Renderer(options)
            },
            createCircularNeedle: function(type) {
                if (isString(type))
                    switch (type.toLowerCase()) {
                        case'rectangle':
                            return new circularNeedles.RectangleNeedle;
                        case'twocolorrectangle':
                            return new circularNeedles.TwoColorRectangleNeedle;
                        case'triangle':
                            return new circularNeedles.TriangleNeedle
                    }
                return undefined
            },
            createLinearNeedle: function(type) {
                if (isString(type))
                    switch (type.toLowerCase()) {
                        case'rectangle':
                            return new linearNeedles.RectangleNeedle;
                        case'rhombus':
                            return new linearNeedles.RhombusNeedle;
                        case'circle':
                            return new linearNeedles.CircleNeedle
                    }
                return undefined
            },
            createCircularMarker: function(type) {
                if (isString(type))
                    switch (type.toLowerCase()) {
                        case'triangle':
                            return new circularMarkers.TriangleMarker;
                        case'textcloud':
                            return new circularMarkers.TextCloudMarker
                    }
                return undefined
            },
            createLinearMarker: function(type) {
                if (isString(type))
                    switch (type.toLowerCase()) {
                        case'triangle':
                            return new linearMarkers.TriangleMarker;
                        case'textcloud':
                            return new linearMarkers.TextCloudMarker
                    }
                return undefined
            },
            createCircularRangeBar: function() {
                return new internals.CircularRangeBar
            },
            createLinearRangeBar: function() {
                return new internals.LinearRangeBar
            },
            createCircularScale: function() {
                return new internals.CircularScale
            },
            createLinearScale: function() {
                return new internals.LinearScale
            },
            createCircularRangeContainer: function() {
                return new internals.CircularRangeContainer
            },
            createLinearRangeContainer: function() {
                return new internals.LinearRangeContainer
            },
            createCircularSpindle: function() {
                return new internals.CircularSpindle
            },
            createTitle: function() {
                return new internals.Title
            },
            createIndicator: function() {
                return internals.Indicator && new internals.Indicator || null
            },
            createTooltip: function() {
                return new internals.Tooltip
            },
            createLayoutManager: function() {
                return new internals.LayoutManager
            },
            createThemeManager: function(theme) {
                return new internals.ThemeManager(theme)
            },
            createPresetManager: function() {
                return new internals.PresetManager
            },
            createTracker: function() {
                return new internals.Tracker
            }
        }
    })(DevExpress);
    /*! Module viz, file baseGaugeItem.js */
    (function(DX, $, undefined) {
        var $extend = $.extend;
        DX.viz.gauges.__internals.BaseGaugeItem = DX.Class.inherit({
            ctor: function() {
                this._options = {}
            },
            _getDefaultOptions: function() {
                return {}
            },
            create: function(options) {
                var self = this;
                self._renderer = options.renderer;
                self._rootElement = self._renderer.createGroup().append(options.ownerElement);
                $extend(true, self._options, self._getDefaultOptions(), options);
                self._create(options);
                return self
            },
            update: function(options) {
                var self = this;
                $extend(true, self._options, options);
                self._update(options);
                return self
            },
            showTooltip: function(element, coord, text) {
                if (element && element.$element)
                    element.$element.trigger('showToolTip', [coord, text])
            },
            hideTooltip: function(element) {
                if (element && element.$element)
                    element.$element.trigger('hideToolTip')
            },
            destroy: function() {
                this._rootElement.remove();
                return this
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz, file scale.js */
    (function(DX, $, undefined) {
        var formatHelper = DX.formatHelper;
        var getCosAndSin = DX.utils.getCosAndSin,
            normalizeAngle = DX.utils.normalizeAngle,
            convertAngleToRendererSpace = DX.utils.convertAngleToRendererSpace,
            isDefined = DX.utils.isDefined,
            isString = DX.utils.isString,
            isFunction = DX.utils.isFunction,
            isArray = DX.utils.isArray,
            isNaN = window.isNaN,
            Number = window.Number,
            String = window.String,
            max = Math.max,
            min = Math.min,
            abs = Math.abs,
            atan = Math.atan,
            acos = Math.acos,
            ceil = Math.ceil,
            $extend = $.extend,
            $map = $.map;
        var PI = Math.PI;
        var tickProvider = DX.viz.core.tickProvider;
        function binarySearch(x, list) {
            var a = 0,
                b = list.length - 1,
                flag = list[a] - list[b] < 0,
                c,
                k = -1;
            if (list[a] === x)
                k = a;
            if (list[b] === x)
                k = b;
            while (k < 0 && a <= b) {
                c = ~~((a + b) / 2);
                if (list[c] === x)
                    k = c;
                else if (list[c] - x < 0 === flag)
                    a = c + 1;
                else
                    b = c - 1
            }
            return k
        }
        DX.viz.gauges.__internals.BaseScale = DX.Class.inherit({
            setup: function(parameters) {
                var self = this;
                DX.utils.debug.assertParam(parameters.renderer, '"renderer" was not passed');
                DX.utils.debug.assertParam(parameters.owner, '"owner" was not passed');
                DX.utils.debug.assertParam(parameters.incidentOccured, '"incidentOccured" was not passed');
                self._renderer = parameters.renderer;
                self._owner = parameters.owner;
                self._incidentOccured = parameters.incidentOccured;
                return self
            },
            init: function(options) {
                var self = this;
                self._options = $extend(true, self._options || {}, options);
                self._options.majorTick || (self._options.majorTick = {});
                self._options.minorTick || (self._options.minorTick = {});
                if (options && options.majorTick && isDefined(options.majorTick.customTickValues))
                    self._options.majorTick.customTickValues = isArray(options.majorTick.customTickValues) ? options.majorTick.customTickValues.slice(0) : null;
                if (options && options.minorTick && isDefined(options.minorTick.customTickValues))
                    self._options.minorTick.customTickValues = isArray(options.minorTick.customTickValues) ? options.minorTick.customTickValues.slice(0) : null;
                delete self._processed;
                return self
            },
            _getCustomValues: function(values, compare) {
                var translator = this._options.translator,
                    result = [];
                if (isArray(values)) {
                    result = $map(values, function(x) {
                        return !isNaN(translator.translate(x)) ? Number(x) : null
                    }).sort(compare);
                    result = $map(result, function(x, i) {
                        return x !== result[i - 1] ? x : null
                    })
                }
                return result
            },
            _getTicks: function() {
                var self = this,
                    options = self._options,
                    translator = options.translator,
                    startValue = translator.getDomainStart(),
                    endValue = translator.getDomainEnd(),
                    compare = startValue < endValue ? function(x, y) {
                        return x - y
                    } : function(x, y) {
                        return y - x
                    },
                    gridSpacingFactor = self._getGridSpacingFactor(),
                    info,
                    majorValues,
                    minorValues,
                    customMajorValues,
                    customMinorValues,
                    list,
                    ticks = {};
                info = tickProvider.getFullTicks(startValue, endValue, self._getScreenDelta(), {
                    tickInterval: options.majorTick.tickInterval > 0 ? Number(options.majorTick.tickInterval) : undefined,
                    gridSpacingFactor: gridSpacingFactor.majorTicks,
                    numberMultipliers: [1, 2, 5]
                }, {
                    tickInterval: options.minorTick.tickInterval > 0 ? Number(options.minorTick.tickInterval) : undefined,
                    gridSpacingFactor: gridSpacingFactor.minorTicks,
                    numberMultipliers: [1, 2, 5]
                });
                if (options.majorTick.showCalculatedTicks) {
                    majorValues = info.majorTicks;
                    if (options.majorTick.useTicksAutoArrangement)
                        majorValues = self._cutTicks(majorValues)
                }
                else
                    majorValues = [];
                customMajorValues = self._getCustomValues(options.majorTick.customTickValues, compare);
                customMajorValues = $map(customMajorValues, function(value) {
                    return binarySearch(value, majorValues) === -1 ? value : null
                });
                if (options.minorTick.showCalculatedTicks)
                    minorValues = info.minorTicks;
                else
                    minorValues = [];
                minorValues = $map(minorValues, function(value) {
                    return binarySearch(value, customMajorValues) === -1 ? value : null
                });
                customMinorValues = self._getCustomValues(options.minorTick.customTickValues, compare);
                list = majorValues.concat(minorValues, customMajorValues).sort(compare);
                customMinorValues = $map(customMinorValues, function(value) {
                    return binarySearch(value, list) === -1 ? value : null
                });
                ticks.major = $map(majorValues.concat(customMajorValues), function(value) {
                    return {
                            value: value,
                            position: translator.translate(value)
                        }
                });
                ticks.minor = $map(minorValues.concat(customMinorValues), function(value) {
                    return {
                            value: value,
                            position: translator.translate(value)
                        }
                });
                return ticks
            },
            _cutTicks: function(values) {
                var self = this,
                    factor = self._getCuttingFactor(values.length, {
                        width: self._textWidth,
                        height: self._textHeight
                    }),
                    cutValues = [],
                    i = 0,
                    ii = values.length;
                for (; i < ii; i += factor)
                    cutValues.push(values[i]);
                return cutValues
            },
            _renderContent: function(ticks) {
                var self = this,
                    options = self._options,
                    i,
                    ii,
                    item,
                    points,
                    element,
                    majorTickColor,
                    minorTickColor,
                    textPosition,
                    textValue;
                if (self._majorTickLength && self._majorTickWidth) {
                    majorTickColor = isString(options.majorTick.color) ? options.majorTick.color : 'none';
                    points = self._getTickPoints(self._majorTickLength, self._majorTickWidth);
                    i = 0;
                    ii = ticks.major.length;
                    options.hideFirstTick === true && ++i;
                    options.hideLastTick === true && --ii;
                    for (; i < ii; ++i) {
                        item = ticks.major[i];
                        element = self._renderer.createArea(points, {
                            'class': 'dx-major-tick',
                            fill: majorTickColor,
                            stroke: 'none',
                            strokeWidth: 0
                        });
                        self._moveTick(element, item);
                        element.append(self._majorTicks)
                    }
                }
                if (self._minorTickLength && self._minorTickWidth) {
                    minorTickColor = isString(options.minorTick.color) ? options.minorTick.color : 'none';
                    points = self._getTickPoints(self._minorTickLength, self._minorTickWidth);
                    for (i = 0, ii = ticks.minor.length; i < ii; ++i) {
                        item = ticks.minor[i];
                        element = self._renderer.createArea(points, {
                            'class': 'dx-minor-tick',
                            fill: minorTickColor,
                            stroke: 'none',
                            strokeWidth: 0
                        });
                        self._moveTick(element, item);
                        element.append(self._minorTicks)
                    }
                }
                if (self._textIndent) {
                    textPosition = self._getLabelPosition(self._majorTickLength || 0, self._textIndent);
                    i = 0;
                    ii = ticks.major.length;
                    options.hideFirstLabel === true && ++i;
                    options.hideLastLabel === true && --ii;
                    for (; i < ii; ++i) {
                        item = ticks.major[i];
                        textValue = self._formatValue(item.value);
                        points = self._getLabelOptions(textValue, textPosition, self._textIndent, item);
                        self._renderer.createText(textValue, points.x, points.y + self._textVerticalOffset, {
                            'class': 'dx-gauge-scale-label',
                            align: points.align,
                            font: options.label.font
                        }).append(self._labels)
                    }
                }
            },
            _processOptions: function() {
                var self = this,
                    options = self._options;
                if (self._processed)
                    return;
                self._processed = true;
                self._setupOrientation();
                if (options.majorTick.visible) {
                    if (options.majorTick.length > 0)
                        self._majorTickLength = Number(options.majorTick.length);
                    else
                        self._incidentOccured('Major ticks are not rendered because the value of "majorTick.length" option is not valid');
                    if (options.majorTick.width > 0)
                        self._majorTickWidth = Number(options.majorTick.width);
                    else
                        self._incidentOccured('Major ticks are not rendered because the value of "majorTick.width" option is not valid')
                }
                if (options.minorTick.visible) {
                    if (options.minorTick.length > 0)
                        self._minorTickLength = Number(options.minorTick.length);
                    else
                        self._incidentOccured('Minor ticks are not rendered because the value of "minorTick.length" option is not valid');
                    if (options.minorTick.width > 0)
                        self._minorTickWidth = Number(options.minorTick.width);
                    else
                        self._incidentOccured('Minor ticks are not rendered because the value of "minorTick.width" option is not valid')
                }
                if (options.label.visible)
                    if (Number(options.label.indentFromTick) !== 0) {
                        self._textIndent = Number(options.label.indentFromTick);
                        self._measureText()
                    }
                    else
                        self._incidentOccured('Labels are not rendered because the value of the "label.indentFromTick" option is not valid')
            },
            render: function() {
                var self = this,
                    ticks;
                if (!self._rootElement) {
                    self._rootElement = self._renderer.createGroup({'class': 'scale'});
                    self._majorTicks = self._renderer.createGroup({'class': 'dx-major-ticks'}).append(self._rootElement);
                    self._minorTicks = self._renderer.createGroup({'class': 'dx-minor-ticks'}).append(self._rootElement);
                    self._labels = self._renderer.createGroup({'class': 'labels'}).append(self._rootElement)
                }
                self._rootElement.append(self._owner);
                self._majorTicks.clear();
                self._minorTicks.clear();
                self._labels.clear();
                self._processOptions();
                if (self._isVisible()) {
                    ticks = self._getTicks();
                    self._renderContent(ticks)
                }
                else if (self._rootElement) {
                    self._rootElement.remove();
                    delete self._rootElement;
                    delete self._majorTicks;
                    delete self._minorTicks;
                    delete self._labels
                }
                return self
            },
            _formatValue: function(value) {
                var labelOptions = this._options.label,
                    result = formatHelper.format(value, labelOptions.format, labelOptions.precision);
                if (isFunction(labelOptions.customizeText)) {
                    result = {
                        value: value,
                        valueText: result
                    };
                    result = String(labelOptions.customizeText.call(result, result))
                }
                return result
            },
            _getSampleText: function() {
                var self = this,
                    start = self._options.translator.getDomainStart(),
                    end = self._options.translator.getDomainEnd(),
                    texts = [],
                    i,
                    ii,
                    text,
                    maxLength = 0,
                    maxText;
                var ticks = tickProvider.getTicks({
                        min: start,
                        max: end,
                        tickInterval: self._options.majorTick.tickInterval,
                        screenDelta: self._options.approximateScreenDelta,
                        gridSpacingFactor: self._getGridSpacingFactor().majorTicks
                    });
                for (i = 0, ii = ticks.length; i < ii; ++i) {
                    text = self._formatValue(ticks[i]);
                    text.length > maxLength && (maxText = text) && (maxLength = text.length)
                }
                return maxText
            },
            _measureText: function() {
                var self = this,
                    root = self._renderer.createGroup({'class': 'scale'}).append(self._rootElement),
                    labels = self._renderer.createGroup({'class': 'labels'}).append(root),
                    value = self._getSampleText(),
                    text = self._renderer.createText(value, 0, 0, {
                        'class': 'dx-gauge-scale-label',
                        align: 'center',
                        font: self._options.label.font
                    }).append(labels),
                    bbox = text.getBBox();
                root.remove();
                self._textVerticalOffset = -bbox.y - bbox.height / 2;
                self._textWidth = bbox.width;
                self._textHeight = bbox.height;
                self._textLength = value.length
            }
        });
        function getBasedAngle(startAngle, endAngle) {
            var startDelta,
                endDelta,
                tmp;
            if (startAngle > endAngle) {
                tmp = endAngle;
                endAngle = startAngle;
                startAngle = tmp
            }
            startDelta = 0 <= startAngle && startAngle <= 180 ? abs(90 - startAngle) : abs(270 - startAngle);
            startDelta = startAngle < 90 && 90 < endAngle || startAngle < 270 && 270 < endAngle ? 0 : startDelta;
            endDelta = 0 < endAngle && endAngle < 180 ? abs(90 - endAngle) : abs(270 - endAngle);
            return startDelta < endDelta ? startDelta : endDelta
        }
        DX.viz.gauges.__internals.CircularScale = DX.viz.gauges.__internals.BaseScale.inherit({
            _getGridSpacingFactor: function() {
                return {
                        majorTicks: 17,
                        minorTicks: 5
                    }
            },
            _getScreenDelta: function() {
                var options = this._options;
                return (options.translator.getCodomainStart() - options.translator.getCodomainEnd()) * options.radius * PI / 180
            },
            _getCuttingFactor: function(ticksCount, maxLabelSize) {
                var self = this,
                    options = self._options,
                    startAngle = options.translator.getCodomainStart(),
                    endAngle = options.translator.getCodomainEnd(),
                    radius = self._getLabelPosition(self._majorTickLength || 0, self._textIndent),
                    baseAngle = getBasedAngle(normalizeAngle(startAngle), normalizeAngle(endAngle)),
                    baseAngleCosSin = getCosAndSin(baseAngle),
                    degreesPerTick = (startAngle - endAngle) / ticksCount,
                    minAngleBetweenTicks,
                    widthBasedAngle,
                    tanOfWidthBasedAngle,
                    heightBasedAngle,
                    cosOfHeightBasedAngle,
                    cuttingBackFactor = 1;
                tanOfWidthBasedAngle = (baseAngleCosSin.sin * radius + maxLabelSize.width) / (baseAngleCosSin.cos * radius);
                widthBasedAngle = abs(baseAngle - atan(tanOfWidthBasedAngle) * 180 / PI);
                cosOfHeightBasedAngle = baseAngleCosSin.cos - maxLabelSize.height / radius;
                heightBasedAngle = -1 > cosOfHeightBasedAngle || cosOfHeightBasedAngle > 1 ? 90 : abs(baseAngle - acos(cosOfHeightBasedAngle) * 180 / PI);
                minAngleBetweenTicks = widthBasedAngle < heightBasedAngle ? widthBasedAngle : heightBasedAngle;
                if (degreesPerTick < minAngleBetweenTicks)
                    cuttingBackFactor = ceil(minAngleBetweenTicks / degreesPerTick);
                return max(1, cuttingBackFactor)
            },
            _setupOrientation: function() {
                var self = this,
                    inner = 0,
                    outer = 0;
                switch (self._options.orientation) {
                    case'inside':
                        inner = 1;
                        break;
                    case'center':
                        inner = outer = 0.5;
                        break;
                    default:
                        self._options.orientation !== 'outside' && self._incidentOccured('The value of the "orientation" option is not valid');
                        outer = 1;
                        break
                }
                self._inner = inner;
                self._outer = outer
            },
            _getTickPoints: function(length, width) {
                var options = this._options,
                    x1 = options.x - width / 2,
                    x2 = options.x + width / 2,
                    y1 = options.y - options.radius - length * this._outer,
                    y2 = options.y - options.radius + length * this._inner;
                return [x1, y1, x2, y1, x2, y2, x1, y2]
            },
            _moveTick: function(element, tick) {
                element.rotate(convertAngleToRendererSpace(tick.position), this._options.x, this._options.y)
            },
            _getLabelPosition: function(tickLength, textIndent) {
                return this._options.radius + tickLength * (textIndent >= 0 ? this._outer : -this._inner) + textIndent
            },
            _getLabelOptions: function(textValue, textPosition, textIndent, tick) {
                var self = this,
                    options = self._options,
                    cossin = getCosAndSin(tick.position),
                    x = options.x + cossin.cos * textPosition,
                    y = options.y - cossin.sin * textPosition,
                    dx = cossin.cos * (textValue.length / self._textLength) * self._textWidth / 2,
                    dy = cossin.sin * self._textHeight / 2;
                if (textIndent > 0) {
                    x += dx;
                    y -= dy
                }
                else {
                    x -= dx;
                    y += dy
                }
                return {
                        x: x,
                        y: y,
                        align: 'center'
                    }
            },
            _isVisible: function() {
                var self = this,
                    length = self._majorTickLength || 0,
                    r = self._options.radius,
                    inner = r - self._inner * length,
                    outer = r + self._outer * length;
                return inner > 0 && outer > inner
            },
            measure: function() {
                var self = this,
                    options = self._options,
                    result = {
                        min: options.radius,
                        max: options.radius
                    };
                self._processOptions();
                if (self._majorTickLength) {
                    result.min -= self._inner * self._majorTickLength;
                    result.max += self._outer * self._majorTickLength
                }
                if (self._textIndent) {
                    if (self._textIndent >= 0) {
                        result.horizontalOffset = self._textIndent + self._textWidth;
                        result.verticalOffset = self._textIndent + self._textHeight
                    }
                    else {
                        result.horizontalOffset = 0;
                        result.verticalOffset = 0;
                        result.min += self._textIndent - max(self._textWidth, self._textHeight)
                    }
                    result.inverseHorizontalOffset = self._textWidth / 2;
                    result.inverseVerticalOffset = self._textHeight / 2
                }
                return result
            }
        });
        DX.viz.gauges.__internals.LinearScale = DX.viz.gauges.__internals.BaseScale.inherit({
            _getGridSpacingFactor: function() {
                return {
                        majorTicks: 25,
                        minorTicks: 5
                    }
            },
            _getScreenDelta: function() {
                return abs(this._options.translator.getCodomainEnd() - this._options.translator.getCodomainStart())
            },
            _getCuttingFactor: function(ticksCount, maxLabelSize) {
                var options = this._options,
                    labelSize = this._vertical ? maxLabelSize.height : maxLabelSize.width,
                    screenSize = abs(options.translator.getCodomainEnd() - options.translator.getCodomainStart());
                return max(1, ceil(ticksCount * labelSize / (screenSize + labelSize)))
            },
            _setupOrientation: function() {
                var self = this,
                    inner = 0,
                    outer = 0;
                self._vertical = self._options.orientation === 'vertical';
                if (self._vertical)
                    switch (self._options.horizontalOrientation) {
                        case'left':
                            inner = 1;
                            break;
                        case'center':
                            inner = outer = 0.5;
                            break;
                        default:
                            self._options.horizontalOrientation !== 'right' && self._incidentOccured('The value of the "horizontalOrientation" option is not valid');
                            outer = 1;
                            break
                    }
                else
                    switch (self._options.verticalOrientation) {
                        case'top':
                            inner = 1;
                            break;
                        case'middle':
                            inner = outer = 0.5;
                            break;
                        default:
                            self._options.verticalOrientation !== 'bottom' && self._incidentOccured('The value of the "verticalOrientation" option is not valid');
                            outer = 1;
                            break
                    }
                self._inner = inner;
                self._outer = outer
            },
            _getTickPoints: function(length, width) {
                var options = this._options,
                    x1,
                    x2,
                    y1,
                    y2;
                if (this._vertical) {
                    x1 = options.x - length * this._inner;
                    x2 = options.x + length * this._outer;
                    y1 = -width / 2;
                    y2 = width / 2
                }
                else {
                    x1 = -width / 2;
                    x2 = width / 2;
                    y1 = options.y - length * this._inner;
                    y2 = options.y + length * this._outer
                }
                return [x1, y1, x2, y1, x2, y2, x1, y2]
            },
            _moveTick: function(element, tick) {
                var options = this._options,
                    x = 0,
                    y = 0;
                if (this._vertical)
                    y = tick.position;
                else
                    x = tick.position;
                element.move(x, y)
            },
            _getLabelPosition: function(tickLength, textIndent) {
                var options = this._options,
                    position = tickLength * (textIndent >= 0 ? this._outer : -this._inner) + textIndent;
                if (this._vertical)
                    position += options.x;
                else
                    position += options.y + (textIndent >= 0 ? 1 : -1) * this._textVerticalOffset;
                return position
            },
            _getLabelOptions: function(textValue, textPosition, textIndent, tick) {
                var x,
                    y,
                    align;
                if (this._vertical) {
                    x = textPosition;
                    y = tick.position;
                    align = textIndent > 0 ? 'left' : 'right'
                }
                else {
                    x = tick.position;
                    y = textPosition;
                    align = 'center'
                }
                return {
                        x: x,
                        y: y,
                        align: align
                    }
            },
            _isVisible: function() {
                return true
            },
            measure: function() {
                var self = this,
                    options = self._options,
                    result;
                self._processOptions();
                if (self._vertical) {
                    result = {
                        min: options.x,
                        max: options.x
                    };
                    if (self._majorTickLength) {
                        result.min -= self._inner * self._majorTickLength;
                        result.max += self._outer * self._majorTickLength
                    }
                    if (self._textIndent) {
                        if (self._textIndent >= 0)
                            result.max += self._textIndent + self._textWidth;
                        else
                            result.min += self._textIndent - self._textWidth;
                        result.indent = self._textHeight / 2
                    }
                }
                else {
                    result = {
                        min: options.y,
                        max: options.y
                    };
                    if (self._majorTickLength) {
                        result.min -= self._inner * self._majorTickLength;
                        result.max += self._outer * self._majorTickLength
                    }
                    if (self._textIndent) {
                        if (self._textIndent >= 0)
                            result.max += self._textIndent + self._textHeight;
                        else
                            result.min += self._textIndent - self._textHeight;
                        result.indent = self._textWidth / 2
                    }
                }
                return result
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz, file baseIndicator.js */
    (function(DX, $, undefined) {
        var formatHelper = DX.formatHelper;
        var isFunction = DX.utils.isFunction,
            isFinite = window.isFinite,
            Number = window.Number,
            String = window.String,
            $extend = $.extend;
        DX.viz.gauges.__internals.BaseIndicator = DX.viz.gauges.__internals.BaseGaugeItem.inherit({
            setup: function(parameters) {
                var self = this;
                self._renderer = parameters.renderer;
                self._owner = parameters.owner;
                self._trackerOwner = parameters.tracker;
                self._options = {};
                return self
            },
            init: function(options) {
                $extend(true, this._options, options || {});
                return this
            },
            render: function() {
                var self = this;
                self._actualValue = self._currentValue = self._options.translator.adjust(self._options.currentValue);
                self._isCurrentValueLocked = false;
                delete self._setCurrentValueNext;
                delete self._setCurrentValueHas;
                self._animateStep = self._animateStep || function(_, fx) {
                    var target = self;
                    target._updateActualValue(target._animateStart + target._animateDelta * fx.pos)
                };
                self._animateComplete = self._animateComplete || function() {
                    var target = self;
                    if (target._setCurrentValueHas) {
                        target._runAnimation(target._actualValue, target._setCurrentValueNext);
                        target._setCurrentValueHas = false
                    }
                    else {
                        target._isCurrentValueLocked = false;
                        delete target._animateStart;
                        delete target._animateDelta
                    }
                    target._setCurrentValueNext = undefined
                };
                return self
            },
            _formatValue: function(value) {
                var options = this._options.text,
                    valueText = formatHelper.format(value, options.format, options.precision),
                    obj = {
                        value: value,
                        valueText: valueText
                    };
                return isFunction(options.customizeText) ? String(options.customizeText.call(obj, obj)) : valueText
            },
            _getActualPosition: function() {
                return this._options.translator.translate(this._actualValue)
            },
            _getSampleText: function() {
                var self = this,
                    options = self._options,
                    text1,
                    text2,
                    text;
                if (options.text) {
                    text1 = self._formatValue(options.translator.getDomainStart());
                    text2 = self._formatValue(options.translator.getDomainEnd());
                    text = text1.length >= text2.length ? text1 : text2
                }
                return text
            },
            _updateActualValue: function(value) {
                this._actualValue = value;
                this._updateActiveElements()
            },
            _runAnimation: function(fromValue, toValue) {
                var self = this;
                self._isCurrentValueLocked = true;
                self._animateStart = fromValue;
                self._animateDelta = toValue - fromValue;
                self._rootElement.animate({fake: true}, {
                    duration: self._options.animationDuration,
                    step: self._animateStep,
                    complete: self._animateComplete
                })
            },
            getCurrentValue: function() {
                return this._currentValue
            },
            setCurrentValue: function(value) {
                var self = this,
                    newValue = self._options.translator.adjust(value);
                if (self._currentValue !== newValue && isFinite(newValue)) {
                    self._currentValue = newValue;
                    if (self._rootElement)
                        if (self._options.animationEnabled)
                            if (!self._isCurrentValueLocked)
                                self._runAnimation(self._actualValue, newValue);
                            else {
                                self._setCurrentValueNext = newValue;
                                self._setCurrentValueHas = true
                            }
                        else
                            self._updateActualValue(newValue)
                }
                return self._currentValue
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz, file baseMarker.js */
    (function(DX, $, undefined) {
        var $extend = $.extend;
        var TextCloud = DX.viz.core.TextCloud;
        DX.viz.gauges.__internals.BaseTextCloudMarker = DX.viz.gauges.__internals.BaseIndicator.inherit({
            _updateActiveElements: function() {
                var self = this,
                    bbox,
                    info = new TextCloud,
                    textCloudOptions = self._getTextCloudOptions();
                self._text.applySettings({text: self._formatValue(self._actualValue)});
                bbox = self._text.getBBox();
                info.setup({
                    x: textCloudOptions.x,
                    y: textCloudOptions.y,
                    textWidth: bbox.width,
                    textHeight: bbox.height,
                    horMargin: self._options.horizontalOffset,
                    verMargin: self._options.verticalOffset,
                    tailLength: self._options.arrowLength,
                    type: textCloudOptions.type
                });
                self._text.applySettings({
                    x: info.cx(),
                    y: info.cy() + self._textVerticalOffset
                });
                self._cloud.applySettings({points: info.points()});
                self._tracker.applySettings({points: info.points()})
            },
            _measureText: function() {
                var self = this,
                    bbox;
                self._rootElement = self._rootElement || self._renderer.createGroup({'class': 'marker'});
                self._rootElement.append(self._owner);
                self._cloud = self._cloud || self._renderer.createArea().append(self._rootElement);
                self._text = self._text || self._renderer.createText().append(self._rootElement);
                self._text.applySettings({
                    x: 0,
                    y: 0,
                    align: 'center',
                    font: self._options.text.font,
                    text: self._getSampleText()
                });
                bbox = self._text.getBBox();
                self._textVerticalOffset = -bbox.y - bbox.height / 2;
                self._textWidth = bbox.width;
                self._textHeight = bbox.height;
                self._textFullWidth = self._textWidth + 2 * self._options.horizontalOffset;
                self._textFullHeight = self._textHeight + 2 * self._options.verticalOffset
            },
            render: function() {
                var self = this;
                self.callBase();
                if (self._isVisible()) {
                    self._measureText();
                    self._tracker = self._tracker || self._renderer.createArea([], {
                        stroke: 'none',
                        strokeWidth: 0,
                        fill: '#000000',
                        opacity: 0.0001
                    }).append(self._trackerOwner);
                    self._cloud.applySettings({
                        stroke: 'none',
                        strokeWidth: 0,
                        fill: self._options.color
                    });
                    self._updateActiveElements()
                }
                else
                    self.clear();
                return self
            },
            clear: function() {
                var self = this;
                if (self._rootElement) {
                    self._rootElement.remove();
                    delete self._rootElement;
                    delete self._cloud;
                    delete self._text;
                    delete self._tracker
                }
            },
            getTrackingElement: function() {
                return this._tracker
            },
            getTooltipParameters: function() {
                var position = this._getTextCloudOptions();
                return {
                        x: position.x,
                        y: position.y,
                        value: this._currentValue,
                        color: this._options.color
                    }
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz, file baseRangeBar.js */
    (function(DX, $, undefined) {
        var $extend = $.extend;
        DX.viz.gauges.__internals.BaseRangeBar = DX.viz.gauges.__internals.BaseIndicator.inherit({
            _prepare: function() {
                var self = this,
                    bbox;
                self._hasText = self._isTextVisible();
                if (self._hasText) {
                    self._rootElement = self._rootElement || self._renderer.createGroup({'class': 'rangebar'}).append(self._owner);
                    self._text = self._text || self._renderer.createText().append(self._rootElement);
                    self._text.applySettings({
                        x: 0,
                        y: 0,
                        align: self._getTextAlign(),
                        font: self._getFontOptions(),
                        text: self._getSampleText()
                    });
                    bbox = self._text.getBBox();
                    self._textVerticalOffset = -bbox.y - bbox.height / 2;
                    self._textWidth = bbox.width;
                    self._textHeight = bbox.height
                }
            },
            _updateActiveElements: function() {
                var self = this;
                self._updateBarItemsPositions();
                if (self._hasText) {
                    self._text.applySettings({text: self._formatValue(self._actualValue)});
                    self._updateTextPosition();
                    self._updateLinePosition()
                }
            },
            _updateBarItems: function() {
                var self = this,
                    options = self._options,
                    backgroundColor,
                    spaceColor;
                self._setBarSides();
                self._startPosition = options.translator.translate(options.translator.getDomainStart());
                self._endPosition = options.translator.translate(options.translator.getDomainEnd());
                self._basePosition = options.translator.translate(options.baseValue);
                self._space = self._getSpace();
                backgroundColor = options.backgroundColor || 'none';
                if (backgroundColor !== 'none' && self._space > 0)
                    spaceColor = options.containerBackgroundColor || 'none';
                else {
                    self._space = 0;
                    spaceColor = 'none'
                }
                self._backItem1.applySettings({
                    fill: backgroundColor,
                    stroke: 'none',
                    strokeWidth: 0
                });
                self._backItem2.applySettings({
                    fill: backgroundColor,
                    stroke: 'none',
                    strokeWidth: 0
                });
                self._spaceItem1.applySettings({
                    fill: spaceColor,
                    stroke: 'none',
                    strokeWidth: 0
                });
                self._spaceItem2.applySettings({
                    fill: spaceColor,
                    stroke: 'none',
                    strokeWidth: 0
                });
                self._mainItem.applySettings({
                    fill: options.color,
                    stroke: 'none',
                    strokeWidth: 0
                })
            },
            _getSpace: function() {
                return 0
            },
            _updateTextItems: function() {
                var self = this,
                    options = self._options;
                if (self._isTextVisible()) {
                    self._hasText = true;
                    self._createTextItems();
                    self._updateText();
                    self._updateLine();
                    self._setTextItemsSides()
                }
                else {
                    delete self._hasText;
                    self._destroyTextItems()
                }
            },
            _isTextVisible: function() {
                return false
            },
            _createTextItems: function() {
                var self = this;
                self._line || (self._line = self._renderer.createPath().append(self._rootElement));
                self._text || (self._text = self._renderer.createText().append(self._rootElement))
            },
            _destroyTextItems: function() {
                var self = this;
                self._line && self._line.remove() && delete self._line;
                self._text && self._text.remove() && delete self._text
            },
            _updateText: function() {
                var self = this,
                    bbox;
                self._text.applySettings({
                    x: 0,
                    y: 0,
                    align: self._getTextAlign(),
                    font: self._getFontOptions(),
                    text: self._getSampleText()
                });
                bbox = self._text.getBBox();
                self._textVerticalOffset = -bbox.y - bbox.height / 2;
                self._textWidth = bbox.width;
                self._textHeight = bbox.height
            },
            _getTextAlign: function() {
                return undefined
            },
            _getFontOptions: function() {
                var options = this._options,
                    font = options.text.font;
                if (!font || !font.color)
                    font = $extend({}, font, {color: options.color});
                return font
            },
            _updateLine: function() {
                var self = this;
                self._line.applySettings({
                    fill: self._options.color,
                    stroke: 'none',
                    strokeWidth: 0
                })
            },
            _updateBarItemsPositions: function() {
                var self = this,
                    positions = self._getPositions();
                self._backItem1.applySettings(self._buildItemSettings(positions.start, positions.back1));
                self._backItem2.applySettings(self._buildItemSettings(positions.back2, positions.end));
                self._spaceItem1.applySettings(self._buildItemSettings(positions.back1, positions.main1));
                self._spaceItem2.applySettings(self._buildItemSettings(positions.main2, positions.back2));
                self._mainItem.applySettings(self._buildItemSettings(positions.main1, positions.main2));
                self._tracker.applySettings(self._buildItemSettings(positions.main1, positions.main2))
            },
            render: function() {
                var self = this;
                self.callBase();
                if (self._isVisible()) {
                    self._prepare();
                    self._rootElement = self._rootElement || self._renderer.createGroup({'class': 'rangebar'});
                    self._rootElement.append(self._owner);
                    self._backItem1 = self._backItem1 || self._createBarItem();
                    self._backItem2 = self._backItem2 || self._createBarItem();
                    self._spaceItem1 = self._spaceItem1 || self._createBarItem();
                    self._spaceItem2 = self._spaceItem2 || self._createBarItem();
                    self._mainItem = self._mainItem || self._createBarItem();
                    self._tracker = self._tracker || self._createTracker().append(self._trackerOwner);
                    self._updateBarItems();
                    self._updateTextItems();
                    self._updateActiveElements()
                }
                else
                    self.clear();
                return self
            },
            clear: function() {
                var self = this;
                if (self._rootElement) {
                    self._rootElement.remove();
                    delete self._rootElement;
                    delete self._backItem1;
                    delete self._backItem2;
                    delete self._spaceItem1;
                    delete self._spaceItem2;
                    delete self._mainItem;
                    delete self._tracker;
                    delete self._hasText;
                    self._destroyTextItems()
                }
            },
            getTrackingElement: function() {
                return this._tracker
            },
            getTooltipParameters: function() {
                var position = this._getTooltipPosition();
                return {
                        x: position.x,
                        y: position.y,
                        value: this._currentValue,
                        color: this._options.color
                    }
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz, file circularNeedle.js */
    (function(DX, $, undefined) {
        var circularNeedles = DX.viz.gauges.__internals.circularNeedles;
        var convertAngleToRendererSpace = DX.utils.convertAngleToRendererSpace,
            $extend = $.extend;
        circularNeedles.SimpleIndicator = DX.viz.gauges.__internals.BaseIndicator.inherit({
            _updateActiveElements: function() {
                var self = this,
                    options = self._options,
                    actualAngle = self._getActualPosition(),
                    angle = convertAngleToRendererSpace(actualAngle);
                self._rootElement.rotate(angle, options.x, options.y);
                self._tracker.rotate(angle, options.x, options.y)
            },
            _isVisible: function() {
                var options = this._options;
                return options.width > 0 && options.indentFromCenter >= 0 && options.radius - options.indentFromCenter > 0
            },
            _getClassName: function() {
                return 'needle'
            },
            _getTrackerPoints: function() {
                var options = this._options,
                    y2 = options.y - options.radius,
                    y1 = options.y - options.indentFromCenter || options.y,
                    x1 = options.x - options.width / 2 || options.x,
                    x2 = x1 + options.width || options.x;
                return [x1, y1, x1, y2, x2, y2, x2, y1]
            },
            _destroy: function() {
                delete this._element
            },
            render: function() {
                var self = this;
                self.callBase();
                if (self._isVisible()) {
                    self._rootElement = self._rootElement || self._renderer.createGroup({'class': self._getClassName()});
                    self._rootElement.append(self._owner);
                    self._create();
                    self._tracker = self._tracker || self._renderer.createArea().append(self._trackerOwner);
                    self._tracker.applySettings({
                        points: self._getTrackerPoints(),
                        stroke: 'none',
                        strokeWidth: 0,
                        fill: '#000000',
                        opacity: 0.0001
                    });
                    self._updateActiveElements()
                }
                else if (self._rootElement) {
                    self._rootElement.remove();
                    delete self._rootElement;
                    self._destroy();
                    delete self._tracker
                }
                return self
            },
            measure: function() {
                var options = this._options,
                    result = {max: options.radius};
                if (options.indentFromCenter < 0)
                    result.inverseHorizontalOffset = result.inverseVerticalOffset = -options.indentFromCenter;
                return result
            },
            getTrackingElement: function() {
                return this._tracker
            },
            getTooltipParameters: function() {
                var options = this._options,
                    cossin = DX.utils.getCosAndSin(this._getActualPosition()),
                    r = (options.radius + options.indentFromCenter) / 2;
                return {
                        x: options.x + cossin.cos * r,
                        y: options.y - cossin.sin * r,
                        value: this._currentValue,
                        color: options.color,
                        offset: options.width / 2
                    }
            }
        });
        circularNeedles.RectangleNeedle = circularNeedles.SimpleIndicator.inherit({_create: function() {
                var self = this,
                    options = self._options,
                    y2 = options.y - options.radius,
                    y1 = options.y - options.indentFromCenter || options.y,
                    x1 = options.x - options.width / 2 || options.x,
                    x2 = x1 + options.width || options.x;
                self._element = self._element || self._renderer.createArea().append(self._rootElement);
                self._element.applySettings({
                    points: [x1, y1, x1, y2, x2, y2, x2, y1],
                    stroke: 'none',
                    strokeWidth: 0,
                    fill: options.color
                })
            }});
        circularNeedles.TriangleNeedle = circularNeedles.SimpleIndicator.inherit({_create: function() {
                var self = this,
                    options = self._options,
                    y2 = options.y - options.radius,
                    y1 = options.y - options.indentFromCenter || options.y,
                    x1 = options.x - options.width / 2 || options.x,
                    x2 = options.x + options.width / 2 || options.x;
                self._element = self._element || self._renderer.createArea().append(self._rootElement);
                self._element.applySettings({
                    points: [x1, y1, options.x, y2, x2, y1],
                    stroke: 'none',
                    strokeWidth: 0,
                    fill: options.color
                })
            }});
        circularNeedles.TwoColorRectangleNeedle = circularNeedles.SimpleIndicator.inherit({
            _create: function() {
                var self = this,
                    options = self._options,
                    x1 = options.x - options.width / 2 || options.x,
                    x2 = options.x + options.width / 2 || options.x,
                    y4 = options.y - options.radius,
                    y1 = options.y - options.indentFromCenter || options.y,
                    y3 = y4 + (y1 - y4) * options.secondFraction || y4,
                    y2 = y3 + options.space || y3;
                self._firstElement = self._firstElement || self._renderer.createArea().append(self._rootElement);
                self._spaceElement = self._spaceElement || self._renderer.createArea().append(self._rootElement);
                self._secondElement = self._secondElement || self._renderer.createArea().append(self._rootElement);
                self._firstElement.applySettings({
                    points: [x1, y1, x1, y2, x2, y2, x2, y1],
                    'class': 'dx-needle-part1',
                    fill: options.color,
                    stroke: 'none',
                    strokeWidth: 0
                });
                self._spaceElement.applySettings({
                    points: [x1, y2, x1, y3, x2, y3, x2, y2],
                    'class': 'dx-needle-hole',
                    fill: options.containerBackgroundColor,
                    stroke: 'none',
                    strokeWidth: 0
                });
                self._secondElement.applySettings({
                    points: [x1, y3, x1, y4, x2, y4, x2, y3],
                    'class': 'dx-needle-part2',
                    fill: options.secondColor,
                    stroke: 'none',
                    strokeWidth: 0
                })
            },
            _destroy: function() {
                delete this._firstElement;
                delete this._secondElement;
                delete this._spaceElement
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz, file linearNeedle.js */
    (function(DX, $, undefined) {
        var linearNeedles = DX.viz.gauges.__internals.linearNeedles;
        var $extend = $.extend;
        linearNeedles.SimpleIndicator = DX.viz.gauges.__internals.BaseIndicator.inherit({
            _updateActiveElements: function() {
                var self = this,
                    delta = self._getActualPosition() - self._zeroPosition;
                self._rootElement.move(self._vertical ? 0 : delta, self._vertical ? delta : 0);
                self._tracker.move(self._vertical ? 0 : delta, self._vertical ? delta : 0)
            },
            _isVisible: function() {
                var options = this._options;
                return options.length > 0 && options.width > 0
            },
            _getClassName: function() {
                return 'needle'
            },
            _getTrackerPoints: function() {
                var options = this._options,
                    x1,
                    x2,
                    y1,
                    y2,
                    p = this._zeroPosition;
                if (this._vertical) {
                    x1 = options.x - options.length / 2 || options.x;
                    x2 = options.x + options.length / 2 || options.x;
                    y1 = p + options.width / 2 || p;
                    y2 = p - options.width / 2 || p
                }
                else {
                    x1 = p - options.width / 2 || p;
                    x2 = p + options.width / 2 || p;
                    y1 = options.y + options.length / 2 || options.y;
                    y2 = options.y - options.length / 2 || options.y
                }
                return [x1, y1, x1, y2, x2, y2, x2, y1]
            },
            _destroy: function() {
                delete this._element
            },
            init: function(options) {
                var self = this;
                self.callBase(options);
                self._vertical = self._options.orientation === 'vertical';
                return self
            },
            render: function() {
                var self = this;
                self.callBase();
                if (self._isVisible()) {
                    self._zeroPosition = self._options.translator.getCodomainStart();
                    self._rootElement = self._rootElement || self._renderer.createGroup({'class': self._getClassName()});
                    self._rootElement.append(self._owner);
                    self._create();
                    self._tracker = self._tracker || self._renderer.createArea().append(self._trackerOwner);
                    self._tracker.applySettings({
                        points: self._getTrackerPoints(),
                        stroke: 'none',
                        strokeWidth: 0,
                        fill: '#000000',
                        opacity: 0.0001
                    });
                    self._updateActiveElements()
                }
                else if (self._rootElement) {
                    self._rootElement.remove();
                    delete self._rootElement;
                    self._destroy();
                    delete self._tracker
                }
                return self
            },
            measure: function() {
                var options = this._options,
                    p = this._vertical ? options.x : options.y;
                return {
                        min: p - options.length / 2,
                        max: p + options.length / 2
                    }
            },
            getTrackingElement: function() {
                return this._tracker
            },
            getTooltipParameters: function() {
                var self = this,
                    options = self._options,
                    p = self._getActualPosition(),
                    parameters = {
                        x: p,
                        y: p,
                        value: self._currentValue,
                        color: options.color,
                        offset: options.width / 2
                    };
                self._vertical ? parameters.x = options.x : parameters.y = options.y;
                return parameters
            }
        });
        linearNeedles.RectangleNeedle = linearNeedles.SimpleIndicator.inherit({_create: function() {
                var self = this,
                    options = self._options,
                    p = self._zeroPosition,
                    x1,
                    x2,
                    y1,
                    y2;
                if (self._vertical) {
                    x1 = options.x - options.length / 2 || options.x;
                    x2 = options.x + options.length / 2 || options.x;
                    y1 = p + options.width / 2 || p;
                    y2 = p - options.width / 2 || p
                }
                else {
                    x1 = p - options.width / 2 || p;
                    x2 = p + options.width / 2 || p;
                    y1 = options.y + options.length / 2 || options.y;
                    y2 = options.y - options.length / 2 || options.y
                }
                self._element = self._element || self._renderer.createArea().append(self._rootElement);
                self._element.applySettings({
                    points: [x1, y1, x1, y2, x2, y2, x2, y1],
                    stroke: 'none',
                    strokeWidth: 0,
                    fill: options.color
                })
            }});
        linearNeedles.RhombusNeedle = linearNeedles.SimpleIndicator.inherit({_create: function() {
                var self = this,
                    options = self._options,
                    x,
                    y,
                    dx,
                    dy;
                if (self._vertical) {
                    x = options.x;
                    y = self._zeroPosition;
                    dx = options.length / 2 || 0;
                    dy = options.width / 2 || 0
                }
                else {
                    x = self._zeroPosition;
                    y = options.y;
                    dx = options.width / 2 || 0;
                    dy = options.length / 2 || 0
                }
                self._element = self._element || self._renderer.createArea().append(self._rootElement);
                self._element.applySettings({
                    points: [x - dx, y, x, y - dy, x + dx, y, x, y + dy],
                    stroke: 'none',
                    strokeWidth: 0,
                    fill: options.color
                })
            }});
        linearNeedles.CircleNeedle = linearNeedles.SimpleIndicator.inherit({_create: function() {
                var self = this,
                    options = self._options,
                    x,
                    y,
                    r;
                if (self._vertical) {
                    x = options.x;
                    y = self._zeroPosition
                }
                else {
                    x = self._zeroPosition;
                    y = options.y
                }
                r = options.length / 2 || 0;
                self._element = self._element || self._renderer.createCircle().append(self._rootElement);
                self._element.applySettings({
                    cx: x,
                    cy: y,
                    r: r,
                    stroke: 'none',
                    strokeWidth: 0,
                    fill: options.color
                })
            }})
    })(DevExpress, jQuery);
    /*! Module viz, file circularMarker.js */
    (function(DX, undefined) {
        var circularMarkers = DX.viz.gauges.__internals.circularMarkers;
        var normalizeAngle = DX.utils.normalizeAngle,
            convertAngleToRendererSpace = DX.utils.convertAngleToRendererSpace,
            getCosAndSin = DX.utils.getCosAndSin,
            min = Math.min;
        circularMarkers.TriangleMarker = DX.viz.gauges.__internals.circularNeedles.SimpleIndicator.inherit({
            _isVisible: function() {
                var options = this._options;
                return options.length > 0 && options.width > 0 && options.radius > 0
            },
            _getClassName: function() {
                return 'marker'
            },
            _create: function() {
                var self = this,
                    options = self._options,
                    x = options.x,
                    y1 = options.y - options.radius,
                    dx = options.width / 2 || 0,
                    y2 = y1 - options.length || y1,
                    settings;
                self._element = self._element || self._renderer.createArea([], {'class': 'dx-marker-element'}).append(self._rootElement);
                settings = {
                    points: [x, y1, x - dx, y2, x + dx, y2],
                    stroke: 'none',
                    strokeWidth: 0,
                    fill: options.color
                };
                if (options.space > 0) {
                    settings.strokeWidth = min(options.space, options.width / 4) || 0;
                    settings.stroke = settings.strokeWidth > 0 ? options.containerBackgroundColor || 'none' : 'none'
                }
                self._element.applySettings(settings)
            },
            _getTrackerPoints: function() {
                var options = this._options,
                    x1 = options.x - options.width / 2,
                    x2 = options.x + options.width / 2,
                    y1 = options.y - options.radius,
                    y2 = y1 - options.length || y1;
                return [x1, y1, x1, y2, x2, y2, x2, y1]
            },
            measure: function() {
                var options = this._options;
                return {
                        min: options.radius,
                        max: options.radius + options.length || options.radius
                    }
            },
            getTooltipParameters: function() {
                var options = this._options,
                    cossin = DX.utils.getCosAndSin(this._getActualPosition()),
                    r = options.radius + options.length / 2,
                    parameters = this.callBase();
                parameters.x = options.x + cossin.cos * r;
                parameters.y = options.y - cossin.sin * r;
                parameters.offset = options.length / 2;
                return parameters
            }
        });
        circularMarkers.TextCloudMarker = DX.viz.gauges.__internals.BaseTextCloudMarker.inherit({
            _isVisible: function() {
                return this._options.radius > 0
            },
            _getTextCloudOptions: function() {
                var self = this,
                    angle = self._getActualPosition(),
                    cossin = getCosAndSin(angle),
                    nangle = normalizeAngle(angle);
                return {
                        x: self._options.x + cossin.cos * self._options.radius,
                        y: self._options.y - cossin.sin * self._options.radius,
                        type: nangle > 270 ? 'left-top' : nangle > 180 ? 'top-right' : nangle > 90 ? 'right-bottom' : 'bottom-left'
                    }
            },
            measure: function() {
                var self = this;
                self._measureText();
                return {
                        min: self._options.radius,
                        max: self._options.radius,
                        horizontalOffset: self._textFullWidth + self._options.arrowLength,
                        verticalOffset: self._textFullHeight + self._options.arrowLength
                    }
            }
        })
    })(DevExpress);
    /*! Module viz, file linearMarker.js */
    (function(DX, $, undefined) {
        var linearMarkers = DX.viz.gauges.__internals.linearMarkers;
        var min = Math.min,
            $extend = $.extend;
        linearMarkers.TriangleMarker = DX.viz.gauges.__internals.linearNeedles.SimpleIndicator.inherit({
            _getClassName: function() {
                return 'marker'
            },
            _create: function() {
                var self = this,
                    options = self._options,
                    x1,
                    x2,
                    y1,
                    y2,
                    settings = {
                        stroke: 'none',
                        strokeWidth: 0,
                        fill: options.color
                    };
                if (self._vertical) {
                    x1 = options.x;
                    y1 = self._zeroPosition;
                    x2 = x1 + (self._inverted ? options.length : -options.length);
                    settings.points = [x1, y1, x2, y1 - options.width / 2, x2, y1 + options.width / 2]
                }
                else {
                    y1 = options.y;
                    x1 = self._zeroPosition;
                    y2 = y1 + (self._inverted ? options.length : -options.length);
                    settings.points = [x1, y1, x1 - options.width / 2, y2, x1 + options.width / 2, y2]
                }
                if (options.space > 0) {
                    settings.strokeWidth = min(options.space, options.width / 4) || 0;
                    settings.stroke = settings.strokeWidth > 0 ? options.containerBackgroundColor || 'none' : 'none'
                }
                self._element = self._element || self._renderer.createArea().append(self._rootElement);
                self._element.applySettings(settings)
            },
            _getTrackerPoints: function() {
                var self = this,
                    options = self._options,
                    l = Number(options.length) || 0,
                    w = options.width / 2 || 0,
                    x1,
                    x2,
                    y1,
                    y2,
                    result;
                if (self._vertical) {
                    x1 = x2 = options.x;
                    x2 = x1 + (self._inverted ? options.length : -options.length);
                    y1 = self._zeroPosition + options.width / 2;
                    y2 = self._zeroPosition - options.width / 2;
                    result = [x1, y1, x2, y1, x2, y2, x1, y2]
                }
                else {
                    y1 = options.y;
                    y2 = y1 + (self._inverted ? options.length : -options.length);
                    x1 = self._zeroPosition - options.width / 2;
                    x2 = self._zeroPosition + options.width / 2;
                    result = [x1, y1, x1, y2, x2, y2, x2, y1]
                }
                return result
            },
            init: function(options) {
                var self = this;
                self.callBase(options);
                self._inverted = self._vertical ? self._options.horizontalOrientation === 'right' : self._options.verticalOrientation === 'bottom';
                return self
            },
            measure: function() {
                var self = this,
                    options = self._options,
                    minbound,
                    maxbound,
                    indent = options.width / 2 || 0;
                if (self._vertical) {
                    minbound = maxbound = options.x;
                    if (self._inverted)
                        maxbound = minbound + options.length || minbound;
                    else
                        minbound = maxbound - options.length || maxbound
                }
                else {
                    minbound = maxbound = options.y;
                    if (self._inverted)
                        maxbound = minbound + options.length || minbound;
                    else
                        minbound = maxbound - options.length || maxbound
                }
                return {
                        min: minbound,
                        max: maxbound,
                        indent: indent
                    }
            },
            getTooltipParameters: function() {
                var self = this,
                    options = self._options,
                    s = (self._inverted ? options.length : -options.length) / 2,
                    parameters = self.callBase();
                self._vertical ? parameters.x += s : parameters.y += s;
                parameters.offset = options.length / 2;
                return parameters
            }
        });
        linearMarkers.TextCloudMarker = DX.viz.gauges.__internals.BaseTextCloudMarker.inherit({
            _isVisible: function() {
                return true
            },
            _getTextCloudOptions: function() {
                var self = this,
                    position = self._getActualPosition(),
                    x = position,
                    y = position,
                    type;
                if (self._vertical) {
                    x = self._options.x;
                    type = self._inverted ? 'top-left' : 'top-right'
                }
                else {
                    y = self._options.y;
                    type = self._inverted ? 'right-top' : 'right-bottom'
                }
                return {
                        x: x,
                        y: y,
                        type: type
                    }
            },
            init: function(options) {
                var self = this;
                self.callBase(options);
                self._vertical = self._options.orientation === 'vertical';
                self._inverted = self._vertical ? self._options.horizontalOrientation === 'right' : self._options.verticalOrientation === 'bottom';
                return self
            },
            measure: function() {
                var self = this,
                    options = self._options,
                    minbound,
                    maxbound,
                    indent;
                self._measureText();
                if (self._vertical) {
                    indent = self._textFullHeight;
                    if (self._inverted) {
                        minbound = options.x;
                        maxbound = options.x + options.arrowLength + self._textFullWidth
                    }
                    else {
                        minbound = options.x - options.arrowLength - self._textFullWidth;
                        maxbound = options.x
                    }
                }
                else {
                    indent = self._textFullWidth;
                    if (self._inverted) {
                        minbound = options.y;
                        maxbound = options.y + options.arrowLength + self._textFullHeight
                    }
                    else {
                        minbound = options.y - options.arrowLength - self._textFullHeight;
                        maxbound = options.y
                    }
                }
                return {
                        min: minbound,
                        max: maxbound,
                        indent: indent
                    }
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz, file circularRangeBar.js */
    (function(DX, undefined) {
        var getCosAndSin = DX.utils.getCosAndSin,
            convertAngleToRendererSpace = DX.utils.convertAngleToRendererSpace,
            max = Math.max,
            min = Math.min;
        DX.viz.gauges.__internals.CircularRangeBar = DX.viz.gauges.__internals.BaseRangeBar.inherit({
            _isVisible: function() {
                var options = this._options;
                return options.size > 0 && options.radius - options.size > 0
            },
            _createBarItem: function() {
                return this._renderer.createArc().append(this._rootElement)
            },
            _createTracker: function() {
                return this._renderer.createArc(0, 0, 0, 0, 0, 0, {
                        stroke: 'none',
                        strokeWidth: 0,
                        fill: '#000000',
                        opacity: 0.0001
                    })
            },
            _setBarSides: function() {
                var self = this,
                    options = self._options;
                self._minSide = options.radius - options.size;
                self._maxSide = options.radius
            },
            _getSpace: function() {
                var options = this._options;
                return options.space > 0 ? options.space * 180 / options.radius / Math.PI : 0
            },
            _isTextVisible: function() {
                var options = this._options.text || {};
                return options.indent > 0
            },
            _getTextAlign: function() {
                return 'center'
            },
            _setTextItemsSides: function() {
                var self = this,
                    options = self._options;
                self._lineFrom = options.y - options.radius;
                self._lineTo = self._lineFrom - options.text.indent;
                self._textRadius = options.radius + options.text.indent
            },
            _getPositions: function() {
                var self = this,
                    basePosition = self._basePosition,
                    actualPosition = self._getActualPosition(),
                    mainPosition1,
                    mainPosition2,
                    space = self._space;
                if (basePosition >= actualPosition) {
                    mainPosition1 = basePosition;
                    mainPosition2 = actualPosition
                }
                else {
                    mainPosition1 = actualPosition;
                    mainPosition2 = basePosition
                }
                return {
                        start: self._startPosition,
                        end: self._endPosition,
                        main1: mainPosition1,
                        main2: mainPosition2,
                        back1: min(mainPosition1 + space, self._startPosition),
                        back2: max(mainPosition2 - space, self._endPosition)
                    }
            },
            _buildItemSettings: function(from, to) {
                var self = this;
                return {
                        x: self._options.x,
                        y: self._options.y,
                        innerRadius: self._minSide,
                        outerRadius: self._maxSide,
                        startAngle: to,
                        endAngle: from
                    }
            },
            _updateTextPosition: function() {
                var self = this,
                    cossin = getCosAndSin(self._getActualPosition()),
                    x = self._options.x + self._textRadius * cossin.cos,
                    y = self._options.y - self._textRadius * cossin.sin;
                x += cossin.cos * self._textWidth / 2;
                y -= cossin.sin * self._textHeight / 2;
                self._text.applySettings({
                    x: x,
                    y: y + self._textVerticalOffset
                })
            },
            _updateLinePosition: function() {
                var self = this,
                    angle = convertAngleToRendererSpace(self._getActualPosition()),
                    actualPosition = self._getActualPosition(),
                    x = self._options.x,
                    x1,
                    x2;
                if (self._basePosition > actualPosition) {
                    x1 = x - 2;
                    x2 = x
                }
                else if (self._basePosition < actualPosition) {
                    x1 = x;
                    x2 = x + 2
                }
                else {
                    x1 = x - 1;
                    x2 = x + 1
                }
                self._line.applySettings({points: [x1, self._lineFrom, x1, self._lineTo, x2, self._lineTo, x2, self._lineFrom]});
                self._line.rotate(angle, x, self._options.y)
            },
            _getTooltipPosition: function() {
                var self = this,
                    cossin = getCosAndSin((self._basePosition + self._getActualPosition()) / 2),
                    r = (self._minSide + self._maxSide) / 2;
                return {
                        x: self._options.x + cossin.cos * r,
                        y: self._options.y - cossin.sin * r
                    }
            },
            measure: function() {
                var self = this,
                    options = self._options,
                    result = {
                        min: options.radius - options.size || options.radius,
                        max: options.radius
                    };
                self._prepare();
                if (self._hasText) {
                    result.max += options.text.indent;
                    result.horizontalOffset = self._textWidth;
                    result.verticalOffset = self._textHeight
                }
                return result
            }
        })
    })(DevExpress);
    /*! Module viz, file linearRangeBar.js */
    (function(DX, undefined) {
        DX.viz.gauges.__internals.LinearRangeBar = DX.viz.gauges.__internals.BaseRangeBar.inherit({
            _isVisible: function() {
                var options = this._options;
                return options.size > 0
            },
            _prepare: function() {
                var self = this;
                self.callBase();
                self._vertical = self._options.orientation === 'vertical';
                self._inverted = self._vertical ? self._options.horizontalOrientation === 'right' : self._options.verticalOrientation === 'bottom'
            },
            _createBarItem: function() {
                return this._renderer.createArea().append(this._rootElement)
            },
            _createTracker: function() {
                return this._renderer.createArea([], {
                        stroke: 'none',
                        strokeWidth: 0,
                        fill: '#000000',
                        opacity: 0.0001
                    })
            },
            _setBarSides: function() {
                var self = this,
                    options = self._options,
                    minSide,
                    maxSide;
                if (self._vertical)
                    if (self._inverted) {
                        minSide = options.x;
                        maxSide = options.x + options.size
                    }
                    else {
                        minSide = options.x - options.size;
                        maxSide = options.x
                    }
                else if (self._inverted) {
                    minSide = options.y;
                    maxSide = options.y + options.size
                }
                else {
                    minSide = options.y - options.size;
                    maxSide = options.y
                }
                self._minSide = minSide;
                self._maxSide = maxSide;
                self._minBound = minSide;
                self._maxBound = maxSide
            },
            _getSpace: function() {
                var options = this._options;
                return options.space > 0 ? Number(options.space) : 0
            },
            _isTextVisible: function() {
                var textOptions = this._options.text || {};
                return textOptions.indent > 0 || textOptions.indent < 0
            },
            _getTextAlign: function() {
                return this._vertical ? this._options.text.indent > 0 ? 'left' : 'right' : 'center'
            },
            _setTextItemsSides: function() {
                var self = this,
                    indent = Number(self._options.text.indent);
                if (indent > 0) {
                    self._lineStart = self._maxSide;
                    self._lineEnd = self._maxSide + indent;
                    self._textPosition = self._lineEnd + (self._vertical ? 2 : self._textHeight / 2);
                    self._maxBound = self._textPosition + (self._vertical ? self._textWidth : self._textHeight / 2)
                }
                else if (indent < 0) {
                    self._lineStart = self._minSide;
                    self._lineEnd = self._minSide + indent;
                    self._textPosition = self._lineEnd - (self._vertical ? 2 : self._textHeight / 2);
                    self._minBound = self._textPosition - (self._vertical ? self._textWidth : self._textHeight / 2)
                }
            },
            _getPositions: function() {
                var self = this,
                    options = self._options,
                    startPosition = self._startPosition,
                    endPosition = self._endPosition,
                    space = self._space,
                    basePosition = self._basePosition,
                    actualPosition = self._getActualPosition(),
                    mainPosition1,
                    mainPosition2,
                    backPosition1,
                    backPosition2;
                if (startPosition < endPosition) {
                    if (basePosition < actualPosition) {
                        mainPosition1 = basePosition;
                        mainPosition2 = actualPosition
                    }
                    else {
                        mainPosition1 = actualPosition;
                        mainPosition2 = basePosition
                    }
                    backPosition1 = mainPosition1 - space;
                    backPosition2 = mainPosition2 + space
                }
                else {
                    if (basePosition > actualPosition) {
                        mainPosition1 = basePosition;
                        mainPosition2 = actualPosition
                    }
                    else {
                        mainPosition1 = actualPosition;
                        mainPosition2 = basePosition
                    }
                    backPosition1 = mainPosition1 + space;
                    backPosition2 = mainPosition2 - space
                }
                return {
                        start: startPosition,
                        end: endPosition,
                        main1: mainPosition1,
                        main2: mainPosition2,
                        back1: backPosition1,
                        back2: backPosition2
                    }
            },
            _buildItemSettings: function(from, to) {
                var self = this,
                    side1 = self._minSide,
                    side2 = self._maxSide;
                var points = self._vertical ? [side1, from, side1, to, side2, to, side2, from] : [from, side1, from, side2, to, side2, to, side1];
                return {points: points}
            },
            _updateTextPosition: function() {
                var self = this,
                    options = self._options,
                    position = self._getActualPosition();
                self._text.applySettings(self._vertical ? {
                    x: self._textPosition,
                    y: position + self._textVerticalOffset
                } : {
                    x: position,
                    y: self._textPosition + self._textVerticalOffset
                })
            },
            _updateLinePosition: function() {
                var self = this,
                    actualPosition = self._getActualPosition(),
                    side1,
                    side2,
                    points;
                if (self._vertical) {
                    if (self._basePosition >= actualPosition) {
                        side1 = actualPosition;
                        side2 = actualPosition + 2
                    }
                    else {
                        side1 = actualPosition - 2;
                        side2 = actualPosition
                    }
                    points = [self._lineStart, side1, self._lineStart, side2, self._lineEnd, side2, self._lineEnd, side1]
                }
                else {
                    if (self._basePosition <= actualPosition) {
                        side1 = actualPosition - 2;
                        side2 = actualPosition
                    }
                    else {
                        side1 = actualPosition;
                        side2 = actualPosition + 2
                    }
                    points = [side1, self._lineStart, side1, self._lineEnd, side2, self._lineEnd, side2, self._lineStart]
                }
                self._line.applySettings({points: points})
            },
            _getTooltipPosition: function() {
                var self = this,
                    crossCenter = (self._minSide + self._maxSide) / 2,
                    alongCenter = (self._basePosition + self._getActualPosition()) / 2,
                    position = {};
                if (self._vertical)
                    position = {
                        x: crossCenter,
                        y: alongCenter
                    };
                else
                    position = {
                        x: alongCenter,
                        y: crossCenter
                    };
                return position
            },
            measure: function() {
                var self = this,
                    options = self._options,
                    minbound,
                    maxbound,
                    indent;
                self._prepare();
                if (self._vertical) {
                    minbound = maxbound = options.x;
                    if (self._inverted)
                        maxbound = maxbound + options.size || maxbound;
                    else
                        minbound = minbound - options.size || minbound;
                    if (self._hasText) {
                        indent = self._textHeight / 2;
                        if (options.text.indent > 0)
                            maxbound += options.text.indent + self._textWidth;
                        if (options.text.indent < 0)
                            minbound += options.text.indent - self._textWidth
                    }
                }
                else {
                    minbound = maxbound = options.y;
                    if (self._inverted)
                        maxbound = maxbound + options.size || maxbound;
                    else
                        minbound = minbound - options.size || minbound;
                    if (self._hasText) {
                        indent = self._textWidth / 2;
                        if (options.text.indent > 0)
                            maxbound += options.text.indent + self._textHeight;
                        if (options.text.indent < 0)
                            minbound += options.text.indent - self._textHeight
                    }
                }
                return {
                        min: minbound,
                        max: maxbound,
                        indent: indent
                    }
            }
        })
    })(DevExpress);
    /*! Module viz, file circularSpindle.js */
    (function(DX, $, undefined) {
        var min = Math.min,
            $extend = $.extend;
        DX.viz.gauges.__internals.CircularSpindle = DX.Class.inherit({
            setup: function(parameters) {
                this._renderer = parameters.renderer;
                this._owner = parameters.owner;
                return this
            },
            init: function(options) {
                this._options = $extend(true, this._options || {}, options);
                return this
            },
            render: function() {
                var self = this,
                    options = self._options;
                if (options.visible !== false && options.size > 0) {
                    self._rootElement = self._rootElement || self._renderer.createGroup({'class': 'spindle'});
                    self._rootElement.append(self._owner);
                    self._element = self._element || self._renderer.createCircle().append(self._rootElement);
                    self._element.applySettings({
                        'class': 'dx-spindle-border',
                        cx: options.x,
                        cy: options.y,
                        r: options.size / 2,
                        fill: options.color || 'none',
                        stroke: 'none',
                        strokeWidth: 0
                    });
                    if (options.gapSize > 0) {
                        self._gapElement = self._gapElement || self._renderer.createCircle().append(self._rootElement);
                        self._gapElement.applySettings({
                            cx: options.x,
                            cy: options.y,
                            r: min(options.size, options.gapSize) / 2,
                            'class': 'dx-spindle-hole',
                            fill: options.containerBackgroundColor || 'none',
                            stroke: 'none',
                            strokeWidth: 0
                        })
                    }
                    else {
                        self._gapElement && self._gapElement.remove();
                        delete self._gapElement
                    }
                }
                else {
                    self._rootElement && self._rootElement.remove();
                    delete self._rootElement;
                    self._element && self._element.remove();
                    delete self._element;
                    self._gapElement && self._gapElement.remove();
                    delete self._gapElement
                }
                return self
            },
            measure: function() {
                var r = this._options.size / 2 || 0;
                return {
                        inverseHorizontalOffset: r,
                        inverseVerticalOffset: r
                    }
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz, file rangeContainer.js */
    (function(DX, $, undefined) {
        var isDefined = DX.utils.isDefined,
            isString = DX.utils.isString,
            isArray = DX.utils.isArray,
            Number = window.Number,
            isFinite = window.isFinite,
            max = Math.max,
            abs = Math.abs,
            $each = $.each,
            $map = $.map,
            $extend = $.extend;
        function subtractSegmentAsc(segmentStart, segmentEnd, otherStart, otherEnd) {
            var result;
            if (otherStart > segmentStart && otherEnd < segmentEnd)
                result = [{
                        start: segmentStart,
                        end: otherStart
                    }, {
                        start: otherEnd,
                        end: segmentEnd
                    }];
            else if (otherStart >= segmentEnd || otherEnd <= segmentStart)
                result = [{
                        start: segmentStart,
                        end: segmentEnd
                    }];
            else if (otherStart <= segmentStart && otherEnd >= segmentEnd)
                result = [];
            else if (otherStart > segmentStart)
                result = [{
                        start: segmentStart,
                        end: otherStart
                    }];
            else if (otherEnd < segmentEnd)
                result = [{
                        start: otherEnd,
                        end: segmentEnd
                    }];
            return result
        }
        function subtractSegmentDes(segmentStart, segmentEnd, otherStart, otherEnd) {
            var result;
            if (otherStart < segmentStart && otherEnd > segmentEnd)
                result = [{
                        start: segmentStart,
                        end: otherStart
                    }, {
                        start: otherEnd,
                        end: segmentEnd
                    }];
            else if (otherStart <= segmentEnd || otherEnd >= segmentStart)
                result = [{
                        start: segmentStart,
                        end: segmentEnd
                    }];
            else if (otherStart >= segmentStart && otherEnd <= segmentEnd)
                result = [];
            else if (otherStart < segmentStart)
                result = [{
                        start: segmentStart,
                        end: otherStart
                    }];
            else if (otherEnd > segmentEnd)
                result = [{
                        start: otherEnd,
                        end: segmentEnd
                    }];
            return result
        }
        function isNotEmptySegmentAsc(start, end, threshold) {
            return end - start >= threshold
        }
        function isNotEmptySegmentDes(start, end, threshold) {
            return start - end >= threshold
        }
        DX.viz.gauges.__internals.BaseRangeContainer = DX.Class.inherit({
            setup: function(parameters) {
                var self = this;
                DX.utils.debug.assertParam(parameters.renderer, '"renderer" was not passed');
                DX.utils.debug.assertParam(parameters.owner, '"owner" was not passed');
                DX.utils.debug.assertParam(parameters.incidentOccured, '"incidentOccured" was not passed');
                self._renderer = parameters.renderer;
                self._owner = parameters.owner;
                self._incidentOccured = parameters.incidentOccured;
                return self
            },
            init: function(options) {
                var self = this;
                self._options = $extend(true, self._options || {}, options);
                if (options && isDefined(options.ranges))
                    self._options.ranges = isArray(options.ranges) ? options.ranges.slice(0) : null;
                return self
            },
            _getRanges: function() {
                var options = this._options,
                    translator = options.translator,
                    totalStart = translator.getDomainStart(),
                    totalEnd = translator.getDomainEnd(),
                    totalDelta = totalEnd - totalStart,
                    isNotEmptySegment = totalDelta >= 0 ? isNotEmptySegmentAsc : isNotEmptySegmentDes,
                    subtractSegment = totalDelta >= 0 ? subtractSegmentAsc : subtractSegmentDes,
                    list = [],
                    ranges = [],
                    backgroundRanges = [{
                            start: totalStart,
                            end: totalEnd
                        }],
                    threshold = abs(totalDelta) / 1E4,
                    palette = isArray(options.palette) ? options.palette : [],
                    paletteOffset,
                    backgroundColor = isString(options.backgroundColor) ? options.backgroundColor : 'none',
                    width = options.width || {},
                    startWidth = Number(width > 0 ? width : width.start),
                    endWidth = Number(width > 0 ? width : width.end),
                    deltaWidth = endWidth - startWidth;
                if (!options.ranges) {
                    this._incidentOccured('The range container is not rendered because the value of the "ranges" option is not valid');
                    return null
                }
                if (!(startWidth >= 0 && endWidth >= 0 && startWidth + endWidth > 0)) {
                    this._incidentOccured('The range container is not rendered because the value of the "width" option is not valid');
                    return null
                }
                list = $map(options.ranges, function(rangeOptions) {
                    rangeOptions = rangeOptions || {};
                    var start = translator.adjust(rangeOptions.startValue),
                        end = translator.adjust(rangeOptions.endValue);
                    return isFinite(start) && isFinite(end) && isNotEmptySegment(start, end, threshold) ? {
                            start: start,
                            end: end,
                            color: rangeOptions.color
                        } : null
                });
                paletteOffset = max(0, palette.length - list.length);
                $each(list, function(i, item) {
                    var color = item.color;
                    isString(color) || (color = palette[i + paletteOffset]);
                    isString(color) || (color = 'none');
                    item.color = color
                });
                $each(list, function(_, item) {
                    var i,
                        ii,
                        sub,
                        subs,
                        range,
                        newRanges = [],
                        newBackgroundRanges = [];
                    for (i = 0, ii = ranges.length; i < ii; ++i) {
                        range = ranges[i];
                        subs = subtractSegment(range.start, range.end, item.start, item.end);
                        (sub = subs[0]) && (sub.color = range.color) && newRanges.push(sub);
                        (sub = subs[1]) && (sub.color = range.color) && newRanges.push(sub)
                    }
                    newRanges.push(item);
                    ranges = newRanges;
                    for (i = 0, ii = backgroundRanges.length; i < ii; ++i) {
                        range = backgroundRanges[i];
                        subs = subtractSegment(range.start, range.end, item.start, item.end);
                        (sub = subs[0]) && newBackgroundRanges.push(sub);
                        (sub = subs[1]) && newBackgroundRanges.push(sub)
                    }
                    backgroundRanges = newBackgroundRanges
                });
                $each(backgroundRanges, function(_, range) {
                    range.color = backgroundColor;
                    range['class'] = 'dx-background-range';
                    ranges.push(range)
                });
                $each(ranges, function(_, range) {
                    range.startPosition = translator.translate(range.start);
                    range.endPosition = translator.translate(range.end);
                    range.startWidth = (range.start - totalStart) / totalDelta * deltaWidth + startWidth;
                    range.endWidth = (range.end - totalStart) / totalDelta * deltaWidth + startWidth
                });
                return ranges
            },
            render: function() {
                var self = this,
                    ranges;
                self._rootElement = self._rootElement || self._renderer.createGroup({'class': 'range-container'});
                self._rootElement.append(self._owner).clear();
                ranges = self._getRanges();
                if (!ranges || !self._renderRanges(ranges)) {
                    self._rootElement.remove();
                    delete self._rootElement
                }
                return self
            }
        });
        DX.viz.gauges.__internals.CircularRangeContainer = DX.viz.gauges.__internals.BaseRangeContainer.inherit({
            _renderRanges: function(ranges) {
                var self = this,
                    options = self._options,
                    x = options.x,
                    y = options.y,
                    r = options.radius,
                    renderer = self._renderer,
                    root = self._rootElement,
                    inner = 0,
                    outer = 0,
                    width = options.width > 0 ? options.width : max(options.width.start, options.width.end);
                switch (options.orientation) {
                    case'inside':
                        inner = 1;
                        break;
                    case'outside':
                        outer = 1;
                        break;
                    case'center':
                        inner = outer = 0.5;
                        break;
                    default:
                        self._incidentOccured('The range container is not rendered because the value of the "orientation" option is not valid');
                        break
                }
                if ((inner || outer) && r + outer * width > 0 && r - inner * width > 0) {
                    $each(ranges, function(_, range) {
                        var width = (range.startWidth + range.endWidth) / 2;
                        var element = renderer.createArc(x, y, r + outer * width, r - inner * width, range.endPosition, range.startPosition, {
                                stroke: 'none',
                                strokeWidth: 0,
                                fill: range.color
                            }).append(root);
                        'class' in range && element.applySettings({'class': range['class']})
                    });
                    return true
                }
                return false
            },
            measure: function() {
                var options = this._options,
                    radius = options.radius,
                    size = options.width || {},
                    result = null;
                size = Number(size) || max(size.start, size.end, 0) || 0;
                switch (options.orientation) {
                    case'inside':
                        result = {
                            min: radius - size,
                            max: radius
                        };
                        break;
                    case'outside':
                        result = {
                            min: radius,
                            max: radius + size
                        };
                        break;
                    case'center':
                        result = {
                            min: radius - size / 2,
                            max: radius + size / 2
                        };
                        break
                }
                return result
            }
        });
        DX.viz.gauges.__internals.LinearRangeContainer = DX.viz.gauges.__internals.BaseRangeContainer.inherit({
            _renderRanges: function(ranges) {
                var self = this,
                    options = self._options,
                    renderer = self._renderer,
                    root = self._rootElement,
                    inner = 0,
                    outer = 0,
                    position;
                if (options.orientation === 'vertical') {
                    position = options.x;
                    switch (options.horizontalOrientation) {
                        case'left':
                            inner = 1;
                            break;
                        case'right':
                            outer = 1;
                            break;
                        case'center':
                            inner = outer = 0.5;
                            break;
                        default:
                            self._incidentOccured('The range container is not rendered because the value of the "horizontalOrientation" option is not valid');
                            break
                    }
                    if (inner || outer) {
                        $each(ranges, function(_, range) {
                            var element = renderer.createArea([position - range.startWidth * inner, range.startPosition, position - range.endWidth * inner, range.endPosition, position + range.endWidth * outer, range.endPosition, position + range.startWidth * outer, range.startPosition], {
                                    stroke: 'none',
                                    strokeWidth: 0,
                                    fill: range.color
                                }).append(root);
                            'class' in range && element.applySettings({'class': range['class']})
                        });
                        return true
                    }
                }
                else {
                    position = options.y;
                    switch (options.verticalOrientation) {
                        case'top':
                            inner = 1;
                            break;
                        case'bottom':
                            outer = 1;
                            break;
                        case'middle':
                            inner = outer = 0.5;
                            break;
                        default:
                            self._incidentOccured('The range container is not rendered because the value of the "verticalOrientation" option is not valid');
                            break
                    }
                    if (inner || outer) {
                        $each(ranges, function(_, range) {
                            var element = renderer.createArea([range.startPosition, position + range.startWidth * outer, range.startPosition, position - range.startWidth * inner, range.endPosition, position - range.endWidth * inner, range.endPosition, position + range.endWidth * outer], {
                                    stroke: 'none',
                                    strokeWidth: 0,
                                    fill: range.color
                                }).append(root);
                            'class' in range && element.applySettings({'class': range['class']})
                        });
                        return true
                    }
                }
                return false
            },
            measure: function() {
                var options = this._options,
                    size = options.width || {},
                    result = null;
                size = Number(size) || max(size.start, size.end, 0) || 0;
                if (options.orientation === 'vertical') {
                    result = {
                        min: options.x,
                        max: options.x
                    };
                    switch (options.horizontalOrientation) {
                        case'left':
                            result.min -= size;
                            break;
                        case'right':
                            result.max += size;
                            break;
                        case'center':
                            result.min -= size / 2;
                            result.max += size / 2;
                            break
                    }
                }
                else {
                    result = {
                        min: options.y,
                        max: options.y
                    };
                    switch (options.verticalOrientation) {
                        case'top':
                            result.min -= size;
                            break;
                        case'bottom':
                            result.max += size;
                            break;
                        case'middle':
                            result.min -= size / 2;
                            result.max += size / 2;
                            break
                    }
                }
                return result
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz, file title.js */
    (function(DX, $, undefined) {
        var Rectangle = DX.viz.core.Rectangle;
        var isString = DX.utils.isString,
            isDefined = DX.utils.isDefined,
            min = Math.min,
            max = Math.max,
            floor = Math.floor,
            ceil = Math.ceil,
            $extend = $.extend;
        DX.viz.gauges.__internals.Title = DX.Class.inherit({
            ctor: function() {
                this._options = {
                    title: {},
                    subtitle: {}
                }
            },
            _measureTexts: function() {
                var self = this,
                    mainBox = self._mainText ? self._mainText.getBBox() : null,
                    subBox = self._subText ? self._subText.getBBox() : null,
                    dy;
                self._location = {
                    x: 0,
                    y: 0
                };
                if (mainBox && subBox) {
                    self._subText.applySettings({y: ceil(-subBox.y)});
                    self._rect = new Rectangle({
                        left: floor(min(mainBox.x, subBox.x)),
                        right: ceil(max(mainBox.x + mainBox.width, subBox.x + subBox.width)),
                        top: floor(mainBox.y),
                        bottom: ceil(subBox.height)
                    })
                }
                else if (mainBox || subBox) {
                    mainBox = mainBox || subBox;
                    self._rect = new Rectangle({
                        left: floor(mainBox.x),
                        right: ceil(mainBox.x + mainBox.width),
                        top: floor(mainBox.y),
                        bottom: ceil(mainBox.y + mainBox.height)
                    })
                }
            },
            render: function(options) {
                var self = this;
                $extend(true, self._options, options);
                self._root = self._root || self._renderer.createGroup().applySettings({'class': 'dx-gauge-title'}).append(self._owner);
                if (isString(self._options.title.text)) {
                    self._mainText = self._mainText || self._renderer.createText().append(self._root);
                    self._mainText.applySettings({
                        x: 0,
                        y: 0,
                        align: 'center',
                        font: self._options.title.font,
                        text: self._options.title.text
                    })
                }
                else {
                    self._mainText && self._mainText.remove();
                    delete self._mainText
                }
                if (isString(self._options.subtitle.text)) {
                    self._subText = self._subText || self._renderer.createText().append(self._root);
                    self._subText.applySettings({
                        x: 0,
                        y: 0,
                        align: 'center',
                        font: self._options.subtitle.font,
                        text: self._options.subtitle.text
                    })
                }
                else {
                    self._subText && self._subText.remove();
                    delete self._subText
                }
                if (self._mainText || self._subText)
                    self._measureTexts();
                else {
                    self._root && self._root.remove();
                    delete self._root
                }
                return self
            },
            processTitleOptions: function(options) {
                if (isString(options))
                    return {text: options};
                else if (!isDefined(options))
                    return {text: null};
                else {
                    options = $extend({}, options);
                    options.layout = $extend({}, options.layout, {position: options.position});
                    return options
                }
            },
            processSubtitleOptions: function(options) {
                if (isString(options))
                    return {text: options};
                else if (!isDefined(options))
                    return {text: null};
                else
                    return $extend({}, options)
            },
            isVisible: function() {
                return !!(this._mainText || this._subText)
            },
            getBoundingRect: function() {
                return this._rect.clone()
            },
            getLayoutOptions: function() {
                return this._options.title.layout || {}
            },
            move: function(dx, dy) {
                var self = this;
                self._root.move(self._location.x += dx, self._location.y += dy);
                self._rect = self._rect.move(dx, dy);
                return self
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz, file layoutManager.js */
    (function(DX, undefined) {
        var min = Math.min,
            max = Math.max,
            isString = DX.utils.isString;
        var Rectangle = DX.viz.core.Rectangle;
        function parseLayoutOptions(options) {
            options = options || {};
            var parts = (isString(options) ? options : options.position || '').split('-');
            return {
                    primary: isString(parts[0]) ? parts[0].toLowerCase() : '',
                    secondary: isString(parts[1]) ? parts[1].toLowerCase() : '',
                    overlay: options.overlay > 0 ? Number(options.overlay) : 0
                }
        }
        DX.viz.gauges.__internals.LayoutManager = DX.Class.inherit({
            setRect: function(rect) {
                this._rect = rect.clone();
                return this
            },
            getRect: function() {
                return this._rect.clone()
            },
            applyLayout: function(rect, options) {
                var dx = 0,
                    dy = 0,
                    availableRect = this._rect,
                    resultRect = rect.clone(),
                    options_ = parseLayoutOptions(options),
                    delta = resultRect.height() - options_.overlay;
                switch (options_.primary) {
                    case'top':
                        if (delta >= 0) {
                            dy = availableRect.top - resultRect.top;
                            availableRect.top = min(availableRect.top + delta, availableRect.bottom)
                        }
                        else
                            dy = availableRect.top - resultRect.top - delta;
                        break;
                    case'bottom':
                        if (delta >= 0) {
                            dy = availableRect.bottom - resultRect.bottom;
                            availableRect.bottom = max(availableRect.bottom - delta, availableRect.top)
                        }
                        else
                            dy = availableRect.bottom - resultRect.bottom + delta;
                        break
                }
                switch (options_.secondary) {
                    case'':
                    case'center':
                        dx = availableRect.horizontalMiddle() - resultRect.horizontalMiddle();
                        break;
                    case'left':
                        dx = availableRect.left - resultRect.left;
                        break;
                    case'right':
                        dx = availableRect.right - resultRect.right;
                        break
                }
                resultRect = resultRect.move(dx, dy);
                return {
                        rect: resultRect,
                        dx: dx,
                        dy: dy
                    }
            },
            dock: function(rect, options) {
                var dx = 0,
                    dy = 0,
                    mainRect = this._rect,
                    resultRect = rect.clone(),
                    options_ = parseLayoutOptions(options);
                switch (options_.primary) {
                    case'top':
                        dy = mainRect.top - resultRect.bottom + options_.overlay;
                        break;
                    case'bottom':
                        dy = mainRect.bottom - resultRect.top - options_.overlay;
                        break
                }
                resultRect = resultRect.move(dx, dy);
                return {
                        rect: resultRect,
                        dx: dx,
                        dy: dy
                    }
            },
            selectRectByAspectRatio: function(aspectRatio, margins) {
                var rect = this._rect.clone(),
                    selfAspectRatio,
                    width = 0,
                    height = 0;
                margins = margins || {};
                if (aspectRatio > 0) {
                    rect.left += margins.left || 0;
                    rect.right -= margins.right || 0;
                    rect.top += margins.top || 0;
                    rect.bottom -= margins.bottom || 0;
                    if (rect.width() > 0 && rect.height() > 0) {
                        selfAspectRatio = rect.height() / rect.width();
                        if (selfAspectRatio > 1)
                            aspectRatio < selfAspectRatio ? width = rect.width() : height = rect.height();
                        else
                            aspectRatio > selfAspectRatio ? height = rect.height() : width = rect.width();
                        width > 0 || (width = height / aspectRatio);
                        height > 0 || (height = width * aspectRatio);
                        width = (rect.width() - width) / 2;
                        height = (rect.height() - height) / 2;
                        rect.left += width;
                        rect.right -= width;
                        rect.top += height;
                        rect.bottom -= height
                    }
                    else {
                        rect.left = rect.right = rect.horizontalMiddle();
                        rect.top = rect.bottom = rect.verticalMiddle()
                    }
                }
                return rect
            },
            selectRectBySizes: function(sizes, margins) {
                var rect = this._rect.clone(),
                    step;
                margins = margins || {};
                if (sizes) {
                    rect.left += margins.left || 0;
                    rect.right -= margins.right || 0;
                    rect.top += margins.top || 0;
                    rect.bottom -= margins.bottom || 0;
                    if (sizes.width > 0) {
                        step = (rect.width() - sizes.width) / 2;
                        if (step > 0) {
                            rect.left += step;
                            rect.right -= step
                        }
                    }
                    if (sizes.height > 0) {
                        step = (rect.height() - sizes.height) / 2;
                        if (step > 0) {
                            rect.top += step;
                            rect.bottom -= step
                        }
                    }
                }
                return rect
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz, file themeManager.js */
    (function($, DX, undefined) {
        var defaultFormatText = function(text) {
                if (isString(text))
                    return text;
                if (isNumber(text))
                    return text.toString();
                return 'N/A'
            };
        DX.viz.gauges.__internals.ThemeManager = DX.viz.core.BaseThemeManager.inherit(function() {
            var ctor = function(userTheme) {
                    this.callBase(userTheme, 'gauge');
                    this.theme.area.defaultFormatText = defaultFormatText
                };
            var getRangeTheme = function() {
                    return this.theme.range || {}
                };
            var getScaleTheme = function() {
                    return this.theme.scale || {}
                };
            var getNeedleTheme = function() {
                    return this.theme.needle || {}
                };
            var getMarkerTheme = function() {
                    return this.theme.marker || {}
                };
            return {
                    ctor: ctor,
                    getRangeTheme: getRangeTheme,
                    getScaleTheme: getScaleTheme,
                    getNeedleTheme: getNeedleTheme,
                    getMarkerTheme: getMarkerTheme
                }
        }())
    })(jQuery, DevExpress);
    /*! Module viz, file presetManager.js */
    (function(DX, $, undefined) {
        var internals = DX.viz.gauges.__internals;
        var circularPresets = {
                preset1: {
                    commonNeedleSettings: {type: 'rectangle'},
                    commonMarkerSettings: {type: 'textcloud'}
                },
                preset2: {
                    commonNeedleSettings: {type: 'twocolorrectangle'},
                    commonMarkerSettings: {
                        offset: 6,
                        type: 'triangle'
                    }
                },
                preset3: {
                    commonMarkerSettings: {
                        offset: 6,
                        type: 'triangle'
                    },
                    commonRangeBarSettings: {text: {indent: 70}}
                }
            };
        var linearPresets = {
                preset1: {
                    commonNeedleSettings: {type: 'rhombus'},
                    commonMarkerSettings: {type: 'textcloud'}
                },
                preset2: {
                    commonNeedleSettings: {type: 'circle'},
                    commonMarkerSettings: {type: 'triangle'}
                }
            };
        DX.viz.gauges.__internals.PresetManager = DX.Class.inherit({
            setup: function(gaugeType, presetName) {
                var self = this;
                self._activePreset = {};
                self._setPresetsCollection(self._selectPresets(gaugeType), 'preset1');
                return self._setActivePreset(presetName)
            },
            _selectPresets: function(gaugeType) {
                var presets = {};
                switch (gaugeType) {
                    case'circular':
                        presets = circularPresets;
                        break;
                    case'linear':
                        presets = linearPresets;
                        break
                }
                return presets
            },
            _setActivePreset: function(preset) {
                var currentPreset = {},
                    argIsString = !preset || typeof preset === 'string';
                this._presetName = argIsString ? preset : preset.name;
                if (this._presetName !== 'none') {
                    if (!argIsString)
                        this._updatePreset(preset);
                    this._activePreset = this._getCollectionElement(this._presetName)
                }
                else
                    this._activePreset = argIsString ? currentPreset : preset;
                return this._activePreset
            },
            getNeedlePreset: function() {
                return this._activePreset.commonNeedleSettings || {}
            },
            getMarkerPreset: function() {
                return this._activePreset.commonMarkerSettings || {}
            },
            getRangeBarPreset: function() {
                return this._activePreset.commonRangeBarSettings || {}
            },
            getScalePreset: function() {
                return this._activePreset.commonScaleSettings || {}
            },
            getRangePreset: function() {
                return this._activePreset.commonRangeSettings || {}
            },
            getTitlePreset: function() {
                return this._activePreset.title || {}
            },
            getSubtitlePreset: function() {
                return this._activePreset.subtitle || {}
            },
            getIndicatorPreset: function() {
                return this._activePreset.indicator || {}
            },
            getSpindlePreset: function() {
                return this._activePreset.spindle || {}
            },
            _updatePreset: function(preset) {
                if (this._presetsCollection.hasOwnProperty(preset.name))
                    $.extend(true, this._presetsCollection[preset.name], preset);
                else
                    $.extend(true, this._presetsCollection.defaultPreset, preset)
            },
            _getCollectionElement: function(elementName) {
                var element = {};
                if (this._presetsCollection.hasOwnProperty(elementName))
                    element = this._presetsCollection[elementName];
                else
                    element = this._presetsCollection.defaultPreset;
                return element
            },
            _setPresetsCollection: function(presetsCollection, defaultPresetName) {
                this._presetsCollection = $.extend(true, {}, presetsCollection || {});
                if (defaultPresetName && this._presetsCollection.hasOwnProperty(defaultPresetName))
                    this._presetsCollection.defaultPreset = $.extend({}, this._presetsCollection[defaultPresetName]);
                else
                    this._presetsCollection.defaultPreset = {}
            }
        });
        $.extend(DX.viz.gauges.__tests, {
            circularPresets: circularPresets,
            linearPresets: linearPresets
        })
    })(DevExpress, jQuery);
    /*! Module viz, file gauge.js */
    (function(DX, $, undefined) {
        var factory = DX.viz.gauges.__factory;
        var Rectangle = DX.viz.core.Rectangle;
        var isNumber = DX.utils.isNumber,
            isString = DX.utils.isString,
            isFunction = DX.utils.isFunction,
            isFinite = window.isFinite,
            setTimeout = window.setTimeout,
            windowResizeCallbacks = DX.utils.windowResizeCallbacks,
            $extend = $.extend,
            $each = $.each;
        var REDRAW_DELAY = 500;
        var DEFAULT_GAUGE_OPTIONS = {
                size: {
                    width: undefined,
                    height: undefined
                },
                margin: {
                    left: 0,
                    top: 0,
                    right: 0,
                    bottom: 0
                },
                geometry: {},
                preset: 'preset1',
                containerBackgroundColor: '#FFFFFF',
                animationEnabled: true,
                animationDuration: 1000,
                redrawOnResize: true,
                incidentOccured: $.noop,
                scale: {
                    startValue: 0,
                    endValue: 100,
                    majorTick: {
                        visible: true,
                        type: 'rectangle',
                        tickInterval: undefined,
                        customTickValues: [],
                        length: 5,
                        width: 2,
                        showCalculatedTicks: true,
                        useTicksAutoArrangement: true,
                        color: '#FFFFFF'
                    },
                    minorTick: {
                        visible: false,
                        type: 'rectangle',
                        tickInterval: undefined,
                        customTickValues: [],
                        length: 3,
                        width: 1,
                        showCalculatedTicks: true,
                        color: '#FFFFFF'
                    },
                    label: {
                        visible: true,
                        format: '',
                        precision: 2,
                        customizeText: undefined,
                        font: {
                            color: '#7F7F7F',
                            size: 12,
                            family: "'SegoeUI', 'Segoe UI', 'HelveticaNeue', 'Helvetica Neue', 'Trebuchet MS', Verdana",
                            weight: 400
                        }
                    }
                },
                rangeContainer: {
                    offset: 0,
                    width: 5,
                    backgroundColor: '#808080',
                    palette: ['#AD79CE', '#639EC6', '#A5C763', '#FFB65A', '#E78E94'],
                    ranges: []
                },
                commonNeedleSettings: {
                    __info: 'needle',
                    color: '#C2C2C2'
                },
                commonMarkerSettings: {
                    __info: 'marker',
                    color: '#679EC5',
                    space: 2,
                    length: 14,
                    width: 13,
                    arrowLength: 5,
                    horizontalOffset: 6,
                    verticalOffset: 3,
                    text: {
                        customizeText: undefined,
                        font: {
                            color: '#FFFFFF',
                            size: 18,
                            family: "'SegoeUI', 'Segoe UI', 'HelveticaNeue', 'Helvetica Neue', 'Trebuchet MS', Verdana",
                            weight: 400
                        }
                    }
                },
                commonRangeBarSettings: {
                    baseValue: undefined,
                    color: '#AD79CE',
                    backgroundColor: 'none',
                    space: 2,
                    size: 10,
                    text: {
                        indent: 0,
                        customizeText: undefined,
                        font: {
                            size: 14,
                            family: "'SegoeUI', 'Segoe UI', 'HelveticaNeue', 'Helvetica Neue', 'Trebuchet MS', Verdana",
                            weight: 400
                        }
                    }
                },
                title: {
                    layout: {
                        position: 'top-center',
                        overlay: 0
                    },
                    font: {
                        size: 18,
                        color: '#232323',
                        family: "'SegoeUI-Light', 'Segoe UI Light', 'HelveticaNeue-Light', 'Helvetica Neue Light', 'SegoeUI', 'Segoe UI', 'HelveticaNeue', 'Helvetica Neue', 'Trebuchet MS', Verdana",
                        weight: 200
                    }
                },
                subtitle: {font: {
                        size: 14,
                        color: '#232323',
                        family: "'SegoeUI-Light', 'Segoe UI Light', 'HelveticaNeue-Light', 'Helvetica Neue Light', 'SegoeUI', 'Segoe UI', 'HelveticaNeue', 'Helvetica Neue', 'Trebuchet MS', Verdana",
                        weight: 200
                    }},
                indicator: {
                    hasPositiveMeaning: true,
                    text: {
                        format: 'fixedPoint',
                        precision: 0,
                        customizeText: $.none,
                        useDefaultColor: false,
                        font: {
                            color: '#7F7F7F',
                            size: 18,
                            family: "'SegoeUI', 'Segoe UI', 'HelveticaNeue', 'Helvetica Neue', 'Trebuchet MS', Verdana",
                            weight: 400
                        }
                    },
                    layout: {
                        position: 'bottom-center',
                        overlay: 0
                    }
                },
                tooltip: {
                    enabled: false,
                    format: undefined,
                    precision: undefined,
                    customizeText: undefined,
                    font: {
                        color: '#FFFFFF',
                        size: 26,
                        family: "'SegoeUI-Light', 'Segoe UI Light', 'HelveticaNeue-Light', 'Helvetica Neue Light', 'SegoeUI', 'Segoe UI', 'HelveticaNeue', 'Helvetica Neue', 'Trebuchet MS', Verdana",
                        weight: 200
                    },
                    horizontalPadding: 22,
                    verticalPadding: 6,
                    arrowLength: 10
                },
                tracker: {tooltipDelay: 500}
            };
        DX.viz.gauges.Gauge = DX.ui.Component.inherit({
            _defaultOptions: function() {
                return $extend(true, {}, DEFAULT_GAUGE_OPTIONS)
            },
            _initOptions: function(options) {
                var self = this,
                    preset;
                self._presetManager = factory.createPresetManager();
                preset = self._presetManager.setup(self._gaugeType(), options ? options.preset : {});
                self.option(preset);
                self.callBase(options)
            },
            _getPresetName: function(options) {
                return options && isString(options.preset) ? options.preset : this.option('preset')
            },
            _init: function() {
                var self = this;
                self._initRenderer();
                self._tracker = factory.createTracker();
                self._tracker.setup(self);
                self._layoutManager = factory.createLayoutManager();
                self._defaultOpts = self._defaultOptions();
                self._creationOptions = self._getCreationOptions();
                self._mainElements = [];
                self._externalElements = [];
                self._needles = [];
                self._markers = [];
                self._rangeBars = [];
                self._initResizeHandler()
            },
            _dispose: function() {
                var self = this;
                self._disposeRenderer();
                delete self._tracker;
                delete self._layoutManager;
                delete self._defaultOpts;
                delete self._creationOptions;
                delete self._mainElements;
                delete self._externalElements;
                delete self._needles;
                delete self._markers;
                delete self._rangeBars;
                self._disposeResizeHandler();
                self.callBase()
            },
            _initRenderer: function() {
                var self = this;
                self._canvas = {
                    width: 1,
                    height: 1,
                    marginLeft: 0,
                    marginRight: 0,
                    marginTop: 0,
                    marginBottom: 0
                };
                self._renderer = factory.createRenderer({
                    width: 1,
                    height: 1
                });
                self._rootElement = self._renderer.getRoot();
                self._trackerGroup = self._renderer.createGroup({'class': 'tracker'}).append(self._rootElement)
            },
            _disposeRenderer: function() {
                var self = this;
                delete self._canvas;
                delete self._renderer;
                delete self._rootElement;
                delete self._trackerGroup
            },
            _initResizeHandler: function() {
                var self = this;
                self._resizeHandler = DX.utils.createResizeHandler(function() {
                    self._renderCore()
                });
                self._resizeHandler.dispose = function() {
                    self = null;
                    return this
                }
            },
            _disposeResizeHandler: function() {
                windowResizeCallbacks.remove(this._resizeHandler.stop().dispose());
                delete this._resizeHandler
            },
            _trackWindowResize: function() {
                var self = this;
                if (self.option('redrawOnResize') === true)
                    windowResizeCallbacks.has(self._resizeHandler) || windowResizeCallbacks.add(self._resizeHandler);
                else
                    windowResizeCallbacks.remove(self._resizeHandler)
            },
            _getIncidentOccured: function() {
                var incidentOccured = this.option('incidentOccured');
                isFunction(incidentOccured) || (incidentOccured = this._defaultOpts.incidentOccured);
                return function() {
                        incidentOccured.apply(null, arguments)
                    }
            },
            _getCreationOptions: function() {
                return {
                        renderer: this._renderer,
                        ownerElement: this._rootElement,
                        owner: this._rootElement
                    }
            },
            _getCommonOptions: function() {
                var self = this,
                    formatOptions = self._getDefaultFormatOptions();
                return {
                        translator: self._area.translator,
                        animationEnabled: self.option('animationEnabled'),
                        animationDuration: self.option('animationDuration'),
                        containerBackgroundColor: self.option('containerBackgroundColor'),
                        defaultTextFormat: formatOptions.format,
                        defaultTextPrecision: formatOptions.precision
                    }
            },
            _getDefaultFormatOptions: function() {
                var area = this._area;
                return DX.utils.getAppropriateFormat(area.startValue, area.endValue, this._getApproximateScreenRange())
            },
            _getCommonNeedleSettings: function() {
                var self = this;
                return $extend(true, {}, self._defaultOpts.commonNeedleSettings, self._presetManager.getNeedlePreset(), self.option('commonNeedleSettings'))
            },
            _getCommonMarkerSettings: function() {
                var self = this;
                return $extend(true, {}, self._defaultOpts.commonMarkerSettings, self._presetManager.getMarkerPreset(), self.option('commonMarkerSettings'))
            },
            _getCommonRangeBarSettings: function() {
                var self = this;
                return $extend(true, self._defaultOpts.commonRangeBarSettings, self._presetManager.getRangeBarPreset(), self.option('commonRangeBarSettings'))
            },
            _hide: function() {
                !this._isHidden && (this._isHidden = true) && this._renderer.getRoot().hide()
            },
            _show: function() {
                this._isHidden && delete this._isHidden && this._renderer.getRoot().show()
            },
            _getCanvas: function() {
                var self = this,
                    size = self.option('size') || {},
                    margin = self.option('margin') || {},
                    container = self._element(),
                    defaultSize = self._getDefaultContainerSize(),
                    width = size.width >= 0 ? Number(size.width) : container.width(),
                    height = size.height >= 0 ? Number(size.height) : container.height();
                if (!width && Number(size.width) !== 0)
                    width = defaultSize.width;
                if (!height && Number(size.height) !== 0)
                    height = defaultSize.height;
                return {
                        width: width,
                        height: height,
                        marginLeft: margin.left > 0 ? Number(margin.left) : 0,
                        marginTop: margin.top > 0 ? Number(margin.top) : 0,
                        marginRight: margin.right > 0 ? Number(margin.right) : 0,
                        marginBottom: margin.bottom > 0 ? Number(margin.bottom) : 0
                    }
            },
            _updateVisibility: function(canvas) {
                var self = this;
                if (canvas.width - canvas.marginLeft - canvas.marginRight >= 2 && canvas.height - canvas.marginTop - canvas.marginBottom >= 2 && self._element().is(':visible')) {
                    self._show();
                    return true
                }
                else {
                    self._hide();
                    self._incidentOccured('Gauge cannot be rendered since container is too small or not visible');
                    return false
                }
            },
            _getArea: function() {
                var self = this,
                    scale = self.option('scale') || {},
                    area = {};
                area.startValue = isNumber(scale.startValue) ? Number(scale.startValue) : 0;
                area.endValue = isNumber(scale.endValue) ? Number(scale.endValue) : 100;
                area.baseValue = Math.min(area.startValue, area.endValue);
                self._setupArea(area);
                area.translator = factory.createTranslator(area.startCoord, area.endCoord, area.startValue, area.endValue);
                return area
            },
            _renderTitle: function() {
                var self = this,
                    titleOptions = self.option('title'),
                    subtitleOptions = self.option('subtitle');
                if (!self._title) {
                    self._title = factory.createTitle();
                    self._title._renderer = self._renderer;
                    self._title._owner = self._rootElement
                }
                titleOptions = $extend(true, {}, self._defaultOpts.title, self._presetManager.getTitlePreset(), self._title.processTitleOptions(titleOptions));
                subtitleOptions = $extend(true, {}, self._defaultOpts.subtitle, self._presetManager.getSubtitlePreset(), self._title.processSubtitleOptions(subtitleOptions));
                self._title.render({
                    title: titleOptions,
                    subtitle: subtitleOptions
                });
                self._title.isVisible() && self._externalElements.push(self._title)
            },
            _renderDeltaIndicator: function() {
                var self = this,
                    options = self.option('indicator');
                if (!self._indicator) {
                    self._indicator = factory.createIndicator();
                    if (self._indicator) {
                        self._indicator._renderer = self._renderer;
                        self._indicator._owner = self._rootElement
                    }
                }
                if (self._indicator) {
                    options = $extend(true, {}, self._defaultOpts.indicator, self._presetManager.getIndicatorPreset(), options);
                    self._indicator.render(options);
                    self._indicator.isVisible() && self._externalElements.push(self._indicator)
                }
            },
            _renderTooltip: function() {
                var self = this,
                    options = $extend({}, self._defaultOpts.tooltip, self.option('tooltip'));
                if (!self._tooltip) {
                    self._tooltip = factory.createTooltip();
                    self._tooltip.setup(self)
                }
                self._tooltip.init($extend(true, {}, self._defaultOpts.tooltip, self.option('tooltip')));
                self._tooltip.render()
            },
            _renderDebugInfo: function() {
                var self = this,
                    group = self._debugGroup || self._renderer.createGroup({'class': 'debug-info'}).append(),
                    rect;
                group.clear();
                rect = self._rootRect;
                self._renderer.createRect(rect.left, rect.top, rect.width(), rect.height(), 0, {
                    stroke: '#000000',
                    strokeWidth: 1,
                    fill: 'none'
                }).append(group);
                rect = self._mainRect;
                self._renderer.createRect(rect.left, rect.top, rect.width(), rect.height(), 0, {
                    stroke: '#0000FF',
                    strokeWidth: 1,
                    fill: 'none'
                }).append(group);
                rect = self._layoutManager.getRect();
                rect && self._renderer.createRect(rect.left, rect.top, rect.width(), rect.height(), 0, {
                    stroke: '#FF0000',
                    strokeWidth: 1,
                    fill: 'none'
                }).append(group);
                rect = self._title && self._title.isVisible() ? self._title.getBoundingRect() : null;
                rect && self._renderer.createRect(rect.left, rect.top, rect.width(), rect.height(), 0, {
                    stroke: '#00FF00',
                    strokeWidth: 1,
                    fill: 'none'
                }).append(group);
                rect = self._indicator && self._indicator.isVisible() ? self._indicator.getBoundingRect() : null;
                rect && self._renderer.createRect(rect.left, rect.top, rect.width(), rect.height(), 0, {
                    stroke: '#00FF00',
                    strokeWidth: 1,
                    fill: 'none'
                }).append(group)
            },
            _renderCore: function(force) {
                var self = this,
                    currentCanvas = self._canvas,
                    canvas = self._getCanvas();
                if (!self._updateVisibility(canvas))
                    return;
                if (canvas.width === currentCanvas.width && canvas.height === currentCanvas.height && !force)
                    return;
                self._renderer.container || self._renderer.draw(self._element().get(0));
                self._renderer.resize(canvas.width, canvas.height);
                self._canvas = canvas;
                self._rootRect = new Rectangle({
                    left: canvas.marginLeft,
                    top: canvas.marginTop,
                    right: canvas.width - canvas.marginRight,
                    bottom: canvas.height - canvas.marginBottom
                });
                self._layoutManager.setRect(self._rootRect);
                self._mainRect = self._rootRect.clone();
                self._area = self._getArea();
                self._commonOptions = self._getCommonOptions();
                self._mainElements.length = 0;
                self._externalElements.length = 0;
                self._renderTitle();
                self._renderDeltaIndicator();
                $each(self._externalElements, function(_, item) {
                    var layout = self._layoutManager.applyLayout(item.getBoundingRect(), item.getLayoutOptions());
                    item.move(layout.dx, layout.dy)
                });
                self._mainRect = self._layoutManager.getRect();
                self._prepareMainElements();
                self._applyMainLayout(self._measureMainElements());
                self._renderMainElements();
                $each(self._externalElements, function(_, item) {
                    var layout = self._layoutManager.dock(item.getBoundingRect(), item.getLayoutOptions());
                    item.move(layout.dx, layout.dy)
                });
                self._renderTooltip();
                self._tracker.init(self.option('tracker')).activate()
            },
            _render: function() {
                var self = this;
                self._incidentOccured = self._getIncidentOccured();
                self._renderCore(true);
                self._updateActiveElements();
                self._trackWindowResize();
                self.option('debugMode') === true && self._renderDebugInfo()
            },
            _prepareMainElements: function() {
                var self = this;
                self._renderRangeContainer();
                self._renderScale();
                var rangeBarsOption = self.option('rangeBars'),
                    needlesOption = self.option('needles'),
                    markersOption = self.option('markers');
                if (rangeBarsOption === undefined && needlesOption === undefined && markersOption === undefined)
                    needlesOption = [{value: self._area.baseValue}];
                self._renderIndicators('_rangeBars', rangeBarsOption || [], self._getCommonRangeBarSettings(), self._createRangeBar);
                self._renderIndicators('_needles', needlesOption || [], self._getCommonNeedleSettings(), self._createNeedle);
                self._renderIndicators('_markers', markersOption || [], self._getCommonMarkerSettings(), self._createMarker)
            },
            _updateActiveElements: function() {
                var self = this;
                $each(self._mainElements, function(_, item) {
                    item.setCurrentValue && item.setCurrentValue(item._options.value)
                })
            },
            _renderScale: function() {
                var self = this,
                    scale = self._scale,
                    userOptions = self.option('scale'),
                    options;
                if (!scale) {
                    scale = self._scale = self._createScale();
                    scale.setup({
                        renderer: self._renderer,
                        owner: self._rootElement,
                        incidentOccured: self._incidentOccured
                    })
                }
                options = self._combineOptions(self._commonOptions, self._defaultOpts.commonScaleSettings, self._presetManager.getScalePreset(), userOptions, {
                    approximateScreenDelta: self._getApproximateScreenRange(),
                    offset: 0
                });
                options.majorTick.customTickValues = options.majorTick.customTickValues || [];
                options.minorTick.customTickValues = options.minorTick.customTickValues || [];
                scale.init(options);
                self._mainElements.push(scale)
            },
            _renderRangeContainer: function() {
                var self = this,
                    rangeContainer = self._rangeContainer,
                    userOptions = self.option('rangeContainer'),
                    options;
                if (!rangeContainer) {
                    rangeContainer = self._rangeContainer = self._createRangeContainer();
                    rangeContainer.setup({
                        renderer: self._renderer,
                        owner: self._rootElement,
                        incidentOccured: self._incidentOccured
                    })
                }
                options = self._combineOptions(self._commonOptions, self._defaultOpts.commonRangeSettings, self._presetManager.getRangePreset(), userOptions);
                options.ranges = options.ranges || [];
                rangeContainer.init(options);
                self._mainElements.push(rangeContainer)
            },
            _renderIndicators: function(fieldName, userOptions, commonSettings, createHandler) {
                var self = this,
                    list = self[fieldName],
                    newList = [],
                    currentUserOptions,
                    i,
                    count,
                    item,
                    newItem;
                for (i = 0, count = list.length; i < count; ++i) {
                    item = list[i];
                    currentUserOptions = userOptions[i];
                    if (currentUserOptions) {
                        newItem = self._renderIndicator(item, commonSettings, currentUserOptions, createHandler);
                        item !== newItem && item.destroy();
                        newItem && newList.push(newItem)
                    }
                    else
                        item.destroy()
                }
                for (i = count, count = userOptions.length; i < count; ++i) {
                    currentUserOptions = userOptions[i];
                    if (currentUserOptions) {
                        newItem = self._renderIndicator(undefined, commonSettings, currentUserOptions, createHandler);
                        newItem && newList.push(newItem)
                    }
                }
                self[fieldName] = newList
            },
            _renderIndicator: function(indicator, commonSettings, userOptions, createHandler) {
                var self = this,
                    options = self._combineOptions(self._commonOptions, commonSettings, userOptions),
                    item = indicator;
                self._updateIndicatorOptions(item, options);
                if (options.value !== undefined) {
                    if (!item || item._options.type !== options.type) {
                        item = createHandler.call(self, options.type);
                        if (item)
                            item.setup({
                                renderer: self._renderer,
                                owner: self._rootElement,
                                tracker: self._trackerGroup
                            });
                        else
                            self._incidentOccured('Cannot create ' + options.__info + ': type "' + options.type + '" is unknown')
                    }
                    if (item) {
                        item.init(options);
                        self._mainElements.push(item)
                    }
                }
                else
                    item = undefined;
                return item
            },
            _updateIndicatorOptions: function(indicator, options) {
                options.baseValue = isFinite(options.translator.translate(options.baseValue)) ? options.baseValue : this._area.baseValue;
                indicator && (options.currentValue = indicator.getCurrentValue());
                isFinite(options.currentValue) || (options.currentValue = options.baseValue);
                options.value = options.translator.adjust(options.value);
                if (options.text && !options.text.format && !options.text.precision) {
                    options.text.format = this._commonOptions.defaultTextFormat;
                    options.text.precision = this._commonOptions.defaultTextPrecision
                }
            },
            _getTrackedElements: function() {
                var list = [];
                $each(this._rangeBars, function(i, item) {
                    list.push({
                        target: item,
                        info: {
                            type: 'rangebar',
                            index: i
                        }
                    })
                });
                $each(this._needles, function(i, item) {
                    list.push({
                        target: item,
                        info: {
                            type: 'needle',
                            index: i
                        }
                    })
                });
                $each(this._markers, function(i, item) {
                    list.push({
                        target: item,
                        info: {
                            type: 'marker',
                            index: i
                        }
                    })
                });
                return list
            },
            _accessIndicatorValue: function(indicator, value) {
                if (value === undefined)
                    return indicator ? indicator.getCurrentValue() : undefined;
                else {
                    indicator && indicator.setCurrentValue(value);
                    return this
                }
            },
            needleValue: function(name, value) {
                return this._accessIndicatorValue(this._needles[name], value)
            },
            markerValue: function(name, value) {
                return this._accessIndicatorValue(this._markers[name], value)
            },
            rangeBarValue: function(name, value) {
                return this._accessIndicatorValue(this._rangeBars[name], value)
            },
            indicatorValue: function(value) {
                var self = this;
                if (value !== undefined)
                    self._indicator && self._indicator.update(value)
            },
            _optionValuesEqual: function(name, oldValue, newValue) {
                if (name === 'rangeContainer')
                    oldValue && newValue && newValue.ranges && (oldValue.ranges = null);
                if (name === 'scale') {
                    oldValue && oldValue.majorTick && newValue.majorTick && newValue.majorTick.customTickValues && (oldValue.majorTick.customTickValues = null);
                    oldValue && oldValue.minorTick && newValue.minorTick && newValue.minorTick.customTickValues && (oldValue.minorTick.customTickValues = null)
                }
                return this.callBase.apply(this, arguments)
            }
        });
        DX.viz.gauges.__tests.DEFAULT_GAUGE_OPTIONS = DEFAULT_GAUGE_OPTIONS
    })(DevExpress, jQuery);
    /*! Module viz, file circularGauge.js */
    (function(DX, $, undefined) {
        var factory = DX.viz.gauges.__factory;
        var isNumber = DX.utils.isNumber,
            Number = window.Number,
            normalizeAngle = DX.utils.normalizeAngle,
            getCosAndSin = DX.utils.getCosAndSin,
            abs = Math.abs,
            max = Math.max,
            min = Math.min,
            round = Math.round,
            slice = Array.prototype.slice,
            $extend = $.extend,
            $each = $.each;
        var PI = Math.PI;
        var DEFAULT_GAUGE_OPTIONS = {
                geometry: {
                    startAngle: 225,
                    endAngle: 315,
                    totalRadius: undefined
                },
                scale: {
                    orientation: 'outside',
                    label: {indentFromTick: 10}
                },
                rangeContainer: {orientation: 'outside'},
                spindle: {
                    visible: true,
                    size: 14,
                    gapSize: 10,
                    color: '#C2C2C2'
                },
                commonNeedleSettings: {
                    offset: 20,
                    type: 'rectangle',
                    indentFromCenter: 0,
                    width: 2,
                    space: 2,
                    secondColor: '#E18E92',
                    secondFraction: 0.4
                },
                commonMarkerSettings: {
                    offset: -6,
                    type: 'textcloud'
                },
                commonRangeBarSettings: {offset: 30}
            };
        function getSides(startAngle, endAngle) {
            var startCosSin = getCosAndSin(startAngle),
                endCosSin = getCosAndSin(endAngle),
                startCos = startCosSin.cos,
                startSin = startCosSin.sin,
                endCos = endCosSin.cos,
                endSin = endCosSin.sin;
            return {
                    left: startSin <= 0 && endSin >= 0 || startSin <= 0 && endSin <= 0 && startCos <= endCos || startSin >= 0 && endSin >= 0 && startCos >= endCos ? -1 : min(startCos, endCos, 0),
                    right: startSin >= 0 && endSin <= 0 || startSin >= 0 && endSin >= 0 && startCos >= endCos || startSin <= 0 && endSin <= 0 && startCos <= endCos ? 1 : max(startCos, endCos, 0),
                    up: startCos <= 0 && endCos >= 0 || startCos <= 0 && endCos <= 0 && startSin >= endSin || startCos >= 0 && endCos >= 0 && startSin <= endSin ? -1 : -max(startSin, endSin, 0),
                    down: startCos >= 0 && endCos <= 0 || startCos >= 0 && endCos >= 0 && startSin <= endSin || startCos <= 0 && endCos <= 0 && startSin >= endSin ? 1 : -min(startSin, endSin, 0)
                }
        }
        DX.viz.gauges.CircularGauge = DX.viz.gauges.Gauge.inherit({
            _gaugeType: function() {
                return 'circular'
            },
            _defaultOptions: function() {
                return $extend(true, {}, this.callBase(), DEFAULT_GAUGE_OPTIONS)
            },
            _setupArea: function(area) {
                var self = this,
                    geometry = self.option('geometry'),
                    startAngle = geometry.startAngle,
                    endAngle = geometry.endAngle,
                    centerAngle;
                startAngle = isNumber(startAngle) ? normalizeAngle(startAngle) : self._defaultOpts.geometry.startAngle;
                endAngle = isNumber(endAngle) ? normalizeAngle(endAngle) : self._defaultOpts.geometry.endAngle;
                if (abs(startAngle - endAngle) < 1) {
                    centerAngle = (startAngle + endAngle) / 2;
                    if (startAngle <= endAngle) {
                        startAngle = centerAngle - 0.5;
                        endAngle = centerAngle - 360 + 0.5
                    }
                    else {
                        startAngle = centerAngle + 0.5;
                        endAngle = centerAngle - 0.5
                    }
                }
                else if (startAngle < endAngle)
                    endAngle -= 360;
                area.x = 0;
                area.y = 0;
                area.radius = 100;
                area.startCoord = startAngle;
                area.endCoord = endAngle;
                area.totalRadius = geometry.totalRadius > 0 ? Number(geometry.totalRadius) : self._defaultOpts.geometry.totalRadius;
                area.sides = getSides(startAngle, endAngle)
            },
            _getCreationOptions: function() {
                var result = this.callBase();
                result.type = 'circular';
                return result
            },
            _getCommonOptions: function() {
                var area = this._area;
                return $extend(true, this.callBase(), {
                        x: area.x,
                        y: area.y,
                        areaRadius: area.radius,
                        type: 'circular'
                    })
            },
            _combineOptions: function() {
                var args = [true, {}].concat(slice.apply(arguments)),
                    options = $extend.apply($, args);
                options.radius = round(options.areaRadius - Number(options.offset) || options.areaRadius);
                return options
            },
            _measureMainElements: function() {
                var self = this,
                    maxRadius = 0,
                    minRadius = Infinity,
                    maxHorizontalOffset = 0,
                    maxVerticalOffset = 0,
                    maxInverseHorizontalOffset = 0,
                    maxInverseVerticalOffset = 0;
                $each(self._mainElements, function(_, x) {
                    var bounds = x.measure();
                    bounds.min > 0 && (minRadius = min(minRadius, bounds.min));
                    bounds.max > 0 && (maxRadius = max(maxRadius, bounds.max));
                    bounds.horizontalOffset > 0 && (maxHorizontalOffset = max(maxHorizontalOffset, bounds.max + bounds.horizontalOffset));
                    bounds.verticalOffset > 0 && (maxVerticalOffset = max(maxVerticalOffset, bounds.max + bounds.verticalOffset));
                    bounds.inverseHorizontalOffset > 0 && (maxInverseHorizontalOffset = max(maxInverseHorizontalOffset, bounds.inverseHorizontalOffset));
                    bounds.inverseVerticalOffset > 0 && (maxInverseVerticalOffset = max(maxInverseVerticalOffset, bounds.inverseVerticalOffset))
                });
                maxHorizontalOffset = max(maxHorizontalOffset - maxRadius, 0);
                maxVerticalOffset = max(maxVerticalOffset - maxRadius, 0);
                return {
                        minRadius: minRadius,
                        maxRadius: maxRadius,
                        horizontalMargin: maxHorizontalOffset,
                        verticalMargin: maxVerticalOffset,
                        inverseHorizontalMargin: maxInverseHorizontalOffset,
                        inverseVerticalMargin: maxInverseVerticalOffset
                    }
            },
            _applyMainLayout: function(measurements) {
                var self = this,
                    area = self._area,
                    sides = area.sides,
                    margins = {
                        left: (sides.left < -0.1 ? measurements.horizontalMargin : measurements.inverseHorizontalMargin) || 0,
                        right: (sides.right > 0.1 ? measurements.horizontalMargin : measurements.inverseHorizontalMargin) || 0,
                        top: (sides.up < -0.1 ? measurements.verticalMargin : measurements.inverseVerticalMargin) || 0,
                        bottom: (sides.down > 0.1 ? measurements.verticalMargin : measurements.inverseVerticalMargin) || 0
                    },
                    rect = self._layoutManager.selectRectByAspectRatio((sides.down - sides.up) / (sides.right - sides.left), margins),
                    radius = min(rect.width() / (sides.right - sides.left), rect.height() / (sides.down - sides.up)),
                    x,
                    y;
                if (radius > area.totalRadius) {
                    rect = rect.scale(area.totalRadius / radius);
                    radius = area.totalRadius
                }
                radius = radius - measurements.maxRadius + area.radius;
                x = rect.left - rect.width() * sides.left / (sides.right - sides.left);
                y = rect.top - rect.height() * sides.up / (sides.down - sides.up);
                area.x = round(x);
                area.y = round(y);
                area.radius = radius;
                rect.left -= margins.left;
                rect.right += margins.right;
                rect.top -= margins.top;
                rect.bottom += margins.bottom;
                self._layoutManager.setRect(rect)
            },
            _renderMainElements: function() {
                var self = this,
                    x = self._area.x,
                    y = self._area.y,
                    r = self._area.radius;
                $each(self._mainElements, function(_, item) {
                    item.init({
                        x: x,
                        y: y,
                        radius: round(r - Number(item._options.offset) || r)
                    }).render()
                })
            },
            _createScale: function() {
                return factory.createCircularScale()
            },
            _createRangeContainer: function() {
                return factory.createCircularRangeContainer()
            },
            _createNeedle: function(type) {
                return factory.createCircularNeedle(type)
            },
            _createMarker: function(type) {
                return factory.createCircularMarker(type)
            },
            _createRangeBar: function() {
                return factory.createCircularRangeBar()
            },
            _createSpindle: function() {
                return factory.createCircularSpindle()
            },
            _prepareMainElements: function() {
                this.callBase();
                this._renderSpindle()
            },
            _renderSpindle: function() {
                var self = this;
                if (!self._spindle) {
                    self._spindle = self._createSpindle();
                    self._spindle.setup({
                        renderer: self._renderer,
                        owner: self._rootElement
                    })
                }
                self._spindle.init(self._combineOptions(self._commonOptions, self._defaultOpts.spindle, self._presetManager.getSpindlePreset(), self.option('spindle')));
                self._mainElements.push(self._spindle)
            },
            _getApproximateScreenRange: function() {
                var self = this,
                    area = self._area,
                    r = min(self._mainRect.width() / (area.sides.right - area.sides.left), self._mainRect.height() / (area.sides.down - area.sides.up));
                r > area.totalRadius && (r = area.totalRadius);
                r = 0.8 * r;
                return -area.translator.getCodomainRange() * r * PI / 180
            },
            _getDefaultContainerSize: function() {
                return {
                        width: 300,
                        height: 300
                    }
            }
        });
        DX.viz.gauges.__tests.getSides = getSides;
        DX.viz.gauges.__tests.DEFAULT_CIRCULAR_GAUGE_OPTIONS = DEFAULT_GAUGE_OPTIONS
    })(DevExpress, jQuery);
    /*! Module viz, file linearGauge.js */
    (function(DX, $, undefined) {
        var factory = DX.viz.gauges.__factory;
        var max = Math.max,
            min = Math.min,
            round = Math.round,
            slice = Array.prototype.slice,
            $extend = $.extend,
            $each = $.each;
        var DEFAULT_GAUGE_OPTIONS = {
                geometry: {
                    orientation: 'horizontal',
                    totalSize: undefined
                },
                scale: {
                    horizontalOrientation: 'right',
                    verticalOrientation: 'bottom',
                    label: {indentFromTick: -10}
                },
                rangeContainer: {
                    horizontalOrientation: 'right',
                    verticalOrientation: 'bottom'
                },
                commonNeedleSettings: {
                    offset: 2.5,
                    type: 'rhombus',
                    length: 15,
                    width: 15
                },
                commonMarkerSettings: {
                    offset: -1,
                    type: 'textcloud',
                    horizontalOrientation: 'left',
                    verticalOrientation: 'top'
                },
                commonRangeBarSettings: {
                    offset: 10,
                    horizontalOrientation: 'right',
                    verticalOrientation: 'bottom'
                }
            };
        DX.viz.gauges.LinearGauge = DX.viz.gauges.Gauge.inherit({
            _gaugeType: function() {
                return 'linear'
            },
            _defaultOptions: function() {
                return $extend(true, this.callBase(), DEFAULT_GAUGE_OPTIONS)
            },
            _setupArea: function(area) {
                var geometry = this.option('geometry');
                area.vertical = geometry.orientation === 'vertical';
                area.x = 0;
                area.y = 0;
                area.startCoord = -100;
                area.endCoord = 100;
                area.totalSize = geometry.totalSize > 0 ? Number(geometry.totalSize) : undefined
            },
            _getCreationOptions: function() {
                var result = this.callBase();
                result.type = 'linear';
                return result
            },
            _getCommonOptions: function() {
                var area = this._area;
                return $extend(true, this.callBase(), {
                        baseX: area.x,
                        baseY: area.y,
                        orientation: area.vertical ? 'vertical' : 'horizontal'
                    })
            },
            _combineOptions: function() {
                var args = [true, {}].concat(slice.apply(arguments)),
                    options = $extend.apply($, args);
                options.x = round(options.baseX + Number(options.offset) || options.baseX);
                options.y = round(options.baseY + Number(options.offset) || options.baseY);
                return options
            },
            _measureMainElements: function() {
                var self = this,
                    minBound = 1000,
                    maxBound = 0,
                    indent = 0;
                $each(self._mainElements, function(_, item) {
                    var bounds = item.measure();
                    maxBound = max(maxBound, bounds.max);
                    minBound = min(minBound, bounds.min);
                    if (bounds.indent > 0)
                        indent = max(indent, bounds.indent)
                });
                return {
                        minBound: minBound,
                        maxBound: maxBound,
                        indent: indent
                    }
            },
            _applyMainLayout: function(measurements) {
                var self = this,
                    area = self._area,
                    rect,
                    offset;
                if (area.vertical) {
                    rect = self._layoutManager.selectRectBySizes({
                        width: measurements.maxBound - measurements.minBound,
                        height: area.totalSize
                    });
                    offset = rect.horizontalMiddle() - (measurements.minBound + measurements.maxBound) / 2;
                    area.startCoord = rect.bottom - measurements.indent;
                    area.endCoord = rect.top + measurements.indent;
                    area.x = round(area.x + offset)
                }
                else {
                    rect = self._layoutManager.selectRectBySizes({
                        height: measurements.maxBound - measurements.minBound,
                        width: area.totalSize
                    });
                    offset = rect.verticalMiddle() - (measurements.minBound + measurements.maxBound) / 2;
                    area.startCoord = rect.left + measurements.indent;
                    area.endCoord = rect.right - measurements.indent;
                    area.y = round(area.y + offset)
                }
                area.translator = factory.createTranslator(area.startCoord, area.endCoord, area.startValue, area.endValue);
                self._layoutManager.setRect(rect)
            },
            _renderMainElements: function() {
                var self = this,
                    x = self._area.x,
                    y = self._area.y,
                    translator = self._area.translator;
                $each(self._mainElements, function(_, item) {
                    item.init({
                        x: round(x + Number(item._options.offset) || x),
                        y: round(y + Number(item._options.offset) || y),
                        translator: translator
                    }).render()
                })
            },
            _createScale: function() {
                return factory.createLinearScale()
            },
            _createRangeContainer: function() {
                return factory.createLinearRangeContainer()
            },
            _createNeedle: function(type) {
                return factory.createLinearNeedle(type)
            },
            _createMarker: function(type) {
                return factory.createLinearMarker(type)
            },
            _createRangeBar: function() {
                return factory.createLinearRangeBar()
            },
            _getApproximateScreenRange: function() {
                var self = this,
                    area = self._area,
                    s = area.vertical ? self._mainRect.height() : self._mainRect.width();
                s > area.totalSize && (s = area.totalSize);
                s = s * 0.8;
                return s
            },
            _getDefaultContainerSize: function() {
                var geometry = this.option('geometry');
                if (geometry.orientation === 'vertical')
                    return {
                            width: 100,
                            height: 300
                        };
                else
                    return {
                            width: 300,
                            height: 100
                        }
            }
        });
        DX.viz.gauges.__tests.DEFAULT_LINEAR_GAUGE_OPTIONS = DEFAULT_GAUGE_OPTIONS
    })(DevExpress, jQuery);
    /*! Module viz, file tooltip.js */
    (function(DX, $, undefined) {
        var formatHelper = DX.formatHelper;
        var Number = window.Number,
            String = window.String,
            isFunction = DX.utils.isFunction,
            round = Math.round,
            $extend = $.extend;
        var SHADOW_OFFSET = 4;
        var MASKS = {
                up: [-0.5, -1, -1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, 1],
                down: [0.5, 1, 1, 0, 0, 1, -1, 0, 0, -1, 1, 0, 0, -1],
                left: [-1, 0.5, 0, 1, -1, 0, 0, -1, 1, 0, 0, 1, 1, 0],
                right: [1, -0.5, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0]
            };
        DX.viz.gauges.__internals.Tooltip = DX.Class.inherit({
            setup: function(gauge) {
                var self = this;
                DX.utils.debug.assertParam(gauge, '"gauge" parameter');
                self._gauge = gauge;
                self._renderer = gauge._renderer;
                self._options = {};
                return self
            },
            init: function(options) {
                var self = this;
                $extend(true, self._options, options);
                return self
            },
            render: function() {
                var self = this;
                if (self._options.enabled) {
                    self._rootElement = self._rootElement || self._renderer.createGroup({'class': 'tooltip'});
                    self._rootElement.append(self._gauge._rootElement);
                    self._shadow = self._shadow || self._renderer.createArea().append(self._rootElement);
                    self._cloud = self._cloud || self._renderer.createArea().append(self._rootElement);
                    self._text = self._text || self._renderer.createText().append(self._rootElement);
                    self._shadow.applySettings({
                        stroke: 'none',
                        strokeWidth: 0,
                        fill: '#000000',
                        opacity: 0.1
                    });
                    self._cloud.applySettings({
                        stroke: 'none',
                        strokeWidth: 0
                    });
                    self._text.applySettings({
                        align: 'center',
                        font: self._options.font
                    });
                    self._rootElement.applySettings({visibility: 'hidden'});
                    self._visible = false
                }
                else
                    self.clear();
                return self
            },
            clear: function() {
                var self = this;
                if (self._rootElement) {
                    self._rootElement.remove();
                    delete self._rootElement;
                    delete self._shadow;
                    delete self._cloud;
                    delete self._text
                }
                return self
            },
            _formatValue: function(value, context) {
                var options = this._options,
                    text = formatHelper.format(value, options.format, options.precision);
                if (isFunction(options.customizeText)) {
                    var target = $extend(true, context || {}, {
                            value: value,
                            valueText: text
                        });
                    return String(options.customizeText.call(target, target))
                }
                return text
            },
            _selectMask: function(x, y, width, height, arrowLength) {
                var rect = this._gauge._rootRect,
                    mask;
                if (x + width / 2 > rect.right)
                    mask = MASKS.left;
                else if (x - width / 2 < rect.left)
                    mask = MASKS.right;
                else if (y - arrowLength - height < rect.top)
                    mask = MASKS.down;
                else
                    mask = MASKS.up;
                return mask
            },
            _getSettings: function(x, y, textWidth, textHeight, offset) {
                var options = this._options,
                    cloudWidth = textWidth + 2 * Number(options.horizontalPadding),
                    cloudHeight = textHeight + 2 * Number(options.verticalPadding),
                    arrowLength = Number(options.arrowLength),
                    mask = this._selectMask(x, y, cloudWidth, cloudHeight, arrowLength),
                    i,
                    cloudPoints,
                    shadowPoints,
                    cx,
                    cy;
                cloudPoints = [cx = round(x - mask[12] * offset), cy = round(y - mask[13] * offset), cx += round(mask[0] * arrowLength), cy += round(mask[1] * arrowLength), cx += round(mask[2] * (cloudWidth - arrowLength) / 2), cy += round(mask[3] * (cloudHeight - arrowLength) / 2), cx += round(mask[4] * cloudWidth), cy += round(mask[5] * cloudHeight), cx += round(mask[6] * cloudWidth), cy += round(mask[7] * cloudHeight), cx += round(mask[8] * cloudWidth), cy += round(mask[9] * cloudHeight), cx += round(mask[10] * (cloudWidth - arrowLength) / 2), cy += round(mask[11] * (cloudHeight - arrowLength) / 2)];
                shadowPoints = cloudPoints.slice(0);
                cx = round(mask[12] * SHADOW_OFFSET);
                cy = round(mask[13] * SHADOW_OFFSET);
                for (i = 0; i < 14; i += 2) {
                    shadowPoints[i] += cx;
                    shadowPoints[i + 1] += cy
                }
                cx = round(x - mask[12] * (arrowLength + cloudWidth / 2 + offset));
                cy = round(y - mask[13] * (arrowLength + cloudHeight / 2 + offset)) - 2;
                return {
                        x: cx,
                        y: cy,
                        cloudPoints: cloudPoints,
                        shadowPoints: shadowPoints
                    }
            },
            show: function(parameters) {
                parameters = parameters || {};
                var self = this,
                    text = self._formatValue(parameters.value, parameters.context),
                    box,
                    settings;
                self._text.applySettings({
                    text: text,
                    x: 0,
                    y: 0
                });
                box = self._text.getBBox();
                settings = self._getSettings(parameters.x, parameters.y, box.width, box.height, parameters.offset || 0);
                self._shadow.applySettings({points: settings.shadowPoints});
                self._cloud.applySettings({
                    points: settings.cloudPoints,
                    fill: parameters.color
                });
                self._text.applySettings({
                    x: settings.x,
                    y: round(settings.y - box.y - box.height / 2 + 2)
                });
                !self._visible && self._rootElement.applySettings({visibility: 'visible'}) && (self._visible = true);
                return self
            },
            hide: function() {
                var self = this;
                self._visible && self._rootElement.applySettings({visibility: 'hidden'}) && (self._visible = false);
                return self
            },
            enabled: function() {
                return !!this._rootElement
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz, file tracker.js */
    (function(DX, $, undefined) {
        var setTimeout = window.setTimeout,
            clearTimeout = window.clearTimeout,
            Number = window.Number,
            $extend = $.extend,
            $each = $.each,
            abs = Math.abs;
        function handleMouseOver(event) {
            var tracker = event.data.tracker;
            if (tracker._context !== null)
                tracker._processLeave();
            tracker._context = event.data;
            tracker._processEnter(event)
        }
        function handleMouseOut(event) {
            var tracker = event.data.tracker;
            if (tracker._context !== null) {
                tracker._processLeave();
                tracker._context = null
            }
        }
        function handleMouseMove(event) {
            event.data.tracker._processMove(event)
        }
        var HOVER_DELAY = 200;
        var HOVER_SENSITIVITY = 3;
        var mouseOverOutEvents = {
                mouseover: handleMouseOver,
                mouseout: handleMouseOut
            };
        var mouseMoveEvents = {mousemove: handleMouseMove};
        DX.viz.gauges.__internals.Tracker = DX.Class.inherit({
            setup: function(gauge) {
                var self = this;
                DX.utils.debug.assertParam(gauge, '"gauge" parameter');
                self._gauge = gauge;
                self._listeners = [];
                self._context = null;
                self._options = {};
                self._waitHoverCallback = function() {
                    self._context.element.off(mouseMoveEvents);
                    self._context.hover = true;
                    self._processHoverOn()
                };
                return self
            },
            init: function(options) {
                $extend(true, this._options, options);
                return this
            },
            activate: function() {
                var self = this;
                self._detachListeners();
                if (self._gauge._tooltip.enabled())
                    self._attachListeners();
                self._gauge._trackerGroup.toForeground();
                self._tooltipDelay = self._options.tooltipDelay >= 0 ? Number(self._options.tooltipDelay) : 0;
                return self
            },
            _attachListeners: function() {
                var self = this;
                $each(self._gauge._getTrackedElements(), function(_, item) {
                    var element;
                    if (item.target.getTrackingElement) {
                        element = item.target.getTrackingElement();
                        if (element) {
                            self._listeners.push(element);
                            element.on(mouseOverOutEvents, {
                                tracker: self,
                                element: element,
                                target: item.target,
                                info: item.info
                            })
                        }
                    }
                })
            },
            _detachListeners: function() {
                var self = this;
                $each(self._listeners, function(_, item) {
                    item.off()
                });
                self._listeners.length = 0
            },
            _processEnter: function(event) {
                var self = this,
                    context = self._context;
                context.x = event.pageX;
                context.y = event.pageY;
                context.element.on(mouseMoveEvents, context);
                context.hoverTimeout = setTimeout(self._waitHoverCallback, HOVER_DELAY)
            },
            _processLeave: function() {
                var self = this;
                self._context.element.off(mouseMoveEvents);
                clearTimeout(self._context.hoverTimeout);
                self._context.hover && self._processHoverOff();
                delete self._context.hover
            },
            _processMove: function(event) {
                var self = this,
                    context = self._context;
                if (abs(event.pageX - context.x) > HOVER_SENSITIVITY || abs(event.pageY - context.y) > HOVER_SENSITIVITY) {
                    context.x = event.pageX;
                    context.y = event.pageY;
                    clearTimeout(context.hoverTimeout);
                    context.hoverTimeout = setTimeout(self._waitHoverCallback, HOVER_DELAY)
                }
            },
            _processHoverOn: function() {
                this._gauge._tooltip.show($extend(true, this._context.target.getTooltipParameters(), {context: this._context.info}));
                this._debug_hoverOn && this._debug_hoverOn(this._context)
            },
            _processHoverOff: function() {
                this._gauge._tooltip.hide();
                this._debug_hoverOff && this._debug_hoverOff(this._context)
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz, file namespaces.js */
    (function(DevExpress) {
        DevExpress.viz.rangeSelector = {utils: {}}
    })(DevExpress);
    /*! Module viz, file baseVisualElement.js */
    (function(DX) {
        DevExpress.viz.rangeSelector.BaseVisualElement = DX.Class.inherit({
            ctor: function(renderer) {
                this._renderer = renderer;
                this._isDrawn = false
            },
            applyOptions: function(options) {
                this._options = options || {};
                this._applyOptions(this._options)
            },
            _applyOptions: function(options){},
            redraw: function(group) {
                var self = this;
                if (!self._isDrawn) {
                    self._isDrawn = !(self._draw(group || self._group) === false);
                    if (group)
                        self._group = group
                }
                else
                    self._update(group || self._group)
            },
            isDrawn: function() {
                return !!this._isDrawn
            },
            isInitialized: function() {
                return !!this._options
            },
            _draw: function(group){},
            _update: function(group) {
                group.clear();
                this._draw(group)
            }
        })
    })(DevExpress);
    /*! Module viz, file rangeSelector.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            core = DX.viz.core,
            utils = DX.utils,
            dataUtils = DX.data.utils,
            rangeSelectorUtils = rangeSelector.utils,
            ParseUtils = DX.viz.core.ParseUtils,
            formatHelper = DX.formatHelper;
        var REDRAW_DELAY = 100;
        rangeSelector.consts = {
            fontHeightRatio: 0.55,
            emptySliderMarkerText: '. . .'
        };
        rangeSelector.formatValue = function(value, formatOptions) {
            var formatObject = {
                    value: value,
                    valueText: formatHelper.format(value, formatOptions.format, formatOptions.precision)
                };
            return String(formatOptions.customizeText ? formatOptions.customizeText.call(formatObject, formatObject) : formatObject.valueText)
        };
        rangeSelector.RangeSelector = DX.ui.Component.inherit(function() {
            var SCALE_TEXT_SPACING = 5;
            var defaultRangeSelectorOptions = {
                    size: undefined,
                    margin: {
                        left: 0,
                        top: 0,
                        right: 0,
                        bottom: 0
                    },
                    scale: {
                        showCustomBoundaryTicks: true,
                        showMinorTicks: true,
                        startValue: undefined,
                        endValue: undefined,
                        minorTickCount: undefined,
                        minorTickInterval: undefined,
                        majorTickInterval: undefined,
                        useTicksAutoArrangement: true,
                        setTicksAtUnitBeginning: true,
                        minRange: undefined,
                        maxRange: undefined,
                        placeholderHeight: undefined,
                        valueType: undefined,
                        label: {
                            visible: true,
                            format: undefined,
                            precision: undefined,
                            customizeText: undefined
                        },
                        marker: {
                            visible: true,
                            label: {
                                format: undefined,
                                precision: undefined,
                                customizeText: undefined
                            }
                        }
                    },
                    selectedRange: undefined,
                    sliderMarker: {
                        visible: true,
                        format: undefined,
                        precision: undefined,
                        customizeText: undefined,
                        placeholderSize: undefined
                    },
                    behavior: {
                        snapToTicks: true,
                        animationEnabled: true,
                        moveSelectedRangeByClick: true,
                        manualRangeSelectionEnabled: true,
                        allowSlidersSwap: true,
                        callSelectedRangeChanged: "onMovingComplete"
                    },
                    background: {
                        color: "#C0BAE1",
                        visible: true,
                        image: {
                            url: undefined,
                            location: 'full'
                        }
                    },
                    chart: {
                        commonSeriesSettings: {
                            type: 'area',
                            label: {visible: false},
                            hoverMode: 'none'
                        },
                        equalBarWidth: true,
                        topIndent: 0.1,
                        bottomIndent: 0,
                        valueAxis: {
                            min: undefined,
                            max: undefined,
                            inverted: false
                        },
                        series: undefined
                    },
                    dataSource: undefined,
                    dataSourceField: 'arg',
                    redrawOnResize: true,
                    theme: undefined,
                    selectedRangeChanged: null,
                    incidentOccured: $.noop
                };
            var calculateMarkerSize = function(renderer, value, sliderMarkerOptions) {
                    var formattedText = value === undefined ? rangeSelector.consts.emptySliderMarkerText : rangeSelector.formatValue(value, sliderMarkerOptions),
                        textBBox = rangeSelectorUtils.getTextBBox(renderer, formattedText, sliderMarkerOptions.font);
                    return {
                            width: Math.ceil(textBBox.width) + 2 * sliderMarkerOptions.padding,
                            height: Math.ceil(textBBox.height * rangeSelector.consts.fontHeightRatio) + 2 * sliderMarkerOptions.padding + sliderMarkerOptions.pointerSize
                        }
                };
            var calculateScaleLabelHalfWidth = function(renderer, value, scaleOptions) {
                    var formattedText = rangeSelector.formatValue(value, scaleOptions.label),
                        textBBox = rangeSelectorUtils.getTextBBox(renderer, formattedText, scaleOptions.label.font);
                    return Math.ceil(textBBox.width / 2)
                };
            var calculateRangeContainerCanvas = function(size, margin, sliderMarkerSpacing) {
                    var canvas = {
                            left: margin.left + sliderMarkerSpacing.left,
                            top: margin.top + sliderMarkerSpacing.top,
                            width: size.width - margin.left - margin.right - sliderMarkerSpacing.left - sliderMarkerSpacing.right,
                            height: size.height - margin.top - margin.bottom - sliderMarkerSpacing.top - sliderMarkerSpacing.bottom
                        };
                    if (canvas.width <= 0)
                        canvas.width = 1;
                    return canvas
                };
            var parseSliderMarkersPlaceholderSize = function(placeholderSize) {
                    var placeholderWidthLeft,
                        placeholderWidthRight,
                        placeholderHeight;
                    if (utils.isNumber(placeholderSize))
                        placeholderWidthLeft = placeholderWidthRight = placeholderHeight = placeholderSize;
                    else if (placeholderSize) {
                        if (utils.isNumber(placeholderSize.height))
                            placeholderHeight = placeholderSize.height;
                        if (utils.isNumber(placeholderSize.width))
                            placeholderWidthLeft = placeholderWidthRight = placeholderSize.width;
                        else if (placeholderSize.width) {
                            if (utils.isNumber(placeholderSize.width.left))
                                placeholderWidthLeft = placeholderSize.width.left;
                            if (utils.isNumber(placeholderSize.width.right))
                                placeholderWidthRight = placeholderSize.width.right
                        }
                    }
                    return {
                            widthLeft: placeholderWidthLeft,
                            widthRight: placeholderWidthRight,
                            height: placeholderHeight
                        }
                };
            var calculateSliderMarkersSpacing = function(renderer, size, scale, sliderMarkerOptions) {
                    var leftMarkerSize,
                        leftScaleLabelWidth = 0,
                        rightScaleLabelWidth = 0,
                        rightMarkerSize,
                        canvas,
                        placeholderWidthLeft = 0,
                        placeholderWidthRight = 0,
                        placeholderHeight = 0,
                        parsedPlaceholderSize;
                    parsedPlaceholderSize = parseSliderMarkersPlaceholderSize(sliderMarkerOptions.placeholderSize);
                    placeholderWidthLeft = parsedPlaceholderSize.widthLeft || 0;
                    placeholderWidthRight = parsedPlaceholderSize.widthRight || 0;
                    placeholderHeight = parsedPlaceholderSize.height || 0;
                    if (sliderMarkerOptions.visible) {
                        leftMarkerSize = calculateMarkerSize(renderer, scale.startValue, sliderMarkerOptions);
                        if (!placeholderWidthLeft)
                            placeholderWidthLeft = leftMarkerSize.width;
                        rightMarkerSize = calculateMarkerSize(renderer, scale.endValue, sliderMarkerOptions);
                        if (!placeholderWidthRight)
                            placeholderWidthRight = rightMarkerSize.width;
                        if (!placeholderHeight)
                            placeholderHeight = Math.max(leftMarkerSize.height, rightMarkerSize.height)
                    }
                    if (scale.label.visible) {
                        leftScaleLabelWidth = calculateScaleLabelHalfWidth(renderer, scale.startValue, scale);
                        rightScaleLabelWidth = calculateScaleLabelHalfWidth(renderer, scale.endValue, scale)
                    }
                    placeholderWidthLeft = Math.max(placeholderWidthLeft, leftScaleLabelWidth);
                    placeholderWidthRight = Math.max(placeholderWidthRight, rightScaleLabelWidth);
                    return {
                            left: placeholderWidthLeft,
                            right: placeholderWidthRight,
                            top: placeholderHeight,
                            bottom: 0
                        }
                };
            var clearContainer = function(container) {
                    if (container)
                        container.empty()
                };
            var getContainer = function(self) {
                    return self._element()
                };
            var createRangeContainer = function(rangeContainerOptions) {
                    return rangeSelector.rangeSelectorFactory.createRangeContainer(rangeContainerOptions)
                };
            var createTranslator = function(range, canvas) {
                    return rangeSelector.rangeSelectorFactory.createTranslator(range, canvas)
                };
            var createTranslatorCanvas = function(sizeOptions, rangeContainerCanvas, scaleLabelsAreaHeight) {
                    return {
                            left: rangeContainerCanvas.left,
                            top: rangeContainerCanvas.top,
                            right: sizeOptions.width - rangeContainerCanvas.width - rangeContainerCanvas.left,
                            bottom: sizeOptions.height - rangeContainerCanvas.height - rangeContainerCanvas.top + scaleLabelsAreaHeight,
                            width: sizeOptions.width,
                            height: sizeOptions.height
                        }
                };
            var createRenderer = function(self) {
                    var renderer = self.option('renderer');
                    if (renderer)
                        return renderer;
                    renderer = rangeSelector.rangeSelectorFactory.createRenderer();
                    return renderer
                };
            var createThemeManager = function(theme) {
                    return rangeSelector.rangeSelectorFactory.createThemeManager(theme)
                };
            var calculateValueType = function(firstValue, secondValue) {
                    var types = [$.type(firstValue), $.type(secondValue)];
                    $.inArray();
                    return $.inArray('date', types) != -1 ? 'datetime' : $.inArray('number', types) != -1 ? 'numeric' : ''
                };
            var createSeriesDataSource = function(self) {
                    var seriesDataSource,
                        dataSource = self._dataSource && self._dataSource.items(),
                        scaleOptions = self.option('scale'),
                        valueType = scaleOptions.valueType;
                    if (!valueType)
                        valueType = calculateValueType(scaleOptions.startValue, scaleOptions.endValue);
                    if (dataSource || self.option('chart').series)
                        seriesDataSource = new rangeSelector.SeriesDataSource({
                            renderer: self.renderer,
                            dataSource: dataSource,
                            valueType: (valueType || '').toLowerCase(),
                            chart: self.option('chart'),
                            dataSourceField: self.option('dataSourceField'),
                            backgroundColor: self._userBackgroundColor,
                            incidentOccured: self.option('incidentOccured')
                        });
                    return seriesDataSource
                };
            var calculateTranslatorRange = function(self, seriesDataSource, scaleOptions) {
                    var translatorRange,
                        minValue,
                        maxValue,
                        inverted = false;
                    if (utils.isDefined(scaleOptions.startValue) && utils.isDefined(scaleOptions.endValue)) {
                        inverted = scaleOptions.inverted = scaleOptions.startValue > scaleOptions.endValue;
                        minValue = inverted ? scaleOptions.endValue : scaleOptions.startValue;
                        maxValue = inverted ? scaleOptions.startValue : scaleOptions.endValue
                    }
                    else if (utils.isDefined(scaleOptions.startValue) || utils.isDefined(scaleOptions.endValue)) {
                        minValue = scaleOptions.startValue;
                        maxValue = scaleOptions.endValue
                    }
                    translatorRange = seriesDataSource ? seriesDataSource.getBoundRange() : new DX.viz.charts.Range;
                    if (minValue !== maxValue) {
                        translatorRange.invertX = inverted;
                        translatorRange.getBoundRange({
                            minX: minValue,
                            maxX: maxValue,
                            minVisibleX: minValue,
                            maxVisibleX: maxValue
                        })
                    }
                    if (!translatorRange.isDefinedX())
                        translatorRange.setStubDataX(scaleOptions.valueType);
                    return translatorRange
                };
            var calculateScaleAreaHeight = function(renderer, scaleOptions, visibleMarkers) {
                    var textBBox,
                        visibleLabels = scaleOptions.label.visible;
                    if (scaleOptions.placeholderHeight)
                        return scaleOptions.placeholderHeight;
                    else {
                        textBBox = rangeSelectorUtils.getTextBBox(renderer, '0', scaleOptions.label.font);
                        return (visibleLabels ? scaleOptions.label.topIndent + textBBox.height : 0) + (visibleMarkers ? scaleOptions.marker.topIndent + scaleOptions.marker.separatorHeight : 0)
                    }
                };
            var getTicksInfo = function(self, scaleOptions, translator, screenDelta) {
                    var isEmpty = scaleOptions.isEmpty,
                        tickProvider = rangeSelector.rangeSelectorFactory.getTickProvider(),
                        minorTicksOptions,
                        majorTicksOptions,
                        startValue,
                        endValue,
                        businessRange = translator.getBusinessRange();
                    minorTicksOptions = {
                        tickInterval: isEmpty ? 0 : self.option('scale').minorTickInterval,
                        showCustomBoundaryTicks: scaleOptions.showCustomBoundaryTicks,
                        minorTickCount: scaleOptions.minorTickCount
                    };
                    majorTicksOptions = {
                        textOptions: {
                            align: 'center',
                            font: scaleOptions.label.font
                        },
                        renderer: self.renderer,
                        getText: function(value) {
                            return rangeSelector.formatValue(value, scaleOptions.label)
                        },
                        translator: translator,
                        isStartTickGenerated: !utils.isDefined(self.option('scale').majorTickInterval),
                        tickInterval: scaleOptions.majorTickInterval,
                        textSpacing: SCALE_TEXT_SPACING,
                        setTicksAtUnitBeginning: scaleOptions.setTicksAtUnitBeginning,
                        useTicksAutoArrangement: scaleOptions.useTicksAutoArrangement,
                        hideLabels: isEmpty
                    };
                    startValue = isEmpty ? businessRange.minX : scaleOptions.startValue;
                    endValue = isEmpty ? businessRange.maxX : scaleOptions.endValue;
                    return tickProvider.getFullTicks(startValue, endValue, screenDelta, majorTicksOptions, minorTicksOptions)
                };
            var updateTickIntervals = function(scaleOptions, screenDelta, incidentOccured) {
                    var tickProvider = rangeSelector.rangeSelectorFactory.getTickProvider(),
                        tickIntervals = tickProvider.getTickIntervals(scaleOptions.startValue, scaleOptions.endValue, screenDelta, {
                            tickInterval: scaleOptions.majorTickInterval,
                            incidentOccured: incidentOccured
                        }, {
                            tickInterval: scaleOptions.minorTickInterval,
                            incidentOccured: incidentOccured
                        });
                    scaleOptions.minorTickInterval = tickIntervals.minorTickInterval;
                    scaleOptions.majorTickInterval = tickIntervals.majorTickInterval
                };
            var updateScaleOptions = function(self, seriesDataSource, translatorRange, screenDelta, scaleOptions) {
                    var minVisibleX = utils.isDefined(translatorRange.minVisibleX) ? translatorRange.minVisibleX : translatorRange.minX,
                        maxVisibleX = utils.isDefined(translatorRange.maxVisibleX) ? translatorRange.maxVisibleX : translatorRange.maxX;
                    if (seriesDataSource && !seriesDataSource.isEmpty()) {
                        scaleOptions.startValue = scaleOptions.inverted ? maxVisibleX : minVisibleX;
                        scaleOptions.endValue = scaleOptions.inverted ? minVisibleX : maxVisibleX
                    }
                    scaleOptions.isEmpty = !utils.isDefined(scaleOptions.startValue) || !utils.isDefined(scaleOptions.endValue) || scaleOptions.startValue === scaleOptions.endValue || scaleOptions.valueType === 'string';
                    if (scaleOptions.isEmpty)
                        scaleOptions.startValue = scaleOptions.endValue = undefined;
                    else {
                        updateTickIntervals(scaleOptions, screenDelta, self.option('incidentOccured'));
                        if (scaleOptions.valueType === 'datetime' && !utils.isDefined(scaleOptions.label.format))
                            if (!scaleOptions.marker.visible)
                                scaleOptions.label.format = formatHelper.getDateFormatByTickInterval(scaleOptions.startValue, scaleOptions.endValue, scaleOptions.majorTickInterval);
                            else
                                scaleOptions.label.format = utils.getDateUnitInterval(scaleOptions.majorTickInterval)
                    }
                };
            var prepareSliderMarkersOptions = function(self, scaleOptions, screenDelta) {
                    var sliderMarkerOptions = $.extend(true, {}, self.option('sliderMarker')),
                        businessInterval;
                    if (!sliderMarkerOptions.format) {
                        if (!self.option('behavior').snapToTicks && utils.isNumber(scaleOptions.startValue)) {
                            businessInterval = Math.abs(scaleOptions.endValue - scaleOptions.startValue);
                            sliderMarkerOptions.format = 'fixedPoint';
                            sliderMarkerOptions.precision = utils.getSignificantDigitPosition(businessInterval / screenDelta)
                        }
                        if (scaleOptions.valueType === 'datetime')
                            if (!scaleOptions.marker.visible)
                                sliderMarkerOptions.format = formatHelper.getDateFormatByTickInterval(scaleOptions.startValue, scaleOptions.endValue, scaleOptions.minorTickInterval !== 0 ? scaleOptions.minorTickInterval : scaleOptions.majorTickInterval);
                            else
                                sliderMarkerOptions.format = utils.getDateUnitInterval(utils.isDefined(scaleOptions.minorTickInterval) && scaleOptions.minorTickInterval !== 0 ? scaleOptions.minorTickInterval : scaleOptions.majorTickInterval)
                    }
                    return sliderMarkerOptions
                };
            var showScaleMarkers = function(scaleOptions) {
                    return scaleOptions.valueType == 'datetime' && scaleOptions.marker.visible
                };
            var updateTranslatorRangeInterval = function(translatorRange, scaleOptions) {
                    var intervalX = scaleOptions.minorTickInterval || scaleOptions.majorTickInterval;
                    translatorRange = translatorRange.getBoundRange({intervalX: intervalX})
                };
            var prepareScaleOptions = function(self, seriesDataSource) {
                    var scaleOptions = $.extend(true, {}, self.option('scale')),
                        incidentOccured = self.option('incidentOccured'),
                        parsedValue = 0,
                        parseUtils = new ParseUtils({incidentOccured: incidentOccured}),
                        valueType = parseUtils.correctValueType((scaleOptions.valueType || '').toLowerCase());
                    if (seriesDataSource)
                        valueType = seriesDataSource.getCalculatedValueType() || valueType;
                    if (!valueType)
                        valueType = calculateValueType(scaleOptions.startValue, scaleOptions.endValue) || 'numeric';
                    scaleOptions.valueType = valueType;
                    if (scaleOptions.valueType === 'string') {
                        incidentOccured('The type of the argument values specified in the data source is unsupported.');
                        return scaleOptions
                    }
                    var parser = parseUtils.getParser(valueType, 'scale');
                    if (utils.isDefined(scaleOptions.startValue)) {
                        parsedValue = parser(scaleOptions.startValue);
                        if (utils.isDefined(parsedValue))
                            scaleOptions.startValue = parsedValue;
                        else {
                            scaleOptions.startValue = undefined;
                            incidentOccured.call(null, "Cannot parse the value specified as the startValue property of the scale configuration object.")
                        }
                    }
                    if (utils.isDefined(scaleOptions.endValue)) {
                        parsedValue = parser(scaleOptions.endValue);
                        if (utils.isDefined(parsedValue))
                            scaleOptions.endValue = parsedValue;
                        else {
                            scaleOptions.endValue = undefined;
                            incidentOccured.call(null, "Cannot parse the value specified as the endValue property of the scale configuration object.")
                        }
                    }
                    scaleOptions.parser = parser;
                    return scaleOptions
                };
            var correctSizeOptions = function(self, sizeOptions, scaleOptions) {
                    var size = self.option('size') || {};
                    if (!sizeOptions.height && size.height !== 0)
                        if (scaleOptions.valueType === 'datetime' && scaleOptions.marker.visible !== false)
                            sizeOptions.height = 160;
                        else
                            sizeOptions.height = 120;
                    if (!sizeOptions.width && size.width !== 0)
                        sizeOptions.width = 400
                };
            var applyOptions = function(self) {
                    var rangeContainerCanvas,
                        seriesDataSource,
                        translatorRange,
                        scaleLabelsAreaHeight,
                        sizeOptions,
                        sliderMarkerSpacing,
                        sliderMarkerOptions,
                        selectedRange,
                        $container = self.container,
                        isEmpty;
                    self._isUpdating = true;
                    sizeOptions = calculateSize(self);
                    self._actualSize = sizeOptions;
                    seriesDataSource = createSeriesDataSource(self);
                    self._scaleOptions = prepareScaleOptions(self, seriesDataSource);
                    correctSizeOptions(self, sizeOptions, self._scaleOptions);
                    if (!sizeOptions.width || !sizeOptions.height || !$container.is(':visible')) {
                        self.stopRedraw = true;
                        self.option('incidentOccured')('RangeSelector can not be drawn as container is not visible');
                        return
                    }
                    else
                        self.stopRedraw = false;
                    updateRendererSize(self, sizeOptions);
                    translatorRange = calculateTranslatorRange(self, seriesDataSource, self._scaleOptions);
                    updateScaleOptions(self, seriesDataSource, translatorRange, sizeOptions.width, self._scaleOptions);
                    updateTranslatorRangeInterval(translatorRange, self._scaleOptions);
                    sliderMarkerOptions = prepareSliderMarkersOptions(self, self._scaleOptions, sizeOptions.width);
                    selectedRange = initSelection(self, self._scaleOptions);
                    sliderMarkerSpacing = calculateSliderMarkersSpacing(self.renderer, sizeOptions, self._scaleOptions, sliderMarkerOptions);
                    rangeContainerCanvas = calculateRangeContainerCanvas(sizeOptions, self.option('margin'), sliderMarkerSpacing);
                    scaleLabelsAreaHeight = calculateScaleAreaHeight(self.renderer, self._scaleOptions, showScaleMarkers(self._scaleOptions));
                    self.translator = createTranslator(translatorRange, createTranslatorCanvas(sizeOptions, rangeContainerCanvas, scaleLabelsAreaHeight));
                    self._scaleOptions.ticksInfo = getTicksInfo(self, self._scaleOptions, self.translator, rangeContainerCanvas.width);
                    self._testTicksInfo = self._scaleOptions.ticksInfo;
                    self._selectedRange = selectedRange;
                    if (seriesDataSource)
                        seriesDataSource.adjustSeriesDimensions(self.translator);
                    self.rangeContainer.applyOptions({
                        canvas: rangeContainerCanvas,
                        scaleLabelsAreaHeight: scaleLabelsAreaHeight,
                        sliderMarkerSpacing: sliderMarkerSpacing,
                        translator: self.translator,
                        selectedRange: selectedRange,
                        scale: self._scaleOptions,
                        behavior: self.option('behavior'),
                        background: self.option('background'),
                        chart: self.option('chart'),
                        seriesDataSource: seriesDataSource,
                        sliderMarker: sliderMarkerOptions,
                        sliderHandle: self.option('sliderHandle'),
                        shutter: self.option('shutter'),
                        selectedRangeChanged: createSelectedRangeChangedFunction(self),
                        setSelectedRange: function(selectedRange) {
                            self.setSelectedRange(selectedRange)
                        }
                    });
                    self._isUpdating = false
                };
            var createSelectedRangeChangedFunction = function(self) {
                    return function(selectedRange, blockSelectedRangeChanged) {
                            var selectedRangeChanged = self.option('selectedRangeChanged');
                            self.option('selectedRange', selectedRange);
                            if (selectedRangeChanged && !blockSelectedRangeChanged)
                                selectedRangeChanged(selectedRange)
                        }
                };
            var calculateSize = function(self) {
                    var $container = self.container,
                        size = self.option('size') || {},
                        result = {
                            width: size.width,
                            height: size.height
                        };
                    if ($container) {
                        if (!result.width)
                            result.width = $container.width();
                        if (!result.height)
                            result.height = $container.height()
                    }
                    return result
                };
            var updateRendererSize = function(self, size) {
                    var renderer = self.renderer;
                    if (renderer.isInitialized())
                        renderer.getRoot().applySettings({
                            width: size.width,
                            height: size.height
                        });
                    else {
                        renderer.recreateCanvas(size.width, size.height);
                        renderer.draw(self.container[0])
                    }
                };
            var prepareChartThemeOptions = function(self, options) {
                    var chartTheme;
                    if (!self.option('chart').theme && options && options.theme) {
                        chartTheme = options.theme;
                        if (chartTheme) {
                            if (typeof chartTheme === 'object') {
                                chartTheme = chartTheme.chart || {};
                                chartTheme.name = options.theme.name
                            }
                            self.option('chart').theme = chartTheme
                        }
                    }
                };
            var initSelection = function(self, scaleOptions) {
                    var selectedRangeOptions = self.option('selectedRange'),
                        parser = scaleOptions.parser || function() {
                            return null
                        },
                        parseValue = function(value, entity) {
                            var parsedValue,
                                result = scaleOptions[entity];
                            if (utils.isDefined(value))
                                parsedValue = parser(value);
                            if (!utils.isDefined(parsedValue))
                                self.option('incidentOccured').call(null, "Cannot parse the value specified as the " + entity + " property of the selectedRange configuration object.");
                            else
                                result = parsedValue;
                            return result
                        };
                    if (!selectedRangeOptions)
                        return {
                                startValue: scaleOptions.startValue,
                                endValue: scaleOptions.endValue
                            };
                    else
                        return {
                                startValue: parseValue(selectedRangeOptions.startValue, 'startValue'),
                                endValue: parseValue(selectedRangeOptions.endValue, 'endValue')
                            }
                };
            var _isSizeChanged = function(self) {
                    var actualSize = self._actualSize,
                        newSize = calculateSize(self);
                    return actualSize && (actualSize.width !== newSize.width || actualSize.height !== newSize.height)
                };
            var _resizeHandler = function(self) {
                    return DX.utils.createResizeHandler(function() {
                            if (_isSizeChanged(self))
                                self._render(true)
                        })
                };
            return {
                    isSizeChanged: function() {
                        return _isSizeChanged(this)
                    },
                    _defaultOptions: function() {
                        return defaultRangeSelectorOptions
                    },
                    _dataSourceOptions: function() {
                        return {
                                paginate: false,
                                _preferSync: true
                            }
                    },
                    _init: function() {
                        var self = this;
                        self.container = getContainer(self);
                        clearContainer(self.container);
                        self.renderer = createRenderer(self);
                        self.rangeContainer = createRangeContainer(self.renderer);
                        if (self.option('redrawOnResize') === true)
                            utils.windowResizeCallbacks.add(_resizeHandler(self));
                        if (!$.isFunction(self.option('incidentOccured'))) {
                            utils.debug.assert(false, 'Function should be passed as "info" callback');
                            self.option('incidentOccured', $.noop)
                        }
                        if (self.option('incidentOccured') === $.noop)
                            self.option('incidentOccured', utils.logger.warn);
                        self._reinitDataSource()
                    },
                    _reinitDataSource: function() {
                        this._initDataSource();
                        this._loadDataSource()
                    },
                    _initOptions: function(options) {
                        var self = this,
                            themeManager;
                        this._optionsInitializing = true;
                        options = options || {};
                        self._userOptions = $.extend(true, {}, options);
                        themeManager = createThemeManager(options.theme);
                        themeManager.setBackgroundColor(options.containerBackgroundColor);
                        self.option(themeManager.applyRangeSelectorTheme(options));
                        prepareChartThemeOptions(self, options);
                        if (options.background)
                            self._userBackgroundColor = options.background.color
                    },
                    _render: function(isResizing) {
                        this._optionsInitializing = false;
                        var self = this,
                            currentAnimationEnabled,
                            behaviorOptions;
                        applyOptions(self);
                        if (!self.stopRedraw)
                            if (isResizing) {
                                behaviorOptions = self.option('behavior');
                                currentAnimationEnabled = behaviorOptions.animationEnabled;
                                behaviorOptions.animationEnabled = false;
                                self.rangeContainer.redraw();
                                behaviorOptions.animationEnabled = currentAnimationEnabled
                            }
                            else
                                self.rangeContainer.redraw()
                    },
                    _optionChanged: function(name, value, prevValue) {
                        var self = this;
                        if (!this._optionsInitializing)
                            dataUtils.compileSetter(name)(self._userOptions, value, {
                                functionsAsIs: true,
                                merge: true
                            });
                        if (name === "dataSource") {
                            self._reinitDataSource();
                            self._invalidate()
                        }
                        else if (name === "selectedRange")
                            self.setSelectedRange(self.option('selectedRange'));
                        else if (name === "selectedRangeChanged")
                            self.rangeContainer.slidersContainer.selectedRangeChanged = createSelectedRangeChangedFunction(self);
                        else if (name === 'containerBackgroundColor' || name === 'theme') {
                            this._initOptions(self._userOptions);
                            self._invalidate()
                        }
                        else
                            self._invalidate()
                    },
                    _handleDataSourceChanged: function() {
                        var self = this;
                        if (self.renderer.isInitialized())
                            self._render()
                    },
                    getSelectedRange: function() {
                        var self = this;
                        var selectedRange = self.rangeContainer.slidersContainer.getSelectedRange();
                        return {
                                startValue: selectedRange.startValue,
                                endValue: selectedRange.endValue
                            }
                    },
                    setSelectedRange: function(selectedRange) {
                        var self = this;
                        if (self._isUpdating || !selectedRange)
                            return;
                        var oldSelectedRange = self.rangeContainer.slidersContainer.getSelectedRange();
                        if (oldSelectedRange && oldSelectedRange.startValue === selectedRange.startValue && oldSelectedRange.endValue === selectedRange.endValue)
                            return;
                        self.rangeContainer.slidersContainer.setSelectedRange(selectedRange)
                    },
                    resetSelectedRange: function(blockSelectedRangeChanged) {
                        var self = this;
                        self.setSelectedRange({
                            startValue: self._scaleOptions.startValue,
                            endValue: self._scaleOptions.endValue,
                            blockSelectedRangeChanged: blockSelectedRangeChanged
                        })
                    }
                }
        }()).include(DX.ui.DataHelperMixin)
    })(jQuery, DevExpress);
    /*! Module viz, file rangeContainer.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector;
        rangeSelector.RangeContainer = rangeSelector.BaseVisualElement.inherit(function() {
            var ctor = function(renderer) {
                    this.callBase(renderer);
                    this.slidersContainer = createSlidersContainer(renderer);
                    this.rangeView = createRangeView(renderer);
                    this.scale = createScale(renderer)
                };
            var _applyOptions = function(options) {
                    var self = this,
                        isEmpty = options.scale.isEmpty,
                        viewCanvas = {
                            left: options.canvas.left,
                            top: options.canvas.top,
                            width: options.canvas.width,
                            height: options.canvas.height >= options.scaleLabelsAreaHeight ? options.canvas.height - options.scaleLabelsAreaHeight : 0
                        };
                    self._viewCanvas = viewCanvas;
                    self.slidersContainer.applyOptions({
                        canvas: viewCanvas,
                        translator: options.translator,
                        scale: options.scale,
                        selectedRange: options.selectedRange,
                        sliderMarker: options.sliderMarker,
                        sliderHandle: options.sliderHandle,
                        shutter: options.shutter,
                        behavior: options.behavior,
                        selectedRangeChanged: options.selectedRangeChanged,
                        isEmpty: isEmpty
                    });
                    self.rangeView.applyOptions({
                        canvas: viewCanvas,
                        translator: options.translator,
                        background: options.background,
                        chart: options.chart,
                        seriesDataSource: options.seriesDataSource,
                        behavior: options.behavior,
                        isEmpty: isEmpty
                    });
                    self.scale.applyOptions({
                        canvas: options.canvas,
                        translator: options.translator,
                        scale: options.scale,
                        hideLabels: isEmpty,
                        scaleLabelsAreaHeight: options.scaleLabelsAreaHeight,
                        setSelectedRange: options.setSelectedRange
                    })
                };
            var createSlidersContainer = function(options) {
                    return rangeSelector.rangeSelectorFactory.createSlidersContainer(options)
                };
            var createScale = function(options) {
                    return rangeSelector.rangeSelectorFactory.createScale(options)
                };
            var createRangeView = function(options) {
                    return rangeSelector.rangeSelectorFactory.createRangeView(options)
                };
            var _createClipRectCanvas = function(canvas, sliderMarkerSpacing) {
                    return {
                            left: canvas.left - sliderMarkerSpacing.left,
                            top: canvas.top - sliderMarkerSpacing.top,
                            width: canvas.width + sliderMarkerSpacing.right + sliderMarkerSpacing.left,
                            height: canvas.height + sliderMarkerSpacing.bottom + sliderMarkerSpacing.top
                        }
                };
            var _draw = function() {
                    var self = this,
                        containerGroup,
                        rangeViewGroup,
                        slidersContainerGroup,
                        scaleGroup,
                        trackersGroup,
                        size = self._options.size,
                        clipRectCanvas = _createClipRectCanvas(self._options.canvas, self._options.sliderMarkerSpacing),
                        viewCanvas = self._viewCanvas;
                    self._clipRect = self._renderer.createClipRect(clipRectCanvas.left, clipRectCanvas.top, clipRectCanvas.width, clipRectCanvas.height).append();
                    containerGroup = self._renderer.createGroup({
                        'class': 'rangeContainer',
                        clipId: self._clipRect.id
                    }).append();
                    self._viewClipRect = self._renderer.createClipRect(viewCanvas.left, viewCanvas.top, viewCanvas.width, viewCanvas.height).append();
                    rangeViewGroup = self._renderer.createGroup({
                        'class': 'view',
                        clipId: self._viewClipRect.id
                    });
                    rangeViewGroup.append(containerGroup);
                    self.rangeView.redraw(rangeViewGroup);
                    slidersContainerGroup = self._renderer.createGroup({'class': 'slidersContainer'});
                    slidersContainerGroup.append(containerGroup);
                    self.slidersContainer.redraw(slidersContainerGroup);
                    scaleGroup = self._renderer.createGroup({'class': 'scale'});
                    scaleGroup.append(containerGroup);
                    self.scale.redraw(scaleGroup);
                    trackersGroup = self._renderer.createGroup({'class': 'trackers'});
                    trackersGroup.append(containerGroup);
                    self._trackersGroup = trackersGroup;
                    self.slidersContainer.appendTrackers(trackersGroup)
                };
            var _update = function() {
                    var self = this,
                        clipRectCanvas = _createClipRectCanvas(self._options.canvas, self._options.sliderMarkerSpacing),
                        viewCanvas = self._viewCanvas;
                    self._clipRect.updateRectangle({
                        x: clipRectCanvas.left,
                        y: clipRectCanvas.top,
                        width: clipRectCanvas.width,
                        height: clipRectCanvas.height
                    });
                    self._viewClipRect.updateRectangle({
                        x: viewCanvas.left,
                        y: viewCanvas.top,
                        width: viewCanvas.width,
                        height: viewCanvas.height
                    });
                    self.rangeView.redraw();
                    self.slidersContainer.redraw();
                    self.slidersContainer.appendTrackers(self._trackersGroup);
                    self.scale.redraw()
                };
            var prototypeObject = {
                    createSlidersContainer: createSlidersContainer,
                    createScale: createScale,
                    ctor: ctor,
                    _applyOptions: _applyOptions,
                    _draw: _draw,
                    _update: _update
                };
            return prototypeObject
        }())
    })(jQuery, DevExpress);
    /*! Module viz, file scale.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            formatHelper = DX.formatHelper,
            utils = DX.utils;
        var SCALE_TEXT_SPACING = 5;
        rangeSelector.Scale = rangeSelector.BaseVisualElement.inherit({
            _setupDateUnitInterval: function(scaleOptions) {
                var key,
                    hasObjectSingleField = function(object) {
                        var fieldsCounter = 0;
                        $.each(object, function() {
                            return ++fieldsCounter < 2
                        });
                        return fieldsCounter === 1
                    },
                    millisecTickInterval,
                    majorTickInterval = scaleOptions.ticksInfo.majorTickInterval,
                    majorTicks = scaleOptions.ticksInfo.majorTicks;
                if (scaleOptions.valueType === 'datetime') {
                    if (utils.isObject(majorTickInterval) && !hasObjectSingleField(majorTickInterval))
                        utils.logger.warn('More than one field is specified within the object assigned to the "tickInterval" option. Assign an object with a single field specified (days, hours or a similar one).');
                    if (majorTicks && majorTicks.autoArrangementStep > 1) {
                        if (utils.isString(majorTickInterval))
                            majorTickInterval = utils.getDateIntervalByString(majorTickInterval);
                        for (key in majorTickInterval) {
                            majorTickInterval[key] *= majorTicks.autoArrangementStep;
                            millisecTickInterval = utils.convertDateTickIntervalToMilliseconds(majorTickInterval)
                        }
                        majorTickInterval = utils.convertMillisecondsToDateUnits(millisecTickInterval)
                    }
                    this.dateUnitInterval = utils.getDateUnitInterval(majorTickInterval)
                }
            },
            _prepareDatesDifferences: function(datesDifferences, tickInterval) {
                var deleteDifferent = tickInterval,
                    dateUnitInterval,
                    i;
                if (deleteDifferent === 'week')
                    deleteDifferent = 'day';
                if (deleteDifferent === 'quarter')
                    deleteDifferent = 'month';
                if (datesDifferences[deleteDifferent])
                    for (i = 0; i < utils.dateUnitIntervals.length; i++) {
                        dateUnitInterval = utils.dateUnitIntervals[i];
                        if (datesDifferences[dateUnitInterval]) {
                            datesDifferences[dateUnitInterval] = false;
                            datesDifferences.count--
                        }
                        if (dateUnitInterval === deleteDifferent)
                            break
                    }
            },
            _getMarkerDate: function(date, tickInterval) {
                var markerDate = new Date(date.getTime()),
                    month = 0;
                switch (tickInterval) {
                    case'quarter':
                        month = formatHelper.getFirstQuarterMonth(date.getMonth());
                    case'month':
                        markerDate.setMonth(month);
                    case'week':
                    case'day':
                        markerDate.setDate(1);
                    case'hour':
                        markerDate.setHours(0, 0, 0, 0);
                        break;
                    case'millisecond':
                        markerDate.setMilliseconds(0);
                        break;
                    case'second':
                        markerDate.setSeconds(0, 0);
                        break;
                    case'minute':
                        markerDate.setMinutes(0, 0, 0);
                        break
                }
                return markerDate
            },
            _drawDateMarker: function(date, options) {
                var labelPosX,
                    labelPosY,
                    dateFormated,
                    scaleOptions,
                    textElement;
                if (options.x === null)
                    return;
                scaleOptions = this._options.scale;
                this.lineOptions['class'] = 'dx-range-selector-date-marker';
                this._renderer.createLine(options.x, options.y, options.x, options.y + scaleOptions.marker.separatorHeight, this.lineOptions).append(options.group);
                dateFormated = this._getLabel(date, options.label);
                labelPosX = options.x + scaleOptions.tick.width + scaleOptions.marker.textLeftIndent;
                labelPosY = options.y + scaleOptions.marker.textTopIndent + scaleOptions.label.font.size;
                this.textOptions.align = 'left';
                textElement = this._renderer.createText(dateFormated, labelPosX, labelPosY, this.textOptions).append(options.group);
                return labelPosX + textElement.getBBox().width
            },
            _drawDateMarkers: function(dates, group) {
                var dateMarker,
                    i,
                    datesDifferences,
                    markerDate,
                    posX,
                    prevMarkerRightX = -1;
                if (this._options.scale.valueType !== 'datetime' || !this.visibleMarkers)
                    return;
                var markerDatePositions = [];
                if (dates.length > 1) {
                    for (i = 1; i < dates.length; i++) {
                        datesDifferences = utils.getDatesDifferences(dates[i - 1], dates[i]);
                        this._prepareDatesDifferences(datesDifferences, this.dateUnitInterval);
                        if (datesDifferences.count > 0) {
                            markerDate = this._getMarkerDate(dates[i], this.dateUnitInterval);
                            this.markerDates = this.markerDates || [];
                            this.markerDates.push(markerDate);
                            posX = this.translator.translateX(markerDate);
                            if (posX > prevMarkerRightX) {
                                posX !== null && markerDatePositions.push({
                                    date: markerDate,
                                    posX: posX
                                });
                                prevMarkerRightX = this._drawDateMarker(markerDate, {
                                    group: group,
                                    y: this._options.canvas.top + this._options.canvas.height - this.markersAreaHeight + this._options.scale.marker.topIndent,
                                    x: posX,
                                    label: this._getLabelFormatOptions(formatHelper.getDateFormatByDifferences(datesDifferences))
                                })
                            }
                        }
                    }
                    this._initializeMarkersEvents(markerDatePositions, group)
                }
            },
            _getLabelFormatOptions: function(formatString) {
                if (!utils.isDefined(this._options.scale.marker.label.format))
                    return $.extend({}, this._options.scale.marker.label, {format: formatString});
                return this._options.scale.marker.label
            },
            _calculateRangeByMarkerPosition: function(posX, markerDatePositions, scaleOptions) {
                var selectedRange = {},
                    index,
                    position;
                for (index in markerDatePositions) {
                    position = markerDatePositions[index];
                    if (!scaleOptions.inverted) {
                        if (posX >= position.posX)
                            selectedRange.startValue = position.date;
                        else if (!selectedRange.endValue)
                            selectedRange.endValue = position.date
                    }
                    else if (posX < position.posX)
                        selectedRange.endValue = position.date;
                    else if (!selectedRange.startValue)
                        selectedRange.startValue = position.date
                }
                selectedRange.startValue = selectedRange.startValue || scaleOptions.startValue;
                selectedRange.endValue = selectedRange.endValue || scaleOptions.endValue;
                return selectedRange
            },
            _initializeMarkersEvents: function(markerDatePositions, group) {
                var self = this,
                    markersAreaTop = this._options.canvas.top + this._options.canvas.height - this.markersAreaHeight + this._options.scale.marker.topIndent,
                    markersTracker,
                    svgOffsetLeft,
                    index,
                    posX,
                    selectedRange;
                if (markerDatePositions.length > 0) {
                    markersTracker = self._renderer.createRect(self._options.canvas.left, markersAreaTop, self._options.canvas.width, self._options.scale.marker.separatorHeight, 0, {
                        fill: 'grey',
                        stroke: 'grey',
                        opacity: 0.0001
                    });
                    markersTracker.append(group);
                    markersTracker.on(rangeSelector.events.start, function(e) {
                        svgOffsetLeft = rangeSelector.utils.getRootOffsetLeft(self._renderer);
                        posX = rangeSelector.utils.getEventPageX(e) - svgOffsetLeft;
                        selectedRange = self._calculateRangeByMarkerPosition(posX, markerDatePositions, self._options.scale);
                        self._options.setSelectedRange(selectedRange)
                    });
                    self._markersTracker = markersTracker
                }
            },
            _getLabel: function(value, options) {
                var formatObject = {
                        value: value,
                        valueText: formatHelper.format(value, options.format, options.precision)
                    };
                return String(options.customizeText ? options.customizeText.call(formatObject, formatObject) : formatObject.valueText)
            },
            _drawLabel: function(value, group) {
                var textY = this._options.canvas.top + this._options.canvas.height - this.markersAreaHeight,
                    textElement = this._renderer.createText(this._getLabel(value, this._options.scale.label), this.translator.translateX(value), textY, this.textOptions);
                textElement.append(group);
                this.textElements = this.textElements || [];
                this.textElements.push(textElement)
            },
            _drawTick: function(value, group) {
                this.lineOptions['class'] = 'dx-range-selector-tick';
                var secondY = this._options.canvas.top + this._options.canvas.height - this.scaleLabelsAreaHeight,
                    posX = this.translator.translateX(value),
                    tickElement = this._renderer.createLine(posX, this._options.canvas.top, posX, secondY, this.lineOptions).append(group);
                this.tickElements = this.tickElements || [];
                this.tickElements.push(tickElement)
            },
            _redraw: function(group, isOptimize) {
                var self = this,
                    scaleOptions = self._options.scale,
                    ticksGroup = self._renderer.createGroup(),
                    labelsGroup = self._renderer.createGroup().append(group),
                    majorTicks = scaleOptions.ticksInfo.majorTicks,
                    minorTicks = scaleOptions.ticksInfo.minorTicks,
                    customBoundaryTicks = scaleOptions.ticksInfo.customBoundaryTicks,
                    hideLabels = self._options.hideLabels || majorTicks.hideLabels || !scaleOptions.label.visible,
                    i;
                for (i = 0; i < majorTicks.length; i++) {
                    if (!hideLabels)
                        self._drawLabel(majorTicks[i], labelsGroup);
                    self._drawTick(majorTicks[i], ticksGroup)
                }
                if (scaleOptions.showMinorTicks)
                    for (i = 0; i < minorTicks.length; i++)
                        self._drawTick(minorTicks[i], ticksGroup);
                for (i = 0; i < customBoundaryTicks.length; i++)
                    self._drawTick(customBoundaryTicks[i], ticksGroup);
                ticksGroup.append(group);
                self._drawDateMarkers(majorTicks, labelsGroup)
            },
            _applyOptions: function(options) {
                var scaleOptions = options.scale,
                    labelsAreaHeight;
                this.textOptions = {
                    align: 'center',
                    'class': 'dx-range-selector-scale',
                    font: scaleOptions.label.font,
                    style: {'-webkit-user-select': 'none'}
                };
                this.lineOptions = {
                    strokeWidth: scaleOptions.tick.width,
                    stroke: scaleOptions.tick.color,
                    strokeOpacity: scaleOptions.tick.opacity
                };
                this._setupDateUnitInterval(scaleOptions);
                this.visibleMarkers = scaleOptions.marker.visible === undefined ? true : scaleOptions.marker.visible;
                labelsAreaHeight = scaleOptions.label.visible ? scaleOptions.label.topIndent + scaleOptions.label.font.size : 0;
                this.scaleLabelsAreaHeight = options.scaleLabelsAreaHeight;
                this.markersAreaHeight = this.scaleLabelsAreaHeight - labelsAreaHeight;
                this.translator = options.translator
            },
            _draw: function(group) {
                this._redraw(group, false)
            },
            _update: function(group) {
                var callBase = this.callBase;
                if (this._markersTracker)
                    this._markersTracker.off(rangeSelector.events.start, '**');
                this.callBase = callBase;
                this.callBase(group)
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file rangeFactory.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            renderers = DX.viz.renderers;
        rangeSelector.rangeSelectorFactory = function() {
            return {
                    createRenderer: function(options) {
                        return new renderers.Renderer(options)
                    },
                    createTranslator: function(range, canvas) {
                        return new DX.viz.core.LinearTranslator(range, canvas)
                    },
                    getTickProvider: function() {
                        return DX.viz.core.tickProvider
                    },
                    createRangeContainer: function(rangeContainerOptions) {
                        return new rangeSelector.RangeContainer(rangeContainerOptions)
                    },
                    createSlidersContainer: function(options) {
                        return new rangeSelector.SlidersContainer(options)
                    },
                    createScale: function(options) {
                        return new rangeSelector.Scale(options)
                    },
                    createSliderMarker: function(options) {
                        return new rangeSelector.SliderMarker(options)
                    },
                    createRangeView: function(options) {
                        return new rangeSelector.RangeView(options)
                    },
                    createThemeManager: function(options) {
                        return new rangeSelector.ThemeManager(options)
                    },
                    createSlider: function(renderer, sliderIndex) {
                        return new rangeSelector.Slider(renderer, sliderIndex)
                    },
                    createSlidersEventsManager: function(renderer, slidersController, processSelectionChanged) {
                        return new rangeSelector.SlidersEventsManager(renderer, slidersController, processSelectionChanged)
                    },
                    createSlidersController: function(sliders) {
                        return new rangeSelector.SlidersController(sliders)
                    }
                }
        }()
    })(jQuery, DevExpress);
    /*! Module viz, file slidersContainer.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            utils = DX.utils;
        var msPointerEnabled = window.navigator.msPointerEnabled || window.navigator.pointerEnabled;
        var isNumber = DX.utils.isNumber;
        var isDate = DX.utils.isDate;
        var START_VALUE_INDEX = 0,
            END_VALUE_INDEX = 1;
        rangeSelector.SlidersContainer = rangeSelector.BaseVisualElement.inherit(function() {
            var prototypeObject = {
                    getController: function() {
                        return this._controller
                    },
                    _drawAreaTracker: function(group) {
                        var self = this,
                            areaTracker,
                            selectedAreaTracker;
                        areaTracker = self._renderer.createRect(self._options.canvas.left, self._options.canvas.top, self._options.canvas.width, self._options.canvas.height, 0, {
                            fill: 'grey',
                            stroke: 'grey',
                            opacity: 0.0001
                        });
                        areaTracker.append(group);
                        selectedAreaTracker = self._renderer.createRect(self._options.canvas.left, self._options.canvas.top, self._options.canvas.width, self._options.canvas.height, 0, {
                            fill: 'grey',
                            stroke: 'grey',
                            opacity: 0.0001,
                            style: {cursor: 'pointer'}
                        });
                        selectedAreaTracker.append(group);
                        self._controller.setAreaTrackers(areaTracker, selectedAreaTracker)
                    },
                    _processSelectionChanged: function(moving, blockSelectedRangeChanged) {
                        var self = this,
                            equalLastSelectedRange = function(selectedRange) {
                                return selectedRange && self._lastSelectedRange.startValue === selectedRange.startValue && self._lastSelectedRange.endValue === selectedRange.endValue
                            },
                            selectedRange = self.getSelectedRange();
                        if ((!moving || (self._options.behavior.callSelectedRangeChanged || '').toLowerCase() === "onmoving") && self._options.selectedRangeChanged && !equalLastSelectedRange(selectedRange)) {
                            self._updateLastSelectedRange(selectedRange);
                            if (typeof self._options.selectedRangeChanged === 'function')
                                self._options.selectedRangeChanged.call(null, selectedRange, blockSelectedRangeChanged);
                            if (!moving && !equalLastSelectedRange(selectedRange))
                                self.setSelectedRange(selectedRange)
                        }
                    },
                    _updateLastSelectedRange: function(selectedRange) {
                        selectedRange = selectedRange || this._options.selectedRange;
                        this._lastSelectedRange = {
                            startValue: selectedRange.startValue,
                            endValue: selectedRange.endValue
                        }
                    },
                    _createSlider: function(sliderIndex) {
                        return rangeSelector.rangeSelectorFactory.createSlider(this._renderer, sliderIndex)
                    },
                    _createSlidersController: function(sliders) {
                        return rangeSelector.rangeSelectorFactory.createSlidersController(sliders)
                    },
                    _createSlidersEventsManager: function(controller) {
                        var self = this;
                        return rangeSelector.rangeSelectorFactory.createSlidersEventsManager(self._renderer, controller, function(moving) {
                                self._processSelectionChanged(moving)
                            })
                    },
                    ctor: function(renderer) {
                        var self = this,
                            sliders;
                        self.callBase(renderer);
                        sliders = [self._createSlider(START_VALUE_INDEX), self._createSlider(END_VALUE_INDEX)];
                        self._controller = self._createSlidersController(sliders);
                        self._eventsManager = self._createSlidersEventsManager(self._controller);
                        self._lastSelectedRange = {}
                    },
                    getSelectedRange: function() {
                        return this._controller.getSelectedRange()
                    },
                    setSelectedRange: function(selectedRange) {
                        var self = this,
                            scale = self._options.scale,
                            startValue,
                            endValue,
                            currentSelectedRange = self._options.selectedRange;
                        if (selectedRange) {
                            startValue = selectedRange.startValue;
                            endValue = selectedRange.endValue
                        }
                        if (isNumber(scale.startValue) && isNumber(startValue) || isDate(scale.startValue) && isDate(startValue))
                            currentSelectedRange.startValue = startValue;
                        if (isNumber(scale.endValue) && isNumber(endValue) || isDate(scale.endValue) && isDate(endValue))
                            currentSelectedRange.endValue = endValue;
                        self._controller.applySelectedRange(currentSelectedRange);
                        self._controller.applyPosition();
                        self._processSelectionChanged(false, selectedRange && selectedRange.blockSelectedRangeChanged)
                    },
                    appendTrackers: function(group) {
                        this._controller.appendTrackers(group)
                    },
                    _applyOptions: function(options) {
                        var self = this;
                        self._controller.applyOptions({
                            translator: options.translator,
                            canvas: options.canvas,
                            sliderMarker: options.sliderMarker,
                            sliderHandle: options.sliderHandle,
                            shutter: options.shutter,
                            scale: options.scale,
                            behavior: options.behavior
                        });
                        self._eventsManager.applyOptions({behavior: options.behavior})
                    },
                    _draw: function(group) {
                        var self = this,
                            rootElement;
                        if (msPointerEnabled) {
                            rootElement = self._renderer.getRoot();
                            rootElement && (rootElement.element.style.msTouchAction = "none")
                        }
                        self._controller.redraw(group);
                        self._drawAreaTracker(group);
                        self._eventsManager.initialize();
                        self._update()
                    },
                    _update: function() {
                        var self = this,
                            isEmpty = self._options.isEmpty;
                        self._eventsManager.setEnabled(!isEmpty);
                        self._controller.applySelectedRange(isEmpty ? {} : self._options.selectedRange);
                        self._controller.applyPosition(self.isDrawn());
                        self._updateLastSelectedRange();
                        self._controller.redraw()
                    }
                };
            return prototypeObject
        }())
    })(jQuery, DevExpress);
    /*! Module viz, file slidersController.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            utils = DX.utils;
        var START_VALUE_INDEX = 0,
            END_VALUE_INDEX = 1;
        rangeSelector.SlidersController = DX.Class.inherit(function() {
            return {
                    ctor: function(sliders) {
                        this._sliders = sliders;
                        sliders[START_VALUE_INDEX].setAnotherSlider(sliders[END_VALUE_INDEX]);
                        sliders[END_VALUE_INDEX].setAnotherSlider(sliders[START_VALUE_INDEX])
                    },
                    setAreaTrackers: function(areaTracker, selectedAreaTracker) {
                        this._areaTracker = areaTracker;
                        this._selectedAreaTracker = selectedAreaTracker
                    },
                    applyOptions: function(options) {
                        var self = this,
                            values = null;
                        self._options = options;
                        self.getSlider(START_VALUE_INDEX).applyOptions(options);
                        self.getSlider(END_VALUE_INDEX).applyOptions(options);
                        if (options.behavior.snapToTicks) {
                            values = options.scale.ticksInfo.fullTicks;
                            if (values.length > 1 && values[0] > values[values.length - 1])
                                values = values.reverse()
                        }
                        self.getSlider(START_VALUE_INDEX).setAvailableValues(values);
                        self.getSlider(END_VALUE_INDEX).setAvailableValues(values)
                    },
                    processDocking: function(sliderIndex) {
                        var self = this;
                        if (sliderIndex !== undefined)
                            self.getSlider(sliderIndex).processDocking();
                        else {
                            self.getSlider(START_VALUE_INDEX).processDocking();
                            self.getSlider(END_VALUE_INDEX).processDocking()
                        }
                        self.setTrackersCursorStyle('default');
                        self.applyAreaTrackersPosition()
                    },
                    getSelectedRangeInterval: function() {
                        var self = this;
                        return rangeSelector.utils.getInterval(self.getSlider(START_VALUE_INDEX).getValue(), self.getSlider(END_VALUE_INDEX).getValue())
                    },
                    moveSliders: function(postitionDelta, selectedRangeInterval) {
                        var self = this;
                        self.getSlider(START_VALUE_INDEX).setPosition(self.getSlider(START_VALUE_INDEX).getPosition() + postitionDelta, false, selectedRangeInterval);
                        self.applyPosition(true)
                    },
                    moveSlider: function(sliderIndex, fastSwap, position, offsetPosition, startOffsetPosition, startOffsetPositionChangedCallback) {
                        var self = this,
                            slider = self.getSlider(sliderIndex),
                            anotherSlider = slider.getAnotherSlider(),
                            anotherSliderIndex = anotherSlider.getIndex(),
                            doSwap;
                        if (slider.canSwap())
                            if (sliderIndex === START_VALUE_INDEX ? position > anotherSlider.getPosition() : position < anotherSlider.getPosition()) {
                                doSwap = fastSwap;
                                if (!fastSwap)
                                    if (Math.abs(offsetPosition) >= Math.abs(startOffsetPosition) && offsetPosition * startOffsetPosition < 0) {
                                        doSwap = true;
                                        position += 2 * startOffsetPosition;
                                        startOffsetPositionChangedCallback(-startOffsetPosition)
                                    }
                                if (doSwap) {
                                    self.swapSliders();
                                    anotherSlider.applyPosition(true)
                                }
                            }
                        slider.setPosition(position, true);
                        slider.applyPosition(true);
                        self.applyAreaTrackersPosition();
                        self.setTrackersCursorStyle('w-resize')
                    },
                    applySelectedAreaCenterPosition: function(pos) {
                        var self = this,
                            slidersContainerHalfWidth = (self.getSlider(END_VALUE_INDEX).getPosition() - self.getSlider(START_VALUE_INDEX).getPosition()) / 2,
                            selectedRangeInterval = self.getSelectedRangeInterval();
                        self.getSlider(START_VALUE_INDEX).setPosition(pos - slidersContainerHalfWidth, false, selectedRangeInterval);
                        self.applyPosition();
                        self.processDocking()
                    },
                    processManualSelection: function(startPosition, endPosition, eventArgs) {
                        var self = this,
                            animateSliderIndex,
                            movingSliderIndex,
                            positionRange = [Math.min(startPosition, endPosition), Math.max(startPosition, endPosition)];
                        animateSliderIndex = startPosition < endPosition ? START_VALUE_INDEX : END_VALUE_INDEX;
                        movingSliderIndex = startPosition < endPosition ? END_VALUE_INDEX : START_VALUE_INDEX;
                        self.getSlider(movingSliderIndex).setPosition(positionRange[movingSliderIndex]);
                        self.getSlider(animateSliderIndex).setPosition(positionRange[animateSliderIndex]);
                        self.getSlider(movingSliderIndex).setPosition(positionRange[movingSliderIndex], true);
                        self.getSlider(movingSliderIndex).startEventHandler(eventArgs);
                        self.getSlider(animateSliderIndex).processDocking();
                        self.getSlider(movingSliderIndex).applyPosition(true)
                    },
                    applySelectedRange: function(selectedRange) {
                        var self = this,
                            inverted = self._options.scale.inverted;
                        utils.debug.assertParam(selectedRange, 'selectedRange not passed');
                        if (!inverted && selectedRange.startValue > selectedRange.endValue || inverted && selectedRange.startValue < selectedRange.endValue) {
                            self.getSlider(START_VALUE_INDEX).setValue(selectedRange.endValue);
                            self.getSlider(END_VALUE_INDEX).setValue(selectedRange.startValue)
                        }
                        else {
                            self.getSlider(START_VALUE_INDEX).setValue(selectedRange.startValue);
                            self.getSlider(END_VALUE_INDEX).setValue(selectedRange.endValue)
                        }
                    },
                    getSelectedRange: function() {
                        var self = this;
                        return {
                                startValue: self.getSlider(START_VALUE_INDEX).getValue(),
                                endValue: self.getSlider(END_VALUE_INDEX).getValue()
                            }
                    },
                    swapSliders: function() {
                        var self = this;
                        self._sliders.reverse();
                        self.getSlider(START_VALUE_INDEX).changeLocation();
                        self.getSlider(END_VALUE_INDEX).changeLocation()
                    },
                    applyAreaTrackersPosition: function() {
                        var self = this,
                            selectedRange = self.getSelectedRange(),
                            scaleOptions = self._options.scale,
                            width = self.getSlider(END_VALUE_INDEX).getPosition() - self.getSlider(START_VALUE_INDEX).getPosition(),
                            options = {
                                x: self.getSlider(START_VALUE_INDEX).getPosition(),
                                width: width < 0 ? 0 : width,
                                y: self._options.canvas.top,
                                height: self._options.canvas.height,
                                style: {cursor: scaleOptions.endValue - scaleOptions.startValue === selectedRange.endValue - selectedRange.startValue ? 'default' : 'pointer'}
                            };
                        self._selectedAreaTracker.applySettings(options);
                        self._areaTracker.applySettings({
                            x: self._options.canvas.left,
                            width: self._options.canvas.width,
                            y: self._options.canvas.top,
                            height: self._options.canvas.height
                        })
                    },
                    applyPosition: function(disableAnimation) {
                        var self = this;
                        self.getSlider(START_VALUE_INDEX).applyPosition(disableAnimation);
                        self.getSlider(END_VALUE_INDEX).applyPosition(disableAnimation);
                        self.applyAreaTrackersPosition()
                    },
                    redraw: function(group) {
                        var self = this;
                        self.getSlider(START_VALUE_INDEX).redraw(group);
                        self.getSlider(END_VALUE_INDEX).redraw(group)
                    },
                    appendTrackers: function(group) {
                        var self = this;
                        if (self._areaTracker && self._selectedAreaTracker) {
                            self._areaTracker.append(group);
                            self._selectedAreaTracker.append(group)
                        }
                        self.getSlider(START_VALUE_INDEX).appendTrackers(group);
                        self.getSlider(END_VALUE_INDEX).appendTrackers(group)
                    },
                    getSlider: function(sliderIndex) {
                        return this._sliders[sliderIndex]
                    },
                    getAreaTracker: function() {
                        return this._areaTracker
                    },
                    getSelectedAreaTracker: function() {
                        return this._selectedAreaTracker
                    },
                    setTrackersCursorStyle: function(style) {
                        var self = this;
                        self._selectedAreaTracker.applySettings({style: {cursor: style}});
                        self._areaTracker.applySettings({style: {cursor: style}})
                    }
                }
        }())
    })(jQuery, DevExpress);
    /*! Module viz, file slidersEventsManager.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            utils = DX.utils;
        var setEvents = function() {
                var win = window;
                win = DX.viz.rangeSelector.mockWindow || window;
                var touchSupport = "ontouchstart" in win;
                var msPointerEnabled = win.navigator.msPointerEnabled;
                var pointerEnabled = win.navigator.pointerEnabled;
                rangeSelector.events = {
                    start: pointerEnabled ? "pointerdown" : msPointerEnabled ? "MSPointerDown" : touchSupport ? "touchstart mousedown" : "mousedown",
                    move: pointerEnabled ? "pointermove" : msPointerEnabled ? "MSPointerMove" : touchSupport ? "touchmove mousemove" : "mousemove",
                    end: pointerEnabled ? "pointerup pointercancel" : msPointerEnabled ? "MSPointerUp MSPointerCancel" : touchSupport ? "touchend mouseup" : "mouseup"
                }
            };
        setEvents();
        rangeSelector.__setEvents = setEvents;
        var MIN_MANUAL_SELECTING_WIDTH = 10,
            START_VALUE_INDEX = 0,
            END_VALUE_INDEX = 1;
        rangeSelector.SlidersEventsManager = DX.Class.inherit(function() {
            var getRootOffsetLeft = function(self) {
                    return rangeSelector.utils.getRootOffsetLeft(self._renderer)
                };
            var getEventPageX = function(eventArgs) {
                    return rangeSelector.utils.getEventPageX(eventArgs)
                };
            var isLeftButtonPressed = function(event) {
                    var e = event || window.event,
                        originalEvent = e.originalEvent,
                        touches = e.touches,
                        pointerType = originalEvent ? originalEvent.pointerType : false,
                        eventTouches = originalEvent ? originalEvent.touches : false,
                        isIE8LeftClick = e.which === undefined && e.button === 1,
                        isMSPointerLeftClick = originalEvent && pointerType !== undefined && (pointerType === (originalEvent.MSPOINTER_TYPE_TOUCH || 'touch') || pointerType === (originalEvent.MSPOINTER_TYPE_MOUSE || 'mouse') && originalEvent.buttons === 1),
                        isLeftClick = isIE8LeftClick || e.which === 1,
                        isTouches = touches && touches.length > 0 || eventTouches && eventTouches.length > 0;
                    return isLeftClick || isMSPointerLeftClick || isTouches
                };
            var isTouchEventArgs = function(e) {
                    return e && e.type && e.type.indexOf('touch') === 0
                };
            var initializeSliderEvents = function(self, sliderIndex) {
                    var renderer = self._renderer,
                        isTouchEvent,
                        slidersController = self._slidersController,
                        processSelectionChanged = self._processSelectionChanged,
                        slider = slidersController.getSlider(sliderIndex),
                        anotherSlider = slider.getAnotherSlider(),
                        fastSwap,
                        startOffsetPosition,
                        splitterMoving;
                    slider.startEventHandler = function(e) {
                        if (!self._enabled || !isLeftButtonPressed(e) || splitterMoving)
                            return;
                        fastSwap = this === slider.getSliderTracker().element;
                        splitterMoving = true;
                        isTouchEvent = isTouchEventArgs(e);
                        startOffsetPosition = getEventPageX(e) - slider.getPosition() - getRootOffsetLeft(self);
                        e.stopPropagation();
                        e.preventDefault()
                    };
                    slider.on(rangeSelector.events.start, slider.startEventHandler);
                    utils.subscribeEventToDocument(rangeSelector.events.end, function(e) {
                        if (splitterMoving) {
                            splitterMoving = false;
                            slidersController.processDocking();
                            processSelectionChanged(false)
                        }
                    });
                    utils.subscribeEventToDocument(rangeSelector.events.move, slider.__moveEventHandler = function(e) {
                        var doSwap,
                            pageX,
                            offsetPosition,
                            svgOffsetLeft = getRootOffsetLeft(self),
                            position,
                            sliderIndex = slider.getIndex();
                        if (isTouchEvent !== isTouchEventArgs(e))
                            return;
                        if (!isLeftButtonPressed(e, true) && splitterMoving) {
                            splitterMoving = false;
                            slidersController.processDocking();
                            processSelectionChanged(false)
                        }
                        else if (splitterMoving) {
                            e.preventDefault();
                            pageX = getEventPageX(e);
                            position = pageX - startOffsetPosition - svgOffsetLeft;
                            offsetPosition = pageX - slider.getPosition() - svgOffsetLeft;
                            slidersController.moveSlider(sliderIndex, fastSwap, position, offsetPosition, startOffsetPosition, function(newStartOffsetPosition) {
                                startOffsetPosition = newStartOffsetPosition
                            });
                            processSelectionChanged(true)
                        }
                    })
                };
            var initializeSelectedAreaEvents = function(self) {
                    var renderer = self._renderer,
                        isTouchEvent,
                        slidersController = self._slidersController,
                        processSelectionChanged = self._processSelectionChanged,
                        selectedAreaTracker = slidersController.getSelectedAreaTracker(),
                        selectedAreaMoving = false,
                        offsetStartPosition,
                        selectedRangeInterval;
                    selectedAreaTracker.on(rangeSelector.events.start, function(e) {
                        if (!self._enabled || !isLeftButtonPressed(e) || selectedAreaMoving)
                            return;
                        selectedAreaMoving = true;
                        isTouchEvent = isTouchEventArgs(e);
                        offsetStartPosition = getEventPageX(e) - slidersController.getSlider(START_VALUE_INDEX).getPosition();
                        selectedRangeInterval = slidersController.getSelectedRangeInterval();
                        e.stopPropagation();
                        e.preventDefault()
                    });
                    utils.subscribeEventToDocument(rangeSelector.events.end, function(e) {
                        if (selectedAreaMoving) {
                            selectedAreaMoving = false;
                            slidersController.processDocking();
                            processSelectionChanged(false)
                        }
                    });
                    utils.subscribeEventToDocument(rangeSelector.events.move, self.__selectedAreaMoveEventHandler = function(e) {
                        var positionDelta,
                            pageX;
                        if (isTouchEvent !== isTouchEventArgs(e))
                            return;
                        if (selectedAreaMoving && !isLeftButtonPressed(e)) {
                            selectedAreaMoving = false;
                            slidersController.processDocking();
                            processSelectionChanged(false)
                        }
                        if (selectedAreaMoving) {
                            e.preventDefault();
                            pageX = getEventPageX(e);
                            positionDelta = pageX - slidersController.getSlider(START_VALUE_INDEX).getPosition() - offsetStartPosition;
                            slidersController.moveSliders(positionDelta, selectedRangeInterval);
                            processSelectionChanged(true)
                        }
                    })
                };
            var initializeAreaEvents = function(self) {
                    var renderer = self._renderer,
                        isTouchEvent,
                        slidersController = self._slidersController,
                        processSelectionChanged = self._processSelectionChanged,
                        areaTracker = slidersController.getAreaTracker(),
                        unselectedAreaProcessing = false,
                        splitterMoving = false,
                        startPageX;
                    areaTracker.on(rangeSelector.events.start, function(e) {
                        if (!self._enabled || !isLeftButtonPressed(e) || unselectedAreaProcessing)
                            return;
                        unselectedAreaProcessing = true;
                        isTouchEvent = isTouchEventArgs(e);
                        startPageX = getEventPageX(e)
                    });
                    utils.subscribeEventToDocument(rangeSelector.events.end, function(e) {
                        var pageX;
                        if (unselectedAreaProcessing) {
                            pageX = getEventPageX(e);
                            if (self._options.behavior.moveSelectedRangeByClick && Math.abs(startPageX - pageX) < MIN_MANUAL_SELECTING_WIDTH)
                                slidersController.applySelectedAreaCenterPosition(pageX - getRootOffsetLeft(self));
                            unselectedAreaProcessing = false;
                            processSelectionChanged(false)
                        }
                    });
                    utils.subscribeEventToDocument(rangeSelector.events.move, self.__areaMoveEventHandler = function(e) {
                        var pageX,
                            startPosition,
                            endPosition,
                            svgOffsetLeft = getRootOffsetLeft(self);
                        if (isTouchEvent !== isTouchEventArgs(e))
                            return;
                        if (unselectedAreaProcessing && !isLeftButtonPressed(e)) {
                            unselectedAreaProcessing = false;
                            processSelectionChanged(false)
                        }
                        if (unselectedAreaProcessing) {
                            pageX = getEventPageX(e);
                            if (self._options.behavior.manualRangeSelectionEnabled && Math.abs(startPageX - pageX) >= MIN_MANUAL_SELECTING_WIDTH) {
                                startPosition = startPageX - svgOffsetLeft;
                                endPosition = pageX - svgOffsetLeft;
                                slidersController.processManualSelection(startPosition, endPosition, e);
                                unselectedAreaProcessing = false;
                                processSelectionChanged(true)
                            }
                        }
                    })
                };
            rangeSelector.getRootOffsetLeft = getRootOffsetLeft;
            return {
                    ctor: function(renderer, slidersController, processSelectionChanged) {
                        this._renderer = renderer;
                        this._slidersController = slidersController;
                        this._processSelectionChanged = processSelectionChanged;
                        this._enabled = true
                    },
                    applyOptions: function(options) {
                        this._options = options
                    },
                    initialize: function() {
                        var self = this;
                        if (!self._renderer.isInitialized())
                            return;
                        initializeSelectedAreaEvents(self);
                        initializeAreaEvents(self);
                        initializeSliderEvents(self, START_VALUE_INDEX);
                        initializeSliderEvents(self, END_VALUE_INDEX)
                    },
                    setEnabled: function(enabled) {
                        this._enabled = enabled
                    }
                }
        }())
    })(jQuery, DevExpress);
    /*! Module viz, file slider.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            utils = DX.utils;
        var touchSupport = "ontouchstart" in window;
        var msPointerEnabled = window.navigator.msPointerEnabled || window.navigator.pointerEnabled;
        var animationOptions = {duration: 250};
        var SPLITTER_WIDTH = 8,
            TOUCH_SPLITTER_WIDTH = 20,
            START_VALUE_INDEX = 0,
            END_VALUE_INDEX = 1;
        rangeSelector.Slider = rangeSelector.BaseVisualElement.inherit(function() {
            return {
                    getText: function() {
                        if (this._marker)
                            return this._marker.getText()
                    },
                    getAvailableValues: function() {
                        return this._values
                    },
                    getShutter: function() {
                        return this._shutter
                    },
                    getMarker: function() {
                        return this._marker
                    },
                    _createSlider: function() {
                        var self = this,
                            sliderHandle,
                            sliderGroup,
                            sliderHandleOptions = self._options.sliderHandle;
                        sliderGroup = self._renderer.createGroup({'class': 'slider'});
                        sliderGroup.applySettings({
                            translateX: self._options.canvas.left,
                            translateY: self._options.canvas.top
                        });
                        sliderHandle = self._renderer.createLine(0, 0, 0, self._options.canvas.height, {
                            'class': 'dx-range-selector-slider',
                            strokeWidth: sliderHandleOptions.width,
                            stroke: sliderHandleOptions.color,
                            strokeOpacity: sliderHandleOptions.opacity
                        });
                        sliderHandle.append(sliderGroup);
                        sliderGroup.setValid = function(correct) {
                            sliderHandle.applySettings({stroke: correct ? self._options.sliderHandle.color : self._options.sliderMarker.invalidRangeColor})
                        };
                        sliderGroup.updateHeight = function() {
                            sliderHandle.applySettings({points: [0, 0, 0, self._options.canvas.height]})
                        };
                        sliderGroup.applyOptions = function(options) {
                            sliderHandle.applySettings(options)
                        };
                        sliderGroup.__line = sliderHandle;
                        return sliderGroup
                    },
                    _createSliderTracker: function() {
                        var self = this,
                            sliderWidth = touchSupport || msPointerEnabled ? TOUCH_SPLITTER_WIDTH : SPLITTER_WIDTH,
                            sliderTracker,
                            sliderTrackerGroup;
                        sliderTracker = self._renderer.createRect(-sliderWidth / 2, 0, sliderWidth, self._options.canvas.height, 0, {
                            fill: 'grey',
                            stroke: 'grey',
                            opacity: 0.0001,
                            style: {cursor: 'w-resize'}
                        });
                        sliderTrackerGroup = self._renderer.createGroup({'class': 'sliderTracker'});
                        sliderTrackerGroup.applySettings({
                            translateX: 0,
                            translateY: self._options.canvas.top
                        });
                        sliderTracker.append(sliderTrackerGroup);
                        sliderTrackerGroup.updateHeight = function() {
                            sliderTracker.applySettings({height: self._options.canvas.height})
                        };
                        sliderTrackerGroup.__rect = sliderTracker;
                        return sliderTrackerGroup
                    },
                    _drawSliderTracker: function(group) {
                        var self = this,
                            sliderTracker = self._createSliderTracker();
                        if (sliderTracker) {
                            sliderTracker.append(group);
                            self._sliderTracker = sliderTracker
                        }
                    },
                    _createSliderMarker: function(options) {
                        return rangeSelector.rangeSelectorFactory.createSliderMarker(options)
                    },
                    _setPosition: function(position, correctByMinMaxRange) {
                        var self = this,
                            correctedPosition = self._correctPosition(position),
                            value = self._options.translator.untranslateX(correctedPosition);
                        self.setValue(value, correctByMinMaxRange);
                        self._position = correctedPosition
                    },
                    _setPositionForBothSliders: function(startPosition, interval) {
                        var self = this,
                            anotherSlider,
                            startValue,
                            endValue,
                            endPosition,
                            inverted = self._options.scale.inverted;
                        anotherSlider = self.getAnotherSlider();
                        startPosition = self._correctBounds(startPosition);
                        startValue = self._options.translator.untranslateX(startPosition);
                        endValue = utils.addInterval(startValue, interval);
                        if (!inverted && endValue > self._options.scale.endValue || inverted && endValue < self._options.scale.endValue) {
                            endValue = self._options.scale.endValue;
                            endPosition = self._options.canvas.left + self._options.canvas.width;
                            startValue = utils.addInterval(endValue, interval, true);
                            startPosition = self._options.translator.translateX(startValue)
                        }
                        else
                            endPosition = self._options.translator.translateX(endValue);
                        if (self._values)
                            if (!inverted ? startValue < self._values[0] : startValue > self._values[self._values.length - 1]) {
                                startValue = self._correctBusinessValueByAvailableValues(startValue);
                                endValue = utils.addInterval(startValue, interval)
                            }
                            else {
                                endValue = self._correctBusinessValueByAvailableValues(endValue);
                                startValue = utils.addInterval(endValue, interval, true)
                            }
                        anotherSlider.setValue(endValue);
                        self.setValue(startValue);
                        self._position = startPosition;
                        anotherSlider._position = endPosition
                    },
                    _correctPosition: function(position) {
                        var self = this,
                            correctedPosition = self._correctInversion(position);
                        correctedPosition = self._correctBounds(correctedPosition);
                        return correctedPosition
                    },
                    _correctInversion: function(position) {
                        var self = this,
                            correctedPosition = position,
                            anotherSliderPosition = self.getAnotherSlider().getPosition(),
                            slidersInverted = self.getIndex() === START_VALUE_INDEX ? position > anotherSliderPosition : position < anotherSliderPosition;
                        if (slidersInverted)
                            correctedPosition = anotherSliderPosition;
                        return correctedPosition
                    },
                    _correctBounds: function(position) {
                        var self = this,
                            correctedPosition = position,
                            canvas = self._options.canvas;
                        if (position < canvas.left)
                            correctedPosition = canvas.left;
                        if (position > canvas.left + canvas.width)
                            correctedPosition = canvas.left + canvas.width;
                        return correctedPosition
                    },
                    _correctBusinessValue: function(businessValue, correctByMinMaxRange) {
                        var self = this,
                            result = self._correctBusinessValueByAvailableValues(businessValue);
                        if (correctByMinMaxRange)
                            result = self._correctBusinessValueByMinMaxRangeFromAnotherSlider(result);
                        result = self._correctBusinessValueByMinRangeFromStartEndValues(result);
                        return result
                    },
                    _correctBusinessValueByAvailableValues: function(businessValue) {
                        var values = this._values;
                        if (values)
                            return rangeSelector.utils.findNearValue(values, businessValue);
                        return businessValue
                    },
                    _correctBusinessValueByMinMaxRangeFromAnotherSlider: function(businessValue) {
                        var self = this,
                            result = businessValue,
                            scale = self._options.scale,
                            values = self._values,
                            sliderIndex = self.getIndex(),
                            anotherBusinessValue = self.getAnotherSlider().getValue(),
                            isValid = true,
                            minValue,
                            maxValue;
                        if (!scale.inverted && sliderIndex === START_VALUE_INDEX || scale.inverted && sliderIndex === END_VALUE_INDEX) {
                            if (scale.maxRange)
                                minValue = utils.addInterval(anotherBusinessValue, scale.maxRange, true);
                            if (scale.minRange)
                                maxValue = utils.addInterval(anotherBusinessValue, scale.minRange, true)
                        }
                        else {
                            if (scale.maxRange)
                                maxValue = utils.addInterval(anotherBusinessValue, scale.maxRange);
                            if (scale.minRange)
                                minValue = utils.addInterval(anotherBusinessValue, scale.minRange)
                        }
                        if (maxValue !== undefined && result > maxValue) {
                            result = values ? rangeSelector.utils.findLessOrEqualValue(values, maxValue) : maxValue;
                            isValid = false
                        }
                        else if (minValue !== undefined && result < minValue) {
                            result = values ? rangeSelector.utils.findGreaterOrEqualValue(values, minValue) : minValue;
                            isValid = false
                        }
                        self._setValid(isValid);
                        return result
                    },
                    _correctBusinessValueByMinRangeFromStartEndValues: function(businessValue) {
                        var self = this,
                            values = self._values,
                            startValue,
                            endValue,
                            isValid = true,
                            scale = self._options.scale,
                            result = businessValue;
                        if (scale.minRange)
                            if (self.getIndex() === END_VALUE_INDEX) {
                                startValue = utils.addInterval(scale.startValue, scale.minRange, scale.inverted);
                                if (!scale.inverted && result < startValue || scale.inverted && result > startValue)
                                    result = startValue
                            }
                            else if (self.getIndex() === START_VALUE_INDEX) {
                                endValue = utils.addInterval(scale.endValue, scale.minRange, !scale.inverted);
                                if (!scale.inverted && result > endValue || scale.inverted && result < endValue)
                                    result = endValue
                            }
                        return result
                    },
                    _applySliderPosition: function(position, disableAnimation) {
                        var self = this,
                            isAnimation = self._options.behavior.animationEnabled && !disableAnimation,
                            top = self._options.canvas.top,
                            slider = self._slider;
                        if (isAnimation || slider.inAnimation) {
                            slider.inAnimation = true;
                            slider.animate({translate: {
                                    x: position,
                                    y: top
                                }}, isAnimation ? animationOptions : {duration: 0}, function() {
                                slider.inAnimation = false
                            });
                            self._sliderTracker.animate({translate: {
                                    x: position,
                                    y: top
                                }}, isAnimation ? animationOptions : {duration: 0})
                        }
                        else {
                            self._slider.applySettings({
                                translateX: position,
                                translateY: top
                            });
                            self._sliderTracker.applySettings({
                                translateX: position,
                                translateY: top
                            })
                        }
                        self._sliderTracker.updateHeight();
                        self._slider.updateHeight()
                    },
                    _applyShutterPosition: function(position, disableAnimation) {
                        var self = this,
                            shutterSettings,
                            shutter = self._shutter,
                            isAnimation = self._options.behavior.animationEnabled && !disableAnimation,
                            sliderIndex = self.getIndex();
                        if (sliderIndex == START_VALUE_INDEX)
                            shutterSettings = {
                                x: self._options.canvas.left,
                                y: self._options.canvas.top,
                                width: position - self._options.canvas.left,
                                height: self._options.canvas.height
                            };
                        else if (sliderIndex == END_VALUE_INDEX)
                            shutterSettings = {
                                x: position + 1,
                                y: self._options.canvas.top,
                                width: self._options.canvas.left + self._options.canvas.width - position,
                                height: self._options.canvas.height
                            };
                        if (shutterSettings)
                            if (isAnimation || shutter.inAnimation) {
                                shutter.inAnimation = true;
                                shutter.animate(shutterSettings, isAnimation ? animationOptions : {duration: 0}, function() {
                                    shutter.inAnimation = false
                                })
                            }
                            else
                                shutter.applySettings(shutterSettings)
                    },
                    _setValid: function(isValid) {
                        var self = this;
                        if (self._marker)
                            self._marker.setValid(isValid);
                        self._slider.setValid(isValid)
                    },
                    _setText: function(text) {
                        var self = this;
                        if (self._marker)
                            self._marker.setText(text)
                    },
                    ctor: function(renderer, index) {
                        var self = this;
                        self.callBase(renderer);
                        self._index = index
                    },
                    getIndex: function() {
                        return this._index
                    },
                    setAvailableValues: function(values) {
                        this._values = values
                    },
                    setAnotherSlider: function(slider) {
                        this._anotherSlider = slider
                    },
                    getAnotherSlider: function(slider) {
                        return this._anotherSlider
                    },
                    appendTrackers: function(group) {
                        var self = this;
                        if (self._sliderTracker)
                            self._sliderTracker.append(group)
                    },
                    getSliderTracker: function() {
                        return this._sliderTracker
                    },
                    changeLocation: function() {
                        var self = this;
                        if (self._marker)
                            self._marker.changeLocation();
                        self._index = this._index === START_VALUE_INDEX ? END_VALUE_INDEX : START_VALUE_INDEX;
                        self._lastPosition = null
                    },
                    setPosition: function(position, correctByMinMaxRange, selectedRangeInterval) {
                        var self = this,
                            slider;
                        if (selectedRangeInterval !== undefined) {
                            slider = self.getIndex() === START_VALUE_INDEX ? self : self.getAnotherSlider();
                            slider._setPositionForBothSliders(position, selectedRangeInterval)
                        }
                        else
                            self._setPosition(position, correctByMinMaxRange)
                    },
                    getPosition: function() {
                        return this._position
                    },
                    _applyOptions: function(options) {
                        this._lastPosition = null
                    },
                    setValue: function(value, correctByMinMaxRange) {
                        var self = this;
                        if (value === undefined) {
                            self._value = undefined;
                            self._valuePosition = self._position = self.getIndex() === START_VALUE_INDEX ? self._options.canvas.left : self._options.canvas.left + self._options.canvas.width;
                            self._setText(rangeSelector.consts.emptySliderMarkerText)
                        }
                        else {
                            self._value = self._correctBusinessValue(value, correctByMinMaxRange);
                            self._valuePosition = self._position = self._options.translator.translateX(self._value);
                            self._setText(rangeSelector.formatValue(self._value, self._options.sliderMarker))
                        }
                    },
                    getValue: function() {
                        return this._value
                    },
                    canSwap: function() {
                        var self = this,
                            scale = self._options.scale,
                            startValue,
                            endValue,
                            anotherSliderValue;
                        if (self._options.behavior.allowSlidersSwap) {
                            if (scale.minRange) {
                                anotherSliderValue = self.getAnotherSlider().getValue();
                                if (self.getIndex() === START_VALUE_INDEX) {
                                    endValue = utils.addInterval(scale.endValue, scale.minRange, !scale.inverted);
                                    if (!scale.inverted && anotherSliderValue > endValue || scale.inverted && anotherSliderValue < endValue)
                                        return false
                                }
                                else {
                                    startValue = utils.addInterval(scale.startValue, scale.minRange, scale.inverted);
                                    if (!scale.inverted && anotherSliderValue < startValue || scale.inverted && anotherSliderValue > startValue)
                                        return false
                                }
                            }
                            return true
                        }
                        return false
                    },
                    processDocking: function() {
                        var self = this;
                        self._position = self._valuePosition;
                        self.applyPosition(false);
                        self._setValid(true)
                    },
                    applyPosition: function(disableAnimation) {
                        var self = this,
                            position = self.getPosition();
                        if (self._lastPosition !== position) {
                            self._applySliderPosition(position, disableAnimation);
                            self._applyShutterPosition(position, disableAnimation);
                            self._lastPosition = position
                        }
                    },
                    on: function(event, handler) {
                        var self = this;
                        self._sliderTracker.on(event, handler);
                        if (self._marker)
                            self._marker.getTracker().on(event, handler)
                    },
                    _update: function() {
                        var self = this;
                        self._marker && self._marker.applyOptions(self._options.sliderMarker);
                        self._shutter && self._shutter.applySettings({
                            fill: self._options.shutter.color,
                            fillOpacity: self._options.shutter.opacity
                        });
                        self._slider && self._slider.applyOptions({
                            strokeWidth: self._options.sliderHandle.width,
                            stroke: self._options.sliderHandle.color,
                            strokeOpacity: self._options.sliderHandle.opacity
                        })
                    },
                    _draw: function(group) {
                        var self = this,
                            slider,
                            marker,
                            sliderAreaGroup,
                            shutter,
                            startPos,
                            startWidth,
                            index = self.getIndex();
                        sliderAreaGroup = self._renderer.createGroup({'class': 'sliderArea'});
                        sliderAreaGroup.append(group);
                        if (index === START_VALUE_INDEX)
                            shutter = self._renderer.createRect(self._options.canvas.left, self._options.canvas.top, 0, self._options.canvas.height, 0);
                        else if (index === END_VALUE_INDEX)
                            shutter = self._renderer.createRect(self._options.canvas.left, self._options.canvas.top, self._options.canvas.width, self._options.canvas.height, 0);
                        if (shutter) {
                            shutter.append(sliderAreaGroup);
                            slider = self._createSlider();
                            if (slider)
                                slider.append(sliderAreaGroup);
                            if (self._options.sliderMarker.visible) {
                                marker = self._createSliderMarker({
                                    renderer: self._renderer,
                                    isLeftPointer: index === END_VALUE_INDEX,
                                    sliderMarkerOptions: self._options.sliderMarker
                                });
                                marker.draw(slider)
                            }
                            self._shutter = shutter;
                            self._slider = slider;
                            self._marker = marker
                        }
                        self._drawSliderTracker(group)
                    }
                }
        }())
    })(jQuery, DevExpress);
    /*! Module viz, file sliderMarker.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector;
        rangeSelector.SliderMarker = DX.Class.inherit(function() {
            var ctor = function(options) {
                    this._renderer = options.renderer;
                    this._text = options.text;
                    this._isLeftPointer = options.isLeftPointer;
                    this._options = options.sliderMarkerOptions;
                    this._isValid = true;
                    initializeAreaPoints(this, {
                        width: 10,
                        height: 10
                    })
                };
            var applyOptions = function(options) {
                    this._options = options;
                    this.update()
                };
            var getRectSize = function(self, textSize) {
                    return {
                            width: Math.round(2 * self._options.padding + textSize.width),
                            height: Math.round(2 * self._options.padding + textSize.height * rangeSelector.consts.fontHeightRatio)
                        }
                };
            var initializeAreaPoints = function(self, textSize) {
                    var rectSize = getRectSize(self, textSize);
                    self._points = [];
                    if (self._isLeftPointer) {
                        self._points.push({
                            x: 0,
                            y: 0
                        });
                        self._points.push({
                            x: rectSize.width,
                            y: 0
                        });
                        self._points.push({
                            x: rectSize.width,
                            y: rectSize.height
                        });
                        self._points.push({
                            x: self._options.pointerSize,
                            y: rectSize.height
                        });
                        self._points.push({
                            x: 0,
                            y: rectSize.height + self._options.pointerSize
                        })
                    }
                    else {
                        self._points.push({
                            x: 0,
                            y: 0
                        });
                        self._points.push({
                            x: rectSize.width,
                            y: 0
                        });
                        self._points.push({
                            x: rectSize.width,
                            y: rectSize.height + self._options.pointerSize
                        });
                        self._points.push({
                            x: rectSize.width - self._options.pointerSize,
                            y: rectSize.height
                        });
                        self._points.push({
                            x: 0,
                            y: rectSize.height
                        })
                    }
                };
            var getPointerPosition = function(self, textSize) {
                    var rectSize = getRectSize(self, textSize);
                    if (self._isLeftPointer)
                        return {
                                x: 0,
                                y: rectSize.height + self._options.pointerSize
                            };
                    else
                        return {
                                x: rectSize.width - 1,
                                y: rectSize.height + self._options.pointerSize
                            }
                };
            var draw = function(group) {
                    var self = this;
                    var padding = self._options.padding;
                    self._sliderMarkerGroup = self._renderer.createGroup({'class': 'sliderMarker'});
                    self._sliderMarkerGroup.append(group);
                    self._area = self._renderer.createArea(self.points, {fill: self._options.color});
                    self._area.append(self._sliderMarkerGroup);
                    self._label = self._renderer.createText(self._text, padding, padding, {
                        font: self._options.font,
                        style: {'-webkit-user-select': 'none'}
                    });
                    self._label.append(self._sliderMarkerGroup);
                    self._tracker = self._renderer.createRect(0, 0, 2 * padding, 2 * padding + self._options.pointerSize, 0, {
                        fill: 'grey',
                        stroke: 'grey',
                        opacity: 0.0001,
                        style: {cursor: 'pointer'}
                    });
                    self._tracker.append(self._sliderMarkerGroup);
                    self._drawn = true;
                    self.update()
                };
            var getTextSize = function(self) {
                    var textSize = self._label.getBBox();
                    if (!self._textHeight && isFinite(textSize.height))
                        self._textHeight = textSize.height;
                    return {
                            width: textSize.width,
                            height: self._textHeight
                        }
                };
            var update = function(stop) {
                    var self = this,
                        textSize,
                        rectSize,
                        pointerPosition;
                    self._interval && clearInterval(self._interval);
                    delete self._interval;
                    if (!self._drawn)
                        return;
                    self._label.updateText(self._text);
                    textSize = getTextSize(self);
                    if (!stop) {
                        self._textSize = self._textSize || textSize;
                        self._textSize = textSize.width > self._textSize.width || textSize.height > self._textSize.height ? textSize : self._textSize;
                        textSize = self._textSize;
                        self._interval = setInterval(function() {
                            update.call(self, [true])
                        }, 75)
                    }
                    else {
                        delete self._textSize;
                        self._textSize = textSize
                    }
                    rectSize = getRectSize(self, textSize);
                    pointerPosition = getPointerPosition(self, textSize);
                    self._sliderMarkerGroup.applySettings({
                        translateX: -pointerPosition.x,
                        translateY: -pointerPosition.y
                    });
                    initializeAreaPoints(self, textSize);
                    self._area.applySettings({
                        points: self._points,
                        fill: self._isValid ? self._options.color : self._options.invalidRangeColor
                    });
                    self._tracker.applySettings({
                        width: rectSize.width,
                        height: rectSize.height + self._options.pointerSize
                    });
                    self._label.applySettings({
                        x: self._options.padding,
                        y: rectSize.height - self._options.padding
                    })
                };
            var getText = function() {
                    var self = this;
                    return self._text
                };
            var setText = function(value) {
                    var self = this;
                    if (self._text !== value) {
                        self._text = value;
                        self.update()
                    }
                };
            var setValid = function(isValid) {
                    var self = this;
                    self._isValid = isValid;
                    self.update()
                };
            var changeLocation = function() {
                    var self = this;
                    self._isLeftPointer = !self._isLeftPointer;
                    self.update()
                };
            var getTracker = function() {
                    var self = this;
                    return self._tracker
                };
            return {
                    ctor: ctor,
                    draw: draw,
                    update: update,
                    getText: getText,
                    setText: setText,
                    changeLocation: changeLocation,
                    applyOptions: applyOptions,
                    getTracker: getTracker,
                    setValid: setValid
                }
        }())
    })(jQuery, DevExpress);
    /*! Module viz, file rangeView.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector;
        rangeSelector.RangeView = rangeSelector.BaseVisualElement.inherit(function() {
            var createThemeManager = function(self) {
                    return DX.viz.charts.factory.createThemeManager(self.chart.theme)
                };
            return {_draw: function(group) {
                        var self = this,
                            viewRect,
                            viewImage,
                            backgroundColor,
                            series,
                            i,
                            showChart,
                            canvas,
                            isEmpty = self._options.isEmpty;
                        showChart = self._options.seriesDataSource && self._options.seriesDataSource.isShowChart() && !isEmpty;
                        canvas = self._options.canvas;
                        if (showChart)
                            backgroundColor = self._options.seriesDataSource.getBackgroundColor();
                        else if (!isEmpty && self._options.background.visible)
                            backgroundColor = self._options.background.color;
                        if (self._options.background.visible && backgroundColor) {
                            viewRect = self._renderer.createRect(canvas.left, canvas.top, canvas.width + 1, canvas.height, 0, {
                                fill: backgroundColor,
                                'class': 'dx-range-selector-background'
                            });
                            viewRect.append(group)
                        }
                        if (self._options.background.visible && self._options.background.image && self._options.background.image.url) {
                            viewImage = self._renderer.createImage(canvas.left, canvas.top, canvas.width + 1, canvas.height, self._options.background.image.url, {location: self._options.background.image.location});
                            viewImage.append(group)
                        }
                        if (showChart) {
                            series = self._options.seriesDataSource.getSeries();
                            for (i = 0; i < series.length; i++) {
                                series[i].options.seriesGroup = group;
                                series[i].options.seriesLabelsGroup = group;
                                series[i].options.trackerGroup = group;
                                series[i].draw(self._options.translator);
                                if (self._options.behavior && self._options.behavior.animationEnabled)
                                    series[i].animate()
                            }
                        }
                    }}
        }())
    })(jQuery, DevExpress);
    /*! Module viz, file seriesDataSource.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            charts = DX.viz.charts;
        rangeSelector.SeriesDataSource = DX.Class.inherit(function() {
            var createThemeManager = function(chartOptions) {
                    return charts.factory.createThemeManager(chartOptions, 'rangeSelector.chart')
                };
            var isArrayOfSimpleTypes = function(data) {
                    return $.isArray(data) && data.length > 0 && (DX.utils.isNumber(data[0]) || DX.utils.isDate(data[0]))
                };
            var convertToArrayOfObjects = function(data) {
                    return $.map(data, function(item, i) {
                            return {
                                    arg: item,
                                    val: i
                                }
                        })
                };
            var calculateSeries = function(self, options) {
                    var series = [],
                        particularSeriesOptions,
                        seriesTheme,
                        data,
                        chartThemeManager = createThemeManager(options.chart),
                        allSeriesOptions = options.chart.series,
                        seriesValueType = options.chart.valueAxis && options.chart.valueAxis.valueType,
                        dataSourceField,
                        chartOptions,
                        i;
                    if (options.dataSource && !allSeriesOptions) {
                        if (isArrayOfSimpleTypes(options.dataSource))
                            options.dataSource = convertToArrayOfObjects(options.dataSource);
                        dataSourceField = options.dataSourceField || 'arg';
                        allSeriesOptions = {
                            argumentField: dataSourceField,
                            valueField: dataSourceField
                        };
                        self._hideChart = true
                    }
                    allSeriesOptions = $.isArray(allSeriesOptions) ? allSeriesOptions : allSeriesOptions ? [allSeriesOptions] : [];
                    chartOptions = chartThemeManager.applyTheme(chartThemeManager.getTheme(), options.chart);
                    $.extend(chartOptions.commonSeriesSettings, {
                        argumentType: options.valueType,
                        valueType: dataSourceField ? options.valueType : seriesValueType,
                        incidentOccured: options.incidentOccured
                    });
                    self._backgroundColor = options.backgroundColor !== undefined ? options.backgroundColor : chartOptions.backgroundColor;
                    for (i = 0; i < allSeriesOptions.length; i++) {
                        particularSeriesOptions = allSeriesOptions[i];
                        particularSeriesOptions.rotated = false;
                        data = particularSeriesOptions.data || options.dataSource;
                        seriesTheme = chartThemeManager.applyNextSeriesTheme(particularSeriesOptions, chartOptions.commonSeriesSettings);
                        if (data && data.length > 0) {
                            var newSeries = charts.factory.createSeries(particularSeriesOptions.type || chartOptions.commonSeriesSettings.type, options.renderer, data, seriesTheme);
                            newSeries._suppressTrackers = true;
                            series.push(newSeries)
                        }
                    }
                    return series
                };
            var processSeriesFamilies = function(series, equalBarWidth) {
                    var families = [],
                        types = [];
                    $.each(series, function(i, item) {
                        if ($.inArray(item.type, types) === -1)
                            types.push(item.type)
                    });
                    $.each(types, function(_, type) {
                        var family = new charts.factory.createSeriesFamily({
                                type: type,
                                equalBarWidth: equalBarWidth
                            });
                        family.add(series);
                        family.adjustSeriesValues();
                        families.push(family)
                    });
                    return families
                };
            var prototypeObject = {
                    ctor: function(options) {
                        var self = this;
                        self._indent = {
                            top: options.chart.topIndent >= 0 && options.chart.topIndent < 1 ? options.chart.topIndent : 0,
                            bottom: options.chart.bottomIndent >= 0 && options.chart.bottomIndent < 1 ? options.chart.bottomIndent : 0
                        };
                        self._valueAxis = options.chart.valueAxis || {};
                        self._hideChart = false;
                        self._series = calculateSeries(self, options);
                        self._seriesFamilies = processSeriesFamilies(self._series, options.chart.equalBarWidth)
                    },
                    adjustSeriesDimensions: function(translator) {
                        var self = this;
                        $.each(self._seriesFamilies, function() {
                            this.adjustSeriesDimensions(translator)
                        })
                    },
                    getBoundRange: function() {
                        var self = this,
                            seriesElement,
                            rangeData,
                            range = new DX.viz.charts.Range({
                                minY: self._valueAxis.min,
                                minVisibleY: self._valueAxis.min,
                                maxY: self._valueAxis.max,
                                maxVisibleY: self._valueAxis.max
                            }),
                            rangeYSize,
                            rangeVisibleSizeY,
                            i,
                            minIndent,
                            maxIndent;
                        for (i = 0; i < self._series.length; i++) {
                            rangeData = self._series[i].getRangeData();
                            range = range.getBoundRange(rangeData)
                        }
                        if (range.isDefined()) {
                            minIndent = self._valueAxis.inverted ? self._indent.top : self._indent.bottom;
                            maxIndent = self._valueAxis.inverted ? self._indent.bottom : self._indent.top;
                            rangeYSize = range.maxY - range.minY;
                            rangeVisibleSizeY = ($.isNumeric(range.maxVisibleY) ? range.maxVisibleY : range.maxY) - ($.isNumeric(range.minVisibleY) ? range.minVisibleY : range.minY);
                            range.minY -= rangeYSize * minIndent;
                            range.maxY += rangeYSize * maxIndent;
                            if ($.isNumeric(rangeVisibleSizeY)) {
                                range.maxVisibleY = range.maxVisibleY ? range.maxVisibleY + rangeVisibleSizeY * maxIndent : undefined;
                                range.minVisibleY = range.minVisibleY ? range.minVisibleY - rangeVisibleSizeY * minIndent : undefined
                            }
                            range.invertY = self._valueAxis.inverted
                        }
                        return range
                    },
                    getSeries: function() {
                        var self = this;
                        return self._series
                    },
                    getBackgroundColor: function() {
                        var self = this;
                        return self._backgroundColor
                    },
                    isEmpty: function() {
                        var self = this;
                        return self.getSeries().length === 0
                    },
                    isShowChart: function() {
                        var self = this;
                        return !self.isEmpty() && !self._hideChart
                    },
                    getCalculatedValueType: function() {
                        var self = this,
                            result;
                        if (self._series.length)
                            result = self._series[0].options.argumentType;
                        return result
                    }
                };
            return prototypeObject
        }())
    })(jQuery, DevExpress);
    /*! Module viz, file utils.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            utils = rangeSelector.utils,
            dxUtils = DX.utils;
        var INVISIBLE_POS = -1000;
        var findLessOrEqualValueIndex = function(values, value) {
                if (!values || values.length === 0)
                    return -1;
                var minIndex = 0,
                    maxIndex = values.length - 1,
                    index = 0;
                while (maxIndex - minIndex > 1) {
                    var index = minIndex + maxIndex >> 1;
                    if (values[index] > value)
                        maxIndex = index;
                    else
                        minIndex = index
                }
                return values[maxIndex] <= value ? maxIndex : minIndex
            };
        var findLessOrEqualValue = function(values, value) {
                var index = findLessOrEqualValueIndex(values, value);
                if (values && index >= 0 && index < values.length)
                    return values[index];
                return value
            };
        var findNearValue = function(values, value) {
                var index = findLessOrEqualValueIndex(values, value);
                if (values && index >= 0 && index < values.length) {
                    if (index + 1 < values.length)
                        if (dxUtils.isDate(value)) {
                            if (values[index + 1].getTime() - value.getTime() < value.getTime() - values[index].getTime())
                                index++
                        }
                        else if (values[index + 1] - value < value - values[index])
                            index++;
                    return values[index]
                }
                return value
            };
        var findGreaterOrEqualValue = function(values, value) {
                var index = findLessOrEqualValueIndex(values, value);
                if (values && index >= 0 && index < values.length) {
                    if (values[index] < value && index + 1 < values.length)
                        index++;
                    return values[index]
                }
                return value
            };
        var getInterval = function(valueMin, valueMax, delta) {
                var result,
                    minDateDaysCount,
                    maxDateDaysCount,
                    daysCount,
                    prevMaxDaysCount;
                if (dxUtils.isDate(valueMin)) {
                    if (delta === 'year' || delta === 'quarter' || delta === 'month')
                        return {months: valueMax.getFullYear() * 12 + valueMax.getMonth() - valueMin.getFullYear() * 12 - valueMin.getMonth()};
                    else
                        return {milliseconds: valueMax.valueOf() - valueMin.valueOf()};
                    return result
                }
                else
                    return valueMax - valueMin
            };
        var getRootOffsetLeft = function(renderer) {
                var node,
                    result = 0,
                    root = renderer.getRoot();
                if (root) {
                    node = root.element;
                    if (node.getScreenCTM)
                        result = node.createSVGPoint().matrixTransform(node.getScreenCTM()).x;
                    else
                        result = $(node).offset().left
                }
                return result
            };
        var getEventPageX = function(eventArgs) {
                var result = 0;
                if (eventArgs.pageX)
                    result = eventArgs.pageX;
                else if (eventArgs.originalEvent && eventArgs.originalEvent.pageX)
                    result = eventArgs.originalEvent.pageX;
                if (eventArgs.originalEvent && eventArgs.originalEvent.touches)
                    if (eventArgs.originalEvent.touches.length > 0)
                        result = eventArgs.originalEvent.touches[0].pageX;
                    else if (eventArgs.originalEvent.changedTouches.length > 0)
                        result = eventArgs.originalEvent.changedTouches[0].pageX;
                return result
            };
        var getTextBBox = function(renderer, text, fontOptions) {
                var textElement = renderer.createText(text, INVISIBLE_POS, INVISIBLE_POS, {font: fontOptions}).append();
                var textBBox = textElement.getBBox();
                textElement.remove();
                return textBBox
            };
        utils.findLessOrEqualValue = findLessOrEqualValue;
        utils.findNearValue = findNearValue;
        utils.findGreaterOrEqualValue = findGreaterOrEqualValue;
        utils.getInterval = getInterval;
        utils.getRootOffsetLeft = getRootOffsetLeft;
        utils.getEventPageX = getEventPageX;
        utils.getTextBBox = getTextBBox
    })(jQuery, DevExpress);
    /*! Module viz, file themeManager.js */
    (function($, DX, undefined) {
        DX.viz.rangeSelector = DX.viz.rangeSelector;
        DX.viz.rangeSelector.ThemeManager = DX.viz.core.BaseThemeManager.inherit({
            ctor: function(userTheme) {
                var self = this;
                self.callBase(userTheme, 'rangeSelector');
                self.initializeFont(self.theme.scale.label.font);
                self.initializeFont(self.theme.sliderMarker.font)
            },
            applyRangeSelectorTheme: function(userOptions) {
                var self = this,
                    refs = {dataSource: userOptions.dataSource},
                    result;
                delete userOptions.dataSource;
                result = self.applyTheme(self.theme, userOptions);
                result.dataSource = refs.dataSource;
                return result
            },
            setBackgroundColor: function(containerBackgroundColor) {
                var theme = this.theme;
                if (containerBackgroundColor)
                    theme.containerBackgroundColor = containerBackgroundColor;
                theme.shutter.color = theme.shutter.color || theme.containerBackgroundColor
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz, file viz.js */
    (function(DevExpress) {
        var viz = DevExpress.viz;
        viz.Chart = viz.charts.Chart;
        viz.PieChart = viz.charts.PieChart;
        viz.RangeSelector = viz.rangeSelector.RangeSelector;
        viz.CircularGauge = viz.gauges.CircularGauge;
        viz.LinearGauge = viz.gauges.LinearGauge
    })(DevExpress);
    /*! Module viz, file dxChart.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            viz = DX.viz;
        ui.registerComponent("dxChart", viz.Chart)
    })(jQuery, DevExpress);
    /*! Module viz, file dxPieChart.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            viz = DX.viz;
        ui.registerComponent("dxPieChart", viz.PieChart)
    })(jQuery, DevExpress);
    /*! Module viz, file dxCircularGauge.js */
    (function(DX, undefined) {
        DX.ui.registerComponent("dxCircularGauge", DX.viz.CircularGauge)
    })(DevExpress);
    /*! Module viz, file dxLinearGauge.js */
    (function(DX, undefined) {
        DX.ui.registerComponent("dxLinearGauge", DX.viz.LinearGauge)
    })(DevExpress);
    /*! Module viz, file dxRangeSelector.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            viz = DX.viz;
        ui.registerComponent("dxRangeSelector", viz.RangeSelector)
    })(jQuery, DevExpress);
    DevExpress.MOD_VIZ = true
}
