/*! 
* DevExtreme Web
* Version: 14.1.7
* Build date: Sep 22, 2014
*
* Copyright (c) 2012 - 2014 Developer Express Inc. ALL RIGHTS RESERVED
* EULA: https://www.devexpress.com/Support/EULAs/DevExtreme.xml
*/

"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] < 10)
                throw Error("Your version of jQuery is too old. Please upgrade jQuery to 1.10.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 that = this;
                        if (!members)
                            return that;
                        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(that.prototype[this]) && $.isFunction(members[this]);
                            that.prototype[this] = overridden ? wrapOverridden(that.parent.prototype, this, members[this]) : members[this]
                        });
                        return that
                    };
                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 === global || typeof this.constructor !== "function")
                                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
            }();
        function createQueue(discardPendingTasks) {
            var _tasks = [],
                _busy = false;
            function exec() {
                while (_tasks.length) {
                    _busy = true;
                    var task = _tasks.shift(),
                        result = task();
                    if (result === undefined)
                        continue;
                    if (result.then) {
                        $.when(result).always(exec);
                        return
                    }
                    throw Error("Queued task returned unexpected result");
                }
                _busy = false
            }
            function add(task, removeTaskCallback) {
                if (!discardPendingTasks)
                    _tasks.push(task);
                else {
                    if (_tasks[0] && removeTaskCallback)
                        removeTaskCallback(_tasks[0]);
                    _tasks = [task]
                }
                if (!_busy)
                    exec()
            }
            function busy() {
                return _busy
            }
            return {
                    add: add,
                    busy: busy
                }
        }
        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 hideTopOverlayCallback = function() {
                var callbacks = [];
                return {
                        add: function(callback) {
                            var indexOfCallback = $.inArray(callback, callbacks);
                            if (indexOfCallback === -1)
                                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
                        },
                        hasCallback: function() {
                            return callbacks.length > 0
                        },
                        reset: function() {
                            callbacks = []
                        }
                    }
            }();
        var overlayTargetContainer = function() {
                var defaultTargetContainer = "body";
                return function(targetContainer) {
                        if (arguments.length)
                            defaultTargetContainer = targetContainer;
                        return defaultTargetContainer
                    }
            }();
        $.extend(global.DevExpress, {
            VERSION: "14.1.7",
            abstract: function() {
                throw Error("Not implemented");
            },
            Class: Class,
            createQueue: createQueue,
            enqueue: createQueue().add,
            enqueueAsync: enqueueAsync,
            parseUrl: parseUrl,
            hideTopOverlayCallback: hideTopOverlayCallback,
            hardwareBackButton: $.Callbacks(),
            overlayTargetContainer: overlayTargetContainer,
            rtlEnabled: false
        })
    })(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 utils.common.js */
    (function($, DX, undefined) {
        var isDefined = function(object) {
                return object !== null && object !== undefined
            };
        var isString = function(object) {
                return $.type(object) === 'string'
            };
        var isNumber = function(object) {
                return typeof object === "number" && isFinite(object) || $.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 isExponential = function(value) {
                return isNumber(value) && value.toString().indexOf('e') !== -1
            };
        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 clone = function() {
                function Clone(){}
                return 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()
            };
        var stringFormat = function() {
                var s = arguments[0];
                for (var i = 0; i < arguments.length - 1; i++) {
                    var reg = new RegExp("\\{" + i + "\\}", "gm");
                    s = s.replace(reg, arguments[i + 1])
                }
                return s
            };
        var findBestMatches = function(targetFilter, items, mapFn) {
                var bestMatches = [],
                    maxMatchCount = 0;
                $.each(items, function(index, itemSrc) {
                    var matchCount = 0,
                        item = mapFn ? mapFn(itemSrc) : itemSrc;
                    $.each(targetFilter, function(paramName) {
                        var value = item[paramName];
                        if (value === undefined)
                            return;
                        if (value === targetFilter[paramName]) {
                            matchCount++;
                            return
                        }
                        matchCount = -1;
                        return false
                    });
                    if (matchCount < maxMatchCount)
                        return;
                    if (matchCount > maxMatchCount) {
                        bestMatches.length = 0;
                        maxMatchCount = matchCount
                    }
                    bestMatches.push(itemSrc)
                });
                return bestMatches
            };
        var preg_quote = function(str) {
                return (str + "").replace(/([\+\*\?\\\.\[\^\]\$\(\)\{\}\>\<\|\=\!\:])/g, "\\$1")
            };
        var replaceAll = function(text, searchToken, replacementToken) {
                return text.replace(new RegExp("(" + preg_quote(searchToken) + ")", "gi"), replacementToken)
            };
        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 stringPairToObject = function(raw) {
                var pair = splitPair(raw),
                    x = parseInt(pair && pair[0], 10),
                    y = parseInt(pair && pair[1], 10);
                if (!isFinite(x))
                    x = 0;
                if (!isFinite(y))
                    y = x;
                return {
                        x: x,
                        y: y
                    }
            };
        function icontains(elem, text) {
            var result = false;
            $.each($(elem).contents(), function(index, content) {
                if (content.nodeType === 3 && (content.textContent || content.nodeValue || "").toLowerCase().indexOf((text || "").toLowerCase()) > -1) {
                    result = true;
                    return false
                }
            });
            return result
        }
        $.expr[":"].dxicontains = $.expr.createPseudo(function(text) {
            return function(elem) {
                    return icontains(elem, text)
                }
        });
        function deepExtendArraySafe(target, changes) {
            var prevValue,
                newValue;
            for (var name in changes) {
                prevValue = target[name];
                newValue = changes[name];
                if (target === newValue)
                    continue;
                if ($.isPlainObject(newValue) && !(newValue instanceof $.Event))
                    target[name] = deepExtendArraySafe($.isPlainObject(prevValue) ? prevValue : {}, newValue);
                else if (newValue !== undefined)
                    target[name] = newValue
            }
            return target
        }
        function unwrapObservable(value) {
            if (DX.support.hasKo)
                return ko.utils.unwrapObservable(value);
            return value
        }
        DX.utils = {
            isDefined: isDefined,
            isString: isString,
            isNumber: isNumber,
            isObject: isObject,
            isArray: isArray,
            isDate: isDate,
            isFunction: isFunction,
            isExponential: isExponential,
            extendFromObject: extendFromObject,
            clone: clone,
            executeAsync: executeAsync,
            stringFormat: stringFormat,
            findBestMatches: findBestMatches,
            replaceAll: replaceAll,
            deepExtendArraySafe: deepExtendArraySafe,
            splitPair: splitPair,
            stringPairToObject: stringPairToObject,
            unwrapObservable: unwrapObservable
        }
    })(jQuery, DevExpress);
    /*! Module core, file utils.console.js */
    (function($, DX, undefined) {
        var logger = function() {
                var console = window.console;
                function info(text) {
                    if (!console || !$.isFunction(console.info))
                        return;
                    console.info(text)
                }
                function warn(text) {
                    if (!console || !$.isFunction(console.warn))
                        return;
                    console.warn(text)
                }
                function error(text) {
                    if (!console || !$.isFunction(console.error))
                        return;
                    console.error(text)
                }
                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
                    }
            }();
        $.extend(DX.utils, {
            logger: logger,
            debug: debug
        })
    })(jQuery, DevExpress);
    /*! Module core, file utils.math.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 isNumber = DX.utils.isNumber,
            isExponential = DX.utils.isExponential;
        var getPrecision = function(value) {
                var stringFraction,
                    stringValue = value.toString(),
                    pointIndex = stringValue.indexOf('.'),
                    startIndex,
                    precision;
                if (isExponential(value)) {
                    precision = getDecimalOrder(value);
                    if (precision < 0)
                        return Math.abs(precision);
                    else
                        return 0
                }
                if (pointIndex !== -1) {
                    startIndex = pointIndex + 1;
                    stringFraction = stringValue.substring(startIndex, startIndex + 20);
                    return stringFraction.length
                }
                return 0
            };
        var getLog = function(value, base) {
                if (!value)
                    return 0;
                return Math.log(value) / Math.log(base)
            };
        var raiseTo = function(power, base) {
                return Math.pow(base, power)
            };
        var sign = function(value) {
                if (value === 0)
                    return 0;
                return value / abs(value)
            };
        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 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 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 roundValue = function(value, precision) {
                if (precision > 20)
                    precision = 20;
                if (isNumber(value))
                    if (isExponential(value))
                        return Number(value.toExponential(precision));
                    else
                        return Number(value.toFixed(precision))
            };
        var applyPrecisionByMinDelta = function(min, delta, value) {
                var minPrecision = getPrecision(min),
                    deltaPrecision = getPrecision(delta);
                return roundValue(value, minPrecision < deltaPrecision ? deltaPrecision : minPrecision)
            };
        $.extend(DX.utils, {
            getLog: getLog,
            raiseTo: raiseTo,
            sign: sign,
            normalizeAngle: normalizeAngle,
            convertAngleToRendererSpace: convertAngleToRendererSpace,
            degreesToRadians: degreesToRadians,
            getCosAndSin: getCosAndSin,
            getDecimalOrder: getDecimalOrder,
            getAppropriateFormat: getAppropriateFormat,
            getFraction: getFraction,
            adjustValue: adjustValue,
            roundValue: roundValue,
            applyPrecisionByMinDelta: applyPrecisionByMinDelta,
            getSignificantDigitPosition: getSignificantDigitPosition
        });
        DX.utils.getPrecision = getPrecision
    })(jQuery, DevExpress);
    /*! Module core, file utils.date.js */
    (function($, DX, undefined) {
        var isObject = DX.utils.isObject,
            isString = DX.utils.isString,
            isDate = DX.utils.isDate;
        var dateUnitIntervals = ['millisecond', 'second', 'minute', 'hour', 'day', 'week', 'month', 'quarter', 'year'];
        var addSubValues = function(value1, value2, isSub) {
                return value1 + (isSub ? -1 : 1) * value2
            };
        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
                }
            };
        function parseISO8601(isoString) {
            var result = new Date(0);
            var chunks = isoString.replace("Z", "").split("T"),
                date = String(chunks[0]).split("-"),
                time = String(chunks[1]).split(":");
            var year,
                month,
                day,
                hours,
                minutes,
                seconds,
                milliseconds;
            year = Number(date[0]);
            month = Number(date[1]) - 1;
            day = Number(date[2]);
            result.setUTCDate(day);
            result.setUTCMonth(month);
            result.setUTCFullYear(year);
            if (time.length) {
                hours = Number(time[0]);
                minutes = Number(time[1]);
                seconds = Number(String(time[2]).split(".")[0]);
                milliseconds = Number(String(time[2]).split(".")[1]) || 0;
                result.setUTCHours(hours);
                result.setUTCMinutes(minutes);
                result.setUTCSeconds(seconds);
                result.setUTCMilliseconds(milliseconds)
            }
            return result
        }
        function formatISO8601(date) {
            function pad(n) {
                if (n < 10)
                    return "0".concat(n);
                return String(n)
            }
            return [date.getFullYear(), "-", pad(date.getMonth() + 1), "-", pad(date.getDate()), "T", pad(date.getHours()), ":", pad(date.getMinutes()), ":", pad(date.getSeconds()), "Z"].join("")
        }
        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 convertDateUnitToMilliseconds = function(dateUnit, count) {
                return toMilliseconds(dateUnit) * count
            };
        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 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 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 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 sameMonthAndYear = function(date1, date2) {
                return date1 && date2 && date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth()
            };
        var getFirstMonthDate = function(date) {
                return new Date(date.getFullYear(), date.getMonth(), 1)
            };
        var dateInRange = function(date, min, max) {
                return normalizeDate(date, min, max) === date
            };
        var normalizeDate = function(date, min, max) {
                var normalizedDate = date;
                if (date < min)
                    normalizedDate = min;
                else if (date > max)
                    normalizedDate = max;
                return normalizedDate
            };
        var getPower = function(value) {
                return value.toExponential().split("e")[1]
            };
        $.extend(DX.utils, {
            dateUnitIntervals: dateUnitIntervals,
            parseIso8601Date: parseISO8601,
            formatIso8601Date: formatISO8601,
            convertMillisecondsToDateUnits: convertMillisecondsToDateUnits,
            convertDateTickIntervalToMilliseconds: convertDateTickIntervalToMilliseconds,
            convertDateUnitToMilliseconds: convertDateUnitToMilliseconds,
            getDateUnitInterval: getDateUnitInterval,
            getDatesDifferences: getDatesDifferences,
            correctDateWithUnitBeginning: correctDateWithUnitBeginning,
            addInterval: addInterval,
            getDateIntervalByString: getDateIntervalByString,
            sameMonthAndYear: sameMonthAndYear,
            getFirstMonthDate: getFirstMonthDate,
            dateInRange: dateInRange,
            normalizeDate: normalizeDate,
            getPower: getPower
        })
    })(jQuery, DevExpress);
    /*! Module core, file utils.dom.js */
    (function($, DX, undefined) {
        var IOS_APP_BAR_HEIGHT = "20px";
        var timeRedrawOnResize = 100;
        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()
                        }, timeRedrawOnResize)
                    };
                handler.stop = function() {
                    clearTimeout(timeout);
                    return this
                };
                return handler
            };
        var windowResizeCallbacks = function() {
                var prevSize,
                    callbacks = $.Callbacks(),
                    jqWindow = $(window),
                    resizeEventHandlerAttached = false,
                    originalCallbacksAdd = callbacks.add,
                    originalCallbacksRemove = callbacks.remove;
                var formatSize = function() {
                        return [jqWindow.width(), jqWindow.height()].join()
                    };
                var handleResize = function() {
                        var now = formatSize();
                        if (now === prevSize)
                            return;
                        prevSize = now;
                        setTimeout(callbacks.fire)
                    };
                prevSize = formatSize();
                callbacks.add = function() {
                    var result = originalCallbacksAdd.apply(callbacks, arguments);
                    if (!resizeEventHandlerAttached && callbacks.has()) {
                        jqWindow.on("resize", handleResize);
                        resizeEventHandlerAttached = true
                    }
                    return result
                };
                callbacks.remove = function() {
                    var result = originalCallbacksRemove.apply(callbacks, arguments);
                    if (!callbacks.has() && resizeEventHandlerAttached) {
                        jqWindow.off("resize", handleResize);
                        resizeEventHandlerAttached = false
                    }
                    return result
                };
                return callbacks
            }();
        var resetActiveElement = function() {
                var activeElement = document.activeElement;
                if (activeElement && activeElement !== document.body && activeElement.blur)
                    activeElement.blur()
            };
        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 initMobileViewport = function(options) {
                options = $.extend({}, options);
                var device = DX.devices.current();
                var realDevice = DX.devices.real();
                var allowZoom = options.allowZoom,
                    allowPan = options.allowPan,
                    allowSelection = "allowSelection" in options ? options.allowSelection : device.platform == "desktop";
                DX.overlayTargetContainer(".dx-viewport");
                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, user-scalable=no");
                if (allowPan)
                    msTouchVerbs.push("pan-x", "pan-y");
                if (!allowPan && !allowZoom)
                    $("html, body").css({
                        "-ms-content-zooming": "none",
                        "-ms-user-select": "none",
                        overflow: "hidden"
                    });
                else
                    $("html").css("-ms-overflow-style", "-ms-autohiding-scrollbar");
                if (!allowSelection) {
                    if (realDevice.ios)
                        $(document).on("selectstart", function() {
                            return false
                        });
                    $(".dx-viewport").css("user-select", "none")
                }
                $(metaSelector).attr("content", metaVerbs.join());
                $("html").css("-ms-touch-action", msTouchVerbs.join(" ") || "none");
                if (DX.support.touch)
                    $(document).off(".dxInitMobileViewport").on("touchmove.dxInitMobileViewport", function(e) {
                        var count = e.originalEvent.touches.length,
                            zoomDisabled = !allowZoom && count > 1,
                            panDisabled = !allowPan && count === 1 && !e.isScrollingEvent;
                        if (zoomDisabled || panDisabled)
                            e.preventDefault()
                    });
                realDevice = DX.devices.real();
                if (realDevice.ios) {
                    var isPhoneGap = document.location.protocol === "file:";
                    if (!isPhoneGap)
                        windowResizeCallbacks.add(function() {
                            var windowWidth = $(window).width();
                            $("body").width(windowWidth)
                        });
                    else if (realDevice.version[0] > 6) {
                        $(".dx-viewport").css("position", "relative");
                        $("body").css({"box-sizing": "border-box"});
                        $("body").css("padding-top", IOS_APP_BAR_HEIGHT);
                        if (realDevice.version[0] === 7 && realDevice.version[1] < 1) {
                            var setDeviceHeight = function() {
                                    var deviceHeight = "height=device-" + (Math.abs(window.orientation) === 90 ? "width" : "height");
                                    $(metaSelector).attr("content", metaVerbs.join() + "," + deviceHeight)
                                };
                            $(window).on("orientationchange", setDeviceHeight);
                            setDeviceHeight()
                        }
                    }
                }
            };
        var triggerVisibilityChangeEvent = function(event) {
                return function(element) {
                        $(element || "body").find(".dx-visibility-change-handler").each(function() {
                            $(this).triggerHandler(event)
                        })
                    }
            };
        $.extend(DX.utils, {
            createResizeHandler: createResizeHandler,
            windowResizeCallbacks: windowResizeCallbacks,
            resetActiveElement: resetActiveElement,
            createMarkupFromString: createMarkupFromString,
            triggerShownEvent: triggerVisibilityChangeEvent("dxshown"),
            triggerHidingEvent: triggerVisibilityChangeEvent("dxhiding"),
            initMobileViewport: initMobileViewport
        });
        DX.utils.__timeRedrawOnResize = timeRedrawOnResize
    })(jQuery, DevExpress);
    /*! Module core, file utils.graphics.js */
    (function($, DX, undefined) {
        var isFunction = DX.utils.isFunction,
            iDevice = /iphone|ipad/.test(navigator.userAgent.toLowerCase());
        var processSeriesTemplate = function(seriesTemplate, items) {
                var customizeSeries = isFunction(seriesTemplate.customizeSeries) ? seriesTemplate.customizeSeries : $.noop,
                    nameField = seriesTemplate.nameField || 'series',
                    generatedSeries = {},
                    seriesOrder = [],
                    series;
                for (var i = 0, length = items.length; i < length; i++) {
                    var data = items[i];
                    if (nameField in data) {
                        series = generatedSeries[data[nameField]];
                        if (!series) {
                            series = generatedSeries[data[nameField]] = {
                                name: data[nameField],
                                data: []
                            };
                            seriesOrder.push(series.name)
                        }
                        series.data.push(data)
                    }
                }
                return $.map(seriesOrder, function(orderedName) {
                        var group = generatedSeries[orderedName],
                            seriesOptions = customizeSeries.call(null, group.name);
                        return $.extend(group, seriesOptions)
                    })
            };
        var getNextDefsSvgId = function() {
                var numDefsSvgElements = 1;
                return function() {
                        return 'DevExpress_' + numDefsSvgElements++
                    }
            }();
        var getRootOffset = function(renderer) {
                var node,
                    result = {
                        left: 0,
                        top: 0
                    },
                    pointTransform,
                    root = renderer.getRoot();
                if (root) {
                    node = root.element;
                    if (node.getScreenCTM && !iDevice) {
                        var ctm = node.getScreenCTM();
                        if (ctm) {
                            pointTransform = node.createSVGPoint().matrixTransform(ctm);
                            result.left = pointTransform.x + (document.body.scrollLeft || document.documentElement.scrollLeft);
                            result.top = pointTransform.y + (document.body.scrollTop || document.documentElement.scrollTop)
                        }
                        else {
                            result.left = document.body.scrollLeft || document.documentElement.scrollLeft;
                            result.top = document.body.scrollTop || document.documentElement.scrollTop
                        }
                    }
                    else
                        result = $(node).offset()
                }
                return result
            };
        $.extend(DX.utils, {
            processSeriesTemplate: processSeriesTemplate,
            getNextDefsSvgId: getNextDefsSvgId,
            getRootOffset: getRootOffset
        })
    })(jQuery, DevExpress);
    /*! Module core, file utils.arrays.js */
    (function($, DX, undefined) {
        var wrapToArray = function(entity) {
                return $.isArray(entity) ? entity : [entity]
            };
        var removeDublicates = function(from, what) {
                if (!$.isArray(from) || from.length === 0)
                    return [];
                if (!$.isArray(what) || what.length === 0)
                    return from.slice();
                var result = [];
                $.each(from, function(_, value) {
                    var bIndex = $.inArray(value, what);
                    if (bIndex === -1)
                        result.push(value)
                });
                return result
            };
        $.extend(DX.utils, {
            wrapToArray: wrapToArray,
            removeDublicates: removeDublicates
        })
    })(jQuery, DevExpress);
    /*! Module core, file devices.js */
    (function($, DX, undefined) {
        var KNOWN_UA_TABLE = {
                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 Mobile"
            };
        var DEFAULT_DEVICE = {
                deviceType: "",
                platform: "",
                version: [],
                phone: false,
                tablet: false,
                android: false,
                ios: false,
                win8: false,
                tizen: false,
                generic: false
            };
        var GENERIC_DEVICE = $.extend(DEFAULT_DEVICE, {
                platform: "generic",
                deviceType: "desktop",
                generic: true
            });
        var uaParsers = {
                win8: function(userAgent) {
                    var isPhone = /windows phone/i.test(userAgent),
                        isTablet = !isPhone && /arm(.*)trident/i.test(userAgent),
                        isDesktop = !isPhone && !isTablet && /msapphost/i.test(userAgent);
                    if (!(isPhone || isTablet || isDesktop))
                        return;
                    var matches = userAgent.match(/windows phone (\d+).(\d+)/i) || userAgent.match(/windows nt (\d+).(\d+)/i),
                        version = matches ? [parseInt(matches[1], 10), parseInt(matches[2], 10)] : [];
                    return {
                            deviceType: isPhone ? "phone" : isTablet ? "tablet" : "desktop",
                            platform: "win8",
                            version: version
                        }
                },
                ios: function(userAgent) {
                    if (!/ip(hone|od|ad)/i.test(userAgent))
                        return;
                    var isPhone = /ip(hone|od)/i.test(userAgent);
                    var matches = userAgent.match(/os (\d+)_(\d+)_?(\d+)?/i);
                    var version = matches ? [parseInt(matches[1], 10), parseInt(matches[2], 10), parseInt(matches[3] || 0, 10)] : [];
                    return {
                            deviceType: isPhone ? "phone" : "tablet",
                            platform: "ios",
                            version: version
                        }
                },
                android: function(userAgent) {
                    if (!/android|htc_|silk/i.test(userAgent))
                        return;
                    var isPhone = /mobile/i.test(userAgent);
                    var matches = userAgent.match(/android (\d+)\.(\d+)\.?(\d+)?/i);
                    var version = matches ? [parseInt(matches[1], 10), parseInt(matches[2], 10), parseInt(matches[3] || 0, 10)] : [];
                    return {
                            deviceType: isPhone ? "phone" : "tablet",
                            platform: "android",
                            version: version
                        }
                },
                tizen: function(userAgent) {
                    if (!/tizen/i.test(userAgent))
                        return;
                    var isPhone = /mobile/i.test(userAgent);
                    var matches = userAgent.match(/tizen (\d+)\.(\d+)/i);
                    var version = matches ? [parseInt(matches[1], 10), parseInt(matches[2], 10)] : [];
                    return {
                            deviceType: isPhone ? "phone" : "tablet",
                            platform: "tizen",
                            version: version
                        }
                }
            };
        DX.Devices = DX.Class.inherit({
            ctor: function(options) {
                this._window = options && options.window || window;
                this._realDevice = this._getDevice();
                this._currentDevice = undefined;
                this._currentOrientation = undefined;
                this.orientationChanged = $.Callbacks();
                this._recalculateOrientation();
                DX.utils.windowResizeCallbacks.add($.proxy(this._recalculateOrientation, this))
            },
            current: function(deviceOrName) {
                if (deviceOrName) {
                    this._currentDevice = this._getDevice(deviceOrName);
                    DX.ui.themes.init({_autoInit: true})
                }
                else {
                    if (!this._currentDevice) {
                        deviceOrName = undefined;
                        try {
                            deviceOrName = this._getDeviceOrNameFromWindowScope()
                        }
                        catch(e) {
                            deviceOrName = this._getDeviceNameFromSessionStorage()
                        }
                        finally {
                            if (!deviceOrName)
                                deviceOrName = this._getDeviceNameFromSessionStorage()
                        }
                        this._currentDevice = this._getDevice(deviceOrName)
                    }
                    return this._currentDevice
                }
            },
            real: function() {
                var forceDevice = arguments[0];
                if ($.isPlainObject(forceDevice)) {
                    $.extend(this._realDevice, forceDevice);
                    return
                }
                return $.extend({}, this._realDevice)
            },
            orientation: function() {
                return this._currentOrientation
            },
            isRippleEmulator: function() {
                return !!this._window.tinyHippos
            },
            attachCssClasses: function(element, device) {
                var realDevice = this._realDevice,
                    $element = $(element);
                device = device || this.current();
                if (device.deviceType)
                    $element.addClass("dx-device-" + device.deviceType);
                $element.addClass("dx-device-" + realDevice.platform);
                if (realDevice.version && realDevice.version.length)
                    $element.addClass("dx-device-" + realDevice.platform + "-" + realDevice.version[0]);
                if (DX.devices.isSimulator())
                    $element.addClass("dx-simulator");
                if (DX.rtlEnabled)
                    $element.addClass("dx-rtl")
            },
            isSimulator: function() {
                try {
                    return this._isSimulator || this._window.top !== this._window.self && this._window.top["dx-force-device"] || this.isRippleEmulator()
                }
                catch(e) {
                    return false
                }
            },
            forceSimulator: function() {
                this._isSimulator = true
            },
            _getDevice: function(deviceName) {
                if (deviceName === "genericPhone")
                    deviceName = {
                        deviceType: "phone",
                        platform: "generic",
                        generic: true
                    };
                if ($.isPlainObject(deviceName))
                    return this._fromConfig(deviceName);
                else {
                    var ua;
                    if (deviceName) {
                        ua = KNOWN_UA_TABLE[deviceName];
                        if (!ua)
                            throw Error("Unknown device");
                    }
                    else
                        ua = navigator.userAgent;
                    return this._fromUA(ua)
                }
            },
            _getDeviceOrNameFromWindowScope: function() {
                var result;
                if (this._window.top["dx-force-device-object"] || this._window.top["dx-force-device"])
                    result = this._window.top["dx-force-device-object"] || this._window.top["dx-force-device"];
                return result
            },
            _getDeviceNameFromSessionStorage: function() {
                return this._window.sessionStorage && (sessionStorage.getItem("dx-force-device") || sessionStorage.getItem("dx-simulator-device"))
            },
            _fromConfig: function(config) {
                var shortcuts = {
                        phone: config.deviceType === "phone",
                        tablet: config.deviceType === "tablet",
                        android: config.platform === "android",
                        ios: config.platform === "ios",
                        win8: config.platform === "win8",
                        tizen: config.platform === "tizen",
                        generic: config.platform === "generic"
                    };
                return $.extend({}, DEFAULT_DEVICE, this._currentDevice, shortcuts, config)
            },
            _fromUA: function(ua) {
                var config;
                $.each(uaParsers, function(platform, parser) {
                    config = parser(ua);
                    return !config
                });
                if (config)
                    return this._fromConfig(config);
                return GENERIC_DEVICE
            },
            _changeOrientation: function() {
                var $window = $(this._window),
                    orientation = $window.height() > $window.width() ? "portrait" : "landscape";
                if (this._currentOrientation === orientation)
                    return;
                this._currentOrientation = orientation;
                this.orientationChanged.fire({orientation: orientation})
            },
            _recalculateOrientation: function() {
                var windowWidth = $(this._window).width();
                if (this._currentWidth === windowWidth)
                    return;
                this._currentWidth = windowWidth;
                this._changeOrientation()
            }
        });
        DX.devices = new DX.Devices
    })(jQuery, DevExpress);
    /*! Module core, file browser.js */
    (function($, DX, global, undefined) {
        var webkitRegExp = /(webkit)[ \/]([\w.]+)/,
            operaRegExp = /(opera)(?:.*version)?[ \/]([\w.]+)/,
            ieRegExp = /(msie) (\d{1,2}\.\d)/,
            ie11RegExp = /(trident).*rv:(\d{1,2}\.\d)/,
            mozillaRegExp = /(mozilla)(?:.*? rv:([\w.]+))?/;
        var ua = navigator.userAgent.toLowerCase();
        var browser = function() {
                var result = {},
                    matches = webkitRegExp.exec(ua) || operaRegExp.exec(ua) || ieRegExp.exec(ua) || ie11RegExp.exec(ua) || ua.indexOf("compatible") < 0 && mozillaRegExp.exec(ua) || [],
                    browserName = matches[1],
                    browserVersion = matches[2];
                if (browserName === "trident")
                    browserName = "msie";
                if (browserName) {
                    result[browserName] = true;
                    result.version = browserVersion
                }
                return result
            }();
        DX.browser = browser
    })(jQuery, DevExpress, this);
    /*! 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)
            };
        var isNativeScrollingSupported = function(device) {
                var realDevice = DX.devices.real(),
                    realPlatform = realDevice.platform,
                    realVersion = realDevice.version,
                    isObsoleteAndroid = realVersion && realVersion[0] < 4 && realPlatform === "android",
                    isNativeScrollDevice = !isObsoleteAndroid && $.inArray(realPlatform, ["ios", "android", "win8"]) > -1;
                return isNativeScrollDevice
            };
        DX.support = {
            touch: "ontouchstart" in window,
            pointer: window.navigator.pointerEnabled,
            transform3d: supportProp("transform"),
            transition: supportProp("transition"),
            transitionEndEventName: transitionEndEventNames[styleProp("transition")],
            animation: supportProp("animation"),
            nativeScrolling: isNativeScrollingSupported(),
            winJS: "WinJS" in window,
            styleProp: styleProp,
            supportProp: supportProp,
            hasKo: !!window.ko,
            hasNg: !window.ko && !!window.angular,
            inputType: function(type) {
                if (type === "text")
                    return true;
                var input = document.createElement("input");
                try {
                    input.setAttribute("type", type);
                    input.value = "wrongValue";
                    return !input.value
                }
                catch(e) {
                    return false
                }
            }
        }
    })(jQuery, DevExpress, this);
    /*! Module core, file position.js */
    (function($, DX, undefined) {
        var horzRe = /left|right/,
            vertRe = /top|bottom/,
            collisionRe = /fit|flip|none/;
        var normalizeAlign = function(raw) {
                var result = {
                        h: "center",
                        v: "center"
                    };
                var pair = DX.utils.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 values = DX.utils.stringPairToObject(raw);
                return {
                        h: values.x,
                        v: values.y
                    }
            };
        var normalizeCollision = function(raw) {
                var pair = DX.utils.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 calculateOversize = function(data, bounds) {
                var oversize = 0;
                if (data.myLocation < bounds.min)
                    oversize += bounds.min - data.myLocation;
                if (data.myLocation > bounds.max)
                    oversize += data.myLocation - bounds.max;
                return oversize
            };
        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) {
                    var result = false;
                    if (data.myLocation > bounds.max) {
                        data.myLocation = bounds.max;
                        result = true
                    }
                    if (data.myLocation < bounds.min) {
                        data.myLocation = bounds.min;
                        result = true
                    }
                    return result
                },
                flip: function(data, bounds) {
                    if (data.myAlign === "center" && data.atAlign === "center")
                        return false;
                    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);
                        inverseData.oversize = calculateOversize(inverseData, bounds);
                        if (inverseData.myLocation >= bounds.min && inverseData.myLocation <= bounds.max || inverseData.myLocation > data.myLocation || inverseData.oversize < data.oversize) {
                            data.myLocation = inverseData.myLocation;
                            data.oversize = inverseData.oversize;
                            return true
                        }
                    }
                    return false
                }
            };
        var scrollbarWidth;
        var defaultPositionResult = {
                h: {
                    location: 0,
                    flip: false,
                    fit: false,
                    oversize: 0
                },
                v: {
                    location: 0,
                    flip: false,
                    fit: false,
                    oversize: 0
                }
            };
        var calculatePosition = function(what, options) {
                var $what = $(what),
                    currentOffset = $what.offset(),
                    result = $.extend(true, {}, defaultPositionResult, {
                        h: {location: currentOffset.left},
                        v: {location: currentOffset.top}
                    });
                if (!options)
                    return result;
                var my = normalizeAlign(options.my),
                    at = normalizeAlign(options.at),
                    of = options.of || window,
                    offset = normalizeOffset(options.offset),
                    collision = normalizeCollision(options.collision),
                    boundaryOffset = normalizeOffset(options.boundaryOffset);
                var h = {
                        mySize: $what.outerWidth(),
                        myAlign: my.h,
                        atAlign: at.h,
                        offset: offset.h,
                        collision: collision.h,
                        boundaryOffset: boundaryOffset.h
                    };
                var v = {
                        mySize: $what.outerHeight(),
                        myAlign: my.v,
                        atAlign: at.v,
                        offset: offset.v,
                        collision: collision.v,
                        boundaryOffset: boundaryOffset.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),
                            windowWidth = win.width(),
                            windowHeight = win.height(),
                            left = win.scrollLeft(),
                            top = win.scrollTop(),
                            hScrollbar = document.width > document.documentElement.clientWidth,
                            vScrollbar = document.height > document.documentElement.clientHeight,
                            hZoomLevel = DX.support.touch ? document.documentElement.clientWidth / (vScrollbar ? windowWidth - scrollbarWidth : windowWidth) : 1,
                            vZoomLevel = DX.support.touch ? document.documentElement.clientHeight / (hScrollbar ? windowHeight - scrollbarWidth : windowHeight) : 1;
                        if (scrollbarWidth === undefined)
                            scrollbarWidth = calculateScrollbarWidth();
                        return {
                                h: {
                                    min: left + h.boundaryOffset,
                                    max: left + windowWidth / hZoomLevel - h.mySize - h.boundaryOffset
                                },
                                v: {
                                    min: top + v.boundaryOffset,
                                    max: top + windowHeight / vZoomLevel - v.mySize - v.boundaryOffset
                                }
                            }
                    }();
                h.oversize = calculateOversize(h, bounds.h);
                v.oversize = calculateOversize(v, bounds.v);
                if (decolliders[h.collision])
                    result.h[h.collision] = decolliders[h.collision](h, bounds.h);
                if (decolliders[v.collision])
                    result.v[v.collision] = decolliders[v.collision](v, bounds.v);
                $.extend(true, result, {
                    h: {
                        location: Math.round(h.myLocation),
                        oversize: Math.round(h.oversize)
                    },
                    v: {
                        location: Math.round(v.myLocation),
                        oversize: Math.round(v.oversize)
                    }
                });
                return result
            };
        var position = function(what, options) {
                var $what = $(what);
                if (!options)
                    return $what.offset();
                DX.translator.resetPosition($what);
                var offset = $what.offset(),
                    targetPosition = options.h && options.v ? options : calculatePosition($what, options);
                DX.translator.move($what, {
                    left: Math.round(targetPosition.h.location - offset.left),
                    top: Math.round(targetPosition.v.location - offset.top)
                });
                return targetPosition
            };
        $.extend(DX, {
            calculatePosition: calculatePosition,
            position: position,
            inverseAlign: inverseAlign
        });
        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._excludeValidators = config.excludeValidators
                },
                execute: function() {
                    var e = {
                            action: this._action,
                            args: Array.prototype.slice.call(arguments),
                            context: this._context,
                            component: this._component,
                            cancel: false,
                            handled: false
                        };
                    if (!this._validateAction(e))
                        return;
                    this._beforeExecute.call(this._context, e);
                    if (e.cancel)
                        return;
                    var result = this._executeAction(e);
                    this._afterExecute.call(this._context, e);
                    return result
                },
                _validateAction: function(e) {
                    var excludeValidators = this._excludeValidators;
                    $.each(actionExecutors, function(name, executor) {
                        if (excludeValidators && $.inArray(name, excludeValidators) > -1)
                            return;
                        if (executor.validate)
                            executor.validate(e);
                        if (e.cancel)
                            return false
                    });
                    return !e.cancel
                },
                _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 translator.js */
    (function($, DX, undefined) {
        var support = DX.support,
            TRANSLATOR_DATA_KEY = "dxTranslator",
            TRANSFORM_MATRIX_REGEX = /matrix(3d)?\((.+?)\)/,
            TRANSLATE_REGEX = /translate(?:3d)?\((.+?)\)/;
        var locate = function($element) {
                var result,
                    position,
                    finalPosition;
                if (support.transform3d) {
                    var translate = getTranslate($element);
                    result = {
                        left: translate.x,
                        top: translate.y
                    }
                }
                else {
                    var originalTop = $element.css("top"),
                        originalLeft = $element.css("left");
                    position = $element.position();
                    $element.css({
                        transform: "none",
                        top: 0,
                        left: 0
                    });
                    clearCache($element);
                    finalPosition = $element.position();
                    result = {
                        left: position.left - finalPosition.left || parseInt(originalLeft) || 0,
                        top: position.top - finalPosition.top || parseInt(originalTop) || 0
                    };
                    $element.css({
                        top: originalTop,
                        left: originalLeft
                    })
                }
                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 || 0;
                if (top !== undefined)
                    translate.y = top || 0;
                $element.css({transform: getTranslateCss(translate)});
                if (isPersentValue(left) || isPersentValue(top))
                    clearCache($element)
            };
        var isPersentValue = function(value) {
                return $.type(value) === "string" && value[value.length - 1] === "%"
            };
        var getTranslate = function($element) {
                var result = $element.data(TRANSLATOR_DATA_KEY);
                if (!result) {
                    var transformValue = $element.css("transform") || getTranslateCss({
                            x: 0,
                            y: 0
                        }),
                        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];
                    result = {
                        x: parseFloat(matrix[0]),
                        y: parseFloat(matrix[1]),
                        z: parseFloat(matrix[2])
                    };
                    cacheTranslate($element, result)
                }
                return result
            };
        var cacheTranslate = function($element, translate) {
                $element.data(TRANSLATOR_DATA_KEY, translate)
            };
        var clearCache = function($element) {
                $element.removeData(TRANSLATOR_DATA_KEY)
            };
        var resetPosition = function($element) {
                $element.css({
                    left: 0,
                    top: 0,
                    transform: "none"
                });
                clearCache($element)
            };
        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) {
                translate.x = translate.x || 0;
                translate.y = translate.y || 0;
                var xValueString = isPersentValue(translate.x) ? translate.x : translate.x + "px";
                var yValueString = isPersentValue(translate.y) ? translate.y : translate.y + "px";
                return "translate(" + xValueString + ", " + yValueString + ")"
            };
        DX.translator = {
            move: move,
            locate: locate,
            clearCache: clearCache,
            parseTranslate: parseTranslate,
            getTranslate: getTranslate,
            getTranslateCss: getTranslateCss,
            resetPosition: resetPosition
        }
    })(jQuery, DevExpress);
    /*! Module core, file animationFrame.js */
    (function($, DX, undefined) {
        var FRAME_ANIMATION_STEP_TIME = 1000 / 60,
            requestAnimationFrame = function(callback, element) {
                return this.setTimeout(callback, FRAME_ANIMATION_STEP_TIME)
            },
            cancelAnimationFrame = function(requestID) {
                return this.clearTimeout(requestID)
            },
            nativeRequestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame,
            nativeCancelAnimationFrame = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.oCancelAnimationFrame || window.msCancelAnimationFrame;
        if (nativeRequestAnimationFrame && nativeCancelAnimationFrame) {
            requestAnimationFrame = nativeRequestAnimationFrame;
            cancelAnimationFrame = nativeCancelAnimationFrame
        }
        if (nativeRequestAnimationFrame && !nativeCancelAnimationFrame) {
            var cancelledRequests = {};
            requestAnimationFrame = function(callback) {
                var requestId = nativeRequestAnimationFrame.call(window, function() {
                        try {
                            if (requestId in cancelledRequests)
                                return;
                            callback.apply(this, arguments)
                        }
                        finally {
                            delete cancelledRequests[requestId]
                        }
                    });
                return requestId
            };
            cancelAnimationFrame = function(requestId) {
                cancelledRequests[requestId] = true
            }
        }
        requestAnimationFrame = $.proxy(requestAnimationFrame, window);
        cancelAnimationFrame = $.proxy(cancelAnimationFrame, window);
        $.extend(DX, {
            requestAnimationFrame: requestAnimationFrame,
            cancelAnimationFrame: cancelAnimationFrame
        })
    })(jQuery, DevExpress);
    /*! Module core, file animator.js */
    (function($, DX, undefined) {
        DX.Animator = DX.Class.inherit({
            ctor: function() {
                this._finished = true;
                this._stopped = false
            },
            start: function() {
                this._stopped = false;
                this._finished = false;
                this._stepCore()
            },
            stop: function() {
                this._stopped = true
            },
            _stepCore: function() {
                if (this._isStopped()) {
                    this._stop();
                    return
                }
                if (this._isFinished()) {
                    this._finished = true;
                    this._complete();
                    return
                }
                this._step();
                DX.requestAnimationFrame.call(window, $.proxy(this._stepCore, this))
            },
            _step: DX.abstract,
            _isFinished: $.noop,
            _stop: $.noop,
            _complete: $.noop,
            _isStopped: function() {
                return this._stopped
            },
            inProgress: function() {
                return !(this._stopped || this._finished)
            }
        })
    })(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+)?)\)/,
            RELATIVE_VALUE_REGEX = /^([+-])=(.*)/i,
            ANIM_DATA_KEY = "dxAnimData",
            ANIM_QUEUE_KEY = "dxAnimQueue",
            TRANSFORM_PROP = "transform";
        var TransitionAnimationStrategy = {
                animate: function($element, config) {
                    var that = this,
                        deferred = $.Deferred();
                    config.transitionAnimation = {finish: function() {
                            that._cleanup($element, config);
                            deferred.resolveWith($element, [config, $element])
                        }};
                    this._startAnimation($element, config);
                    this._completeAnimationCallback($element, config).done(function() {
                        config.transitionAnimation.finish()
                    });
                    if (!config.duration)
                        config.transitionAnimation.finish();
                    return deferred.promise()
                },
                _completeAnimationCallback: function($element, config) {
                    var startTime = $.now() + config.delay,
                        deferred = $.Deferred(),
                        transitionEndFired = $.Deferred(),
                        simulatedTransitionEndFired = $.Deferred();
                    $element.one(transitionEndEventName, function(e) {
                        if ($.now() - startTime >= config.duration)
                            transitionEndFired.reject()
                    });
                    config.transitionAnimation.simulatedEndEventTimer = setTimeout(function() {
                        simulatedTransitionEndFired.reject()
                    }, config.duration + config.delay);
                    $.when(transitionEndFired, simulatedTransitionEndFired).fail($.proxy(function() {
                        deferred.resolve()
                    }, this));
                    return deferred.promise()
                },
                _startAnimation: function($element, config) {
                    $element.css("transform");
                    $element.css({
                        transitionProperty: "all",
                        transitionDelay: config.delay + "ms",
                        transitionDuration: config.duration + "ms",
                        transitionTimingFunction: config.easing
                    });
                    setProps($element, config.to)
                },
                _cleanup: function($element, config) {
                    $element.css("transition", "none").off(transitionEndEventName);
                    clearTimeout(config.transitionAnimation.simulatedEndEventTimer)
                },
                stop: function($element, config, jumpToEnd) {
                    if (!config)
                        return;
                    if (jumpToEnd)
                        config.transitionAnimation.finish();
                    else {
                        $.each(config.to, function(key) {
                            $element.css(key, $element.css(key))
                        });
                        this._cleanup($element, config)
                    }
                }
            };
        var FrameAnimationStrategy = {
                animate: function($element, config) {
                    var deferred = $.Deferred(),
                        that = this;
                    if (!config)
                        return deferred.reject().promise();
                    $.each(config.to, function(prop) {
                        if (config.from[prop] === undefined)
                            config.from[prop] = that._normalizeValue($element.css(prop))
                    });
                    if (config.to[TRANSFORM_PROP]) {
                        config.from[TRANSFORM_PROP] = that._parseTransform(config.from[TRANSFORM_PROP]);
                        config.to[TRANSFORM_PROP] = that._parseTransform(config.to[TRANSFORM_PROP])
                    }
                    config.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) {
                        config.frameAnimation.startTime += config.delay;
                        config.frameAnimation.delayTimeout = setTimeout(function() {
                            that._animationStep($element, config)
                        }, config.delay)
                    }
                    else
                        that._animationStep($element, config);
                    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, config, jumpToEnd) {
                    var frameAnimation = config && config.frameAnimation;
                    if (!frameAnimation)
                        return;
                    clearTimeout(frameAnimation.delayTimeout);
                    if (jumpToEnd)
                        frameAnimation.finish();
                    delete config.frameAnimation
                },
                _animationStep: function($element, config) {
                    var frameAnimation = config && config.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();
                    DX.requestAnimationFrame($.proxy(function() {
                        this._animationStep($element, config)
                    }, 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 location = translator.locate($element);
                    this._setUpConfig(location, config.from);
                    this._setUpConfig(location, config.to);
                    translator.clearCache($element);
                    if (!support.transform3d && $element.css("position") === "static")
                        $element.css("position", "relative")
                },
                _setUpConfig: function(location, config) {
                    config.left = "left" in config ? config.left : "+=0";
                    config.top = "top" in config ? config.top : "+=0";
                    this._initNewPosition(location, config)
                },
                _initNewPosition: function(location, config) {
                    var position = {
                            left: config.left,
                            top: config.top
                        };
                    delete config.left;
                    delete config.top;
                    var relativeValue = this._getRelativeValue(position.left);
                    if (relativeValue !== undefined)
                        position.left = relativeValue + location.left;
                    else
                        config.left = 0;
                    relativeValue = this._getRelativeValue(position.top);
                    if (relativeValue !== undefined)
                        position.top = relativeValue + location.top;
                    else
                        config.top = 0;
                    var translate = {
                            x: 0,
                            y: 0
                        };
                    if (support.transform3d)
                        translate = {
                            x: position.left,
                            y: position.top
                        };
                    else {
                        config.left = position.left;
                        config.top = position.top
                    }
                    config[TRANSFORM_PROP] = translator.getTranslateCss(translate)
                },
                _getRelativeValue: function(value) {
                    var relativeValue;
                    if (typeof value === "string" && (relativeValue = RELATIVE_VALUE_REGEX.exec(value)))
                        return parseInt(relativeValue[1] + "1") * relativeValue[2]
                }
            };
        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) {
                    var from = config.from,
                        to = config.to,
                        fromOpacity = "opacity" in from ? from.opacity : $element.css("opacity"),
                        toOpacity = "opacity" in to ? to.opacity : 1,
                        fromScale = "scale" in from ? from.scale : 0,
                        toScale = "scale" in to ? to.scale : 1;
                    config.from = {opacity: fromOpacity};
                    var translate = translator.getTranslate($element);
                    config.from[TRANSFORM_PROP] = this._getCssTransform(translate, fromScale);
                    config.to = {opacity: toOpacity};
                    config.to[TRANSFORM_PROP] = this._getCssTransform(translate, toScale)
                },
                _getCssTransform: function(translate, scale) {
                    return translator.getTranslateCss(translate) + "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,
                start: $.noop,
                complete: $.noop,
                easing: "ease",
                delay: 0
            };
        var animate = function(element, config) {
                var $element = $(element);
                config = $.extend(true, {}, defaultConfig, config);
                if (!$element.length)
                    return $.Deferred().resolve().promise();
                var configurator = getAnimationConfigurator(config.type);
                if ($.isFunction(configurator.validateConfig))
                    configurator.validateConfig(config);
                return pushInAnimationQueue($element, config)
            };
        var pushInAnimationQueue = function($element, config) {
                config.deferred = config.deferred || $.Deferred();
                var queueData = getAnimQueueData($element);
                writeAnimQueueData($element, queueData);
                queueData.push(config);
                if (!isAnimating($element))
                    shiftFromAnimationQueue($element, queueData);
                return config.deferred.promise()
            };
        var getAnimQueueData = function($element) {
                return $element.data(ANIM_QUEUE_KEY) || []
            };
        var writeAnimQueueData = function($element, queueData) {
                $element.data(ANIM_QUEUE_KEY, queueData)
            };
        var destroyAnimQueueData = function($element) {
                $element.removeData(ANIM_QUEUE_KEY)
            };
        var isAnimating = function($element) {
                return !!$element.data(ANIM_DATA_KEY)
            };
        var shiftFromAnimationQueue = function($element, queueData) {
                var queueData = getAnimQueueData($element);
                if (!queueData.length)
                    return;
                var config = queueData.shift();
                if (queueData.length === 0)
                    destroyAnimQueueData($element);
                executeAnimation($element, config).done(function() {
                    shiftFromAnimationQueue($element)
                })
            };
        var executeAnimation = function($element, config) {
                setupPosition($element, config.from);
                setupPosition($element, config.to);
                var configurator = getAnimationConfigurator(config.type);
                configurator.setup($element, config);
                $element.data(ANIM_DATA_KEY, config);
                if (DX.fx.off)
                    config.duration = 0;
                setProps($element, config.from);
                config.start.apply(this, [$element, config]);
                return getAnimationStrategy(config).animate($element, config).done(function() {
                        $element.removeData(ANIM_DATA_KEY);
                        config.complete.apply(this, [$element, config]);
                        config.deferred.resolveWith(this, [$element, config])
                    })
            };
        var setupPosition = function($element, config) {
                if (!config.position)
                    return;
                var position = DX.calculatePosition($element, config.position),
                    offset = $element.offset(),
                    currentPosition = $element.position();
                $.extend(config, {
                    left: position.h.location - offset.left + currentPosition.left,
                    top: position.v.location - offset.top + currentPosition.top
                });
                delete config.position
            };
        var setProps = function($element, props) {
                $.each(props, function(key, value) {
                    $element.css(key, value)
                })
            };
        var stop = function(element, jumpToEnd) {
                var $element = $(element),
                    queueData = getAnimQueueData($element);
                $.each(queueData, function(_, config) {
                    config.duration = 0
                });
                var config = $element.data(ANIM_DATA_KEY);
                getAnimationStrategy(config).stop($element, config, jumpToEnd);
                $element.removeData(ANIM_DATA_KEY);
                destroyAnimQueueData($element)
            };
        DX.fx = {
            off: false,
            animationTypes: animationConfigurators,
            animate: animate,
            isAnimating: isAnimating,
            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 = {
            defaultQuarterFormat: 'Q{0}',
            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)
            },
            getFirstQuarterMonth: function(month) {
                return this.getQuarter(month) * 3
            },
            _getQuarterString: function(date, format) {
                var quarter = this.getQuarter(date.getMonth());
                switch (format) {
                    case'q':
                        return this.romanDigits[quarter];
                    case'qq':
                        return utils.stringFormat(this.defaultQuarterFormat, this.romanDigits[quarter]);
                    case'Q':
                        return (quarter + 1).toString();
                    case'QQ':
                        return utils.stringFormat(this.defaultQuarterFormat, (quarter + 1).toString())
                }
                return ''
            },
            _formatCustomString: function(value, format) {
                var regExp = /qq|q|QQ|Q/g,
                    quarterFormat,
                    result = '',
                    index = 0;
                regExp.lastIndex = 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 that = 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 = that._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 = that._applyUnitToValue(value, unit);
                number = Math.abs(value);
                isNegative = value < 0;
                switch (numericFormatType) {
                    case DX.NumericFormat.decimal:
                        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 DX.NumericFormat.fixedpoint:
                        currentFormat = numberFormat;
                    case DX.NumericFormat.currency:
                        currentFormat = currentFormat || currencyFormat;
                    case DX.NumericFormat.percent:
                        currentFormat = currentFormat || percentFormat;
                        pattern = isNegative ? currentFormat.pattern[0] : currentFormat.pattern[1] || "n";
                        number = Globalize.format(number * (numericFormatType === DX.NumericFormat.percent ? 100 : 1), "N" + precision);
                        if (!showTrailingZeros)
                            number = that._excludeTrailingZeros(number, floatingSymbol);
                        if (!includeGroupSeparator)
                            number = number.replace(new RegExp('\\' + groupSymbol, 'g'), '');
                        break;
                    case DX.NumericFormat.exponential:
                        return that._formatNumberExponential(value, precision);
                    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 that = this,
                    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 that._formatDate(value, 'monthandyear');
                        case'quarteryear':
                            return that._getQuarterString(value, 'QQ') + ' ' + value.getFullYear();
                        case'daymonthyear':
                            return that._formatDate(value, dateType + 'Date');
                        case'datehour':
                            time = new Date(value.getTime());
                            time.setMinutes(0);
                            dateStr = dateType === 'timeOnly' ? '' : that._formatDate(value, dateType + 'Date');
                            return dateType === 'timeOnly' ? that._formatDate(time, 'shorttime') : dateStr + ' ' + that._formatDate(time, 'shorttime');
                        case'datehourminute':
                            dateStr = dateType === 'timeOnly' ? '' : that._formatDate(value, dateType + 'Date');
                            return dateType === 'timeOnly' ? that._formatDate(value, 'shorttime') : dateStr + ' ' + that._formatDate(value, 'shorttime');
                        case'datehourminutesecond':
                            dateStr = dateType === 'timeOnly' ? '' : that._formatDate(value, dateType + 'Date');
                            return dateType === 'timeOnly' ? that._formatDate(value, 'longtime') : dateStr + ' ' + that._formatDate(value, 'longtime');
                        case'year':
                            dateStr = value.toString();
                            return dateType === 'abbr' ? dateStr.slice(2, 4) : dateStr;
                        case'quarter':
                            return utils.stringFormat(that.defaultQuarterFormat, 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 that._formatDate(time, 'shorttime')
                            }
                            else
                                return value.toString();
                        case'dayofweek':
                            index = utils.isString(value) ? $.inArray(value, ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']) : value;
                            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 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: /^rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*(\d*\.*\d+)\)$/,
                    process: function(colorString) {
                        return [parseInt(colorString[1], 10), parseInt(colorString[2], 10), parseInt(colorString[3], 10), parseFloat(colorString[4])]
                    }
                }, {
                    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)]
                    }
                }, {
                    re: /^hsv\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
                    process: function(colorString) {
                        var h = parseInt(colorString[1], 10),
                            s = parseInt(colorString[2], 10),
                            v = parseInt(colorString[3], 10),
                            rgb = hsvToRgb(h, s, v);
                        return [rgb[0], rgb[1], rgb[2], 1, [h, s, v]]
                    }
                }, {
                    re: /^hsl\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
                    process: function(colorString) {
                        var h = parseInt(colorString[1], 10),
                            s = parseInt(colorString[2], 10),
                            l = parseInt(colorString[3], 10),
                            rgb = hslToRgb(h, s, l);
                        return [rgb[0], rgb[1], rgb[2], 1, null, [h, s, l]]
                    }
                }];
        function Color(value) {
            this.baseColor = value;
            var color;
            if (value) {
                color = String(value).toLowerCase().replace(/ /g, '');
                color = standardColorNames[color] ? '#' + standardColorNames[color] : color;
                color = parseColor(color)
            }
            if (!color)
                this.colorIsInvalid = true;
            color = color || {};
            this.r = normalize(color[0]);
            this.g = normalize(color[1]);
            this.b = normalize(color[2]);
            this.a = normalize(color[3], 1, 1);
            if (color[4])
                this.hsv = {
                    h: color[4][0],
                    s: color[4][1],
                    v: color[4][2]
                };
            else
                this.hsv = toHsvFromRgb(this.r, this.g, this.b);
            if (color[5])
                this.hsl = {
                    h: color[5][0],
                    s: color[5][1],
                    l: color[5][2]
                };
            else
                this.hsl = toHslFromRgb(this.r, this.g, this.b)
        }
        function parseColor(color) {
            if (color === "transparent")
                return [0, 0, 0, 0];
            var result,
                i = 0,
                ii = standardColorTypes.length,
                str;
            for (; i < ii; ++i) {
                str = standardColorTypes[i].re.exec(color);
                if (str)
                    return standardColorTypes[i].process(str)
            }
            return null
        }
        function normalize(colorComponent, def, max) {
            def = def || 0;
            max = max || 255;
            return colorComponent < 0 || isNaN(colorComponent) ? def : colorComponent > max ? max : colorComponent
        }
        function toHexFromRgb(r, g, b) {
            return '#' + (0X01000000 | r << 16 | g << 8 | b).toString(16).slice(1)
        }
        function toHsvFromRgb(r, g, b) {
            var max = Math.max(r, g, b),
                min = Math.min(r, g, b),
                delta = max - min,
                H,
                S,
                V;
            V = max;
            S = max === 0 ? 0 : 1 - min / max;
            if (max === min)
                H = 0;
            else
                switch (max) {
                    case r:
                        H = 60 * ((g - b) / delta);
                        if (g < b)
                            H = H + 360;
                        break;
                    case g:
                        H = 60 * ((b - r) / delta) + 120;
                        break;
                    case b:
                        H = 60 * ((r - g) / delta) + 240;
                        break
                }
            S *= 100;
            V *= 100 / 255;
            return {
                    h: Math.round(H),
                    s: Math.round(S),
                    v: Math.round(V)
                }
        }
        function hsvToRgb(h, s, v) {
            var Vdec,
                Vinc,
                Vmin,
                Hi,
                a,
                r,
                g,
                b;
            Hi = Math.floor(h / 60);
            Vmin = (100 - s) * v / 100;
            a = (v - Vmin) * (h % 60 / 60);
            Vinc = Vmin + a;
            Vdec = v - a;
            switch (Hi) {
                case 0:
                    r = v;
                    g = Vinc;
                    b = Vmin;
                    break;
                case 1:
                    r = Vdec;
                    g = v;
                    b = Vmin;
                    break;
                case 2:
                    r = Vmin;
                    g = v;
                    b = Vinc;
                    break;
                case 3:
                    r = Vmin;
                    g = Vdec;
                    b = v;
                    break;
                case 4:
                    r = Vinc;
                    g = Vmin;
                    b = v;
                    break;
                case 5:
                    r = v;
                    g = Vmin;
                    b = Vdec;
                    break
            }
            return [Math.round(r * 2.55), Math.round(g * 2.55), Math.round(b * 2.55)]
        }
        function calculateHue(r, g, b, delta) {
            var max = Math.max(r, g, b);
            switch (max) {
                case r:
                    return (g - b) / delta + (g < b ? 6 : 0);
                case g:
                    return (b - r) / delta + 2;
                case b:
                    return (r - g) / delta + 4
            }
        }
        function toHslFromRgb(r, g, b) {
            r = convertTo01Bounds(r, 255);
            g = convertTo01Bounds(g, 255);
            b = convertTo01Bounds(b, 255);
            var max = Math.max(r, g, b),
                min = Math.min(r, g, b),
                maxMinSumm = max + min,
                h,
                s,
                l = maxMinSumm / 2;
            if (max === min)
                h = s = 0;
            else {
                var delta = max - min;
                if (l > 0.5)
                    s = delta / (2 - maxMinSumm);
                else
                    s = delta / maxMinSumm;
                h = calculateHue(r, g, b, delta);
                h /= 6
            }
            return {
                    h: _round(h * 360),
                    s: _round(s * 100),
                    l: _round(l * 100)
                }
        }
        function makeTc(colorPart, h) {
            var Tc = h;
            if (colorPart === "r")
                Tc = h + 1 / 3;
            if (colorPart === "b")
                Tc = h - 1 / 3;
            return Tc
        }
        function modifyTc(Tc) {
            if (Tc < 0)
                Tc += 1;
            if (Tc > 1)
                Tc -= 1;
            return Tc
        }
        function hueToRgb(p, q, Tc) {
            Tc = modifyTc(Tc);
            if (Tc < 1 / 6)
                return p + (q - p) * 6 * Tc;
            if (Tc < 1 / 2)
                return q;
            if (Tc < 2 / 3)
                return p + (q - p) * (2 / 3 - Tc) * 6;
            return p
        }
        function hslToRgb(h, s, l) {
            var r,
                g,
                b,
                h = convertTo01Bounds(h, 360),
                s = convertTo01Bounds(s, 100),
                l = convertTo01Bounds(l, 100);
            if (s === 0)
                r = g = b = l;
            else {
                var q = l < 0.5 ? l * (1 + s) : l + s - l * s,
                    p = 2 * l - q;
                r = hueToRgb(p, q, makeTc("r", h));
                g = hueToRgb(p, q, makeTc("g", h));
                b = hueToRgb(p, q, makeTc("b", h))
            }
            return [_round(r * 255), _round(g * 255), _round(b * 255)]
        }
        function convertTo01Bounds(n, max) {
            n = Math.min(max, Math.max(0, parseFloat(n)));
            if (Math.abs(n - max) < 0.000001)
                return 1;
            return n % max / parseFloat(max)
        }
        function isIntegerBtwMinAndMax(number, min, max) {
            min = min || 0;
            max = max || 255;
            if (number % 1 !== 0 || number < min || number > max || typeof number !== 'number' || isNaN(number))
                return false;
            return true
        }
        var _round = Math.round;
        Color.prototype = {
            constructor: Color,
            highlight: function(step) {
                step = step || 10;
                return this.alter(step).toHex()
            },
            darken: function(step) {
                step = step || 10;
                return this.alter(-step).toHex()
            },
            alter: function(step) {
                var result = new Color;
                result.r = normalize(this.r + step);
                result.g = normalize(this.g + step);
                result.b = normalize(this.b + step);
                return result
            },
            blend: function(blendColor, opacity) {
                var other = blendColor instanceof Color ? blendColor : new Color(blendColor),
                    result = new Color;
                result.r = normalize(_round(this.r * (1 - opacity) + other.r * opacity));
                result.g = normalize(_round(this.g * (1 - opacity) + other.g * opacity));
                result.b = normalize(_round(this.b * (1 - opacity) + other.b * opacity));
                return result
            },
            toHex: function() {
                return toHexFromRgb(this.r, this.g, this.b)
            },
            getPureColor: function() {
                var rgb = hsvToRgb(this.hsv.h, 100, 100);
                return new Color("rgb(" + rgb.join(",") + ")")
            },
            isValidHex: function(hex) {
                return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(hex)
            },
            isValidRGB: function(r, g, b) {
                if (!isIntegerBtwMinAndMax(r) || !isIntegerBtwMinAndMax(g) || !isIntegerBtwMinAndMax(b))
                    return false;
                return true
            },
            isValidAlpha: function(a) {
                if (isNaN(a) || a < 0 || a > 1 || typeof a !== 'number')
                    return false;
                return true
            },
            colorIsInvalid: false
        };
        DX.Color = Color
    })(DevExpress);
    /*! Module core, file localization.js */
    (function($, DX, undefined) {
        Globalize.localize = function(key, cultureSelector) {
            var neutral = (cultureSelector || this.cultureSelector || "").substring(0, 2);
            return this.findClosestCulture(cultureSelector).messages[key] || this.findClosestCulture(neutral).messages[key] || this.cultures["default"].messages[key]
        };
        var localization = function() {
                var newMessages = {};
                return {
                        setup: function(localizablePrefix) {
                            this.localizeString = function(text) {
                                var regex = new RegExp("(^|[^a-zA-Z_0-9" + localizablePrefix + "-]+)(" + localizablePrefix + "{1,2})([a-zA-Z_0-9-]+)", "g"),
                                    escapeString = localizablePrefix + localizablePrefix;
                                return text.replace(regex, function(str, prefix, escape, localizationKey) {
                                        var result = prefix + localizablePrefix + localizationKey;
                                        if (escape !== escapeString)
                                            if (Globalize.cultures["default"].messages[localizationKey])
                                                result = prefix + Globalize.localize(localizationKey);
                                            else
                                                newMessages[localizationKey] = DX.inflector.humanize(localizationKey);
                                        return result
                                    })
                            }
                        },
                        localizeNode: function(node) {
                            var that = this;
                            $(node).each(function(index, nodeItem) {
                                if (!nodeItem.nodeType)
                                    return;
                                if (nodeItem.nodeType === 3)
                                    nodeItem.nodeValue = that.localizeString(nodeItem.nodeValue);
                                else {
                                    $.each(nodeItem.attributes || [], function(index, attr) {
                                        if (typeof attr.value === "string") {
                                            var localizedValue = that.localizeString(attr.value);
                                            if (attr.value !== localizedValue)
                                                attr.value = localizedValue
                                        }
                                    });
                                    $(nodeItem).contents().each(function(index, node) {
                                        that.localizeNode(node)
                                    })
                                }
                            })
                        },
                        getDictionary: function(onlyNew) {
                            if (onlyNew)
                                return newMessages;
                            return $.extend({}, newMessages, Globalize.cultures["default"].messages)
                        }
                    }
            }();
        localization.setup("@");
        DX.localization = localization
    })(jQuery, DevExpress);
    /*! Module core, file localization.en.js */
    Globalize.addCultureInfo("default", {messages: {
            Yes: "Yes",
            No: "No",
            Cancel: "Cancel",
            Clear: "Clear",
            Done: "Done",
            Loading: "Loading...",
            Select: "Select...",
            Search: "Search",
            Back: "Back",
            OK: "OK",
            "dxLookup-searchPlaceholder": "Minimum character number: {0}",
            "dxCollectionContainerWidget-noDataText": "No data to display",
            "dxList-pullingDownText": "Pull down to refresh...",
            "dxList-pulledDownText": "Release to refresh...",
            "dxList-refreshingText": "Refreshing...",
            "dxList-pageLoadingText": "Loading...",
            "dxList-nextButtonText": "More",
            "dxListEditDecorator-delete": "Delete",
            "dxListEditDecorator-more": "More",
            "dxScrollView-pullingDownText": "Pull down to refresh...",
            "dxScrollView-pulledDownText": "Release to refresh...",
            "dxScrollView-refreshingText": "Refreshing...",
            "dxScrollView-reachBottomText": "Loading...",
            "dxSwitch-onText": "ON",
            "dxSwitch-offText": "OFF",
            "dxDateBox-simulatedDataPickerTitleTime": "Select time",
            "dxDateBox-simulatedDataPickerTitleDate": "Select date",
            "dxDateBox-simulatedDataPickerTitleDateTime": "Select date and time",
            "dxDataGrid-columnChooserTitle": "Column Chooser",
            "dxDataGrid-columnChooserEmptyText": "Drag a column here to hide it",
            "dxDataGrid-groupContinuesMessage": "Continues on the next page",
            "dxDataGrid-groupContinuedMessage": "Continued from the previous page",
            "dxDataGrid-editingEditRow": "Edit",
            "dxDataGrid-editingSaveRowChanges": "Save",
            "dxDataGrid-editingCancelRowChanges": "Cancel",
            "dxDataGrid-editingDeleteRow": "Delete",
            "dxDataGrid-editingUndeleteRow": "Undelete",
            "dxDataGrid-editingConfirmDeleteMessage": "Are you sure you want to delete this record?",
            "dxDataGrid-editingConfirmDeleteTitle": "",
            "dxDataGrid-groupPanelEmptyText": "Drag a column header here to group by that column",
            "dxDataGrid-noDataText": "No data",
            "dxDataGrid-searchPanelPlaceholder": "Search...",
            "dxDataGrid-filterRowShowAllText": "(All)",
            "dxDataGrid-filterRowResetOperationText": "Reset",
            "dxDataGrid-filterRowOperationEquals": "Equals",
            "dxDataGrid-filterRowOperationNotEquals": "Does not equal",
            "dxDataGrid-filterRowOperationLess": "Less than",
            "dxDataGrid-filterRowOperationLessOrEquals": "Less than or equal to",
            "dxDataGrid-filterRowOperationGreater": "Greater than",
            "dxDataGrid-filterRowOperationGreaterOrEquals": "Greater than or equal to",
            "dxDataGrid-filterRowOperationStartsWith": "Starts with",
            "dxDataGrid-filterRowOperationContains": "Contains",
            "dxDataGrid-filterRowOperationNotContains": "Does not contain",
            "dxDataGrid-filterRowOperationEndsWith": "Ends with",
            "dxDataGrid-trueText": "true",
            "dxDataGrid-falseText": "false",
            "dxDataGrid-sortingAscendingText": "Sort Ascending",
            "dxDataGrid-sortingDescendingText": "Sort Descending",
            "dxDataGrid-sortingClearText": "Clear Sorting"
        }});
    /*! Module core, file data.js */
    (function($, DX, undefined) {
        var bracketsToDots = function(expr) {
                return expr.replace(/\[/g, ".").replace(/\]/g, "")
            };
        var unwrapObservable = DX.utils.unwrapObservable;
        var isObservable = function(value) {
                return DX.support.hasKo && ko.isObservable(value)
            };
        var readPropValue = function(obj, propName) {
                if (propName === "this")
                    return obj;
                return obj[propName]
            };
        var assignPropValue = function(obj, propName, value) {
                if (propName === "this")
                    throw Error("Cannot assign to self");
                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) {
                expr = expr || "this";
                expr = bracketsToDots(expr);
                var pos = expr.lastIndexOf("."),
                    targetGetter = compileGetter(expr.substr(0, pos)),
                    targetPropName = expr.substr(1 + pos);
                return function(obj, value, options) {
                        options = options || {};
                        var target = targetGetter(obj, {functionsAsIs: options.functionsAsIs}),
                            prevTargetValue = readPropValue(target, targetPropName);
                        if (!options.functionsAsIs && $.isFunction(prevTargetValue) && !isObservable(prevTargetValue))
                            target[targetPropName](value);
                        else {
                            prevTargetValue = unwrapObservable(prevTargetValue);
                            if (options.merge && $.isPlainObject(value) && (prevTargetValue === undefined || $.isPlainObject(prevTargetValue)) && !(value instanceof $.Event)) {
                                if (!prevTargetValue)
                                    assignPropValue(target, targetPropName, {});
                                DX.utils.deepExtendArraySafe(unwrapObservable(readPropValue(target, targetPropName)), value)
                            }
                            else
                                assignPropValue(target, targetPropName, value)
                        }
                    }
            };
        var normalizeBinaryCriterion = function(crit) {
                return [crit[0], crit.length < 3 ? "=" : String(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.getter || 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, 12)].join("-")
                },
                _generate: function() {
                    var value = "";
                    for (var i = 0; i < 32; i++)
                        value += Math.round(Math.random() * 15).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 MapIterator = WrappedIterator.inherit({
                ctor: function(iter, mapper) {
                    this.callBase(iter);
                    this.index = -1;
                    this.mapper = mapper
                },
                current: function() {
                    return this.mapper(this.callBase(), this.index)
                },
                next: function() {
                    var hasNext = this.callBase();
                    if (hasNext)
                        this.index++;
                    return hasNext
                }
            });
        var SortIterator = Iterator.inherit({
                ctor: function(iter, getter, desc) {
                    if (!(iter instanceof MapIterator))
                        iter = new MapIterator(iter, this._wrap);
                    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 MapIterator(new ArrayIterator(this.iter.toArray().sort($.proxy(this._compare, this))), this._unwrap)
                },
                _wrap: function(record, index) {
                    return {
                            index: index,
                            value: record
                        }
                },
                _unwrap: function(wrappedItem) {
                    return wrappedItem.value
                },
                _compare: function(x, y) {
                    var xIndex = x.index,
                        yIndex = y.index;
                    x = x.value;
                    y = y.value;
                    if (x === y)
                        return xIndex - yIndex;
                    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 xIndex - yIndex
                }
            });
        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 compileEquals(getter, value);
                            case"<>":
                                return compileEquals(getter, value, true);
                            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
                                    }
                        }
                        throw Error("Unknown filter operation: " + op);
                    };
                function compileEquals(getter, value, negate) {
                    return function(obj) {
                            obj = toComparable(getter(obj));
                            var result = useStrictComparison(value) ? obj === value : obj == value;
                            if (negate)
                                result = !result;
                            return result
                        }
                }
                function useStrictComparison(value) {
                    return value === "" || value === 0 || value === null || value === false || value === undefined
                }
                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) {
                        return chainQuery(new GroupIterator(iter, getter))
                    },
                    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, extra) {
                            if (!taskQueue.length)
                                d.resolve(result, extra);
                            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,
            utils = DX.utils,
            Guid = data.Guid;
        var VERBOSE_DATE_REGEX = /^\/Date\((-?\d+)((\+|-)?(\d+)?)\)\/$/;
        var ISO8601_DATE_REGEX = /^(\d{4})(?:-?W(\d+)(?:-?(\d+)D?)?|(?:-(\d+))?-(\d+))(?:[T ](\d+):(\d+)(?::(\d+)(?:\.(\d+))?)?)?(?:Z(-?\d*))?$/;
        var TIMEZONE_OFFSET = (new Date).getTimezoneOffset() * 60 * 1000;
        var JSON_VERBOSE_MIME_TYPE = "application/json;odata=verbose";
        function stringify(object) {
            return JSON.stringify(object, replacer);
            function replacer(key, value) {
                if (this[key] instanceof Date)
                    return utils.formatIso8601Date(this[key]);
                return value
            }
        }
        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 : 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 = interpretJsonFormat(obj, textStatus),
                        error = tuplet.error,
                        data = tuplet.data,
                        nextUrl = tuplet.nextUrl,
                        extra;
                    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 {
                        if (isFinite(tuplet.count))
                            extra = {totalCount: tuplet.count};
                        d.resolve(data, extra)
                    }
                });
                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",
                    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 || response["@odata.error"]);
                if (errorObj) {
                    message = formatDotNetError(errorObj) || message;
                    if (httpStatus === 200)
                        httpStatus = 500;
                    if (errorObj.code)
                        httpStatus = Number(errorObj.code);
                    return $.extend(Error(message), {
                            httpStatus: httpStatus,
                            errorDetails: errorObj
                        })
                }
                else if (httpStatus !== 200)
                    return $.extend(Error(message), {httpStatus: httpStatus})
            };
        var interpretJsonFormat = function(obj, textStatus) {
                var error = errorFromResponse(obj, textStatus),
                    value;
                if (error)
                    return {error: error};
                if (!$.isPlainObject(obj))
                    return {data: obj};
                if ("d" in obj && (utils.isArray(obj.d) || utils.isObject(obj.d)))
                    value = interpretVerboseJsonFormat(obj, textStatus);
                else
                    value = interpretLightJsonFormat(obj, textStatus);
                transformDates(value);
                return value
            };
        var interpretVerboseJsonFormat = function(obj, textStatus) {
                var data = obj.d;
                if (!data)
                    return {error: Error("Malformed or unsupported JSON response received")};
                data = data.results || data;
                return {
                        data: data,
                        nextUrl: obj.d.__next,
                        count: parseInt(obj.d.__count, 10)
                    }
            };
        var interpretLightJsonFormat = function(obj, textStatus) {
                var data = obj.value || obj;
                if (!data)
                    return {error: Error("Malformed or unsupported JSON response received")};
                return {
                        data: data,
                        nextUrl: obj["@odata.nextLink"],
                        count: parseInt(obj["@odata.count"], 10)
                    }
            };
        var EdmLiteral = DX.Class.inherit({
                ctor: function(value) {
                    this._value = value
                },
                valueOf: function() {
                    return this._value
                }
            });
        var transformDates = function(obj) {
                $.each(obj, function(key, value) {
                    if (value !== null && typeof value === "object")
                        transformDates(value);
                    else if (typeof value === "string")
                        if (value.match(VERBOSE_DATE_REGEX))
                            obj[key] = new Date(TIMEZONE_OFFSET + Number(RegExp.$1) + RegExp.$2 * 60000);
                        else if (ISO8601_DATE_REGEX.test(value))
                            obj[key] = new Date(TIMEZONE_OFFSET + utils.parseIso8601Date(obj[key]).valueOf())
                })
            };
        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.getFullYear(), "-", pad(date.getMonth() + 1), "-", pad(date.getDate())];
                        if (date.getHours() || date.getMinutes() || date.getSeconds() || date.getMilliseconds()) {
                            result.push("T", pad(date.getHours()), ":", pad(date.getMinutes()), ":", pad(date.getSeconds()));
                            if (date.getMilliseconds())
                                result.push(".", date.getMilliseconds())
                        }
                        result.push("'");
                        return result.join("")
                    }
            }();
        var serializeString = function(value) {
                return "'" + value.replace(/</g, "%26lt").replace(/'/g, "''") + "'"
            };
        var serializePropName = function(propName) {
                if (propName instanceof EdmLiteral)
                    return propName.valueOf();
                return propName.replace(/\./g, "/")
            };
        var serializeValueV4 = function(value) {
                if (value instanceof Date)
                    return utils.formatIso8601Date(value);
                return serializeValueV2(value)
            };
        var serializeValueV2 = 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 serializeString(value);
                return String(value)
            };
        var DEFAULT_PROTOCOL_VERSION = 2;
        var serializeValue = function(value, protocolVersion) {
                protocolVersion = protocolVersion || DEFAULT_PROTOCOL_VERSION;
                switch (protocolVersion) {
                    case 2:
                    case 3:
                        return serializeValueV2(value);
                    case 4:
                        return serializeValueV4(value);
                    default:
                        throw new Error("Unknown OData protocol version");
                }
            };
        var serializeKey = function(key, protocolVersion) {
                if ($.isPlainObject(key)) {
                    var parts = [];
                    $.each(key, function(k, v) {
                        parts.push(serializePropName(k) + "=" + serializeValue(v, protocolVersion))
                    });
                    return parts.join()
                }
                return serializeValue(key)
            };
        var keyConverters = {
                String: function(value) {
                    return value + ""
                },
                Int32: function(value) {
                    return Math.floor(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)
                },
                Boolean: function(value) {
                    return !!value
                },
                Single: function(value) {
                    if (value instanceof EdmLiteral)
                        return value;
                    return new EdmLiteral(value + "f")
                },
                Decimal: function(value) {
                    if (value instanceof EdmLiteral)
                        return value;
                    return new EdmLiteral(value + "m")
                }
            };
        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")
                    };
                var formattersV2 = $.extend({}, formatters, {
                        contains: createStringFuncFormatter("substringof", true),
                        notcontains: createStringFuncFormatter("not substringof", true)
                    });
                var formattersV4 = $.extend({}, formatters, {
                        contains: createStringFuncFormatter("contains"),
                        notcontains: createStringFuncFormatter("not contains")
                    });
                var compileBinary = function(criteria, bag, protocolVersion) {
                        criteria = data.utils.normalizeBinaryCriterion(criteria);
                        var op = criteria[1],
                            formatters = protocolVersion === 4 ? formattersV4 : formattersV2,
                            formatter = formatters[op.toLowerCase()];
                        if (!formatter)
                            throw Error("Unknown filter operation: " + op);
                        formatter(serializePropName(criteria[0]), serializeValue(criteria[2], protocolVersion), bag)
                    };
                var compileGroup = function(criteria, bag, protocolVersion) {
                        var pushAnd = false;
                        $.each(criteria, function() {
                            if ($.isArray(this)) {
                                if (pushAnd)
                                    bag.push(" and ");
                                bag.push("(");
                                compileCore(this, bag, protocolVersion);
                                bag.push(")");
                                pushAnd = true
                            }
                            else {
                                bag.push(/and|&/i.test(this) ? " and " : " or ");
                                pushAnd = false
                            }
                        })
                    };
                var compileCore = function(criteria, bag, protocolVersion) {
                        if ($.isArray(criteria[0]))
                            compileGroup(criteria, bag, protocolVersion);
                        else
                            compileBinary(criteria, bag, protocolVersion)
                    };
                return function(criteria, protocolVersion) {
                        var bag = [];
                        compileCore(criteria, bag, protocolVersion);
                        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, queryOptions.version);
                        if (countQuery)
                            result["$top"] = 0;
                        if (queryOptions.requireTotalCount || countQuery)
                            if (queryOptions.version !== 4)
                                result["$inlinecount"] = "allpages";
                            else
                                result["$count"] = "true";
                        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}
        });
        data.OData__internals = {interpretJsonFormat: interpretJsonFormat}
    })(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"];
        function multiLevelGroup(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.utils.multiLevelGroup = multiLevelGroup;
        function arrangeSortingInfo(groupInfo, sortInfo) {
            var filteredGroup = [];
            $.each(groupInfo, function(_, group) {
                var collision = $.grep(sortInfo, function(sort) {
                        return group.selector == sort.selector
                    });
                if (collision.length < 1)
                    filteredGroup.push(group)
            });
            return filteredGroup.concat(sortInfo)
        }
        data.Store = Class.inherit({
            ctor: function(options) {
                var that = this;
                options = options || {};
                $.each(STORE_CALLBACK_NAMES, function() {
                    var callbacks = that[this] = $.Callbacks();
                    if (this in options)
                        callbacks.add(options[this])
                });
                this._key = options.key;
                this._errorHandler = options.errorHandler;
                this._useDefaultSearch = true
            },
            _customLoadOptions: function() {
                return null
            },
            key: function() {
                return this._key
            },
            keyOf: function(obj) {
                if (!this._keyGetter)
                    this._keyGetter = data.utils.compileGetter(this.key());
                return this._keyGetter(obj)
            },
            _requireKey: function() {
                if (!this.key())
                    throw Error("Key expression is required for this operation");
            },
            load: function(options) {
                var that = this;
                options = options || {};
                this.loading.fire(options);
                return this._loadImpl(options).done(function(result, extra) {
                        that.loaded.fire(result, extra)
                    })
            },
            _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 || group) {
                    sort = normalizeSortingInfo(sort || []);
                    if (group)
                        sort = arrangeSortingInfo(group, 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,
            totalCount: function(options) {
                return this._addFailHandlers(this._totalCountImpl(options))
            },
            _totalCountImpl: function(options) {
                options = options || {};
                var q = this.createQuery(),
                    group = options.group,
                    filter = options.filter;
                if (filter)
                    q = q.filter(filter);
                if (group) {
                    group = normalizeSortingInfo(group);
                    q = multiLevelGroup(q, group)
                }
                return q.count()
            },
            byKey: function(key, extraOptions) {
                return this._addFailHandlers(this._byKeyImpl(key, extraOptions))
            },
            _byKeyImpl: abstract,
            insert: function(values) {
                var that = this;
                that.modifying.fire();
                that.inserting.fire(values);
                return that._addFailHandlers(that._insertImpl(values).done(function(callbackValues, callbackKey) {
                        that.inserted.fire(callbackValues, callbackKey);
                        that.modified.fire()
                    }))
            },
            _insertImpl: abstract,
            update: function(key, values) {
                var that = this;
                that.modifying.fire();
                that.updating.fire(key, values);
                return that._addFailHandlers(that._updateImpl(key, values).done(function(callbackKey, callbackValues) {
                        that.updated.fire(callbackKey, callbackValues);
                        that.modified.fire()
                    }))
            },
            _updateImpl: abstract,
            remove: function(key) {
                var that = this;
                that.modifying.fire();
                that.removing.fire(key);
                return that._addFailHandlers(that._removeImpl(key).done(function(callbackKey) {
                        that.removed.fire(callbackKey);
                        that.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);
                var initialArray = options.data;
                if (initialArray && !$.isArray(initialArray))
                    throw Error("Invalid 'data' option value");
                this._array = initialArray || []
            },
            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;
                DX.utils.deepExtendArraySafe(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.keyOf(this._array[i]), key))
                        return i;
                return -1
            },
            clear: function() {
                this._array = []
            }
        })
    })(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.callBase();
                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, version) {
                if (!params)
                    return params;
                var result = {};
                $.each(params, function(k, v) {
                    result[k] = odataUtils.serializeValue(v, version)
                });
                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._version = options.version;
                    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
                        })
                },
                version: function() {
                    return this._version
                }
            };
        var ODataStore = data.Store.inherit({
                ctor: function(options) {
                    this.callBase(options);
                    this._extractServiceOptions(options);
                    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,
                            version: this._version,
                            withCredentials: this._withCredentials,
                            params: escapeServiceOperationParams(loadOptions.customQueryParams, this._version),
                            expand: loadOptions.expand,
                            requireTotalCount: loadOptions.requireTotalCount
                        })
                },
                _insertImpl: function(values) {
                    this._requireKey();
                    var that = this,
                        d = $.Deferred();
                    $.when(this._sendRequest(this._url, "POST", null, values)).done(function(serverResponse) {
                        d.resolve(values, that.keyOf(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, this._version)) + ")"
                }
            }).include(SharedMethods);
        var ODataContext = Class.inherit({
                ctor: function(options) {
                    var that = this;
                    that._extractServiceOptions(options);
                    that._errorHandler = options.errorHandler;
                    $.each(options.entities || [], function(entityAlias, entityOptions) {
                        that[entityAlias] = new ODataStore($.extend({}, options, {url: that._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, this._version))).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) {
                DX.utils.logger.warn("RestStore is deprecated, use CustomStore instead");
                var that = this;
                that.callBase(options);
                options = options || {};
                that._url = String(options.url).replace(/\/+$/, "");
                that._jsonp = options.jsonp;
                that._withCredentials = options.withCredentials;
                $.each(["Load", "Insert", "Update", "Remove", "ByKey", "Operation"], function() {
                    var value = options["customize" + this];
                    if (value)
                        that[operationCustomizerPropName(this)] = value
                });
                $.each(["load", "insert", "update", "remove", "byKey"], function() {
                    var value = options[this + "Path"];
                    if (value)
                        that[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(),
                    that = 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, that.key() && that.keyOf(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.custom.js */
    (function($, DX, undefined) {
        var data = DX.data;
        var ERROR_QUERY_NOT_SUPPORTED = "CustomStore does not support creating queries",
            ERROR_MISSING_USER_FUNC = "Required option is not specified or is not a function: ",
            ERROR_INVALID_RETURN = "Invalid return value: ";
        var TOTAL_COUNT = "totalCount",
            LOAD = "load",
            BY_KEY = "byKey",
            INSERT = "insert",
            UPDATE = "update",
            REMOVE = "remove";
        function isPromise(obj) {
            return obj && $.isFunction(obj.done) && $.isFunction(obj.fail) && $.isFunction(obj.promise)
        }
        function trivialPromise(value) {
            return $.Deferred().resolve(value).promise()
        }
        function ensureRequiredFuncOption(name, obj) {
            if (!$.isFunction(obj))
                throw Error(ERROR_MISSING_USER_FUNC + name);
        }
        function throwInvalidUserFuncResult(name) {
            throw Error(ERROR_INVALID_RETURN + name);
        }
        function createUserFuncFailureHandler(pendingDeferred) {
            function errorMessageFromXhr(promiseArguments) {
                var xhr = promiseArguments[0],
                    textStatus = promiseArguments[1];
                if (!xhr || !xhr.getResponseHeader)
                    return null;
                return data.utils.errorMessageFromXhr(xhr, textStatus)
            }
            return function(arg) {
                    var error;
                    if (arg instanceof Error)
                        error = arg;
                    else
                        error = Error(errorMessageFromXhr(arguments) || arg && String(arg) || "Unknown error");
                    pendingDeferred.reject(error)
                }
        }
        data.CustomStore = data.Store.inherit({
            ctor: function(options) {
                options = options || {};
                this.callBase(options);
                this._useDefaultSearch = false;
                this._loadFunc = options[LOAD];
                this._totalCountFunc = options[TOTAL_COUNT];
                this._byKeyFunc = options[BY_KEY] || options.lookup;
                this._insertFunc = options[INSERT];
                this._updateFunc = options[UPDATE];
                this._removeFunc = options[REMOVE]
            },
            createQuery: function() {
                throw Error(ERROR_QUERY_NOT_SUPPORTED);
            },
            _totalCountImpl: function(options) {
                var userFunc = this._totalCountFunc,
                    userResult,
                    d = $.Deferred();
                ensureRequiredFuncOption(TOTAL_COUNT, userFunc);
                userResult = userFunc(options);
                if (!isPromise(userResult)) {
                    userResult = Number(userResult);
                    if (!isFinite(userResult))
                        throwInvalidUserFuncResult(TOTAL_COUNT);
                    userResult = trivialPromise(userResult)
                }
                userResult.done(function(count) {
                    d.resolve(Number(count))
                }).fail(createUserFuncFailureHandler(d));
                return d.promise()
            },
            _loadImpl: function(options) {
                var userFunc = this._loadFunc,
                    userResult,
                    d = $.Deferred();
                ensureRequiredFuncOption(LOAD, userFunc);
                userResult = userFunc(options);
                if ($.isArray(userResult))
                    userResult = trivialPromise(userResult);
                else if (userResult === null || userResult === undefined)
                    userResult = trivialPromise([]);
                else if (!isPromise(userResult))
                    throwInvalidUserFuncResult(LOAD);
                userResult.done(function(data, extra) {
                    d.resolve(data, extra)
                }).fail(createUserFuncFailureHandler(d));
                return this._addFailHandlers(d.promise())
            },
            _byKeyImpl: function(key) {
                var userFunc = this._byKeyFunc,
                    userResult,
                    d = $.Deferred();
                ensureRequiredFuncOption(BY_KEY, userFunc);
                userResult = userFunc(key);
                if (!isPromise(userResult))
                    userResult = trivialPromise(userResult);
                userResult.done(function(obj) {
                    d.resolve(obj)
                }).fail(createUserFuncFailureHandler(d));
                return d.promise()
            },
            _insertImpl: function(values) {
                var userFunc = this._insertFunc,
                    userResult,
                    d = $.Deferred();
                ensureRequiredFuncOption(INSERT, userFunc);
                userResult = userFunc(values);
                if (!isPromise(userResult))
                    userResult = trivialPromise(userResult);
                userResult.done(function(newKey) {
                    d.resolve(values, newKey)
                }).fail(createUserFuncFailureHandler(d));
                return d.promise()
            },
            _updateImpl: function(key, values) {
                var userFunc = this._updateFunc,
                    userResult,
                    d = $.Deferred();
                ensureRequiredFuncOption(UPDATE, userFunc);
                userResult = userFunc(key, values);
                if (!isPromise(userResult))
                    userResult = trivialPromise();
                userResult.done(function() {
                    d.resolve(key, values)
                }).fail(createUserFuncFailureHandler(d));
                return d.promise()
            },
            _removeImpl: function(key) {
                var userFunc = this._removeFunc,
                    userResult,
                    d = $.Deferred();
                ensureRequiredFuncOption(REMOVE, userFunc);
                userResult = userFunc(key);
                if (!isPromise(userResult))
                    userResult = trivialPromise();
                userResult.done(function() {
                    d.resolve(key)
                }).fail(createUserFuncFailureHandler(d));
                return d.promise()
            }
        });
        data.CustomStore_internals = {ERRORS: {
                QUERY_NOT_SUPPORTED: ERROR_QUERY_NOT_SUPPORTED,
                MISSING_USER_FUNC: ERROR_MISSING_USER_FUNC,
                INVALID_RETURN: ERROR_INVALID_RETURN
            }}
    })(jQuery, DevExpress);
    /*! Module core, file data.dataSource.js */
    (function($, DX, undefined) {
        var data = DX.data,
            CustomStore = data.CustomStore,
            Class = DX.Class;
        var storeTypeRegistry = {
                jaydata: "JayDataStore",
                breeze: "BreezeStore",
                odata: "ODataStore",
                local: "LocalStore",
                array: "ArrayStore"
            };
        function normalizeDataSourceOptions(options) {
            var store;
            function createCustomStoreFromLoadFunc() {
                var storeConfig = {};
                $.each(["key", "load", "byKey", "lookup", "totalCount", "insert", "update", "remove"], function() {
                    storeConfig[this] = options[this];
                    delete options[this]
                });
                return new CustomStore(storeConfig)
            }
            function createStoreFromConfig(storeConfig) {
                var storeCtor = data[storeTypeRegistry[storeConfig.type]];
                delete storeConfig.type;
                return new storeCtor(storeConfig)
            }
            function createCustomStoreFromUrl(url) {
                return new CustomStore({load: function() {
                            return $.getJSON(url)
                        }})
            }
            if (typeof options === "string")
                options = createCustomStoreFromUrl(options);
            if (options === undefined)
                options = [];
            if ($.isArray(options) || options instanceof data.Store)
                options = {store: options};
            else
                options = $.extend({}, options);
            if (options.store === undefined)
                options.store = [];
            store = options.store;
            if ("load" in options)
                store = createCustomStoreFromLoadFunc();
            else if ($.isArray(store))
                store = new data.ArrayStore(store);
            else if ($.isPlainObject(store))
                store = createStoreFromConfig($.extend({}, store));
            options.store = store;
            return options
        }
        function normalizeStoreLoadOptionAccessorArguments(originalArguments) {
            switch (originalArguments.length) {
                case 0:
                    return undefined;
                case 1:
                    return originalArguments[0]
            }
            return $.makeArray(originalArguments)
        }
        function generateStoreLoadOptionAccessor(optionName) {
            return function() {
                    var args = normalizeStoreLoadOptionAccessorArguments(arguments);
                    if (args !== undefined)
                        this._storeLoadOptions[optionName] = args;
                    return this._storeLoadOptions[optionName]
                }
        }
        function addOldUserDataSourceBackwardCompatibilityOptions(dataSource, storeLoadOptions) {
            storeLoadOptions.refresh = !dataSource._paginate || dataSource._pageIndex === 0;
            if (storeLoadOptions.searchValue !== null)
                storeLoadOptions.searchString = storeLoadOptions.searchValue
        }
        var DataSource = Class.inherit({
                ctor: function(options) {
                    options = normalizeDataSourceOptions(options);
                    this._store = options.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._totalCount = -1;
                    this._isLoaded = false;
                    this._loadingCount = 0;
                    this._preferSync = options._preferSync;
                    this._loadQueue = this._createLoadQueue();
                    this._searchValue = "searchValue" in options ? options.searchValue : null;
                    this._searchOperation = options.searchOperation || "contains";
                    this._searchExpr = options.searchExpr;
                    this._paginate = options.paginate;
                    if (this._paginate === undefined)
                        this._paginate = !this.group();
                    this._isLastPage = !this._paginate;
                    this._userData = {};
                    this.changed = $.Callbacks();
                    this.loadError = $.Callbacks();
                    this.loadingChanged = $.Callbacks()
                },
                dispose: function() {
                    this.changed.empty();
                    this.loadError.empty();
                    this.loadingChanged.empty();
                    delete this._store;
                    this._disposed = true
                },
                _extractLoadOptions: function(options) {
                    var result = {},
                        names = ["sort", "filter", "select", "group", "requireTotalCount"],
                        customNames = this._store._customLoadOptions();
                    if (customNames)
                        names = names.concat(customNames);
                    $.each(names, function() {
                        result[this] = options[this]
                    });
                    return result
                },
                loadOptions: function() {
                    return this._storeLoadOptions
                },
                items: function() {
                    return this._items
                },
                pageIndex: function(newIndex) {
                    if (newIndex !== undefined) {
                        this._pageIndex = newIndex;
                        this._isLastPage = !this._paginate
                    }
                    return this._pageIndex
                },
                paginate: function(value) {
                    if (arguments.length < 1)
                        return this._paginate;
                    value = !!value;
                    if (this._paginate !== value) {
                        this._paginate = value;
                        this.pageIndex(0)
                    }
                },
                isLastPage: function() {
                    return this._isLastPage
                },
                sort: generateStoreLoadOptionAccessor("sort"),
                filter: function() {
                    var newFilter = normalizeStoreLoadOptionAccessorArguments(arguments);
                    if (newFilter !== undefined) {
                        this._storeLoadOptions.filter = newFilter;
                        this.pageIndex(0)
                    }
                    return this._storeLoadOptions.filter
                },
                group: generateStoreLoadOptionAccessor("group"),
                select: generateStoreLoadOptionAccessor("select"),
                searchValue: function(value) {
                    if (value !== undefined) {
                        this.pageIndex(0);
                        this._searchValue = value
                    }
                    return this._searchValue
                },
                searchOperation: function(op) {
                    if (op !== undefined) {
                        this.pageIndex(0);
                        this._searchOperation = op
                    }
                    return this._searchOperation
                },
                searchExpr: function(expr) {
                    var argc = arguments.length;
                    if (argc) {
                        if (argc > 1)
                            expr = $.makeArray(arguments);
                        this.pageIndex(0);
                        this._searchExpr = expr
                    }
                    return this._searchExpr
                },
                store: function() {
                    return this._store
                },
                key: function() {
                    return this._store && this._store.key()
                },
                totalCount: function() {
                    return this._totalCount
                },
                isLoaded: function() {
                    return this._isLoaded
                },
                isLoading: function() {
                    return this._loadingCount > 0
                },
                _createLoadQueue: function() {
                    return DX.createQueue()
                },
                _changeLoadingCount: function(increment) {
                    var oldLoading = this.isLoading(),
                        newLoading;
                    this._loadingCount += increment;
                    newLoading = this.isLoading();
                    if (oldLoading ^ newLoading)
                        this.loadingChanged.fire(newLoading)
                },
                _scheduleLoadCallbacks: function(deferred) {
                    var thisSource = this;
                    thisSource._changeLoadingCount(1);
                    deferred.always(function() {
                        thisSource._changeLoadingCount(-1)
                    })
                },
                _scheduleChangedCallbacks: function(deferred) {
                    var that = this;
                    deferred.done(function() {
                        that.changed.fire()
                    })
                },
                loadSingle: function(propName, propValue) {
                    var that = this;
                    var d = $.Deferred().fail(this.loadError.fire),
                        key = this.key(),
                        store = this._store,
                        loadOptions = this._createStoreLoadOptions();
                    function handleSuccess(data) {
                        d.resolve(that._transformLoadedData(data)[0])
                    }
                    if (arguments.length < 2) {
                        propValue = propName;
                        propName = key
                    }
                    delete loadOptions.skip;
                    delete loadOptions.group;
                    delete loadOptions.refresh;
                    delete loadOptions.pageIndex;
                    delete loadOptions.searchString;
                    if (propName === key || store instanceof data.CustomStore)
                        store.byKey(propValue, loadOptions).done(handleSuccess).fail(d.reject);
                    else {
                        loadOptions.take = 1;
                        loadOptions._preferSync = true;
                        loadOptions.filter = loadOptions.filter ? [loadOptions.filter, [propName, propValue]] : [propName, propValue];
                        store.load(loadOptions).done(handleSuccess).fail(d.reject)
                    }
                    return d.promise()
                },
                load: function() {
                    var thisSource = this,
                        d = $.Deferred(),
                        errorCallback = this.loadError,
                        storeLoadOptions;
                    this._scheduleLoadCallbacks(d);
                    this._scheduleChangedCallbacks(d);
                    storeLoadOptions = this._createStoreLoadOptions();
                    function loadTask() {
                        if (thisSource._disposed)
                            return undefined;
                        return thisSource._loadFromStore(storeLoadOptions, d)
                    }
                    this._loadQueue.add(function() {
                        loadTask();
                        return d.promise()
                    }, function() {
                        thisSource._changeLoadingCount(-1)
                    });
                    return d.promise().fail($.proxy(errorCallback.fire, errorCallback))
                },
                _addSearchOptions: function(storeLoadOptions) {
                    if (this._disposed)
                        return;
                    if (this.store()._useDefaultSearch)
                        this._addSearchFilter(storeLoadOptions);
                    else {
                        storeLoadOptions.searchValue = this._searchValue;
                        storeLoadOptions.searchExpr = this._searchExpr
                    }
                },
                _createStoreLoadOptions: function() {
                    var result = $.extend({}, this._storeLoadOptions);
                    this._addSearchOptions(result);
                    if (this._paginate) {
                        result.pageIndex = this._pageIndex;
                        if (this._pageSize) {
                            result.skip = this._pageIndex * this._pageSize;
                            result.take = this._pageSize
                        }
                    }
                    result.userData = this._userData;
                    addOldUserDataSourceBackwardCompatibilityOptions(this, result);
                    return result
                },
                _addSearchFilter: function(storeLoadOptions) {
                    var value = this._searchValue,
                        op = this._searchOperation,
                        selector = this._searchExpr,
                        searchFilter = [];
                    if (!value)
                        return;
                    if (!selector)
                        selector = "this";
                    if (!$.isArray(selector))
                        selector = [selector];
                    $.each(selector, function(i, item) {
                        if (searchFilter.length)
                            searchFilter.push("or");
                        searchFilter.push([item, op, value])
                    });
                    if (storeLoadOptions.filter)
                        storeLoadOptions.filter = [searchFilter, storeLoadOptions.filter];
                    else
                        storeLoadOptions.filter = searchFilter
                },
                _loadFromStore: function(storeLoadOptions, pendingDeferred) {
                    var thisSource = this;
                    function handleSuccess(data, extra) {
                        function processResult() {
                            thisSource._processStoreLoadResult(data, extra, storeLoadOptions, pendingDeferred)
                        }
                        if (thisSource._preferSync)
                            processResult();
                        else
                            DX.utils.executeAsync(processResult)
                    }
                    return this.store().load(storeLoadOptions).done(handleSuccess).fail($.proxy(pendingDeferred.reject, pendingDeferred))
                },
                _processStoreLoadResult: function(data, extra, storeLoadOptions, pendingDeferred) {
                    var thisSource = this;
                    function resolvePendingDeferred() {
                        thisSource._isLoaded = true;
                        thisSource._totalCount = isFinite(extra.totalCount) ? extra.totalCount : -1;
                        return pendingDeferred.resolve(data, extra)
                    }
                    function proceedLoadingTotalCount() {
                        thisSource.store().totalCount(storeLoadOptions).done(function(count) {
                            extra.totalCount = count;
                            resolvePendingDeferred()
                        }).fail(function(){})
                    }
                    if (thisSource._disposed)
                        return;
                    data = thisSource._transformLoadedData(data);
                    if (!$.isPlainObject(extra))
                        extra = {};
                    thisSource._items = data;
                    if (!data.length || !thisSource._paginate || thisSource._pageSize && data.length < thisSource._pageSize)
                        thisSource._isLastPage = true;
                    if (storeLoadOptions.requireTotalCount && !isFinite(extra.totalCount))
                        proceedLoadingTotalCount();
                    else
                        resolvePendingDeferred()
                },
                _transformLoadedData: function(data) {
                    var result = $.makeArray(data);
                    if (this._mapFunc)
                        result = $.map(result, this._mapFunc);
                    if (this._postProcessFunc)
                        result = this._postProcessFunc(result);
                    return result
                }
            });
        data.Store.redefine({toDataSource: function(options) {
                DX.utils.logger.warn("toDataSource() method is deprecated, use 'new DevExpress.data.DataSource(...)' instead");
                return new DataSource($.extend({store: this}, options))
            }});
        $.extend(true, data, {
            DataSource: DataSource,
            createDataSource: function(options) {
                DX.utils.logger.warn("createDataSource() method is deprecated, use 'new DevExpress.data.DataSource(...)' instead");
                return new DataSource(options)
            },
            utils: {
                storeTypeRegistry: storeTypeRegistry,
                normalizeDataSourceOptions: normalizeDataSourceOptions
            }
        })
    })(jQuery, DevExpress);
    /*! Module core, file ko.js */
    (function($, DX, undefined) {
        if (!DX.support.hasKo)
            return;
        var ko = window.ko;
        (function checkKnockoutVersion(version) {
            version = version.split(".");
            if (version[0] < 2 || version[0] == 2 && version[1] < 3)
                throw Error("Your version of KnockoutJS is too old. Please upgrade KnockoutJS to 2.3.0 or later.");
        })(ko.version)
    })(jQuery, DevExpress);
    /*! Module core, file ng.js */
    (function($, DX, undefined) {
        if (!DX.support.hasNg)
            return;
        DX.ng = {module: window.angular.module("dx", ["ngSanitize"])}
    })(jQuery, DevExpress);
    /*! Module core, file component.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            utils = DX.utils,
            dataUtils = DX.data.utils;
        var Component = DX.Class.inherit({
                NAME: "Component",
                _deprecatedOptions: {},
                _optionAliases: {},
                _setDefaultOptions: function(){},
                _defaultOptionsRules: function() {
                    return []
                },
                _setOptionsByDevice: function() {
                    var rules = this._defaultOptionsRules(),
                        currentDevice = DX.devices.current(),
                        result = {};
                    if (this._customRules)
                        rules = rules.concat(this._customRules);
                    var deviceMatch = function(device, filter) {
                            filter = $.makeArray(filter);
                            return filter.length === 1 && $.isEmptyObject(filter[0]) || utils.findBestMatches(device, filter).length > 0
                        };
                    $.each(rules, function(index, rule) {
                        var deviceFilter = rule.device || {},
                            match;
                        if ($.isFunction(deviceFilter))
                            match = deviceFilter(currentDevice);
                        else
                            match = deviceMatch(currentDevice, deviceFilter);
                        if (match)
                            $.extend(result, rule.options)
                    });
                    this.option(result)
                },
                _optionsByReference: function() {
                    return {}
                },
                ctor: function(options) {
                    if (!this.NAME)
                        throw Error("NAME is not specified");
                    this._options = {};
                    this._updateLockCount = 0;
                    this.optionChanged = $.Callbacks();
                    this.beginUpdate();
                    try {
                        this._suppressDeprecatedWarnings();
                        this._setDefaultOptions();
                        this._setOptionsByDevice();
                        this._resumeDeprecatedWarnings();
                        this._initialOptions = $.extend({}, this.option());
                        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 && newValue && oldValue.jquery && newValue.jquery)
                        return newValue.is(oldValue);
                    if (oldValue === null || typeof oldValue !== "object")
                        return oldValue === newValue;
                    return false
                },
                _init: $.noop,
                _optionChanged: $.noop,
                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
                            }
                        }
                },
                _logWarningIfDeprecated: function(option) {
                    var info = this._deprecatedOptions[option];
                    if (info && !this._deprecatedOptionsSuppressed)
                        this._logDeprecatedWarning(option, info)
                },
                _logDeprecatedWarningCount: 0,
                _logDeprecatedWarning: function(option, info) {
                    utils.logger.warn("'" + option + "' option is deprecated since " + info.since + ". " + info.message);
                    ++this._logDeprecatedWarningCount
                },
                _suppressDeprecatedWarnings: function() {
                    this._deprecatedOptionsSuppressed = true
                },
                _resumeDeprecatedWarnings: function() {
                    this._deprecatedOptionsSuppressed = false
                },
                _getOptionAliases: function(option) {
                    return $.map(this._optionAliases, function(aliasedOption, alias) {
                            return option === aliasedOption ? alias : undefined
                        })
                },
                _notifyOptionChanged: function(option, value, previousValue) {
                    var that = this,
                        optionWithAliases;
                    if (this._initialized) {
                        optionWithAliases = this._getOptionAliases(option);
                        optionWithAliases.push(option);
                        $.each(optionWithAliases, function(index, name) {
                            var topLevelName = name.split(/[.\[]/)[0];
                            that.optionChanged.fireWith(that, [topLevelName, value, previousValue]);
                            that._optionChanged(topLevelName, value, previousValue)
                        })
                    }
                },
                initialOption: function(optionName) {
                    var options = this._initialOptions;
                    return options[optionName]
                },
                option: function(options) {
                    var that = this,
                        name = options,
                        value = arguments[1];
                    if (arguments.length < 2 && $.type(name) !== "object") {
                        if (name) {
                            this._logWarningIfDeprecated(name);
                            if (this._optionAliases[name])
                                name = this._optionAliases[name]
                        }
                        $.each(this._optionAliases, function(alias, option) {
                            that._options[alias] = dataUtils.compileGetter(option)(that._options, {functionsAsIs: true})
                        });
                        return dataUtils.compileGetter(name)(that._options, {functionsAsIs: true})
                    }
                    if (typeof name === "string") {
                        options = {};
                        options[name] = value
                    }
                    that.beginUpdate();
                    try {
                        $.each(options, function(name, value) {
                            that._logWarningIfDeprecated(name);
                            if (that._optionAliases[name])
                                name = that._optionAliases[name];
                            var prevValue = dataUtils.compileGetter(name)(that._options, {functionsAsIs: true});
                            if (that._optionValuesEqual(name, prevValue, value))
                                return;
                            dataUtils.compileSetter(name)(that._options, value, {
                                functionsAsIs: true,
                                merge: !that._optionsByReference()[name]
                            });
                            that._notifyOptionChanged(name, value, prevValue)
                        })
                    }
                    finally {
                        that.endUpdate()
                    }
                }
            });
        $.extend(DX, {Component: Component})
    })(jQuery, DevExpress);
    /*! Module core, file DOMComponent.js */
    (function($, DX, undefined) {
        var windowResizeCallbacks = DX.utils.windowResizeCallbacks;
        var RTL_DIRECTION_CLASS = "dx-rtl",
            COMPONENT_NAMES_DATA_KEY = "dxComponents",
            VISIBILITY_CHANGE_CLASS = "dx-visibility-change-handler",
            VISIBILITY_CHANGE_EVENTNAMESPACE = "dxVisibilityChange";
        var DOMComponent = DX.Component.inherit({
                NAME: "DOMComponent",
                NAMESPACE: DX,
                _setDefaultOptions: function() {
                    this.callBase();
                    this.option({rtlEnabled: DX.rtlEnabled})
                },
                ctor: function(element, options) {
                    this._$element = $(element);
                    this._element().data(this.NAME, this);
                    this._attachInstanceToElement(this._$element);
                    this.disposing = $.Callbacks();
                    this.callBase(options)
                },
                _attachInstanceToElement: $.noop,
                _visibilityChanged: DX.abstract,
                _dimensionChanged: DX.abstract,
                _init: function() {
                    this.callBase();
                    this._attachWindowResizeCallback()
                },
                _attachWindowResizeCallback: function() {
                    if (this._isDimensionChangeSupported()) {
                        var windowResizeCallBack = this._windowResizeCallBack = $.proxy(this._dimensionChanged, this);
                        windowResizeCallbacks.add(windowResizeCallBack)
                    }
                },
                _isDimensionChangeSupported: function() {
                    return this._dimensionChanged !== DX.abstract
                },
                _render: function() {
                    this._toggleRTLDirection(this.option("rtlEnabled"));
                    this._renderVisiblityChange()
                },
                _renderVisiblityChange: function() {
                    if (!this._isVisibilityChangeSupported())
                        return;
                    this._element().addClass(VISIBILITY_CHANGE_CLASS);
                    this._attachVisiblityChangeHandlers()
                },
                _attachVisiblityChangeHandlers: function() {
                    var that = this;
                    that._element().off("." + VISIBILITY_CHANGE_EVENTNAMESPACE).on("dxhiding." + VISIBILITY_CHANGE_EVENTNAMESPACE, function() {
                        that._visibilityChanged(false)
                    }).on("dxshown." + VISIBILITY_CHANGE_EVENTNAMESPACE, function() {
                        that._visibilityChanged(true)
                    })
                },
                _isVisibilityChangeSupported: function() {
                    return this._visibilityChanged !== DX.abstract
                },
                _clean: $.noop,
                _modelByElement: $.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._detachWindowResizeCallback();
                    this.optionChanged.empty();
                    this.disposing.fireWith(this).empty()
                },
                _detachWindowResizeCallback: function() {
                    if (this._isDimensionChangeSupported())
                        windowResizeCallbacks.remove(this._windowResizeCallBack)
                },
                _toggleRTLDirection: function(rtl) {
                    this._element().toggleClass(RTL_DIRECTION_CLASS, rtl)
                },
                _createAction: function(actionSource, config) {
                    var that = this;
                    config = $.extend({}, config);
                    var element = config.element || that._element(),
                        model = that._modelByElement(element);
                    config.context = model || that;
                    config.component = that;
                    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: that,
                                    element: element,
                                    model: model
                                }))
                        }
                },
                _createActionByOption: function(optionName, config) {
                    if (typeof optionName !== "string")
                        throw Error("Option name type is unexpected");
                    this._suppressDeprecatedWarnings();
                    var action = this._createAction(this.option(optionName), config);
                    this._resumeDeprecatedWarnings();
                    return action
                },
                _optionChanged: function(name, value, prevValue) {
                    if (name === "rtlEnabled")
                        this._invalidate()
                },
                _element: function() {
                    return this._$element
                },
                endUpdate: function() {
                    var requireRender = !this._initializing && !this._initialized;
                    this.callBase.apply(this, arguments);
                    if (!this._updateLockCount)
                        if (requireRender)
                            this._render();
                        else if (this._requireRefresh) {
                            this._requireRefresh = false;
                            this._refresh()
                        }
                }
            });
        var registerComponent = function(name, componentClass) {
                componentClass.redefine({_attachInstanceToElement: function($element) {
                        $element.data(name, this);
                        if (!$element.data(COMPONENT_NAMES_DATA_KEY))
                            $element.data(COMPONENT_NAMES_DATA_KEY, []);
                        $element.data(COMPONENT_NAMES_DATA_KEY).push(name)
                    }});
                componentClass.prototype.NAMESPACE[name] = componentClass;
                componentClass.prototype.NAME = name;
                componentClass.defaultOptions = function(rule) {
                    componentClass.prototype._customRules = componentClass.prototype._customRules || [];
                    componentClass.prototype._customRules.push(rule)
                };
                $.fn[name] = function(options) {
                    var isMemberInvoke = typeof options === "string",
                        result;
                    if (isMemberInvoke) {
                        var memberName = options,
                            memberArgs = $.makeArray(arguments).slice(1);
                        this.each(function() {
                            var instance = $(this).data(name);
                            if (!instance)
                                throw Error(DX.utils.stringFormat("Component {0} has not been initialized on this element", name));
                            var member = instance[memberName],
                                memberValue = member.apply(instance, memberArgs);
                            if (result === undefined)
                                result = memberValue
                        })
                    }
                    else {
                        this.each(function() {
                            var instance = $(this).data(name);
                            if (instance)
                                instance.option(options);
                            else
                                new componentClass(this, options)
                        });
                        result = this
                    }
                    return result
                }
            };
        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)
                    })
            };
        var disposeComponents = function() {
                $.each(getComponents(this), function() {
                    this._dispose()
                })
            };
        var originalCleanData = $.cleanData;
        $.cleanData = function(element) {
            $.each(element, disposeComponents);
            return originalCleanData.apply(this, arguments)
        };
        registerComponent("DOMComponent", DOMComponent);
        DX.registerComponent = registerComponent
    })(jQuery, DevExpress);
    /*! Module core, file social.js */
    DevExpress.social = {};
    /*! Module core, file facebook.js */
    (function($, DX, undefined) {
        function notifyDeprecated() {
            DX.utils.logger.warn("DevExpress.social API is deprecated. Use official Facebook library instead")
        }
        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) {
                notifyDeprecated();
                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() {
                notifyDeprecated();
                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) {
                notifyDeprecated();
                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 TemplateProvider = DX.Class.inherit({
                getTemplateClass: function() {
                    return Template
                },
                supportDefaultTemplate: function() {
                    return false
                },
                getDefaultTemplate: function() {
                    return null
                }
            });
        var Template = DX.Class.inherit({
                ctor: function(element, owner) {
                    this._template = this._element = $(element).detach();
                    this._owner = owner
                },
                render: function(container) {
                    var renderedTemplate = this._template.clone();
                    container.append(renderedTemplate);
                    return renderedTemplate
                },
                dispose: function() {
                    this._owner = null
                },
                owner: function() {
                    return this._owner
                }
            });
        var GESTURE_LOCK_KEY = "dxGestureLock";
        DX.registerActionExecutor({
            designMode: {validate: function(e) {
                    if (DX.designMode)
                        e.cancel = true
                }},
            gesture: {validate: function(e) {
                    if (!e.args.length)
                        return;
                    var args = e.args[0],
                        jQueryEvent = args.jQueryEvent;
                    if (!jQueryEvent)
                        return;
                    var element = $(jQueryEvent.target);
                    while (element && element.length) {
                        if (element.data(GESTURE_LOCK_KEY)) {
                            e.cancel = true;
                            break
                        }
                        element = element.parent()
                    }
                }},
            disabled: {validate: function(e) {
                    if (!e.args.length)
                        return;
                    var args = e.args[0],
                        element = args.itemElement || args.element;
                    if (element && element.is(".dx-state-disabled, .dx-state-disabled *"))
                        e.cancel = true
                }}
        });
        $.extend(ui, {
            TemplateProvider: TemplateProvider,
            Template: Template,
            initViewport: function() {
                DX.utils.logger.warn("DevExpress.ui.initViewport is deprecated. Use DX.utils.initMobileViewport instead");
                DX.utils.initMobileViewport()
            }
        });
        ui.__internals = ui.__internals || {};
        $.extend(ui.__internals, {Template: Template})
    })(jQuery, DevExpress);
    /*! Module core, file ko.components.js */
    (function($, DX, undefined) {
        if (!DX.support.hasKo)
            return;
        var ko = window.ko,
            ui = DX.ui,
            LOCKS_DATA_KEY = "dxKoLocks",
            CREATED_WITH_KO_DATA_KEY = "dxKoCreation";
        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) {
                ko.bindingHandlers[componentName] = {init: function(domNode, valueAccessor) {
                        var element = $(domNode),
                            ctorOptions = {},
                            optionNameToModelMap = {};
                        var applyModelValueToOption = function(optionName, modelValue) {
                                var component = element.data(componentName),
                                    locks = element.data(LOCKS_DATA_KEY),
                                    optionValue = ko.utils.unwrapObservable(modelValue);
                                if (ko.isWriteableObservable(modelValue))
                                    optionNameToModelMap[optionName] = modelValue;
                                if (component) {
                                    if (locks.locked(optionName))
                                        return;
                                    locks.obtain(optionName);
                                    try {
                                        component.option(optionName, optionValue)
                                    }
                                    finally {
                                        locks.release(optionName)
                                    }
                                }
                                else
                                    ctorOptions[optionName] = optionValue
                            };
                        var handleOptionChanged = function(optionName, optionValue) {
                                if (!(optionName in optionNameToModelMap))
                                    return;
                                var element = this._$element,
                                    locks = element.data(LOCKS_DATA_KEY);
                                if (locks.locked(optionName))
                                    return;
                                locks.obtain(optionName);
                                try {
                                    optionNameToModelMap[optionName](optionValue)
                                }
                                finally {
                                    locks.release(optionName)
                                }
                            };
                        var createComponent = function() {
                                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)
                            };
                        ko.computed(function() {
                            var component = element.data(componentName);
                            if (component)
                                component.beginUpdate();
                            $.each(ko.unwrap(valueAccessor()), function(modelName, modelValueExpr) {
                                ko.computed(function() {
                                    applyModelValueToOption(modelName, modelValueExpr)
                                }, null, {disposeWhenNodeIsRemoved: domNode})
                            });
                            if (component)
                                component.endUpdate();
                            else
                                createComponent()
                        }, null, {disposeWhenNodeIsRemoved: domNode});
                        return {controlsDescendantBindings: ui[componentName] && ui[componentName].subclassOf(ui.Widget)}
                    }}
            };
        var KoComponent = DX.DOMComponent.inherit({_modelByElement: function(element) {
                    if (element.length)
                        return ko.dataFor(element.get(0))
                }});
        var originalRegisterComponent = DX.registerComponent;
        var registerKoComponent = function(name, componentClass) {
                originalRegisterComponent(name, componentClass);
                registerComponentKoBinding(name)
            };
        ko.bindingHandlers.dxAction = {update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
                var $element = $(element);
                var unwrappedValue = ko.utils.unwrapObservable(valueAccessor()),
                    actionSource = unwrappedValue,
                    actionOptions = {context: element};
                if (unwrappedValue.execute) {
                    actionSource = unwrappedValue.execute;
                    $.extend(actionOptions, unwrappedValue)
                }
                var action = new DX.Action(actionSource, actionOptions);
                $element.off(".dxActionBinding").on("dxclick.dxActionBinding", function(e) {
                    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)
                        },
                        jQueryEvent: e
                    });
                    if (!actionOptions.bubbling)
                        e.stopPropagation()
                })
            }};
        var cleanKoData = function(element, andSelf) {
                var cleanNode = function() {
                        ko.cleanNode(this)
                    };
                if (andSelf)
                    element.each(cleanNode);
                else
                    element.find("*").each(cleanNode)
            };
        var originalEmpty = $.fn.empty;
        $.fn.empty = function() {
            cleanKoData(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);
                cleanKoData(subject, true)
            }
            return originalRemove.call(this, selector, keepData)
        };
        var originalHtml = $.fn.html;
        $.fn.html = function(value) {
            if (typeof value === "string")
                cleanKoData(this, false);
            return originalHtml.apply(this, arguments)
        };
        DX.registerComponent = registerKoComponent;
        registerKoComponent("DOMComponent", KoComponent)
    })(jQuery, DevExpress);
    /*! Module core, file ng.components.js */
    (function($, DX, undefined) {
        if (!DX.support.hasNg)
            return;
        var ui = DX.ui,
            compileSetter = DX.data.utils.compileSetter,
            compileGetter = DX.data.utils.compileGetter;
        var CREATED_WITH_NG_DATA_KEY = "dxNgCreation",
            TEMPLATES_DATA_KEY = "dxTemplates",
            COMPILER_DATA_KEY = "dxNgCompiler",
            DEFAULT_COMPILER_DATA_KEY = "dxDefaultCompilerGetter",
            ANONYMOUS_TEMPLATE_NAME = "template";
        var phoneJsModule = DX.ng.module;
        var ComponentBuilder = DX.Class.inherit({
                ctor: function(options) {
                    this._componentName = options.componentName;
                    this._$element = options.$element;
                    this._$templates = options.$templates;
                    this._scope = options.scope;
                    this._compile = options.compile;
                    this._ngOptions = options.ngOptions;
                    this._componentDisposing = $.Callbacks();
                    this._$element.data(CREATED_WITH_NG_DATA_KEY, true);
                    if (options.ngOptions.data)
                        this._initDataScope(options.ngOptions.data)
                },
                initDefaultCompilerGetter: function() {
                    var that = this;
                    that._$element.data(DEFAULT_COMPILER_DATA_KEY, function($template) {
                        return that._compilerByTemplate($template)
                    })
                },
                initTemplateCompilers: function() {
                    var that = this;
                    if (this._$templates)
                        this._$templates.each(function(i, template) {
                            $(template).data(COMPILER_DATA_KEY, that._compilerByTemplate(template))
                        })
                },
                initComponentWithBindings: function() {
                    this._initComponent(this._scope);
                    this._initComponentBindings()
                },
                _initDataScope: function(data) {
                    if (typeof data === "string") {
                        var dataStr = data,
                            rootScope = this._scope;
                        data = rootScope.$eval(data);
                        this._scope = rootScope.$new();
                        this._synchronizeDataScopes(rootScope, this._scope, data, dataStr)
                    }
                    $.extend(this._scope, data)
                },
                _synchronizeDataScopes: function(parentScope, childScope, data, parentPrefix) {
                    var that = this;
                    $.each(data, function(fieldPath) {
                        that._synchronizeScopeField({
                            parentScope: parentScope,
                            childScope: childScope,
                            fieldPath: fieldPath,
                            parentPrefix: parentPrefix
                        })
                    })
                },
                _initComponent: function(scope) {
                    this._component = this._$element[this._componentName](this._evalOptions(scope)).data(this._componentName)
                },
                _initComponentBindings: function() {
                    var that = this,
                        optionDependencies = {};
                    if (that._ngOptions.bindingOptions)
                        $.each(that._ngOptions.bindingOptions, function(optionPath, valuePath) {
                            var separatorIndex = optionPath.search(/\[|\./),
                                optionForSubscribe = separatorIndex > -1 ? optionPath.substring(0, separatorIndex) : optionPath,
                                watchMethod = $.isArray(that._scope.$eval(valuePath)) ? "$watchCollection" : "$watch";
                            if (!optionDependencies[optionForSubscribe])
                                optionDependencies[optionForSubscribe] = {};
                            optionDependencies[optionForSubscribe][optionPath] = valuePath;
                            var clearWatcher = that._scope[watchMethod](valuePath, function(newValue, oldValue) {
                                    if (newValue !== oldValue)
                                        that._component.option(optionPath, newValue)
                                }, true);
                            that._component.disposing.add(function() {
                                clearWatcher();
                                that._componentDisposing.fire()
                            })
                        });
                    that._component.optionChanged.add(function(optionName, optionValue) {
                        if (that._scope.$root.$$phase === "$digest" || !optionDependencies || !optionDependencies[optionName])
                            return;
                        safeApply(function(scope) {
                            $.each(optionDependencies[optionName], function(optionPath, valuePath) {
                                var setter = compileSetter(valuePath),
                                    getter = compileGetter(optionPath);
                                var tmpData = {};
                                tmpData[optionName] = optionValue;
                                setter(scope, getter(tmpData))
                            })
                        }, that._scope)
                    })
                },
                _compilerByTemplate: function(template) {
                    var that = this,
                        scopeItemsPath = this._getScopeItemsPath();
                    return function(data, index) {
                            var $resultMarkup = $(template).clone(),
                                templateScope;
                            if (data !== undefined) {
                                var dataIsScope = data.$id,
                                    templateScope = dataIsScope ? data : that._createScopeWithData(data);
                                $resultMarkup.on("$destroy", function() {
                                    var destroyAlreadyCalled = !templateScope.$parent;
                                    if (destroyAlreadyCalled)
                                        return;
                                    templateScope.$destroy()
                                })
                            }
                            else
                                templateScope = that._scope;
                            if (scopeItemsPath)
                                that._synchronizeScopes(templateScope, scopeItemsPath, index);
                            safeApply(that._compile($resultMarkup), templateScope);
                            return $resultMarkup
                        }
                },
                _getScopeItemsPath: function() {
                    if (ui[this._componentName].subclassOf(ui.CollectionContainerWidget) && this._ngOptions.bindingOptions)
                        return this._ngOptions.bindingOptions.items
                },
                _createScopeWithData: function(data) {
                    var newScope = this._scope.$new(true);
                    if (typeof data === "object")
                        $.extend(newScope, data);
                    else
                        newScope.scopeValue = data;
                    return newScope
                },
                _synchronizeScopes: function(itemScope, parentPrefix, itemIndex) {
                    var that = this,
                        item = compileGetter(parentPrefix + "[" + itemIndex + "]")(this._scope);
                    if (!$.isPlainObject(item))
                        item = {scopeValue: item};
                    $.each(item, function(itemPath) {
                        that._synchronizeScopeField({
                            parentScope: that._scope,
                            childScope: itemScope,
                            fieldPath: itemPath,
                            parentPrefix: parentPrefix,
                            itemIndex: itemIndex
                        })
                    })
                },
                _synchronizeScopeField: function(args) {
                    var parentScope = args.parentScope,
                        childScope = args.childScope,
                        fieldPath = args.fieldPath,
                        parentPrefix = args.parentPrefix,
                        itemIndex = args.itemIndex;
                    var innerPathSuffix = fieldPath === "scopeValue" ? "" : "." + fieldPath,
                        collectionField = itemIndex !== undefined,
                        optionOuterBag = [parentPrefix],
                        optionOuterPath;
                    if (collectionField)
                        optionOuterBag.push("[", itemIndex, "]");
                    optionOuterBag.push(innerPathSuffix);
                    optionOuterPath = optionOuterBag.join("");
                    var clearParentWatcher = parentScope.$watch(optionOuterPath, function(newValue, oldValue) {
                            if (newValue !== oldValue)
                                compileSetter(fieldPath)(childScope, newValue)
                        });
                    var clearItemWatcher = childScope.$watch(fieldPath, function(newValue, oldValue) {
                            if (newValue !== oldValue) {
                                if (collectionField && !compileGetter(parentPrefix)(parentScope)[itemIndex]) {
                                    clearItemWatcher();
                                    return
                                }
                                compileSetter(optionOuterPath)(parentScope, newValue)
                            }
                        });
                    this._componentDisposing.add([clearParentWatcher, clearItemWatcher])
                },
                _evalOptions: function(scope) {
                    var result = $.extend({}, this._ngOptions);
                    delete result.data;
                    delete result.bindingOptions;
                    if (this._ngOptions.bindingOptions)
                        $.each(this._ngOptions.bindingOptions, function(key, value) {
                            result[key] = scope.$eval(value)
                        });
                    return result
                }
            });
        var safeApply = function(func, scope) {
                if (scope.$root.$$phase)
                    func(scope);
                else
                    scope.$apply(function() {
                        func(scope)
                    })
            };
        var extractTemplates = function($element, componentName) {
                if ($element.data(TEMPLATES_DATA_KEY))
                    return $element.data(TEMPLATES_DATA_KEY);
                var $templates;
                if (ui[componentName] && ui[componentName].subclassOf(ui.Widget) && $.trim($element.html())) {
                    var isAnonymousTemplate = !$element.children().first().attr("data-options");
                    if (isAnonymousTemplate)
                        $templates = $("<div/>").attr("data-options", "dxTemplate: { name: '" + ANONYMOUS_TEMPLATE_NAME + "' }").append($element.contents());
                    else
                        $templates = $element.children().detach();
                    $element.data(TEMPLATES_DATA_KEY, $templates)
                }
                return $templates
            };
        var NgComponent = DX.DOMComponent.inherit({
                _modelByElement: function(element) {
                    if (element.length)
                        return element.scope()
                },
                _createActionByOption: function() {
                    var action = this.callBase.apply(this, arguments);
                    var component = this,
                        wrappedAction = function() {
                            var that = this,
                                scope = component._modelByElement(component._element()),
                                args = arguments;
                            if (!scope || scope.$root.$$phase)
                                return action.apply(that, args);
                            return scope.$apply(function() {
                                    return action.apply(that, args)
                                })
                        };
                    return wrappedAction
                }
            });
        var originalRegisterComponent = DX.registerComponent;
        var registerNgComponent = function(componentName, componentClass) {
                originalRegisterComponent(componentName, componentClass);
                phoneJsModule.directive(componentName, ["$compile", function(compile) {
                        return {
                                restrict: "A",
                                compile: function($element) {
                                    var $templates = extractTemplates($element, componentName);
                                    return function(scope, $element, attrs) {
                                            var componentBuilder = new ComponentBuilder({
                                                    componentName: componentName,
                                                    compile: compile,
                                                    $element: $element,
                                                    scope: scope,
                                                    ngOptions: attrs[componentName] ? scope.$eval(attrs[componentName]) : {},
                                                    $templates: $templates
                                                });
                                            componentBuilder.initTemplateCompilers();
                                            componentBuilder.initDefaultCompilerGetter();
                                            componentBuilder.initComponentWithBindings()
                                        }
                                }
                            }
                    }])
            };
        DX.registerComponent = registerNgComponent;
        registerNgComponent("DOMComponent", NgComponent)
    })(jQuery, DevExpress);
    /*! Module core, file ko.templates.js */
    (function($, DX, undefined) {
        if (!DX.support.hasKo)
            return;
        var ko = window.ko,
            ui = DX.ui,
            CREATED_WITH_KO_DATA_KEY = "dxKoCreation";
        var KoTemplate = ui.Template.inherit({
                ctor: function(element) {
                    this.callBase.apply(this, arguments);
                    this._template = $("<div>").append(element);
                    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) {
                    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.callBase();
                    this._template.remove()
                }
            });
        var KoTemplateProvider = ui.TemplateProvider.inherit({
                getTemplateClass: function(widget) {
                    return this._createdWithKo(widget) ? KoTemplate : 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)
                }
            });
        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);
                            cache[widgetName] = new KoTemplate(markup)
                        }
                        return cache[widgetName]
                    }
            }();
        var createElementWithBindAttr = function(tagName, bindings, closeTag, additionalProperties) {
                closeTag = closeTag === undefined ? true : closeTag;
                var bindAttr = $.map(bindings, function(value, key) {
                        return key + ":" + value
                    }).join(",");
                additionalProperties = additionalProperties || "";
                return "<" + tagName + " data-bind=\"" + bindAttr + "\" " + additionalProperties + ">" + (closeTag ? "</" + tagName + ">" : "")
            };
        var defaultKoTemplateBasicBindings = {css: "{ 'dx-state-disabled': $data.disabled, 'dx-state-invisible': !($data.visible === undefined || ko.unwrap($data.visible)) }"};
        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", {text: "String($data)"});
                    template.push("<!-- ko if: $data.html && !$data.text -->", htmlBinding, "<!-- /ko -->", "<!-- ko if: !$data.html && $data.text -->", textBinding, "<!-- /ko -->", "<!-- ko ifnot: $.isPlainObject($data) -->", primitiveBinding, "<!-- /ko -->", "</div>");
                    return template.join("")
                }};
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxPivotTabs = function() {
            var template = DEFAULT_ITEM_TEMPLATE_GENERATORS.base(),
                titleBinding = createElementWithBindAttr("span", {text: "title"});
            var divInnerStart = template.indexOf(">") + 1,
                divInnerFinish = template.length - 6;
            template = [template.substring(0, divInnerStart), titleBinding, template.substring(divInnerFinish, template.length)];
            return template.join("")
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxPanorama = function() {
            var template = DEFAULT_ITEM_TEMPLATE_GENERATORS.base(),
                headerBinding = createElementWithBindAttr("div", {text: "header"}, true, 'class="dx-panorama-item-header"');
            var divInnerStart = template.indexOf(">") + 1;
            template = [template.substring(0, divInnerStart), "<!-- ko if: $data.header -->", headerBinding, "<!-- /ko -->", template.substring(divInnerStart, template.length)];
            return template.join("")
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxList = function() {
            var template = DEFAULT_ITEM_TEMPLATE_GENERATORS.base(),
                keyBinding = createElementWithBindAttr("div", {text: "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", {text: "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: !!ko.unwrap($data.disabled) }"})
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxNavBar = DEFAULT_ITEM_TEMPLATE_GENERATORS.dxTabs;
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxMenu = function() {
            var template = [createElementWithBindAttr("div", defaultKoTemplateBasicBindings, false)],
                iconBinding = createElementWithBindAttr("span", {
                    attr: "{ 'class': 'dx-icon-' + $data.icon }",
                    css: "{ 'dx-icon': true }"
                }),
                iconSrcBinding = createElementWithBindAttr("img", {
                    attr: "{ src: $data.iconSrc }",
                    css: "{ 'dx-icon': true }"
                }),
                textBinding = createElementWithBindAttr("span", {
                    text: "text",
                    css: "{ 'dx-menu-item-text': true }"
                }),
                primitiveBinding = createElementWithBindAttr("span", {
                    text: "String($data)",
                    css: "{ 'dx-menu-item-text': true }"
                }),
                popout = '<span class="dx-menu-item-popout-container"><div class="dx-menu-item-popout"></div></span>';
            template.push('<div class="dx-menu-item-content">', '<!-- ko if: $data.icon -->', iconBinding, '<!-- /ko -->', '<!-- ko if: !$data.icon && $data.iconSrc -->', iconSrcBinding, '<!-- /ko -->', '<!-- ko if: $.isPlainObject($data) -->', textBinding, '<!-- /ko -->', '<!-- ko ifnot: $.isPlainObject($data) -->', primitiveBinding, '<!-- /ko -->', '<!-- ko if: $data.items -->', popout, '<!-- /ko -->', '</div>', '</div>');
            return template.join("")
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxContextMenu = DEFAULT_ITEM_TEMPLATE_GENERATORS.dxMenu;
        $.extend(ui, {
            TemplateProvider: KoTemplateProvider,
            Template: KoTemplate,
            defaultTemplate: defaultKoTemplate
        });
        ui.__internals = ui.__internals || {};
        $.extend(ui.__internals, {KoTemplate: KoTemplate})
    })(jQuery, DevExpress);
    /*! Module core, file ng.templates.js */
    (function($, DX, undefined) {
        if (!DX.support.hasNg)
            return;
        var ui = DX.ui;
        var CREATED_WITH_NG_DATA_KEY = "dxNgCreation",
            COMPILER_DATA_KEY = "dxNgCompiler",
            DEFAULT_COMPILER_DATA_KEY = "dxDefaultCompilerGetter";
        var NgTemplate = ui.Template.inherit({
                ctor: function() {
                    this.callBase.apply(this, arguments);
                    this._compiler = this._template.data(COMPILER_DATA_KEY)
                },
                render: function(container, data, index) {
                    var compiler = this._compiler,
                        result = $.isFunction(compiler) ? compiler(data, index) : compiler;
                    container.append(result);
                    return result
                },
                setCompiler: function(compilerGetter) {
                    this._compiler = compilerGetter(this._element)
                }
            });
        var NgTemplateProvider = ui.TemplateProvider.inherit({
                getTemplateClass: function(widget) {
                    if (this._createdWithNg(widget))
                        return NgTemplate;
                    return this.callBase(widget)
                },
                supportDefaultTemplate: function(widget) {
                    return this._createdWithNg(widget) ? true : this.callBase(widget)
                },
                getDefaultTemplate: function(widget) {
                    if (this._createdWithNg(widget)) {
                        var compilerGetter = widget._element().data(DEFAULT_COMPILER_DATA_KEY),
                            template = defaultNgTemplate(widget.NAME);
                        template.setCompiler(compilerGetter);
                        return template
                    }
                },
                _createdWithNg: function(widget) {
                    return !!widget._element().data(CREATED_WITH_NG_DATA_KEY)
                }
            });
        var defaultNgTemplate = function() {
                var cache = {};
                return function(widgetName) {
                        if (!DEFAULT_ITEM_TEMPLATE_GENERATORS[widgetName])
                            widgetName = "base";
                        if (!cache[widgetName])
                            cache[widgetName] = DEFAULT_ITEM_TEMPLATE_GENERATORS[widgetName]();
                        return new NgTemplate(cache[widgetName])
                    }
            }();
        var baseElements = {
                container: function() {
                    return $("<div>").attr("ng-class", "{ 'dx-state-invisible': !visible && visible != undefined, 'dx-state-disabled': !!disabled }")
                },
                html: function() {
                    return $("<div>").attr("ng-if", "html").attr("ng-bind-html", "html")
                },
                text: function() {
                    return $("<div>").attr("ng-if", "text").attr("ng-bind", "text")
                },
                primitive: function() {
                    return $("<div>").attr("ng-if", "scopeValue").attr("ng-bind-html", "'' + scopeValue")
                }
            };
        var DEFAULT_ITEM_TEMPLATE_GENERATORS = {base: function() {
                    return baseElements.container().append(baseElements.html()).append(baseElements.text()).append(baseElements.primitive())
                }};
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxList = function() {
            return DEFAULT_ITEM_TEMPLATE_GENERATORS.base().append($("<div>").attr("ng-if", "key").attr("ng-bind", "key"))
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxToolbar = function() {
            var template = DEFAULT_ITEM_TEMPLATE_GENERATORS.base();
            $.each(["button", "tabs", "dropDownMenu"], function(i, widgetName) {
                var bindingName = "dx-" + DX.inflector.dasherize(this);
                $("<div>").attr("ng-if", "widget === '" + widgetName + "'").attr(bindingName, "options").appendTo(template)
            });
            return template
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxGallery = function() {
            return baseElements.container().append(baseElements.html()).append(baseElements.text()).append($("<img>").attr("ng-if", "scopeValue").attr("ng-src", "{{'' + scopeValue}}"))
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxTabs = function() {
            var container = baseElements.container();
            var text = $("<span>").addClass("dx-tab-text").attr("ng-bind", "text").attr("ng-if", "text"),
                icon = $("<span>").attr("ng-if", "icon").addClass("dx-icon").attr("ng-class", "'dx-icon-' + icon"),
                iconSrc = $("<img>").attr("ng-if", "iconSrc").addClass("dx-icon").attr("ng-src", "{{iconSrc}}");
            return container.append(baseElements.html()).append(icon).append(iconSrc).append(text).append(baseElements.primitive())
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxMenu = function() {
            var container = baseElements.container();
            var content = $("<div>").addClass("dx-menu-item-content"),
                text = $("<span>").attr("ng-if", "text").addClass("dx-menu-item-text").attr("ng-bind", "text"),
                icon = $("<span>").attr("ng-if", "icon").addClass("dx-icon").attr("ng-class", "'dx-icon-' + icon"),
                iconSrc = $("<img>").attr("ng-if", "iconSrc").addClass("dx-icon").attr("ng-src", "{{iconSrc}}"),
                popout = $("<span>").addClass("dx-menu-item-popout-container").attr("ng-if", "items").append($("<div>").addClass("dx-menu-item-popout"));
            content.append(baseElements.html()).append(icon).append(iconSrc).append(text).append(popout).append(baseElements.primitive()).appendTo(container);
            return container
        },
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxActionSheet = function() {
            return $("<div>").attr("dx-button", "{ bindingOptions: { text: 'text', clickAction: 'clickAction', type: 'type', disabled: 'disabled' } }")
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxNavBar = DEFAULT_ITEM_TEMPLATE_GENERATORS.dxTabs;
        $.extend(ui, {
            Template: NgTemplate,
            TemplateProvider: NgTemplateProvider
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.themes.js */
    (function($, DX, undefined) {
        var DX_LINK_SELECTOR = "link[rel=dx-theme]",
            THEME_ATTR = "data-theme",
            ACTIVE_ATTR = "data-active";
        var context,
            $activeThemeLink,
            knownThemes,
            currentThemeName,
            pendingThemeName;
        var THEME_MARKER_PREFIX = "dx.";
        function readThemeMarker() {
            var element = $("<div></div>", context).addClass("dx-theme-marker").appendTo(context.documentElement),
                result;
            try {
                result = element.css("font-family");
                if (!result)
                    return null;
                result = result.replace(/["']/g, "");
                if (result.substr(0, THEME_MARKER_PREFIX.length) !== THEME_MARKER_PREFIX)
                    return null;
                return result.substr(THEME_MARKER_PREFIX.length)
            }
            finally {
                element.remove()
            }
        }
        function waitForThemeLoad(themeName, callback) {
            var timerId,
                waitStartTime;
            pendingThemeName = themeName;
            function handleLoaded() {
                pendingThemeName = null;
                callback()
            }
            if (isPendingThemeLoaded())
                handleLoaded();
            else {
                waitStartTime = $.now();
                timerId = setInterval(function() {
                    var isLoaded = isPendingThemeLoaded(),
                        isTimeout = !isLoaded && $.now() - waitStartTime > 15 * 1000;
                    if (isTimeout)
                        DX.utils.logger.warn("Theme loading timed out: " + pendingThemeName);
                    if (isLoaded || isTimeout) {
                        clearInterval(timerId);
                        handleLoaded()
                    }
                }, 10)
            }
        }
        function isPendingThemeLoaded() {
            return !pendingThemeName || readThemeMarker() === pendingThemeName
        }
        function processMarkup() {
            var $allThemeLinks = $(DX_LINK_SELECTOR, context);
            if (!$allThemeLinks.length)
                return;
            knownThemes = {};
            $activeThemeLink = $(DX.utils.createMarkupFromString("<link rel=stylesheet>"), context);
            $allThemeLinks.each(function() {
                var link = $(this, context),
                    fullThemeName = link.attr(THEME_ATTR),
                    url = link.attr("href"),
                    isActive = link.attr(ACTIVE_ATTR) === "true";
                knownThemes[fullThemeName] = {
                    url: url,
                    isActive: isActive
                }
            });
            $allThemeLinks.last().after($activeThemeLink);
            $allThemeLinks.remove()
        }
        function resolveFullThemeName(desiredThemeName) {
            var desiredThemeParts = desiredThemeName.split("."),
                result = null;
            if (knownThemes)
                $.each(knownThemes, function(knownThemeName, themeData) {
                    var knownThemeParts = knownThemeName.split(".");
                    if (knownThemeParts[0] !== desiredThemeParts[0])
                        return;
                    if (desiredThemeParts[1] && desiredThemeParts[1] !== knownThemeParts[1])
                        return;
                    if (!result || themeData.isActive)
                        result = knownThemeName;
                    if (themeData.isActive)
                        return false
                });
            return result
        }
        function initContext(newContext) {
            try {
                if (newContext !== context)
                    knownThemes = null
            }
            catch(x) {
                knownThemes = null
            }
            context = newContext
        }
        function init(options) {
            options = options || {};
            initContext(options.context || document);
            processMarkup();
            currentThemeName = undefined;
            current(options)
        }
        function current(options) {
            if (!arguments.length)
                return currentThemeName || readThemeMarker();
            options = options || {};
            if (typeof options === "string")
                options = {theme: options};
            var isAutoInit = options._autoInit,
                loadCallback = options.loadCallback,
                currentThemeData;
            currentThemeName = options.theme || currentThemeName;
            if (isAutoInit && !currentThemeName)
                currentThemeName = themeNameFromDevice(DX.devices.current());
            currentThemeName = resolveFullThemeName(currentThemeName);
            if (currentThemeName)
                currentThemeData = knownThemes[currentThemeName];
            if (currentThemeData) {
                $activeThemeLink.removeAttr("href");
                $activeThemeLink.attr("href", knownThemes[currentThemeName].url);
                if (loadCallback)
                    waitForThemeLoad(currentThemeName, loadCallback);
                else if (pendingThemeName)
                    pendingThemeName = currentThemeName
            }
            else if (isAutoInit) {
                if (loadCallback)
                    loadCallback()
            }
            else
                throw Error("Unknown theme: " + currentThemeName);
        }
        function themeNameFromDevice(device) {
            var themeName = device.platform,
                majorVersion = device.version && device.version[0];
            if (themeName === "ios" && (!majorVersion || majorVersion > 6))
                themeName += "7";
            return themeName
        }
        function getCssClasses(themeName) {
            themeName = themeName || current();
            var result = [],
                themeNameParts = themeName && themeName.split(".");
            if (themeNameParts) {
                result.push("dx-theme-" + themeNameParts[0], "dx-theme-" + themeNameParts[0] + "-typography");
                if (themeNameParts.length > 1)
                    result.push("dx-color-scheme-" + themeNameParts[1])
            }
            return result
        }
        function attachCssClasses(element, themeName) {
            $(element).addClass(getCssClasses(themeName).join(" "))
        }
        function detachCssClasses(element, themeName) {
            $(element).removeClass(getCssClasses(themeName).join(" "))
        }
        $.holdReady(true);
        init({
            _autoInit: true,
            loadCallback: function() {
                $.holdReady(false)
            }
        });
        $(function() {
            if ($(DX_LINK_SELECTOR, context).length)
                throw Error("LINK[rel=dx-theme] tags must go before DevExpress included scripts");
        });
        DX.ui.themes = {
            init: init,
            current: current,
            attachCssClasses: attachCssClasses,
            detachCssClasses: detachCssClasses
        };
        DX.ui.themes.__internals = {
            themeNameFromDevice: themeNameFromDevice,
            waitForThemeLoad: waitForThemeLoad,
            resetTheme: function() {
                $activeThemeLink.attr("href", "about:blank");
                currentThemeName = null;
                pendingThemeName = null
            }
        }
    })(jQuery, DevExpress);
    /*! Module core, file ui.events.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            eventNS = $.event,
            specialNS = eventNS.special,
            EVENT_SOURCES_REGEX = {
                mouse: /(mouse|wheel|click)/i,
                wheel: /wheel/i,
                touch: /^touch/i,
                keyboard: /^key/i,
                pointer: /pointer/i
            };
        var eventSource = function(e) {
                var result = "other";
                $.each(EVENT_SOURCES_REGEX, function(key) {
                    if (this.test(e.type)) {
                        result = key;
                        return false
                    }
                });
                return result
            };
        var isPointerEvent = function(e) {
                return eventSource(e) === "pointer"
            };
        var isMouseEvent = function(e) {
                return eventSource(e) === "mouse" || isPointerEvent(e) && e.pointerType === "mouse"
            };
        var isTouchEvent = function(e) {
                return eventSource(e) === "touch" || isPointerEvent(e) && e.pointerType === "touch"
            };
        var isKeyboardEvent = function(e) {
                return eventSource(e) === "keyboard"
            };
        var isMouseWheelEvent = function(e) {
                return EVENT_SOURCES_REGEX["wheel"].test(e.type)
            };
        var addNamespace = function(eventNames, namespace) {
                if (!namespace)
                    throw Error("Namespace is not defined");
                if (typeof eventNames === "string")
                    return addNamespace(eventNames.split(/\s+/g), namespace);
                $.each(eventNames, function(index, eventName) {
                    eventNames[index] = eventName + "." + namespace
                });
                return eventNames.join(" ")
            };
        var eventData = function(e) {
                if (isPointerEvent(e) && isTouchEvent(e)) {
                    var touch = (e.originalEvent.originalEvent || e.originalEvent).changedTouches[0];
                    return {
                            x: touch.pageX,
                            y: touch.pageY,
                            time: e.timeStamp
                        }
                }
                if (isMouseEvent(e))
                    return {
                            x: e.pageX,
                            y: e.pageY,
                            time: e.timeStamp
                        };
                if (isTouchEvent(e)) {
                    var touch = (e.changedTouches || e.originalEvent.changedTouches)[0];
                    return {
                            x: touch.pageX,
                            y: touch.pageY,
                            time: e.timeStamp
                        }
                }
            };
        var eventDelta = function(from, to) {
                return {
                        x: to.x - from.x,
                        y: to.y - from.y,
                        time: to.time - from.time || 1
                    }
            };
        var hasTouches = function(e) {
                if (isTouchEvent(e))
                    return (e.originalEvent.touches || []).length;
                return 0
            };
        var needSkipEvent = function(e) {
                var $target = $(e.target),
                    touchInInput = $target.is("input, textarea, select");
                if (isMouseWheelEvent(e) && touchInInput)
                    return false;
                if (isMouseEvent(e))
                    return touchInInput || e.which > 1;
                if (isTouchEvent(e))
                    return touchInInput && $target.is(":focus") || (e.originalEvent.changedTouches || e.originalEvent.originalEvent.changedTouches).length !== 1
            };
        var createEvent = function(sourceEvent, props) {
                var event = $.Event(sourceEvent),
                    originalEvent = event.originalEvent,
                    propNames = $.event.props.slice();
                if (isMouseEvent(sourceEvent) || isTouchEvent(sourceEvent))
                    $.merge(propNames, $.event.mouseHooks.props);
                if (isKeyboardEvent(sourceEvent))
                    $.merge(propNames, $.event.keyHooks.props);
                if (originalEvent)
                    $.each(propNames, function() {
                        event[this] = originalEvent[this]
                    });
                if (props)
                    $.extend(event, props);
                return event
            };
        var fireEvent = function(props) {
                var event = createEvent(props.originalEvent, props);
                $.event.trigger(event, null, props.target || event.target);
                return event
            };
        var handleGestureEvent = function(e, type) {
                var gestureEvent = $(e.target).data("dxGestureEvent");
                if (!gestureEvent || gestureEvent === type) {
                    $(e.target).data("dxGestureEvent", type);
                    return true
                }
                return false
            };
        var registerEvent = function(eventName, eventObject) {
                var strategy = {};
                if ("noBubble" in eventObject)
                    strategy.noBubble = eventObject.noBubble;
                if ("bindType" in eventObject)
                    strategy.bindType = eventObject.bindType;
                if ("delegateType" in eventObject)
                    strategy.delegateType = eventObject.delegateType;
                $.each(["setup", "teardown", "add", "remove", "trigger", "handle", "_default", "dispose"], function(_, methodName) {
                    if (!eventObject[methodName])
                        return;
                    strategy[methodName] = function() {
                        var args = $.makeArray(arguments);
                        args.unshift(this);
                        return eventObject[methodName].apply(eventObject, args)
                    }
                });
                specialNS[eventName] = strategy
            };
        ui.events = {
            eventSource: eventSource,
            isPointerEvent: isPointerEvent,
            isMouseEvent: isMouseEvent,
            isTouchEvent: isTouchEvent,
            isKeyboardEvent: isKeyboardEvent,
            addNamespace: addNamespace,
            hasTouches: hasTouches,
            eventData: eventData,
            eventDelta: eventDelta,
            needSkipEvent: needSkipEvent,
            createEvent: createEvent,
            fireEvent: fireEvent,
            handleGestureEvent: handleGestureEvent,
            registerEvent: registerEvent
        }
    })(jQuery, DevExpress);
    /*! Module core, file ko.events.js */
    (function($, DX, undefined) {
        if (!DX.support.hasKo)
            return;
        var ko = window.ko,
            events = DX.ui.events;
        var originalRegisterEvent = events.registerEvent;
        var registerKoEvent = function(eventName, eventObject) {
                originalRegisterEvent(eventName, eventObject);
                var koBindingEventName = events.addNamespace(eventName, eventName + "Binding");
                ko.bindingHandlers[eventName] = {update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
                        var $element = $(element),
                            unwrappedValue = ko.utils.unwrapObservable(valueAccessor()),
                            eventSource = unwrappedValue.execute ? unwrappedValue.execute : unwrappedValue;
                        $element.off(koBindingEventName).on(koBindingEventName, $.isPlainObject(unwrappedValue) ? unwrappedValue : {}, function(e) {
                            eventSource(viewModel, e)
                        })
                    }}
            };
        $.extend(events, {registerEvent: registerKoEvent})
    })(jQuery, DevExpress);
    /*! Module core, file ng.events.js */
    (function($, DX, undefined) {
        if (!DX.support.hasNg)
            return;
        var events = DX.ui.events;
        var originalRegisterEvent = events.registerEvent;
        var registerNgEvent = function(eventName, eventObject) {
                originalRegisterEvent(eventName, eventObject);
                var ngEventName = eventName.slice(0, 2) + eventName.charAt(2).toUpperCase() + eventName.slice(3);
                DX.ng.module.directive(ngEventName, ['$parse', function($parse) {
                        return function(scope, element, attr) {
                                var attrValue = $.trim(attr[ngEventName]),
                                    handler,
                                    eventOptions = {};
                                if (attrValue.charAt(0) === "{") {
                                    eventOptions = scope.$eval(attrValue);
                                    handler = $parse(eventOptions.execute)
                                }
                                else
                                    handler = $parse(attr[ngEventName]);
                                element.on(eventName, eventOptions, function(e) {
                                    scope.$apply(function() {
                                        handler(scope, {$event: e})
                                    })
                                })
                            }
                    }])
            };
        $.extend(events, {registerEvent: registerNgEvent})
    })(jQuery, DevExpress);
    /*! Module core, file ui.hierarchicalKeyDownProcessor.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            events = ui.events;
        ui.HierarchicalKeyDownProcessor = DX.Class.inherit({
            _keydown: events.addNamespace("keydown", "HierarchicalKeyDownProcessor"),
            codes: {
                "9": "tab",
                "13": "enter",
                "27": "escape",
                "33": "pageUp",
                "34": "pageDown",
                "37": "leftArrow",
                "38": "upArrow",
                "39": "rightArrow",
                "40": "downArrow",
                "32": "space",
                "70": "F",
                "65": "A"
            },
            ctor: function(options) {
                var _this = this;
                options = options || {};
                if (options.element)
                    this._element = $(options.element);
                this._handler = options.handler;
                this._context = options.context;
                this._childProcessors = [];
                if (this._element)
                    this._element.on(this._keydown, function(e) {
                        _this.process(e)
                    })
            },
            dispose: function() {
                if (this._element)
                    this._element.off(this._keydown);
                this._element = undefined;
                this._handler = undefined;
                this._context = undefined;
                this._childProcessors = undefined
            },
            attachChildProcessor: function() {
                var childProcessor = new ui.HierarchicalKeyDownProcessor;
                this._childProcessors.push(childProcessor);
                return childProcessor
            },
            reinitialize: function(childHandler, childContext) {
                this._context = childContext;
                this._handler = childHandler;
                return this
            },
            process: function(e) {
                var args = {
                        key: this.codes[e.which],
                        ctrl: e.ctrlKey,
                        shift: e.shiftKey,
                        originalEvent: e
                    };
                if (this.codes[e.which] && this._handler && this._handler.call(this._context, args))
                    $.each(this._childProcessors, function(index, childProcessor) {
                        childProcessor.process(e)
                    })
            }
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.dialog.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            utils = DX.utils;
        var DEFAULT_BUTTON = {
                text: "OK",
                clickAction: function() {
                    return true
                }
            };
        var DX_DIALOG_CLASSNAME = "dx-dialog",
            DX_DIALOG_WRAPPER_CLASSNAME = DX_DIALOG_CLASSNAME + "-wrapper",
            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 FakeDialogComponent = DX.Component.inherit({
                NAME: "dxDialog",
                ctor: function(element, options) {
                    this.callBase(options)
                },
                _defaultOptionsRules: function() {
                    return this.callBase().slice(0).concat([{
                                device: [{platform: "ios"}, {platform: "ios7"}],
                                options: {width: 276}
                            }, {
                                device: {platform: "android"},
                                options: {
                                    lWidth: "60%",
                                    pWidth: "80%"
                                }
                            }, {
                                device: {
                                    platform: "win8",
                                    phone: false
                                },
                                options: {width: function() {
                                        return $(window).width()
                                    }}
                            }, {
                                device: {
                                    platform: "win8",
                                    phone: true
                                },
                                options: {position: {
                                        my: "top center",
                                        at: "top center",
                                        of: window,
                                        offset: "0 0"
                                    }}
                            }])
                }
            });
        var dialog = function(options) {
                var that = this,
                    result;
                if (!ui.dxPopup)
                    throw new Error("DevExpress.ui.dxPopup required");
                var deferred = $.Deferred();
                var defaultOptions = (new FakeDialogComponent).option();
                options = $.extend(defaultOptions, options);
                var $holder = $(DX.overlayTargetContainer());
                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 || that.title,
                        height: "auto",
                        width: function() {
                            var isPortrait = $(window).height() > $(window).width(),
                                key = (isPortrait ? "p" : "l") + "Width",
                                widthOption = options.hasOwnProperty(key) ? options[key] : options["width"];
                            return $.isFunction(widthOption) ? widthOption() : widthOption
                        },
                        contentReadyAction: function() {
                            popupInstance.content().addClass(DX_DIALOG_CONTENT_CLASSNAME).append($message).append($buttons)
                        },
                        animation: {
                            show: {
                                type: "pop",
                                duration: 400
                            },
                            hide: {
                                type: "pop",
                                duration: 400,
                                to: {
                                    opacity: 0,
                                    scale: 0
                                },
                                from: {
                                    opacity: 1,
                                    scale: 1
                                }
                            }
                        },
                        rtlEnabled: DX.rtlEnabled
                    }).data("dxPopup");
                popupInstance._wrapper().addClass(DX_DIALOG_WRAPPER_CLASSNAME);
                if (options.position)
                    popupInstance.option("position", options.position);
                $.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._wrapper().addClass(DX_DIALOG_ROOT_CLASSNAME);
                function show() {
                    popupInstance.show();
                    utils.resetActiveElement();
                    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: Globalize.localize("Yes"),
                                clickAction: function() {
                                    return true
                                }
                            }, {
                                text: Globalize.localize("No"),
                                clickAction: function() {
                                    return false
                                }
                            }]
                    };
                dialogInstance = ui.dialog.custom(options);
                return dialogInstance.show()
            };
        var notify = function(message, type, displayTime) {
                var options = $.isPlainObject(message) ? message : {message: message};
                if (!ui.dxToast) {
                    alert(options.message);
                    return
                }
                var userHiddenAction = options.hiddenAction;
                $.extend(options, {
                    type: type,
                    displayTime: displayTime,
                    hiddenAction: function(args) {
                        args.element.remove();
                        new DX.Action(userHiddenAction, {context: args.model}).execute(arguments)
                    }
                });
                $("<div>").appendTo(DX.overlayTargetContainer()).dxToast(options).dxToast("instance").show()
            };
        $.extend(ui, {
            notify: notify,
            dialog: {
                custom: dialog,
                alert: alert,
                confirm: confirm,
                FakeDialogComponent: FakeDialogComponent
            }
        })
    })(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",
            DATA_SOURCE_LOADING_CHANGED_METHOD = "_handleDataSourceLoadingChanged";
        DX.ui.DataHelperMixin = {
            ctor: function() {
                this.disposing.add(function() {
                    this._disposeDataSource()
                })
            },
            _refreshDataSource: function() {
                this._initDataSource();
                this._loadDataSource()
            },
            _initDataSource: function() {
                var dataSourceOptions = this.option("dataSource"),
                    widgetDataSourceOptions,
                    dataSourceType;
                this._disposeDataSource();
                if (dataSourceOptions) {
                    if (dataSourceOptions instanceof data.DataSource) {
                        this._isSharedDataSource = true;
                        this._dataSource = dataSourceOptions
                    }
                    else {
                        widgetDataSourceOptions = DATA_SOURCE_OPTIONS_METHOD in this ? this[DATA_SOURCE_OPTIONS_METHOD]() : {};
                        dataSourceType = this._dataSourceType ? this._dataSourceType() : data.DataSource;
                        this._dataSource = new dataSourceType($.extend(true, {}, widgetDataSourceOptions, data.utils.normalizeDataSourceOptions(dataSourceOptions)))
                    }
                    this._addDataSourceHandlers()
                }
            },
            _addDataSourceHandlers: function() {
                if (DATA_SOURCE_CHANGED_METHOD in this)
                    this._addDataSourceChangeHandler();
                if (DATA_SOURCE_LOAD_ERROR_METHOD in this)
                    this._addDataSourceLoadErrorHandler();
                if (DATA_SOURCE_LOADING_CHANGED_METHOD in this)
                    this._addDataSourceLoadingChangedHandler()
            },
            _addDataSourceChangeHandler: function() {
                var that = this,
                    dataSource = this._dataSource;
                this._dataSourceChangedHandler = function() {
                    that[DATA_SOURCE_CHANGED_METHOD](dataSource.items())
                };
                dataSource.changed.add(this._dataSourceChangedHandler)
            },
            _addDataSourceLoadErrorHandler: function() {
                this._dataSourceLoadErrorHandler = $.proxy(this[DATA_SOURCE_LOAD_ERROR_METHOD], this);
                this._dataSource.loadError.add(this._dataSourceLoadErrorHandler)
            },
            _addDataSourceLoadingChangedHandler: function() {
                this._dataSourceLoadingChangedHandler = $.proxy(this[DATA_SOURCE_LOADING_CHANGED_METHOD], this);
                this._dataSource.loadingChanged.add(this._dataSourceLoadingChangedHandler)
            },
            _loadDataSource: function() {
                if (this._dataSource) {
                    var dataSource = this._dataSource;
                    if (dataSource.isLoaded())
                        this._dataSourceChangedHandler();
                    else
                        dataSource.load()
                }
            },
            _loadSingle: function(key, value) {
                key = key === "this" ? this._dataSource.key() || "this" : key;
                return this._dataSource.loadSingle(key, value)
            },
            _disposeDataSource: function() {
                if (this._dataSource) {
                    if (this._isSharedDataSource) {
                        delete this._isSharedDataSource;
                        this._dataSource.changed.remove(this._dataSourceChangedHandler);
                        this._dataSource.loadError.remove(this._dataSourceLoadErrorHandler);
                        this._dataSource.loadingChanged.remove(this._dataSourceLoadingChangedHandler)
                    }
                    else
                        this._dataSource.dispose();
                    delete this._dataSource;
                    delete this._dataSourceChangedHandler;
                    delete this._dataSourceLoadErrorHandler;
                    delete this._dataSourceLoadingChangedHandler
                }
            }
        }
    })(jQuery, DevExpress);
    /*! Module core, file ui.events.mspointer.js */
    (function($, DX, undefined) {
        var POINTER_TYPE_MAP = {
                2: "touch",
                3: "pen",
                4: "mouse"
            };
        var pointerEventHook = {
                filter: function(event, originalEvent) {
                    var pointerType = originalEvent.pointerType;
                    if ($.isNumeric(pointerType))
                        event.pointerType = POINTER_TYPE_MAP[pointerType];
                    return event
                },
                props: $.event.mouseHooks.props.concat(["pointerId", "originalTarget", "namespace", "width", "height", "pressure", "result", "tiltX", "charCode", "tiltY", "detail", "isPrimary", "prevValue"])
            };
        $.each(["MSPointerDown", "MSPointerMove", "MSPointerUp", "MSPointerCancel", "MSPointerOver", "MSPointerOut", "MSPointerEnter", "MSPointerLeave", "pointerdown", "pointermove", "pointerup", "pointercancel", "pointerover", "pointerout", "pointerenter", "pointerleave"], function() {
            $.event.fixHooks[this] = pointerEventHook
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.events.touch.js */
    (function($, DX, undefined) {
        var touchEventHook = {
                filter: function(event, originalEvent) {
                    if (originalEvent.changedTouches.length)
                        $.each(["pageX", "pageY", "screenX", "screenY", "clientX", "clientY"], function() {
                            event[this] = originalEvent.changedTouches[0][this]
                        });
                    return event
                },
                props: $.event.mouseHooks.props.concat(["touches", "changedTouches", "targetTouches", "detail", "result", "namespace", "originalTarget", "charCode", "prevValue"])
            };
        $.each(["touchstart", "touchmove", "touchend", "touchcancel"], function() {
            $.event.fixHooks[this] = touchEventHook
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.events.pointer.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            support = DX.support,
            device = $.proxy(DX.devices.real, DX.devices),
            events = ui.events;
        var POINTER_EVENTS_NAMESPACE = "dxPointerEvents",
            MouseStrategyEventMap = {
                dxpointerdown: "mousedown",
                dxpointermove: "mousemove",
                dxpointerup: "mouseup",
                dxpointercancel: ""
            },
            TouchStrategyEventMap = {
                dxpointerdown: "touchstart",
                dxpointermove: "touchmove",
                dxpointerup: "touchend",
                dxpointercancel: "touchcancel"
            },
            PointerStrategyEventMap = {
                dxpointerdown: "pointerdown",
                dxpointermove: "pointermove",
                dxpointerup: "pointerup",
                dxpointercancel: "pointercancel"
            },
            MouseAndTouchStrategyEventMap = {
                dxpointerdown: "touchstart mousedown",
                dxpointermove: "touchmove mousemove",
                dxpointerup: "touchend mouseup",
                dxpointercancel: "touchcancel"
            };
        var eventMap = function() {
                if (support.touch && !(device().tablet || device().phone))
                    return MouseAndTouchStrategyEventMap;
                if (support.touch)
                    return TouchStrategyEventMap;
                return MouseStrategyEventMap
            }();
        var skipTouchWithSameIdentifier = function(pointerEvent) {
                return device().platform === "ios" && (pointerEvent === "dxpointerdown" || pointerEvent === "dxpointerup")
            };
        var SingleEventStrategy = DX.Class.inherit({
                ctor: function(eventName, originalEvents) {
                    this._eventName = eventName;
                    this._eventNamespace = [POINTER_EVENTS_NAMESPACE, ".", this._eventName].join("");
                    this._originalEvents = originalEvents;
                    this._pointerId = 0;
                    this._handlerCount = 0
                },
                _handler: function(e) {
                    if (this._eventName === "dxpointerdown")
                        $(e.target).data("dxGestureEvent", null);
                    if (events.isTouchEvent(e) && skipTouchWithSameIdentifier(this._eventName)) {
                        var touch = e.changedTouches[0];
                        if (this._pointerId === touch.identifier && this._pointerId !== 0)
                            return;
                        this._pointerId = touch.identifier
                    }
                    return events.fireEvent({
                            type: this._eventName,
                            pointerType: events.eventSource(e),
                            originalEvent: e
                        })
                },
                setup: function() {
                    if (this._handlerCount > 0)
                        return;
                    $(document).on(events.addNamespace(this._originalEvents, this._eventNamespace), $.proxy(this._handler, this))
                },
                add: function() {
                    this._handlerCount++
                },
                remove: function() {
                    this._handlerCount--
                },
                teardown: function() {
                    if (this._handlerCount)
                        return;
                    $(document).off("." + this._eventNamespace)
                },
                dispose: function() {
                    $(document).off("." + this._eventNamespace)
                }
            });
        var MultiEventStrategy = SingleEventStrategy.inherit({
                EVENT_LOCK_TIMEOUT: 100,
                _handler: function(e) {
                    if (events.isTouchEvent(e))
                        this._skipNextEvents = true;
                    if (events.isMouseEvent(e) && this._mouseLocked)
                        return;
                    if (events.isMouseEvent(e) && this._skipNextEvents) {
                        this._skipNextEvents = false;
                        this._mouseLocked = true;
                        clearTimeout(this._unlockMouseTimer);
                        this._unlockMouseTimer = setTimeout($.proxy(function() {
                            this._mouseLocked = false
                        }, this), this.EVENT_LOCK_TIMEOUT);
                        return
                    }
                    return this.callBase(e)
                },
                dispose: function() {
                    this.callBase();
                    this._skipNextEvents = false;
                    this._mouseLocked = false;
                    clearTimeout(this._unlockMouseTimer)
                }
            });
        var getStrategy = function() {
                return eventMap === MouseAndTouchStrategyEventMap ? MultiEventStrategy : SingleEventStrategy
            };
        $.each(eventMap, function(pointerEvent, originalEvents) {
            var Strategy = getStrategy();
            events.registerEvent(pointerEvent, new Strategy(pointerEvent, originalEvents))
        });
        DX.ui.events.__internals = DX.ui.events.__internals || {};
        $.extend(DX.ui.events.__internals, {
            SingleEventStrategy: SingleEventStrategy,
            MultiEventStrategy: MultiEventStrategy,
            MouseStrategyEventMap: MouseStrategyEventMap,
            TouchStrategyEventMap: TouchStrategyEventMap,
            PointerStrategyEventMap: PointerStrategyEventMap,
            MouseAndTouchStrategyEventMap: MouseAndTouchStrategyEventMap,
            eventMap: eventMap
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.events.click.js */
    (function($, DX, wnd, undefined) {
        var ua = navigator.userAgent,
            screen = wnd.screen,
            ui = DX.ui,
            utils = DX.utils,
            events = ui.events,
            support = DX.support,
            device = $.proxy(DX.devices.real, DX.devices),
            EVENTS_NAME_SPACE = "dxSpecialEvents",
            CLICK_NAME_SPACE = "dxClick" + EVENTS_NAME_SPACE,
            CLICK_EVENT_NAME = "dxclick",
            SCROLLABLE_PARENT_DATA_KEY = "dxClickScrollableParent",
            SCROLLABLE_PARENT_SCROLL_OFFSET_DATA_KEY = "dxClickScrollableParentOffset",
            preferNativeClick = function() {
                var iPhone4SAndElder = device().deviceType === "phone" && screen.height <= 480,
                    iPad2AndElder = device().deviceType === "tablet" && wnd.devicePixelRatio < 2,
                    IOS7AndNewer = device().platform === "ios" && device().version[0] > 6;
                return IOS7AndNewer && (iPhone4SAndElder || iPad2AndElder)
            }(),
            useNativeClick = function() {
                if (!support.touch)
                    return true;
                var chromeInfo = ua.match(/Chrome\/([0-9]+)/) || [],
                    chrome = !!chromeInfo[0],
                    chromeVersion = ~~chromeInfo[1],
                    android = device().platform === "android";
                if (chrome)
                    if (android) {
                        if ($("meta[name=viewport][content*='width=device-width']").length)
                            return false;
                        if (chromeVersion > 31 && wnd.innerWidth <= screen.width)
                            return true;
                        if ($("meta[name=viewport][content*='user-scalable=no']").length)
                            return true
                    }
                    else
                        return true;
                return false
            }();
        var SimulatedStrategy = DX.Class.inherit({
                TOUCH_BOUNDARY: 10,
                ctor: function() {
                    this._startX = 0;
                    this._startY = 0;
                    this._handlerCount = 0;
                    this._target = null
                },
                _touchWasMoved: function(e) {
                    var boundary = this.TOUCH_BOUNDARY;
                    return Math.abs(e.pageX - this._startX) > boundary || Math.abs(e.pageY - this._startY) > boundary
                },
                _getClosestScrollable: function($element) {
                    var $scrollParent = $();
                    if ($element.data(SCROLLABLE_PARENT_DATA_KEY))
                        $scrollParent = $element.data(SCROLLABLE_PARENT_DATA_KEY);
                    else {
                        var $current = $element;
                        while ($current.length) {
                            if ($current[0].scrollHeight - $current[0].offsetHeight > 1) {
                                $scrollParent = $current;
                                $element.data(SCROLLABLE_PARENT_DATA_KEY, $scrollParent);
                                break
                            }
                            $current = $current.parent()
                        }
                    }
                    return $scrollParent
                },
                _saveClosestScrollableOffset: function($element) {
                    var $scrollable = this._getClosestScrollable($element);
                    if ($scrollable.length)
                        $element.data(SCROLLABLE_PARENT_SCROLL_OFFSET_DATA_KEY, $scrollable.scrollTop())
                },
                _closestScrollableWasMoved: function($element) {
                    var $scrollable = $element.data(SCROLLABLE_PARENT_DATA_KEY);
                    return $scrollable && $scrollable.scrollTop() !== $element.data(SCROLLABLE_PARENT_SCROLL_OFFSET_DATA_KEY)
                },
                _hasClosestScrollable: function($element) {
                    var $scrollable = this._getClosestScrollable($element);
                    if (!$scrollable.length)
                        return false;
                    if ($scrollable.is("body"))
                        return false;
                    if ($scrollable === window)
                        return false;
                    if ($scrollable.css("overflow") === "hidden")
                        return false;
                    return true
                },
                _handleStart: function(e) {
                    this._reset();
                    if (events.isMouseEvent(e) && e.which !== 1)
                        return;
                    this._saveClosestScrollableOffset($(e.target));
                    this._target = e.target;
                    this._startX = e.pageX;
                    this._startY = e.pageY
                },
                _handleEnd: function(e) {
                    var $target = $(e.target);
                    if (!$target.is(this._target) || this._touchWasMoved(e))
                        return;
                    if (this._nativeClickShouldBeUsed($target) || this._closestScrollableWasMoved($target))
                        return;
                    var targetIsInput = $target.is("input, textarea");
                    if (!targetIsInput && !e.dxPreventBlur)
                        utils.resetActiveElement();
                    this._fireClickEvent(e)
                },
                _handleCancel: function(e) {
                    this._reset()
                },
                _reset: function() {
                    this._target = null
                },
                _handleClick: function(e) {
                    var $target = $(e.target);
                    if ($target.is(this._target)) {
                        if (this._nativeClickShouldBeUsed($target))
                            this._fireClickEvent(e)
                    }
                    else if ($target.is("input, textarea"))
                        utils.resetActiveElement()
                },
                _nativeClickShouldBeUsed: function($target) {
                    return preferNativeClick && this._hasClosestScrollable($target)
                },
                _fireClickEvent: function(e) {
                    if (events.handleGestureEvent(e, CLICK_EVENT_NAME))
                        events.fireEvent({
                            type: CLICK_EVENT_NAME,
                            originalEvent: e
                        })
                },
                _makeElementClickable: function($element) {
                    if (!$element.attr("onclick"))
                        $element.attr("onclick", "void(0)")
                },
                setup: function(element) {
                    var $element = $(element);
                    this._makeElementClickable($element);
                    if (this._handlerCount > 0)
                        return;
                    var $doc = $(document).on(events.addNamespace("dxpointerdown", CLICK_NAME_SPACE), $.proxy(this._handleStart, this)).on(events.addNamespace("dxpointerup", CLICK_NAME_SPACE), $.proxy(this._handleEnd, this)).on(events.addNamespace("dxpointercancel", CLICK_NAME_SPACE), $.proxy(this._handleCancel, this)).on(events.addNamespace("click", CLICK_NAME_SPACE), $.proxy(this._handleClick, this))
                },
                add: function() {
                    this._handlerCount++
                },
                remove: function() {
                    this._handlerCount--
                },
                teardown: function(element) {
                    if (this._handlerCount)
                        return;
                    $(element).off("." + CLICK_NAME_SPACE);
                    this.dispose()
                },
                dispose: function() {
                    $(document).off("." + CLICK_NAME_SPACE)
                }
            });
        var NativeStrategy = DX.Class.inherit({
                bindType: "click",
                delegateType: "click",
                handle: function(element, event) {
                    event.type = "dxclick";
                    if (events.handleGestureEvent(event, CLICK_EVENT_NAME))
                        return event.handleObj.handler.call(element, event)
                }
            });
        events.registerEvent(CLICK_EVENT_NAME, new(useNativeClick ? NativeStrategy : SimulatedStrategy));
        DX.ui.events.__internals = DX.ui.events.__internals || {};
        $.extend(DX.ui.events.__internals, {
            NativeClickStrategy: NativeStrategy,
            SimulatedClickStrategy: SimulatedStrategy,
            preferNativeClickAccessor: function(value) {
                if (!arguments.length)
                    return preferNativeClick;
                preferNativeClick = value
            }
        })
    })(jQuery, DevExpress, window);
    /*! Module core, file ui.events.hold.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            events = ui.events,
            jqSpecialEvent = $.event.special,
            EVENTS_NAME_SPACE = "dxSpecialEvents",
            HOLD_NAME_SPACE = "dxHold",
            HOLD_EVENT_NAME = "dxhold",
            HOLD_TIMER_DATA_KEY = EVENTS_NAME_SPACE + "HoldTimer";
        var Hold = DX.Class.inherit({
                HOLD_TIMEOUT: 750,
                TOUCH_BOUNDARY: 5,
                _startX: 0,
                _startY: 0,
                _touchWasMoved: function(e) {
                    var boundary = this.TOUCH_BOUNDARY;
                    return Math.abs(e.pageX - this._startX) > boundary || Math.abs(e.pageY - this._startY) > boundary
                },
                setup: function(element, data) {
                    var $target,
                        holdInited = false;
                    var handleStart = function(e) {
                            if (holdInited)
                                return;
                            $target = $(e.target);
                            holdInited = true;
                            if ($target.data(HOLD_TIMER_DATA_KEY))
                                return;
                            this._startX = e.pageX;
                            this._startY = e.pageY;
                            var holdTimeout = data && "timeout" in data ? data.timeout : this.HOLD_TIMEOUT;
                            var holdTimer = setTimeout(function() {
                                    $target.removeData(HOLD_TIMER_DATA_KEY);
                                    if (events.handleGestureEvent(e, HOLD_EVENT_NAME))
                                        events.fireEvent({
                                            type: HOLD_EVENT_NAME,
                                            originalEvent: e
                                        })
                                }, holdTimeout);
                            $target.data(HOLD_TIMER_DATA_KEY, holdTimer)
                        };
                    var handleMove = function(e) {
                            if (!this._touchWasMoved(e))
                                return;
                            handleEnd()
                        };
                    var handleEnd = function() {
                            if ($target) {
                                clearTimeout($target.data(HOLD_TIMER_DATA_KEY));
                                $target.removeData(HOLD_TIMER_DATA_KEY);
                                $target = null;
                                holdInited = false
                            }
                        };
                    $(element).on(events.addNamespace("dxpointerdown", HOLD_NAME_SPACE), $.proxy(handleStart, this)).on(events.addNamespace("dxpointermove", HOLD_NAME_SPACE), $.proxy(handleMove, this)).on(events.addNamespace("dxpointerup", HOLD_NAME_SPACE), $.proxy(handleEnd, this))
                },
                teardown: function(element) {
                    element = $(element);
                    clearTimeout(element.data(HOLD_TIMER_DATA_KEY));
                    element.removeData(HOLD_TIMER_DATA_KEY).off("." + HOLD_NAME_SPACE)
                }
            });
        events.registerEvent(HOLD_EVENT_NAME, new Hold)
    })(jQuery, DevExpress);
    /*! Module core, file ui.events.hover.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            events = ui.events;
        var HOVER_EVENTS_NAMESPACE = "dxSpecialEvents",
            HOVER_START = "dxhoverstart",
            HOVER_END = "dxhoverend",
            MOUSE_ENTER = "mouseenter",
            MOUSE_LEAVE = "mouseleave",
            TOUCH_START = "dxpointerdown";
        var HoverStart = DX.Class.inherit({
                ctor: function() {
                    this._wasTouch = false;
                    this._selector = undefined
                },
                setup: function(element, data) {
                    var $element = $(element);
                    this._selector = data ? data.selector : undefined;
                    if (!!$element.data("dxHoverStart"))
                        return;
                    $element.data("dxHoverStart", true).on(events.addNamespace(MOUSE_ENTER, HOVER_EVENTS_NAMESPACE), this._selector, $.proxy(this._handleEnter, this)).on(events.addNamespace(TOUCH_START, HOVER_EVENTS_NAMESPACE), $.proxy(this._handleTouchStart, this))
                },
                _handleEnter: function(e) {
                    if (!this._wasTouch)
                        events.fireEvent({
                            type: HOVER_START,
                            originalEvent: e
                        })
                },
                _handleTouchStart: function(e) {
                    this._wasTouch = events.isTouchEvent(e)
                },
                teardown: function(element) {
                    $(element).data("dxHoverStart", false).off(events.addNamespace(MOUSE_ENTER, HOVER_EVENTS_NAMESPACE), this._selector).off(events.addNamespace(TOUCH_START, HOVER_EVENTS_NAMESPACE))
                }
            });
        var HoverEnd = DX.Class.inherit({
                ctor: function() {
                    this._wasTouch = false;
                    this._selector = undefined
                },
                setup: function(element, data) {
                    var $element = $(element);
                    this._selector = data ? data.selector : undefined;
                    if (!!$element.data("dxHoverEnd"))
                        return;
                    $element.data("dxHoverEnd", true).on(events.addNamespace(MOUSE_LEAVE, HOVER_EVENTS_NAMESPACE), this._selector, $.proxy(this._handleLeave, this)).on(events.addNamespace(TOUCH_START, HOVER_EVENTS_NAMESPACE), $.proxy(this._handleTouchStart, this))
                },
                _handleLeave: function(e) {
                    if (!this._wasTouch)
                        events.fireEvent({
                            type: HOVER_END,
                            originalEvent: e
                        })
                },
                _handleTouchStart: function(e) {
                    this._wasTouch = events.isTouchEvent(e)
                },
                teardown: function(element) {
                    $(element).data("dxHoverEnd", false).off(events.addNamespace(MOUSE_LEAVE, HOVER_EVENTS_NAMESPACE), this._selector).off(events.addNamespace(TOUCH_START, HOVER_EVENTS_NAMESPACE))
                }
            });
        events.registerEvent(HOVER_START, new HoverStart);
        events.registerEvent(HOVER_END, new HoverEnd)
    })(jQuery, DevExpress);
    /*! Module core, file ui.events.wheel.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            events = ui.events;
        var EVENT_NAME = "dxmousewheel",
            EVENT_NAMESPACE = "dxWheel";
        var WHEEL_DISTANCE = 10;
        $.event.fixHooks["wheel"] = $.event.mouseHooks;
        var wheelEvent = document.onmousewheel !== undefined ? "mousewheel" : "wheel";
        var wheel = {
                setup: function(element, data) {
                    var $element = $(element);
                    $element.on(events.addNamespace(wheelEvent, EVENT_NAMESPACE), $.proxy(wheel._handleWheel, wheel))
                },
                teardown: function(element) {
                    var $element = $(element);
                    $element.off("." + EVENT_NAMESPACE)
                },
                _handleWheel: function(e) {
                    $(e.target).data("dxGestureEvent", null);
                    var delta = this._getWheelDelta(e.originalEvent);
                    events.fireEvent({
                        type: EVENT_NAME,
                        originalEvent: e,
                        delta: delta
                    });
                    e.stopPropagation()
                },
                _getWheelDelta: function(event) {
                    return event.wheelDelta / 60 || -event.deltaY
                }
            };
        events.registerEvent(EVENT_NAME, wheel)
    })(jQuery, DevExpress);
    /*! Module core, file ui.gestureEmitter.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            events = ui.events;
        var GestureEmitter = DX.Class.inherit({
                ctor: function(element) {
                    this._$element = $(element);
                    this._cancelCallback = $.Callbacks()
                },
                getElement: function() {
                    return this._$element
                },
                getDirection: function() {
                    return this.direction
                },
                validate: function(e) {
                    return e.type !== "dxmousewheel"
                },
                configurate: function(data) {
                    $.extend(this, data)
                },
                addCancelCallback: function(callback) {
                    this._cancelCallback.add(callback)
                },
                removeCancelCallback: function() {
                    this._cancelCallback.empty()
                },
                init: $.noop,
                start: $.noop,
                move: $.noop,
                end: $.noop,
                cancel: $.noop,
                wheel: $.noop,
                _fireEvent: function(eventName, event, params) {
                    var eventData = {
                            type: eventName,
                            originalEvent: event,
                            target: this.getElement().get(0)
                        };
                    event = events.fireEvent($.extend(eventData, params));
                    if (event.cancel)
                        this._cancel(event);
                    return event
                },
                _cancel: function(e) {
                    this._cancelCallback.fire()
                }
            });
        var gestureEmitters = [];
        $.extend(ui, {
            GestureEmitter: GestureEmitter,
            gestureEmitters: gestureEmitters
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.scrollEmitter.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            events = ui.events;
        var SCROLL_INIT_EVENT = "dxscrollinit",
            SCROLL_START_EVENT = "dxscrollstart",
            SCROLL_MOVE_EVENT = "dxscroll",
            SCROLL_END_EVENT = "dxscrollend",
            SCROLL_STOP_EVENT = "dxscrollstop",
            SCROLL_CANCEL_EVENT = "dxscrollcancel",
            SCROLL_WHEEL_EVENT = "dxscrollwheel",
            INERTIA_TIMEOUT = 100,
            VELOCITY_CALC_TIMEOUT = 200,
            FRAME_DURATION = Math.round(1000 / 60);
        var ScrollEmitter = ui.GestureEmitter.inherit({
                ctor: function(element) {
                    this.callBase(element);
                    this.direction = "vertical"
                },
                init: function(e) {
                    this._savedEventData = this._prevEventData = events.eventData(e);
                    this._fireEvent(SCROLL_INIT_EVENT, e)
                },
                start: function(e) {
                    this._fireEvent(SCROLL_START_EVENT, e, {delta: events.eventDelta(this._prevEventData, events.eventData(e))})
                },
                move: function(e) {
                    var currentEventData = events.eventData(e);
                    this._fireEvent(SCROLL_MOVE_EVENT, e, {delta: events.eventDelta(this._prevEventData, currentEventData)});
                    var eventDelta = events.eventDelta(this._savedEventData, currentEventData);
                    if (eventDelta.time > VELOCITY_CALC_TIMEOUT)
                        this._savedEventData = this._prevEventData;
                    this._prevEventData = currentEventData
                },
                end: function(e) {
                    var endEventDelta = events.eventDelta(this._prevEventData, events.eventData(e));
                    var velocity = {
                            x: 0,
                            y: 0
                        };
                    if (endEventDelta.time < INERTIA_TIMEOUT) {
                        var deltaEventData = events.eventDelta(this._savedEventData, this._prevEventData);
                        velocity = {
                            x: deltaEventData.x * FRAME_DURATION / deltaEventData.time,
                            y: deltaEventData.y * FRAME_DURATION / deltaEventData.time
                        }
                    }
                    this._fireEvent(SCROLL_END_EVENT, e, {velocity: velocity})
                },
                stop: function(e) {
                    this._fireEvent(SCROLL_STOP_EVENT, e)
                },
                cancel: function(e) {
                    this._fireEvent(SCROLL_CANCEL_EVENT, e)
                },
                wheel: function(e) {
                    this._fireEvent(SCROLL_WHEEL_EVENT, e, {delta: e.delta})
                }
            });
        ui.gestureEmitters.push({
            emitter: ScrollEmitter,
            events: [SCROLL_INIT_EVENT, SCROLL_START_EVENT, SCROLL_MOVE_EVENT, SCROLL_END_EVENT, SCROLL_STOP_EVENT, SCROLL_CANCEL_EVENT, SCROLL_WHEEL_EVENT]
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.swipeEmitter.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            utils = DX.utils,
            events = ui.events,
            SWIPE_START_EVENT = "dxswipestart",
            SWIPE_EVENT = "dxswipe",
            SWIPE_END_EVENT = "dxswipeend";
        var HorizontalStrategy = {
                defaultItemSizeFunc: function() {
                    return this.getElement().width()
                },
                getBounds: function() {
                    return [this._maxLeftOffset, this._maxRightOffset]
                },
                calcOffsetRatio: function(e) {
                    var endEventData = events.eventData(e);
                    return (endEventData.x - (this._startEventData && this._startEventData.x || 0)) / this._itemSizeFunc().call(this, e)
                },
                isFastSwipe: function(e) {
                    var endEventData = events.eventData(e);
                    return this.FAST_SWIPE_SPEED_LIMIT * Math.abs(endEventData.x - this._tickData.x) >= endEventData.time - this._tickData.time
                }
            };
        var VerticalStrategy = {
                defaultItemSizeFunc: function() {
                    return this.getElement().height()
                },
                getBounds: function() {
                    return [this._maxTopOffset, this._maxBottomOffset]
                },
                calcOffsetRatio: function(e) {
                    var endEventData = events.eventData(e);
                    return (endEventData.y - (this._startEventData && this._startEventData.y || 0)) / this._itemSizeFunc().call(this, e)
                },
                isFastSwipe: function(e) {
                    var endEventData = events.eventData(e);
                    return this.FAST_SWIPE_SPEED_LIMIT * Math.abs(endEventData.y - this._tickData.y) >= endEventData.time - this._tickData.time
                }
            };
        var STRATEGIES = {
                horizontal: HorizontalStrategy,
                vertical: VerticalStrategy
            };
        var SwipeEmitter = ui.GestureEmitter.inherit({
                TICK_INTERVAL: 300,
                FAST_SWIPE_SPEED_LIMIT: 5,
                ctor: function(element) {
                    this.callBase(element);
                    this.direction = "horizontal";
                    this.elastic = true
                },
                _getStrategy: function() {
                    return STRATEGIES[this.direction]
                },
                _defaultItemSizeFunc: function() {
                    return this._getStrategy().defaultItemSizeFunc.call(this)
                },
                _itemSizeFunc: function() {
                    return this.itemSizeFunc || this._defaultItemSizeFunc
                },
                init: function(e) {
                    this._startEventData = events.eventData(e);
                    this._tickData = {time: 0}
                },
                start: function(e) {
                    e = this._fireEvent(SWIPE_START_EVENT, e);
                    if (!e.cancel) {
                        this._maxLeftOffset = e.maxLeftOffset;
                        this._maxRightOffset = e.maxRightOffset;
                        this._maxTopOffset = e.maxTopOffset;
                        this._maxBottomOffset = e.maxBottomOffset
                    }
                },
                move: function(e) {
                    var strategy = this._getStrategy(),
                        moveEventData = events.eventData(e),
                        offset = strategy.calcOffsetRatio.call(this, e);
                    offset = this._fitOffset(offset, this.elastic);
                    if (moveEventData.time - this._tickData.time > this.TICK_INTERVAL)
                        this._tickData = moveEventData;
                    this._fireEvent(SWIPE_EVENT, e, {offset: offset});
                    e.preventDefault()
                },
                end: function(e) {
                    var strategy = this._getStrategy(),
                        offsetRatio = strategy.calcOffsetRatio.call(this, e),
                        isFast = strategy.isFastSwipe.call(this, e),
                        startOffset = offsetRatio,
                        targetOffset = this._calcTargetOffset(offsetRatio, isFast);
                    startOffset = this._fitOffset(startOffset, this.elastic);
                    targetOffset = this._fitOffset(targetOffset, false);
                    this._fireEvent(SWIPE_END_EVENT, e, {
                        offset: startOffset,
                        targetOffset: targetOffset
                    })
                },
                _fitOffset: function(offset, elastic) {
                    var strategy = this._getStrategy(),
                        bounds = strategy.getBounds.call(this);
                    if (offset < -bounds[0])
                        return elastic ? (-2 * bounds[0] + offset) / 3 : -bounds[0];
                    if (offset > bounds[1])
                        return elastic ? (2 * bounds[1] + offset) / 3 : bounds[1];
                    return offset
                },
                _calcTargetOffset: function(offsetRatio, isFast) {
                    var result;
                    if (isFast) {
                        result = Math.ceil(Math.abs(offsetRatio));
                        if (offsetRatio < 0)
                            result = -result
                    }
                    else
                        result = Math.round(offsetRatio);
                    return result
                }
            });
        ui.gestureEmitters.push({
            emitter: SwipeEmitter,
            events: [SWIPE_START_EVENT, SWIPE_EVENT, SWIPE_END_EVENT]
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.dragEmitter.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            utils = DX.utils,
            events = ui.events,
            wrapToArray = utils.wrapToArray;
        var DRAG_START_EVENT = "dxdragstart",
            DRAG_EVENT = "dxdrag",
            DRAG_END_EVENT = "dxdragend",
            DRAG_ENTER_EVENT = "dxdragenter",
            DRAG_LEAVE_EVENT = "dxdragleave",
            DROP_EVENT = "dxdrop";
        var knownDropTargets = [],
            knownDropTargetConfigs = [];
        var dropTargetRegistration = {
                setup: function(element, data) {
                    var knownDropTarget = $.inArray(element, knownDropTargets) !== -1;
                    if (!knownDropTarget) {
                        knownDropTargets.push(element);
                        knownDropTargetConfigs.push(data || {})
                    }
                },
                teardown: function(element, data) {
                    var elementEvents = $._data(element, "events"),
                        handlersCount = 0;
                    $.each([DRAG_ENTER_EVENT, DRAG_LEAVE_EVENT, DROP_EVENT], function(_, eventName) {
                        var eventHandlers = elementEvents[eventName];
                        if (eventHandlers)
                            handlersCount += eventHandlers.length
                    });
                    if (!handlersCount) {
                        var index = $.inArray(element, knownDropTargets);
                        knownDropTargets.splice(index, 1);
                        knownDropTargetConfigs.splice(index, 1)
                    }
                }
            };
        events.registerEvent(DRAG_ENTER_EVENT, dropTargetRegistration);
        events.registerEvent(DRAG_LEAVE_EVENT, dropTargetRegistration);
        events.registerEvent(DROP_EVENT, dropTargetRegistration);
        var getItemConfig = function($element) {
                var dropTargetIndex = $.inArray($element.get(0), knownDropTargets);
                return knownDropTargetConfigs[dropTargetIndex]
            };
        var getItemPosition = function($element) {
                var dropTargetConfig = getItemConfig($element);
                if (dropTargetConfig.itemPositionFunc)
                    return dropTargetConfig.itemPositionFunc();
                else
                    return $element.offset()
            };
        var getItemSize = function($element) {
                var dropTargetConfig = getItemConfig($element);
                if (dropTargetConfig.itemSizeFunc)
                    return dropTargetConfig.itemSizeFunc();
                else
                    return {
                            width: $element.width(),
                            height: $element.height()
                        }
            };
        var DragEmitter = ui.GestureEmitter.inherit({
                ctor: function(element) {
                    this.callBase(element);
                    this.direction = "both"
                },
                init: function(e) {
                    var eventData = events.eventData(e);
                    this._startEventData = eventData
                },
                start: function(e) {
                    e = this._fireEvent(DRAG_START_EVENT, e);
                    this._maxLeftOffset = e.maxLeftOffset;
                    this._maxRightOffset = e.maxRightOffset;
                    this._maxTopOffset = e.maxTopOffset;
                    this._maxBottomOffset = e.maxBottomOffset;
                    var dropTargets = wrapToArray(e.targetElements || knownDropTargets);
                    this._$dropTargetElements = $.map(dropTargets, function(element) {
                        return $(element)
                    })
                },
                move: function(e) {
                    var eventData = events.eventData(e),
                        dragOffset = this._calculateOffset(eventData);
                    this._fireEvent(DRAG_EVENT, e, {offset: dragOffset});
                    this._processDropTargets(e, dragOffset);
                    e.preventDefault()
                },
                _calculateOffset: function(eventData) {
                    return {
                            x: this._calculateXOffset(eventData),
                            y: this._calculateYOffset(eventData)
                        }
                },
                _calculateXOffset: function(eventData) {
                    if (this.direction !== "vertical") {
                        var offset = eventData.x - this._startEventData.x;
                        return this._fitOffset(offset, this._maxLeftOffset, this._maxRightOffset)
                    }
                    return 0
                },
                _calculateYOffset: function(eventData) {
                    if (this.direction !== "horizontal") {
                        var offset = eventData.y - this._startEventData.y;
                        return this._fitOffset(offset, this._maxTopOffset, this._maxBottomOffset)
                    }
                    return 0
                },
                _fitOffset: function(offset, minOffset, maxOffset) {
                    if (minOffset != null)
                        offset = Math.max(offset, -minOffset);
                    if (maxOffset != null)
                        offset = Math.min(offset, maxOffset);
                    return offset
                },
                _processDropTargets: function(e, dragOffset) {
                    var target = this._findDropTarget(e),
                        sameTarget = target === this._$currentDropTarget;
                    if (!sameTarget) {
                        this._fireDropTargetEvent(e, DRAG_LEAVE_EVENT);
                        this._$currentDropTarget = target;
                        this._fireDropTargetEvent(e, DRAG_ENTER_EVENT)
                    }
                },
                _fireDropTargetEvent: function(event, eventName) {
                    if (!this._$currentDropTarget)
                        return;
                    var eventData = {
                            type: eventName,
                            originalEvent: event,
                            draggingElement: this._$element.get(0),
                            target: this._$currentDropTarget.get(0)
                        };
                    events.fireEvent(eventData)
                },
                _findDropTarget: function(e) {
                    var that = this,
                        $result;
                    $.each(this._$dropTargetElements, function(_, $target) {
                        if (that._checkDropTarget($target, e)) {
                            $result = $target;
                            return false
                        }
                    });
                    return $result
                },
                _checkDropTarget: function($target, e) {
                    var isDraggingElement = $target.get(0) === this._$element.get(0);
                    if (isDraggingElement)
                        return false;
                    var targetPosition = getItemPosition($target);
                    if (e.pageX < targetPosition.left)
                        return false;
                    if (e.pageY < targetPosition.top)
                        return false;
                    var targetSize = getItemSize($target);
                    if (e.pageX > targetPosition.left + targetSize.width)
                        return false;
                    if (e.pageY > targetPosition.top + targetSize.height)
                        return false;
                    return $target
                },
                end: function(e) {
                    var eventData = events.eventData(e);
                    this._fireEvent(DRAG_END_EVENT, e, {offset: this._calculateOffset(eventData)});
                    this._fireDropTargetEvent(e, DROP_EVENT);
                    delete this._$currentDropTarget
                }
            });
        ui.gestureEmitters.push({
            emitter: DragEmitter,
            events: [DRAG_START_EVENT, DRAG_EVENT, DRAG_END_EVENT]
        });
        DX.ui.events.__internals = DX.ui.events.__internals || {};
        $.extend(DX.ui.events.__internals, {dropTargets: knownDropTargets})
    })(jQuery, DevExpress);
    /*! Module core, file ui.events.gesture.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            events = ui.events,
            utils = DX.utils;
        var abs = Math.abs;
        var GESTURE_EVENT = "dxGesture",
            GESTURE_EVENT_DATA = "dxGestureEmitter",
            GESTURE_LOCK_KEY = "dxGestureLock",
            GESTURE_UNLOCK_TIMEOUT = 400,
            TOUCH_BOUNDARY = 10,
            HORIZONTAL = "horizontal",
            VERTICAL = "vertical",
            BOTH = "both";
        var GestureEventManager = DX.Class.inherit({
                SLEEP: 0,
                INITED: 1,
                STARTED: 2,
                ctor: function() {
                    this._attachHandlers();
                    this.reset()
                },
                _attachHandlers: function() {
                    $(document).on(events.addNamespace("dxpointerdown", GESTURE_EVENT), $.proxy(this._handlePointerDown, this)).on(events.addNamespace("dxpointermove", GESTURE_EVENT), $.proxy(this._handlePointerMove, this)).on(events.addNamespace("dxpointerup dxpointercancel", GESTURE_EVENT), $.proxy(this._handlePointerUp, this)).on(events.addNamespace("dxmousewheel", GESTURE_EVENT), $.proxy(this._handleMouseWheel, this))
                },
                _eachEmitter: function(callback) {
                    $.each(this._activeEmitters || {}, function(direction, emitter) {
                        return callback(emitter, direction)
                    })
                },
                _noEmitters: function() {
                    return $.isEmptyObject(this._activeEmitters)
                },
                reset: function() {
                    this._eachEmitter(function(emitter) {
                        emitter.removeCancelCallback()
                    });
                    this._forgetGesture();
                    this._stage = this.SLEEP;
                    this._activeEmitters = {}
                },
                _handlePointerDown: function(e) {
                    if (events.needSkipEvent(e) || events.hasTouches(e) > 1)
                        return;
                    this.reset();
                    this._activeEmitters = this._closestEmitter(e);
                    if (this._noEmitters())
                        return;
                    this._startEvent = e;
                    this._startEventData = events.eventData(e);
                    this._stage = this.INITED;
                    this._applyToActive("init", e)
                },
                _applyToActive: function(method) {
                    var args = $.makeArray(arguments).slice(1);
                    this._eachEmitter(function(emitter) {
                        if (method in emitter)
                            emitter[method].apply(emitter, args)
                    })
                },
                _closestEmitter: function(e) {
                    var result = {},
                        foundForAllDirections = false,
                        $element = $(e.target);
                    while ($element.length && !foundForAllDirections) {
                        var emitter = $element.data(GESTURE_EVENT_DATA);
                        if (emitter && emitter.validate(e)) {
                            var direction = emitter.getDirection(e);
                            if (direction) {
                                emitter.addCancelCallback($.proxy(this._handleCancel, this, emitter, e));
                                result[direction] = result[direction] || emitter
                            }
                        }
                        foundForAllDirections = result[HORIZONTAL] && result[VERTICAL] || result[BOTH];
                        $element = $element.parent()
                    }
                    return result
                },
                _handleCancel: function(canceledEmitter, e) {
                    var canceledDirection;
                    this._eachEmitter(function(emitter, direction) {
                        if (emitter === canceledEmitter) {
                            canceledDirection = direction;
                            emitter.removeCancelCallback()
                        }
                    });
                    this._forgetGesture([canceledEmitter]);
                    this._cancelEmitter(canceledEmitter, e);
                    if (this._noEmitters())
                        this.reset()
                },
                _handlePointerMove: function(e) {
                    if (this._stage === this.INITED && this._directionDetected(e))
                        this._handleStart(e);
                    if (this._stage === this.STARTED)
                        this._handleMove(e)
                },
                _directionDetected: function(e) {
                    var delta = events.eventDelta(this._startEventData, events.eventData(e));
                    return delta.x || delta.y
                },
                _handleStart: function(e) {
                    this._filterEmitters(e);
                    if (this._noEmitters())
                        return;
                    this._resetActiveElement();
                    this._applyToActive("start", this._startEvent);
                    this._stage = this.STARTED
                },
                _resetActiveElement: function() {
                    if (DX.devices.real().platform !== "ios")
                        return;
                    this._eachEmitter(function(emitter) {
                        if ($(":focus", emitter.getElement()).length)
                            utils.resetActiveElement()
                    })
                },
                _filterEmitters: function(e) {
                    this._filterByDirection(e);
                    if (this._emitersAmount() > 1)
                        this._takeFirstEmitter()
                },
                _emitersAmount: function() {
                    var result = 0;
                    this._eachEmitter(function() {
                        result++
                    });
                    return result
                },
                _filterByDirection: function(e) {
                    var delta = events.eventDelta(this._startEventData, events.eventData(e)),
                        horizontalMove = abs(delta.y) < abs(delta.x),
                        verticalMove = abs(delta.y) > abs(delta.x),
                        horizontalEmmiter = this._activeEmitters[HORIZONTAL],
                        verticalEmmiter = this._activeEmitters[VERTICAL],
                        bothEmitter = this._activeEmitters[BOTH],
                        existsHorizontalEmitter = horizontalEmmiter || bothEmitter,
                        existsVerticalEmitter = verticalEmmiter || bothEmitter;
                    if (horizontalMove && existsHorizontalEmitter)
                        this._cancelEmitter(verticalEmmiter, e);
                    else if (verticalMove && existsVerticalEmitter)
                        this._cancelEmitter(horizontalEmmiter, e)
                },
                _cancelEmitter: function(canceledEmmiter, e) {
                    if (!canceledEmmiter)
                        return;
                    canceledEmmiter.cancel(e);
                    delete this._activeEmitters[canceledEmmiter.getDirection(e)]
                },
                _takeFirstEmitter: function() {
                    var activeEmitters = {};
                    this._eachEmitter(function(emitter, direction) {
                        activeEmitters[direction] = emitter;
                        return false
                    });
                    this._activeEmitters = activeEmitters
                },
                _prepareGesture: function() {
                    this._gestureLocked = true;
                    clearTimeout(this._gestureEndTimer);
                    this._eachEmitter(function(emitter) {
                        emitter.getElement().data(GESTURE_LOCK_KEY, true)
                    });
                    ui.feedback.reset()
                },
                _handleMove: function(e) {
                    if (!this._gestureLocked) {
                        var delta = events.eventDelta(this._startEventData, events.eventData(e));
                        if (abs(delta.x) > TOUCH_BOUNDARY || abs(delta.y) > TOUCH_BOUNDARY) {
                            events.handleGestureEvent(e, GESTURE_EVENT);
                            this._prepareGesture()
                        }
                    }
                    this._applyToActive("move", e)
                },
                _forgetGesture: function(activeEmitters) {
                    activeEmitters = activeEmitters || this._activeEmitters;
                    if (this._noEmitters())
                        return;
                    this._gestureLocked = false;
                    this._gestureEndTimer = setTimeout(function() {
                        $.each(activeEmitters, function(_, emitter) {
                            emitter.getElement().data(GESTURE_LOCK_KEY, false)
                        })
                    }, GESTURE_UNLOCK_TIMEOUT)
                },
                _handlePointerUp: function(e) {
                    if (!DX.devices.isRippleEmulator() && events.hasTouches(e))
                        return;
                    if (this._stage === this.STARTED)
                        this._applyToActive("end", e);
                    else if (this._stage === this.INITED)
                        this._applyToActive("stop", e);
                    this.reset()
                },
                _handleMouseWheel: function(e) {
                    this._handlePointerDown(e);
                    if (this._stage !== this.INITED)
                        return;
                    this._takeFirstEmitter();
                    this._eachEmitter(function(emitter, direction) {
                        var prop = direction !== "horizontal" ? "pageY" : "pageX";
                        e[prop] += e.delta
                    });
                    this._handlePointerMove(e);
                    this._handlePointerUp(e)
                },
                isActive: function(element) {
                    var result = false;
                    this._eachEmitter(function(emitter) {
                        result = result || emitter.getElement().is(element)
                    });
                    return result
                }
            });
        var gestureEventManager = new GestureEventManager;
        var registerEmitter = function(emitterConfig) {
                var emitterClass = emitterConfig.emitter;
                $.each(emitterConfig.events, function(_, eventName) {
                    events.registerEvent(eventName, {
                        noBubble: true,
                        setup: function(element, data) {
                            var emitter = $(element).data(GESTURE_EVENT_DATA) || new emitterClass(element);
                            emitter.configurate(data);
                            $(element).data(GESTURE_EVENT_DATA, emitter)
                        },
                        teardown: function(element) {
                            if (gestureEventManager.isActive(element))
                                gestureEventManager.reset();
                            $(element).removeData(GESTURE_EVENT_DATA)
                        }
                    })
                })
            };
        $.each(ui.gestureEmitters, function(_, emitterConfig) {
            registerEmitter(emitterConfig)
        });
        events.__internals = events.__internals || {};
        $.extend(events.__internals, {registerEmitter: registerEmitter})
    })(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",
            HOVER_STATE_CLASS = "dx-state-hover",
            FEEDBACK_SHOW_TIMEOUT = 30,
            FEEDBACK_HIDE_TIMEOUT = 400,
            HOVER_START = "dxhoverstart",
            HOVER_END = "dxhoverend",
            ANONYMOUS_TEMPLATE_NAME = "template",
            TEMPLATE_SELECTOR = "[data-options*='dxTemplate']",
            TEMPLATES_DATA_KEY = "dxTemplates";
        var getTemplateOptions = function(element) {
                var options = $(element).data("options");
                if ($.trim(options).charAt(0) !== "{")
                    options = "{" + options + "}";
                return new Function("return " + options)().dxTemplate
            };
        var activeElement,
            events = ui.events;
        ui.feedback = {reset: function() {
                handleEnd(true)
            }};
        ui.Widget = DX.DOMComponent.inherit({
            NAME: "Widget",
            NAMESPACE: ui,
            _setDefaultOptions: function() {
                this.callBase();
                this.option({
                    disabled: false,
                    visible: true,
                    activeStateEnabled: true,
                    width: undefined,
                    height: undefined,
                    contentReadyAction: null,
                    hoverStateEnabled: false
                })
            },
            _init: function() {
                this.callBase();
                this._feedbackShowTimeout = FEEDBACK_SHOW_TIMEOUT;
                this._feedbackHideTimeout = FEEDBACK_HIDE_TIMEOUT;
                if (this._templatesSupported()) {
                    this._initTemplates();
                    this._initContentReadyAction()
                }
            },
            _templatesSupported: function() {
                return this._renderContentImpl !== DX.abstract
            },
            _initTemplates: function() {
                var that = this,
                    templates = {},
                    dataTemplateElements = this._element().data(TEMPLATES_DATA_KEY),
                    templateElements = dataTemplateElements ? dataTemplateElements : this._element().contents().filter(TEMPLATE_SELECTOR);
                this._templateProvider = new ui.TemplateProvider;
                this._templateClass = this._templateProvider.getTemplateClass(this);
                if (templateElements.length) {
                    var templatesMap = {};
                    templateElements.each(function() {
                        var templateOptions = getTemplateOptions(this);
                        if (!templateOptions)
                            return;
                        if (!templateOptions.name)
                            throw Error("Template name was not specified");
                        templatesMap[templateOptions.name] = templatesMap[templateOptions.name] || [];
                        templatesMap[templateOptions.name].push(this)
                    });
                    $.each(templatesMap, function(templateName, value) {
                        var deviceTemplate = that._findTemplateByDevice(value);
                        if (deviceTemplate)
                            templates[templateName] = that._createTemplate(deviceTemplate)
                    })
                }
                else
                    templates[ANONYMOUS_TEMPLATE_NAME] = that._createTemplate(that._element().contents());
                this.option("_templates", templates)
            },
            _getTemplateByOption: function(optionName) {
                return this._getTemplate(this.option(optionName))
            },
            _getTemplate: function(templateName) {
                var result = this._acquireTemplate.apply(this, arguments);
                if (!result && this._templateProvider.supportDefaultTemplate(this)) {
                    result = this._templateProvider.getDefaultTemplate(this);
                    if (!result)
                        throw Error(DX.utils.stringFormat("Template \"{0}\" was not found and no default template specified!", templateName));
                }
                return result
            },
            _acquireTemplate: function(templateSource) {
                if (templateSource == null)
                    return templateSource;
                if (templateSource instanceof this._templateClass)
                    return templateSource;
                if (templateSource.nodeType || templateSource.jquery) {
                    templateSource = $(templateSource);
                    if (templateSource.is("script"))
                        templateSource = templateSource.html();
                    return this._createTemplate(templateSource)
                }
                if (typeof templateSource === "string")
                    return this.option("_templates")[templateSource];
                if ($.isFunction(templateSource)) {
                    var args = $.makeArray(arguments).slice(1);
                    return this._acquireTemplate(templateSource.apply(this, args))
                }
                return this._acquireTemplate(templateSource.toString())
            },
            _createTemplate: function(element) {
                return new this._templateClass(element, this)
            },
            _findTemplateByDevice: function(templates) {
                var suitableTemplate = DX.utils.findBestMatches(DX.devices.current(), templates, function(template) {
                        return getTemplateOptions(template)
                    })[0];
                $.each(templates, function(index, template) {
                    if (template !== suitableTemplate)
                        $(template).remove()
                });
                return suitableTemplate
            },
            _cleanTemplates: function() {
                var that = this;
                $.each(this.option("_templates"), function(templateName, template) {
                    if (that === template.owner())
                        template.dispose()
                })
            },
            _initContentReadyAction: function() {
                this._contentReadyAction = this._createActionByOption("contentReadyAction", {excludeValidators: ["gesture", "designMode", "disabled"]})
            },
            _render: function() {
                this.callBase();
                this._element().addClass("dx-widget");
                this._toggleDisabledState(this.option("disabled"));
                this._toggleVisibility(this.option("visible"));
                this._refreshFeedback();
                this._renderDimensions();
                if (this._templatesSupported())
                    this._renderContent();
                this._attachHoverEvents()
            },
            _renderContent: function() {
                this._renderContentImpl();
                this._fireContentReadyAction()
            },
            _renderContentImpl: DX.abstract,
            _fireContentReadyAction: function() {
                this._contentReadyAction({excludeValidators: ["disabled", "gesture"]})
            },
            _dispose: function() {
                if (this._templatesSupported())
                    this._cleanTemplates();
                this._contentReadyAction = null;
                this._clearTimers();
                if (activeElement && activeElement.closest(this._element()).length)
                    activeElement = 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)
            },
            _attachHoverEvents: function() {
                var that = this,
                    hoverableSelector = that._activeStateUnit,
                    nameStart = events.addNamespace(HOVER_START, UI_FEEDBACK),
                    nameEnd = events.addNamespace(HOVER_END, UI_FEEDBACK);
                that._element().off(nameStart, hoverableSelector).off(nameEnd, hoverableSelector);
                if (this.option("hoverStateEnabled")) {
                    var startAction = new DX.Action(function(args) {
                            var $target = args.element;
                            that._refreshHoveredElement($target)
                        });
                    that._element().on(nameStart, hoverableSelector, {selector: hoverableSelector}, function(e) {
                        startAction.execute({element: $(e.target)})
                    }).on(nameEnd, hoverableSelector, {selector: hoverableSelector}, function(e) {
                        e.stopImmediatePropagation();
                        that._forgetHoveredElement()
                    })
                }
                else
                    this._toggleHoverClass(false)
            },
            _refreshHoveredElement: function(hoveredElement) {
                var selector = this._activeStateUnit || this._element();
                this._forgetHoveredElement();
                this._hoveredElement = hoveredElement.closest(selector);
                this._toggleHoverClass(true)
            },
            _forgetHoveredElement: function() {
                this._toggleHoverClass(false);
                delete this._hoveredElement
            },
            _toggleHoverClass: function(value) {
                if (this._hoveredElement)
                    this._hoveredElement.toggleClass(HOVER_STATE_CLASS, value && this.option("hoverStateEnabled"))
            },
            _renderDimensions: function() {
                var width = this.option("width"),
                    height = this.option("height");
                this._setDimension(width, "width");
                this._setDimension(height, "height")
            },
            _setDimension: function(dimensionSize, dimension) {
                var $element = this._element();
                dimensionSize = $.isFunction(dimensionSize) ? dimensionSize() : dimensionSize;
                if ($.isNumeric(dimensionSize))
                    dimensionSize = dimensionSize + "px";
                if (!dimensionSize && dimension === "width")
                    dimensionSize = this._calculateWidth();
                $element.css(dimension, dimensionSize)
            },
            _calculateWidth: function() {
                var $element = this._element(),
                    explicitWidth = $element[0].style.width,
                    calculatedWidth;
                if (explicitWidth[explicitWidth.length - 1] === "%" && !this.option("width"))
                    return explicitWidth;
                else
                    calculatedWidth = explicitWidth && explicitWidth !== "auto" && explicitWidth !== "inherit" ? $element.outerWidth() : this.option("width");
                return calculatedWidth
            },
            _refreshFeedback: function() {
                if (this._feedbackDisabled()) {
                    this._feedbackOff(true);
                    this._element().removeClass(UI_FEEDBACK_CLASS)
                }
                else
                    this._element().addClass(UI_FEEDBACK_CLASS)
            },
            _feedbackDisabled: function() {
                return !this.option("activeStateEnabled") || this.option("disabled")
            },
            _feedbackOn: function(element, immediate) {
                if (this._feedbackDisabled())
                    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);
                    this._toggleHoverClass(false)
                }
            },
            _saveActiveElement: function() {
                activeElement = this._element()
            },
            _feedbackOff: function(immediate) {
                this._clearTimers();
                if (immediate)
                    this._feedbackHide();
                else
                    this._feedbackHideTimer = window.setTimeout($.proxy(this._feedbackHide, this), this._feedbackHideTimeout)
            },
            _feedbackHide: function() {
                var activeStateElement = this._element();
                if (this._activeStateUnit)
                    activeStateElement = activeStateElement.find(this._activeStateUnit);
                activeStateElement.removeClass(ACTIVE_STATE_CLASS);
                this._toggleHoverClass(!this.option("disabled"));
                this._clearActiveElement()
            },
            _clearActiveElement: function() {
                var rootDomElement = this._element().get(0),
                    activeDomElement = activeElement && activeElement.get(0);
                if (activeDomElement && (activeDomElement === rootDomElement || $.contains(rootDomElement, activeDomElement)))
                    activeElement = null
            },
            _toggleDisabledState: function(value) {
                this._element().toggleClass(DISABLED_STATE_CLASS, Boolean(value));
                this._toggleHoverClass(!value)
            },
            _optionChanged: function(name, value) {
                switch (name) {
                    case"disabled":
                        this._toggleDisabledState(value);
                        this._refreshFeedback();
                        break;
                    case"activeStateEnabled":
                        this._refreshFeedback();
                        break;
                    case"hoverStateEnabled":
                        this._attachHoverEvents();
                        break;
                    case"visible":
                        this._toggleVisibility(value);
                        break;
                    case"width":
                    case"height":
                        this._renderDimensions();
                        break;
                    case"contentReadyAction":
                        this._initContentReadyAction();
                        break;
                    case"_templates":
                        this._refresh();
                        break;
                    default:
                        this.callBase.apply(this, arguments)
                }
            },
            repaint: function() {
                this._refresh()
            }
        });
        var handleStart = function(args, immediate) {
                var e = args.jQueryEvent,
                    $target = args.element,
                    widget;
                if (events.needSkipEvent(e))
                    return;
                if (activeElement) {
                    widget = getWidget(activeElement);
                    if (widget)
                        widget._feedbackOff(true)
                }
                var closestFeedbackElement = $target.closest("." + UI_FEEDBACK_CLASS);
                if (closestFeedbackElement.length) {
                    widget = getWidget(closestFeedbackElement);
                    if (!widget)
                        return;
                    widget._feedbackOn($target, immediate);
                    if (immediate)
                        widget._feedbackOff()
                }
            };
        var handleEnd = function(immediate) {
                if (!activeElement)
                    return;
                var widget = getWidget(activeElement);
                if (widget)
                    widget._feedbackOff(immediate)
            };
        var getWidget = function(widgetElement) {
                var result;
                $.each(widgetElement.data("dxComponents") || [], function(index, componentName) {
                    if (ui[componentName] && ui[componentName].subclassOf(ui.Widget)) {
                        result = widgetElement.data(componentName);
                        return false
                    }
                });
                return result
            };
        $(function() {
            var startAction = new DX.Action(handleStart);
            $(document).on(events.addNamespace("dxpointerdown", UI_FEEDBACK), function(e) {
                startAction.execute({
                    jQueryEvent: e,
                    element: $(e.target)
                })
            }).on(events.addNamespace("dxpointerup dxpointercancel", UI_FEEDBACK), function(e) {
                var activeElementClicked = activeElement && $(e.target).closest("." + UI_FEEDBACK_CLASS).get(0) === activeElement.get(0);
                if (activeElementClicked)
                    startAction.execute({
                        jQueryEvent: e,
                        element: $(e.target)
                    }, true);
                handleEnd()
            })
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.editor.js */
    (function($, DX, undefined) {
        var ui = DX.ui;
        DX.registerComponent("dxEditor", ui.Widget.inherit({
            _setDefaultOptions: function() {
                this.callBase();
                this.option({
                    value: undefined,
                    valueChangeAction: undefined
                })
            },
            _recreateValueChangeAction: function() {
                this._valueChangeAction = this._createActionByOption("valueChangeAction")
            },
            _suppressValueChangeAction: function() {
                this._valueChangeActionSuppressed = true
            },
            _resumeValueChangeAction: function() {
                this._valueChangeActionSuppressed = false
            },
            _render: function() {
                this._recreateValueChangeAction();
                this.callBase()
            },
            _raiseValueChangeAction: function(value, previousValue, extraArguments) {
                var args = {
                        value: value,
                        previousValue: previousValue,
                        jQueryEvent: this._valueChangeEventInstance
                    };
                if (extraArguments)
                    args = $.extend(args, extraArguments);
                this._valueChangeAction(args)
            },
            _optionChanged: function(name, value, previousValue) {
                switch (name) {
                    case"valueChangeAction":
                        this._recreateValueChangeAction();
                        break;
                    case"value":
                        if (!this._valueChangeActionSuppressed)
                            this._raiseValueChangeAction(value, previousValue);
                        this._valueChangeEventInstance = undefined;
                        break;
                    default:
                        this.callBase.apply(this, arguments)
                }
            }
        }))
    })(jQuery, DevExpress);
    /*! Module core, file ui.template.js */
    (function($, DX, undefined) {
        var isString = DX.utils.isString;
        var currentTemplateEngine;
        var templateEngines = [];
        var BaseTemplate = DevExpress.Class.inherit({
                _compile: function(html, element) {
                    return element
                },
                _render: function(template, data) {
                    return template
                },
                ctor: function(element) {
                    this._element = $(element);
                    if (this._element.length === 1) {
                        if (this._element[0].nodeName.toLowerCase() !== "script")
                            this._element = $("<div />").append(this._element);
                        this._template = this._compile(this._element.html() || "", this._element)
                    }
                },
                render: function(container, data) {
                    var result;
                    if (this._template) {
                        result = this._render(this._template, data);
                        if (isString(result))
                            result = $.parseHTML(result);
                        result = $(result);
                        if (container)
                            container.append(result);
                        return result
                    }
                },
                owner: $.noop,
                dispose: $.noop
            });
        var createTemplateEngine = function(options) {
                if (options && options.compile && options.render)
                    return BaseTemplate.inherit({
                            allowRenderToDetachedContainer: options.allowRenderToDetachedContainer !== false,
                            _compile: options.compile,
                            _render: options.render
                        });
                else
                    throw Error("Template Engine must contains compile and render methods");
            };
        if (window.ko) {
            var koCustomTemplateEngine = function(){};
            koCustomTemplateEngine.prototype = ko.utils.extend(new ko.templateEngine, {
                renderTemplateSource: function(templateSource, bindingContext, options) {
                    var precompiledTemplate = templateSource["data"]("precompiledTemplate");
                    if (!precompiledTemplate) {
                        precompiledTemplate = new currentTemplateEngine(templateSource.domElement);
                        templateSource["data"]("precompiledTemplate", precompiledTemplate)
                    }
                    return precompiledTemplate.render(null, bindingContext.$data)
                },
                allowTemplateRewriting: false
            })
        }
        DevExpress.ui.setTemplateEngine = function(templateEngine) {
            if (isString(templateEngine)) {
                currentTemplateEngine = templateEngines && templateEngines[templateEngine];
                if (!currentTemplateEngine && templateEngine !== "default")
                    throw Error(DX.utils.stringFormat("Template Engine \"{0}\" is not supported", templateEngine));
            }
            else
                currentTemplateEngine = createTemplateEngine(templateEngine) || currentTemplateEngine;
            if (window.ko)
                ko.setTemplateEngine(currentTemplateEngine ? new koCustomTemplateEngine : new ko.nativeTemplateEngine)
        };
        DevExpress.ui.TemplateProvider = DevExpress.ui.TemplateProvider.inherit({getTemplateClass: function() {
                if (currentTemplateEngine)
                    return currentTemplateEngine;
                return this.callBase.apply(this, arguments)
            }});
        var registerTemplateEngine = function(name, templateOptions) {
                templateEngines[name] = createTemplateEngine(templateOptions)
            };
        registerTemplateEngine("jquery-tmpl", {
            compile: function(html, element) {
                return element
            },
            render: function(template, data) {
                return template.tmpl(data)
            }
        });
        registerTemplateEngine("jsrender", {
            compile: function(html) {
                return $.templates(html)
            },
            render: function(template, data) {
                return template.render(data)
            }
        });
        registerTemplateEngine("mustache", {
            compile: function(html) {
                return Mustache.compile(html)
            },
            render: function(template, data) {
                return template(data)
            }
        });
        registerTemplateEngine("hogan", {
            compile: function(html) {
                return Hogan.compile(html)
            },
            render: function(template, data) {
                return template.render(data)
            }
        });
        registerTemplateEngine("underscore", {
            compile: function(html) {
                return _.template(html)
            },
            render: function(template, data) {
                return template(data)
            }
        });
        registerTemplateEngine("handlebars", {
            compile: function(html) {
                return Handlebars.compile(html)
            },
            render: function(template, data) {
                return template(data)
            }
        });
        registerTemplateEngine("doT", {
            compile: function(html) {
                return doT.template(html)
            },
            render: function(template, data) {
                return template(data)
            }
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.collectionContainerWidget.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            events = ui.events;
        var CollectionContainerWidget = ui.Widget.inherit({
                _setDefaultOptions: function() {
                    this.callBase();
                    this.option({
                        items: [],
                        itemTemplate: "item",
                        itemRender: null,
                        itemRenderedAction: null,
                        itemClickAction: null,
                        itemHoldAction: null,
                        itemHoldTimeout: 750,
                        noDataText: Globalize.localize("dxCollectionContainerWidget-noDataText"),
                        dataSource: null,
                        selectedIndex: -1,
                        itemSelectAction: null
                    })
                },
                _init: function() {
                    this.callBase();
                    this._cleanRenderedItems();
                    this._refreshDataSource()
                },
                _dataSourceOptions: function() {
                    var options = {
                            paginate: false,
                            _preferSync: false
                        };
                    if ($.isArray(this.option("dataSource")))
                        options._preferSync = true;
                    return options
                },
                _cleanRenderedItems: function() {
                    this._renderedItemsCount = 0
                },
                _fireSelectItemEvent: function(index, prevIndex) {
                    if (this._selectionEnabled()) {
                        this._updateSelectedIndex(index, prevIndex);
                        this._handleItemEvent(this._selectedItemElement(index), "itemSelectAction", {
                            selectedIndex: index,
                            previousIndex: prevIndex
                        }, {excludeValidators: ["gesture", "disabled"]})
                    }
                },
                _optionChanged: function(name, value, prevValue) {
                    switch (name) {
                        case"items":
                            if (this._selectionEnabled()) {
                                var itemsCount = value && value.length || 0,
                                    maxIndex = Math.max(itemsCount - 1, 0);
                                if (maxIndex < this.option("selectedIndex"))
                                    this.option("selectedIndex", 0)
                            }
                            this._cleanRenderedItems();
                            this._invalidate();
                            break;
                        case"dataSource":
                            this._refreshDataSource();
                            if (!this._dataSource)
                                this.option("items", []);
                            this._renderEmptyMessage();
                            break;
                        case"noDataText":
                            this._renderEmptyMessage();
                            break;
                        case"itemTemplate":
                            this._invalidate();
                            break;
                        case"itemRender":
                            this._itemRender = null;
                            this._invalidate();
                            break;
                        case"itemRenderedAction":
                            this._createItemRenderAction();
                            break;
                        case"itemClickAction":
                            break;
                        case"itemHoldAction":
                        case"itemHoldTimeout":
                            this._attachHoldEvent();
                            break;
                        case"selectedIndex":
                            this._fireSelectItemEvent(value, prevValue);
                            break;
                        case"itemSelectAction":
                            break;
                        default:
                            this.callBase(name, value, prevValue)
                    }
                },
                _expectNextPageLoading: function() {
                    this._startIndexForAppendedItems = 0
                },
                _expectLastItemLoading: function() {
                    this._startIndexForAppendedItems = -1
                },
                _forgetNextPageLoading: function() {
                    this._startIndexForAppendedItems = null
                },
                _handleDataSourceChanged: function(newItems) {
                    var items = this.option("items");
                    if (this._initialized && items && this._shouldAppendItems()) {
                        this._renderedItemsCount = items.length;
                        if (!this._dataSource.isLastPage() || this._startIndexForAppendedItems !== -1)
                            this.option().items = items.concat(newItems.slice(this._startIndexForAppendedItems));
                        this._renderContent();
                        this._forgetNextPageLoading()
                    }
                    else
                        this.option("items", newItems)
                },
                _handleDataSourceLoadError: function() {
                    this._forgetNextPageLoading()
                },
                _shouldAppendItems: function() {
                    return this._startIndexForAppendedItems != null && this._allowDinamicItemsAppend()
                },
                _allowDinamicItemsAppend: function() {
                    return false
                },
                _clean: function() {
                    this._itemContainer().empty()
                },
                _refresh: function() {
                    this._cleanRenderedItems();
                    this.callBase.apply(this, arguments)
                },
                _itemContainer: function() {
                    return this._element()
                },
                _itemClass: DX.abstract,
                _itemSelector: function() {
                    return "." + this._itemClass()
                },
                _itemDataKey: DX.abstract,
                _itemElements: function() {
                    return this._itemContainer().find(this._itemSelector())
                },
                _render: function() {
                    this.callBase();
                    this._attachClickEvent();
                    this._attachHoldEvent();
                    if (this._selectionEnabled()) {
                        this._renderSelectedIndex(this.option("selectedIndex"));
                        this._attachSelectedEvent()
                    }
                },
                _selectionEnabled: function() {
                    return this._renderSelectedIndex !== DX.abstract
                },
                _selectionByClickEnabled: function() {
                    return true
                },
                _renderSelectedIndex: DX.abstract,
                _attachSelectedEvent: function() {
                    if (!this._selectionByClickEnabled())
                        return;
                    var itemSelector = this._itemSelector(),
                        itemSelectHandler = this._createAction($.proxy(function(e) {
                            this._handleItemSelect(e.jQueryEvent)
                        }, this)),
                        eventName = events.addNamespace("dxclick", this.NAME);
                    this._element().off(eventName, itemSelector).on(eventName, itemSelector, $.proxy(function(e) {
                        var $itemElement = $(e.target).closest(itemSelector);
                        itemSelectHandler({
                            itemElement: $itemElement,
                            jQueryEvent: e
                        });
                        this._handleItemClick(e)
                    }, this))
                },
                _handleItemSelect: function(e) {
                    if (events.needSkipEvent(e))
                        return;
                    var items = this.option("items"),
                        selectedItem = $(e.currentTarget).data(this._itemDataKey()),
                        selectedItemIndex = $.inArray(selectedItem, items);
                    this.option("selectedIndex", selectedItemIndex)
                },
                _updateSelectedIndex: function() {
                    this._renderSelectedIndex.apply(this, arguments)
                },
                _selectedItemElement: function(index) {
                    return this._itemElements().eq(index)
                },
                _attachClickEvent: function() {
                    if (this._selectionEnabled() && this._selectionByClickEnabled())
                        return;
                    var itemSelector = this._itemSelector(),
                        eventName = events.addNamespace("dxclick", this.NAME);
                    this._itemContainer().off(eventName, itemSelector).on(eventName, itemSelector, $.proxy(this._handleItemClick, this))
                },
                _handleItemClick: function(e) {
                    this._handleItemJQueryEvent(e, "itemClickAction")
                },
                _attachHoldEvent: function() {
                    var $itemContainer = this._itemContainer(),
                        itemSelector = this._itemSelector(),
                        eventName = events.addNamespace("dxhold", this.NAME);
                    $itemContainer.off(eventName, itemSelector);
                    if (this._shouldAttachHoldEvent())
                        $itemContainer.on(eventName, itemSelector, {timeout: this.option("itemHoldTimeout")}, $.proxy(this._handleItemHold, this))
                },
                _shouldAttachHoldEvent: function() {
                    return this.option("itemHoldAction")
                },
                _handleItemHold: function(e) {
                    this._handleItemJQueryEvent(e, "itemHoldAction")
                },
                _renderContentImpl: function() {
                    var items = this.option("items") || [];
                    if (this._renderedItemsCount)
                        this._renderItems(items.slice(this._renderedItemsCount));
                    else
                        this._renderItems(items)
                },
                _renderItems: function(items) {
                    if (items.length)
                        $.each(items, $.proxy(this._renderItem, this));
                    this._renderEmptyMessage()
                },
                _renderItem: function(index, itemData, container) {
                    container = container || this._itemContainer();
                    var itemRenderer = this._getItemRenderer(),
                        itemTemplateName = this._getItemTemplateName(itemData),
                        itemTemplate = this._getTemplate(itemTemplateName, index, itemData),
                        itemElement,
                        renderArgs = {
                            index: index,
                            item: itemData,
                            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(), itemData);
                    var postprocessRenderArgs = {
                            itemElement: itemElement,
                            itemData: itemData,
                            itemIndex: index
                        };
                    this._postprocessRenderItem(postprocessRenderArgs);
                    this._getItemRenderAction()({
                        itemElement: itemElement,
                        itemData: itemData
                    });
                    return itemElement
                },
                _createItemRenderAction: function() {
                    return this._itemRenderAction = this._createActionByOption("itemRenderedAction", {
                            element: this._element(),
                            excludeValidators: ["gesture", "designMode", "disabled"]
                        })
                },
                _getItemRenderAction: function() {
                    return this._itemRenderAction || this._createItemRenderAction()
                },
                _getItemRenderer: function() {
                    this._itemRender = this._itemRender || this.option("itemRender");
                    return this._itemRender
                },
                _createItemByRenderer: function(itemRenderer, renderArgs) {
                    var itemElement = $("<div />").appendTo(renderArgs.container);
                    var rendererResult = itemRenderer.call(this, renderArgs.item, renderArgs.index, itemElement);
                    if (rendererResult != null && itemElement[0] !== rendererResult[0])
                        itemElement.append(rendererResult);
                    return itemElement
                },
                _getItemTemplateName: function(itemData) {
                    return itemData && itemData.template || this.option("itemTemplate")
                },
                _createItemByTemplate: function(itemTemplate, renderArgs) {
                    return itemTemplate.render(renderArgs.container, renderArgs.item, renderArgs.index, "ignoreTarget")
                },
                _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))
                },
                _postprocessRenderItem: $.noop,
                _renderEmptyMessage: function() {
                    if (!this._selectionEnabled()) {
                        var noDataText = this.option("noDataText"),
                            items = this.option("items"),
                            dataSourceLoading = this._dataSource && this._dataSource.isLoading(),
                            hideNoData = !noDataText || items && items.length || dataSourceLoading;
                        if (hideNoData && this._$nodata) {
                            this._$nodata.remove();
                            this._$nodata = null
                        }
                        if (!hideNoData) {
                            this._$nodata = this._$nodata || $("<div />").addClass("dx-empty-message");
                            this._$nodata.appendTo(this._itemContainer()).text(noDataText)
                        }
                    }
                },
                _handleItemJQueryEvent: function(jQueryEvent, handlerOptionName, actionArgs, actionConfig) {
                    this._handleItemEvent(jQueryEvent.target, handlerOptionName, $.extend(actionArgs, {jQueryEvent: jQueryEvent}), actionConfig)
                },
                _handleItemEvent: function(initiator, handlerOptionName, actionArgs, actionConfig) {
                    var action = this._createActionByOption(handlerOptionName, actionConfig);
                    return this._handleItemEventImpl(initiator, action, actionArgs)
                },
                _handleItemEventByHandler: function(initiator, handler, actionArgs, actionConfig) {
                    var action = this._createAction(handler, actionConfig);
                    return this._handleItemEventImpl(initiator, action, actionArgs)
                },
                _handleItemEventImpl: function(initiator, action, actionArgs) {
                    var $itemElement = this._closestItemElement($(initiator));
                    actionArgs = $.extend({
                        itemElement: $itemElement,
                        itemData: this._getItemData($itemElement)
                    }, actionArgs);
                    return action(actionArgs)
                },
                _closestItemElement: function($element) {
                    return $($element).closest(this._itemSelector())
                },
                _getItemData: function($itemElement) {
                    return $itemElement.data(this._itemDataKey())
                },
                itemElements: function() {
                    return this._itemElements()
                },
                itemsContainer: function() {
                    return this._itemContainer()
                }
            }).include(ui.DataHelperMixin);
        ui.CollectionContainerWidget = CollectionContainerWidget
    })(jQuery, DevExpress);
    /*! Module core, file ui.tooltip.js */
    (function($, DX, undefined) {
        var $tooltip = null;
        var createTooltip = function(options) {
                options = $.extend({position: "top"}, options);
                var content = options.content;
                delete options.content;
                return $("<div />").html(content).appendTo(DX.overlayTargetContainer()).dxTooltip(options)
            };
        var removeTooltip = function() {
                if (!$tooltip)
                    return;
                $tooltip.remove();
                $tooltip = null
            };
        var tooltip = {
                show: function(options) {
                    removeTooltip();
                    $tooltip = createTooltip(options);
                    return $tooltip.dxTooltip("show")
                },
                hide: function() {
                    if (!$tooltip)
                        return $.when();
                    return $tooltip.dxTooltip("hide").done(removeTooltip).promise()
                }
            };
        DX.ui.tooltip = tooltip
    })(jQuery, DevExpress)
}
if (!DevExpress.MOD_VIZ_CORE) {
    if (!window.DevExpress)
        throw Error('Required module is not referenced: core');
    /*! Module viz-core, file namespaces.js */
    (function(DevExpress) {
        DevExpress.viz = {}
    })(DevExpress);
    /*! Module viz-core, file namespaces.js */
    (function(DevExpress) {
        DevExpress.viz.core = {}
    })(DevExpress);
    /*! Module viz-core, file errorsWarnings.js */
    (function(DevExpress) {
        DevExpress.viz.core.errorsWarnings = {
            E2001: "Invalid data source",
            E2002: "Axis type and data type are incompatible",
            E2003: "\"{0}\" data source field contains data of unsupported type",
            E2004: "\"{0}\" data source field is inconsistent",
            E2101: "Unknown series type was specified: {0}",
            E2102: "Ambiguity occurred between two value axes with the same name",
            E2103: "\"{0}\" option must be a function",
            E2104: "Invalid logarithm base",
            E2105: "Invalid value of a \"{0}\"",
            E2106: "Invalid visible range",
            E2201: "Invalid type of data source field",
            E2202: "Invalid scale {0} value",
            E2203: "The \"{0}\" field of the \"selectedRange\" configuration object is not valid",
            W2001: "{0} cannot be drawn because its container is invisible",
            W2002: "The {0} data field is absent",
            W2003: "Tick interval is too small",
            W2101: "\"{0}\" pane does not exist; \"{1}\" pane is used instead",
            W2102: "Value axis with the \"{0}\" name was created automatically",
            W2103: "Chart title was hidden due to container size",
            W2104: "Legend was hidden due to container size",
            W2105: "Title of \"{0}\" axis was hidden due to container size",
            W2106: "Labels of \"{0}\" axis were hidden due to container size",
            W2301: "Invalid value range"
        }
    })(DevExpress);
    /*! Module viz-core, file tickProvider.js */
    (function($, DX, undefined) {
        var utils = DX.utils,
            math = Math,
            mathCeil = math.ceil,
            mathFloor = math.floor,
            mathAbs = math.abs,
            mathRound = math.round,
            core = DX.viz.core;
        var TICKS_COUNT_LIMIT = 2000;
        core.outOfScreen = {
            x: -1000,
            y: -1000
        };
        core.tickIntervalCalculator = {
            _defaultNumberMultipliers: [1, 2, 3, 5],
            _defaultGridSpacingFactor: 30,
            _getCommonTickInterval: function(deltaCoef, numberMultipliers) {
                var factor,
                    result = 0,
                    hasResult = false,
                    i;
                for (factor = 1; !hasResult; factor *= 10)
                    for (i = 0; i < numberMultipliers.length; i++) {
                        result = numberMultipliers[i] * factor;
                        if (deltaCoef <= result) {
                            hasResult = true;
                            break
                        }
                    }
                return result
            },
            _getNumericTickInterval: function(deltaCoef, numberMultipliers) {
                var factor,
                    result = 0,
                    newResult,
                    hasResult = false,
                    i;
                if (deltaCoef > 1.0)
                    result = this._getCommonTickInterval(deltaCoef, numberMultipliers);
                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)
            },
            _getLogarithmicTickInterval: function(deltaCoef, numberMultipliers) {
                var result = 0;
                if (deltaCoef !== 0)
                    result = this._getCommonTickInterval(deltaCoef, numberMultipliers);
                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 > 0 && deltaCoef < 1.0)
                    return {milliseconds: 1};
                else if (deltaCoef === 0)
                    return 0;
                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(options) {
                var that = this,
                    gridSpacingFactor = options.gridSpacingFactor || that._defaultGridSpacingFactor,
                    numberMultipliers = options.numberMultipliers || that._defaultNumberMultipliers,
                    businessDelta = options.businessDelta,
                    screenDelta = options.screenDelta,
                    deltaCoef = screenDelta > 0 && gridSpacingFactor < screenDelta ? gridSpacingFactor * businessDelta / screenDelta : 0;
                that._testNumberMultipliers = numberMultipliers;
                if (options.axisType === 'logarithmic')
                    return that._getLogarithmicTickInterval(deltaCoef, numberMultipliers);
                else
                    switch (options.dataType) {
                        case'numeric':
                            return that._getNumericTickInterval(deltaCoef, numberMultipliers);
                            break;
                        case'datetime':
                            return that._getDateTimeTickInterval(deltaCoef, numberMultipliers);
                            break
                    }
                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 = mathFloor(businessDelta / numberMultipliers[i]);
                    if (deltaCoef <= result)
                        return utils.convertMillisecondsToDateUnits(result)
                }
                return 0
            },
            _getCommonTickInterval: 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(options) {
                var that = this,
                    gridSpacingFactor = !utils.isDefined(options.gridSpacingFactor) ? that._defaultGridSpacingFactor : options.gridSpacingFactor,
                    numberMultipliers = options.numberMultipliers || that._defaultNumberMultipliers,
                    businessDelta = options.businessDelta,
                    deltaCoef = gridSpacingFactor * businessDelta / options.screenDelta;
                if (options.axisType === 'logarithmic')
                    return that._getCommonTickInterval(businessDelta, deltaCoef, numberMultipliers);
                else
                    switch (options.dataType) {
                        case'numeric':
                            return that._getCommonTickInterval(businessDelta, deltaCoef, numberMultipliers);
                        case'datetime':
                            return that._getDateTimeTickInterval(businessDelta, deltaCoef, numberMultipliers)
                    }
                return 0
            }
        };
        core.tickProvider = {
            _appendFakeSVGElement: function(value, text, options) {
                var textOptions = $.extend({}, options.textOptions, {rotate: 0});
                return options.renderer.createText(text, core.outOfScreen.x + (options.translator.translate(value) || 0), core.outOfScreen.y, textOptions).append()
            },
            _getDistanceByAngle: function(elementHeight, rotationAngle) {
                return elementHeight / mathAbs(math.sin(rotationAngle * (math.PI / 180)))
            },
            _areDisplayValuesValid: function(value1, value2, options) {
                var that = this,
                    getText = that._getTextFunc(options),
                    rotationAngle = options.textOptions && utils.isNumber(options.textOptions.rotate) ? options.textOptions.rotate : 0,
                    svgElement1 = that._appendFakeSVGElement(value1, getText(value1), options),
                    svgElement2 = that._appendFakeSVGElement(value2, getText(value2), options),
                    bBox1 = svgElement1.getBBox(),
                    bBox2 = svgElement2.getBBox(),
                    result,
                    translator = options.translator;
                if (rotationAngle !== 0)
                    result = that._getDistanceByAngle(bBox1.height, rotationAngle) <= mathAbs(bBox2.x - bBox1.x);
                else if (options.isHorizontal)
                    result = !translator.getBusinessRange().invert ? bBox1.x + bBox1.width < bBox2.x : bBox2.x + bBox2.width < bBox1.x;
                else
                    result = mathAbs(translator.translate(value1) - translator.translate(value2)) > bBox1.height;
                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)
            },
            _getValueSize: function(values, options) {
                var that = this,
                    value,
                    rotationAngle = options.textOptions ? options.textOptions.rotate : 0,
                    svgElement,
                    bBox,
                    result,
                    getText = that._getTextFunc(options),
                    i;
                if (values.length === 0)
                    return 0;
                options.isRotate = utils.isNumber(rotationAngle) && rotationAngle !== 0;
                if (options.isRotate || !options.isHorizontal)
                    value = getText(values[0]);
                else {
                    value = [];
                    for (i = 0; i < values.length; i++)
                        value.push(getText(values[i]));
                    value = value.join('\n')
                }
                svgElement = that._appendFakeSVGElement(value, value, options);
                bBox = svgElement.getBBox();
                if (options.isRotate)
                    result = that._getDistanceByAngle(bBox.height, rotationAngle);
                else
                    result = options.isHorizontal ? bBox.width : bBox.height;
                svgElement.remove();
                return mathCeil(result)
            },
            _adjustNumericTickValue: function(value, interval, min) {
                return utils.isExponential(value) ? utils.adjustValue(value) : utils.applyPrecisionByMinDelta(min, interval, value)
            },
            _generateStartTick: function(tickInterval, options) {
                var that = this,
                    milliseconds = 0,
                    boundedRule = options.min - options.max < 0,
                    startTick = options.min,
                    isDate = utils.isDate(options.min),
                    currentTickInterval = isDate ? utils.convertDateTickIntervalToMilliseconds(tickInterval) : tickInterval,
                    nextTick;
                if (options.axisType === 'logarithmic')
                    startTick = utils.raiseTo(mathFloor(utils.adjustValue(utils.getLog(options.min, options.base)) / currentTickInterval * currentTickInterval), options.base);
                else {
                    startTick = mathFloor(options.min / currentTickInterval) * currentTickInterval;
                    startTick = isDate ? new Date(startTick) : that._adjustNumericTickValue(startTick, currentTickInterval, options.min)
                }
                while (boundedRule === startTick - options.min < 0 && startTick !== options.min) {
                    nextTick = that._nextTick(startTick, tickInterval, options);
                    if (nextTick !== startTick)
                        startTick = nextTick;
                    else
                        return nextTick
                }
                return startTick
            },
            _nextTick: function(tick, tickInterval, options) {
                var nextTick,
                    lgPower,
                    that = this;
                if (options.axisType === 'logarithmic') {
                    lgPower = utils.addInterval(utils.adjustValue(utils.getLog(tick, options.base)), tickInterval, options.min > options.max);
                    nextTick = utils.raiseTo(lgPower, options.base);
                    nextTick = that._adjustNumericTickValue(nextTick, tickInterval, math.min(options.min, options.max))
                }
                else {
                    nextTick = utils.addInterval(tick, tickInterval, options.min > options.max);
                    if (options.dataType === 'numeric')
                        nextTick = that._adjustNumericTickValue(nextTick, tickInterval, options.min);
                    if (options.dataType === 'datetime' && options.setTicksAtUnitBeginning)
                        utils.correctDateWithUnitBeginning(nextTick, tickInterval)
                }
                return nextTick
            },
            _addMinorTicks: function(majorTick1, majorTick2, ticksInfo, options, isReverse) {
                var that = this,
                    i,
                    dataType = options.dataType,
                    businessDelta,
                    minorTicks = [],
                    interval = 0,
                    minorTickIntervalsCount = options.minorTickCount + 1,
                    intervalsCount,
                    tickInterval;
                options.min = majorTick1;
                options.max = majorTick2;
                if (!utils.isDefined(options.tickInterval)) {
                    options.businessDelta = businessDelta = mathAbs(options.max - options.min);
                    options.screenDelta = businessDelta * options.deltaCoef;
                    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 = mathRound(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(options)
                }
                options = $.extend(true, {}, options, {tickInterval: tickInterval});
                minorTicks = that.getTicks(options);
                if (isReverse)
                    minorTicks.reverse();
                if (minorTicks.length > 0)
                    if (mathCeil(mathAbs(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(min, max, screenDelta, ticksInfo, options) {
                var that = this,
                    businessDelta,
                    hasMinorsCount = utils.isDefined(options.minorTickCount);
                $.extend(true, options, {
                    addMinMax: {
                        min: false,
                        max: false
                    },
                    deltaCoef: that._getDeltaCoef(screenDelta, max, min, options.axisType, options.base)
                }, options);
                options.numberMultipliers = hasMinorsCount ? [options.minorTickCount + 1] : options.numberMultipliers;
                options.gridSpacingFactor = hasMinorsCount ? 0 : options.gridSpacingFactor;
                if (!hasMinorsCount && ticksInfo.majorTicks.length > 1) {
                    options.businessDelta = businessDelta = that._getBusinessDelta(options.axisType, ticksInfo.majorTicks[0], ticksInfo.majorTicks[1], options.base);
                    if (that.needTickIntervalCalculation(businessDelta, ticksInfo.minorTickInterval, options.incidentOccured)) {
                        options.screenDelta = businessDelta * options.deltaCoef;
                        ticksInfo.minorTickInterval = core.minorTickIntervalCalculator.getTickInterval(options);
                        if (utils.isNumber(min))
                            options.tickInterval = ticksInfo.minorTickInterval;
                        else
                            options.tickInterval = undefined
                    }
                }
            },
            _getDataType: function(value) {
                return utils.isDate(value) ? 'datetime' : 'numeric'
            },
            _getBusinessDelta: function(type, min, max, base) {
                return type === 'logarithmic' ? mathRound(mathAbs(utils.getLog(min, base) - utils.getLog(max, base))) : mathAbs(min - max)
            },
            _getDeltaCoef: function(screenDelta, max, min, type, base) {
                return screenDelta / this._getBusinessDelta(type, min, max, base)
            },
            _initializeMajorTicksOptions: function(min, max, screenDelta, ticksInfo, options) {
                var businessDelta;
                options.screenDelta = screenDelta;
                $.extend(true, options, {
                    min: min,
                    max: max,
                    screenDelta: screenDelta,
                    isHorizontal: true
                });
                if (utils.isDefined(min) && utils.isDefined(max)) {
                    options.businessDelta = businessDelta = this._getBusinessDelta(options.axisType, min, max, options.base);
                    if (this.needTickIntervalCalculation(businessDelta, ticksInfo.majorTickInterval, options.incidentOccured)) {
                        options.isStartTickGenerated = true;
                        ticksInfo.majorTickInterval = core.tickIntervalCalculator.getTickInterval(options);
                        options.tickInterval = ticksInfo.majorTickInterval
                    }
                }
            },
            _getTextFunc: function(options) {
                return options.getText || function(value) {
                        return value.toString()
                    }
            },
            _generateTicks: function(options) {
                var that = this,
                    ticks = [],
                    tick,
                    boundedRule = options.max - options.min > 0,
                    leftBound,
                    rightBound,
                    tickInterval,
                    isStartTickGenerated = options.isStartTickGenerated,
                    businessDelta,
                    useTicksAutoArrangement = options.useTicksAutoArrangement;
                options.dataType = options.dataType || that._getDataType(options.min);
                options.businessDelta = businessDelta = that._getBusinessDelta(options.axisType, options.min, options.max, options.base);
                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;
                    if (this.needTickIntervalCalculation(businessDelta, tickInterval, options.incidentOccured)) {
                        isStartTickGenerated = utils.isDefined(isStartTickGenerated) ? isStartTickGenerated : true;
                        tickInterval = core.tickIntervalCalculator.getTickInterval(options)
                    }
                    ticks.tickInterval = tickInterval;
                    that.isTestStartTickGenerated = isStartTickGenerated;
                    that.isTestTickInterval = tickInterval;
                    that.testGridSpacingFactor = options.gridSpacingFactor;
                    if (tickInterval && tickInterval.valueOf() !== 0 && options.min.valueOf() !== options.max.valueOf()) {
                        tick = isStartTickGenerated ? that._generateStartTick(tickInterval, options) : options.min;
                        do {
                            ticks.push(tick);
                            tick = that._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);
                        that._correctBoundedTicks(options.min, options.max, ticks, options.addMinMax)
                    }
                    if (options.min.valueOf() === options.max.valueOf()) {
                        tick = options.min;
                        ticks.push(tick)
                    }
                }
                return ticks
            },
            _getAutoArrangementStep: function(ticks, options) {
                var that = this,
                    requiredValuesCount,
                    addedSpacing = options.isHorizontal ? options.textSpacing : 0;
                if (options.getCustomAutoArrangementStep)
                    return options.getCustomAutoArrangementStep(ticks, options);
                if (options.maxDisplayValueSize > 0) {
                    requiredValuesCount = mathFloor((options.screenDelta + options.textSpacing) / (options.maxDisplayValueSize + addedSpacing));
                    return mathCeil((options.ticksCount || ticks.length) / requiredValuesCount)
                }
                return 1
            },
            _getAutoArrangementTicks: function(ticks, options, step) {
                var that = this,
                    resultTicks = ticks,
                    i;
                if (step > 1) {
                    resultTicks = [];
                    for (i = 0; i < ticks.length; i += step)
                        resultTicks.push(ticks[i]);
                    resultTicks.tickInterval = ticks.tickInterval * step
                }
                return resultTicks
            },
            isOverlappedTicks: function(ticks, options) {
                options.maxDisplayValueSize = this._getValueSize(ticks, options);
                return this._getAutoArrangementStep(ticks, options) > 1
            },
            getCorrectedTicks: function(ticks, ticksOptions) {
                var step = Math.ceil(core.tickIntervalCalculator.getTickInterval({
                        screenDelta: ticksOptions.screenDelta * 4,
                        businessDelta: ticks.length,
                        gridSpacingFactor: ticksOptions.gridSpacingFactor,
                        numberMultipliers: ticksOptions.numberMultipliers,
                        dataType: "numeric"
                    })) || ticks.length;
                return this._getAutoArrangementTicks(ticks, ticksOptions, step)
            },
            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('W2003')
                        }
                        else
                            return false
                }
                return true
            },
            getTickIntervals: function(min, max, screenDelta, majorTicksOptions, minorTicksOptions, options) {
                var that = this,
                    i,
                    options = options || {},
                    ticksInfo = {
                        majorTickInterval: majorTicksOptions.tickInterval,
                        minorTickInterval: minorTicksOptions.tickInterval,
                        majorTicks: []
                    };
                majorTicksOptions.base = minorTicksOptions.base = options.base;
                majorTicksOptions.axisType = minorTicksOptions.axisType = options.axisType;
                majorTicksOptions.dataType = minorTicksOptions.dataType = options.dataType;
                that._initializeMajorTicksOptions(min, max, screenDelta, ticksInfo, majorTicksOptions);
                if (utils.isDefined(min) && utils.isDefined(max)) {
                    ticksInfo.majorTicks.push(min);
                    ticksInfo.majorTicks.push(that._nextTick(min, ticksInfo.majorTickInterval, {
                        min: min,
                        max: max,
                        setTicksAtUnitBeginning: majorTicksOptions.setTicksAtUnitBeginning,
                        dataType: options.dataType,
                        axisType: options.axisType,
                        base: options.base
                    }));
                    that._initializeMinorTicksOptions(min, max, screenDelta, ticksInfo, minorTicksOptions)
                }
                return ticksInfo
            },
            getFullTicks: function(min, max, screenDelta, majorTicksOptions, minorTicksOptions, options) {
                var that = this,
                    i,
                    options = options || {},
                    ticksInfo = {
                        customBoundaryTicks: [],
                        fullTicks: [],
                        majorTickInterval: majorTicksOptions.tickInterval,
                        majorTicks: [],
                        minorTickInterval: minorTicksOptions.tickInterval,
                        minorTicks: []
                    };
                majorTicksOptions.base = minorTicksOptions.base = options.base;
                majorTicksOptions.axisType = minorTicksOptions.axisType = options.axisType;
                majorTicksOptions.dataType = minorTicksOptions.dataType = options.dataType || that._getDataType(min);
                that._initializeMajorTicksOptions(min, max, screenDelta, ticksInfo, majorTicksOptions);
                ticksInfo.majorTicks = that.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;
                    that._initializeMinorTicksOptions(min, max, screenDelta, ticksInfo, minorTicksOptions);
                    that._addLeftBoudedTicks(ticksInfo, min, minorTicksOptions);
                    for (i = 0; i < ticksInfo.majorTicks.length - 1; i++) {
                        ticksInfo.fullTicks.push(ticksInfo.majorTicks[i]);
                        that._addMinorTicks(ticksInfo.majorTicks[i], ticksInfo.majorTicks[i + 1], ticksInfo, minorTicksOptions)
                    }
                    that._addRightBoudedTicks(ticksInfo, max, minorTicksOptions)
                }
                return ticksInfo
            },
            getTicks: function(options) {
                var that = this,
                    step,
                    maxDisplayValue,
                    ticks = options.customTicks ? options.customTicks : that._generateTicks(options);
                if (options.useTicksAutoArrangement) {
                    options.maxDisplayValueSize = that._getValueSize(ticks, options);
                    step = that._getAutoArrangementStep(ticks, options);
                    if (step > 1) {
                        if (utils.isDefined(options.tickInterval) || utils.isDefined(options.customTicks)) {
                            utils.isDefined(options.customTicks) && (ticks.tickInterval = options.tickInterval);
                            ticks = that._getAutoArrangementTicks(ticks, options, step)
                        }
                        else
                            ticks = that._generateTicks($.extend({}, options, {gridSpacingFactor: options.maxDisplayValueSize}));
                        ticks.autoArrangementStep = step
                    }
                    that._removeInvalidDatesWithUnitBegining(ticks, options)
                }
                return ticks
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file numericTranslator.js */
    (function($, DX, undefined) {
        var utils = DX.utils,
            isDefined = utils.isDefined,
            getPower = utils.getPower,
            round = Math.round;
        DX.viz.core.numericTranslatorFunctions = {
            translate: function(bp) {
                var that = this,
                    canvasOptions = that._canvasOptions,
                    doubleError = canvasOptions.rangeDoubleError,
                    specialValue = that.translateSpecialCase(bp);
                if (isDefined(specialValue))
                    return specialValue;
                if (isNaN(bp) || bp.valueOf() + doubleError < canvasOptions.rangeMin || bp.valueOf() - doubleError > canvasOptions.rangeMax)
                    return null;
                return round(that._calculateProjection((bp - canvasOptions.rangeMinVisible) * canvasOptions.ratioOfCanvasRange))
            },
            untranslate: function(pos) {
                var canvasOptions = this._canvasOptions,
                    startPoint = canvasOptions.startPoint;
                if (pos < startPoint || pos > canvasOptions.endPoint)
                    return null;
                return this._calculateUnProjection((pos - startPoint) / canvasOptions.ratioOfCanvasRange)
            },
            getInterval: function() {
                return round(this._canvasOptions.ratioOfCanvasRange * (this._businessRange.interval || Math.abs(this._canvasOptions.rangeMax - this._canvasOptions.rangeMin)))
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file datetimeTranslator.js */
    (function($, DX, undefined) {
        var core = DX.viz.core,
            numericTranslator = core.numericTranslatorFunctions;
        core.datetimeTranslatorFunctions = {
            translate: numericTranslator.translate,
            untranslate: function(pos) {
                var result = numericTranslator.untranslate.call(this, pos);
                return result === null ? result : new Date(result)
            },
            getInterval: numericTranslator.getInterval
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file categoryTranslator.js */
    (function($, DX, undefined) {
        var isDefined = DX.utils.isDefined,
            round = Math.round;
        function doubleRound(value) {
            return round(round(value * 10) / 10)
        }
        DX.viz.core.categoryTranslatorFunctions = {
            translate: function(category) {
                var that = this,
                    canvasOptions = that._canvasOptions,
                    categoryRecord = that._categoriesToPoints[category],
                    stickDelta,
                    specialValue = that.translateSpecialCase(category);
                if (isDefined(specialValue))
                    return specialValue;
                if (!categoryRecord)
                    return 0;
                stickDelta = that._businessRange.stick ? categoryRecord.index : categoryRecord.index + 0.5;
                return round(canvasOptions.startPoint + canvasOptions.interval * stickDelta)
            },
            untranslate: function(pos) {
                var that = this,
                    canvasOptions = that._canvasOptions,
                    startPoint = canvasOptions.startPoint,
                    categoriesLength = that._categories.length,
                    result = 0;
                if (pos < startPoint || pos > canvasOptions.endPoint)
                    return null;
                result = doubleRound((pos - startPoint) / canvasOptions.interval + (that._businessRange.stick ? 0.5 : 0) - 0.5);
                if (categoriesLength === result)
                    result--;
                if (canvasOptions.invert)
                    result = categoriesLength - result - 1;
                return that._categories[result]
            },
            getInterval: function() {
                return this._canvasOptions.interval
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file logarithmicTranslator.js */
    (function($, DX, undefined) {
        var core = DX.viz.core,
            numericTranslator = core.numericTranslatorFunctions,
            utils = DX.utils,
            raiseTo = utils.raiseTo,
            getLog = utils.getLog;
        core.logarithmicTranslatorFunctions = {
            translate: function(bp) {
                var that = this,
                    specialValue = that.translateSpecialCase(bp);
                if (utils.isDefined(specialValue))
                    return specialValue;
                return numericTranslator.translate.call(that, getLog(bp, that._businessRange.base))
            },
            untranslate: function(pos) {
                var result = numericTranslator.untranslate.call(this, pos);
                return result === null ? result : raiseTo(result, this._businessRange.base)
            },
            getInterval: numericTranslator.getInterval
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file translator1D.js */
    (function(DX, undefined) {
        var _Number = Number;
        function Translator1D() {
            this.setDomain(arguments[0], arguments[1]).setCodomain(arguments[2], arguments[3])
        }
        Translator1D.prototype = {
            constructor: Translator1D,
            setDomain: function(domain1, domain2) {
                var that = this;
                that._domain1 = _Number(domain1);
                that._domain2 = _Number(domain2);
                that._domainDelta = that._domain2 - that._domain1;
                return that
            },
            setCodomain: function(codomain1, codomain2) {
                var that = this;
                that._codomain1 = _Number(codomain1);
                that._codomain2 = _Number(codomain2);
                that._codomainDelta = that._codomain2 - that._codomain1;
                return that
            },
            getDomain: function() {
                return [this._domain1, this._domain2]
            },
            getCodomain: function() {
                return [this._codomain1, this._codomain2]
            },
            getDomainStart: function() {
                return this._domain1
            },
            getDomainEnd: function() {
                return this._domain2
            },
            getCodomainStart: function() {
                return this._codomain1
            },
            getCodomainEnd: function() {
                return this._codomain2
            },
            getDomainRange: function() {
                return this._domainDelta
            },
            getCodomainRange: function() {
                return this._codomainDelta
            },
            translate: function(value) {
                var ratio = (_Number(value) - this._domain1) / this._domainDelta;
                return 0 <= ratio && ratio <= 1 ? this._codomain1 + ratio * this._codomainDelta : NaN
            },
            adjust: function(value) {
                var ratio = (_Number(value) - this._domain1) / this._domainDelta,
                    result = NaN;
                if (ratio < 0)
                    result = this._domain1;
                else if (ratio > 1)
                    result = this._domain2;
                else if (0 <= ratio && ratio <= 1)
                    result = _Number(value);
                return result
            }
        };
        DX.viz.core.Translator1D = Translator1D
    })(DevExpress);
    /*! Module viz-core, file translator2D.js */
    (function($, DX, undefined) {
        var core = DX.viz.core,
            utils = DX.utils,
            getLog = utils.getLog,
            getPower = utils.getPower,
            raiseTo = utils.raiseTo,
            isDefined = utils.isDefined,
            CANVAS_PROP = ["width", "height", "left", "top", "bottom", "right"],
            NUMBER_EQUALITY_CORRECTION = 1,
            DATETIME_EQUALITY_CORRECTION = 60000;
        var validateCanvas = function(canvas) {
                $.each(CANVAS_PROP, function(_, prop) {
                    canvas[prop] = parseInt(canvas[prop]) || 0
                });
                return canvas
            };
        var raiseToFlooredLog = function(value, base, correction) {
                return raiseTo(Math.floor(getLog(value, base)) + (correction || 0), base)
            };
        var makeCategoriesToPoints = function(categories, invert) {
                var categoriesToPoints = {},
                    category,
                    length = categories.length,
                    i;
                for (i = 0; i < length; i++) {
                    category = categories[i];
                    categoriesToPoints[category] = {
                        name: category,
                        index: invert ? length - 1 - i : i
                    }
                }
                return categoriesToPoints
            };
        var validateBusinessRange = function(businessRange) {
                function validate(valueSelector, baseValueSeletor) {
                    if (!isDefined(businessRange[valueSelector]) && isDefined(businessRange[baseValueSeletor]))
                        businessRange[valueSelector] = businessRange[baseValueSeletor]
                }
                validate("minVisible", "min");
                validate("maxVisible", "max");
                return businessRange
            };
        core.Translator2D = function(businessRange, canvas, options) {
            var that = this;
            that._options = $.extend(that._options || {}, options);
            that._canvas = validateCanvas(canvas);
            that.updateBusinessRange(businessRange)
        };
        $.extend(core.Translator2D.prototype, {
            reinit: function() {
                var that = this,
                    range = that._businessRange,
                    categories = range.categories || [],
                    script = {},
                    canvasOptions = that._prepareCanvasOptions(),
                    interval,
                    correctedCategoriesCount;
                switch (range.axisType) {
                    case"logarithmic":
                        script = core.logarithmicTranslatorFunctions;
                        break;
                    case"discrete":
                        script = core.categoryTranslatorFunctions;
                        that._categories = categories;
                        correctedCategoriesCount = categories.length - (range.stick ? 1 : 0);
                        if (correctedCategoriesCount > 0)
                            interval = canvasOptions.canvasLength / correctedCategoriesCount;
                        else
                            interval = canvasOptions.canvasLength;
                        canvasOptions.interval = interval;
                        that._categoriesToPoints = makeCategoriesToPoints(categories, canvasOptions.invert);
                        break;
                    default:
                        if (range.dataType === "datetime")
                            script = core.datetimeTranslatorFunctions;
                        else
                            script = core.numericTranslatorFunctions
                }
                that.translate = script.translate;
                that.untranslate = script.untranslate;
                that.getInterval = script.getInterval
            },
            _getCanvasBounds: function(range) {
                var min = range.min,
                    max = range.max,
                    minVisible = range.minVisible,
                    maxVisible = range.maxVisible,
                    newMin,
                    newMax,
                    base = range.base,
                    isDateTime = utils.isDate(max) || utils.isDate(min),
                    correction = isDateTime ? DATETIME_EQUALITY_CORRECTION : NUMBER_EQUALITY_CORRECTION;
                if (isDefined(min) && isDefined(max) && min.valueOf() === max.valueOf()) {
                    newMin = min.valueOf() - correction;
                    newMax = max.valueOf() + correction;
                    if (isDateTime) {
                        min = new Date(newMin);
                        max = new Date(newMax)
                    }
                    else {
                        min = min !== 0 ? newMin : 0;
                        max = newMax
                    }
                }
                if (isDefined(minVisible) && isDefined(maxVisible) && minVisible.valueOf() === maxVisible.valueOf()) {
                    newMin = minVisible.valueOf() - correction;
                    newMax = maxVisible.valueOf() + correction;
                    if (isDateTime) {
                        minVisible = newMin < min.valueOf() ? min : new Date(newMin);
                        maxVisible = newMax > max.valueOf() ? max : new Date(newMax)
                    }
                    else {
                        if (minVisible !== 0)
                            minVisible = newMin < min ? min : newMin;
                        maxVisible = newMax > max ? max : newMax
                    }
                }
                if (range.axisType === 'logarithmic') {
                    maxVisible = getLog(maxVisible, base);
                    minVisible = getLog(minVisible, base);
                    min = getLog(min, base);
                    max = getLog(max, base)
                }
                return {
                        base: base,
                        rangeMin: min,
                        rangeMax: max,
                        rangeMinVisible: minVisible,
                        rangeMaxVisible: maxVisible
                    }
            },
            _prepareCanvasOptions: function() {
                var that = this,
                    rangeMin,
                    rangeMax,
                    rangeMinVisible,
                    rangeMaxVisible,
                    businessRange = that._businessRange,
                    canvasOptions = that._canvasOptions = that._getCanvasBounds(businessRange),
                    length;
                if (that._options.direction === "horizontal") {
                    canvasOptions.startPoint = that._canvas.left;
                    length = that._canvas.width;
                    canvasOptions.endPoint = that._canvas.width - that._canvas.right;
                    canvasOptions.invert = businessRange.invert
                }
                else {
                    canvasOptions.startPoint = that._canvas.top;
                    length = that._canvas.height;
                    canvasOptions.endPoint = that._canvas.height - that._canvas.bottom;
                    canvasOptions.invert = !businessRange.invert
                }
                that.canvasLength = canvasOptions.canvasLength = canvasOptions.endPoint - canvasOptions.startPoint;
                canvasOptions.rangeDoubleError = Math.pow(10, getPower(canvasOptions.rangeMax - canvasOptions.rangeMin) - getPower(length) - 2);
                canvasOptions.ratioOfCanvasRange = canvasOptions.canvasLength / (canvasOptions.rangeMaxVisible - canvasOptions.rangeMinVisible);
                return canvasOptions
            },
            updateBusinessRange: function(businessRange) {
                this._businessRange = validateBusinessRange(businessRange);
                this.reinit()
            },
            getBusinessRange: function() {
                return this._businessRange
            },
            getCanvasVisibleArea: function() {
                return {
                        min: this._canvasOptions.startPoint,
                        max: this._canvasOptions.endPoint
                    }
            },
            translateSpecialCase: function(value) {
                var that = this,
                    canvasOptions = that._canvasOptions,
                    startPoint = canvasOptions.startPoint,
                    endPoint = canvasOptions.endPoint,
                    range = that._businessRange,
                    minVisible = range.minVisible,
                    maxVisible = range.maxVisible,
                    invert,
                    result = null;
                switch (value) {
                    case"canvas_position_default":
                        if (minVisible <= 0 && maxVisible >= 0)
                            result = that.translate(0);
                        else {
                            invert = range.invert ^ (minVisible <= 0 && maxVisible <= 0);
                            if (that._options.direction === "horizontal")
                                result = invert ? endPoint : startPoint;
                            else
                                result = invert ? startPoint : endPoint
                        }
                        break;
                    case"canvas_position_left":
                    case"canvas_position_top":
                        result = startPoint;
                        break;
                    case"canvas_position_center":
                    case"canvas_position_middle":
                        result = startPoint + canvasOptions.canvasLength / 2;
                        break;
                    case"canvas_position_right":
                    case"canvas_position_bottom":
                        result = endPoint;
                        break;
                    case"canvas_position_start":
                        result = range.invert ? endPoint : startPoint;
                        break;
                    case"canvas_position_end":
                        result = range.invert ? startPoint : endPoint;
                        break
                }
                return result
            },
            _calculateProjection: function(distance) {
                var canvasOptions = this._canvasOptions;
                return canvasOptions.invert ? canvasOptions.endPoint - distance : canvasOptions.startPoint + distance
            },
            _calculateUnProjection: function(distance) {
                var canvasOptions = this._canvasOptions;
                return canvasOptions.invert ? canvasOptions.rangeMaxVisible.valueOf() - distance : canvasOptions.rangeMinVisible.valueOf() + distance
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file rectangle.js */
    (function(DX, undefined) {
        var isFinite = window.isFinite;
        DX.viz.core.Rectangle = DX.Class.inherit({
            ctor: function(options) {
                var that = this;
                options = options || {};
                that.left = Number(options.left) || 0;
                that.right = Number(options.right) || 0;
                that.top = Number(options.top) || 0;
                that.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 that = this;
                return {
                        left: that.left,
                        top: that.top,
                        right: that.right,
                        bottom: that.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 that = this;
                if (factor > 0)
                    return that.inflate(that.width() * (factor - 1) / 2, that.height() * (factor - 1) / 2);
                return that.clone()
            }
        })
    })(DevExpress);
    /*! Module viz-core, file themes.js */
    (function($, DX, undefined) {
        var viz = DX.viz,
            core = viz.core;
        var currentThemeId = 0;
        var findThemeId = function(themeName) {
                var themeId,
                    themes = viz.themes;
                for (themeId = 0; themeId < themes.length; themeId++)
                    if (themes[themeId].name === themeName)
                        return themeId;
                return -1
            };
        core.findTheme = function(themeName) {
            var themeId = findThemeId(themeName),
                themes = viz.themes;
            if (themeId < 0)
                themeId = currentThemeId;
            return themes[themeId]
        };
        core.currentTheme = function(themeName, colorScheme, version) {
            var themeId = -1,
                themes = viz.themes;
            if (themeName === undefined)
                return themes[currentThemeId].name;
            else {
                if (version && colorScheme)
                    themeId = findThemeId(themeName + ':' + version + '-' + colorScheme);
                if (themeId < 0 && version)
                    themeId = findThemeId(themeName + ':' + version);
                if (colorScheme && themeId < 0)
                    themeId = findThemeId(themeName + '-' + colorScheme);
                if (themeId < 0)
                    themeId = findThemeId(themeName);
                currentThemeId = themeId >= 0 ? themeId : 0
            }
        };
        core.registerTheme = function(theme, basedOnThemeName) {
            var baseTheme,
                extendedTheme,
                themes = viz.themes;
            if (!theme || !theme.name || !core.findTheme(theme.name))
                return;
            baseTheme = core.findTheme(basedOnThemeName);
            if (baseTheme) {
                extendedTheme = $.extend(true, {}, baseTheme, theme);
                themes.push(extendedTheme)
            }
            else
                themes.push(theme)
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file palette.js */
    (function(DX, $, undefined) {
        var _String = window.String,
            _Color = DX.Color,
            _isArray = DX.utils.isArray,
            _isString = DX.utils.isString,
            _extend = $.extend;
        var palettes = {
                'default': {
                    simpleSet: ['#5f8b95', '#ba4d51', '#af8a53', '#955f71', '#859666', '#7e688c'],
                    indicatingSet: ['#a3b97c', '#e1b676', '#ec7f83'],
                    gradientSet: ['#5f8b95', '#ba4d51']
                },
                'harmony light': {
                    simpleSet: ['#fcb65e', '#679ec5', '#ad79ce', '#7abd5c', '#e18e92', '#b6d623', '#b7abea', '#85dbd5'],
                    indicatingSet: ['#b6d623', '#fcb65e', '#e18e92'],
                    gradientSet: ['#7abd5c', '#fcb65e']
                },
                'soft pastel': {
                    simpleSet: ['#60a69f', '#78b6d9', '#6682bb', '#a37182', '#eeba69', '#90ba58', '#456c68', '#7565a4'],
                    indicatingSet: ['#90ba58', '#eeba69', '#a37182'],
                    gradientSet: ['#78b6d9', '#eeba69']
                },
                pastel: {
                    simpleSet: ['#bb7862', '#70b3a1', '#bb626a', '#057d85', '#ab394b', '#dac599', '#153459', '#b1d2c6'],
                    indicatingSet: ['#70b3a1', '#dac599', '#bb626a'],
                    gradientSet: ['#bb7862', '#70b3a1']
                },
                bright: {
                    simpleSet: ['#70c92f', '#f8ca00', '#bd1550', '#e97f02', '#9d419c', '#7e4452', '#9ab57e', '#36a3a6'],
                    indicatingSet: ['#70c92f', '#f8ca00', '#bd1550'],
                    gradientSet: ['#e97f02', '#f8ca00']
                },
                soft: {
                    simpleSet: ['#cbc87b', '#9ab57e', '#e55253', '#7e4452', '#e8c267', '#565077', '#6babac', '#ad6082'],
                    indicatingSet: ['#9ab57e', '#e8c267', '#e55253'],
                    gradientSet: ['#9ab57e', '#e8c267']
                },
                ocean: {
                    simpleSet: ['#75c099', '#acc371', '#378a8a', '#5fa26a', '#064970', '#38c5d2', '#00a7c6', '#6f84bb'],
                    indicatingSet: ['#c8e394', '#7bc59d', '#397c8b'],
                    gradientSet: ['#acc371', '#38c5d2']
                },
                vintage: {
                    simpleSet: ['#dea484', '#efc59c', '#cb715e', '#eb9692', '#a85c4c', '#f2c0b5', '#c96374', '#dd956c'],
                    indicatingSet: ['#ffe5c6', '#f4bb9d', '#e57660'],
                    gradientSet: ['#efc59c', '#cb715e']
                },
                violet: {
                    simpleSet: ['#d1a1d1', '#eeacc5', '#7b5685', '#7e7cad', '#a13d73', '#5b41ab', '#e287e2', '#689cc1'],
                    indicatingSet: ['#d8e2f6', '#d0b2da', '#d56a8a'],
                    gradientSet: ['#eeacc5', '#7b5685']
                }
            };
        var currentPaletteName = 'default';
        function currentPalette(name) {
            if (name === undefined)
                return currentPaletteName;
            else {
                name = String(name).toLowerCase();
                currentPaletteName = name in palettes ? name : 'default'
            }
        }
        function getPalette(palette, parameters) {
            var result;
            if (_isArray(palette))
                result = palette;
            else {
                parameters = parameters || {};
                var type = parameters.type || 'simpleSet';
                if (_isString(palette)) {
                    var name = palette.toLowerCase(),
                        baseContainer = palettes[name],
                        themedContainer = parameters.theme && palettes[name + '_' + _String(parameters.theme).toLowerCase()];
                    result = themedContainer && themedContainer[type] || baseContainer && baseContainer[type]
                }
                if (!result)
                    result = palettes[currentPaletteName][type]
            }
            return result ? result.slice(0) : null
        }
        function registerPalette(name, palette, theme) {
            var item = {};
            if (_isArray(palette))
                item.simpleSet = palette.slice(0);
            else if (palette) {
                item.simpleSet = _isArray(palette.simpleSet) ? palette.simpleSet.slice(0) : undefined;
                item.indicatingSet = _isArray(palette.indicatingSet) ? palette.indicatingSet.slice(0) : undefined;
                item.gradientSet = _isArray(palette.gradientSet) ? palette.gradientSet.slice(0) : undefined
            }
            if (item.simpleSet || item.indicatingSet || item.gradientSet) {
                var paletteName = _String(name).toLowerCase();
                if (theme)
                    paletteName = paletteName + '_' + _String(theme).toLowerCase();
                _extend(palettes[paletteName] = palettes[paletteName] || {}, item)
            }
        }
        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
            }
        }
        function Palette(palette, parameters) {
            parameters = parameters || {};
            this._originalPalette = getPalette(palette, parameters);
            var stepHighlight = parameters ? parameters.stepHighlight || 0 : 0;
            this._paletteSteps = new RingBuf([0, stepHighlight, -stepHighlight]);
            this._resetPalette()
        }
        _extend(Palette.prototype, {
            dispose: function() {
                this._originalPalette = this._palette = this._paletteSteps = null;
                return this
            },
            getNextColor: function() {
                var that = this;
                if (that._currentColor >= that._palette.length)
                    that._resetPalette();
                return that._palette[that._currentColor++]
            },
            _resetPalette: function() {
                var that = this;
                that._currentColor = 0;
                var step = that._paletteSteps.next(),
                    originalPalette = that._originalPalette;
                if (step) {
                    var palette = that._palette = [],
                        i = 0,
                        ii = originalPalette.length;
                    for (; i < ii; ++i)
                        palette[i] = getNewColor(originalPalette[i], step)
                }
                else
                    that._palette = originalPalette.slice(0)
            },
            reset: function() {
                this._paletteSteps.reset();
                this._resetPalette();
                return this
            }
        });
        function getNewColor(currentColor, step) {
            var newColor = new _Color(currentColor).alter(step),
                lightness = getLightness(newColor);
            if (lightness > 200 || lightness < 55)
                newColor = new _Color(currentColor).alter(-step / 2);
            return newColor.toHex()
        }
        function getLightness(color) {
            return color.r * 0.3 + color.g * 0.59 + color.b * 0.11
        }
        function GradientPalette(source, size) {
            var palette = getPalette(source, {type: 'gradientSet'});
            palette = size > 0 ? createGradientColors(palette[0], palette[1], size) : [];
            this.getColor = function(index) {
                return palette[index] || null
            };
            this._DEBUG_source = source;
            this._DEBUG_size = size
        }
        function createGradientColors(start, end, count) {
            var startColor = new _Color(start),
                endColor = new _Color(end);
            if (count === 1)
                return [startColor.blend(endColor, 0.5).toHex()];
            else {
                var list = [],
                    step = 1 / (count - 1),
                    i,
                    ii = count;
                list.push(0);
                for (i = 1; i < ii - 1; ++i)
                    list.push(step * i);
                list.push(1);
                for (i = 0; i < ii; ++i)
                    list[i] = startColor.blend(endColor, list[i]).toHex();
                return list
            }
        }
        _extend(DX.viz.core, {
            registerPalette: registerPalette,
            getPalette: getPalette,
            Palette: Palette,
            GradientPalette: GradientPalette,
            currentPalette: currentPalette
        });
        DX.viz.core._DEBUG_palettes = palettes
    })(DevExpress, jQuery);
    /*! Module viz-core, file baseThemeManager.js */
    (function(DX, $, undefined) {
        var _isString = DX.utils.isString,
            _findTheme = DX.viz.core.findTheme,
            _extend = $.extend,
            _each = $.each;
        DX.viz.core.BaseThemeManager = DX.Class.inherit({
            dispose: function() {
                this._theme = this._font = null;
                return this
            },
            setTheme: function(theme) {
                theme = theme || {};
                var that = this,
                    themeObj = _findTheme(_isString(theme) ? theme : theme.name);
                that._themeName = themeObj.name;
                that._font = _extend({}, themeObj.font, theme.font);
                that._themeSection && _each(that._themeSection.split('.'), function(_, path) {
                    themeObj = _extend(true, {}, themeObj[path], that._IE8 ? themeObj[path + 'IE8'] : {})
                });
                that._theme = _extend(true, {}, themeObj, _isString(theme) ? {} : theme);
                that._initializeTheme();
                return that
            },
            theme: function() {
                return this._theme
            },
            themeName: function() {
                return this._themeName
            },
            _initializeTheme: function(){},
            _initializeFont: function(font) {
                _extend(font, this._font, _extend({}, font))
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz-core, 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 that = 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);
                        that._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)];
                        that._cx = cx + type[0] * tailWidth + (type[0] + type[2]) * cloudWidth / 2;
                        that._cy = cy + type[1] * tailHeight + (type[1] + type[3]) * cloudHeight / 2;
                        that._cloudWidth = cloudWidth;
                        that._cloudHeight = cloudHeight;
                        that._tailLength = ops.tailLength;
                        return that
                    },
                    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-core, 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 that = this,
                        parser,
                        message = 'valueType is unknown.';
                    if (entity)
                        message = 'The type specified as the "valueType" field of the ' + entity + ' configuration object is unknown.';
                    valueType = that.correctValueType(valueType);
                    parser = that._parsers[valueType];
                    if (!parser)
                        this._incidentOccured.call(null, message);
                    return parser || $.noop
                }
            });
        core.ParseUtils = parseUtils
    })(jQuery, DevExpress);
    /*! Module viz-core, file utils.js */
    (function($, DX) {
        var core = DX.viz.core,
            math = Math;
        core.utils = {decreaseGaps: function(object, keys, decrease) {
                var arrayGaps,
                    eachDecrease,
                    middleValue;
                do {
                    arrayGaps = $.map(keys, function(key) {
                        return object[key] ? object[key] : null
                    });
                    middleValue = math.ceil(decrease / arrayGaps.length);
                    arrayGaps.push(middleValue);
                    eachDecrease = math.min.apply(null, arrayGaps);
                    $.each(keys, function(_, key) {
                        if (object[key]) {
                            object[key] -= eachDecrease;
                            decrease -= eachDecrease
                        }
                    })
                } while (decrease > 0 && arrayGaps.length > 1);
                return decrease
            }}
    })(jQuery, DevExpress);
    /*! Module viz-core, file loadIndicator.js */
    (function($, DX) {
        var viz = DX.viz,
            core = viz.core,
            ANIMATION_SETTINGS = {
                easing: 'linear',
                duration: 150
            },
            INVISIBLE_POINT = {
                x: -10000,
                y: -10000
            };
        var applySettings = function(element, settings, animate, complete) {
                var prevAnimation = element.animation;
                if (prevAnimation) {
                    prevAnimation.options.complete = null;
                    prevAnimation.stop()
                }
                if (animate)
                    element.animate(settings, {complete: complete});
                else {
                    element.applySettings(settings);
                    complete && complete()
                }
            };
        core.LoadIndicator = DX.Class.inherit({
            ctor: function(options, widgetContainer) {
                var that = this;
                that._$widgetContainer = $(widgetContainer);
                that._$container = $('<div>', {css: {
                        position: 'relative',
                        height: 0,
                        padding: 0,
                        margin: 0,
                        border: 0
                    }}).appendTo(that._$widgetContainer);
                that._updateContainer();
                that.applyOptions(options);
                that._endLoadingCompleteHandler = function() {
                    that._endLoad = false;
                    that._externalComplete && that._externalComplete();
                    that._externalComplete = null;
                    that._onCompleteAction && that[that._onCompleteAction]();
                    that._onCompleteAction = null
                };
                that._$container.hide()
            },
            _updateRenderer: function(width, height, top) {
                if (this._renderer)
                    this._renderer.recreateCanvas(width, height);
                else if (this._$container.get(0)) {
                    this._renderer = new viz.renderers.Renderer({
                        width: width,
                        height: height,
                        animation: ANIMATION_SETTINGS
                    });
                    this._renderer.draw(this._$container[0])
                }
                this._renderer && this._renderer.getRoot().applySettings({style: {
                        position: 'absolute',
                        top: top,
                        left: 0
                    }});
                return this._renderer
            },
            applyOptions: function(options, width, height) {
                var pane = this._pane;
                if (pane && options) {
                    pane.rect.applySettings({fill: options.backgroundColor});
                    pane.text.applySettings({
                        font: options.font,
                        text: options.text
                    })
                }
                if (this.isShown && (width || height))
                    this._updateContainer(width, height)
            },
            _draw: function() {
                var pane,
                    renderer = this._renderer;
                if (renderer) {
                    pane = this._pane = {};
                    pane.rect = renderer.createRect(0, 0, 0, 0, 0, {opacity: 0}).append();
                    pane.text = renderer.createText('', 0, 0, {
                        align: 'center',
                        translateX: INVISIBLE_POINT.x,
                        translateY: INVISIBLE_POINT.y
                    }).append()
                }
            },
            _updateContainer: function(width, height) {
                var that = this,
                    $widgetContainer = that._$widgetContainer,
                    canvasTop;
                width = width || $widgetContainer.width();
                height = height || $widgetContainer.height();
                if ($widgetContainer.get(0))
                    canvasTop = $widgetContainer.offset().top - that._$container.offset().top;
                else
                    canvasTop = -height;
                that._updateRenderer(width, height, canvasTop);
                if (!that._pane)
                    that._draw();
                else {
                    that._pane.rect.applySettings({
                        width: width,
                        height: height
                    });
                    that._pane.text.move(width / 2, height / 2)
                }
            },
            dispose: function() {
                this._$widgetContainer = null;
                this._$container.remove().detach();
                this._$container = null;
                this._renderer.dispose();
                this._renderer = null;
                this._pane = null
            },
            toForeground: function() {
                this._$container.appendTo(this._$widgetContainer)
            },
            show: function(width, height) {
                if (this._endLoad) {
                    this._onCompleteAction = 'show';
                    return
                }
                this._$container.show();
                this._updateContainer(width, height);
                applySettings(this._pane.rect, {opacity: 0.85}, true);
                this.isShown = true
            },
            endLoading: function(complete, disableAnimation) {
                this._externalComplete = complete;
                if (this._endLoad)
                    return;
                if (this.isShown) {
                    this._endLoad = true;
                    applySettings(this._pane.rect, {opacity: 1}, !disableAnimation, this._endLoadingCompleteHandler)
                }
                else
                    complete && complete()
            },
            hide: function() {
                var that = this;
                if (this._endLoad) {
                    this._onCompleteAction = 'hide';
                    return
                }
                if (this.isShown) {
                    this._pane.text.move(INVISIBLE_POINT.x, INVISIBLE_POINT.y);
                    applySettings(that._pane.rect, {opacity: 0}, true, function() {
                        that._$container.hide()
                    });
                    this.isShown = false
                }
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file tooltip.js */
    (function($, DX, undefined) {
        var ARROW_WIDTH = 20,
            MAX_SHADOW_SIZE = 10,
            formatHelper = DX.formatHelper,
            X_INTERVAL = 15,
            _max = Math.max,
            _round = Math.round,
            _isFunction = DX.utils.isFunction,
            _isDefined = DX.utils.isDefined,
            _extend = $.extend,
            FORMAT_PRECISION = {
                argument: ['argumentFormat', 'argumentPrecision'],
                percent: ['percent', 'percentPrecision'],
                value: ['format', 'precision']
            },
            VISIBLE = {visibility: 'visible'},
            HIDDEN = {visibility: 'hidden'},
            LEFT = 'left',
            RIGHT = 'right';
        DX.viz.core.Tooltip = DX.Class.inherit({
            ctor: function(options, group, renderer) {
                this._state = {};
                this._options = {};
                this._renderer = renderer;
                this._group = group;
                this._cloud = renderer.createArea();
                this._textGroup = renderer.createGroup();
                if (!$.isEmptyObject(options))
                    this.update(options);
                this._createTextContent()
            },
            dispose: function() {
                this._shadow.dispose();
                this._shadow = null;
                this._cloud = null;
                this._text = null;
                this._group = null;
                this._options = null;
                this._renderer = null;
                this._tooltipTextArray = null;
                this._textGroup = null;
                return this
            },
            update: function(options) {
                options = options || {};
                var that = this,
                    group = that._group,
                    shadowOptions = options.shadow || {},
                    shadow = that._shadow = that._shadow || that._renderer.createFilter('shadow').applySettings({
                        width: '200%',
                        height: '200%',
                        color: shadowOptions.color,
                        opacity: shadowOptions.opacity,
                        dx: shadowOptions.offsetX,
                        dy: shadowOptions.offsetY,
                        blur: shadowOptions.blur,
                        x: '-50%',
                        y: '-50%'
                    }),
                    borderSettings = options.border,
                    shapeSettings = _extend({
                        opacity: options.opacity,
                        filter: shadow.append().ref
                    }, borderSettings && borderSettings.visible ? {
                        strokeWidth: borderSettings.width,
                        stroke: borderSettings.color,
                        strokeOpacity: borderSettings.opacity,
                        dashStyle: borderSettings.dashStyle
                    } : {
                        strokeWidth: null,
                        stroke: null
                    }),
                    textSettings = _extend({}, {
                        align: 'center',
                        font: options.font
                    }, options.text);
                that._options = options;
                that.setSize(options.canvasWidth, options.canvasHeight);
                that._customizeTooltip = _isFunction(options.customizeTooltip) ? options.customizeTooltip : null;
                if (!that._customizeTooltip && _isFunction(options.customizeText))
                    that._customizeTooltip = function() {
                        return {text: options.customizeText.apply(this, arguments)}
                    };
                that._cloud.applySettings(shapeSettings).append(group);
                that._text && options.font && that._text.applySettings({font: {size: options.font.size}});
                that._textGroup.applySettings(textSettings).append(group);
                that.hide();
                return that
            },
            formatValue: function(value, specialFormat) {
                var formatObj = FORMAT_PRECISION[specialFormat || 'value'],
                    format = formatObj[0] in this._options ? this._options[formatObj[0]] : specialFormat;
                return formatHelper.format(value, format, this._options[formatObj[1]] || 0)
            },
            prepare: function(formatObject, params, defaultTextValueField) {
                this._state = this._state || {};
                defaultTextValueField = defaultTextValueField || 'valueText';
                var defaultText = formatObject[defaultTextValueField] || '';
                _extend(this._state, params);
                if (this._customizeTooltip) {
                    var customize = this._customizeTooltip.call(formatObject, formatObject);
                    customize = $.isPlainObject(customize) ? customize : {};
                    if ('text' in customize)
                        this._state.text = _isDefined(customize.text) ? String(customize.text) : '';
                    else {
                        if ($.isArray(defaultText)) {
                            this._options._justify = true;
                            this._createTextContent();
                            defaultText = defaultText.join('<br/>')
                        }
                        this._state.text = defaultText
                    }
                    this._state.color = customize.color || this._options.color
                }
                else {
                    this._state.text = defaultText;
                    this._state.color = this._options.color
                }
                if (this._options._justify)
                    this._state.text = this._state.text.split('<br/>');
                if (this._state.visibility == VISIBLE && !!this._state.text)
                    this.show();
                return !!this._state.text
            },
            enabled: function() {
                return !!this._options.enabled
            },
            formatColorTooltip: function(that) {
                return that._customizeTooltip && that._customizeTooltip.call(this, this)
            },
            _getData: function() {
                var that = this,
                    x = that._state.x,
                    y = that._state.y,
                    xt = x,
                    yt = y,
                    align = 'center',
                    points = [],
                    bbox = that._state.textBBox,
                    options = that._options,
                    paddingLeftRight = options.paddingLeftRight,
                    paddingTopBottom = options.paddingTopBottom,
                    arrowLength = options.arrowLength > 0 ? options.arrowLength : 0,
                    horPosition = options.cloudHorizontalPosition,
                    verPosition = options.cloudVerticalPosition,
                    isHorPositionDefined = horPosition !== undefined && horPosition !== null,
                    isVerPositionDefined = verPosition !== undefined && verPosition !== null,
                    cloudWidth = bbox.width + paddingLeftRight * 2,
                    cloudHeight = bbox.height + paddingTopBottom * 2,
                    updatedText;
                updatedText = that._checkWidthText(cloudWidth, cloudHeight);
                if (updatedText) {
                    that._state.textBBox = bbox = updatedText.bbox;
                    cloudWidth = updatedText.cloudWidth;
                    cloudHeight = updatedText.cloudHeight;
                    paddingLeftRight = updatedText.paddingLeftRight;
                    paddingTopBottom = updatedText.paddingTopBottom
                }
                if (isHorPositionDefined ? horPosition === RIGHT : cloudWidth / 2 > x) {
                    points = that._setArrowLeft(cloudWidth, cloudHeight, arrowLength, x, y);
                    align = LEFT;
                    xt += paddingLeftRight
                }
                else if (isHorPositionDefined ? horPosition === LEFT : x + cloudWidth / 2 > that._canvasWidth) {
                    points = that._setArrowRight(cloudWidth, cloudHeight, arrowLength, x, y);
                    align = RIGHT;
                    xt -= paddingLeftRight
                }
                else
                    points = that._setArrowCenter(cloudWidth, cloudHeight, arrowLength, x, y);
                if (isVerPositionDefined ? verPosition === 'top' : cloudHeight + arrowLength < y) {
                    yt -= arrowLength + cloudHeight / 2 - bbox.height / 2 + that._state.offset;
                    that.tooltipInverted = false
                }
                else {
                    yt += arrowLength + cloudHeight / 2 + bbox.height / 2 + that._state.offset;
                    that.tooltipInverted = true
                }
                yt = that._correctYTextContent(yt);
                return {
                        points: points,
                        text: {
                            x: xt,
                            y: yt,
                            align: align
                        }
                    }
            },
            _updateTextContent: function() {
                if (this._options._justify) {
                    this._textGroup.clear();
                    this._calculateTextContent();
                    this._locateTextContent(0, 0, 'center')
                }
                else
                    this._text.updateText(this._state.text);
                this._state.textBBox = this._textGroup.getBBox()
            },
            _correctYTextContent: function(y) {
                var bbox;
                if (this._options._justify) {
                    this._locateTextContent(0, y, 'center');
                    bbox = this._textGroup.getBBox()
                }
                else {
                    this._text.applySettings({y: y});
                    bbox = this._text.getBBox()
                }
                return y - (bbox.y + bbox.height - y)
            },
            _adjustTextContent: function(data) {
                if (this._options._justify)
                    this._locateTextContent(data.text.x, data.text.y, data.text.align);
                else
                    this._text.applySettings({
                        x: data.text.x,
                        y: data.text.y,
                        align: data.text.align
                    })
            },
            _updateTooltip: function() {
                var that = this,
                    box,
                    data,
                    scale;
                data = that._getData();
                that._cloud.applySettings({
                    points: data.points,
                    fill: that._state.color,
                    'class': that._state.className
                });
                that._adjustTextContent(data);
                box = that._group.getBBox();
                if (box.y + box.height > that._canvasHeight) {
                    scale = (that._canvasHeight - box.y) / box.height;
                    that._group.applySettings({
                        scale: scale,
                        translateX: that._state.x * (1 - scale),
                        translateY: that._state.y * (1 - scale)
                    })
                }
                else
                    that._group.applySettings({
                        scale: 1,
                        translateX: 0,
                        translateY: 0
                    })
            },
            _createTextContent: function() {
                var that = this,
                    options = that._options,
                    fontSize;
                that._textGroup.clear();
                that._text = null;
                if (!options._justify) {
                    fontSize = options.font && options.font.size;
                    that._text = that._renderer.createText(undefined, 0, 0, {font: {size: fontSize}}).append(that._textGroup)
                }
            },
            _getTextContentParams: function() {
                var that = this,
                    i,
                    text,
                    textBBox,
                    textArray = that._state.text,
                    textArrayLength = textArray.length,
                    textParams = {
                        width: [],
                        height: []
                    };
                that._tooltipTextArray = [];
                for (i = 0; i < textArrayLength; i++) {
                    text = that._renderer.createText(textArray[i], 0, 0, {}).append(this._textGroup);
                    that._tooltipTextArray.push(text);
                    textBBox = text.getBBox();
                    textParams.width.push(textBBox.width)
                }
                that._lineHeight = -2 * textBBox.y - textBBox.height;
                return textParams
            },
            _locateTextContent: function(x, y, alignment) {
                var that = this,
                    tooltipTextArray = that._tooltipTextArray,
                    textWidth = that._textContentWidth,
                    lineSpacing = that._options.lineSpacing,
                    yDelta = (lineSpacing > 0 ? lineSpacing : 0) + that._lineHeight,
                    leftXCoord,
                    rightXCoord,
                    i,
                    rtl = that._options._rtl;
                if (alignment === LEFT)
                    leftXCoord = x;
                else if (alignment === RIGHT)
                    leftXCoord = x - textWidth;
                else
                    leftXCoord = _round(x - textWidth / 2);
                rightXCoord = leftXCoord + textWidth;
                for (i = tooltipTextArray.length - 1; i >= 0; i -= 2) {
                    tooltipTextArray[i].applySettings({
                        x: !rtl ? rightXCoord : leftXCoord,
                        y: y,
                        align: !rtl ? RIGHT : LEFT
                    });
                    if (tooltipTextArray[i - 1])
                        tooltipTextArray[i - 1].applySettings({
                            x: !rtl ? leftXCoord : rightXCoord,
                            y: y,
                            align: !rtl ? LEFT : RIGHT
                        });
                    y -= yDelta
                }
            },
            _calculateTextContent: function() {
                var that = this,
                    textArray = that._state.text,
                    textArrayLength = textArray.length,
                    textParams,
                    width,
                    stringWidthArray = [],
                    i;
                textParams = that._getTextContentParams();
                for (i = 0; i < textArrayLength; i += 2) {
                    if (textParams.width[i + 1])
                        width = textParams.width[i] + X_INTERVAL + textParams.width[i + 1];
                    else
                        width = textParams.width[i];
                    stringWidthArray.push(width)
                }
                that._textContentWidth = _max.apply(null, stringWidthArray)
            },
            setSize: function(width, height) {
                this._canvasWidth = _isDefined(width) ? width : this._canvasWidth;
                this._canvasHeight = _isDefined(height) ? height : this._canvasHeight;
                return this
            },
            getBBox: function() {
                var that = this,
                    options = that._options,
                    paddingLeftRight = options.paddingLeftRight || 0,
                    paddingTopBottom = options.paddingTopBottom || 0,
                    borderWidth = options.border.visible && options.border.width || 0,
                    tooltipBBox = that._textGroup.getBBox();
                return tooltipBBox.isEmpty ? tooltipBBox : {
                        x: tooltipBBox.x - paddingLeftRight - borderWidth / 2 - MAX_SHADOW_SIZE,
                        y: tooltipBBox.y - paddingTopBottom - borderWidth / 2 - MAX_SHADOW_SIZE,
                        height: tooltipBBox.height + 2 * paddingTopBottom + borderWidth + MAX_SHADOW_SIZE * 2,
                        width: tooltipBBox.width + 2 * paddingLeftRight + borderWidth + MAX_SHADOW_SIZE * 2,
                        isEmpty: false
                    }
            },
            show: function() {
                this._state.visibility = VISIBLE;
                this._updateTextContent();
                this.move(this._state.x, this._state.y, this._state.offset);
                this._cloud.applySettings(VISIBLE);
                this._textGroup.applySettings(VISIBLE);
                return this
            },
            hide: function() {
                this._state.visibility = HIDDEN;
                this._cloud.applySettings(HIDDEN);
                this._textGroup.applySettings(HIDDEN);
                return this
            },
            move: function(x, y, offset) {
                this._state.x = _isDefined(x) ? x : this._state.x || 0;
                this._state.y = _isDefined(y) ? y : this._state.y || 0;
                this._state.offset = _isDefined(offset) ? offset : this._state.offset || 0;
                this._updateTooltip();
                return this
            },
            _setArrowCenter: function(cloudWidth, cloudHeight, arrowLength, x, y) {
                var that = this,
                    position = that._options.cloudVerticalPosition,
                    isPosDefined = position !== undefined && position !== null,
                    verticalInvert = !(isPosDefined ? position === 'top' : cloudHeight + arrowLength < y),
                    x0 = x,
                    y0 = verticalInvert ? y + that._state.offset : y - that._state.offset,
                    x1 = x0 + ARROW_WIDTH / 2,
                    y1 = verticalInvert ? y0 + arrowLength : y0 - arrowLength,
                    x2 = x1 + cloudWidth / 2 - ARROW_WIDTH / 2,
                    y2 = y1,
                    x3 = x2,
                    y3 = verticalInvert ? y2 + cloudHeight : y2 - cloudHeight,
                    x4 = x3 - cloudWidth,
                    y4 = y3,
                    x5 = x4,
                    y5 = verticalInvert ? y4 - cloudHeight : y4 + cloudHeight,
                    x6 = x5 + cloudWidth / 2 - ARROW_WIDTH / 2,
                    y6 = y5;
                return [x0, y0, x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, x6, y6]
            },
            _setArrowLeft: function(cloudWidth, cloudHeight, arrowLength, x, y) {
                var that = this,
                    position = that._options.cloudVerticalPosition,
                    isPosDefined = position !== undefined && position !== null,
                    verticalInvert = !(isPosDefined ? position === 'top' : cloudHeight + arrowLength < y),
                    x0 = x,
                    y0 = verticalInvert ? y + that._state.offset : y - that._state.offset,
                    x1 = x0 + ARROW_WIDTH,
                    y1 = verticalInvert ? y0 + arrowLength : y0 - arrowLength,
                    x2 = x1 + cloudWidth - ARROW_WIDTH,
                    y2 = y1,
                    x3 = x2,
                    y3 = verticalInvert ? y2 + cloudHeight : y2 - cloudHeight,
                    x4 = x3 - cloudWidth,
                    y4 = y3,
                    x5 = x4,
                    y5 = verticalInvert ? y4 - cloudHeight - arrowLength : y4 + cloudHeight + arrowLength;
                return [x0, y0, x1, y1, x2, y2, x3, y3, x4, y4, x5, y5]
            },
            _setArrowRight: function(cloudWidth, cloudHeight, arrowLength, x, y) {
                var that = this,
                    position = that._options.cloudVerticalPosition,
                    isPosDefined = position !== undefined && position !== null,
                    verticalInvert = !(isPosDefined ? position === 'top' : cloudHeight + arrowLength < y),
                    x0 = x,
                    y0 = verticalInvert ? y + that._state.offset : y - that._state.offset,
                    x1 = x0,
                    y1 = verticalInvert ? y0 + arrowLength + cloudHeight : y0 - arrowLength - cloudHeight,
                    x2 = x1 - cloudWidth,
                    y2 = y1,
                    x3 = x2,
                    y3 = verticalInvert ? y2 - cloudHeight : y2 + cloudHeight,
                    x4 = x3 + cloudWidth - ARROW_WIDTH,
                    y4 = y3,
                    x5 = x4 + ARROW_WIDTH,
                    y5 = verticalInvert ? y4 - arrowLength : y4 + arrowLength;
                return [x0, y0, x1, y1, x2, y2, x3, y3, x4, y4, x5, y5]
            },
            _checkWidthText: function(cloudWidth, cloudHeight) {
                if (this._options._justify)
                    return;
                var x = this._state.x,
                    text = this._state.text,
                    index,
                    paddingLeftRight = this._options.paddingLeftRight,
                    paddingTopBottom = this._options.paddingTopBottom,
                    textLength,
                    maxTooltipWidth,
                    remainLength,
                    newIndex,
                    bbox = this._state.textBBox;
                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 = _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._state.text = 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._state.text += text.substr(index + 1, newIndex) + "<br/>";
                            remainLength = text.substr(index + 1 + newIndex).length;
                            index += newIndex + 1
                        }
                        else
                            break
                    }
                    this._state.text += text.substr(index + 1);
                    this._text.updateText(this._state.text);
                    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-core, file legend.js */
    (function(DX, $, undefined) {
        var DEFAULT_MARGIN = 10,
            _math = Math,
            _round = _math.round,
            _ceil = _math.ceil,
            _floor = _math.floor,
            CENTER = 'center',
            RIGHT = 'right',
            LEFT = 'left',
            TOP = 'top',
            BOTTOM = 'bottom',
            HORIZONTAL = 'horizontal',
            VERTICAL = 'vertical',
            INSIDE = 'inside',
            OUTSIDE = 'outside',
            NONE = 'none',
            decreaseGaps = DevExpress.viz.core.utils.decreaseGaps,
            DEFAULT_MARKER_HATCHING_WIDTH = 2,
            DEFAULT_MARKER_HATCHING_STEP = 5;
        function getPatternId(renderer, states, action, color) {
            if (!states)
                return;
            var direction = states[action].hatching.direction,
                hatching,
                colorFromAction = states[action].fill;
            color = colorFromAction === NONE ? color : colorFromAction;
            direction = !direction || direction === NONE ? RIGHT : direction;
            hatching = $.extend({}, states[action].hatching, {
                direction: direction,
                step: DEFAULT_MARKER_HATCHING_STEP,
                width: DEFAULT_MARKER_HATCHING_WIDTH
            });
            return renderer.createPattern(color, hatching).append().id
        }
        DX.viz.core.Legend = DX.Class.inherit({
            ctor: function(data, options, renderer, group) {
                var that = this;
                that._renderer = renderer;
                that._legendGroup = group;
                that._markersPatternsIds = [];
                that._data = data;
                that._init(options)
            },
            _init: function(options) {
                if (!options)
                    return;
                var debug = DX.utils.debug;
                debug.assertParam(options.visible, 'Visibility 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 that = this,
                    i;
                that._parseMargins(options);
                that._parseAlignments(options);
                options.orientation = (options.orientation || '').toLowerCase();
                if (options.orientation !== VERTICAL && options.orientation !== HORIZONTAL) {
                    if (options.horizontalAlignment === CENTER)
                        options.orientation = HORIZONTAL;
                    if (options.horizontalAlignment === RIGHT || options.horizontalAlignment === LEFT)
                        options.orientation = VERTICAL
                }
                if (!options.itemTextPosition)
                    options.itemTextPosition = options.orientation === HORIZONTAL ? BOTTOM : RIGHT;
                else
                    options.itemTextPosition = options.itemTextPosition;
                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
                };
                that._options = options;
                !that._trackerGroup && (that._trackerGroup = that._renderer.createGroup({
                    'class': 'dxc-legend-trackers',
                    stroke: NONE,
                    fill: 'grey',
                    opacity: 0.0001
                }));
                that.__initialized = true
            },
            _parseMargins: function(options) {
                if (options.margin >= 0) {
                    options.margin = Number(options.margin);
                    options.margin = {
                        top: options.margin,
                        bottom: options.margin,
                        left: options.margin,
                        right: options.margin
                    }
                }
                else
                    options.margin = {
                        top: options.margin.top >= 0 ? Number(options.margin.top) : DEFAULT_MARGIN,
                        bottom: options.margin.bottom >= 0 ? Number(options.margin.bottom) : DEFAULT_MARGIN,
                        left: options.margin.left >= 0 ? Number(options.margin.left) : DEFAULT_MARGIN,
                        right: options.margin.right >= 0 ? Number(options.margin.right) : DEFAULT_MARGIN
                    }
            },
            _parseAlignments: function(options) {
                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
                }
            },
            update: function(data, options) {
                this._data = data;
                this.boundingRect = {
                    width: 0,
                    height: 0,
                    x: 0,
                    y: 0
                };
                this._init(options);
                return this
            },
            setSize: function(size) {
                this._size = size;
                return this
            },
            draw: function() {
                if (!this._options)
                    return this;
                var that = this,
                    renderer = that._renderer,
                    options = that._options,
                    items = that._data,
                    itemsLength = items.length,
                    seriesGroups = [],
                    i,
                    label,
                    marker,
                    singleSeriesGroup,
                    trackers = [],
                    insideLegendGroup,
                    markersId = new Array(itemsLength),
                    passedId,
                    border = options.border,
                    borderVisible = border.visible && border.width && border.color && border.color !== NONE,
                    markers = new Array(itemsLength);
                if (!(options.visible && items && itemsLength)) {
                    that._disposeTrackers();
                    return that
                }
                that._cleanLegendGroups();
                insideLegendGroup = that._insideLegendGroup = renderer.createGroup().append(that._legendGroup);
                that._createBackground(borderVisible);
                for (i = 0; i < itemsLength; i++) {
                    singleSeriesGroup = renderer.createGroup({'class': 'dxc-item'}).append(insideLegendGroup);
                    marker = that._createMarker(items[i], singleSeriesGroup, i);
                    passedId = items[i].id;
                    label = that._createLabel(items[i], passedId, singleSeriesGroup);
                    markersId[i] = passedId;
                    that._locateLabelAndMarker(label, marker);
                    markers[i] = marker;
                    trackers.push({
                        rect: renderer.createRect(0, 0, 0, 0, 0, {
                            stroke: NONE,
                            fill: 'grey',
                            opacity: 0.0001,
                            inh: true
                        }),
                        id: passedId
                    });
                    seriesGroups.push(singleSeriesGroup)
                }
                that._seriesGroups = seriesGroups;
                that._trackers = trackers;
                that.drawTrackers();
                that._markers = markers;
                that._markersId = markersId;
                that._locateElements(options);
                return that
            },
            _locateElements: function(options) {
                var that = this,
                    border = options.border,
                    borderVisible = border.visible && border.width && border.color && border.color !== NONE;
                that._moveInInitialValues();
                that._locateRowsColumns(that._seriesGroups, that._trackers, that._data.length, that._background, options);
                if (that._background)
                    that._adjustBackgroundSettings(that._background, borderVisible, options);
                that._setBoundingRect(options)
            },
            _moveInInitialValues: function() {
                var that = this;
                that._legendGroup && that._legendGroup.move(0, 0);
                that._trackerGroup && that._trackerGroup.move(0, 0);
                that._background && that._background.applySettings({
                    x: 0,
                    y: 0,
                    width: 0,
                    height: 0
                })
            },
            _applyMarkerOptions: function(marker, options) {
                if (marker)
                    marker.applySettings(options)
            },
            applySelected: function(id) {
                var index = this._getIndexById(id);
                if (index !== null)
                    this._applyMarkerOptions(this._markers[index], {fill: this._markersPatternsIds[index].selectedPatternId});
                return this
            },
            applyHover: function(id) {
                var index = this._getIndexById(id);
                if (index !== null)
                    this._applyMarkerOptions(this._markers[index], {fill: this._markersPatternsIds[index].hoverPatternId});
                return this
            },
            resetItem: function(id) {
                var index = this._getIndexById(id);
                if (index !== null)
                    this._applyMarkerOptions(this._markers[index], {fill: this._data[index].color || this._data[index].states.normal.fill})
            },
            _getIndexById: function(id) {
                var i,
                    markersId = this._markersId,
                    markersIdLen = markersId.length;
                for (i = 0; i < markersIdLen; i++)
                    if (markersId[i] === id)
                        return i;
                return null
            },
            drawTrackers: function() {
                if (!this._options.visible || !this._insideLegendGroup)
                    return;
                var that = this,
                    trackerGroup = that._trackerGroup.append(that._legendGroup);
                $.each(that._trackers || [], function(i, tracker) {
                    var trackerRect = tracker.rect;
                    trackerRect.data({
                        itemIndex: tracker.id,
                        mode: that._options.hoverMode
                    });
                    trackerRect.append(trackerGroup)
                });
                return that
            },
            _disposeTrackers: function() {
                var that = this;
                $.each(that._trackers || [], function(_, tracker) {
                    tracker.rect.removeData()
                });
                that._trackers = null
            },
            _createMarker: function(data, group, markerIndex) {
                var that = this,
                    renderer = that._renderer,
                    markersPatternsIds = that._markersPatternsIds,
                    size = that._options.markerSize,
                    states = data.states,
                    marker;
                marker = renderer.createRect(0, 0, size, size, 0, {fill: data.color}).append(group);
                markersPatternsIds[markerIndex] = {
                    hoverPatternId: getPatternId(renderer, states, 'hover', data.color),
                    selectedPatternId: getPatternId(renderer, states, 'selection', data.color)
                };
                return marker
            },
            _createLabel: function(data, index, group) {
                var that = this,
                    options = that._options,
                    position = options.itemTextPosition,
                    align = position === TOP || position === BOTTOM ? CENTER : LEFT,
                    text,
                    label,
                    labelFormatObject = {
                        seriesName: data.text,
                        seriesNumber: index,
                        seriesColor: data.color
                    };
                text = that._formatLabel.call(labelFormatObject, options);
                label = that._renderer.createText(text, 0, 0, {
                    font: options.font,
                    align: align
                }).append(group);
                return label
            },
            _cleanLegendGroups: function() {
                var that = this,
                    trackerGroup = that._trackerGroup,
                    legendGroup = that._legendGroup;
                if (legendGroup) {
                    legendGroup.clear();
                    that._insideLegendGroup && that._insideLegendGroup.dispose();
                    that._insideLegendGroup = null
                }
                if (trackerGroup)
                    trackerGroup.clear()
            },
            _createBackground: function(borderVisible) {
                var that = this,
                    options = that._options,
                    isInside = options.position === INSIDE,
                    color = options.backgroundColor,
                    fill = color || (isInside ? options.containerBackgroundColor : NONE);
                if (isInside || color || borderVisible)
                    that._background = that._renderer.createRect(0, 0, 0, 0, 0, {
                        fill: fill,
                        'class': 'dxc-border'
                    }).append(that._insideLegendGroup)
            },
            _formatLabel: function(options) {
                return options.customizeText.call(this, this)
            },
            _locateLabelAndMarker: function(label, marker) {
                var that = this,
                    defaultXMargin = 7,
                    defaultTopMargin = 4,
                    defaultBottomMargin = 2,
                    labelX = 0,
                    labelY = 0,
                    markerX,
                    markerY,
                    labelBox = label.getBBox(),
                    markerWidth = that._options.markerSize,
                    markerHeight = markerWidth,
                    approximateLabelY = markerHeight / 2 - (labelBox.y + labelBox.height / 2),
                    approximateLabelX = markerWidth / 2 - (labelBox.x + labelBox.width / 2);
                switch (that._options.itemTextPosition) {
                    case LEFT:
                        labelY = _round(approximateLabelY);
                        markerX = labelBox.width + defaultXMargin;
                        break;
                    case RIGHT:
                        labelX = markerWidth + defaultXMargin;
                        labelY = _round(approximateLabelY);
                        break;
                    case TOP:
                        labelX = _round(approximateLabelX);
                        markerY = defaultTopMargin;
                        break;
                    case BOTTOM:
                        labelX = _round(approximateLabelX);
                        labelY = markerHeight + defaultBottomMargin - labelBox.y;
                        break
                }
                label.applySettings({
                    x: labelX,
                    y: labelY
                });
                marker.applySettings({
                    x: markerX,
                    y: markerY
                })
            },
            _locateRowsColumns: function(groups, trackers, count, background, options) {
                var that = this,
                    itemTextPosition = options.itemTextPosition,
                    size = that._size,
                    legendBox,
                    rowsColumns = that._getRowsColumns(count),
                    rows = rowsColumns.rows,
                    columns = rowsColumns.columns,
                    margin = options.margin,
                    paddingLeftRight = background ? options.paddingLeftRight : 0,
                    paddingTopBottom = background ? options.paddingTopBottom : 0,
                    placeholderWidth = size.width - margin.left - margin.right - 2 * paddingLeftRight,
                    placeholderHeight = size.height - margin.top - margin.bottom - 2 * paddingTopBottom,
                    rowsColumnsData,
                    condition;
                var moveRowsColumns = function(rows, columns) {
                        rowsColumnsData = that._getDataRowsColumns(groups, columns, rows);
                        that._moveItems(rowsColumnsData, groups, itemTextPosition, trackers, options)
                    };
                moveRowsColumns(rows, columns);
                legendBox = that._insideLegendGroup ? that._insideLegendGroup.getBBox() : {};
                if (rowsColumns.autoEdit)
                    if (rows === 1) {
                        if (legendBox.width > placeholderWidth && columns > 1) {
                            columns = _floor(columns * placeholderWidth / legendBox.width) || 1;
                            columns = validate(columns, count);
                            rows = _ceil(count / columns);
                            moveRowsColumns(rows, columns)
                        }
                    }
                    else if (columns === 1)
                        if (legendBox.height > placeholderHeight && rows > 1) {
                            rows = _floor(rows * placeholderHeight / legendBox.height) || 1;
                            rows = validate(rows, count);
                            columns = _ceil(count / rows);
                            moveRowsColumns(rows, columns)
                        }
                that._rowsCountDrawed = rows;
                that._columnsCountDrawed = columns;
                function validate(rowsOrColumns, count) {
                    if (rowsOrColumns > count || rowsOrColumns < 1)
                        rowsOrColumns = count;
                    return rowsOrColumns
                }
            },
            _moveItems: function(data, seriesGroups, horizontalTextPosition, trackers, options) {
                var that = this,
                    i,
                    j,
                    rows,
                    cols,
                    number,
                    group,
                    box,
                    xShift = 0,
                    yShift = 0,
                    widthColumn,
                    xPadding = options.columnItemSpacing,
                    yPadding = options.rowItemSpacing,
                    equalColumnWidth = options.equalColumnWidth,
                    renderer = that._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 (horizontalTextPosition === RIGHT) {
                            group.move(xShift - box.x, yShift);
                            trackers[number].rect.applySettings({
                                x: xShift - xPadding / 2,
                                y: yShift + box.y - yPadding / 2,
                                height: maxHeightRow + yPadding,
                                width: widthColumn + xPadding
                            })
                        }
                        else if (horizontalTextPosition === LEFT) {
                            group.move(box.x + widthColumn - box.width + xShift - xPadding / 2, yShift);
                            trackers[number].rect.applySettings({
                                x: box.x + widthColumn - box.width + 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].rect.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
                }
            },
            _getDataRowsColumns: function(seriesGroups, cols, rows) {
                var that = this,
                    i,
                    j,
                    options = that._options,
                    equalColumnWidth = options.equalColumnWidth,
                    series = that.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
                    }
            },
            _getRowsColumns: function(count) {
                var that = this,
                    options = that._options,
                    isHorizontal = options.orientation === HORIZONTAL,
                    rows = options.rowCount,
                    onRows = _ceil(count / rows),
                    columns = options.columnCount,
                    onColumns = _ceil(count / columns),
                    autoEdit;
                if (columns && !rows)
                    rows = onColumns;
                else if (!columns && rows)
                    columns = onRows;
                else if (columns && rows) {
                    if (isHorizontal && columns < onRows)
                        columns = onRows;
                    else if (!isHorizontal && rows < onColumns)
                        rows = onColumns
                }
                else {
                    autoEdit = true;
                    if (isHorizontal) {
                        rows = 1;
                        columns = count
                    }
                    else {
                        columns = 1;
                        rows = count
                    }
                }
                return {
                        rows: rows,
                        columns: columns,
                        autoEdit: autoEdit
                    }
            },
            _adjustBackgroundSettings: function(background, borderVisible, options) {
                var that = this,
                    border = options.border,
                    legendBox = that._insideLegendGroup.getBBox(),
                    backgroundSettings = {
                        x: _round(legendBox.x - options.paddingLeftRight),
                        y: _round(legendBox.y - options.paddingTopBottom),
                        width: _round(legendBox.width) + 2 * options.paddingLeftRight,
                        height: _round(legendBox.height) + 2 * options.paddingTopBottom,
                        opacity: options.backgroundOpacity
                    };
                if (borderVisible) {
                    backgroundSettings.strokeWidth = border.width;
                    backgroundSettings.stroke = border.color;
                    backgroundSettings.strokeOpacity = border.opacity;
                    backgroundSettings.dashStyle = border.dashStyle;
                    backgroundSettings.rx = border.cornerRadius || 0;
                    backgroundSettings.ry = border.cornerRadius || 0
                }
                background.applySettings(backgroundSettings)
            },
            _setBoundingRect: function(options) {
                var that = this,
                    box,
                    margin = options.margin;
                if (!that._insideLegendGroup)
                    return;
                box = that._insideLegendGroup.getBBox();
                box.height += margin.top + margin.bottom;
                box.width += margin.left + margin.right;
                box.x -= margin.left;
                box.y -= margin.top;
                that.boundingRect = box
            },
            changeSize: function(size) {
                var that = this,
                    options = $.extend(true, {}, that._options),
                    margin = options.margin;
                if (size.height >= 0) {
                    size.height = decreaseGaps(margin, ["top", "bottom"], size.height);
                    if (options.border.visible)
                        size.height = 2 * decreaseGaps(options, ["paddingTopBottom"], size.height / 2);
                    if (that._rowsCountDrawed - 1)
                        size.height = (that._rowsCountDrawed - 1) * decreaseGaps(options, ["rowItemSpacing"], size.height / (that._rowsCountDrawed - 1))
                }
                if (size.width >= 0) {
                    size.width = decreaseGaps(margin, ["left", "right"], size.width);
                    if (options.border.visible)
                        size.width = 2 * decreaseGaps(options, ["paddingLeftRight"], size.width / 2);
                    if (that._columnsCountDrawed - 1)
                        size.width = (that._columnsCountDrawed - 1) * decreaseGaps(options, ["columnItemSpacing"], size.width / (that._columnsCountDrawed - 1))
                }
                if (that._insideLegendGroup)
                    if (size.height > 0 || size.width > 0) {
                        that._options._incidentOccured("W2104");
                        that._insideLegendGroup.remove();
                        that._insideLegendGroup = null;
                        that._trackerGroup && that._trackerGroup.clear()
                    }
                    else
                        that._locateElements(options)
            },
            getTrackerGroup: function() {
                return this._trackerGroup
            },
            getActionCallback: function(point) {
                var that = this;
                if (that._options.visible)
                    return function(act) {
                            var pointType = point.type,
                                isSeries = pointType ? true : false,
                                seriesType = pointType || point.series.type;
                            if (isSeries || seriesType === 'pie' || seriesType === 'doughnut' || seriesType === 'donut')
                                that[act] && that[act](point.index)
                        };
                else
                    return $.noop
            },
            getLayoutOptions: function() {
                var options = this._options,
                    boundingRect = this._insideLegendGroup ? this.boundingRect : {
                        width: 0,
                        height: 0,
                        x: 0,
                        y: 0
                    };
                if (options) {
                    boundingRect.verticalAlignment = options.verticalAlignment;
                    boundingRect.horizontalAlignment = options.horizontalAlignment;
                    if (options.orientation === 'horizontal')
                        boundingRect.cutLayoutSide = options.verticalAlignment;
                    else
                        boundingRect.cutLayoutSide = options.horizontalAlignment === 'center' ? options.verticalAlignment : options.horizontalAlignment;
                    return boundingRect
                }
                return null
            },
            shift: function(x, y) {
                var that = this,
                    settings = {},
                    box = that.getLayoutOptions();
                settings.translateX = x - box.x;
                settings.translateY = y - box.y;
                that._insideLegendGroup && that._insideLegendGroup.applySettings(settings);
                that._trackerGroup && that._trackerGroup.applySettings(settings)
            },
            getPosition: function() {
                return this._options.position
            },
            dispose: function() {
                var that = this;
                that._disposeTrackers();
                that._legendGroup = null;
                that._trackerGroup = null;
                that._insideLegendGroup = null;
                that._renderer = null;
                that._options = null;
                that._data = null;
                return that
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz-core, file range.js */
    (function($, DX, undefined) {
        var core = DX.viz.core,
            utils = DX.utils,
            isDefinedUtils = utils.isDefined,
            isDateUtils = utils.isDate,
            getLogUtils = utils.getLog,
            raiseToUtils = utils.raiseTo;
        var NUMBER_EQUALITY_CORRECTION = 1,
            DATETIME_EQUALITY_CORRECTION = 60000;
        var minSelector = 'min',
            maxSelector = 'max',
            minVisibleSelector = 'minVisible',
            maxVisibleSelector = 'maxVisible',
            minValueMarginSelector = 'minValueMargin',
            maxValueMarginSelector = 'maxValueMargin',
            categoriesSelector = 'categories',
            keepValueMarginsSelector = 'keepValueMargins',
            baseSelector = 'base',
            axisTypeSelector = 'axisType';
        var raiseToFlooredLog = function(value, base, correction) {
                return raiseToUtils(Math.floor(getLogUtils(value, base)) + (correction || 0), base)
            };
        var otherLessThan = function(thisValue, otherValue) {
                return otherValue < thisValue
            };
        var otherGreaterThan = function(thisValue, otherValue) {
                return otherValue > thisValue
            };
        var compareAndReplace = function(thisValue, otherValue, setValue, compare) {
                var otherValueDefined = isDefinedUtils(otherValue);
                if (isDefinedUtils(thisValue)) {
                    if (otherValueDefined && compare(thisValue, otherValue))
                        setValue(otherValue)
                }
                else if (otherValueDefined)
                    setValue(otherValue)
            };
        var applyMargin = function(value, margin, rangeLength, coef, isDateTime) {
                value = value.valueOf() + coef * rangeLength * margin;
                return isDateTime ? new Date(value) : value
            };
        DX.viz.core.__NUMBER_EQUALITY_CORRECTION = NUMBER_EQUALITY_CORRECTION;
        DX.viz.core.__DATETIME_EQUALITY_CORRECTION = DATETIME_EQUALITY_CORRECTION;
        core.Range = function(range) {
            range && $.extend(this, range)
        };
        $.extend(core.Range.prototype, {
            dispose: function() {
                this[categoriesSelector] = null
            },
            addRange: function(otherRange) {
                var that = this,
                    categories = that[categoriesSelector],
                    categoriesValues,
                    otherCategories = otherRange[categoriesSelector],
                    i,
                    j,
                    length,
                    found;
                var setIndentByPriority = function(prefix) {
                        var prioritySelector = prefix + 'Priority',
                            priorityRelation = (that[prioritySelector] || 0) - (otherRange[prioritySelector] || 0);
                        if ((that[prefix] || 0) < otherRange[prefix] && priorityRelation === 0 || priorityRelation < 0) {
                            that[prefix] = otherRange[prefix];
                            that[prioritySelector] = otherRange[prioritySelector]
                        }
                    };
                var compareAndReplaceByField = function(field, compare) {
                        compareAndReplace(that[field], otherRange[field], function(value) {
                            that[field] = value
                        }, compare)
                    };
                var controlValuesByVisibleBounds = function(valueField, visibleValueField, compare) {
                        compareAndReplace(that[valueField], that[visibleValueField], function(value) {
                            isDefinedUtils(that[valueField]) && (that[valueField] = value)
                        }, compare)
                    };
                var checkField = function(field) {
                        that[field] = that[field] || otherRange[field]
                    };
                if (utils.isDefined(otherRange["stick"]))
                    that["stick"] = otherRange["stick"];
                checkField('invert');
                checkField(axisTypeSelector);
                checkField('dataType');
                checkField(keepValueMarginsSelector);
                if (that[axisTypeSelector] === 'logarithmic')
                    checkField(baseSelector);
                else
                    that[baseSelector] = undefined;
                compareAndReplaceByField(minSelector, otherLessThan);
                compareAndReplaceByField(maxSelector, otherGreaterThan);
                compareAndReplaceByField(minVisibleSelector, otherLessThan);
                compareAndReplaceByField(maxVisibleSelector, otherGreaterThan);
                compareAndReplaceByField('interval', otherLessThan);
                setIndentByPriority(minValueMarginSelector);
                setIndentByPriority(maxValueMarginSelector);
                controlValuesByVisibleBounds(minSelector, minVisibleSelector, otherLessThan);
                controlValuesByVisibleBounds(minSelector, maxVisibleSelector, otherLessThan);
                controlValuesByVisibleBounds(maxSelector, maxVisibleSelector, otherGreaterThan);
                controlValuesByVisibleBounds(maxSelector, minVisibleSelector, otherGreaterThan);
                if (categories === undefined)
                    that[categoriesSelector] = otherCategories;
                else {
                    length = categories.length;
                    if (otherCategories && otherCategories.length)
                        for (i = 0; i < otherCategories.length; i++) {
                            for (j = 0, found = false; j < length; j++)
                                if (categories[j].valueOf() === otherCategories[i].valueOf()) {
                                    found = true;
                                    break
                                }
                            !found && categories.push(otherCategories[i])
                        }
                }
                return this
            },
            isDefined: function() {
                return isDefinedUtils(this[minSelector]) && isDefinedUtils(this[maxSelector]) || isDefinedUtils(this[categoriesSelector])
            },
            setStubData: function(dataType) {
                var that = this,
                    year = (new Date).getYear() - 1,
                    isDate = dataType === 'datetime',
                    isCategories = that.axisType === 'discrete';
                if (isCategories)
                    that.categories = ['0', '1', '2'];
                else {
                    that[minSelector] = isDate ? new Date(year, 0, 1) : 0;
                    that[maxSelector] = isDate ? new Date(year, 11, 31) : 10
                }
                that.stubData = true;
                return that
            },
            applyValueMargins: function() {
                var that = this,
                    base = that[baseSelector],
                    isDateTime = isDateUtils(that[maxSelector]) || isDateUtils(that[minSelector]);
                var applyMarginWithZeroCorrection = function(min, max, rangeLength) {
                        var minValue = that[min],
                            maxValue = that[max],
                            minMargin = that[minValueMarginSelector],
                            maxMargin = that[maxValueMarginSelector],
                            minCorrected = false,
                            maxCorrected = false;
                        if (rangeLength && !isDateTime && !that[keepValueMarginsSelector]) {
                            if (minValue <= 0 && maxValue <= 0 && maxMargin > maxValue / (minValue - maxValue)) {
                                that[max] = 0;
                                maxCorrected = true
                            }
                            if (minValue >= 0 && maxValue >= 0 && minMargin > minValue / (maxValue - minValue)) {
                                that[min] = 0;
                                minCorrected = true
                            }
                        }
                        if (isDefinedUtils(maxValue) && !maxCorrected && maxMargin)
                            that[max] = applyMargin(maxValue, maxMargin, rangeLength, 1, isDateTime);
                        if (isDefinedUtils(minValue) && !minCorrected && minMargin)
                            that[min] = applyMargin(minValue, minMargin, rangeLength, -1, isDateTime)
                    };
                var correctValueByBoundaries = function(visibleSelector, valueSelector) {
                        that[visibleSelector] = isDefinedUtils(that[visibleSelector]) ? that[visibleSelector] : that[valueSelector]
                    };
                var processLogarithmicMinValue = function(valueField) {
                        if (isDefinedUtils(that[valueField])) {
                            var intermediateValue = raiseToFlooredLog(that[valueField], base);
                            if (getLogUtils(that[valueField] / intermediateValue, base) < 0.1 && that.alwaysCorrectMin && !that[keepValueMarginsSelector])
                                that[valueField] = raiseToFlooredLog(that[valueField], base, -1);
                            else if (that.alwaysCorrectMin && !that[keepValueMarginsSelector])
                                that[valueField] = intermediateValue;
                            else if (getLogUtils(that[valueField] / intermediateValue, base) < 0.5)
                                that[valueField] = intermediateValue
                        }
                    };
                var processLogarithmicMaxValue = function(valueField) {
                        if (isDefinedUtils(that[valueField])) {
                            var intermediateValue = raiseToFlooredLog(that[valueField], base);
                            if (getLogUtils(that[valueField] / intermediateValue, base) > 0.5)
                                that[valueField] = raiseToUtils(Math.ceil(getLogUtils(that[valueField], base)), base)
                        }
                    };
                var correctLogVisibleValue = function(visibleValueSelector, valueSelector, compare) {
                        if (!isDefinedUtils(that[visibleValueSelector]) || compare)
                            that[visibleValueSelector] = that[valueSelector]
                    };
                if (that[axisTypeSelector] === 'logarithmic' && that[minSelector] !== that[maxSelector]) {
                    processLogarithmicMinValue(minSelector);
                    processLogarithmicMaxValue(maxSelector);
                    if (that.isValueRange && that[minVisibleSelector] !== that[maxVisibleSelector]) {
                        processLogarithmicMinValue(minVisibleSelector);
                        processLogarithmicMaxValue(maxVisibleSelector)
                    }
                    correctLogVisibleValue(minVisibleSelector, minSelector, that[minVisibleSelector] < that[minSelector]);
                    correctLogVisibleValue(maxVisibleSelector, maxSelector, that[maxVisibleSelector] > that[maxSelector])
                }
                else {
                    correctValueByBoundaries(minVisibleSelector, minSelector);
                    correctValueByBoundaries(maxVisibleSelector, maxSelector);
                    applyMarginWithZeroCorrection(minSelector, maxSelector, that[maxSelector] - that[minSelector]);
                    applyMarginWithZeroCorrection(minVisibleSelector, maxVisibleSelector, that[maxVisibleSelector] - that[minVisibleSelector])
                }
                return this
            },
            correctValueZeroLevel: function() {
                var that = this;
                if (isDateUtils(that[maxSelector]) || isDateUtils(that[minSelector]))
                    return that;
                function setZeroLevel(min, max) {
                    that[min] < 0 && that[max] < 0 && (that[max] = 0);
                    that[min] > 0 && that[max] > 0 && (that[min] = 0)
                }
                setZeroLevel(minSelector, maxSelector);
                setZeroLevel(minVisibleSelector, maxVisibleSelector);
                return that
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file seriesConsts.js */
    (function(DX) {
        DX.viz.core.series = DX.viz.core.series || {};
        DX.viz.core.series.helpers = DX.viz.core.series.helpers || {};
        DX.viz.core.series.helpers.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
            },
            animations: {
                showDuration: {duration: 400},
                hideGroup: {opacity: 0.0001},
                showGroup: {opacity: 1}
            }
        }
    })(DevExpress);
    /*! Module viz-core, file seriesFamily.js */
    (function($, DX, undefined) {
        var utils = DX.utils,
            _round = Math.round,
            _abs = Math.abs,
            _pow = Math.pow;
        DX.viz.core.series.helpers.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 that = this,
                        stubFunction = $.noop;
                    $.extend(that, options);
                    that.type = that.type.toLowerCase();
                    that.series = [];
                    switch (that.type) {
                        case"bar":
                            that.adjustSeriesDimensions = adjustBarSeriesDimensions;
                            that.adjustSeriesValues = stubFunction;
                            that.updateSeriesValues = updateBarSeriesValues;
                            break;
                        case"rangebar":
                            that.adjustSeriesDimensions = adjustBarSeriesDimensions;
                            that.adjustSeriesValues = stubFunction;
                            that.updateSeriesValues = stubFunction;
                            break;
                        case"fullstackedbar":
                            that.fullStacked = true;
                            that.adjustSeriesDimensions = adjustStackedBarSeriesDimensions;
                            that.adjustSeriesValues = adjustStackedSeriesValues;
                            that.updateSeriesValues = updateStackedSeriesValues;
                            break;
                        case"stackedbar":
                            that.adjustSeriesDimensions = adjustStackedBarSeriesDimensions;
                            that.adjustSeriesValues = adjustStackedSeriesValues;
                            that.updateSeriesValues = updateStackedSeriesValues;
                            break;
                        case"fullstackedarea":
                        case"fullstackedline":
                            that.fullStacked = true;
                            that.adjustSeriesDimensions = stubFunction;
                            that.adjustSeriesValues = adjustStackedSeriesValues;
                            that.updateSeriesValues = stubFunction;
                            break;
                        case"stackedarea":
                        case"stackedline":
                            that.adjustSeriesDimensions = stubFunction;
                            that.adjustSeriesValues = adjustStackedSeriesValues;
                            that.updateSeriesValues = stubFunction;
                            break;
                        case"candlestick":
                        case"stock":
                            that.adjustSeriesDimensions = adjustCandlestickSeriesDimensions;
                            that.adjustSeriesValues = stubFunction;
                            that.updateSeriesValues = stubFunction;
                            break;
                        case"bubble":
                            that.adjustSeriesDimensions = adjustBubbleSeriesDimensions;
                            that.adjustSeriesValues = stubFunction;
                            that.updateSeriesValues = stubFunction;
                            break;
                        default:
                            that.adjustSeriesDimensions = stubFunction;
                            that.adjustSeriesValues = stubFunction;
                            that.updateSeriesValues = stubFunction;
                            break
                    }
                };
            var dispose = function() {
                    this.series = null;
                    this.translators = null
                };
            var add = function(series) {
                    var that = this,
                        singleSeries,
                        i;
                    if (!$.isArray(series))
                        series = [series];
                    for (i = 0; i < series.length; i++) {
                        singleSeries = series[i];
                        if (singleSeries.type.toLowerCase() === that.type)
                            that.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;
                    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.valueOf()] = 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 getVisibleSeries = function(that) {
                    return $.map(that.series, function(s) {
                            return s.isVisible() ? s : null
                        })
                };
            var adjustBarSeriesDimensions = function(translators) {
                    var debug = DX.utils.debug;
                    debug.assert(translators, "translator was not passed or empty");
                    var that = this,
                        equalBarWidth = that.equalBarWidth,
                        series = getVisibleSeries(that);
                    adjustBarSeriesDimensionsCore(series, getInterval(that, translators), series.length, equalBarWidth, function(seriesIndex) {
                        return seriesIndex
                    })
                };
            var adjustStackedBarSeriesDimensions = function(translators) {
                    var debug = DX.utils.debug;
                    debug.assert(translators, "translators was not passed or empty");
                    var that = this,
                        interval,
                        series = getVisibleSeries(that),
                        stackIndexes = {},
                        stackCount = 0,
                        equalBarWidth = that.equalBarWidth;
                    $.each(series, function() {
                        var stackName = this.getStackName();
                        if (!stackIndexes.hasOwnProperty(stackName))
                            stackIndexes[stackName] = stackCount++
                    });
                    adjustBarSeriesDimensionsCore(series, getInterval(that, translators), stackCount, equalBarWidth, function(seriesIndex) {
                        return stackIndexes[series[seriesIndex].getStackName()]
                    })
                };
            var adjustStackedSeriesValues = function() {
                    var that = this,
                        series = getVisibleSeries(that),
                        stackKeepers = {
                            positive: {},
                            negative: {}
                        };
                    $.each(series, function(_, singleSeries) {
                        var points = singleSeries.getPoints();
                        $.each(points, function(index, point) {
                            var value = point.initialValue,
                                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;
                                points[index].resetCorrection()
                            }
                        })
                    });
                    setPercentStackedValues(series, stackKeepers, that.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(that, translators, minBarSize) {
                    var rotated = that.rotated,
                        valTranslator = rotated ? translators.x : translators.y,
                        canvas = valTranslator.getCanvasVisibleArea();
                    if (minBarSize)
                        return _abs(valTranslator.untranslate(canvas.min) - valTranslator.untranslate(canvas.min + minBarSize))
                };
            var updateStackedSeriesValues = function(translators) {
                    var that = this,
                        series = getVisibleSeries(that),
                        stackKeepers = {
                            positive: {},
                            negative: {}
                        };
                    $.each(series, function(_, singleSeries) {
                        var points = singleSeries.getPoints(),
                            minBarSize = singleSeries.getOptions().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(that, translators, minBarSize);
                            currentStack = stackKeepers[valueType][stackName] = stackKeepers[valueType][stackName] || {};
                            if (currentStack[argument.valueOf()]) {
                                minValue = utils.isNumber(minValue) ? minValue : 0,
                                pointSize = _abs(minValue - value);
                                if (minShownBusinessValue && pointSize < minShownBusinessValue)
                                    updateValue = minShownBusinessValue;
                                else
                                    updateValue = 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)
                                    updateValue = minShownBusinessValue;
                                else
                                    updateValue = value;
                                points[index].value = updateValue;
                                currentStack[argument.valueOf()] = updateValue
                            }
                        })
                    });
                    if (that.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(translators) {
                    var that = this;
                    $.each(that.series, function(_, singleSeries) {
                        var points = singleSeries.getPoints(),
                            minBarSize = singleSeries.getOptions().minBarSize;
                        $.each(points, function(index, point) {
                            var value = point.value,
                                updateValue,
                                pointSize,
                                minShownBusinessValue;
                            minShownBusinessValue = getMinShownBusinessValue(that, translators, minBarSize);
                            pointSize = _abs(value);
                            if (minShownBusinessValue && pointSize < minShownBusinessValue)
                                updateValue = value >= 0 ? minShownBusinessValue : -minShownBusinessValue;
                            else
                                updateValue = value;
                            points[index].value = updateValue
                        })
                    })
                };
            var adjustCandlestickSeriesDimensions = function(translators) {
                    var debug = DX.utils.debug;
                    debug.assert(translators, "translator was not passed or empty");
                    var that = this,
                        series = getVisibleSeries(that);
                    adjustBarSeriesDimensionsCore(series, getInterval(that, translators), series.length, true, function(seriesIndex) {
                        return seriesIndex
                    })
                };
            var getInterval = function(that, translators) {
                    var argTranslator = !that.rotated ? translators.x : translators.y;
                    return that.interval = argTranslator.getInterval()
                };
            var adjustBubbleSeriesDimensions = function(translators) {
                    var debug = DX.utils.debug;
                    debug.assert(translators, "translator was not passed or empty");
                    var that = this,
                        series = getVisibleSeries(that),
                        points,
                        i,
                        visibleAreaX = translators.x.getCanvasVisibleArea(),
                        visibleAreaY = translators.y.getCanvasVisibleArea(),
                        min = Math.min(visibleAreaX.max - visibleAreaX.min, visibleAreaY.max - visibleAreaY.min),
                        minBubbleArea = _pow(that.minBubbleSize, 2),
                        maxBubbleArea = _pow(min * that.maxBubbleSize, 2),
                        equalBubbleSize = (min * that.maxBubbleSize + that.minBubbleSize) / 2,
                        minPointSize = Infinity,
                        maxPointSize = 0,
                        pointSize,
                        bubbleArea,
                        sizeProportion,
                        sizeDispersion,
                        areaDispersion;
                    for (i = 0; i < series.length; i++) {
                        points = series[i].getPoints();
                        $.each(points, function(_, point) {
                            maxPointSize = maxPointSize > point.size ? maxPointSize : point.size;
                            minPointSize = minPointSize < point.size ? minPointSize : point.size
                        })
                    }
                    sizeDispersion = maxPointSize - minPointSize;
                    areaDispersion = _abs(maxBubbleArea - minBubbleArea);
                    minPointSize = minPointSize < 0 ? 0 : minPointSize;
                    for (i = 0; i < series.length; i++) {
                        points = series[i].getPoints();
                        $.each(points, function(_, point) {
                            if (maxPointSize === minPointSize)
                                pointSize = _round(equalBubbleSize);
                            else {
                                sizeProportion = _abs(point.size - minPointSize) / sizeDispersion;
                                bubbleArea = areaDispersion * sizeProportion + minBubbleArea;
                                pointSize = _round(Math.sqrt(bubbleArea))
                            }
                            point.correctCoordinates(pointSize)
                        })
                    }
                };
            return {
                    ctor: ctor,
                    dispose: dispose,
                    add: add
                }
        }())
    })(jQuery, DevExpress);
    /*! Module viz-core, file baseSeries.js */
    (function($, DX) {
        var viz = DX.viz,
            utils = DX.utils,
            _isDefined = utils.isDefined,
            _each = $.each,
            _extend = $.extend,
            _isEmptyObject = $.isEmptyObject,
            _Event = $.Event,
            _noop = $.noop,
            SELECTED_STATE = 2,
            HOVER_STATE = 1,
            NONE_MODE = "none",
            INCLUDE_POINTS = "includepoints",
            EXLUDE_POINTS = "excludepoints",
            ALL_SERIES_POINTS_MODE = "allseriespoints",
            APPLY_SELECTED = "applySelected",
            APPLY_HOVER = "applyHover",
            getEmptyBusinessRange = function() {
                return {
                        arg: {},
                        val: {}
                    }
            };
        viz.core.series.mixins = {
            chart: {},
            pieChart: {}
        };
        viz.core.series.Series = DX.Class.inherit({
            ctor: function(renderer, options) {
                this.fullState = 0;
                this._renderer = renderer;
                this._group = renderer.createGroup({"class": "dxc-series"});
                this.updateOptions(options)
            },
            update: function(data, options) {
                this.updateOptions(options);
                this.updateData(data)
            },
            _createLegendState: function(styleOptions, defaultColor) {
                return {
                        fill: styleOptions.color || defaultColor,
                        hatching: styleOptions.hatching
                    }
            },
            getLegendStyles: function() {
                return this._styles.legendStyles
            },
            _createStyles: function(options) {
                var mainSeriesColor = options.mainSeriesColor,
                    specialMainColor = this._getSpecialColor(mainSeriesColor);
                this._styles = {
                    normal: this._parseStyle(options, mainSeriesColor, mainSeriesColor),
                    hover: this._parseStyle(options.hoverStyle || {}, specialMainColor, mainSeriesColor),
                    selection: this._parseStyle(options.selectionStyle || {}, specialMainColor, mainSeriesColor),
                    legendStyles: {
                        normal: this._createLegendState(options, mainSeriesColor),
                        hover: this._createLegendState(options.hoverStyle || {}, specialMainColor),
                        selection: this._createLegendState(options.selectionStyle || {}, specialMainColor)
                    }
                }
            },
            setAdjustSeriesLabels: function(adjustSeriesLabels) {
                _each(this._points || [], function(_, point) {
                    point.setAdjustSeriesLabels(adjustSeriesLabels)
                })
            },
            setClippingParams: function(id, forceClipping) {
                this._paneClipRectID = id;
                this._forceClipping = forceClipping
            },
            getTagField: function() {
                return this._options.tagField || "tag"
            },
            getValueFields: _noop,
            getArgumentField: _noop,
            getPoints: function() {
                return this._points
            },
            _createPoint: function(data, pointsArray, index) {
                data.index = index;
                if (this._checkData(data)) {
                    var point = pointsArray[index],
                        options = this._customizePoint(data) || this._getCreatingPointOptions();
                    if (point)
                        point.update(data, options);
                    else {
                        point = viz.core.CoreFactory.createPoint(data, options);
                        pointsArray.push(point)
                    }
                    this.pointsByArgument[point.argument.valueOf()] = this.pointsByArgument[point.argument.valueOf()] || point;
                    return true
                }
            },
            getRangeData: function(zoomArgs, calcIntervalFunction) {
                return this._visible ? _extend(true, {}, this._getRangeData(zoomArgs, calcIntervalFunction)) : getEmptyBusinessRange()
            },
            _deleteElementsGroup: function() {
                if (this._elementsGroup) {
                    this._elementsGroup.detach();
                    this._elementsGroup = null
                }
            },
            _deleteBordersGroup: function() {
                if (this._bordersGroup) {
                    this._bordersGroup.detach();
                    this._bordersGroup = null
                }
            },
            _saveOldAnimationMethods: function() {
                this._oldClearingAnimation = this._clearingAnimation;
                this._oldUpdateElement = this._updateElement
            },
            _deleteOldAnimationMethods: function() {
                this._oldClearingAnimation = null;
                this._oldUpdateElement = null
            },
            updateOptions: function(newOptions) {
                var that = this,
                    widgetType = newOptions.widgetType,
                    oldType = that.type,
                    newType = newOptions.type;
                that.type = newType && newType.toString().toLowerCase();
                if (!that._checkType(widgetType)) {
                    that.dispose();
                    that.isUpdated = false;
                    return
                }
                if (oldType !== that.type) {
                    that._firstDrawing = true;
                    that._saveOldAnimationMethods();
                    that._resetType(oldType, widgetType);
                    that._setType(that.type, widgetType)
                }
                that._options = newOptions;
                that._pointOptions = null;
                that._deletePatterns();
                that._patterns = [];
                that.name = newOptions.name;
                that.pane = newOptions.pane;
                that.axis = newOptions.axis;
                that.tag = newOptions.tag;
                that._createStyles(newOptions);
                that._updateOptions(newOptions);
                that._visible = newOptions.visible;
                that.isUpdated = true
            },
            _disposePoints: function(points) {
                $.each(points || [], function(_, p) {
                    p.dispose()
                })
            },
            _correctPointsLength: function(length, points) {
                this._disposePoints(this._oldPoints);
                this._oldPoints = points.splice(length, points.length)
            },
            _getTicksForAggregation: function(min, max, screenDelta, pointSize) {
                return viz.core.tickProvider.getTicks({
                        min: min,
                        max: max,
                        screenDelta: screenDelta,
                        gridSpacingFactor: pointSize
                    })
            },
            updateDataType: function(settings) {
                var that = this;
                that.argumentType = settings.argumentType;
                that.valueType = settings.valueType;
                that.argumentAxisType = settings.argumentAxisType;
                that.valueAxisType = settings.valueAxisType
            },
            getValueCategories: function() {
                return this._options.valueCategories || []
            },
            getOptions: function() {
                return this._options
            },
            getArgumentCategories: function() {
                return this._options.argumentCategories || []
            },
            updateData: function(data) {
                var that = this,
                    points,
                    lastPointIndex = 0,
                    options = that._options,
                    pointData;
                that.pointsByArgument = {};
                points = that._originalPoints || [];
                that._rangeData = getEmptyBusinessRange();
                if (data && data.length)
                    that._canRenderCompleteHandle = true;
                that._beginUpdateData();
                _each(data, function(index, dataItem) {
                    pointData = that._getPointData(dataItem, options);
                    if (that._createPoint(pointData, points, lastPointIndex)) {
                        that._processRange(points[lastPointIndex], lastPointIndex > 0 ? points[lastPointIndex - 1] : null);
                        lastPointIndex++
                    }
                });
                that._points = that._originalPoints = points;
                that._correctPointsLength(lastPointIndex, points);
                that._endUpdateData()
            },
            getTeamplatedFields: function() {
                var that = this,
                    fields = that.getValueFields(),
                    teampleteFields = [];
                fields.push(that.getTagField());
                _each(fields, function(_, field) {
                    var fieldsObject = {};
                    fieldsObject.teamplateField = field + that.name;
                    fieldsObject.originalField = field;
                    teampleteFields.push(fieldsObject)
                });
                return teampleteFields
            },
            resamplePoints: function(translators, min, max) {
                var that = this,
                    originalPoints = that.getAllPoints(),
                    argTranslator = that._options.rotated ? translators.y : translators.x,
                    minI,
                    maxI,
                    sizePoint,
                    ticks;
                if (originalPoints.length) {
                    _each(originalPoints, function(i, point) {
                        minI = point.argument - min <= 0 ? i : minI;
                        if (!maxI)
                            maxI = point.argument - max > 0 ? i : null
                    });
                    minI = minI ? minI : 1;
                    maxI = utils.isDefined(maxI) ? maxI : originalPoints.length - 1;
                    min = originalPoints[minI - 1].argument;
                    max = originalPoints[maxI].argument;
                    sizePoint = that._getPointSize();
                    if (that.argumentAxisType !== "discrete" && that.valueAxisType !== "discrete")
                        ticks = that._getTicksForAggregation(min, max, argTranslator.canvasLength, sizePoint);
                    else
                        ticks = argTranslator.canvasLength / sizePoint;
                    that._points = that._resample(ticks, ticks.tickInterval)
                }
            },
            _removeOldSegments: function(startIndex) {
                var that = this;
                _each(that._graphics.splice(startIndex, that._graphics.length) || [], function(_, elem) {
                    that._removeElement(elem)
                });
                if (that._trackers)
                    _each(that._trackers.splice(startIndex, that._trackers.length) || [], function(_, elem) {
                        elem.remove()
                    })
            },
            draw: function(translators, animationEnabled, hideLayoutLabels, legendCallback) {
                var that = this;
                if (that._oldClearingAnimation && animationEnabled && that._firstDrawing) {
                    var drawComplete = function() {
                            that._draw(translators, true, hideLayoutLabels)
                        };
                    that._oldClearingAnimation(translators, drawComplete)
                }
                else
                    that._draw(translators, animationEnabled, hideLayoutLabels, legendCallback)
            },
            _clearSeries: function() {
                this._deleteElementsGroup();
                this._deleteBordersGroup();
                this._deleteTrackers();
                this._graphics = [];
                this._trackers = []
            },
            _draw: function(translators, animationEnabled, hideLayoutLabels, legendCallback) {
                var that = this,
                    points = that._points || [],
                    segment = [],
                    segmentCount = 0,
                    firstDrawing = that._firstDrawing,
                    markersGroup,
                    labelsGroup;
                that._graphics = that._graphics || [],
                that._graphics = that._graphics || [];
                that._prepareSeriesToDrawing();
                if (!that._visible) {
                    animationEnabled = false;
                    this._group.detach();
                    return
                }
                else
                    that._group.append(that._options.seriesGroup);
                that.translators = translators;
                that._createGroups(animationEnabled, undefined, firstDrawing);
                that._segments = [];
                markersGroup = that._markersGroup;
                labelsGroup = that._labelsGroup;
                that._drawedPoints = [];
                that._firstDrawing = points.length ? false : true;
                _each(this._patterns || [], function(_, pattern) {
                    pattern.append()
                });
                _each(points, function(i, p) {
                    p.translate(translators);
                    if (p.hasValue()) {
                        that._drawPoint(p, markersGroup, labelsGroup, animationEnabled, firstDrawing);
                        segment.push(p)
                    }
                    else if (segment.length) {
                        that._drawSegment(segment, animationEnabled, segmentCount++);
                        segment = []
                    }
                });
                segment.length && that._drawSegment(segment, animationEnabled, segmentCount++);
                that._removeOldSegments(segmentCount);
                that._defaultSegments = that._generateDefaultSegments();
                that._adjustLabels(firstDrawing);
                hideLayoutLabels && that.hideLabels();
                animationEnabled && that._animate(firstDrawing);
                if (that.isSelected())
                    that._changeStyle(legendCallback, APPLY_SELECTED);
                else if (this.isHovered())
                    this._changeStyle(legendCallback, APPLY_HOVER)
            },
            drawTrackers: function() {
                var that = this,
                    trackers = that._trackers = that._trackers || [],
                    trackersGroup = that._trackersGroup = that._trackersGroup || that._renderer.createGroup(),
                    markerTrackerGroup = that._markerTrackerGroup = that._markerTrackerGroup || that._renderer.createGroup();
                if (!that.isVisible()) {
                    trackersGroup.detach();
                    markerTrackerGroup.detach();
                    return
                }
                else {
                    trackersGroup.append(that._options.trackersGroup);
                    markerTrackerGroup.append(that._options.markerTrackerGroup)
                }
                _each(that._segments || [], function(i, segment) {
                    if (!trackers[i]) {
                        trackers[i] = that._drawTrackerElement(segment).append(trackersGroup);
                        trackers[i].data({series: that})
                    }
                    else
                        that._updateTrackerElement(segment, trackers[i])
                });
                _each(that.getVisiblePoints(), function(_, p) {
                    p.drawTracker(that._renderer, markerTrackerGroup)
                });
                that._applyTrackersClippings()
            },
            _checkType: function(widgetType) {
                return !!viz.core.series.mixins[widgetType][this.type]
            },
            _resetType: function(seriesType, widgetType) {
                var that = this;
                if (seriesType)
                    _each(viz.core.series.mixins[widgetType][seriesType], function(methodName) {
                        delete that[methodName]
                    })
            },
            _setType: function(seriesType, widgetType) {
                var that = this;
                _each(viz.core.series.mixins[widgetType][seriesType], function(methodName, method) {
                    that[methodName] = method
                })
            },
            _setSelectedState: function(state, mode, legendCallback) {
                this.lastSelectionMode = mode = (mode || this._options.selectionMode).toLowerCase();
                if (state && !this.isSelected()) {
                    this.fullState = this.fullState | SELECTED_STATE;
                    this._changeStyle(legendCallback, APPLY_SELECTED)
                }
                else if (!state && this.isSelected()) {
                    this.fullState = this.fullState & ~SELECTED_STATE;
                    if (this.isHovered())
                        this._changeStyle(legendCallback, APPLY_HOVER);
                    else
                        this._changeStyle(legendCallback, "resetItem")
                }
            },
            _setHoverState: function(state, mode, legendCallback) {
                this.lastHoverMode = mode = (mode || this._options.hoverMode).toLowerCase();
                if (state && !this.isHovered()) {
                    this.fullState = this.fullState | HOVER_STATE;
                    !this.isSelected() && this._changeStyle(legendCallback, APPLY_HOVER)
                }
                else if (!state && this.isHovered()) {
                    this.fullState = this.fullState & ~HOVER_STATE;
                    !this.isSelected() && this._changeStyle(legendCallback, "resetItem")
                }
            },
            setHoverState: function(mode, legendCallback) {
                this._setHoverState(true, mode, legendCallback)
            },
            releaseHoverState: function(mode, legendCallback) {
                this._setHoverState(false, mode, legendCallback)
            },
            setSelectedState: function(mode, legendCallback) {
                this._setSelectedState(true, mode, legendCallback)
            },
            releaseSelectedState: function(mode, legendCallback) {
                this._setSelectedState(false, mode, legendCallback)
            },
            isFullStackedSeries: function() {
                return this.type.indexOf("fullstacked") === 0
            },
            isStackedSeries: function() {
                return this.type.indexOf("stacked") === 0
            },
            isFinancialSeries: function() {
                return this.type === "stock" || this.type === "candlestick"
            },
            _changeStyle: function(legendCallBack, legendAction) {
                var style = this._calcStyle(),
                    pointStyle;
                if (style.mode === NONE_MODE)
                    return;
                legendCallBack && legendCallBack(legendAction);
                if (style.mode === INCLUDE_POINTS || style.mode === ALL_SERIES_POINTS_MODE) {
                    pointStyle = style.pointStyle;
                    _each(this._points || [], function(_, p) {
                        !p.isSelected() && p.applyStyle(pointStyle)
                    })
                }
                this._applyStyle(style.series)
            },
            _calcStyle: function() {
                var styles = this._styles,
                    isHoverIncludeModeAndSeriesExcludeMode = false,
                    result;
                switch (this.fullState & 3) {
                    case 0:
                        result = {
                            pointStyle: "normal",
                            mode: INCLUDE_POINTS,
                            series: styles.normal
                        };
                        break;
                    case 1:
                        result = {
                            pointStyle: "hover",
                            mode: this.lastHoverMode,
                            series: styles.hover
                        };
                        break;
                    case 2:
                        result = {
                            pointStyle: "selection",
                            mode: this.lastSelectionMode,
                            series: styles.selection
                        };
                        break;
                    case 3:
                        isHoverIncludeModeAndSeriesExcludeMode = this.lastSelectionMode === EXLUDE_POINTS && (this.lastHoverMode === INCLUDE_POINTS || this.lastHoverMode === ALL_SERIES_POINTS_MODE);
                        result = {
                            pointStyle: isHoverIncludeModeAndSeriesExcludeMode ? "normal" : "selection",
                            mode: isHoverIncludeModeAndSeriesExcludeMode ? INCLUDE_POINTS : this.lastSelectionMode,
                            series: styles.selection
                        }
                }
                return result
            },
            _getMainAxisName: function() {
                return this._options.rotated ? "X" : "Y"
            },
            areLabelsVisible: function() {
                return !_isDefined(this._options.maxLabelCount) || this._points.length <= this._options.maxLabelCount
            },
            getLabelVisibility: function() {
                return this.areLabelsVisible() && this._options.label && this._options.label.visible
            },
            _customizePoint: function(pointData) {
                var that = this,
                    options = that._options,
                    customizePoint = that._options.customizePoint,
                    customizeObject,
                    pointOptions,
                    customLabelOptions,
                    customOptions,
                    customizeLabel = that._options.customizeLabel,
                    useLabelCustomOptions,
                    usePointCustomOptions;
                if (customizeLabel && customizeLabel.call) {
                    customizeObject = _extend({
                        seriesName: that.name,
                        series: that
                    }, pointData);
                    customLabelOptions = customizeLabel.call(customizeObject, customizeObject);
                    useLabelCustomOptions = customLabelOptions && !_isEmptyObject(customLabelOptions);
                    customLabelOptions = useLabelCustomOptions ? _extend(true, {}, options.label, customLabelOptions) : null
                }
                if (customizePoint && customizePoint.call) {
                    customizeObject = customizeObject || _extend({
                        seriesName: that.name,
                        series: that
                    }, pointData);
                    customOptions = customizePoint.call(customizeObject, customizeObject);
                    usePointCustomOptions = customOptions && !_isEmptyObject(customOptions)
                }
                if (useLabelCustomOptions || usePointCustomOptions) {
                    pointOptions = that._parsePointOptions(that._preparePointOptions(customOptions), customLabelOptions || options.label);
                    pointOptions.styles.useLabelCustomOptions = useLabelCustomOptions;
                    pointOptions.styles.usePointCustomOptions = usePointCustomOptions
                }
                return pointOptions
            },
            _getLabelOptions: function(labelOptions, defaultColor) {
                var opt = labelOptions || {},
                    labelFont = opt.font || {},
                    labelBorder = opt.border || {},
                    labelConnector = opt.connector || {},
                    labelAttributes = {
                        align: opt.alignment,
                        font: {
                            color: opt.backgroundColor === "none" && labelFont.color.toLowerCase() === "#ffffff" && opt.position !== "inside" ? defaultColor : labelFont.color,
                            family: labelFont.family,
                            weight: labelFont.weight,
                            size: labelFont.size,
                            opacity: labelFont.opacity
                        },
                        style: opt.style
                    },
                    backgroundAttr = {
                        fill: opt.backgroundColor || defaultColor,
                        strokeWidth: labelBorder.visible ? labelBorder.width || 0 : 0,
                        stroke: labelBorder.visible && labelBorder.width ? labelBorder.color : "none",
                        dashStyle: labelBorder.dashStyle
                    },
                    connectorAttr = {
                        stroke: labelConnector.visible && labelConnector.width ? labelConnector.color || defaultColor : "none",
                        strokeWidth: labelConnector.visible ? labelConnector.width || 0 : 0
                    };
                return {
                        format: opt.format,
                        argumentFormat: opt.argumentFormat,
                        precision: opt.precision,
                        argumentPrecision: opt.argumentPrecision,
                        percentPrecision: opt.percentPrecision,
                        customizeText: $.isFunction(opt.customizeText) ? opt.customizeText : undefined,
                        attributes: labelAttributes,
                        visible: labelFont.size !== 0 ? opt.visible : false,
                        showForZeroValues: opt.showForZeroValues,
                        horizontalOffset: opt.horizontalOffset,
                        verticalOffset: opt.verticalOffset,
                        radialOffset: opt.radialOffset,
                        background: backgroundAttr,
                        position: opt.position,
                        connector: connectorAttr,
                        rotationAngle: opt.rotationAngle,
                        resolveLabelsOverlapping: this._options.resolveLabelsOverlapping
                    }
            },
            show: function() {
                if (!this._visible) {
                    this._visible = true;
                    this.hidePointTooltip();
                    this._options.visibilityChanged()
                }
            },
            hide: function() {
                if (this._visible) {
                    this._visible = false;
                    this.hidePointTooltip();
                    this._options.visibilityChanged()
                }
            },
            hideLabels: function() {
                _each(this._points, function(_, point) {
                    point._label.hide()
                })
            },
            _parsePointOptions: function(pointOptions, labelOptions) {
                var options = this._options,
                    styles = this._createPointStyles(pointOptions),
                    parsedOptions;
                parsedOptions = _extend(true, {}, pointOptions, {
                    type: options.type,
                    tag: this.tag,
                    rotated: options.rotated,
                    series: this,
                    styles: styles,
                    visibilityChanged: options.visibilityChanged
                });
                parsedOptions.label = this._getLabelOptions(labelOptions, styles.normal.fill);
                return parsedOptions
            },
            _resample: function(ticks, ticksInterval) {
                var that = this,
                    fusPoints = [],
                    arrayFusPoints,
                    nowIndexTicks = 0,
                    lastPointIndex = 0,
                    originalPoints = that.getAllPoints();
                if (that.argumentAxisType === "discrete" || that.valueAxisType === "discrete") {
                    ticksInterval = originalPoints.length / ticks;
                    arrayFusPoints = $.map(originalPoints, function(point, index) {
                        if (Math.floor(nowIndexTicks) <= index) {
                            nowIndexTicks += ticksInterval;
                            return point
                        }
                        point.setInvisibility();
                        return null
                    });
                    return arrayFusPoints
                }
                that._aggregatedPoints = that._aggregatedPoints || [];
                _each(originalPoints, function(_, point) {
                    switch (that._isInInterval(point.argument, ticks, nowIndexTicks, ticksInterval)) {
                        case true:
                            fusPoints.push(point);
                            break;
                        case"nextInterval":
                            var pointData = that._fusionPoints(fusPoints, ticks[nowIndexTicks], nowIndexTicks);
                            while (that._isInInterval(point.argument, ticks, nowIndexTicks, ticksInterval) === "nextInterval")
                                nowIndexTicks++;
                            fusPoints = [];
                            that._isInInterval(point.argument, ticks, nowIndexTicks, ticksInterval) === true && fusPoints.push(point);
                            if (that._createPoint(pointData, that._aggregatedPoints, lastPointIndex))
                                lastPointIndex++
                    }
                });
                if (fusPoints.length) {
                    var pointData = that._fusionPoints(fusPoints, ticks[nowIndexTicks], nowIndexTicks);
                    if (that._createPoint(pointData, that._aggregatedPoints, lastPointIndex))
                        lastPointIndex++
                }
                that._correctPointsLength(lastPointIndex, that._aggregatedPoints);
                that._endUpdateData();
                return that._aggregatedPoints
            },
            _isInInterval: function(argument, ticks, nowIndexTicks, ticksInterval) {
                var minTick = ticks[nowIndexTicks],
                    maxTick = ticks[nowIndexTicks + 1],
                    sumMinTickTicksInterval;
                ticksInterval = $.isNumeric(ticksInterval) ? ticksInterval : utils.convertDateTickIntervalToMilliseconds(ticksInterval);
                sumMinTickTicksInterval = utils.isDate(minTick) ? new Date(minTick.getTime() + ticksInterval) : minTick + ticksInterval;
                if (argument >= minTick && argument < sumMinTickTicksInterval)
                    return true;
                if (argument < minTick || maxTick === undefined)
                    return false;
                return "nextInterval"
            },
            canRenderCompleteHandle: function() {
                var result = this._canRenderCompleteHandle;
                delete this._canRenderCompleteHandle;
                return !!result
            },
            isHovered: function() {
                return !!(this.fullState & 1)
            },
            isSelected: function() {
                return !!(this.fullState & 2)
            },
            isVisible: function() {
                return this._visible
            },
            getAllPoints: function() {
                return (this._originalPoints || []).slice()
            },
            getPointByPos: function(pos) {
                return (this._points || [])[pos]
            },
            getVisiblePoints: function() {
                return (this._drawedPoints || []).slice()
            },
            setPointHoverState: function(point, legendCallback) {
                point.fullState = point.fullState | HOVER_STATE;
                if (!(this.isSelected() && (this.lastSelectionMode === ALL_SERIES_POINTS_MODE || this.lastSelectionMode === INCLUDE_POINTS)) && !point.isSelected()) {
                    point.applyStyle("hover");
                    legendCallback && legendCallback("applyHover")
                }
            },
            releasePointHoverState: function(point, legendCallback) {
                point.fullState = point.fullState & ~HOVER_STATE;
                if (!(this.isSelected() && (this.lastSelectionMode === ALL_SERIES_POINTS_MODE || this.lastSelectionMode === INCLUDE_POINTS)) && !point.isSelected())
                    if (!(this.isHovered() && (this.lastHoverMode === ALL_SERIES_POINTS_MODE || this.lastHoverMode === INCLUDE_POINTS))) {
                        point.applyStyle("normal");
                        legendCallback && legendCallback("resetItem")
                    }
            },
            setPointSelectedState: function(point, legendCallback) {
                point.fullState = point.fullState | SELECTED_STATE;
                point.applyStyle("selection");
                legendCallback && legendCallback("applySelected")
            },
            releasePointSelectedState: function(point, legendCallback) {
                point.fullState = point.fullState & ~SELECTED_STATE;
                if (this.isHovered() && (this.lastHoverMode === ALL_SERIES_POINTS_MODE || this.lastHoverMode === INCLUDE_POINTS) || point.isHovered()) {
                    point.applyStyle("hover");
                    legendCallback && legendCallback("applyHover")
                }
                else if (this.isSelected() && (this.lastSelectionMode === ALL_SERIES_POINTS_MODE || this.lastSelectionMode === INCLUDE_POINTS)) {
                    point.applyStyle("selection");
                    legendCallback && legendCallback("applySelected")
                }
                else {
                    point.applyStyle("normal");
                    legendCallback && legendCallback("resetItem")
                }
            },
            selectPoint: function(point) {
                this._options.seriesGroup && this._options.seriesGroup.trigger(new _Event("selectpoint"), point)
            },
            deselectPoint: function(point) {
                this._options.seriesGroup && this._options.seriesGroup.trigger(new _Event("deselectpoint"), point)
            },
            showPointTooltip: function(point) {
                this._options.seriesGroup && this._options.seriesGroup.trigger(new _Event("showpointtooltip"), point)
            },
            hidePointTooltip: function(point) {
                this._options.seriesGroup && this._options.seriesGroup.trigger(new _Event("hidepointtooltip"), point)
            },
            select: function() {
                this._options.seriesGroup && this._options.seriesGroup.trigger(new _Event("selectseries", {target: this}), this._options.selectionMode);
                this._group.toForeground();
                this._trackersGroup && this._trackersGroup.toBackground()
            },
            clearSelection: function clearSelection() {
                this._options.seriesGroup && this._options.seriesGroup.trigger(new _Event("deselectseries", {target: this}), this._options.selectionMode)
            },
            getPointByArg: function(arg) {
                return this.pointsByArgument[arg.valueOf()] || null
            },
            _deletePoints: function() {
                this._disposePoints(this._originalPoints);
                this._disposePoints(this._aggregatedPoints);
                this._disposePoints(this._oldPoints);
                this._points = null;
                this._oldPoints = null;
                this._aggregatedPoints = null;
                this._originalPoints = null;
                this._drawedPoint = null
            },
            _deletePatterns: function() {
                _each(this._patterns || [], function(_, pattern) {
                    pattern && pattern.dispose()
                });
                this._patterns = null
            },
            _deleteTrackers: function() {
                var that = this;
                _each(that._trackers || [], function(_, tracker) {
                    tracker.remove()
                });
                that._trackersGroup && that._trackersGroup.detach();
                that._markerTrackerGroup && that._markerTrackerGroup.detach();
                that._trackers = that._trackersGroup = that._markerTrackerGroup = null
            },
            dispose: function() {
                this._deletePoints();
                this._group.detach();
                this._labelsGroup && this._labelsGroup.detach();
                this._deletePatterns();
                this._deleteTrackers();
                this._group = null;
                this._markersGroup = null;
                this._elementsGroup = null;
                this._bordersGroup = null;
                this._labelsGroup = null;
                this._graphics = null;
                this._rangeData = null;
                this._renderer = null;
                this.translators = null;
                this._styles = null;
                this._options = null;
                this._pointOptions = null;
                this._drawedPoints = null;
                this._aggregatedPoints = null;
                this.pointsByArgument = null;
                this._segments = null
            },
            correctPosition: _noop,
            getColor: function() {
                return this.getLegendStyles().normal.fill
            },
            getStackName: function() {
                return this.type === "stackedbar" || this.type === "fullstackedbar" ? this._stackName : null
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file rangeDataCalculator.js */
    (function($, DX) {
        var _math = Math,
            _abs = _math.abs,
            _min = _math.min,
            _each = $.each,
            _isEmptyObject = $.isEmptyObject,
            _isDefined = DevExpress.utils.isDefined,
            FULLSTACKED_SERIES_VALUE_MARGIN_PRIORITY = 15,
            BAR_ZERO_VALUE_MARGIN_PRIORITY = 20,
            SERIES_VALUE_MARGIN_PRIORITY = 20,
            SERIES_LABEL_VALUE_MARGIN = 0.3,
            CATEGORIES_SELECTOR = "categories",
            INTERVAL_SELECTOR = "interval",
            MIN_VALUE_MARGIN_SELECTOR = "minValueMargin",
            MAX_VALUE_MARGIN_SELECTOR = "maxValueMargin",
            MIN = "min",
            MAX = "max",
            MIN_VISIBLE = "minVisible",
            MAX_VISIBLE = "maxVisible";
        DevExpress.viz.core.series.helpers.rangeDataCalculator = function() {
            var _truncateValue = function(data, minField, maxField, value) {
                    var min = data[minField],
                        max = data[maxField];
                    data[minField] = value < min || !_isDefined(min) ? value : data[minField];
                    data[maxField] = value > max || !_isDefined(max) ? value : data[maxField]
                };
            var _processTwoValues = function(series, point, prevPoint, highValueName, lowValueName) {
                    var val = point[highValueName],
                        minVal = point[lowValueName],
                        arg = point.argument,
                        prevVal = prevPoint && prevPoint[highValueName],
                        prevMinVal = prevPoint && prevPoint[lowValueName],
                        prevArg = prevPoint && prevPoint.argument;
                    point.hasValue() && _processRangeValue(series, val, minVal, prevVal, prevMinVal);
                    _processValue(series, "arg", arg, prevArg)
                };
            var _processValue = function(series, type, value, prevValue, calcInterval) {
                    var axis = type === "arg" ? "argument" : "value",
                        data = series._rangeData[type],
                        minInterval = data[INTERVAL_SELECTOR],
                        interval;
                    if (series[axis + "AxisType"] === "discrete") {
                        data[CATEGORIES_SELECTOR] = data[CATEGORIES_SELECTOR] || [];
                        data[CATEGORIES_SELECTOR].push(value)
                    }
                    else {
                        _truncateValue(data, "min", "max", value);
                        if (type === "arg") {
                            interval = _isDefined(prevValue) ? _abs(calcInterval ? calcInterval(value, prevValue) : value - prevValue) : interval;
                            data[INTERVAL_SELECTOR] = _isDefined(interval) && (interval < minInterval || !_isDefined(minInterval)) ? interval : minInterval
                        }
                    }
                };
            var _addToVisibleRange = function(series, value) {
                    var data = series._rangeData.val,
                        isDiscrete = series.valueAxisType === "discrete";
                    if (isDiscrete) {
                        data.visibleCategories = data.visibleCategories || [];
                        data.visibleCategories.push(value)
                    }
                    else {
                        if (value < data.minVisible || !_isDefined(data.minVisible))
                            data.minVisible = value;
                        if (value > data.maxVisible || !_isDefined(data.maxVisible))
                            data.maxVisible = value
                    }
                };
            var _processRangeValue = function(series, val, minVal, prevVal, prevMinVal) {
                    var data = series._rangeData.val,
                        interval,
                        currentInterval = data[INTERVAL_SELECTOR];
                    if (series.valueAxisType === "discrete") {
                        data.categories = data.categories || [];
                        data.categories.push(val, minVal)
                    }
                    else {
                        _truncateValue(data, MIN, MAX, val);
                        _truncateValue(data, MIN, MAX, minVal)
                    }
                };
            var _unique = function(array) {
                    var values = {};
                    return $.map(array, function(item) {
                            var result = !values[item] ? item : null;
                            values[item] = true;
                            return result
                        })
                };
            var _processZoomArgument = function(series, zoomArgs) {
                    var data = series._rangeData.arg,
                        minArg,
                        maxArg;
                    minArg = zoomArgs.minArg < zoomArgs.maxArg ? zoomArgs.minArg : zoomArgs.maxArg;
                    maxArg = zoomArgs.maxArg > zoomArgs.minArg ? zoomArgs.maxArg : zoomArgs.minArg;
                    data.min = minArg < data.min ? minArg : data.min;
                    data.max = maxArg > data.max ? maxArg : data.max;
                    data.minVisible = minArg;
                    data.maxVisible = maxArg
                };
            var _correctZoomValue = function(series, zoomArgs) {
                    var minVal,
                        maxVal;
                    if (_isDefined(zoomArgs.minVal) && _isDefined(zoomArgs.maxVal)) {
                        minVal = zoomArgs.minVal < zoomArgs.maxVal ? zoomArgs.minVal : zoomArgs.maxVal;
                        maxVal = zoomArgs.maxVal > zoomArgs.minVal ? zoomArgs.maxVal : zoomArgs.minVal
                    }
                    if (_isDefined(zoomArgs.minVal)) {
                        series._rangeData.val.min = minVal < series._rangeData.val.min ? minVal : series._rangeData.val.min;
                        series._rangeData.val.minVisible = minVal
                    }
                    if (_isDefined(zoomArgs.maxVal)) {
                        series._rangeData.val.max = maxVal > series._rangeData.val.max ? maxVal : series._rangeData.val.max;
                        series._rangeData.val.maxVisible = maxVal
                    }
                };
            var _processZoomValue = function(series, zoomArgs) {
                    var adjustOnZoom = zoomArgs.adjustOnZoom,
                        points = series._points || [],
                        lastVisibleIndex,
                        prevPointAdded = false;
                    _each(points, function(index, point) {
                        var arg = point.argument,
                            prevPoint = index > 0 ? points[index - 1] : null;
                        if (adjustOnZoom && arg >= series._rangeData.arg.minVisible && arg <= series._rangeData.arg.maxVisible) {
                            if (!prevPointAdded) {
                                prevPoint && prevPoint.hasValue() && _addToVisibleRange(series, prevPoint.value);
                                prevPointAdded = true
                            }
                            point.hasValue() && _addToVisibleRange(series, point.value);
                            lastVisibleIndex = index
                        }
                    });
                    if (_isDefined(lastVisibleIndex) && lastVisibleIndex < points.length - 1 && points[lastVisibleIndex + 1].hasValue())
                        _addToVisibleRange(series, points[lastVisibleIndex + 1].value);
                    _correctZoomValue(series, zoomArgs)
                };
            var _processZoomRangeValue = function(series, zoomArgs, maxValueName, minValueName) {
                    var adjustOnZoom = zoomArgs.adjustOnZoom,
                        points = series._points || [],
                        lastVisibleIndex,
                        prevPointAdded = false;
                    _each(points, function(index, point) {
                        var arg = point.argument,
                            prevPoint = index > 0 ? points[index - 1] : null;
                        if (adjustOnZoom && arg >= series._rangeData.arg.minVisible && arg <= series._rangeData.arg.maxVisible) {
                            if (!prevPointAdded) {
                                if (prevPoint && prevPoint.hasValue()) {
                                    _addToVisibleRange(series, prevPoint[maxValueName]);
                                    _addToVisibleRange(series, prevPoint[minValueName])
                                }
                                prevPointAdded = true
                            }
                            if (point.hasValue()) {
                                _addToVisibleRange(series, point[maxValueName]);
                                _addToVisibleRange(series, point[minValueName])
                            }
                            lastVisibleIndex = index
                        }
                    });
                    if (_isDefined(lastVisibleIndex) && lastVisibleIndex < points.length - 1 && points[lastVisibleIndex + 1].hasValue())
                        _addToVisibleRange(series, points[lastVisibleIndex + 1].value);
                    _correctZoomValue(series, zoomArgs)
                };
            var _processNewInterval = function(series, calcInterval) {
                    var data = series._rangeData,
                        points = series._points || [],
                        isArgumentAxisDiscrete = series.argumentAxisType === "discrete";
                    delete data.arg.interval;
                    _each(points, function(index, point) {
                        var arg = point.argument,
                            prevPoint = index > 0 ? points[index - 1] : null,
                            prevArg = prevPoint && prevPoint.argument;
                        !isArgumentAxisDiscrete && _processValue(series, "arg", arg, prevArg, calcInterval)
                    })
                };
            var _fillRangeData = function(series) {
                    var data = series._rangeData,
                        mainAxis = series._getMainAxisName(),
                        axis = mainAxis === "X" ? "Y" : "X";
                    data.arg.categories && (data.arg.categories = _unique(data.arg.categories));
                    data.val.categories && (data.val.categories = _unique(data.val.categories));
                    data.arg.visibleCategories && (data.arg.visibleCategories = _unique(data.arg.visibleCategories));
                    data.val.visibleCategories && (data.val.visibleCategories = _unique(data.val.visibleCategories));
                    data.arg.axisType = series.argumentAxisType;
                    data.arg.dataType = series.argumentType;
                    data.val.axisType = series.valueAxisType;
                    data.val.dataType = series.valueType;
                    data.val.isValueRange = true
                };
            var _setPadding = function(range, prefix, val, priority) {
                    range[prefix] = val;
                    range[prefix + "Priority"] = priority
                };
            var _setZeroPadding = function(range, val, prefix) {
                    val === 0 && _setPadding(range, prefix, 0, BAR_ZERO_VALUE_MARGIN_PRIORITY)
                };
            var _calculateRangeMinValue = function(series, zoomArgs) {
                    var data = series._rangeData.val,
                        minVisible = data[MIN_VISIBLE],
                        maxVisible = data[MAX_VISIBLE];
                    zoomArgs = zoomArgs || {};
                    if (data) {
                        data.alwaysCorrectMin = true;
                        series._rangeData.arg.keepValueMargins = true;
                        if (series.valueAxisType !== "logarithmic" && series.valueType !== "datetime" && series.getOptions().showZero !== false) {
                            data[MIN_VISIBLE] = minVisible > (zoomArgs.minVal || 0) ? zoomArgs.minVal || 0 : minVisible;
                            data[MAX_VISIBLE] = maxVisible < (zoomArgs.maxVal || 0) ? zoomArgs.maxVal || 0 : maxVisible;
                            data[MIN] = data[MIN] > 0 ? 0 : data[MIN];
                            _setZeroPadding(data, data[MIN], MIN_VALUE_MARGIN_SELECTOR);
                            data[MAX] = data[MAX] < 0 ? 0 : data[MAX];
                            if (data[MAX] === 0 || data[MAX] > 0 && data[MIN] < 0) {
                                data[MIN_VALUE_MARGIN_SELECTOR] = data[MAX_VALUE_MARGIN_SELECTOR];
                                data[MIN_VALUE_MARGIN_SELECTOR + "Priority"] = data[MAX_VALUE_MARGIN_SELECTOR + "Priority"]
                            }
                            _setZeroPadding(data, data[MAX], MAX_VALUE_MARGIN_SELECTOR)
                        }
                    }
                };
            var _processFullStackedRange = function(series) {
                    var data = series._rangeData.val,
                        isRangeEmpty = _isEmptyObject(data);
                    _setPadding(data, "minValueMargin", 0, FULLSTACKED_SERIES_VALUE_MARGIN_PRIORITY);
                    _setPadding(data, "maxValueMargin", 0, FULLSTACKED_SERIES_VALUE_MARGIN_PRIORITY);
                    !isRangeEmpty && (data.min = 0)
                };
            var _processRange = function(series, point, prevPoint) {
                    var val = point.value,
                        arg = point.argument,
                        prevVal = prevPoint && prevPoint.value,
                        prevArg = prevPoint && prevPoint.argument;
                    point.hasValue() && _processValue(series, "val", val, prevVal);
                    _processValue(series, "arg", arg, prevArg)
                };
            var _addLabelPaddings = function(series) {
                    var labelOptions = series.getOptions().label;
                    if (series.areLabelsVisible() && labelOptions && labelOptions.visible && labelOptions.position !== "inside")
                        _setPadding(series._rangeData.val, "maxValueMargin", SERIES_LABEL_VALUE_MARGIN, SERIES_VALUE_MARGIN_PRIORITY)
                };
            var _addRangeSeriesLabelPaddings = function(series) {
                    var data = series._rangeData.val;
                    if (series.areLabelsVisible() && series._options.label.visible && series._options.label.position !== "inside") {
                        _setPadding(data, "maxValueMargin", SERIES_LABEL_VALUE_MARGIN, SERIES_VALUE_MARGIN_PRIORITY);
                        _setPadding(data, "minValueMargin", SERIES_LABEL_VALUE_MARGIN, SERIES_VALUE_MARGIN_PRIORITY)
                    }
                };
            var _calculateRangeData = function(series, zoomArgs, calcIntervalFunction) {
                    var valueData = series._rangeData.val;
                    if (series.argumentAxisType !== "discrete" && zoomArgs && _isDefined(zoomArgs.minArg) && _isDefined(zoomArgs.maxArg)) {
                        valueData[MIN_VISIBLE] = zoomArgs.minVal;
                        valueData[MAX_VISIBLE] = zoomArgs.maxVal;
                        _processZoomArgument(series, zoomArgs);
                        _processZoomValue(series, zoomArgs)
                    }
                    else if (!zoomArgs && calcIntervalFunction)
                        _processNewInterval(series, calcIntervalFunction);
                    _fillRangeData(series)
                };
            var _calculateTwoValuesRangeData = function(series, zoomArgs, calcIntervalFunction, maxValueName, minValueName) {
                    var valueData = series._rangeData.val;
                    if (series.argumentAxisType !== "discrete" && zoomArgs && _isDefined(zoomArgs.minArg) && _isDefined(zoomArgs.maxArg)) {
                        valueData[MIN_VISIBLE] = zoomArgs.minVal;
                        valueData[MAX_VISIBLE] = zoomArgs.maxVal;
                        _processZoomArgument(series, zoomArgs);
                        _processZoomRangeValue(series, zoomArgs, maxValueName, minValueName)
                    }
                    else if (!zoomArgs && calcIntervalFunction)
                        _processNewInterval(series);
                    _fillRangeData(series)
                };
            return {
                    processRange: _processRange,
                    calculateRangeData: _calculateRangeData,
                    calculateTwoValuesRangeData: _calculateTwoValuesRangeData,
                    addLabelPaddings: _addLabelPaddings,
                    addRangeSeriesLabelPaddings: _addRangeSeriesLabelPaddings,
                    processFullStackedRange: _processFullStackedRange,
                    calculateRangeMinValue: _calculateRangeMinValue,
                    processTwoValues: _processTwoValues
                }
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file scatterSeries.js */
    (function($, DX) {
        var viz = DX.viz,
            series = viz.core.series,
            rangeCalculator = series.helpers.rangeDataCalculator(),
            _each = $.each,
            _extend = $.extend,
            _map = $.map,
            _noop = $.noop,
            _isDefined = DX.utils.isDefined,
            _floor = Math.floor,
            DEFAULT_SYMBOL_POINT_SIZE = 2,
            DEFAULT_TRACKER_WIDTH = 20,
            DEFAULT_DURATION = 400;
        series.mixins.chart.scatter = {
            _defaultDuration: DEFAULT_DURATION,
            _defaultTrackerWidth: DEFAULT_TRACKER_WIDTH,
            _applyStyle: _noop,
            _adjustLabels: _noop,
            _updateOptions: _noop,
            _parseStyle: _noop,
            _prepareSegment: _noop,
            _drawSegment: _noop,
            _generateDefaultSegments: _noop,
            _prepareSeriesToDrawing: function() {
                this._deleteOldAnimationMethods();
                this._firstDrawing && this._clearSeries();
                this._disposePoints(this._oldPoints);
                this._oldPoints = null
            },
            _applyTrackersClippings: function() {
                this._markerTrackerGroup.applySettings({clipId: this._forceClipping ? this._paneClipRectID : null})
            },
            updateTeamplateFieldNames: function() {
                var that = this,
                    options = that._options;
                options.valueField = that.getValueFields()[0] + that.name;
                options.tagField = that.getTagField() + that.name
            },
            _applyElementsClipRect: function(settings) {
                settings.clipId = this._paneClipRectID
            },
            _applyMarkerClipRect: function(settings) {
                settings.clipId = this._forceClipping ? this._paneClipRectID : null
            },
            _createGroup: function(groupName, parent, target, settings) {
                var group = parent[groupName];
                if (!group)
                    parent[groupName] = group = this._renderer.createGroup(settings);
                else
                    group.applySettings(settings);
                group.append(target)
            },
            _applyClearingSettings: function(settings) {
                settings.opacity = null;
                settings.scale = null;
                if (this._options.rotated)
                    settings.translateX = null;
                else
                    settings.translateY = null
            },
            _createMarkerGroup: function() {
                var settings = this._getPointOptions().styles.normal;
                settings["class"] = "dxc-markers";
                settings.opacity = 1;
                this._applyMarkerClipRect(settings);
                this._createGroup("_markersGroup", this, this._group, settings)
            },
            _createLabelGroup: function() {
                var settings = {
                        "class": "dxc-labels",
                        visibility: this.getLabelVisibility() ? "visible" : "hidden"
                    };
                this._applyElementsClipRect(settings);
                this._applyClearingSettings(settings);
                this._createGroup("_labelsGroup", this, this._options.labelsGroup, settings)
            },
            _createGroups: function(animationEnabled) {
                this._createMarkerGroup();
                this._createLabelGroup();
                animationEnabled && this._labelsGroup && this._labelsGroup.applySettings({opacity: 0.001})
            },
            _getCreatingPointOptions: function() {
                if (!this._predefinedPointOptions) {
                    var defaultPointOptions = this._getPointOptions(),
                        r = defaultPointOptions.styles && defaultPointOptions.styles.normal && defaultPointOptions.styles.normal.r,
                        strokeWidth = defaultPointOptions.styles && defaultPointOptions.styles.normal && defaultPointOptions.styles.normal.strokeWidth,
                        creatingPointOptions = _extend(true, {}, defaultPointOptions);
                    creatingPointOptions.styles = creatingPointOptions.styles || {};
                    creatingPointOptions.styles.normal = {
                        r: r,
                        strokeWidth: strokeWidth
                    };
                    this._predefinedPointOptions = creatingPointOptions
                }
                return this._predefinedPointOptions
            },
            _getSpecialColor: function(mainSeriesColor) {
                return mainSeriesColor
            },
            _getPointOptions: function() {
                return this._pointOptions || (this._pointOptions = this._parsePointOptions(this._preparePointOptions(), this._options.label))
            },
            _preparePointOptions: function(customOptions) {
                return customOptions ? _extend(true, {}, this._options.point, customOptions) : this._options.point
            },
            _parsePointStyle: function(style, defaultColor, defaultBorderColor) {
                var border = style.border || {};
                return {
                        fill: style.color || defaultColor,
                        stroke: border.color || defaultBorderColor,
                        strokeWidth: border.visible ? border.width : 0,
                        r: style.size / 2 + (border.visible && style.size !== 0 ? ~~(border.width / 2) || 0 : 0)
                    }
            },
            _createPointStyles: function(pointOptions) {
                var mainPointColor = pointOptions.color || this._options.mainSeriesColor,
                    containerColor = this._options.containerBackgroundColor,
                    normalStyle = this._parsePointStyle(pointOptions, mainPointColor, mainPointColor);
                normalStyle.visibility = pointOptions.visible ? "visible" : "hidden";
                return {
                        normal: normalStyle,
                        hover: this._parsePointStyle(pointOptions.hoverStyle, containerColor, mainPointColor),
                        selection: this._parsePointStyle(pointOptions.selectionStyle, containerColor, mainPointColor)
                    }
            },
            _checkData: function(data) {
                return _isDefined(data.argument) && data.value !== undefined
            },
            _processRange: function(point, prevPoint) {
                rangeCalculator.processRange(this, point, prevPoint)
            },
            _getRangeData: function(zoomArgs, calcIntervalFunction) {
                rangeCalculator.calculateRangeData(this, zoomArgs, calcIntervalFunction);
                rangeCalculator.addLabelPaddings(this);
                return this._rangeData
            },
            _getPointData: function(data, options) {
                var argumentField = options.argumentField || "arg",
                    valueField = options.valueField || "val",
                    tagField = options.tagField || "tag";
                return {
                        value: data[valueField],
                        argument: data[argumentField],
                        tag: data[tagField]
                    }
            },
            _drawPoint: function(point, markersGroup, labelsGroup, animationEnabled, firstDrawing) {
                if (point.isInVisibleArea()) {
                    point.clearVisibility();
                    point.draw(this._renderer, markersGroup, labelsGroup, animationEnabled, firstDrawing);
                    this._drawedPoints.push(point)
                }
                else
                    point.setInvisibility()
            },
            _clearingAnimation: function(translators, drawComplete) {
                var that = this,
                    params = {opacity: 0.001},
                    options = {
                        duration: that._defaultDuration,
                        partitionDuration: 0.5
                    };
                that._labelsGroup && that._labelsGroup.animate(params, options, function() {
                    that._markersGroup && that._markersGroup.animate(params, options, drawComplete)
                })
            },
            _animate: function(complete) {
                var that = this,
                    lastPointIndex = that._drawedPoints.length - 1,
                    labelAnimFunc = function() {
                        that._labelsGroup && that._labelsGroup.animate({opacity: 1}, {duration: that._defaultDuration})
                    },
                    settings;
                _each(that._drawedPoints || [], function(i, p) {
                    settings = {translate: {
                            x: p.x,
                            y: p.y
                        }};
                    p.animate(i === lastPointIndex ? labelAnimFunc : undefined, settings)
                })
            },
            _getPointSize: function() {
                return this._options.point.visible ? this._options.point.size : DEFAULT_SYMBOL_POINT_SIZE
            },
            _calcMedianValue: function(fusionPoints, valueField) {
                var result,
                    allValue;
                allValue = _map(fusionPoints, function(point) {
                    return point[valueField]
                });
                allValue.sort(function(a, b) {
                    return a - b
                });
                result = allValue[_floor(allValue.length / 2)];
                return _isDefined(result) ? result : null
            },
            _fusionPoints: function(fusionPoints, tick, index) {
                var result = this._calcMedianValue(fusionPoints, "value");
                return {
                        value: result,
                        argument: tick,
                        tag: null,
                        index: index,
                        seriesName: this.name
                    }
            },
            _endUpdateData: function() {
                delete this._predefinedPointOptions
            },
            getArgumentField: function() {
                return this._options.argumentField || "arg"
            },
            getValueFields: function() {
                return [this._options.valueField || "val"]
            },
            _beginUpdateData: $.noop
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file lineSeries.js */
    (function($, DX) {
        var viz = DX.viz,
            series = viz.core.series.mixins.chart,
            utils = DX.utils,
            scatterSeries = series.scatter,
            _extend = $.extend,
            _map = $.map,
            _each = $.each;
        series.line = _extend({}, scatterSeries, {
            _createElementsGroup: function(elementsStyle) {
                var settings = _extend({"class": "dxc-elements"}, elementsStyle);
                this._applyElementsClipRect(settings);
                this._createGroup("_elementsGroup", this, this._group, settings)
            },
            _createBordersGroup: function(borderStyle) {
                var settings = _extend({"class": "dxc-borders"}, borderStyle);
                this._applyElementsClipRect(settings);
                this._createGroup("_bordersGroup", this, this._group, settings)
            },
            _applyTrackersClippings: function() {
                scatterSeries._applyTrackersClippings.call(this);
                this._trackersGroup.applySettings({clipId: this._paneClipRectID})
            },
            _createGroups: function(animationEnabled, style) {
                var style = style || this._styles.normal;
                this._createElementsGroup(style.elements);
                this._areBordersVisible() && this._createBordersGroup(style.border);
                scatterSeries._createGroups.call(this, animationEnabled, {});
                animationEnabled && this._markersGroup && this._markersGroup.applySettings({opacity: 0.001})
            },
            _areBordersVisible: function() {
                return false
            },
            _getDefaultSegment: function(segment) {
                return {line: _map(segment.line || [], function(pt) {
                            return pt.getDefaultCoords()
                        })}
            },
            _prepareSegment: function(points) {
                return {line: points}
            },
            _parseLineOptions: function(options, defaultColor) {
                return {
                        stroke: options.color || defaultColor,
                        strokeWidth: options.width,
                        dashStyle: options.dashStyle || 'solid'
                    }
            },
            _parseStyle: function(options, defaultColor) {
                return {elements: this._parseLineOptions(options, defaultColor)}
            },
            _applyStyle: function(style) {
                this._elementsGroup && this._elementsGroup.applySettings(style.elements);
                _each(this._graphics || [], function(_, graphic) {
                    graphic.line && graphic.line.applySettings({strokeWidth: style.elements.strokeWidth})
                })
            },
            _drawElement: function(segment, group) {
                return {line: this._createMainElement(segment.line, {strokeWidth: this._styles.normal.elements.strokeWidth}).append(group)}
            },
            _removeElement: function(element) {
                element.line.remove()
            },
            _generateDefaultSegments: function() {
                var that = this,
                    segments = [];
                _each(that._segments || [], function(_, segment) {
                    segments.push(that._getDefaultSegment(segment))
                });
                return segments
            },
            _updateElement: function(element, segment, animate, animateParams, complete) {
                var params = {points: segment.line};
                animate ? element.line.animate(params, animateParams, complete) : element.line.applySettings(params)
            },
            _clearingAnimation: function(translator, drawComplete) {
                var that = this,
                    lastIndex = that._graphics.length - 1,
                    settings = {opacity: 0.001},
                    options = {
                        duration: that._defaultDuration,
                        partitionDuration: 0.5
                    };
                that._labelsGroup && that._labelsGroup.animate(settings, options, function() {
                    that._markersGroup && that._markersGroup.animate(settings, options, function() {
                        _each(that._defaultSegments || [], function(i, segment) {
                            that._oldUpdateElement(that._graphics[i], segment, true, {partitionDuration: 0.5}, i === lastIndex ? drawComplete : undefined)
                        })
                    })
                })
            },
            _animate: function() {
                var that = this,
                    lastIndex = that._graphics.length - 1;
                _each(that._graphics || [], function(i, elem) {
                    that._updateElement(elem, that._segments[i], true, {complete: i === lastIndex ? function() {
                            that._labelsGroup && that._labelsGroup.animate({opacity: 1}, {duration: that._defaultDuration});
                            that._markersGroup && that._markersGroup.animate({opacity: 1}, {duration: that._defaultDuration})
                        } : undefined})
                })
            },
            _drawPoint: function(point, group, labelsGroup) {
                scatterSeries._drawPoint.call(this, point, group, labelsGroup)
            },
            _createMainElement: function(points, settings) {
                return this._renderer.createPath(points, settings)
            },
            _drawSegment: function(points, animationEnabled, segmentCount) {
                var segment = this._prepareSegment(points, this._options.rotated);
                this._segments.push(segment);
                if (!this._graphics[segmentCount])
                    this._graphics[segmentCount] = this._drawElement(animationEnabled ? this._getDefaultSegment(segment) : segment, this._elementsGroup);
                else if (!animationEnabled)
                    this._updateElement(this._graphics[segmentCount], segment)
            },
            _getTrackerSettings: function() {
                return {
                        strokeWidth: this._styles.normal.elements.strokeWidth > this._defaultTrackerWidth ? this._styles.normal.elements.strokeWidth : this._defaultTrackerWidth,
                        fill: "none"
                    }
            },
            _getMainPointsFromSegment: function(segment) {
                return segment.line
            },
            _drawTrackerElement: function(segment) {
                return this._createMainElement(this._getMainPointsFromSegment(segment), this._getTrackerSettings(segment))
            },
            _updateTrackerElement: function(segment, element) {
                var settings = this._getTrackerSettings(segment);
                settings.points = this._getMainPointsFromSegment(segment);
                element.applySettings(settings)
            }
        });
        series.stepline = _extend({}, series.line, {
            _calculateStepLinePoints: function(points) {
                var segment = [];
                _each(points, function(i, pt) {
                    var stepY;
                    if (!i) {
                        segment.push(pt);
                        return
                    }
                    stepY = segment[segment.length - 1].y;
                    if (stepY !== pt.y) {
                        var point = utils.clone(pt);
                        point.y = stepY;
                        segment.push(point)
                    }
                    segment.push(pt)
                });
                return segment
            },
            _prepareSegment: function(points) {
                return series.line._prepareSegment(this._calculateStepLinePoints(points))
            }
        });
        series.stackedline = _extend({}, series.line, {});
        series.fullstackedline = _extend({}, series.line, {_getRangeData: function(zoomArgs, calcIntervalFunction) {
                var rangeCalculator = viz.core.series.helpers.rangeDataCalculator();
                rangeCalculator.calculateRangeData(this, zoomArgs, calcIntervalFunction);
                rangeCalculator.addLabelPaddings(this);
                rangeCalculator.processFullStackedRange(this);
                return this._rangeData
            }});
        series.spline = _extend({}, series.line, {
            _calculateBezierPoints: function(src, rotated) {
                var bezierPoints = [],
                    pointsCopy = src;
                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 = 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 = !!(!rotated && (yCur <= prevPoint.y && yCur <= nextPoint.y || yCur >= prevPoint.y && yCur >= nextPoint.y) || rotated && (xCur <= prevPoint.x && xCur <= nextPoint.x || xCur >= prevPoint.x && xCur >= nextPoint.x));
                            if (curIsExtremum)
                                if (!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 (!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 (!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]);
                return bezierPoints
            },
            _prepareSegment: function(points, rotated) {
                return series.line._prepareSegment(this._calculateBezierPoints(points, rotated))
            },
            _createMainElement: function(points, settings) {
                return this._renderer.createBezierPath(points, settings)
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file areaSeries.js */
    (function($, DX) {
        var viz = DX.viz,
            utils = DX.utils,
            series = viz.core.series.mixins.chart,
            lineSeries = series.line,
            _map = $.map,
            _extend = $.extend,
            HOVER_COLOR_HIGHLIGHTING = 20;
        series.area = _extend({}, lineSeries, {
            _createBorderElement: lineSeries._createMainElement,
            _processSinglePointsAreaSegment: function(points, rotated) {
                if (points.length == 1) {
                    var p = points[0],
                        p1 = utils.clone(p),
                        coord = rotated ? "y" : "x";
                    p1[coord] += 1;
                    return [p, p1]
                }
                return points
            },
            _prepareSegment: function(points, rotated) {
                var processedPoints = this._processSinglePointsAreaSegment(points, rotated);
                return {
                        line: processedPoints,
                        area: _map(processedPoints, function(pt) {
                            return pt.getCoords()
                        }).concat(_map(processedPoints.slice().reverse(), function(pt) {
                            return pt.getCoords(true)
                        })),
                        singlePointSegment: processedPoints !== points
                    }
            },
            _getSpecialColor: function(color) {
                return this._options._IE8 ? new DX.Color(color).highlight(HOVER_COLOR_HIGHLIGHTING) : color
            },
            _getRangeData: function(zoomArgs, calcIntervalFunction) {
                var rangeCalculator = viz.core.series.helpers.rangeDataCalculator();
                rangeCalculator.calculateRangeData(this, zoomArgs, calcIntervalFunction);
                rangeCalculator.addLabelPaddings(this);
                rangeCalculator.calculateRangeMinValue(this, zoomArgs);
                return this._rangeData
            },
            _getDefaultSegment: function(segment) {
                var defaultSegment = lineSeries._getDefaultSegment(segment);
                defaultSegment.area = defaultSegment.line.concat(defaultSegment.line.slice().reverse());
                return defaultSegment
            },
            _updateElement: function(element, segment, animate, animateParams, complete) {
                var lineParams = {points: segment.line},
                    areaParams = {points: segment.area},
                    borderElement = element.line;
                if (animate) {
                    borderElement && borderElement.animate(lineParams, animateParams);
                    element.area.animate(areaParams, animateParams, complete)
                }
                else {
                    borderElement && borderElement.applySettings(lineParams);
                    element.area.applySettings(areaParams)
                }
            },
            _removeElement: function(element) {
                element.line && element.line.remove();
                element.area.remove()
            },
            _drawElement: function(segment, group) {
                return {
                        line: this._bordersGroup && this._createBorderElement(segment.line, {strokeWidth: this._styles.normal.border.strokeWidth}).append(this._bordersGroup),
                        area: this._createMainElement(segment.area).append(this._elementsGroup)
                    }
            },
            _applyStyle: function(style) {
                this._elementsGroup && this._elementsGroup.applySettings(style.elements);
                this._bordersGroup && this._bordersGroup.applySettings(style.border);
                $.each(this._graphics || [], function(_, graphic) {
                    graphic.line && graphic.line.applySettings({strokeWidth: style.border.strokeWidth})
                })
            },
            _createPattern: function(color, hatching) {
                if (hatching) {
                    var pattern = this._renderer.createPattern(color, hatching);
                    this._patterns.push(pattern);
                    return pattern.id
                }
                return color
            },
            _parseStyle: function(options, defaultColor, defaultBorderColor) {
                var borderOptions = options.border || {},
                    borderStyle = lineSeries._parseLineOptions(borderOptions, defaultBorderColor);
                borderStyle.strokeWidth = borderOptions.visible ? borderStyle.strokeWidth : 0;
                return {
                        border: borderStyle,
                        elements: {
                            stroke: "none",
                            fill: this._createPattern(options.color || defaultColor, options.hatching),
                            opacity: options.opacity
                        }
                    }
            },
            _areBordersVisible: function() {
                var options = this._options;
                return options.border.visible || options.hoverStyle.border.visible || options.selectionStyle.border.visible
            },
            _createMainElement: function(points, settings) {
                return this._renderer.createArea(points, settings)
            },
            _getTrackerSettings: function(segment) {
                return {strokeWidth: segment.singlePointSegment ? this._defaultTrackerWidth : 0}
            },
            _getMainPointsFromSegment: function(segment) {
                return segment.area
            }
        });
        series.steparea = _extend({}, series.area, {_prepareSegment: function(points, rotated) {
                points = series.area._processSinglePointsAreaSegment(points, rotated);
                return series.area._prepareSegment.call(this, series.stepline._calculateStepLinePoints(points))
            }});
        series.splinearea = _extend({}, series.area, {
            _areaPointsToSplineAreaPoints: function(areaPoints) {
                var lastFwPoint = areaPoints[areaPoints.length / 2 - 1],
                    firstBwPoint = areaPoints[areaPoints.length / 2];
                areaPoints.splice(areaPoints.length / 2, 0, {
                    x: lastFwPoint.x,
                    y: lastFwPoint.y
                }, {
                    x: firstBwPoint.x,
                    y: firstBwPoint.y
                });
                if (lastFwPoint.defaultCoords)
                    areaPoints[areaPoints.length / 2].defaultCoords = true;
                if (firstBwPoint.defaultCoords)
                    areaPoints[areaPoints.length / 2 - 1].defaultCoords = true
            },
            _prepareSegment: function(points, rotated) {
                var areaSeries = series.area,
                    processedPoints = areaSeries._processSinglePointsAreaSegment(points, rotated),
                    areaSegment = areaSeries._prepareSegment.call(this, series.spline._calculateBezierPoints(processedPoints, rotated));
                this._areaPointsToSplineAreaPoints(areaSegment.area);
                areaSegment.singlePointSegment = processedPoints !== points;
                return areaSegment
            },
            _getDefaultSegment: function(segment) {
                var areaDefaultSegment = series.area._getDefaultSegment(segment);
                this._areaPointsToSplineAreaPoints(areaDefaultSegment.area);
                return areaDefaultSegment
            },
            _createMainElement: function(points, settings) {
                return this._renderer.createBezierArea(points, settings)
            },
            _createBorderElement: series.spline._createMainElement
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file barSeries.js */
    (function($, DX) {
        var viz = DX.viz,
            series = viz.core.series.mixins.chart,
            scatterSeries = series.scatter,
            areaSeries = series.area,
            _extend = $.extend,
            _each = $.each,
            DEFAULT_BAR_POINT_SIZE = 3;
        series.bar = _extend({}, scatterSeries, {
            _getSpecialColor: areaSeries._getSpecialColor,
            _createPattern: areaSeries._createPattern,
            _updateOptions: function(options) {
                this._stackName = "axis_" + (options.axis || "default") + "_stack_" + (options.stack || "default")
            },
            _getRangeData: function(zoomArgs, calcIntervalFunction) {
                var rangeData = areaSeries._getRangeData.apply(this, arguments);
                rangeData.arg.stick = false;
                return rangeData
            },
            _parsePointStyle: function(style, defaultColor, defaultBorderColor) {
                var color = this._createPattern(style.color || defaultColor, style.hatching),
                    base = scatterSeries._parsePointStyle.call(this, style, color, defaultBorderColor);
                base.fill = color;
                delete base.r;
                return base
            },
            _applyMarkerClipRect: function(settings) {
                settings.clipId = null
            },
            _applyTrackersClippings: function() {
                this._markerTrackerGroup.applySettings({clipId: this._paneClipRectID})
            },
            _clearingAnimation: function(translators, drawComplete) {
                var that = this,
                    settings;
                if (that._options.rotated)
                    settings = {
                        scale: {
                            x: 0.001,
                            y: 1
                        },
                        translate: {x: translators.x.translate("canvas_position_default")}
                    };
                else
                    settings = {
                        scale: {
                            x: 1,
                            y: 0.001
                        },
                        translate: {y: translators.y.translate("canvas_position_default")}
                    };
                that._labelsGroup && that._labelsGroup.animate({opacity: 0.001}, {
                    duration: that._defaultDuration,
                    partitionDuration: 0.5
                }, function() {
                    that._markersGroup.animate(settings, {partitionDuration: 0.5}, function() {
                        that._markersGroup.applySettings({
                            scale: null,
                            translateX: 0,
                            translateY: 0
                        });
                        drawComplete()
                    })
                })
            },
            _createGroups: function(animationEnabled, style, firstDrawing) {
                var settings = {};
                scatterSeries._createGroups.apply(this, arguments);
                if (animationEnabled && firstDrawing)
                    if (!this._options.rotated)
                        settings = {
                            scale: {
                                x: 1,
                                y: 0.001
                            },
                            translateY: this.translators.y.translate("canvas_position_default")
                        };
                    else
                        settings = {
                            scale: {
                                x: 0.001,
                                y: 1
                            },
                            translateX: this.translators.x.translate("canvas_position_default")
                        };
                else if (!animationEnabled)
                    settings = {
                        scale: {
                            x: 1,
                            y: 1
                        },
                        translateX: 0,
                        translateY: 0
                    };
                this._markersGroup.applySettings(settings)
            },
            _drawPoint: function(point, markersGroup, labelsGroup, animationEnabled, firstDrawing) {
                scatterSeries._drawPoint.call(this, point, markersGroup, labelsGroup, animationEnabled && !firstDrawing)
            },
            _getMainColor: function() {
                return this._options.mainSeriesColor
            },
            _createPointStyles: function(pointOptions) {
                var mainColor = pointOptions.color || this._getMainColor(),
                    specialMainColor = this._getSpecialColor(mainColor);
                return {
                        normal: this._parsePointStyle(pointOptions, mainColor, mainColor),
                        hover: this._parsePointStyle(pointOptions.hoverStyle || {}, specialMainColor, mainColor),
                        selection: this._parsePointStyle(pointOptions.selectionStyle || {}, specialMainColor, mainColor)
                    }
            },
            _preparePointOptions: function(customOptions) {
                return customOptions ? _extend(true, {}, this._options, customOptions) : this._options
            },
            _animate: function(firstDrawing) {
                var that = this,
                    labelAnimFunc = function() {
                        that._labelsGroup && that._labelsGroup.animate({opacity: 1}, {duration: that._defaultDuration})
                    },
                    lastPointIndex;
                that._markersGroup.animate({
                    scale: {
                        x: 1,
                        y: 1
                    },
                    translate: {
                        y: 0,
                        x: 0
                    }
                }, undefined, labelAnimFunc);
                if (!firstDrawing) {
                    lastPointIndex = that._drawedPoints.length - 1;
                    _each(this._drawedPoints || [], function(i, point) {
                        point.animate(i === lastPointIndex ? labelAnimFunc : undefined, {
                            x: point.x,
                            y: point.y,
                            height: point.height,
                            width: point.width
                        })
                    })
                }
            },
            _getPointSize: function() {
                return DEFAULT_BAR_POINT_SIZE
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file rangeSeries.js */
    (function($, DX) {
        var viz = DX.viz,
            series = viz.core.series.mixins.chart,
            _extend = $.extend,
            _isDefined = DX.utils.isDefined,
            _map = $.map,
            rangeCalculator = viz.core.series.helpers.rangeDataCalculator(),
            areaSeries = series.area;
        var baseRangeSeries = {
                _checkData: function(data) {
                    return _isDefined(data.argument) && data.value !== undefined && data.minValue !== undefined
                },
                updateTeamplateFieldNames: function() {
                    var that = this,
                        options = that._options,
                        valueFields = that.getValueFields(),
                        name = that.name;
                    options.rangeValue1Field = valueFields[0] + name;
                    options.rangeValue2Field = valueFields[1] + name;
                    options.tagField = that.getTagField() + name
                },
                _processRange: function(point, prevPoint) {
                    rangeCalculator.processTwoValues(this, point, prevPoint, "value", "minValue")
                },
                _getRangeData: function(zoomArgs, calcIntervalFunction) {
                    rangeCalculator.calculateTwoValuesRangeData(this, zoomArgs, calcIntervalFunction, "value", "minValue");
                    rangeCalculator.addRangeSeriesLabelPaddings(this);
                    return this._rangeData
                },
                _getPointData: function(data, options) {
                    var argumentField = options.argumentField || "arg",
                        tagField = options.tagField || "tag",
                        rangeValue1Field = options.rangeValue1Field || "val1",
                        rangeValue2Field = options.rangeValue2Field || "val2";
                    return {
                            tag: data[tagField],
                            minValue: data[rangeValue1Field],
                            value: data[rangeValue2Field],
                            argument: data[argumentField]
                        }
                },
                _fusionPoints: function(fusionPoints, tick, index) {
                    var scatterSeries = series.scatter,
                        value = scatterSeries._calcMedianValue.call(this, fusionPoints, "value"),
                        minValue = scatterSeries._calcMedianValue.call(this, fusionPoints, "minValue"),
                        pointData;
                    if (value === null || minValue === null)
                        value = minValue = null;
                    pointData = {
                        minValue: minValue,
                        value: value,
                        argument: tick,
                        tag: null
                    };
                    return pointData
                },
                getValueFields: function() {
                    return [this._options.rangeValue1Field || "val1", this._options.rangeValue2Field || "val2"]
                }
            };
        series.rangebar = _extend({}, series.bar, baseRangeSeries);
        series.rangearea = _extend({}, areaSeries, {
            _drawPoint: function(point, markersGroup, labelsGroup, animationEnabled) {
                if (point.isInVisibleArea()) {
                    point.clearVisibility();
                    point.draw(this._renderer, markersGroup, labelsGroup, animationEnabled);
                    this._drawedPoints.push(point);
                    if (!point.visibleTopMarker)
                        point.hideMarker("top");
                    if (!point.visibleBottomMarker)
                        point.hideMarker("bottom")
                }
                else
                    point.setInvisibility()
            },
            _prepareSegment: function(points, rotated) {
                var processedPoints = this._processSinglePointsAreaSegment(points, rotated),
                    processedMinPointsCoords = $.map(processedPoints, function(pt) {
                        return pt.getCoords(true)
                    });
                return {
                        line: processedPoints,
                        bottomLine: processedMinPointsCoords,
                        area: $.map(processedPoints, function(pt) {
                            return pt.getCoords()
                        }).concat(processedMinPointsCoords.slice().reverse()),
                        singlePointSegment: processedPoints !== points
                    }
            },
            _getDefaultSegment: function(segment) {
                var defaultSegment = areaSeries._getDefaultSegment.call(this, segment);
                defaultSegment.bottomLine = defaultSegment.line;
                return defaultSegment
            },
            _removeElement: function(element) {
                areaSeries._removeElement.call(this, element);
                element.bottomLine && element.bottomLine.remove()
            },
            _drawElement: function(segment, group) {
                var drawnElement = areaSeries._drawElement.call(this, segment, group);
                drawnElement.bottomLine = this._bordersGroup && this._createBorderElement(segment.bottomLine, {strokeWidth: this._styles.normal.border.strokeWidth}).append(this._bordersGroup);
                return drawnElement
            },
            _applyStyle: function(style) {
                this._elementsGroup && this._elementsGroup.applySettings(style.elements);
                this._bordersGroup && this._bordersGroup.applySettings(style.border);
                $.each(this._graphics || [], function(_, graphic) {
                    graphic.line && graphic.line.applySettings({strokeWidth: style.border.strokeWidth});
                    graphic.bottomLine && graphic.bottomLine.applySettings({strokeWidth: style.border.strokeWidth})
                })
            },
            _updateElement: function(element, segment, animate, animateParams, complete) {
                areaSeries._updateElement.call(this, element, segment, animate, animateParams, complete);
                var bottomLineParams = {points: segment.bottomLine},
                    bottomBorderElement = element.bottomLine;
                if (bottomBorderElement)
                    animate ? bottomBorderElement.animate(bottomLineParams, animateParams) : bottomBorderElement.applySettings(bottomLineParams)
            }
        }, baseRangeSeries)
    })(jQuery, DevExpress);
    /*! Module viz-core, file bubbleSeries.js */
    (function($, DX) {
        var viz = DX.viz,
            series = viz.core.series.mixins.chart,
            scatterSeries = series.scatter,
            barSeries = series.bar,
            _isDefined = DX.utils.isDefined,
            _extend = $.extend,
            _each = $.each;
        series.bubble = _extend({}, scatterSeries, {
            _applyTrackersClippings: barSeries._applyTrackersClippings,
            _getMainColor: barSeries._getMainColor,
            _createPointStyles: barSeries._createPointStyles,
            _createPattern: barSeries._createPattern,
            _preparePointOptions: barSeries._preparePointOptions,
            _getSpecialColor: barSeries._getSpecialColor,
            _applyMarkerClipRect: series.line._applyElementsClipRect,
            _parsePointStyle: function(style, defaultColor, defaultBorderColor) {
                var color = this._createPattern(style.color || defaultColor, style.hatching),
                    base = scatterSeries._parsePointStyle.call(this, style, color, defaultBorderColor);
                base.fill = color;
                base.opacity = style.opacity;
                delete base.r;
                return base
            },
            _createMarkerGroup: function() {
                var markersSettings = this._getPointOptions().styles.normal,
                    groupSettings;
                markersSettings["class"] = "dxc-markers";
                this._applyMarkerClipRect(markersSettings);
                groupSettings = _extend({}, markersSettings);
                delete groupSettings.opacity;
                this._createGroup("_markersGroup", this, this._group, groupSettings)
            },
            _getCreatingPointOptions: function() {
                if (!this._predefinedPointOptions) {
                    var styles,
                        defaultPointOptions = this._getPointOptions(),
                        strokeWidth = defaultPointOptions.styles && defaultPointOptions.styles.normal && defaultPointOptions.styles.normal.strokeWidth,
                        r = defaultPointOptions.styles && defaultPointOptions.styles.normal && defaultPointOptions.styles.normal.r,
                        opacity = defaultPointOptions.styles && defaultPointOptions.styles.normal && defaultPointOptions.styles.normal.opacity,
                        creatingPointOptions = _extend(true, {}, defaultPointOptions);
                    creatingPointOptions.styles = styles = creatingPointOptions.styles || {};
                    styles.normal = {
                        strokeWidth: strokeWidth,
                        r: r,
                        opacity: opacity
                    };
                    this._predefinedPointOptions = creatingPointOptions
                }
                return this._predefinedPointOptions
            },
            _checkData: function(data) {
                return _isDefined(data.argument) && _isDefined(data.size) && data.value !== undefined
            },
            _getPointData: function(data, options) {
                var pointData = scatterSeries._getPointData.call(this, data, options),
                    sizeField = options.sizeField || "size";
                pointData.size = data[sizeField];
                return pointData
            },
            _fusionPoints: function(fusionPoints, tick, index) {
                var medianValue = scatterSeries._calcMedianValue.call(this, fusionPoints, "value"),
                    medianSize = scatterSeries._calcMedianValue.call(this, fusionPoints, "size");
                return {
                        size: medianSize,
                        value: medianValue,
                        argument: tick,
                        tag: null
                    }
            },
            getValueFields: function() {
                return [this._options.valueField || "val", this._options.sizeField || "size"]
            },
            updateTeamplateFieldNames: function() {
                var that = this,
                    options = that._options,
                    valueFields = that.getValueFields(),
                    name = that.name;
                options.valueField = valueFields[0] + name;
                options.sizeField = valueFields[1] + name;
                options.tagField = that.getTagField() + name
            },
            _clearingAnimation: function(translators, drawComplete) {
                var that = this,
                    settings = {r: 0},
                    partitionDuration = 0.5,
                    lastPointIndex = that._drawedPoints.length - 1;
                that._labelsGroup && that._labelsGroup.animate({opacity: 0.001}, {
                    duration: that._defaultDuration,
                    partitionDuration: partitionDuration
                }, function() {
                    _each(that._drawedPoints || [], function(i, p) {
                        p.animate(i === lastPointIndex ? drawComplete : undefined, settings, partitionDuration)
                    })
                })
            },
            _animate: function(firstDrawing) {
                var that = this,
                    lastPointIndex = that._drawedPoints.length - 1,
                    labelAnimFunc = function() {
                        that._labelsGroup && that._labelsGroup.animate({opacity: 1}, {duration: that._defaultDuration})
                    };
                _each(that._drawedPoints || [], function(i, p) {
                    p.animate(i === lastPointIndex ? labelAnimFunc : undefined, {
                        r: p.bubbleSize,
                        translate: {
                            x: p.x,
                            y: p.y
                        }
                    })
                })
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file pieSeries.js */
    (function($, DX) {
        var viz = DX.viz,
            mixins = viz.core.series.mixins,
            pieSeries = mixins.pieChart,
            utils = DX.utils,
            scatterSeries = mixins.chart.scatter,
            barSeries = mixins.chart.bar,
            _extend = $.extend,
            _each = $.each,
            _noop = $.noop,
            _map = $.map,
            _isFinite = isFinite,
            _max = Math.max;
        pieSeries.pie = _extend({}, barSeries, {
            _createLabelGroup: scatterSeries._createLabelGroup,
            _createGroups: scatterSeries._createGroups,
            _drawPoint: function(point) {
                scatterSeries._drawPoint.apply(this, arguments);
                !point.isVisible() && point.setInvisibility()
            },
            _applyTrackersClippings: _noop,
            _processRange: _noop,
            _applyElementsClipRect: _noop,
            _updateDataType: _noop,
            getColor: _noop,
            _prepareSeriesToDrawing: _noop,
            _endUpdateData: scatterSeries._prepareSeriesToDrawing,
            resetLabelEllipsis: function() {
                _each(this._points || [], function(_, point) {
                    point._label.setLabelEllipsis = false
                })
            },
            _adjustLabels: function(firstDrawing) {
                var that = this,
                    options = that._options,
                    canvas = that.canvas,
                    points = that._points || [],
                    labelsBBoxes = [],
                    labelsSpaces = [],
                    labelSpace = 0,
                    maxLabelLength,
                    paneSpaceHeight,
                    paneSpaceWidth,
                    min;
                if (options.label.position !== "inside") {
                    _each(points, function(_, point) {
                        if (point._label.hasText())
                            labelsBBoxes.push(point._label.getTextCoords().width)
                    });
                    if (labelsBBoxes.length) {
                        maxLabelLength = _max.apply(null, labelsBBoxes);
                        _each(points, function(_, point) {
                            if (point._label.hasText()) {
                                point._label.updatePosition(maxLabelLength);
                                point._label.setLabelEllipsis = true
                            }
                        });
                        that._firstDrawing = !that.redraw && firstDrawing;
                        that.redraw = true
                    }
                }
                else
                    _each(points, function(i, point) {
                        if (point._label.hasText()) {
                            point._label.setLabelEllipsis = true;
                            point._label.updatePosition()
                        }
                    })
            },
            _getCreatingPointOptions: function() {
                return this._getPointOptions()
            },
            _updateOptions: function(options) {
                this.labelSpace = 0;
                this.innerRadius = this.type === "pie" ? 0 : options.innerRadius;
                this.redraw = false
            },
            _checkData: function(data) {
                var base = barSeries._checkData(data);
                return this._options.paintNullPoints ? base : base && data.value !== null
            },
            _createMarkerGroup: function() {
                if (!this._markersGroup)
                    this._markersGroup = this._renderer.createGroup({"class": "dxc-markers"}).append(this._group)
            },
            _getMainColor: function() {
                return this._options.mainSeriesColor()
            },
            _getPointOptions: function() {
                return this._parsePointOptions(this._preparePointOptions(), this._options.label)
            },
            _getRangeData: function() {
                return this._rangeData
            },
            _getArrangeTotal: function(points) {
                var total = 0;
                _each(points, function(_, point) {
                    if (point.isVisible())
                        total += point.initialValue
                });
                return total
            },
            _createPointStyles: function(pointOptions) {
                var mainColor = pointOptions.color || this._getMainColor(),
                    specialMainColor = this._getSpecialColor(mainColor);
                return {
                        normal: this._parsePointStyle(pointOptions, mainColor, mainColor),
                        hover: this._parsePointStyle(pointOptions.hoverStyle, specialMainColor, mainColor),
                        selection: this._parsePointStyle(pointOptions.selectionStyle, specialMainColor, mainColor),
                        legendStyles: {
                            normal: this._createLegendState(pointOptions, mainColor),
                            hover: this._createLegendState(pointOptions.hoverStyle, specialMainColor),
                            selection: this._createLegendState(pointOptions.selectionStyle, specialMainColor)
                        }
                    }
            },
            _getArrangeMinShownValue: function(points, total) {
                var minSegmentSize = this._options.minSegmentSize,
                    totalMinSegmentSize = 0,
                    totalNotMinValues = 0;
                total = total || points.length;
                _each(points, function(_, point) {
                    if (point.isVisible())
                        if (point.initialValue < minSegmentSize * total / 360)
                            totalMinSegmentSize += minSegmentSize;
                        else
                            totalNotMinValues += point.initialValue
                });
                return totalMinSegmentSize < 360 ? minSegmentSize * totalNotMinValues / (360 - totalMinSegmentSize) : 0
            },
            _applyArrangeCorrection: function(points, minShownValue, total) {
                var options = this._options,
                    isClockWise = options.segmentsDirection !== "anticlockwise",
                    shiftedAngle = _isFinite(options.startAngle) ? utils.normalizeAngle(options.startAngle) : 0,
                    minSegmentSize = options.minSegmentSize,
                    percent,
                    correction = 0,
                    zeroTotalCorrection = 0;
                if (total === 0) {
                    total = points.length;
                    zeroTotalCorrection = 1
                }
                _each(isClockWise ? points : points.concat([]).reverse(), function(_, point) {
                    var val = point.isVisible() ? zeroTotalCorrection || point.initialValue : 0,
                        updatedZeroValue;
                    if (minSegmentSize && point.isVisible() && val < minShownValue)
                        updatedZeroValue = minShownValue;
                    percent = val / total;
                    point.correctValue(correction, percent, zeroTotalCorrection + (updatedZeroValue || 0));
                    point.shiftedAngle = shiftedAngle;
                    correction = correction + (updatedZeroValue || val)
                });
                this._rangeData = {val: {
                        min: 0,
                        max: correction
                    }}
            },
            arrangePoints: function() {
                var that = this,
                    minSegmentSize = that._options.minSegmentSize,
                    minShownValue,
                    pointIndex = 0,
                    total,
                    points = that._originalPoints = that._points = _map(that._originalPoints || [], function(point) {
                        if (point.value === null || point.value < 0 || point.value === 0 && !minSegmentSize) {
                            point.dispose();
                            return null
                        }
                        else {
                            point.index = pointIndex++;
                            return point
                        }
                    });
                total = that._getArrangeTotal(points);
                if (minSegmentSize)
                    minShownValue = this._getArrangeMinShownValue(points, total);
                that._applyArrangeCorrection(points, minShownValue, total)
            },
            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)
                })
            },
            _animate: function(firstDrawing) {
                var that = this,
                    index = 0,
                    timeThreshold = 0.2,
                    points = that._points,
                    pointsCount = points && points.length,
                    duration = 1 / (timeThreshold * (pointsCount - 1) + 1),
                    animateP = function() {
                        points[index] && points[index++].animate(index === pointsCount ? completeFunc : undefined, duration, stepFunc)
                    },
                    stepFunc = function(_, progress) {
                        if (progress >= timeThreshold) {
                            this.step = null;
                            animateP()
                        }
                    },
                    completeFunc = function() {
                        that._labelsGroup && that._labelsGroup.animate({opacity: 1}, {duration: 400})
                    };
                if (firstDrawing)
                    animateP();
                else
                    $.each(points, function(i, p) {
                        p.animate(i == pointsCount - 1 ? completeFunc : undefined)
                    })
            },
            getVisiblePoints: function() {
                return _map(this._points, function(p) {
                        return p.isVisible() ? p : null
                    })
            },
            _beginUpdateData: function() {
                this._deletePatterns();
                this._patterns = []
            }
        });
        pieSeries.doughnut = pieSeries.donut = pieSeries.pie
    })(jQuery, DevExpress);
    /*! Module viz-core, file financialSeries.js */
    (function($, DX) {
        var viz = DX.viz,
            series = viz.core.series.mixins.chart,
            scatterSeries = series.scatter,
            barSeries = series.bar,
            rangeCalculator = viz.core.series.helpers.rangeDataCalculator(),
            _isDefined = DX.utils.isDefined,
            _extend = $.extend,
            _each = $.each,
            _noop = $.noop,
            DEFAULT_FINANCIAL_POINT_SIZE = 10;
        series.stock = _extend({}, scatterSeries, {
            _animate: _noop,
            _applyMarkerClipRect: series.line._applyElementsClipRect,
            _applyTrackersClippings: barSeries._applyTrackersClippings,
            _createPattern: barSeries._createPattern,
            _preparePointOptions: barSeries._preparePointOptions,
            _createMarkerGroup: function() {
                var that = this,
                    markersGroup,
                    styles = that._getPointOptions().styles,
                    defaultStyle = styles.normal,
                    defaultPositiveStyle = styles.positive.normal,
                    reductionStyle = styles.reduction.normal,
                    reductionPositiveStyle = styles.reductionPositive.normal,
                    markerSettings = {"class": "dxc-markers"};
                that._applyMarkerClipRect(markerSettings);
                defaultStyle["class"] = "default-markers";
                defaultPositiveStyle["class"] = "default-positive-markers";
                reductionStyle["class"] = "reduction-markers";
                reductionPositiveStyle["class"] = "reduction-positive-markers";
                that._createGroup("_markersGroup", that, that._group, markerSettings);
                markersGroup = that._markersGroup;
                that._createGroup("defaultMarkersGroup", markersGroup, markersGroup, defaultStyle);
                that._createGroup("reductionMarkersGroup", markersGroup, markersGroup, reductionStyle);
                that._createGroup("defaultPositiveMarkersGroup", markersGroup, markersGroup, defaultPositiveStyle);
                that._createGroup("reductionPositiveMarkersGroup", markersGroup, markersGroup, reductionPositiveStyle)
            },
            _createGroups: function() {
                scatterSeries._createGroups.call(this, false)
            },
            _clearingAnimation: function(translators, drawComplete) {
                drawComplete()
            },
            _getCreatingPointOptions: function() {
                if (!this._predefinedPointOptions) {
                    var styles,
                        defaultPointOptions = this._getPointOptions(),
                        strokeWidth = defaultPointOptions.styles && defaultPointOptions.styles.normal && defaultPointOptions.styles.normal.strokeWidth,
                        creatingPointOptions = _extend(true, {}, defaultPointOptions);
                    creatingPointOptions.styles = styles = creatingPointOptions.styles || {};
                    styles.normal = styles.positive.normal = styles.reduction.normal = styles.reductionPositive.normal = {strokeWidth: strokeWidth};
                    this._predefinedPointOptions = creatingPointOptions
                }
                return this._predefinedPointOptions
            },
            _checkData: function(data) {
                return _isDefined(data.argument) && data.highValue !== undefined && data.lowValue !== undefined && data.openValue !== undefined && data.closeValue !== undefined
            },
            _processRange: function(point, prevPoint) {
                rangeCalculator.processTwoValues(this, point, prevPoint, "highValue", "lowValue")
            },
            _getRangeData: function(zoomArgs, calcIntervalFunction) {
                rangeCalculator.calculateTwoValuesRangeData(this, zoomArgs, calcIntervalFunction, "highValue", "lowValue");
                rangeCalculator.addRangeSeriesLabelPaddings(this);
                return this._rangeData
            },
            _getPointData: function(data, options) {
                var that = this,
                    level,
                    argumentField = options.argumentField || "date",
                    tagField = options.tagField || "tag",
                    openValueField = options.openValueField || "open",
                    closeValueField = options.closeValueField || "close",
                    highValueField = options.highValueField || "high",
                    lowValueField = options.lowValueField || "low",
                    reductionValue;
                that.level = options.reduction.level;
                switch ((that.level || "").toLowerCase()) {
                    case"open":
                        level = openValueField;
                        break;
                    case"high":
                        level = highValueField;
                        break;
                    case"low":
                        level = lowValueField;
                        break;
                    default:
                        level = closeValueField;
                        that.level = "close";
                        break
                }
                reductionValue = data[level];
                return {
                        argument: data[argumentField],
                        highValue: data[highValueField],
                        lowValue: data[lowValueField],
                        closeValue: data[closeValueField],
                        openValue: data[openValueField],
                        reductionValue: reductionValue,
                        tag: data[tagField],
                        isReduction: this._checkReduction(reductionValue)
                    }
            },
            _parsePointStyle: function(style, defaultColor, innerColor) {
                return {
                        stroke: style.color || defaultColor,
                        strokeWidth: style.width,
                        fill: style.color || innerColor
                    }
            },
            updateTeamplateFieldNames: function() {
                var that = this,
                    options = that._options,
                    valueFields = that.getValueFields(),
                    name = that.name;
                options.openValueField = valueFields[0] + name;
                options.highValueField = valueFields[1] + name;
                options.lowValueField = valueFields[2] + name;
                options.closeValueField = valueFields[3] + name;
                options.tagField = that.getTagField() + name
            },
            _getDefaultStyle: function(options) {
                var mainPointColor = options.color || this._options.mainSeriesColor;
                return {
                        normal: this._parsePointStyle(options, mainPointColor, mainPointColor),
                        hover: this._parsePointStyle(options.hoverStyle, mainPointColor, mainPointColor),
                        selection: this._parsePointStyle(options.selectionStyle, mainPointColor, mainPointColor)
                    }
            },
            _getReductionStyle: function(options) {
                var reductionColor = options.reduction.color,
                    normalStyle = this._parsePointStyle({
                        color: reductionColor,
                        width: options.width,
                        hatching: options.hatching
                    }, reductionColor, reductionColor);
                return {
                        normal: normalStyle,
                        hover: this._parsePointStyle(options.hoverStyle, reductionColor, reductionColor),
                        selection: this._parsePointStyle(options.selectionStyle, reductionColor, reductionColor)
                    }
            },
            _createPointStyles: function(pointOptions) {
                var that = this,
                    innerColor = that._options.innerColor,
                    styles = that._getDefaultStyle(pointOptions),
                    positiveStyle,
                    reductionStyle,
                    reductionPositiveStyle;
                positiveStyle = _extend(true, {}, styles);
                reductionStyle = that._getReductionStyle(pointOptions);
                reductionPositiveStyle = _extend(true, {}, reductionStyle);
                positiveStyle.normal.fill = positiveStyle.hover.fill = positiveStyle.selection.fill = innerColor;
                reductionPositiveStyle.normal.fill = reductionPositiveStyle.hover.fill = reductionPositiveStyle.selection.fill = innerColor;
                styles.positive = positiveStyle;
                styles.reduction = reductionStyle;
                styles.reductionPositive = reductionPositiveStyle;
                return styles
            },
            _endUpdateData: function() {
                delete this.prevLevelValue;
                delete this._predefinedPointOptions
            },
            _checkReduction: function(value) {
                var result = false;
                if (value != null) {
                    if (_isDefined(this.prevLevelValue))
                        result = value < this.prevLevelValue;
                    this.prevLevelValue = value
                }
                return result
            },
            _fusionPoints: function(fusionPoints, tick, nowIndexTicks) {
                var fusedPointData = {},
                    reductionLevel,
                    highValue = -Infinity,
                    lowValue = +Infinity,
                    openValue,
                    closeValue;
                if (!fusionPoints.length)
                    return {};
                _each(fusionPoints, function(_, point) {
                    if (!point.hasValue())
                        return;
                    highValue = Math.max(highValue, point.highValue);
                    lowValue = Math.min(lowValue, point.lowValue);
                    openValue = openValue !== undefined ? openValue : point.openValue;
                    closeValue = point.closeValue !== undefined ? point.closeValue : closeValue
                });
                fusedPointData.argument = tick;
                fusedPointData.openValue = openValue;
                fusedPointData.closeValue = closeValue;
                fusedPointData.highValue = highValue;
                fusedPointData.lowValue = lowValue;
                fusedPointData.tag = null;
                switch ((this.level || "").toLowerCase()) {
                    case"open":
                        reductionLevel = openValue;
                        break;
                    case"high":
                        reductionLevel = highValue;
                        break;
                    case"low":
                        reductionLevel = lowValue;
                        break;
                    default:
                        reductionLevel = closeValue;
                        break
                }
                fusedPointData.reductionValue = reductionLevel;
                fusedPointData.isReduction = this._checkReduction(reductionLevel);
                return fusedPointData
            },
            _getPointSize: function() {
                return DEFAULT_FINANCIAL_POINT_SIZE
            },
            getValueFields: function() {
                var options = this._options;
                return [options.openValueField || "open", options.highValueField || "high", options.lowValueField || "low", options.closeValueField || "close"]
            },
            getArgumentField: function() {
                return this._options.argumentField || "date"
            }
        });
        series.candlestick = _extend({}, series.stock, {_parsePointStyle: function(style, defaultColor, innerColor) {
                var color = this._createPattern(style.color || innerColor, style.hatching),
                    base = series.stock._parsePointStyle.call(this, style, defaultColor, color);
                base.fill = color;
                return base
            }})
    })(jQuery, DevExpress);
    /*! Module viz-core, file stackedSeries.js */
    (function($, DX) {
        var viz = DX.viz,
            series = viz.core.series.mixins.chart,
            areaSeries = series.area,
            barSeries = series.bar,
            lineSeries = series.line,
            rangeCalculator = viz.core.series.helpers.rangeDataCalculator(),
            _extend = $.extend,
            _noop = $.noop,
            baseStackedSeries = {
                _processRange: _noop,
                _processStackedRange: function() {
                    var that = this,
                        prevPoint;
                    $.each(that.getAllPoints(), function(i, p) {
                        rangeCalculator.processRange(that, p, prevPoint);
                        prevPoint = p
                    })
                },
                _getRangeData: function() {
                    this._processStackedRange();
                    return areaSeries._getRangeData.apply(this, arguments)
                }
            },
            baseFullStackedSeries = _extend({}, baseStackedSeries, {
                _getRangeData: function(zoomArgs, calcIntervalFunction) {
                    this._processStackedRange();
                    rangeCalculator.calculateRangeData(this, zoomArgs, calcIntervalFunction);
                    rangeCalculator.addLabelPaddings(this);
                    rangeCalculator.processFullStackedRange(this);
                    rangeCalculator.calculateRangeMinValue(this, zoomArgs);
                    return this._rangeData
                },
                isFullStackedSeries: function() {
                    return true
                }
            });
        series.stackedline = _extend({}, lineSeries, baseStackedSeries, {_getRangeData: function() {
                this._processStackedRange();
                return lineSeries._getRangeData.apply(this, arguments)
            }});
        series.fullstackedline = _extend({}, lineSeries, baseFullStackedSeries, {_getRangeData: function(zoomArgs, calcIntervalFunction) {
                this._processStackedRange();
                var rangeCalculator = viz.core.series.helpers.rangeDataCalculator();
                rangeCalculator.calculateRangeData(this, zoomArgs, calcIntervalFunction);
                rangeCalculator.addLabelPaddings(this);
                rangeCalculator.processFullStackedRange(this);
                return this._rangeData
            }});
        series.stackedbar = _extend({}, barSeries, baseStackedSeries, {_getRangeData: function() {
                this._processStackedRange();
                return barSeries._getRangeData.apply(this, arguments)
            }});
        series.fullstackedbar = _extend({}, barSeries, baseFullStackedSeries, {_getRangeData: function(zoomArgs, calcIntervalFunction) {
                var rangeData = baseFullStackedSeries._getRangeData.apply(this, arguments);
                rangeData.arg.stick = false;
                return rangeData
            }});
        series.stackedarea = _extend({}, areaSeries, baseStackedSeries);
        series.fullstackedarea = _extend({}, areaSeries, baseFullStackedSeries)
    })(jQuery, DevExpress);
    /*! Module viz-core, file basePoint.js */
    (function($, DX) {
        var viz = DX.viz,
            statesConsts = viz.core.series.helpers.consts.states,
            _each = $.each,
            _extend = $.extend,
            _isDefined = DX.utils.isDefined,
            _noop = $.noop,
            pointTypes = {
                scatter: "symbolPoint",
                line: "symbolPoint",
                spline: "symbolPoint",
                stepline: "symbolPoint",
                stackedline: "symbolPoint",
                fullstackedline: "symbolPoint",
                area: "symbolPoint",
                splinearea: "symbolPoint",
                steparea: "symbolPoint",
                stackedarea: "symbolPoint",
                fullstackedarea: "symbolPoint",
                rangearea: "rangeSymbolPoint",
                bar: "barPoint",
                stackedbar: "barPoint",
                fullstackedbar: "barPoint",
                rangebar: "rangeBarPoint",
                bubble: "bubblePoint",
                pie: "piePoint",
                doughnut: "piePoint",
                donut: "piePoint",
                stock: "stockPoint",
                candlestick: "candlestickPoint"
            };
        viz.core.series.points = {};
        viz.core.series.points.Point = DX.Class.inherit({
            ctor: function(dataItem, options) {
                this.update(dataItem, options);
                this._emptySettings = {
                    fill: null,
                    stroke: null
                }
            },
            getColor: function() {
                return this._styles.normal.fill || this.series.getColor()
            },
            _getStyle: function() {
                var styles = this._styles,
                    style;
                if (this.isSelected())
                    style = styles.selection;
                else if (this.isHovered())
                    style = styles.hover;
                else {
                    this.fullState = statesConsts.normalMark;
                    style = styles.normal
                }
                return style
            },
            update: function(dataItem, options) {
                this.updateOptions(options);
                this.updateData(dataItem)
            },
            updateData: function(dataItem) {
                this._updateData(dataItem);
                if (!this.hasValue())
                    this.setInvisibility();
                else {
                    this._updateLabelData();
                    this._fillStyle()
                }
            },
            deleteMarker: function() {
                this.graphic && this.graphic.detach();
                this.graphic = null
            },
            deleteTrackerMarker: function() {
                this.trackerGraphic && this.trackerGraphic.remove();
                this.trackerGraphic = null
            },
            draw: function(renderer, markersGroup, labelsGroup, animationEnabled, firstDrawing) {
                if (this._needDeletingOnDraw) {
                    this.deleteMarker();
                    this.deleteTrackerMarker();
                    this._needDeletingOnDraw = false
                }
                if (this._needClearingOnDraw) {
                    this.clearMarker();
                    this._needClearingOnDraw = false
                }
                if (!this._hasGraphic())
                    this._options.visible && this._drawMarker(renderer, markersGroup, animationEnabled, firstDrawing);
                else
                    this._updateMarker(animationEnabled, undefined, markersGroup);
                this._drawLabel(renderer, labelsGroup)
            },
            applyStyle: function(style) {
                if (this.graphic) {
                    if (style === "normal")
                        this.clearMarker();
                    else
                        this.graphic.toForeground();
                    this._updateMarker(true, this._styles[style])
                }
            },
            setHoverState: function() {
                this.series.setPointHoverState(this)
            },
            releaseHoverState: function(callback) {
                this.series.releasePointHoverState(this, callback);
                if (this.graphic)
                    !this.isSelected() && this.graphic.toBackground()
            },
            setSelectedState: function() {
                this.series.setPointSelectedState(this)
            },
            releaseSelectedState: function() {
                this.series.releasePointSelectedState(this)
            },
            select: function() {
                this.series.selectPoint(this)
            },
            clearSelection: function() {
                this.series.deselectPoint(this)
            },
            showTooltip: function() {
                this.series.showPointTooltip(this)
            },
            hideTooltip: function() {
                this.series.hidePointTooltip(this)
            },
            _checkLabelsChanging: function(oldType, newType) {
                if (oldType) {
                    var isNewRange = ~newType.indexOf("range"),
                        isOldRange = ~oldType.indexOf("range");
                    return isOldRange && !isNewRange || !isOldRange && isNewRange
                }
                else
                    return false
            },
            updateOptions: function(newOptions) {
                if (!_isDefined(newOptions))
                    return;
                var that = this,
                    oldOptions = that._options,
                    oldType = oldOptions && oldOptions.type,
                    newType = newOptions.type;
                if (pointTypes[oldType] !== pointTypes[newType]) {
                    that._needDeletingOnDraw = true;
                    that._needClearingOnDraw = false;
                    that._checkLabelsChanging(oldType, newType) && that.deleteLabel();
                    that._resetType(oldType);
                    that._setType(newType)
                }
                else {
                    that._needDeletingOnDraw = that._checkSymbol(oldOptions, newOptions);
                    that._needClearingOnDraw = that._checkCustomize(oldOptions, newOptions)
                }
                that.series = newOptions.series;
                that._options = newOptions;
                that._fillStyle();
                that._updateLabelOptions(pointTypes[newType])
            },
            translate: function(translators) {
                this.translators = translators || this.translators;
                this.translators && this.hasValue() && this._translate(this.translators)
            },
            drawTracker: function(renderer, group) {
                if (!this.trackerGraphic)
                    this._drawTrackerMarker(renderer, group);
                else
                    this._updateTracker()
            },
            _checkCustomize: function(oldOptions, newOptions) {
                return oldOptions.styles.usePointCustomOptions && !newOptions.styles.usePointCustomOptions
            },
            _getCustomLabelVisibility: function() {
                if (this._styles.useLabelCustomOptions)
                    return this._options.label.visible ? "visible" : "hidden"
            },
            _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
                    }
            },
            _resetType: function(type) {
                var that = this;
                if (type)
                    _each(viz.core.series.points.mixins[pointTypes[type]], function(methodName) {
                        delete that[methodName]
                    })
            },
            _setType: function(type) {
                var that = this;
                _each(viz.core.series.points.mixins[pointTypes[type]], function(methodName, method) {
                    that[methodName] = method
                })
            },
            _prepareStatesOptions: function() {
                var that = this;
                if (that._options.states && that._options.states.normal)
                    that._populatePointShape(that._options.states.normal.r)
            },
            isInVisibleArea: function() {
                return this.inVisibleArea
            },
            isSelected: function() {
                return !!(this.fullState & statesConsts.selectedMark)
            },
            isHovered: function() {
                return !!(this.fullState & statesConsts.hoverMark)
            },
            getOptions: function() {
                return this._options
            },
            animate: function(complete, settings, partitionDuration) {
                if (!this.graphic) {
                    complete && complete();
                    return
                }
                this.graphic.animate(settings, {partitionDuration: partitionDuration}, complete)
            },
            getCoords: function(min) {
                if (!min)
                    return {
                            x: this.x,
                            y: this.y
                        };
                if (!this._options.rotated)
                    return {
                            x: this.x,
                            y: this.minY
                        };
                return {
                        x: this.minX,
                        y: this.y
                    }
            },
            getDefaultCoords: function() {
                return !this._options.rotated ? {
                        x: this.x,
                        y: this.defaultY
                    } : {
                        x: this.defaultX,
                        y: this.y
                    }
            },
            _calculateVisibility: function(x, y, width, height) {
                var that = this,
                    visibleAreaX,
                    visibleAreaY,
                    rotated = that._options.rotated;
                if (that.translators) {
                    visibleAreaX = that.translators.x.getCanvasVisibleArea();
                    visibleAreaY = that.translators.y.getCanvasVisibleArea();
                    if (visibleAreaX.min > x + (width || 0) || visibleAreaX.max < x || visibleAreaY.min > y + (height || 0) || visibleAreaY.max < y || rotated && _isDefined(width) && width !== 0 && (visibleAreaX.min === x + width || visibleAreaX.max === x) || !rotated && _isDefined(height) && height !== 0 && (visibleAreaY.min === y + height || visibleAreaY.max === y))
                        that.inVisibleArea = false;
                    else
                        that.inVisibleArea = true
                }
            },
            correctPosition: _noop,
            hasValue: function() {
                return this.value !== null && this.minValue !== null
            },
            _populatePointShape: _noop,
            _checkSymbol: _noop,
            hide: _noop,
            show: _noop,
            hideMarker: _noop,
            setInvisibility: _noop,
            clearVisibility: _noop,
            isVisible: _noop,
            resetCorrection: _noop,
            correctValue: _noop,
            setPercentValue: _noop,
            correctCoordinates: _noop,
            dispose: function() {
                this.deleteMarker();
                this.deleteTrackerMarker();
                this.deleteLabel();
                this._options = null;
                this._styles = null;
                this.series = null;
                this.translators = null
            },
            getTooltipFormatObject: function(tooltip) {
                var that = this,
                    tooltipFormatObject = that._getFormatObject(tooltip),
                    sharedTooltipValuesArray = [],
                    tooltipStackPointsFormatObject = [];
                if (that.stackPoints) {
                    _each(that.stackPoints, function(_, point) {
                        if (!point.isVisible())
                            return;
                        var formatObject = point._getFormatObject(tooltip);
                        tooltipStackPointsFormatObject.push(point._getFormatObject(tooltip));
                        sharedTooltipValuesArray.push(formatObject.seriesName + ": " + formatObject.valueText)
                    });
                    _extend(tooltipFormatObject, {
                        points: tooltipStackPointsFormatObject,
                        valueText: sharedTooltipValuesArray.join("\n"),
                        stackName: that.stackPoints.stackName
                    })
                }
                return tooltipFormatObject
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file label.js */
    (function($, DX) {
        var _isDefined = DX.utils.isDefined,
            _extend = $.extend,
            _math = Math,
            _round = _math.round,
            _floor = _math.floor,
            _isEmptyObject = $.isEmptyObject,
            _noop = $.noop,
            LABEL_BACKGROUND_PADDING_X = 8,
            LABEL_BACKGROUND_PADDING_Y = 4,
            LABEL_OFFSET = 10,
            setPositionFuncCollection = {
                symbolPoint: "_setPositionForSymbol",
                barPoint: "_setPositionForBar",
                bubblePoint: "_setPositionForBubble",
                rangeSymbolPoint: "_setPositionForSymbol",
                rangeBarPoint: "_setPositionForBar",
                stockPoint: "_setPositionForFinancial",
                candlestickPoint: "_setPositionForFinancial"
            },
            checkPositionFuncCollection = {
                symbolPoint: "_checkPositionForSymbol",
                barPoint: "_checkPositionForBar",
                bubblePoint: "_checkPositionForSymbol",
                rangeSymbolPoint: "_checkPositionForSymbol",
                rangeBarPoint: "_checkPositionForBar",
                stockPoint: "_checkPositionForBar",
                candlestickPoint: "_checkPositionForBar"
            };
        DX.viz.core.series.points.Label = DX.Class.inherit({
            ctor: function(data, options) {
                this._offset = LABEL_OFFSET;
                this.updateData(data);
                this.setOptions(options)
            },
            clearVisibility: function() {
                if (this._group && this._group.settings.visibility)
                    this._group.applySettings({visibility: null})
            },
            hide: function() {
                if (this._group && this._group.settings.visibility !== "hidden")
                    this._group.applySettings({visibility: "hidden"})
            },
            updateData: function(data) {
                if (_isDefined(data)) {
                    this._data = data.formatObject;
                    this._initialValue = data.initialValue
                }
            },
            updateOptions: function(options) {
                this.setOptions(_extend(true, {}, {options: this._options}, options))
            },
            setOptions: function(newOptions) {
                var that = this,
                    oldOptions = that._options,
                    newOptions = newOptions || {},
                    pointType = newOptions.type || "symbolPoint";
                that._options = newOptions.options;
                that._rotated = newOptions.rotated;
                that._isFullStacked = newOptions.isFullStacked;
                that._isRange = newOptions.isRange;
                that._setPosition = that[setPositionFuncCollection[pointType]];
                that._checkPosition = that[checkPositionFuncCollection[pointType]];
                if (oldOptions) {
                    that._isBackgroundChanged(oldOptions.background, that._options.background) && that._deleteBackground();
                    that._isConnectorChanged(oldOptions.connector, that._options.connector) && that._deleteConnector()
                }
            },
            setDataField: function(fieldName, fieldValue) {
                this._data = this._data || {};
                this._data[fieldName] = fieldValue
            },
            getData: function() {
                return this._data
            },
            setCoords: function(coords, graphicBbox, location, visibleArea) {
                this._coords = coords;
                this._graphicBbox = graphicBbox;
                this._visibleArea = visibleArea;
                this._location = location
            },
            hasText: function() {
                return !!this._text
            },
            getTextCoords: function() {
                return this._text && this._text.getBBox()
            },
            getCoords: function() {
                var coords = {},
                    insideGroup = this._insideGroup;
                if (insideGroup) {
                    coords = insideGroup.getBBox();
                    coords.x = insideGroup.settings.translateX || 0;
                    coords.y = insideGroup.settings.translateY || 0
                }
                return coords
            },
            updatePosition: function(x, y) {
                var settings = {},
                    insideGroup = this._insideGroup;
                insideGroup.applySettings({
                    translateX: x,
                    translateY: y
                });
                this._connector && this._drawConnector()
            },
            _deleteElements: function() {
                this._deleteConnector();
                this._deleteBackground();
                this._deleteText();
                this._deleteGroups()
            },
            dispose: function() {
                this._data = null;
                this._options = null;
                this._positioningFunction = null;
                this._graphicBbox = null;
                this._visibleArea = null;
                this._coords = null;
                this._deleteElements()
            },
            _deleteText: function() {
                this._text && this._text.detach();
                this._text = null
            },
            _deleteGroups: function() {
                this._insideGroup = null;
                this._group && this._group.detach();
                this._group = null
            },
            _drawGroups: function(renderer, group) {
                if (!this._group)
                    this._group = renderer.createGroup().append(group);
                if (!this._insideGroup)
                    this._insideGroup = renderer.createGroup().append(this._group)
            },
            _drawText: function(renderer, text) {
                if (!this._text)
                    this._text = renderer.createText(text, 0, 0, this._options.attributes).append(this._insideGroup);
                else
                    this._text.applySettings({text: text}, this._options.attributes)
            },
            _drawBackground: function(renderer) {
                var that = this,
                    options = that._options,
                    background = options.background || {},
                    settings;
                if (that._checkBackground(background)) {
                    settings = _extend(that._getBackgroundSettings(), background);
                    if (!that._background)
                        that._background = renderer.createRect(settings.x, settings.y, settings.width, settings.height, 0, background).append(that._insideGroup);
                    else
                        that._background.applySettings(settings);
                    that._background.toBackground()
                }
            },
            _drawConnector: function(renderer) {
                var that = this,
                    connector = that._options.connector || {},
                    points;
                if (that._checkConnector(connector)) {
                    points = that._getConnectorPoints() || [];
                    if (!that._connector)
                        that._connector = renderer.createPath(points, connector).append(that._group);
                    else
                        that._connector.applySettings(_extend({points: points}, connector));
                    that._connector.toBackground()
                }
            },
            _setVisibility: function(visibility) {
                this._group && this._group.applySettings({visibility: visibility})
            },
            draw: function(renderer, group, visibility) {
                var that = this,
                    options = that._options,
                    background = options.background,
                    text = that._format();
                if (_isDefined(text) && text !== "") {
                    that._drawGroups(renderer, group);
                    that._setVisibility(visibility);
                    that._drawText(renderer, text);
                    that._drawBackground(renderer);
                    that._rotateLabel();
                    that._setPosition();
                    that._drawConnector(renderer)
                }
                else
                    that._setVisibility("hidden")
            },
            _deleteBackground: function() {
                this._background && this._background.detach();
                this._background = null
            },
            _isBackgroundChanged: function(oldBackground, newBackground) {
                return this._checkBackground(oldBackground || {}) !== this._checkBackground(newBackground || {})
            },
            _checkBackground: function(background) {
                var hasColor = background.fill && background.fill !== "none",
                    hasBorder = background.strokeWidth && background.stroke && background.stroke !== "none";
                return hasColor || hasBorder
            },
            _getBackgroundSettings: function() {
                var bbox = this._text.getBBox();
                return {
                        x: bbox.x - LABEL_BACKGROUND_PADDING_X,
                        y: bbox.y - LABEL_BACKGROUND_PADDING_Y,
                        width: bbox.width + 2 * LABEL_BACKGROUND_PADDING_X,
                        height: bbox.height + 2 * LABEL_BACKGROUND_PADDING_Y
                    }
            },
            _deleteConnector: function() {
                this._connector && this._connector.detach();
                this._connector = null
            },
            _isConnectorChanged: function(oldConnector, newConnector) {
                return this._checkConnector(oldConnector || {}) !== this._checkConnector(newConnector || {})
            },
            _checkConnector: function(connector) {
                return connector && connector.strokeWidth
            },
            _getConnectorPoints: function() {
                var that = this,
                    rotated = that._rotated,
                    labelBbox = that._insideGroup.getBBox(),
                    graphicBbox = that._graphicBbox,
                    centerLabelY,
                    centerLabelX,
                    rightLabelCoord,
                    bottomLabelCoord,
                    x1,
                    x2,
                    y1,
                    y2;
                labelBbox.x += that._insideGroup.settings.translateX || 0;
                labelBbox.y += that._insideGroup.settings.translateY || 0;
                centerLabelY = that._background ? labelBbox.y + labelBbox.height / 2 : null;
                centerLabelX = that._background ? labelBbox.x + labelBbox.width / 2 : null,
                rightLabelCoord = labelBbox.x + labelBbox.width;
                bottomLabelCoord = labelBbox.y + labelBbox.height;
                x1 = _floor(labelBbox.x + labelBbox.width / 2);
                x2 = _floor(graphicBbox.x + graphicBbox.width / 2);
                if (bottomLabelCoord < graphicBbox.y) {
                    y1 = centerLabelY || bottomLabelCoord;
                    y2 = graphicBbox.y
                }
                else if (labelBbox.y > graphicBbox.y + graphicBbox.height) {
                    y1 = centerLabelY || labelBbox.y;
                    y2 = graphicBbox.y + graphicBbox.height
                }
                else {
                    if (labelBbox.x > graphicBbox.x + graphicBbox.width) {
                        x1 = centerLabelX || labelBbox.x;
                        x2 = graphicBbox.x + graphicBbox.width
                    }
                    else if (rightLabelCoord < graphicBbox.x) {
                        x1 = centerLabelX || rightLabelCoord;
                        x2 = graphicBbox.x
                    }
                    else
                        return;
                    y1 = _floor(labelBbox.y + labelBbox.height / 2);
                    y2 = _floor(graphicBbox.y + graphicBbox.height / 2)
                }
                return [{
                            x: x1,
                            y: y1
                        }, {
                            x: x2,
                            y: y2
                        }]
            },
            _rotateLabel: function() {
                var bbox = this._insideGroup.getBBox();
                this._insideGroup.rotate(this._options.rotationAngle)
            },
            _format: function() {
                var that = this,
                    data = that._data,
                    options = that._options,
                    formatHelper = DX.formatHelper;
                data.valueText = formatHelper.format(data.value, options.format, options.precision);
                data.argumentText = formatHelper.format(data.argument, options.argumentFormat, options.argumentPrecision);
                if (data.percent !== undefined)
                    data.percentText = formatHelper.format(data.percent, "percent", options.percentPrecision);
                if (data.total !== undefined)
                    data.totalText = formatHelper.format(data.total, options.format, options.precision);
                if (data.openValue !== undefined)
                    data.openValueText = formatHelper.format(data.openValue, options.format, options.precision);
                if (data.closeValue !== undefined)
                    data.closeValueText = formatHelper.format(data.closeValue, options.format, options.precision);
                if (data.lowValue !== undefined)
                    data.lowValueText = formatHelper.format(data.lowValue, options.format, options.precision);
                if (data.highValue !== undefined)
                    data.highValueText = formatHelper.format(data.highValue, options.format, options.precision);
                if (data.reductionValue !== undefined)
                    data.reductionValueText = formatHelper.format(data.reductionValue, options.format, options.precision);
                return options.customizeText ? options.customizeText.call(data, data) : data.valueText
            },
            _getOutsideLabelCoords: function(labelBbox) {
                var graphicBbox = this._graphicBbox,
                    x = 0,
                    y = 0,
                    isTop = this._location === "top";
                if (!this._rotated) {
                    x += graphicBbox.width / 2 + graphicBbox.x;
                    if (isTop)
                        y += graphicBbox.y - labelBbox.y - labelBbox.height - this._offset;
                    else
                        y += graphicBbox.y + graphicBbox.height - labelBbox.y + this._offset
                }
                else {
                    y += graphicBbox.y - labelBbox.y - labelBbox.height / 2 + graphicBbox.height / 2;
                    if (isTop)
                        x += graphicBbox.x + graphicBbox.width - labelBbox.x + this._offset;
                    else
                        x += graphicBbox.x - labelBbox.x - labelBbox.width - this._offset
                }
                return {
                        x: x,
                        y: y
                    }
            },
            _getInsideLabelCoords: function(labelBbox) {
                var graphicBbox = this._graphicBbox,
                    isTop = this._location === "top",
                    x = 0,
                    y = 0;
                if (!this._isRange)
                    if (!this._rotated) {
                        x += graphicBbox.width / 2 + graphicBbox.x;
                        y += graphicBbox.y - labelBbox.y - labelBbox.height / 2 + graphicBbox.height / 2
                    }
                    else {
                        y += graphicBbox.y - labelBbox.y - labelBbox.height / 2 + graphicBbox.height / 2;
                        x += graphicBbox.x - labelBbox.x - labelBbox.width / 2 + graphicBbox.width / 2
                    }
                else if (!this._rotated) {
                    x += graphicBbox.width / 2 + graphicBbox.x;
                    if (isTop)
                        y += graphicBbox.y - labelBbox.y - labelBbox.height + this._offset + labelBbox.height;
                    else
                        y += graphicBbox.y + graphicBbox.height - labelBbox.y - this._offset - labelBbox.height
                }
                else {
                    y += graphicBbox.y - labelBbox.y - labelBbox.height / 2 + graphicBbox.height / 2;
                    if (isTop)
                        x += graphicBbox.x + graphicBbox.width - labelBbox.x - labelBbox.width - this._offset;
                    else
                        x += graphicBbox.x - labelBbox.x + this._offset
                }
                return {
                        x: x,
                        y: y
                    }
            },
            _getFullstackedLabelCoords: function(labelBbox) {
                var x = 0,
                    y = 0,
                    graphicBbox = this._graphicBbox;
                if (!this._rotated) {
                    x += graphicBbox.width / 2 + graphicBbox.x;
                    y += this._coords.defaultY - labelBbox.y - labelBbox.height - this._offset
                }
                else {
                    y += graphicBbox.y - labelBbox.y - labelBbox.height / 2 + graphicBbox.height / 2;
                    x += this._coords.defaultX - labelBbox.x + this._offset
                }
                return {
                        x: x,
                        y: y
                    }
            },
            _setPositionForSymbol: function() {
                var that = this,
                    offset = that._offset,
                    labelBBox = that._insideGroup.getBBox(),
                    graphicBbox = that._graphicBbox,
                    isTop = that._location === "top",
                    correctionY = 0,
                    correctionX = 0,
                    x = 0,
                    y = 0;
                if (!that._rotated) {
                    correctionX = that._coords.x;
                    correctionY = isTop ? -labelBBox.y - labelBBox.height - offset : graphicBbox.height - labelBBox.y + offset;
                    correctionY += graphicBbox.y
                }
                else {
                    correctionY = graphicBbox.y - labelBBox.y - labelBBox.height / 2 + graphicBbox.height / 2;
                    correctionX = isTop ? graphicBbox.width - labelBBox.x + offset : -labelBBox.x - labelBBox.width - offset;
                    correctionX += graphicBbox.x
                }
                x += correctionX + that._options.horizontalOffset;
                y += correctionY + that._options.verticalOffset;
                that._checkPosition({
                    x: labelBBox.x + x,
                    y: labelBBox.y + y,
                    height: labelBBox.height,
                    width: labelBBox.width
                }, x, y)
            },
            _checkPositionForSymbol: function(labelBbox, x, y) {
                var that = this,
                    graphicBbox = that._graphicBbox,
                    visibleArea = that._visibleArea,
                    offset = that._offset;
                if (!that._rotated) {
                    if (visibleArea.minX <= graphicBbox.x + graphicBbox.width && visibleArea.maxX >= graphicBbox.x) {
                        if (visibleArea.minX > labelBbox.x && that.adjustSeriesLabels)
                            x += visibleArea.minX - labelBbox.x;
                        if (visibleArea.maxX < labelBbox.x + labelBbox.width && that.adjustSeriesLabels)
                            x -= labelBbox.x + labelBbox.width - visibleArea.maxX;
                        if (visibleArea.minY > labelBbox.y)
                            y += graphicBbox.y + graphicBbox.height - labelBbox.y + offset;
                        if (visibleArea.maxY < labelBbox.y + labelBbox.height)
                            y -= labelBbox.y + labelBbox.height - graphicBbox.y + offset
                    }
                }
                else if (visibleArea.minY <= graphicBbox.y + graphicBbox.height && visibleArea.maxY >= graphicBbox.y) {
                    if (visibleArea.minX > labelBbox.x)
                        x += graphicBbox.x + graphicBbox.width - labelBbox.x + offset;
                    if (visibleArea.maxX < labelBbox.x + labelBbox.width)
                        x -= labelBbox.x + labelBbox.width - graphicBbox.x + offset;
                    if (visibleArea.minY > graphicBbox.y && that.adjustSeriesLabels)
                        y += visibleArea.minY - labelBbox.y;
                    if (visibleArea.maxY < labelBbox.y + labelBbox.height && that.adjustSeriesLabels)
                        y -= labelBbox.y + labelBbox.height - visibleArea.maxY
                }
                that._insideGroup.applySettings({
                    translateX: _round(x),
                    translateY: _round(y)
                })
            },
            _setPositionForBar: function() {
                var that = this,
                    offset = that._offset,
                    labelPosition = that._options.position,
                    labelBbox = that._insideGroup.getBBox(),
                    coords;
                if (that._initialValue === 0 && that._isFullStacked)
                    coords = that._getFullstackedLabelCoords(labelBbox);
                else if (labelPosition === "inside")
                    coords = that._getInsideLabelCoords(labelBbox);
                else
                    coords = that._getOutsideLabelCoords(labelBbox);
                coords.x += that._options.horizontalOffset;
                coords.y += that._options.verticalOffset;
                that._checkPosition({
                    x: labelBbox.x + coords.x,
                    y: labelBbox.y + coords.y,
                    height: labelBbox.height,
                    width: labelBbox.width
                }, coords.x, coords.y)
            },
            _checkPositionForBar: function(labelBbox, x, y) {
                var that = this,
                    graphicBbox = that._graphicBbox,
                    visibleArea = that._visibleArea;
                if (visibleArea.minX <= graphicBbox.x + graphicBbox.width && visibleArea.maxX >= graphicBbox.x && visibleArea.minY <= graphicBbox.y + graphicBbox.height && visibleArea.maxY >= graphicBbox.y)
                    if (!that._rotated) {
                        if (visibleArea.minX > labelBbox.x && that.adjustSeriesLabels)
                            x += visibleArea.minX - labelBbox.x;
                        if (visibleArea.maxX < labelBbox.x + labelBbox.width && that.adjustSeriesLabels)
                            x -= labelBbox.x + labelBbox.width - visibleArea.maxX;
                        if (visibleArea.minY > labelBbox.y)
                            y += visibleArea.minY - labelBbox.y;
                        if (visibleArea.maxY < labelBbox.y + labelBbox.height)
                            y -= labelBbox.y + labelBbox.height - visibleArea.maxY
                    }
                    else {
                        if (visibleArea.minX > labelBbox.x)
                            x += visibleArea.minX - labelBbox.x;
                        if (visibleArea.maxX < labelBbox.x + labelBbox.width)
                            x -= labelBbox.x + labelBbox.width - visibleArea.maxX;
                        if (visibleArea.minY > labelBbox.y && that.adjustSeriesLabels)
                            y += visibleArea.minY - labelBbox.y;
                        if (visibleArea.maxY < labelBbox.y + labelBbox.height && that.adjustSeriesLabels)
                            y -= labelBbox.y + labelBbox.height - visibleArea.maxY
                    }
                if (that._options.resolveLabelsOverlapping && that._options.position === "inside")
                    if (that._rotated) {
                        if (labelBbox.width > graphicBbox.width || labelBbox.height > graphicBbox.height) {
                            that.hide();
                            return
                        }
                    }
                    else if (labelBbox.height > graphicBbox.height || labelBbox.width > graphicBbox.width) {
                        that.hide();
                        return
                    }
                that._insideGroup.applySettings({
                    translateX: _round(x),
                    translateY: _round(y)
                })
            },
            _setPositionForBubble: function() {
                var that = this,
                    labelBbox = that._insideGroup.getBBox(),
                    graphicBbox = that._graphicBbox,
                    x = 0,
                    y = 0;
                if (that._options.position === "inside") {
                    x = that._coords.x;
                    y += graphicBbox.y + graphicBbox.height / 2 - labelBbox.y - labelBbox.height / 2;
                    x += that._options.horizontalOffset;
                    y += that._options.verticalOffset;
                    that._checkPosition({
                        x: labelBbox.x + x,
                        y: labelBbox.y + y,
                        height: labelBbox.height,
                        width: labelBbox.width
                    }, x, y)
                }
                else
                    that._setPositionForSymbol()
            },
            _setPositionForFinancial: function() {
                var that = this,
                    offset = that._offset,
                    labelBbox = that._insideGroup.getBBox(),
                    coords;
                coords = that._getOutsideLabelCoords(labelBbox);
                coords.x += that._options.horizontalOffset;
                coords.y += that._options.verticalOffset;
                that._checkPosition({
                    x: labelBbox.x + coords.x,
                    y: labelBbox.y + coords.y,
                    height: labelBbox.height,
                    width: labelBbox.width
                }, coords.x, coords.y)
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file pieLabel.js */
    (function($, DX) {
        var getCosAndSin = DX.utils.getCosAndSin,
            _extend = $.extend,
            _math = Math,
            _round = _math.round,
            _max = _math.max,
            _inArray = $.inArray,
            _isDefined = DX.utils.isDefined,
            INDENT_FROM_PIE = 30,
            CONNECTOR_LENGTH = 20;
        DX.viz.core.series.points.PieLabel = DX.viz.core.series.points.Label.inherit({
            ctor: function(data, options) {
                this.setLabelEllipsis = false;
                this.indentFromPie = INDENT_FROM_PIE;
                this.updateData(data);
                this.setOptions(options)
            },
            updateData: function(data) {
                if (_isDefined(data))
                    this._data = data.formatObject
            },
            setOptions: function(newOptions) {
                var that = this,
                    oldOptions = that._options,
                    newOptions = newOptions || {};
                that._options = newOptions.options;
                that._borderWidth = newOptions.borderWidth;
                if (oldOptions) {
                    that._isBackgroundChanged(oldOptions.background, that._options.background) && that._deleteBackground();
                    that._isConnectorChanged(oldOptions.connector, that._options.connector) && that._deleteConnector()
                }
            },
            setCoords: function(coords, canvas) {
                this._middleAngle = coords.middleAngle;
                this._radiusOuter = coords.radiusOuter;
                this._centerX = coords.centerX;
                this._centerY = coords.centerY;
                this._canvas = canvas
            },
            updatePosition: function(maxLabelLength) {
                this._setPosition(maxLabelLength);
                this._checkEllipsis();
                this._drawBackground();
                this._rotateLabel();
                this._checkPosition();
                this._connector && this._drawConnector()
            },
            dispose: function() {
                this._data = null;
                this._options = null;
                this._canvas = null;
                this._deleteElements()
            },
            draw: function(renderer, group, visibility) {
                var that = this,
                    options = that._options,
                    background = options.background,
                    text = that._format();
                if (_isDefined(text) && text !== "") {
                    that._drawGroups(renderer, group);
                    that._setVisibility(visibility);
                    that._drawText(renderer, text);
                    that._setPosition();
                    that._checkEllipsis();
                    that._drawBackground(renderer);
                    that._rotateLabel();
                    that._checkPosition();
                    that._drawConnector(renderer)
                }
                else
                    that._setVisibility("hidden")
            },
            _getOutsideGroupLabelPosition: function() {
                this._deleteConnector();
                return this._group && this._group.getBBox()
            },
            _setPosition: function(maxLabelLength) {
                var that = this,
                    bbox = that._text.getBBox(),
                    options = that._options,
                    angleFunctions = getCosAndSin(that._middleAngle),
                    align = "center",
                    rad = that._radiusOuter + options.radialOffset,
                    canvas = that._canvas,
                    rightBorderX = canvas.width - canvas.right,
                    leftBorderX = canvas.left,
                    x,
                    y;
                if (options.position === 'inside') {
                    rad -= that.indentFromPie;
                    x = that._centerX + rad * angleFunctions.cos
                }
                else if (options.position === 'columns') {
                    rad += CONNECTOR_LENGTH;
                    if (angleFunctions.cos >= 0) {
                        align = "right";
                        x = maxLabelLength ? that._centerX + rad + maxLabelLength : rightBorderX;
                        x = x > rightBorderX ? rightBorderX : x
                    }
                    else if (angleFunctions.cos < 0) {
                        align = "left";
                        x = maxLabelLength ? that._centerX - rad - maxLabelLength : leftBorderX;
                        x = x < leftBorderX ? leftBorderX : x
                    }
                }
                else {
                    rad += that.indentFromPie;
                    if (angleFunctions.cos > 0.1)
                        align = "left";
                    else if (angleFunctions.cos < -0.1)
                        align = "right";
                    x = that._centerX + rad * angleFunctions.cos
                }
                y = _round(that._text.settings.y + that._centerY - rad * angleFunctions.sin - bbox.y - bbox.height / 2);
                that._text.applySettings({
                    x: x,
                    y: y,
                    align: align
                })
            },
            _getConnectorPoints: function() {
                var that = this,
                    options = that._options,
                    position = options.position,
                    angleFunctions,
                    rad = that._radiusOuter,
                    box,
                    x,
                    y,
                    points = [];
                if (position !== "inside") {
                    angleFunctions = getCosAndSin(_round(that._middleAngle));
                    points.push({
                        x: _round(that._centerX + (rad - that._borderWidth) * angleFunctions.cos),
                        y: _round(that._centerY - (rad - that._borderWidth) * angleFunctions.sin)
                    });
                    x = _round(that._centerX + (rad + options.radialOffset + CONNECTOR_LENGTH) * angleFunctions.cos);
                    if (position === "columns") {
                        box = that._insideGroup.getBBox();
                        box.x = box.x + (that._insideGroup.settings.translateX || 0);
                        box.y = box.y + (that._insideGroup.settings.translateY || 0);
                        y = box.y + box.height / 2;
                        points.push({
                            x: x,
                            y: y
                        });
                        if (that._background)
                            x = box.x + box.width / 2;
                        else if (angleFunctions.cos < 0)
                            x = box.x + box.width;
                        else if (angleFunctions.cos > 0)
                            x = box.x;
                        points.push({
                            x: x,
                            y: y
                        })
                    }
                    else {
                        y = _round(that._centerY - (rad + options.radialOffset + CONNECTOR_LENGTH) * angleFunctions.sin);
                        points.push({
                            x: x,
                            y: y
                        })
                    }
                }
                return points
            },
            _rotateLabel: function() {
                var that = this,
                    options = that._options,
                    shift = that._radiusOuter + options.radialOffset * 2 + CONNECTOR_LENGTH,
                    angleFunctions = getCosAndSin(that._middleAngle),
                    x,
                    y,
                    box = that._insideGroup.getBBox();
                if (options.position === "inside" || options.position === "columns") {
                    x = box.x + box.width / 2;
                    y = box.y + box.height / 2
                }
                else {
                    x = that._centerX + shift * angleFunctions.cos;
                    y = that._centerY - shift * angleFunctions.sin
                }
                that._insideGroup.applySettings({
                    x: x,
                    y: y,
                    rotate: options.rotationAngle
                })
            },
            _checkEllipsis: function() {
                var that = this,
                    i,
                    LABEL_OFFSET = 10,
                    labelBox,
                    text,
                    textLength = 0,
                    linesLength = [],
                    numLastSpan = [],
                    maxLength,
                    numSpan,
                    index,
                    x,
                    y,
                    width,
                    rotationAngleFunction = getCosAndSin(that._options.rotationAngle),
                    canvas = that._canvas,
                    labelOptions = that._options,
                    angleFunctions = getCosAndSin(that._middleAngle),
                    borderX = that._centerX + (that._radiusOuter + CONNECTOR_LENGTH) * angleFunctions.cos;
                if (!that._text.tspans || !that.setLabelEllipsis)
                    return;
                labelBox = that._text.getBBox();
                x = labelBox.x + labelBox.width < that._centerX ? labelBox.x + labelBox.width : labelBox.x;
                y = labelBox.y + labelBox.height / 2;
                width = labelBox.x + labelBox.width < that._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 < that._text.tspans.length; i++) {
                        textLength += that._text.tspans[i].element.getNumberOfChars();
                        if (!that._text.tspans[i + 1] || that._text.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 = _max.apply(null, linesLength);
                    if (maxLength === 0)
                        break;
                    index = _inArray(maxLength, linesLength);
                    numSpan = numLastSpan[index];
                    if (that._text.tspans[numSpan].element.textContent === "...") {
                        if (that._text.tspans[numSpan].settings.dy > 0 || !that._text.tspans[numSpan - 1])
                            linesLength[index] = 0;
                        else if (that._text.tspans[numSpan - 1]) {
                            that._text.tspans[numSpan].element.textContent = "";
                            numLastSpan[index] -= 1;
                            that._text.tspans[numSpan - 1].element.textContent += "..."
                        }
                    }
                    else {
                        text = that._text.tspans[numSpan].element.textContent;
                        text = text.substr(0, text.length - 1 - 3) + "...";
                        that._text.tspans[numSpan].element.textContent = text;
                        linesLength[index] -= 1
                    }
                    labelBox = that._text.getBBox();
                    x = labelBox.x + labelBox.width < that._centerX ? labelBox.x + labelBox.width : labelBox.x;
                    y = labelBox.y + labelBox.height / 2;
                    width = labelBox.x + labelBox.width < that._centerX ? -labelBox.width : labelBox.width
                }
            },
            _checkPosition: function() {
                var that = this,
                    group = that._insideGroup,
                    box = group.getBBox(),
                    canvas = that._canvas,
                    x = 0,
                    y = 0;
                if (box.y + box.height > canvas.height - canvas.bottom)
                    y = canvas.height - box.y - box.height - canvas.bottom;
                else if (box.y < canvas.top)
                    y = canvas.top - box.y;
                if (box.x + box.width > canvas.width - canvas.right)
                    x = canvas.width - canvas.right - box.x - box.width;
                else if (box.x < canvas.left)
                    x = canvas.left - box.x;
                group.applySettings({
                    translateX: x,
                    translateY: y
                })
            },
            setPosition: function(position) {
                this._options.position = position
            },
            getPosition: function() {
                return this._options.position
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file symbolPoint.js */
    (function($, DX) {
        var viz = DevExpress.viz,
            core = viz.core,
            series = core.series,
            _extend = $.extend,
            _each = $.each,
            _isNumber = DX.utils.isNumber,
            _isDefined = DX.utils.isDefined,
            _isEmptyObject = $.isEmptyObject,
            _math = Math,
            _round = _math.round,
            _floor = _math.floor,
            _ceil = _math.ceil,
            DEFAULT_IMAGE_WIDTH = 20,
            DEFAULT_IMAGE_HEIGHT = 20,
            CANVAS_POSITION_DEFAULT = "canvas_position_default";
        series.points.mixins = series.points.mixins || {};
        series.points.mixins.symbolPoint = {
            deleteLabel: function() {
                this._label.dispose();
                this._label = null
            },
            _hasGraphic: function() {
                return this.graphic
            },
            _clearTrackerVisibility: function() {
                if (this.trackerGraphic && this.trackerGraphic.settings.visibility)
                    this.trackerGraphic.applySettings({visibility: null})
            },
            clearVisibility: function() {
                if (this.graphic && this.graphic.settings.visibility)
                    this.graphic.applySettings({visibility: null});
                this._clearTrackerVisibility();
                this._label.clearVisibility()
            },
            isVisible: function() {
                return this.inVisibleArea && this.series.isVisible()
            },
            _setTrackerInvisibility: function() {
                if (this.trackerGraphic && this.trackerGraphic.settings.visibility !== "hidden")
                    this.trackerGraphic.applySettings({visibility: "hidden"})
            },
            setInvisibility: function() {
                if (this.graphic && this.graphic.settings.visibility !== "hidden")
                    this.graphic.applySettings({visibility: "hidden"});
                this._setTrackerInvisibility();
                this._label.hide()
            },
            clearMarker: function() {
                this.graphic && this.graphic.applySettings(this._emptySettings)
            },
            setAdjustSeriesLabels: function(adjustSeriesLabels) {
                this._label.adjustSeriesLabels = adjustSeriesLabels
            },
            _getLabelOptions: function(type) {
                var options = this._options;
                return {
                        options: options.label,
                        rotated: options.rotated,
                        type: type,
                        isFullStacked: options.series.isFullStackedSeries(),
                        isRange: options.type.indexOf("range") !== -1
                    }
            },
            _createLabel: function() {
                this._label = core.CoreFactory.createLabel(this._options.type)
            },
            _updateLabelData: function() {
                this._label.updateData({
                    formatObject: this._getLabelFormatObject(),
                    initialValue: this.initialValue
                })
            },
            _updateLabelOptions: function(type) {
                !this._label && this._createLabel();
                this._label.setOptions(this._getLabelOptions(type))
            },
            _checkImage: function(image) {
                return _isDefined(image) && (typeof image === "string" || _isDefined(image.url))
            },
            _fillStyle: function() {
                this._styles = this._options.styles
            },
            _checkSymbol: function(oldOptions, newOptions) {
                var oldSymbol = oldOptions.symbol,
                    newSymbol = newOptions.symbol,
                    symbolChanged = oldSymbol === "circle" && newSymbol !== "circle" || oldSymbol !== "circle" && newSymbol === "circle",
                    imageChanged = this._checkImage(oldOptions.image) !== this._checkImage(newOptions.image);
                if (symbolChanged || imageChanged)
                    return true;
                return false
            },
            _getSquareMarkerCoords: function(radius) {
                return [{
                            x: -radius,
                            y: -radius
                        }, {
                            x: radius,
                            y: -radius
                        }, {
                            x: radius,
                            y: radius
                        }, {
                            x: -radius,
                            y: radius
                        }, {
                            x: -radius,
                            y: -radius
                        }]
            },
            _getPolygonMarkerCoords: function(radius) {
                var r = _ceil(radius);
                return [{
                            x: -r,
                            y: 0
                        }, {
                            x: 0,
                            y: -r
                        }, {
                            x: r,
                            y: 0
                        }, {
                            x: 0,
                            y: r
                        }, {
                            x: -r,
                            y: 0
                        }]
            },
            _getTriangleMarkerCoords: function(radius) {
                return [{
                            x: -radius,
                            y: -radius
                        }, {
                            x: radius,
                            y: -radius
                        }, {
                            x: 0,
                            y: radius
                        }, {
                            x: -radius,
                            y: -radius
                        }]
            },
            _getCrossMarkerCoords: function(radius) {
                var r = _ceil(radius),
                    floorHalfRadius = _floor(r / 2),
                    ceilHalfRadius = _ceil(r / 2);
                return [{
                            x: -r,
                            y: -floorHalfRadius
                        }, {
                            x: -floorHalfRadius,
                            y: -r
                        }, {
                            x: 0,
                            y: -ceilHalfRadius
                        }, {
                            x: floorHalfRadius,
                            y: -r
                        }, {
                            x: r,
                            y: -floorHalfRadius
                        }, {
                            x: ceilHalfRadius,
                            y: 0
                        }, {
                            x: r,
                            y: floorHalfRadius
                        }, {
                            x: floorHalfRadius,
                            y: r
                        }, {
                            x: 0,
                            y: ceilHalfRadius
                        }, {
                            x: -floorHalfRadius,
                            y: r
                        }, {
                            x: -r,
                            y: floorHalfRadius
                        }, {
                            x: -ceilHalfRadius,
                            y: 0
                        }]
            },
            _populatePointShape: function(symbol, radius) {
                switch (symbol) {
                    case"square":
                        return this._getSquareMarkerCoords(radius);
                    case"polygon":
                        return this._getPolygonMarkerCoords(radius);
                    case"triangle":
                        return this._getTriangleMarkerCoords(radius);
                    case"cross":
                        return this._getCrossMarkerCoords(radius)
                }
            },
            correctValue: function(correction) {
                if (this.hasValue()) {
                    this.value = this.initialValue + correction;
                    this.minValue = correction;
                    this.translate()
                }
            },
            resetCorrection: function() {
                this.value = this.initialValue;
                this.minValue = CANVAS_POSITION_DEFAULT
            },
            _getTranslates: function(animationEnabled) {
                var translateX,
                    translateY;
                translateX = this.x;
                translateY = this.y;
                if (animationEnabled)
                    if (this._options.rotated)
                        translateX = this.defaultX;
                    else
                        translateY = this.defaultY;
                return {
                        x: translateX,
                        y: translateY
                    }
            },
            _createImageMarker: function(renderer, settings, options) {
                var url,
                    width,
                    height,
                    offsetY,
                    attr = {
                        location: "center",
                        translateX: settings.attr.translateX,
                        translateY: settings.attr.translateY,
                        visibility: settings.attr.visibility
                    };
                url = options.url ? options.url.toString() : options.toString();
                width = options.width || DEFAULT_IMAGE_WIDTH;
                height = options.height || DEFAULT_IMAGE_HEIGHT;
                return renderer.createImage(-_round(width * 0.5), -_round(height * 0.5), width, height, url, attr)
            },
            _createSymbolMarker: function(renderer, pointSettings, animationEnabled) {
                var marker,
                    options = this._options;
                switch (options.symbol) {
                    case"circle":
                        marker = renderer.createCircle(0, 0, pointSettings.r, pointSettings.attr);
                        break;
                    case"square":
                    case"polygon":
                    case"triangle":
                    case"cross":
                        marker = renderer.createArea(pointSettings.points, pointSettings.attr);
                        break
                }
                return marker
            },
            _createMarker: function(renderer, group, image, settings, animationEnabled) {
                var marker = this._checkImage(image) ? this._createImageMarker(renderer, settings, image) : this._createSymbolMarker(renderer, settings, animationEnabled);
                marker && marker.append(group);
                return marker
            },
            _getSymbolBbox: function(x, y, r) {
                var bbox = {};
                bbox.x = x - r;
                bbox.y = y - r;
                bbox.width = bbox.height = r * 2;
                return bbox
            },
            _getImageBbox: function(x, y) {
                var bbox = {},
                    image = this._options.image,
                    width = image.width || DEFAULT_IMAGE_WIDTH,
                    height = image.height || DEFAULT_IMAGE_HEIGHT;
                bbox.x = x - _round(width / 2);
                bbox.y = y - _round(height / 2);
                bbox.width = width;
                bbox.height = height;
                return bbox
            },
            _getGraphicBbox: function() {
                var options = this._options,
                    x = this.x,
                    y = this.y,
                    bbox;
                if (options.visible)
                    bbox = this._checkImage(options.image) ? this._getImageBbox(x, y) : this._getSymbolBbox(x, y, options.styles.normal.r);
                else
                    bbox = {
                        x: x,
                        y: y,
                        width: 0,
                        height: 0
                    };
                return bbox
            },
            _drawLabel: function(renderer, group) {
                var that = this,
                    customVisibility = that._getCustomLabelVisibility(),
                    visibleArea,
                    translators = that.translators;
                if ((that._options.series.getLabelVisibility() || customVisibility) && that.hasValue()) {
                    if (translators)
                        visibleArea = {
                            minX: translators.x.getCanvasVisibleArea().min,
                            maxX: translators.x.getCanvasVisibleArea().max,
                            minY: translators.y.getCanvasVisibleArea().min,
                            maxY: translators.y.getCanvasVisibleArea().max
                        };
                    that._label.setCoords({
                        x: that.x,
                        y: that.y
                    }, that._getGraphicBbox(), that._getLabelPosition(), visibleArea);
                    that._label.draw(renderer, group, customVisibility)
                }
                else
                    that._label.hide()
            },
            _drawMarker: function(renderer, group, animationEnabled) {
                var that = this,
                    options = that._options,
                    translates = that._getTranslates(animationEnabled),
                    marker,
                    style = that._getStyle(),
                    pointAttributes = _extend({
                        translateX: translates.x,
                        translateY: translates.y
                    }, style),
                    pointSettings = {
                        attr: pointAttributes,
                        points: that._populatePointShape(options.symbol, style.r),
                        r: style.r
                    };
                marker = that._createMarker(renderer, group, options.image, pointSettings, animationEnabled);
                that.graphic = marker
            },
            _drawTrackerMarker: function(renderer, group) {
                var radius = this._options.trackerR || this.storeTrackerR();
                this.trackerGraphic = renderer.createCircle(this.x, this.y, radius).append(group);
                this.trackerGraphic.data({point: this})
            },
            getTooltipCoords: function() {
                var coords;
                if (this.graphic)
                    coords = {
                        x: this.x,
                        y: this.y,
                        offset: this.graphic.getBBox().height / 2
                    };
                else
                    coords = {
                        x: this.x,
                        y: this.y,
                        offset: 0
                    };
                return coords
            },
            hasValue: function() {
                return this.value !== null && this.minValue !== null
            },
            setPercentValue: function(total) {
                var valuePercent = this.value / total || 0,
                    percent = valuePercent,
                    minValuePercent = this.minValue / total || 0;
                percent -= _isNumber(this.minValue) ? minValuePercent : 0;
                this._label.setDataField("percent", percent);
                this._label.setDataField("total", total);
                if (this._options.series.isFullStackedSeries() && this.hasValue()) {
                    this.value = valuePercent;
                    this.minValue = !minValuePercent ? this.minValue : minValuePercent;
                    this.translate()
                }
            },
            storeTrackerR: function() {
                var navigator = window.navigator,
                    r = this._options.styles.normal.r,
                    minTrackerSize;
                navigator = this.__debug_navigator || navigator;
                this.__debug_browserNavigator = navigator;
                minTrackerSize = "ontouchstart" in window || navigator.msPointerEnabled && navigator.msMaxTouchPoints || navigator.pointerEnabled && navigator.maxTouchPoints ? 20 : 6;
                this._options.trackerR = r < minTrackerSize ? minTrackerSize : r;
                return this._options.trackerR
            },
            _translate: function(translators) {
                var that = this,
                    mainAxis = that._options.rotated ? "x" : "y",
                    upperMainAxis = mainAxis.toUpperCase(),
                    mainTranslator = translators[mainAxis],
                    axis = that._options.rotated ? "y" : "x";
                that[mainAxis] = mainTranslator.translate(that.value);
                that[axis] = translators[axis].translate(that.argument);
                that["min" + upperMainAxis] = mainTranslator.translate(that.minValue);
                that["default" + upperMainAxis] = mainTranslator.translate(CANVAS_POSITION_DEFAULT);
                that._calculateVisibility(that.x, that.y);
                that._prepareStatesOptions()
            },
            _changeData: function(data) {
                this.value = this.initialValue = this.originalValue = data.value;
                this.argument = this.initialArgument = this.originalArgument = data.argument;
                this.minValue = this.initialMinValue = this.originalMinValue = _isDefined(data.minValue) ? data.minValue : CANVAS_POSITION_DEFAULT;
                this.tag = data.tag;
                this.index = data.index
            },
            _updateData: function(data) {
                if (this.argument !== data.argument || this.value !== data.value || this.tag !== data.tag)
                    this._changeData(data)
            },
            _getImageSettings: function(image) {
                return {
                        href: image.url || image.toString(),
                        width: image.width || DEFAULT_IMAGE_WIDTH,
                        height: image.height || DEFAULT_IMAGE_HEIGHT
                    }
            },
            _updateMarker: function(animationEnabled, style) {
                var that = this,
                    options = that._options,
                    style = style || this._getStyle(),
                    settings,
                    image = options.image;
                if (that._checkImage(image))
                    settings = _extend({}, {visibility: style.visibility}, that._getImageSettings(image));
                else
                    settings = _extend({}, style, {points: that._populatePointShape(options.symbol, style.r)});
                if (!animationEnabled) {
                    settings.translateX = that.x;
                    settings.translateY = that.y
                }
                that.graphic.applySettings(settings)
            },
            _updateTracker: function() {
                this.trackerGraphic.applySettings({
                    cx: this.x,
                    cy: this.y,
                    r: this.storeTrackerR()
                })
            },
            _getLabelFormatObject: function() {
                return {
                        argument: this.initialArgument,
                        value: this.initialValue,
                        originalArgument: this.originalArgument,
                        originalValue: this.originalValue,
                        seriesName: this._options.series.name,
                        point: this
                    }
            },
            _getLabelPosition: function() {
                if (this._options.series.isFullStackedSeries() || this.initialValue > 0)
                    return "top";
                else
                    return "bottom"
            },
            _getFormatObject: function(tooltip) {
                var labelFormatObject = this._label.getData(),
                    valueObject = {
                        argumentText: tooltip.formatValue(this.initialArgument, "argument"),
                        valueText: tooltip.formatValue(this.initialValue)
                    },
                    percentObject = _isDefined(labelFormatObject.percent) ? {percentText: tooltip.formatValue(labelFormatObject.percent, "percent")} : {},
                    totalObject = _isDefined(labelFormatObject.total) ? {totalText: tooltip.formatValue(labelFormatObject.total)} : {};
                return _extend({}, labelFormatObject, valueObject, percentObject, totalObject)
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file barPoint.js */
    (function($, DX) {
        var viz = DevExpress.viz,
            points = viz.core.series.points.mixins,
            _extend = $.extend,
            _math = Math,
            _round = _math.round,
            _abs = _math.abs,
            _min = _math.min,
            CANVAS_POSITION_DEFAULT = "canvas_position_default",
            DEFAULT_BAR_TRACKER_SIZE = 9,
            CORRECTING_BAR_TRACKER_VALUE = 4;
        points.barPoint = _extend({}, points.symbolPoint, {
            correctCoordinates: function(correctOptions) {
                var correction = correctOptions.offset - _round(correctOptions.width / 2),
                    rotated = this._options.rotated,
                    valueSelector = rotated ? "height" : "width",
                    correctionSelector = (rotated ? "y" : "x") + "Correction";
                this[valueSelector] = correctOptions.width;
                this[correctionSelector] = correction
            },
            _getGraphicBbox: function() {
                var bbox = {};
                bbox.x = this.x;
                bbox.y = this.y;
                bbox.width = this.width;
                bbox.height = this.height;
                return bbox
            },
            _getLabelPosition: function() {
                var position,
                    invertX = this.translators.x.getBusinessRange().invert,
                    invertY = this.translators.y.getBusinessRange().invert,
                    isDiscreteValue = this.series.valueAxisType === "discrete",
                    isFullStacked = this.series.isFullStackedSeries(),
                    notVerticalInverted = !isDiscreteValue && (this.initialValue >= 0 && !invertY || this.initialValue < 0 && invertY) || isDiscreteValue && !invertY || isFullStacked,
                    notHorizontalInverted = !isDiscreteValue && (this.initialValue >= 0 && !invertX || this.initialValue < 0 && invertX) || isDiscreteValue && !invertX || isFullStacked;
                if (!this._options.rotated)
                    position = notVerticalInverted ? "top" : "bottom";
                else
                    position = notHorizontalInverted ? "top" : "bottom";
                return position
            },
            _drawLabel: function(renderer, group) {
                var that = this,
                    options = that._options,
                    coords,
                    commonVisibility = options.series.getLabelVisibility(),
                    customVisibility = that._getCustomLabelVisibility(),
                    visibleArea,
                    translators = that.translators;
                if (that.hasValue() && (options.label.showForZeroValues || that.initialValue) && (customVisibility || commonVisibility)) {
                    coords = {
                        x: that.x,
                        y: that.y,
                        defaultX: that.defaultX,
                        defaultY: that.defaultY
                    };
                    if (translators)
                        visibleArea = {
                            minX: translators.x.getCanvasVisibleArea().min,
                            maxX: translators.x.getCanvasVisibleArea().max,
                            minY: translators.y.getCanvasVisibleArea().min,
                            maxY: translators.y.getCanvasVisibleArea().max
                        };
                    that._label.setCoords(coords, that._getGraphicBbox(), that._getLabelPosition(), visibleArea);
                    that._label.draw(renderer, group, customVisibility)
                }
                else
                    that._label.hide()
            },
            _drawMarker: function(renderer, group, animationEnabled) {
                var style = this._getStyle(),
                    x = this.x,
                    y = this.y,
                    width = this.width,
                    height = this.height;
                if (animationEnabled)
                    if (this._options.rotated) {
                        width = 0;
                        x = this.defaultX
                    }
                    else {
                        height = 0;
                        y = this.defaultY
                    }
                this.graphic = renderer.createRect(x, y, width, height, this._options.cornerRadius, style).append(group)
            },
            _getSettingsForTracker: function() {
                var that = this,
                    y = that.y,
                    height = that.height,
                    x = that.x,
                    width = that.width;
                if (that._options.rotated) {
                    if (width === 1) {
                        width = DEFAULT_BAR_TRACKER_SIZE;
                        x -= CORRECTING_BAR_TRACKER_VALUE
                    }
                }
                else if (height === 1) {
                    height = DEFAULT_BAR_TRACKER_SIZE;
                    y -= CORRECTING_BAR_TRACKER_VALUE
                }
                return {
                        x: x,
                        y: y,
                        width: width,
                        height: height
                    }
            },
            _drawTrackerMarker: function(renderer, group) {
                var settings = this._getSettingsForTracker();
                this.trackerGraphic = renderer.createRect(settings.x, settings.y, settings.width, settings.height, this._options.cornerRadius).append(group);
                this.trackerGraphic.data({point: this})
            },
            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
                    }
            },
            getTooltipCoords: function() {
                var x = this.x + this.width / 2,
                    y = this.y + this.height / 2;
                return {
                        x: x,
                        y: y,
                        offset: 0
                    }
            },
            _truncateCoord: function(coord, minBounce, maxBounce) {
                if (coord < minBounce)
                    return minBounce;
                if (coord > maxBounce)
                    return maxBounce;
                return coord
            },
            _translate: function(translators) {
                var that = this,
                    rotated = that._options.rotated,
                    valAxis = rotated ? "x" : "y",
                    argAxis = rotated ? "y" : "x",
                    valIntervalName = rotated ? "width" : "height",
                    argIntervalName = rotated ? "height" : "width",
                    argTranslator = translators[argAxis],
                    valTranslator = translators[valAxis],
                    argVisibleArea = argTranslator.getCanvasVisibleArea(),
                    valVisibleArea = valTranslator.getCanvasVisibleArea(),
                    arg,
                    minArg,
                    val,
                    minVal;
                arg = minArg = argTranslator.translate(that.argument) + (that[argAxis + "Correction"] || 0);
                val = valTranslator.translate(that.value);
                minVal = valTranslator.translate(that.minValue);
                that[valIntervalName] = _abs(val - minVal);
                that._calculateVisibility(rotated ? _min(val, minVal) : _min(arg, minArg), rotated ? _min(arg, minArg) : _min(val, minVal), that.width, that.height);
                val = that._truncateCoord(val, valVisibleArea.min, valVisibleArea.max);
                minVal = that._truncateCoord(minVal, valVisibleArea.min, valVisibleArea.max);
                that[argAxis] = arg;
                that["min" + argAxis.toUpperCase()] = minArg;
                that[valIntervalName] = _abs(val - minVal);
                that[valAxis] = _min(val, minVal) + (that[valAxis + "Correction"] || 0);
                that["min" + valAxis.toUpperCase()] = minVal + (that[valAxis + "Correction"] || 0);
                that["default" + valAxis.toUpperCase()] = valTranslator.translate(CANVAS_POSITION_DEFAULT);
                if (that.inVisibleArea) {
                    if (that[argAxis] < argVisibleArea.min) {
                        that[argIntervalName] = that[argIntervalName] - (argVisibleArea.min - that[argAxis]);
                        that[argAxis] = argVisibleArea.min;
                        that["min" + argAxis.toUpperCase()] = argVisibleArea.min
                    }
                    if (that[argAxis] + that[argIntervalName] > argVisibleArea.max)
                        that[argIntervalName] = argVisibleArea.max - that[argAxis]
                }
            },
            _updateMarker: function(animationEnabled, style) {
                var style = style || this._getStyle(),
                    attributes = _extend({}, style);
                if (!animationEnabled) {
                    attributes.x = this.x;
                    attributes.y = this.y;
                    attributes.width = this.width;
                    attributes.height = this.height
                }
                else
                    attributes.sharpEdges = false;
                this.graphic.applySettings(attributes)
            },
            _updateTracker: function() {
                this.trackerGraphic.applySettings(this._getSettingsForTracker())
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file bubblePoint.js */
    (function($, DX) {
        var viz = DX.viz,
            points = viz.core.series.points.mixins,
            _extend = $.extend,
            MIN_BUBBLE_HEIGHT = 20;
        points.bubblePoint = _extend({}, points.symbolPoint, {
            correctCoordinates: function(diameter) {
                this.bubbleSize = diameter / 2
            },
            _drawMarker: function(renderer, group, animationEnabled) {
                var style = this._getStyle(),
                    attr = _extend({
                        translateX: this.x,
                        translateY: this.y
                    }, style),
                    marker = renderer.createCircle(0, 0, animationEnabled ? 0 : this.bubbleSize, attr).append(group);
                this.graphic = marker
            },
            _drawTrackerMarker: function(renderer, group) {
                this.trackerGraphic = renderer.createCircle(this.x, this.y, this.bubbleSize).append(group);
                this.trackerGraphic.data({point: this})
            },
            getTooltipCoords: function() {
                if (this.graphic) {
                    var height = this.graphic.getBBox().height;
                    return {
                            x: this.x,
                            y: this.y,
                            offset: height < MIN_BUBBLE_HEIGHT ? height / 2 : 0
                        }
                }
            },
            _getLabelFormatObject: function() {
                var symbolMethods = points.symbolPoint,
                    formatObject = symbolMethods._getLabelFormatObject.call(this);
                formatObject.size = this.initialSize;
                return formatObject
            },
            _updateData: function(data) {
                var symbolMethods = points.symbolPoint;
                if (this.argument !== data.argument || this.value !== data.value || this.size !== data.size || this.tag !== data.tag) {
                    symbolMethods._changeData.call(this, data);
                    this.size = this.initialSize = data.size
                }
            },
            _getGraphicBbox: function() {
                return this._getSymbolBbox(this.x, this.y, this.bubbleSize)
            },
            _updateMarker: function(animationEnabled, style) {
                var style = style || this._getStyle();
                if (!animationEnabled)
                    style = $.extend({
                        r: this.bubbleSize,
                        translateX: this.x,
                        translateY: this.y
                    }, style);
                this.graphic.applySettings(style)
            },
            _updateTracker: function() {
                this.trackerGraphic.applySettings({
                    cx: this.x,
                    cy: this.y,
                    r: this.bubbleSize
                })
            },
            _getFormatObject: function(tooltip) {
                var symbolMethods = points.symbolPoint,
                    formatObject = symbolMethods._getFormatObject.call(this, tooltip);
                formatObject.sizeText = tooltip.formatValue(this.initialSize);
                return formatObject
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file piePoint.js */
    (function($, DX) {
        var viz = DevExpress.viz,
            points = viz.core.series.points.mixins,
            _extend = $.extend,
            _round = Math.round,
            _getCosAndSin = DX.utils.getCosAndSin;
        points.piePoint = _extend({}, points.symbolPoint, {
            _populatePointShape: function(target, deltaRadius) {
                var angleFunctions = _getCosAndSin(point.middleAngle);
                target.x = point.centerX - ~~(deltaRadius * angleFunctions.cos);
                target.y = point.centerY + ~~(deltaRadius * angleFunctions.sin);
                target.outerRadius = this.radiusOuter + deltaRadius;
                target.innerRadius = this.radiusInner;
                target.startAngle = this.toAngle;
                target.endAngle = this.fromAngle
            },
            _changeData: function(data) {
                var that = this;
                that.value = that.initialValue = that.originalValue = data.value;
                that.argument = that.initialArgument = that.originalArgument = data.argument;
                that.minValue = that.initialMinValue = that.originalMinValue = DevExpress.utils.isDefined(data.minValue) ? data.minValue : 0;
                that.tag = data.tag;
                that._visible = true;
                that.index = data.index
            },
            animate: function(complete, duration, step) {
                this.graphic.animate({
                    x: this.centerX,
                    y: this.centerY,
                    outerRadius: this.radiusOuter,
                    innerRadius: this.radiusInner,
                    startAngle: this.toAngle,
                    endAngle: this.fromAngle
                }, {
                    partitionDuration: duration,
                    step: step
                }, complete)
            },
            correctPosition: function(correction) {
                this.radiusInner = correction.radiusInner;
                this.radiusOuter = correction.radiusOuter;
                this.centerX = correction.centerX;
                this.centerY = correction.centerY
            },
            correctValue: function(correction, percent, base) {
                this.value = (base || this.initialValue) + correction;
                this.minValue = correction;
                this.percent = percent;
                this._label.setDataField("percent", percent)
            },
            _getLabelOptions: function() {
                var options = this._options,
                    series = options.series,
                    seriesStyle = this._options.styles.normal,
                    borderWidth = series._options.containerBackgroundColor === seriesStyle.stroke ? _round(seriesStyle.strokeWidth / 2) : _round(-seriesStyle.strokeWidth / 2);
                return {
                        options: options.label,
                        borderWidth: borderWidth
                    }
            },
            _updateLabelData: function() {
                this._label.updateData({formatObject: this._getLabelFormatObject()})
            },
            _updateLabelOptions: function() {
                !this._label && this._createLabel();
                this._label.setOptions(this._getLabelOptions())
            },
            _drawLabel: function(renderer, group) {
                var commonVisibility = this._options.series.getLabelVisibility(),
                    customVisibility = this._getCustomLabelVisibility();
                if ((commonVisibility || customVisibility) && this.hasValue()) {
                    this._label.setCoords({
                        middleAngle: this.middleAngle,
                        radiusOuter: this.radiusOuter,
                        centerX: this.centerX,
                        centerY: this.centerY
                    }, this._options.series.canvas);
                    this._label.draw(renderer, group, customVisibility)
                }
                else
                    this._label.hide()
            },
            _drawMarker: function(renderer, group, animationEnabled, firstDrawing) {
                var styles = this._getStyle(),
                    radiusOuter = this.radiusOuter,
                    radiusInner = this.radiusInner,
                    fromAngle = this.fromAngle,
                    toAngle = this.toAngle;
                if (animationEnabled) {
                    radiusInner = radiusOuter = 0;
                    if (!firstDrawing)
                        fromAngle = toAngle = this.shiftedAngle
                }
                this.graphic = renderer.createArc(this.centerX, this.centerY, radiusOuter, radiusInner, toAngle, fromAngle, styles).append(group)
            },
            _drawTrackerMarker: function(renderer, group) {
                this.trackerGraphic = renderer.createArc(this.centerX, this.centerY, this.radiusOuter, this.radiusInner, this.toAngle, this.fromAngle).append(group);
                this.trackerGraphic.data({point: this})
            },
            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
                    }
            },
            _translate: function(translator) {
                var angle = this.shiftedAngle || 0;
                this.fromAngle = translator.translate(this.minValue) + angle;
                this.toAngle = translator.translate(this.value) + angle;
                this.middleAngle = translator.translate((this.value - this.minValue) / 2 + this.minValue) + angle;
                if (!this.isVisible())
                    this.middleAngle = this.toAngle = this.fromAngle = this.fromAngle || angle
            },
            _updateMarker: function(animationEnabled, style) {
                style = style || this._getStyle();
                if (!animationEnabled)
                    style = _extend({
                        x: this.centerX,
                        y: this.centerY,
                        outerRadius: this.radiusOuter,
                        innerRadius: this.radiusInner,
                        startAngle: this.toAngle,
                        endAngle: this.fromAngle
                    }, style);
                this.graphic.applySettings(style)
            },
            _updateTracker: function() {
                this.trackerGraphic.applySettings({
                    x: this.centerX,
                    y: this.centerY,
                    outerRadius: this.radiusOuter,
                    innerRadius: this.radiusInner,
                    startAngle: this.toAngle,
                    endAngle: this.fromAngle
                })
            },
            getLegendStyles: function() {
                return this._styles.legendStyles
            },
            isInVisibleArea: function() {
                return true
            },
            hide: function() {
                if (this._visible) {
                    this._visible = false;
                    this.hideTooltip();
                    this._options.visibilityChanged(this)
                }
            },
            show: function() {
                if (!this._visible) {
                    this._visible = true;
                    this._options.visibilityChanged(this)
                }
            },
            setInvisibility: function() {
                this._setTrackerInvisibility();
                this._label.hide()
            },
            isVisible: function() {
                return this._visible
            },
            _getFormatObject: function(tooltip) {
                var symbolMethods = points.symbolPoint,
                    formatObject = symbolMethods._getFormatObject.call(this, tooltip);
                formatObject.percent = this.percent;
                formatObject.percentText = tooltip.formatValue(this.percent, "percent");
                return formatObject
            },
            getColor: function() {
                return this._styles.normal.fill
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file rangeSymbolPoint.js */
    (function($, DX) {
        var viz = DevExpress.viz,
            points = viz.core.series.points.mixins,
            _extend = $.extend,
            _isDefined = DX.utils.isDefined,
            _math = Math,
            _abs = _math.abs,
            _min = _math.min,
            _max = _math.max,
            _round = _math.round,
            DEFAULT_IMAGE_WIDTH = 20,
            DEFAULT_IMAGE_HEIGHT = 20;
        points.rangeSymbolPoint = _extend({}, points.symbolPoint, {
            deleteLabel: function() {
                this._topLabel.dispose();
                this._topLabel = null;
                this._bottomLabel.dispose();
                this._bottomLabel = null
            },
            hideMarker: function(type) {
                var marker = this.graphic && this.graphic[type + "Marker"],
                    label = this["_" + type + "Label"];
                if (marker && marker.settings.visibility !== "hidden")
                    marker.applySettings({visibility: "hidden"});
                label.hide()
            },
            setInvisibility: function() {
                this.hideMarker("top");
                this.hideMarker("bottom");
                this._setTrackerInvisibility()
            },
            clearVisibility: function() {
                var graphic = this.graphic;
                if (graphic) {
                    if (graphic.topMarker && graphic.topMarker.settings.visibility)
                        graphic.topMarker.applySettings({visibility: null});
                    if (graphic.bottomMarker && graphic.bottomMarker.settings.visibility)
                        graphic.bottomMarker.applySettings({visibility: null})
                }
                this._clearTrackerVisibility();
                this._topLabel.clearVisibility();
                this._bottomLabel.clearVisibility()
            },
            clearMarker: function() {
                if (this.graphic) {
                    this.graphic.topMarker && this.graphic.topMarker.applySettings(this._emptySettings);
                    this.graphic.bottomMarker && this.graphic.bottomMarker.applySettings(this._emptySettings)
                }
            },
            _getLabelPosition: function(markerType) {
                var position,
                    rotated = this._options.rotated,
                    invertY = this.translators.y.getBusinessRange().invert,
                    invertX = this.translators.x.getBusinessRange().invert,
                    isDiscreteValue = this._options.series._options.valueAxisType === "discrete",
                    notInverted = isDiscreteValue && (!invertY && !rotated || invertX && rotated) || !isDiscreteValue && this.value > this.minValue && (!invertY && !rotated || !invertX && rotated);
                if (markerType === "top")
                    position = notInverted ? "top" : "bottom";
                else
                    position = notInverted ? "bottom" : "top";
                return position
            },
            _getLabelMinFormatObject: function() {
                return {
                        index: 0,
                        argument: this.initialArgument,
                        value: this.initialMinValue,
                        seriesName: this._options.series.name,
                        originalValue: this.originalMinValue,
                        originalArgument: this.originalArgument,
                        point: this
                    }
            },
            _updateLabelData: function() {
                var maxFormatObject = this._getLabelFormatObject();
                maxFormatObject.index = 1;
                this._topLabel.updateData({
                    formatObject: maxFormatObject,
                    initialValue: this.initialValue
                });
                this._bottomLabel.updateData({
                    formatObject: this._getLabelMinFormatObject(),
                    initialValue: this.initialMinValue
                })
            },
            _updateLabelOptions: function(type) {
                var options = this._getLabelOptions(type);
                (!this._topLabel || !this._bottomLabel) && this._createLabel();
                this._topLabel.setOptions(options);
                this._bottomLabel.setOptions(options)
            },
            setAdjustSeriesLabels: function(adjustSeriesLabels) {
                this._topLabel.adjustSeriesLabels = adjustSeriesLabels;
                this._bottomLabel.adjustSeriesLabels = adjustSeriesLabels
            },
            _createLabel: function() {
                this._topLabel = viz.core.CoreFactory.createLabel();
                this._bottomLabel = viz.core.CoreFactory.createLabel()
            },
            _getLabelCoords: function(location) {
                var coords = {},
                    isTop = location === "top";
                if (!this._options.rotated) {
                    coords.x = this.x;
                    coords.y = isTop ? _min(this.y, this.minY) : _max(this.y, this.minY)
                }
                else {
                    coords.x = isTop ? _max(this.x, this.minX) : _min(this.x, this.minX);
                    coords.y = this.y
                }
                return coords
            },
            _getGraphicBbox: function(location) {
                var options = this._options,
                    rotated = options.rotated,
                    isTop = location === "top",
                    images = this._getImage(options.image),
                    image = isTop ? this._checkImage(images.top) : this._checkImage(images.bottom),
                    bbox,
                    x,
                    y;
                if (!rotated) {
                    x = this.x;
                    y = isTop ? _min(this.y, this.minY) : _max(this.y, this.minY)
                }
                else {
                    x = isTop ? _max(this.x, this.minX) : _min(this.x, this.minX);
                    y = this.y
                }
                if (options.visible)
                    bbox = image ? this._getImageBbox(x, y) : this._getSymbolBbox(x, y, options.styles.normal.r);
                else
                    bbox = {
                        x: x,
                        y: y,
                        width: 0,
                        height: 0
                    };
                return bbox
            },
            _checkOverlay: function(bottomCoord, topCoord, topValue) {
                return bottomCoord < topCoord + topValue
            },
            _getOverlayCorrections: function(type, topCoords, bottomCoords) {
                var isVertical = type === "vertical",
                    coordSelector = isVertical ? "y" : "x",
                    valueSelector = isVertical ? "height" : "width",
                    visibleArea = this.translators[coordSelector].getCanvasVisibleArea(),
                    minBound = visibleArea.min,
                    maxBound = visibleArea.max,
                    delta = _round((topCoords[coordSelector] + topCoords[valueSelector] - bottomCoords[coordSelector]) / 2),
                    coord1 = topCoords[coordSelector] - delta,
                    coord2 = bottomCoords[coordSelector] + delta;
                if (coord1 < minBound) {
                    delta = minBound - topCoords[coordSelector];
                    coord1 += delta;
                    coord2 += delta
                }
                else if (coord2 + bottomCoords[valueSelector] > maxBound) {
                    delta = -(bottomCoords[coordSelector] + bottomCoords[valueSelector] - maxBound);
                    coord1 += delta;
                    coord2 += delta
                }
                return {
                        coord1: coord1,
                        coord2: coord2
                    }
            },
            _checkLabelsOverlay: function(topLocation) {
                var that = this,
                    topCoords = that._topLabel.getCoords(),
                    bottomCoords = that._bottomLabel.getCoords(),
                    corrections = {};
                if (!that._options.rotated) {
                    if (topLocation === "top") {
                        if (this._checkOverlay(bottomCoords.y, topCoords.y, topCoords.height)) {
                            corrections = this._getOverlayCorrections("vertical", topCoords, bottomCoords);
                            that._topLabel.updatePosition(undefined, corrections.coord1);
                            that._bottomLabel.updatePosition(undefined, corrections.coord2)
                        }
                    }
                    else if (this._checkOverlay(topCoords.y, bottomCoords.y, bottomCoords.height)) {
                        corrections = this._getOverlayCorrections("vertical", bottomCoords, topCoords);
                        that._topLabel.updatePosition(undefined, corrections.coord2);
                        that._bottomLabel.updatePosition(undefined, corrections.coord1)
                    }
                }
                else if (topLocation === "top") {
                    if (this._checkOverlay(topCoords.x, bottomCoords.x, bottomCoords.width)) {
                        corrections = this._getOverlayCorrections("horizontal", bottomCoords, topCoords);
                        that._topLabel.updatePosition(corrections.coord2);
                        that._bottomLabel.updatePosition(corrections.coord1)
                    }
                }
                else if (this._checkOverlay(bottomCoords.x, topCoords.x, topCoords.width)) {
                    corrections = this._getOverlayCorrections("horizontal", topCoords, bottomCoords);
                    that._topLabel.updatePosition(corrections.coord1);
                    that._bottomLabel.updatePosition(corrections.coord2)
                }
            },
            _drawLabel: function(renderer, group) {
                var topCoords,
                    bottomCoords,
                    rotated = this._options.rotated,
                    topLocation = this._getLabelPosition("top"),
                    bottomLocation = this._getLabelPosition("bottom"),
                    isInside = this._options.label.position === "inside",
                    topPosition = isInside ? bottomLocation : topLocation,
                    bottomPosition = isInside ? topLocation : bottomLocation,
                    translators = this.translators,
                    visibleArea,
                    customVisibility = this._getCustomLabelVisibility(),
                    commonVisibility = this._options.series.getLabelVisibility();
                if ((commonVisibility || customVisibility) && this.hasValue()) {
                    if (translators)
                        visibleArea = {
                            minX: translators.x.getCanvasVisibleArea().min,
                            maxX: translators.x.getCanvasVisibleArea().max,
                            minY: translators.y.getCanvasVisibleArea().min,
                            maxY: translators.y.getCanvasVisibleArea().max
                        };
                    this._topLabel.setCoords(this._getLabelCoords(topLocation), this._getGraphicBbox(topLocation), topPosition, visibleArea);
                    this._bottomLabel.setCoords(this._getLabelCoords(bottomLocation), this._getGraphicBbox(bottomLocation), bottomPosition, visibleArea);
                    this.visibleTopMarker && this._topLabel.draw(renderer, group, customVisibility);
                    this.visibleBottomMarker && this._bottomLabel.draw(renderer, group, customVisibility);
                    this._checkLabelsOverlay(topLocation)
                }
                else {
                    this._topLabel.hide();
                    this._bottomLabel.hide()
                }
            },
            _getImage: function(imageOption) {
                var image = {};
                if (_isDefined(imageOption))
                    if (typeof imageOption === "string")
                        image.top = image.bottom = imageOption;
                    else {
                        image.top = {
                            url: typeof imageOption.url === "string" ? imageOption.url : imageOption.url && imageOption.url.rangeMaxPoint,
                            width: typeof imageOption.width === "number" ? imageOption.width : imageOption.width && imageOption.width.rangeMaxPoint,
                            height: typeof imageOption.height === "number" ? imageOption.height : imageOption.height && imageOption.height.rangeMaxPoint
                        };
                        image.bottom = {
                            url: typeof imageOption.url === "string" ? imageOption.url : imageOption.url && imageOption.url.rangeMinPoint,
                            width: typeof imageOption.width === "number" ? imageOption.width : imageOption.width && imageOption.width.rangeMinPoint,
                            height: typeof imageOption.height === "number" ? imageOption.height : imageOption.height && imageOption.height.rangeMinPoint
                        }
                    }
                return image
            },
            _checkSymbol: function(oldOptions, newOptions) {
                var oldSymbol = oldOptions.symbol,
                    newSymbol = newOptions.symbol,
                    symbolChanged = oldSymbol === "circle" && newSymbol !== "circle" || oldSymbol !== "circle" && newSymbol === "circle",
                    oldImages = this._getImage(oldOptions.image),
                    newImages = this._getImage(newOptions.image),
                    topImageChanged = this._checkImage(oldImages.top) !== this._checkImage(newImages.top),
                    bottomImageChanged = this._checkImage(oldImages.bottom) !== this._checkImage(newImages.bottom);
                return symbolChanged || topImageChanged || bottomImageChanged
            },
            _getSettingsForTwoMarkers: function(style) {
                var that = this,
                    options = that._options,
                    settings = {},
                    x = options.rotated ? _min(that.x, that.minX) : that.x,
                    y = options.rotated ? that.y : _min(that.y, that.minY),
                    radius = style.r,
                    points = that._populatePointShape(options.symbol, radius);
                settings.top = {
                    r: radius,
                    points: points,
                    attr: _extend({
                        translateX: x + that.width,
                        translateY: y
                    }, style)
                };
                settings.bottom = {
                    r: radius,
                    points: points,
                    attr: _extend({
                        translateX: x,
                        translateY: y + that.height
                    }, style)
                };
                return settings
            },
            _hasGraphic: function() {
                return this.graphic && this.graphic.topMarker && this.graphic.bottomMarker
            },
            _drawOneMarker: function(renderer, markerType, imageSettings, settings) {
                if (this.graphic[markerType])
                    this._updateOneMarker(markerType, settings);
                else
                    this.graphic[markerType] = this._createMarker(renderer, this.graphic, imageSettings, settings)
            },
            _drawMarker: function(renderer, group, animationEnabled, style) {
                var that = this,
                    style = style || that._getStyle(),
                    settings = that._getSettingsForTwoMarkers(style),
                    image = that._getImage(that._options.image);
                if (that._checkImage(image.top))
                    settings.top = that._getImageSettings(settings.top, image.top);
                if (that._checkImage(image.bottom))
                    settings.bottom = that._getImageSettings(settings.bottom, image.bottom);
                that.graphic = that.graphic || renderer.createGroup().append(group);
                that.visibleTopMarker && that._drawOneMarker(renderer, 'topMarker', image.top, settings.top);
                that.visibleBottomMarker && that._drawOneMarker(renderer, 'bottomMarker', image.bottom, settings.bottom)
            },
            _getSettingsForTracker: function(radius) {
                var that = this,
                    options = that._options,
                    x = options.rotated ? _min(that.x, that.minX) - radius : that.x - radius,
                    y = options.rotated ? that.y - radius : _min(that.y, that.minY) - radius,
                    width = that.width + 2 * radius,
                    height = that.height + 2 * radius;
                return {
                        translateX: x,
                        translateY: y,
                        width: width,
                        height: height
                    }
            },
            _drawTrackerMarker: function(renderer, group) {
                var that = this,
                    options = that._options,
                    radius = options.trackerR || that.storeTrackerR(),
                    settings = that._getSettingsForTracker(radius),
                    attr = {
                        translateX: settings.translateX,
                        translateY: settings.translateY
                    };
                that.trackerGraphic = renderer.createRect(0, 0, settings.width, settings.height, 0, attr).append(group);
                that.trackerGraphic.data({point: that})
            },
            isInVisibleArea: function() {
                var that = this,
                    minArgument = _min(that.minX, that.x) || that.x,
                    maxArgument = _max(that.minX, that.x) || that.x,
                    maxValue = _max(that.minY, that.y) || that.y,
                    minValue = _min(that.minY, that.y) || that.y,
                    notVisibleBothMarkersRight,
                    notVisibleBothMarkersLeft,
                    notVisibleBothMarkersBottom,
                    notVisibleBothMarkersTop,
                    visibleTopMarker = true,
                    visibleBottomMarker = true,
                    visibleRangeArea = true,
                    visibleAreaX,
                    visibleAreaY;
                if (that.translators) {
                    visibleAreaX = that.translators.x.getCanvasVisibleArea();
                    visibleAreaY = that.translators.y.getCanvasVisibleArea();
                    notVisibleBothMarkersRight = visibleAreaX.max < minArgument && visibleAreaX.max < maxArgument;
                    notVisibleBothMarkersLeft = visibleAreaX.min > minArgument && visibleAreaX.min > maxArgument;
                    notVisibleBothMarkersTop = visibleAreaY.min > minValue && visibleAreaY.min > maxValue;
                    notVisibleBothMarkersBottom = visibleAreaY.max < minValue && visibleAreaY.max < maxValue;
                    if (notVisibleBothMarkersTop || notVisibleBothMarkersBottom || notVisibleBothMarkersRight || notVisibleBothMarkersLeft)
                        visibleTopMarker = visibleBottomMarker = visibleRangeArea = false;
                    else if (!that._options.rotated) {
                        visibleTopMarker = visibleAreaY.min < minValue && visibleAreaY.max > minValue;
                        visibleBottomMarker = visibleAreaY.min < maxValue && visibleAreaY.max > maxValue
                    }
                    else {
                        visibleBottomMarker = visibleAreaX.min < minArgument && visibleAreaX.max > minArgument;
                        visibleTopMarker = visibleAreaX.min < maxArgument && visibleAreaX.max > maxArgument
                    }
                }
                that.visibleTopMarker = visibleTopMarker;
                that.visibleBottomMarker = visibleBottomMarker;
                that.visibleRangeArea = visibleRangeArea;
                return visibleRangeArea
            },
            getTooltipCoords: function() {
                var that = this,
                    x,
                    y,
                    min,
                    max,
                    minValue,
                    visibleAreaX = that.translators.x.getCanvasVisibleArea(),
                    visibleAreaY = that.translators.y.getCanvasVisibleArea();
                if (!that._options.rotated) {
                    minValue = _min(that.y, that.minY);
                    x = that.x;
                    min = visibleAreaY.min > minValue ? visibleAreaY.min : minValue;
                    max = visibleAreaY.max < minValue + that.height ? visibleAreaY.max : minValue + that.height;
                    y = min + (max - min) / 2
                }
                else {
                    minValue = _min(that.x, that.minX);
                    y = that.y;
                    min = visibleAreaX.min > minValue ? visibleAreaX.min : minValue;
                    max = visibleAreaX.max < minValue + that.width ? visibleAreaX.max : minValue + that.width;
                    x = min + (max - min) / 2
                }
                return {
                        x: x,
                        y: y,
                        offset: 0
                    }
            },
            _translate: function(translators) {
                var symbolMethods = points.symbolPoint;
                this.minX = this.minY = translators.y.translate(this.minValue);
                symbolMethods._translate.call(this, translators);
                this.height = this._options.rotated ? 0 : _abs(this.minY - this.y);
                this.width = this._options.rotated ? _abs(this.x - this.minX) : 0
            },
            _updateData: function(data) {
                if (this.argument !== data.argument || this.value !== data.value || this.minValue !== data.minValue || this.tag !== data.tag) {
                    this._changeData(data);
                    this.minValue = this.initialMinValue = this.originalMinValue = data.minValue
                }
            },
            _getImageSettings: function(settings, image) {
                var x = settings.attr.translateX,
                    y = settings.attr.translateY;
                return {
                        href: image.url || image.toString(),
                        width: image.width || DEFAULT_IMAGE_WIDTH,
                        height: image.height || DEFAULT_IMAGE_HEIGHT,
                        attr: {
                            translateX: x,
                            translateY: y
                        }
                    }
            },
            _updateOneMarker: function(markerType, settings) {
                this.graphic && this.graphic[markerType] && this.graphic[markerType].applySettings(_extend({}, settings, settings.attr))
            },
            _updateMarker: function(animationEnabled, style) {
                this._drawMarker(undefined, undefined, undefined, style)
            },
            _updateTracker: function() {
                var radius = this.storeTrackerR(),
                    settings = this._getSettingsForTracker(radius);
                this.trackerGraphic.applySettings(settings)
            },
            _getFormatObject: function(tooltip) {
                var minValue = tooltip.formatValue(this.initialMinValue),
                    value = tooltip.formatValue(this.initialValue);
                return {
                        argument: this.initialArgument,
                        argumentText: tooltip.formatValue(this.initialArgument, "argument"),
                        valueText: minValue + " - " + value,
                        rangeValue1Text: minValue,
                        rangeValue2Text: value,
                        rangeValue1: this.initialMinValue,
                        rangeValue2: this.initialValue,
                        seriesName: this.series.name,
                        point: this,
                        originalMinValue: this.originalMinValue,
                        originalValue: this.originalValue,
                        originalArgument: this.originalArgument
                    }
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file rangeBarPoint.js */
    (function($, DX) {
        var viz = DevExpress.viz,
            points = viz.core.series.points.mixins,
            _isDefined = DX.utils.isDefined,
            rangeSymbolPointMethods = points.rangeSymbolPoint,
            _extend = $.extend;
        points.rangeBarPoint = _extend({}, points.barPoint, {
            deleteLabel: rangeSymbolPointMethods.deleteLabel,
            _getFormatObject: rangeSymbolPointMethods._getFormatObject,
            setAdjustSeriesLabels: rangeSymbolPointMethods.setAdjustSeriesLabels,
            clearVisibility: function() {
                if (this.graphic && this.graphic.settings.visibility)
                    this.graphic.applySettings({visibility: null});
                this._topLabel.clearVisibility();
                this._bottomLabel.clearVisibility()
            },
            setInvisibility: function() {
                if (this.graphic && this.graphic.settings.visibility !== "hidden")
                    this.graphic.applySettings({visibility: "hidden"});
                this._topLabel.hide();
                this._bottomLabel.hide()
            },
            _translate: function(translator) {
                var barMethods = points.barPoint;
                barMethods._translate.call(this, translator);
                if (this._options.rotated)
                    this.width = this.width || 1;
                else
                    this.height = this.height || 1
            },
            _updateData: rangeSymbolPointMethods._updateData,
            _getLabelPosition: rangeSymbolPointMethods._getLabelPosition,
            _getLabelMinFormatObject: rangeSymbolPointMethods._getLabelMinFormatObject,
            _updateLabelData: rangeSymbolPointMethods._updateLabelData,
            _updateLabelOptions: rangeSymbolPointMethods._updateLabelOptions,
            _createLabel: rangeSymbolPointMethods._createLabel,
            _checkOverlay: rangeSymbolPointMethods._checkOverlay,
            _getOverlayCorrections: rangeSymbolPointMethods._getOverlayCorrections,
            _drawLabel: function(renderer, group) {
                var topCoords,
                    bottomCoords,
                    rotated = this._options.rotated,
                    topLocation = this._getLabelPosition("top"),
                    bottomLocation = this._getLabelPosition("bottom"),
                    bbox = this._getGraphicBbox(),
                    coords = {
                        x: this.x,
                        y: this.y,
                        defaultX: this.defaultX,
                        defaultY: this.defaultY
                    },
                    translators = this.translators,
                    visibleArea,
                    customVisibility = this._getCustomLabelVisibility(),
                    commonVisibility = this._options.series.getLabelVisibility();
                if ((customVisibility || commonVisibility) && this.hasValue()) {
                    if (translators)
                        visibleArea = {
                            minX: translators.x.getCanvasVisibleArea().min,
                            maxX: translators.x.getCanvasVisibleArea().max,
                            minY: translators.y.getCanvasVisibleArea().min,
                            maxY: translators.y.getCanvasVisibleArea().max
                        };
                    this._topLabel.setCoords(coords, bbox, topLocation, visibleArea);
                    this._bottomLabel.setCoords(coords, bbox, bottomLocation, visibleArea);
                    this._topLabel.draw(renderer, group, customVisibility);
                    this._bottomLabel.draw(renderer, group, customVisibility);
                    rangeSymbolPointMethods._checkLabelsOverlay.call(this, topLocation)
                }
                else {
                    this._topLabel.hide();
                    this._bottomLabel.hide()
                }
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file candlestickPoint.js */
    (function($, DX) {
        var viz = DevExpress.viz,
            points = viz.core.series.points.mixins,
            _isNumeric = $.isNumeric,
            _extend = $.extend,
            _math = Math,
            _abs = _math.abs,
            _min = _math.min,
            _max = _math.max,
            _round = _math.round,
            DEFAULT_FINANCIAL_TRACKER_MARGIN = 2;
        points.candlestickPoint = _extend({}, points.barPoint, {
            _getContinuousPoints: function(minValueName, maxValueName) {
                var that = this,
                    x = that.x,
                    createPoint = that._options.rotated ? function(x, y) {
                        return {
                                x: y,
                                y: x
                            }
                    } : function(x, y) {
                        return {
                                x: x,
                                y: y
                            }
                    },
                    width = that.width,
                    min = that[minValueName],
                    max = that[maxValueName],
                    points;
                if (min === max)
                    points = [createPoint(x, that.highY), createPoint(x, that.lowY), createPoint(x, that.closeY), createPoint(x - width / 2, that.closeY), createPoint(x + width / 2, that.closeY), createPoint(x, that.closeY)];
                else
                    points = [createPoint(x, that.highY), createPoint(x, max), createPoint(x + width / 2, max), createPoint(x + width / 2, min), createPoint(x, min), createPoint(x, that.lowY), createPoint(x, min), createPoint(x - width / 2, min), createPoint(x - width / 2, max), createPoint(x, max)];
                return points
            },
            _getCategoryPoints: function(y) {
                var that = this,
                    x = that.x,
                    createPoint = that._options.rotated ? function(x, y) {
                        return {
                                x: y,
                                y: x
                            }
                    } : function(x, y) {
                        return {
                                x: x,
                                y: y
                            }
                    };
                return [createPoint(x, that.highY), createPoint(x, that.lowY), createPoint(x, y), createPoint(x - that.width / 2, y), createPoint(x + that.width / 2, y), createPoint(x, y)]
            },
            _getPoints: function() {
                var that = this,
                    points,
                    minValueName,
                    maxValueName,
                    openValue = that.openValue,
                    closeValue = that.closeValue;
                if (_isNumeric(openValue) && _isNumeric(closeValue)) {
                    minValueName = openValue > closeValue ? "closeY" : "openY";
                    maxValueName = openValue > closeValue ? "openY" : "closeY";
                    points = that._getContinuousPoints(minValueName, maxValueName)
                }
                else if (openValue === closeValue)
                    points = [{
                            x: that.x,
                            y: that.highY
                        }, {
                            x: that.x,
                            y: that.lowY
                        }];
                else
                    points = that._getCategoryPoints(_isNumeric(openValue) ? that.openY : that.closeY);
                return points
            },
            getColor: function() {
                return this._isReduction ? this._options.reduction.color : this._styles.normal.stroke || this.series.getColor()
            },
            _drawMarkerInGroup: function(group, attributes, renderer) {
                this.graphic = renderer.createArea(this._getPoints(), attributes).append(group)
            },
            _fillStyle: function() {
                var styles = this._options.styles;
                if (this._isReduction && this._isPositive)
                    this._styles = styles.reductionPositive;
                else if (this._isReduction)
                    this._styles = styles.reduction;
                else if (this._isPositive)
                    this._styles = styles.positive;
                else
                    this._styles = styles
            },
            _getMinTrackerWidth: function() {
                return 1 + 2 * this._styles.normal.strokeWidth
            },
            correctCoordinates: function(correctOptions) {
                var minWidth = this._getMinTrackerWidth(),
                    maxWidth = 10;
                this.width = correctOptions.width < minWidth ? minWidth : correctOptions.width > maxWidth ? maxWidth : correctOptions.width;
                this.xCorrection = correctOptions.offset
            },
            _getMarkerGroup: function(group) {
                var markerGroup;
                if (this._isReduction && this._isPositive)
                    markerGroup = group.reductionPositiveMarkersGroup;
                else if (this._isReduction)
                    markerGroup = group.reductionMarkersGroup;
                else if (this._isPositive)
                    markerGroup = group.defaultPositiveMarkersGroup;
                else
                    markerGroup = group.defaultMarkersGroup;
                return markerGroup
            },
            _drawMarker: function(renderer, group) {
                var attributes = this._getStyle(),
                    rotated = this._options.rotated,
                    pointGroup = this._getMarkerGroup(group);
                this._drawMarkerInGroup(pointGroup, attributes, renderer)
            },
            _getSettingsForTracker: function() {
                var that = this,
                    highY = that.highY,
                    lowY = that.lowY,
                    rotated = that._options.rotated,
                    x,
                    y,
                    width,
                    height;
                if (highY === lowY) {
                    highY = rotated ? highY + DEFAULT_FINANCIAL_TRACKER_MARGIN : highY - DEFAULT_FINANCIAL_TRACKER_MARGIN;
                    lowY = rotated ? lowY - DEFAULT_FINANCIAL_TRACKER_MARGIN : lowY + DEFAULT_FINANCIAL_TRACKER_MARGIN
                }
                if (rotated) {
                    x = _min(lowY, highY);
                    y = that.x - that.width / 2;
                    width = _abs(lowY - highY);
                    height = that.width
                }
                else {
                    x = that.x - that.width / 2;
                    y = _min(lowY, highY);
                    width = that.width;
                    height = _abs(lowY - highY)
                }
                return {
                        x: x,
                        y: y,
                        width: width,
                        height: height
                    }
            },
            _drawTrackerMarker: function(renderer, group) {
                var settings = this._getSettingsForTracker();
                this.trackerGraphic = renderer.createRect(settings.x, settings.y, settings.width, settings.height, 0).append(group);
                this.trackerGraphic.data({point: this})
            },
            _getGraphicBbox: function() {
                var bbox = {},
                    rotated = this._options.rotated;
                bbox.x = !rotated ? this.x - _round(this.width / 2) : this.lowY;
                bbox.y = !rotated ? this.highY : this.x - _round(this.width / 2);
                bbox.width = !rotated ? this.width : this.highY - this.lowY;
                bbox.height = !rotated ? this.lowY - this.highY : this.width;
                return bbox
            },
            _drawLabel: function(renderer, group) {
                var coords,
                    commonVisibility = this._options.series.getLabelVisibility(),
                    customVisibility = this._getCustomLabelVisibility(),
                    visibleArea,
                    reductionColor = this._options.reduction.color,
                    translators = this.translators;
                if (this.hasValue() && (commonVisibility || customVisibility)) {
                    visibleArea = {
                        minX: translators.x.getCanvasVisibleArea().min,
                        maxX: translators.x.getCanvasVisibleArea().max,
                        minY: translators.y.getCanvasVisibleArea().min,
                        maxY: translators.y.getCanvasVisibleArea().max
                    };
                    if (this._isReduction)
                        this._label.updateOptions({options: {
                                background: {fill: reductionColor},
                                connector: {stroke: reductionColor}
                            }});
                    coords = this._options.rotated ? {
                        x: this.highY,
                        y: this.x
                    } : {
                        x: this.x,
                        y: this.highY
                    };
                    this._label.setCoords(coords, this._getGraphicBbox(), "top", visibleArea);
                    this._label.draw(renderer, group, customVisibility)
                }
            },
            getTooltipCoords: function() {
                var that = this;
                if (that.graphic) {
                    var x,
                        y,
                        min,
                        max,
                        minValue = _min(that.lowY, that.highY),
                        maxValue = _max(that.lowY, that.highY),
                        visibleAreaX = that.translators.x.getCanvasVisibleArea(),
                        visibleAreaY = that.translators.y.getCanvasVisibleArea();
                    if (!that._options.rotated) {
                        min = _max(visibleAreaY.min, minValue);
                        max = _min(visibleAreaY.max, maxValue);
                        x = that.x;
                        y = min + (max - min) / 2
                    }
                    else {
                        min = _max(visibleAreaX.min, minValue);
                        max = _min(visibleAreaX.max, maxValue);
                        y = that.x;
                        x = min + (max - min) / 2
                    }
                    return {
                            x: x,
                            y: y,
                            offset: 0
                        }
                }
            },
            hasValue: function() {
                return this.highValue !== null && this.lowValue !== null
            },
            _translate: function(translator) {
                var that = this,
                    rotated = that._options.rotated,
                    argTranslator = rotated ? that.translators.y : that.translators.x,
                    valTranslator = rotated ? that.translators.x : that.translators.y,
                    centerValue,
                    height;
                that.x = argTranslator.translate(that.argument) + (that.xCorrection || 0);
                that.openY = that.openValue !== null ? valTranslator.translate(that.openValue) : null;
                that.highY = valTranslator.translate(that.highValue);
                that.lowY = valTranslator.translate(that.lowValue);
                that.closeY = that.closeValue !== null ? valTranslator.translate(that.closeValue) : null;
                height = _abs(that.lowY - that.highY);
                centerValue = _min(that.lowY, that.highY) + _abs(that.lowY - that.highY) / 2;
                that._calculateVisibility(!rotated ? that.x : centerValue, !rotated ? centerValue : that.x)
            },
            _updateData: function(data) {
                var that = this;
                if (that.argument !== data.argument || that.reductionValue !== data.reductionValue || that.highValue !== data.highValue || that.lowValue !== data.lowValue || that.openValue !== data.openValue || that.closeValue !== data.closeValue || that.tag !== data.tag) {
                    that.value = that.initialValue = data.reductionValue;
                    that.originalValue = data.value;
                    that.argument = that.initialArgument = data.argument;
                    that.originalArgument = data.argument;
                    that.lowValue = data.lowValue;
                    that.originalLowValue = data.lowValue;
                    that.highValue = data.highValue;
                    that.originalHighValue = data.highValue;
                    that.openValue = data.openValue;
                    that.originalOpenValue = data.openValue;
                    that.closeValue = data.closeValue;
                    that.originalCloseValue = data.closeValue;
                    that.tag = data.tag;
                    that.pointClassName = data.pointClassName;
                    that._isPositive = data.openValue < data.closeValue;
                    that._isReduction = data.isReduction
                }
            },
            _updateMarker: function(animationEnabled, style, group) {
                var style = style || this._getStyle();
                this.graphic.applySettings(_extend({points: this._getPoints()}, style));
                group && this.graphic.append(this._getMarkerGroup(group))
            },
            _updateTracker: function() {
                this.trackerGraphic.applySettings(this._getSettingsForTracker())
            },
            _getLabelFormatObject: function() {
                return {
                        openValue: this.openValue,
                        highValue: this.highValue,
                        lowValue: this.lowValue,
                        closeValue: this.closeValue,
                        reductionValue: this.initialValue,
                        argument: this.initialArgument,
                        value: this.initialValue,
                        seriesName: this._options.series.name,
                        originalOpenValue: this.originalOpenValue,
                        originalCloseValue: this.originalCloseValue,
                        originalLowValue: this.originalLowValue,
                        originalHighValue: this.originalHighValue,
                        originalArgument: this.originalArgument,
                        point: this
                    }
            },
            _getFormatObject: function(tooltip) {
                var highValue = tooltip.formatValue(this.highValue),
                    openValue = tooltip.formatValue(this.openValue),
                    closeValue = tooltip.formatValue(this.closeValue),
                    lowValue = tooltip.formatValue(this.lowValue),
                    symbolMethods = points.symbolPoint,
                    formatObject = symbolMethods._getFormatObject.call(this, tooltip);
                return _extend({}, formatObject, {
                        valueText: "h: " + highValue + (openValue !== "" ? " o: " + openValue : "") + (closeValue !== "" ? " c: " + closeValue : "") + " l: " + lowValue,
                        highValueText: highValue,
                        openValueText: openValue,
                        closeValueText: closeValue,
                        lowValueText: lowValue
                    })
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file stockPoint.js */
    (function($, DX) {
        var viz = DevExpress.viz,
            points = viz.core.series.points.mixins,
            _extend = $.extend,
            _isNumeric = $.isNumeric;
        points.stockPoint = _extend({}, points.candlestickPoint, {
            _getPoints: function() {
                var that = this,
                    createPoint = that._options.rotated ? function(x, y) {
                        return {
                                x: y,
                                y: x
                            }
                    } : function(x, y) {
                        return {
                                x: x,
                                y: y
                            }
                    },
                    openYExist = _isNumeric(that.openY),
                    closeYExist = _isNumeric(that.closeY),
                    x = that.x,
                    width = that.width,
                    points = [createPoint(x, that.highY), openYExist && createPoint(x, that.openY), openYExist && createPoint(x - width / 2, that.openY), openYExist && createPoint(x, that.openY), closeYExist && createPoint(x, that.closeY), closeYExist && createPoint(x + width / 2, that.closeY), closeYExist && createPoint(x, that.closeY), createPoint(x, that.lowY)];
                return points
            },
            _drawMarkerInGroup: function(group, attributes, renderer) {
                this.graphic = renderer.createPath(this._getPoints(), attributes).append(group)
            },
            _getMinTrackerWidth: function() {
                return 2 + this._styles.normal.strokeWidth
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file default.js */
    (function($, DX, undefined) {
        DX.viz.themes = DX.viz.themes || [];
        var fontFamilyDefault = "'Segoe UI', 'Helvetica Neue', 'Trebuchet MS', Verdana",
            fontFamilyLight = "'Segoe UI Light', 'Helvetica Neue Light', 'Segoe UI', 'Helvetica Neue', 'Trebuchet MS', Verdana",
            baseChartTheme = {
                containerBackgroundColor: '#ffffff',
                animation: {
                    enabled: true,
                    duration: 1000,
                    easing: 'easeOutCubic',
                    maxPointCountSupported: 300
                },
                commonSeriesSettings: {
                    border: {
                        visible: false,
                        width: 2
                    },
                    showInLegend: true,
                    visible: true,
                    hoverMode: 'excludePoints',
                    selectionMode: 'includePoints',
                    hoverStyle: {
                        hatching: {
                            direction: 'right',
                            width: 2,
                            step: 6,
                            opacity: 0.75
                        },
                        border: {
                            visible: false,
                            width: 3
                        }
                    },
                    selectionStyle: {
                        hatching: {
                            direction: 'right',
                            width: 2,
                            step: 6,
                            opacity: 0.5
                        },
                        border: {
                            visible: false,
                            width: 3
                        }
                    },
                    label: {
                        visible: false,
                        alignment: 'center',
                        rotationAngle: 0,
                        horizontalOffset: 0,
                        verticalOffset: 0,
                        radialOffset: 0,
                        format: '',
                        argumentFormat: '',
                        precision: 0,
                        argumentPrecision: 0,
                        percentPrecision: 0,
                        showForZeroValues: true,
                        customizeText: undefined,
                        maxLabelCount: undefined,
                        position: 'outside',
                        font: {color: '#ffffff'},
                        border: {
                            visible: false,
                            width: 1,
                            color: '#d3d3d3',
                            dashStyle: 'solid'
                        },
                        connector: {
                            visible: false,
                            width: 1
                        }
                    }
                },
                redrawOnResize: true,
                margin: {
                    left: 0,
                    top: 0,
                    right: 0,
                    bottom: 0
                },
                seriesSelectionMode: 'single',
                pointSelectionMode: 'single',
                legend: {
                    hoverMode: 'includePoints',
                    verticalAlignment: 'top',
                    horizontalAlignment: 'right',
                    position: 'outside',
                    visible: true,
                    customizeText: undefined,
                    itemTextPosition: undefined,
                    margin: 10,
                    equalColumnWidth: false,
                    markerSize: 12,
                    backgroundColor: undefined,
                    backgroundOpacity: undefined,
                    border: {
                        visible: false,
                        width: 1,
                        color: '#d3d3d3',
                        cornerRadius: 0,
                        dashStyle: 'solid'
                    },
                    paddingLeftRight: 20,
                    paddingTopBottom: 15,
                    columnCount: 0,
                    rowCount: 0,
                    columnItemSpacing: 20,
                    rowItemSpacing: 8
                },
                tooltip: {
                    enabled: false,
                    border: {
                        width: 1,
                        color: '#d3d3d3',
                        dashStyle: 'solid',
                        visible: true
                    },
                    font: {
                        family: fontFamilyDefault,
                        weight: 400,
                        size: 12,
                        color: '#232323'
                    },
                    color: '#ffffff',
                    arrowLength: 10,
                    paddingLeftRight: 18,
                    paddingTopBottom: 15,
                    shared: false,
                    format: '',
                    argumentFormat: '',
                    precision: 0,
                    argumentPrecision: 0,
                    percentPrecision: 0,
                    customizeText: undefined,
                    customizeTooltip: undefined,
                    shadow: {
                        opacity: 0.4,
                        offsetX: 0,
                        offsetY: 4,
                        blur: 2,
                        color: '#000000'
                    }
                },
                size: {
                    width: undefined,
                    height: undefined
                },
                loadingIndicator: {
                    font: {},
                    backgroundColor: '#ffffff',
                    text: 'Loading...'
                },
                dataPrepareSettings: {
                    checkTypeForAllData: false,
                    convertToAxisDataType: true,
                    sortingMethod: true
                },
                title: {
                    font: {
                        family: fontFamilyLight,
                        weight: 200,
                        color: '#232323',
                        size: 28
                    },
                    margin: 10
                },
                adaptiveLayout: {
                    width: 80,
                    height: 80,
                    keepLabels: true
                },
                _rtl: {legend: {itemTextPosition: 'left'}}
            },
            baseDarkChartTheme = {
                containerBackgroundColor: '#2b2b2b',
                commonSeriesSettings: {label: {border: {color: '#494949'}}},
                legend: {border: {color: '#494949'}},
                loadingIndicator: {backgroundColor: '#2b2b2b'},
                title: {font: {color: '#929292'}},
                tooltip: {
                    color: '#2b2b2b',
                    border: {color: '#494949'},
                    font: {color: '#929292'}
                }
            };
        DX.viz.themes.push({
            name: 'desktop',
            font: {
                color: '#767676',
                family: fontFamilyDefault,
                weight: 400,
                size: 12,
                cursor: 'default'
            },
            chart: $.extend(true, {}, baseChartTheme, {
                commonSeriesSettings: {
                    type: 'line',
                    stack: 'default',
                    point: {
                        visible: true,
                        symbol: 'circle',
                        size: 12,
                        border: {
                            visible: false,
                            width: 1
                        },
                        hoverMode: 'onlyPoint',
                        selectionMode: 'onlyPoint',
                        hoverStyle: {
                            border: {
                                visible: true,
                                width: 4
                            },
                            size: 12
                        },
                        selectionStyle: {
                            border: {
                                visible: true,
                                width: 4
                            },
                            size: 12
                        }
                    },
                    scatter: {},
                    line: {
                        width: 2,
                        dashStyle: 'solid',
                        hoverStyle: {
                            width: 3,
                            hatching: {direction: 'none'}
                        },
                        selectionStyle: {width: 3}
                    },
                    stackedline: {
                        width: 2,
                        dashStyle: 'solid',
                        hoverStyle: {
                            width: 3,
                            hatching: {direction: 'none'}
                        },
                        selectionStyle: {width: 3}
                    },
                    fullstackedline: {
                        width: 2,
                        dashStyle: 'solid',
                        hoverStyle: {
                            width: 3,
                            hatching: {direction: 'none'}
                        },
                        selectionStyle: {width: 3}
                    },
                    stepline: {
                        width: 2,
                        dashStyle: 'solid',
                        hoverStyle: {
                            width: 3,
                            hatching: {direction: 'none'}
                        },
                        selectionStyle: {width: 3}
                    },
                    area: {
                        point: {visible: false},
                        opacity: 0.5
                    },
                    stackedarea: {
                        point: {visible: false},
                        opacity: 0.5
                    },
                    fullstackedarea: {
                        point: {visible: false},
                        opacity: 0.5
                    },
                    steparea: {
                        border: {
                            visible: true,
                            width: 2
                        },
                        point: {visible: false},
                        hoverStyle: {border: {
                                visible: true,
                                width: 3
                            }},
                        selectionStyle: {border: {
                                visible: true,
                                width: 3
                            }},
                        opacity: 0.5
                    },
                    spline: {
                        width: 2,
                        hoverStyle: {
                            width: 3,
                            hatching: {direction: 'none'}
                        },
                        selectionStyle: {width: 3}
                    },
                    splinearea: {
                        point: {visible: false},
                        opacity: 0.5
                    },
                    bar: {
                        cornerRadius: 0,
                        point: {
                            hoverStyle: {border: {visible: false}},
                            selectionStyle: {border: {visible: false}}
                        }
                    },
                    stackedbar: {
                        cornerRadius: 0,
                        point: {
                            hoverStyle: {border: {visible: false}},
                            selectionStyle: {border: {visible: false}}
                        },
                        label: {position: "inside"}
                    },
                    fullstackedbar: {
                        cornerRadius: 0,
                        point: {
                            hoverStyle: {border: {visible: false}},
                            selectionStyle: {border: {visible: false}}
                        },
                        label: {position: "inside"}
                    },
                    rangebar: {
                        cornerRadius: 0,
                        point: {
                            hoverStyle: {border: {visible: false}},
                            selectionStyle: {border: {visible: false}}
                        }
                    },
                    rangearea: {
                        point: {visible: false},
                        opacity: 0.5
                    },
                    rangesplinearea: {
                        point: {visible: false},
                        opacity: 0.5
                    },
                    bubble: {
                        opacity: 0.5,
                        point: {
                            hoverStyle: {border: {visible: false}},
                            selectionStyle: {border: {visible: false}}
                        }
                    },
                    candlestick: {
                        width: 1,
                        innerColor: '#ffffff',
                        reduction: {color: '#ff0000'},
                        hoverStyle: {
                            width: 3,
                            hatching: {direction: 'none'}
                        },
                        selectionStyle: {width: 3},
                        point: {border: {visible: true}}
                    },
                    stock: {
                        width: 1,
                        reduction: {color: '#ff0000'},
                        hoverStyle: {
                            width: 3,
                            hatching: {direction: 'none'}
                        },
                        selectionStyle: {width: 3},
                        point: {border: {visible: true}}
                    }
                },
                crosshair: {
                    enabled: false,
                    color: '#c6c6c6',
                    width: 1,
                    dashStyle: 'solid',
                    verticalLine: {visible: true},
                    horizontalLine: {visible: true}
                },
                commonAxisSettings: {
                    tickInterval: undefined,
                    setTicksAtUnitBeginning: true,
                    valueMarginsEnabled: true,
                    placeholderSize: null,
                    logarithmBase: 10,
                    discreteAxisDivisionMode: 'betweenLabels',
                    visible: false,
                    color: '#d3d3d3',
                    width: 1,
                    multipleAxesSpacing: 5,
                    label: {
                        visible: true,
                        overlappingBehavior: {
                            mode: 'auto',
                            rotationAngle: 90,
                            staggeringSpacing: 5
                        },
                        precision: 0,
                        format: '',
                        customizeText: undefined,
                        indentFromAxis: 10
                    },
                    grid: {
                        visible: false,
                        color: '#d3d3d3',
                        width: 1
                    },
                    tick: {
                        visible: false,
                        color: '#d3d3d3'
                    },
                    title: {
                        font: {size: 16},
                        margin: 10
                    },
                    stripStyle: {
                        paddingLeftRight: 10,
                        paddingTopBottom: 5
                    },
                    constantLineStyle: {
                        paddingLeftRight: 10,
                        paddingTopBottom: 10,
                        width: 1,
                        color: '#000000',
                        dashStyle: 'solid',
                        label: {
                            visible: true,
                            position: 'inside'
                        }
                    }
                },
                horizontalAxis: {
                    isHorizontal: true,
                    position: 'bottom',
                    axisDivisionFactor: 50,
                    label: {alignment: "center"},
                    stripStyle: {label: {
                            horizontalAlignment: 'center',
                            verticalAlignment: 'top'
                        }},
                    constantLineStyle: {label: {
                            horizontalAlignment: 'right',
                            verticalAlignment: 'top'
                        }},
                    constantLines: {}
                },
                verticalAxis: {
                    isHorizontal: false,
                    position: 'left',
                    axisDivisionFactor: 30,
                    label: {
                        alignment: 'right',
                        overlappingBehavior: {mode: 'enlargeTickInterval'}
                    },
                    stripStyle: {label: {
                            horizontalAlignment: 'left',
                            verticalAlignment: 'center'
                        }},
                    constantLineStyle: {label: {
                            horizontalAlignment: 'left',
                            verticalAlignment: 'top'
                        }},
                    constantLines: {}
                },
                argumentAxis: {},
                valueAxis: {grid: {visible: true}},
                commonPaneSettings: {
                    backgroundColor: 'none',
                    border: {
                        color: '#d3d3d3',
                        width: 1,
                        visible: false,
                        top: true,
                        bottom: true,
                        left: true,
                        right: true,
                        dashStyle: 'solid'
                    }
                },
                useAggregation: false,
                adjustOnZoom: true,
                rotated: false,
                synchronizeMultiAxes: true,
                equalBarWidth: true,
                minBubbleSize: 12,
                maxBubbleSize: 0.2
            }),
            pie: $.extend(true, {}, baseChartTheme, {
                commonSeriesSettings: {
                    type: 'pie',
                    pie: {
                        border: {
                            visible: false,
                            width: 2,
                            color: '#ffffff'
                        },
                        hoverStyle: {
                            hatching: {
                                direction: 'right',
                                width: 4,
                                step: 10,
                                opacity: 0.75
                            },
                            border: {
                                visible: false,
                                width: 2
                            }
                        },
                        selectionStyle: {
                            hatching: {
                                direction: 'right',
                                width: 4,
                                step: 10,
                                opacity: 0.5
                            },
                            border: {
                                visible: false,
                                width: 2
                            }
                        }
                    },
                    doughnut: {
                        innerRadius: 0.5,
                        border: {
                            visible: false,
                            width: 2,
                            color: '#ffffff'
                        },
                        hoverStyle: {
                            hatching: {
                                direction: 'right',
                                width: 4,
                                step: 10,
                                opacity: 0.75
                            },
                            border: {
                                visible: false,
                                width: 2
                            }
                        },
                        selectionStyle: {
                            hatching: {
                                direction: 'right',
                                width: 4,
                                step: 10,
                                opacity: 0.5
                            },
                            border: {
                                visible: false,
                                width: 2
                            }
                        }
                    },
                    donut: {
                        innerRadius: 0.5,
                        border: {
                            visible: false,
                            width: 2,
                            color: '#ffffff'
                        },
                        hoverStyle: {
                            hatching: {
                                direction: 'right',
                                width: 4,
                                step: 10,
                                opacity: 0.75
                            },
                            border: {
                                visible: false,
                                width: 2
                            }
                        },
                        selectionStyle: {
                            hatching: {
                                direction: 'right',
                                width: 4,
                                step: 10,
                                opacity: 0.5
                            },
                            border: {
                                visible: false,
                                width: 2
                            }
                        }
                    }
                },
                legend: {hoverMode: 'markPoint'},
                adaptiveLayout: {keepLabels: false}
            }),
            pieIE8: {commonSeriesSettings: {
                    pie: {
                        hoverStyle: {border: {
                                visible: true,
                                color: '#ffffff'
                            }},
                        selectionStyle: {border: {
                                visible: true,
                                color: '#ffffff'
                            }}
                    },
                    donut: {
                        hoverStyle: {border: {
                                visible: true,
                                color: '#ffffff'
                            }},
                        selectionStyle: {border: {
                                visible: true,
                                color: '#ffffff'
                            }}
                    },
                    doughnut: {
                        hoverStyle: {border: {
                                visible: true,
                                color: '#ffffff'
                            }},
                        selectionStyle: {border: {
                                visible: true,
                                color: '#ffffff'
                            }}
                    }
                }},
            gauge: {
                containerBackgroundColor: '#ffffff',
                scale: {
                    majorTick: {
                        visible: true,
                        length: 5,
                        width: 2,
                        showCalculatedTicks: true,
                        useTicksAutoArrangement: true,
                        color: '#ffffff'
                    },
                    minorTick: {
                        visible: false,
                        length: 3,
                        width: 1,
                        showCalculatedTicks: true,
                        color: '#ffffff'
                    },
                    label: {
                        visible: true,
                        font: {}
                    }
                },
                rangeContainer: {
                    offset: 0,
                    width: 5,
                    backgroundColor: '#808080'
                },
                valueIndicator: {
                    _default: {color: '#c2c2c2'},
                    rangebar: {
                        space: 2,
                        size: 10,
                        color: '#cbc5cf',
                        backgroundColor: 'none',
                        text: {
                            indent: 0,
                            font: {
                                size: 14,
                                color: null
                            }
                        }
                    },
                    twocolorneedle: {secondColor: '#e18e92'},
                    twocolorrectangle: {secondColor: '#e18e92'}
                },
                subvalueIndicator: {
                    _default: {color: '#8798a5'},
                    trianglemarker: {
                        space: 2,
                        length: 14,
                        width: 13,
                        color: '#8798a5'
                    },
                    triangle: {
                        space: 2,
                        length: 14,
                        width: 13,
                        color: '#8798a5'
                    },
                    textcloud: {
                        arrowLength: 5,
                        horizontalOffset: 6,
                        verticalOffset: 3,
                        color: '#679ec5',
                        text: {font: {
                                color: '#ffffff',
                                size: 18
                            }}
                    }
                },
                valueIndicators: {
                    _default: {color: '#c2c2c2'},
                    rangebar: {
                        space: 2,
                        size: 10,
                        color: '#cbc5cf',
                        backgroundColor: 'none',
                        text: {
                            indent: 0,
                            font: {
                                size: 14,
                                color: null
                            }
                        }
                    },
                    twocolorneedle: {secondColor: '#e18e92'},
                    trianglemarker: {
                        space: 2,
                        length: 14,
                        width: 13,
                        color: '#8798a5'
                    },
                    textcloud: {
                        arrowLength: 5,
                        horizontalOffset: 6,
                        verticalOffset: 3,
                        color: '#679ec5',
                        text: {font: {
                                color: '#ffffff',
                                size: 18
                            }}
                    }
                },
                title: {
                    layout: {
                        horizontalAlignment: 'center',
                        verticalAlignment: 'top',
                        overlay: 0
                    },
                    font: {
                        size: 16,
                        color: '#232323',
                        family: fontFamilyDefault,
                        weight: 400
                    }
                },
                subtitle: {font: {
                        size: 14,
                        color: '#232323',
                        family: fontFamilyDefault,
                        weight: 400
                    }},
                indicator: {
                    hasPositiveMeaning: true,
                    layout: {
                        horizontalAlignment: 'center',
                        verticalAlignment: 'bottom',
                        overlay: 0
                    },
                    text: {font: {size: 18}}
                },
                tooltip: {
                    arrowLength: 10,
                    paddingLeftRight: 18,
                    paddingTopBottom: 15,
                    enabled: false,
                    border: {
                        width: 1,
                        color: '#d3d3d3',
                        dashStyle: 'solid',
                        visible: true
                    },
                    color: '#ffffff',
                    font: {
                        color: '#232323',
                        size: 12,
                        family: fontFamilyDefault,
                        weight: 400
                    },
                    shadow: {
                        opacity: 0.4,
                        offsetX: 0,
                        offsetY: 4,
                        blur: 2,
                        color: '#000000'
                    }
                },
                loadingIndicator: {
                    font: {},
                    backgroundColor: '#ffffff',
                    text: 'Loading...'
                },
                _circular: {
                    scale: {
                        orientation: 'outside',
                        label: {indentFromTick: 10}
                    },
                    rangeContainer: {orientation: 'outside'},
                    valueIndicator: {
                        type: 'rectangleneedle',
                        _default: {
                            offset: 20,
                            indentFromCenter: 0,
                            width: 2,
                            spindleSize: 14,
                            spindleGapSize: 10
                        },
                        triangleneedle: {width: 4},
                        triangle: {width: 4},
                        twocolorneedle: {
                            space: 2,
                            secondFraction: 0.4
                        },
                        twocolorrectangle: {
                            space: 2,
                            secondFraction: 0.4
                        },
                        rangebar: {offset: 30}
                    },
                    subvalueIndicator: {
                        type: 'trianglemarker',
                        trianglemarker: {offset: 6},
                        triangle: {offset: 6},
                        textcloud: {offset: -6}
                    },
                    valueIndicators: {
                        _type: 'rectangleneedle',
                        _default: {
                            offset: 20,
                            indentFromCenter: 0,
                            width: 2,
                            spindleSize: 14,
                            spindleGapSize: 10
                        },
                        triangleneedle: {width: 4},
                        twocolorneedle: {
                            space: 2,
                            secondFraction: 0.4
                        },
                        rangebar: {offset: 30},
                        trianglemarker: {offset: 6},
                        textcloud: {offset: -6}
                    }
                },
                _linear: {
                    scale: {
                        horizontalOrientation: 'right',
                        verticalOrientation: 'bottom',
                        label: {indentFromTick: -10}
                    },
                    rangeContainer: {
                        horizontalOrientation: 'right',
                        verticalOrientation: 'bottom'
                    },
                    valueIndicator: {
                        type: 'rangebar',
                        _default: {
                            offset: 2.5,
                            length: 15,
                            width: 15
                        },
                        rectangle: {width: 10},
                        rangebar: {
                            offset: 10,
                            horizontalOrientation: 'right',
                            verticalOrientation: 'bottom'
                        }
                    },
                    subvalueIndicator: {
                        type: 'trianglemarker',
                        _default: {
                            offset: -1,
                            horizontalOrientation: 'left',
                            verticalOrientation: 'top'
                        }
                    },
                    valueIndicators: {
                        _type: 'rectangle',
                        _default: {
                            offset: 2.5,
                            length: 15,
                            width: 15
                        },
                        rectangle: {width: 10},
                        rangebar: {
                            offset: 10,
                            horizontalOrientation: 'right',
                            verticalOrientation: 'bottom'
                        },
                        trianglemarker: {
                            offset: -1,
                            horizontalOrientation: 'left',
                            verticalOrientation: 'top'
                        },
                        textcloud: {
                            offset: -1,
                            horizontalOrientation: 'left',
                            verticalOrientation: 'top'
                        }
                    }
                }
            },
            barGauge: {
                backgroundColor: '#e0e0e0',
                relativeInnerRadius: 0.3,
                barSpacing: 4,
                label: {
                    indent: 20,
                    connectorWidth: 2,
                    font: {size: 16}
                },
                title: {
                    layout: {
                        horizontalAlignment: 'center',
                        verticalAlignment: 'top',
                        overlay: 0
                    },
                    font: {
                        size: 16,
                        color: '#232323',
                        family: fontFamilyDefault,
                        weight: 400
                    }
                },
                subtitle: {font: {
                        size: 14,
                        color: '#232323',
                        family: fontFamilyDefault,
                        weight: 400
                    }},
                indicator: {
                    hasPositiveMeaning: true,
                    layout: {
                        horizontalAlignment: 'center',
                        verticalAlignment: 'bottom',
                        overlay: 0
                    },
                    text: {font: {size: 18}}
                },
                tooltip: {
                    arrowLength: 10,
                    paddingLeftRight: 18,
                    paddingTopBottom: 15,
                    enabled: false,
                    border: {
                        width: 1,
                        color: '#d3d3d3',
                        dashStyle: 'solid',
                        visible: true
                    },
                    color: '#ffffff',
                    font: {
                        size: 12,
                        color: '#232323',
                        family: fontFamilyDefault,
                        weight: 400
                    },
                    shadow: {
                        opacity: 0.4,
                        offsetX: 0,
                        offsetY: 4,
                        blur: 2,
                        color: '#000000'
                    }
                },
                loadingIndicator: {
                    font: {},
                    backgroundColor: '#ffffff',
                    text: 'Loading...'
                }
            },
            rangeSelector: {
                containerBackgroundColor: '#ffffff',
                scale: {
                    label: {
                        topIndent: 7,
                        font: {size: 11}
                    },
                    tick: {
                        width: 1,
                        color: '#000000',
                        opacity: 0.1
                    },
                    marker: {
                        separatorHeight: 33,
                        topIndent: 10,
                        textLeftIndent: 7,
                        textTopIndent: 11
                    }
                },
                loadingIndicator: {
                    font: {},
                    backgroundColor: '#ffffff',
                    text: 'Loading...'
                },
                sliderMarker: {
                    padding: 7,
                    pointerSize: 6,
                    color: '#9b9b9b',
                    invalidRangeColor: '#ff0000',
                    font: {
                        color: '#ffffff',
                        size: 11
                    }
                },
                sliderHandle: {
                    width: 1,
                    color: '#000000',
                    opacity: 0.2
                },
                shutter: {
                    color: undefined,
                    opacity: 0.75
                },
                background: {color: "#c0bae1"},
                chart: {
                    containerBackgroundColor: undefined,
                    commonSeriesSettings: {
                        label: baseChartTheme.commonSeriesSettings.label,
                        border: {
                            visible: false,
                            width: 1
                        },
                        visible: true,
                        type: 'area',
                        hoverMode: 'none',
                        hoverStyle: {border: {}},
                        selectionStyle: {border: {}},
                        point: {
                            visible: false,
                            symbol: 'circle',
                            border: {
                                visible: false,
                                width: 1
                            },
                            size: 12,
                            hoverStyle: {border: {}},
                            selectionStyle: {border: {}}
                        },
                        line: {width: 2},
                        stepline: {width: 2},
                        scatter: {point: {visible: true}},
                        stackedline: {width: 2},
                        fullstackedline: {width: 2},
                        area: {opacity: 0.5},
                        stackedarea: {opacity: 0.5},
                        fullstackedarea: {opacity: 0.5},
                        spline: {width: 2},
                        splinearea: {opacity: 0.5},
                        steparea: {
                            border: {
                                visible: true,
                                width: 2
                            },
                            opacity: 0.5
                        },
                        bubble: {
                            opacity: 0.5,
                            point: {visible: true}
                        },
                        bar: {
                            cornerRadius: 0,
                            point: {visible: true}
                        },
                        stackedbar: {
                            cornerRadius: 0,
                            point: {visible: true}
                        },
                        fullstackedbar: {
                            cornerRadius: 0,
                            point: {visible: true}
                        },
                        rangebar: {
                            cornerRadius: 0,
                            point: {visible: true}
                        },
                        rangearea: {opacity: 0.5},
                        rangesplinearea: {opacity: 0.5},
                        candlestick: {
                            width: 1,
                            innerColor: '#ffffff',
                            reduction: {color: '#ff0000'}
                        },
                        stock: {
                            width: 1,
                            reduction: {color: '#ff0000'}
                        }
                    },
                    dataPrepareSettings: {
                        checkTypeForAllData: false,
                        convertToAxisDataType: true,
                        sortingMethod: true
                    },
                    useAggregation: false,
                    equalBarWidth: true,
                    minBubbleSize: 12,
                    maxBubbleSize: 0.2,
                    topIndent: 0.1,
                    bottomIndent: 0,
                    valueAxis: {
                        min: undefined,
                        max: undefined,
                        inverted: false,
                        logarithmBase: 10
                    }
                }
            },
            map: {
                background: {
                    borderWidth: 1,
                    borderColor: '#cacaca',
                    color: '#ffffff'
                },
                area: {
                    borderWidth: 1,
                    borderColor: '#ffffff',
                    color: '#d2d2d2',
                    hoveredBorderColor: '#303030',
                    selectedBorderWidth: 2,
                    selectedBorderColor: '#303030'
                },
                marker: {
                    font: {
                        color: '#2b2b2b',
                        size: 12
                    },
                    _dot: {
                        borderWidth: 2,
                        borderColor: '#ffffff',
                        color: '#ba4d51',
                        size: 8,
                        selectedStep: 2,
                        backStep: 18,
                        backColor: '#ffffff',
                        backOpacity: 0.32,
                        shadow: true
                    },
                    _bubble: {
                        minSize: 20,
                        maxSize: 50,
                        color: '#ba4d51',
                        hoveredBorderWidth: 1,
                        hoveredBorderColor: '#303030',
                        selectedBorderWidth: 2,
                        selectedBorderColor: '#303030'
                    },
                    _pie: {
                        size: 50,
                        hoveredBorderWidth: 1,
                        hoveredBorderColor: '#303030',
                        selectedBorderWidth: 2,
                        selectedBorderColor: '#303030'
                    },
                    _image: {size: 20}
                },
                controlBar: {
                    borderColor: '#5d5d5d',
                    borderWidth: 3,
                    color: '#ffffff'
                },
                tooltip: {
                    borderWidth: 1,
                    borderColor: '#d7d7d7',
                    arrowLength: 10,
                    paddingLeftRight: 18,
                    paddingTopBottom: 15,
                    border: {
                        width: 1,
                        color: '#d3d3d3',
                        dashStyle: 'solid',
                        visible: true
                    },
                    color: '#ffffff',
                    font: {
                        color: '#232323',
                        size: 12,
                        family: fontFamilyDefault,
                        weight: 400
                    },
                    shadow: {
                        opacity: 0.4,
                        offsetX: 0,
                        offsetY: 4,
                        blur: 2,
                        color: '#000000'
                    }
                },
                legend: {
                    verticalAlignment: 'bottom',
                    horizontalAlignment: 'right',
                    position: 'inside',
                    visible: true,
                    margin: 10,
                    equalColumnWidth: false,
                    markerSize: 12,
                    backgroundColor: '#ffffff',
                    backgroundOpacity: 0.65,
                    border: {
                        visible: true,
                        width: 1,
                        color: '#cacaca',
                        cornerRadius: 0,
                        dashStyle: 'solid'
                    },
                    paddingLeftRight: 16,
                    paddingTopBottom: 12,
                    columnItemSpacing: 20,
                    rowItemSpacing: 8,
                    font: {
                        color: '#2b2b2b',
                        size: 12
                    }
                },
                loadingIndicator: {
                    backgroundColor: '#ffffff',
                    font: {},
                    text: 'Loading...'
                },
                _rtl: {legend: {itemTextPosition: 'left'}}
            },
            sparkline: {
                lineColor: '#666666',
                lineWidth: 2,
                areaOpacity: 0.2,
                minColor: '#e8c267',
                maxColor: '#e55253',
                barPositiveColor: '#a9a9a9',
                barNegativeColor: '#d7d7d7',
                winColor: '#a9a9a9',
                lossColor: '#d7d7d7',
                firstLastColor: '#666666',
                pointSymbol: 'circle',
                pointColor: '#ffffff',
                pointSize: 4,
                tooltip: {
                    enabled: true,
                    allowContainerResizing: true,
                    verticalAlignment: 'top',
                    horizontalAlignment: 'center',
                    format: '',
                    paddingLeftRight: 18,
                    paddingTopBottom: 15,
                    arrowLength: 10,
                    precision: 0,
                    color: '#ffffff',
                    border: {
                        width: 1,
                        color: '#d3d3d3',
                        dashStyle: 'solid',
                        visible: true
                    },
                    font: {
                        color: '#232323',
                        family: fontFamilyDefault,
                        size: 12,
                        weight: 400
                    },
                    shadow: {
                        opacity: 0.4,
                        offsetX: 0,
                        offsetY: 4,
                        blur: 2,
                        color: '#000000'
                    }
                }
            },
            bullet: {
                color: '#e8c267',
                targetColor: '#666666',
                targetWidth: 4,
                showTarget: true,
                showZeroLevel: true,
                tooltip: {
                    enabled: true,
                    allowContainerResizing: true,
                    verticalAlignment: 'top',
                    horizontalAlignment: 'center',
                    format: '',
                    precision: 0,
                    paddingLeftRight: 18,
                    paddingTopBottom: 15,
                    arrowLength: 10,
                    color: '#ffffff',
                    border: {
                        width: 1,
                        color: '#d3d3d3',
                        dashStyle: 'solid',
                        visible: true
                    },
                    font: {
                        color: '#232323',
                        family: fontFamilyDefault,
                        size: 12,
                        weight: 400
                    },
                    shadow: {
                        opacity: 0.4,
                        offsetX: 0,
                        offsetY: 4,
                        blur: 2,
                        color: '#000000'
                    }
                }
            }
        });
        DX.viz.core.registerTheme({
            name: 'desktop-dark',
            font: {color: '#808080'},
            chart: $.extend(true, {}, baseDarkChartTheme, {
                commonSeriesSettings: {candlestick: {innerColor: '#2b2b2b'}},
                crosshair: {color: '#515151'},
                commonAxisSettings: {
                    color: '#494949',
                    grid: {color: '#494949'},
                    tick: {color: '#494949'},
                    constantLineStyle: {color: '#ffffff'}
                },
                commonPaneSettings: {border: {color: '#494949'}}
            }),
            pie: $.extend(true, {}, baseDarkChartTheme),
            pieIE8: {commonSeriesSettings: {
                    pie: {
                        hoverStyle: {border: {color: '#2b2b2b'}},
                        selectionStyle: {border: {color: '#2b2b2b'}}
                    },
                    donut: {
                        hoverStyle: {border: {color: '#2b2b2b'}},
                        selectionStyle: {border: {color: '#2b2b2b'}}
                    },
                    doughnut: {
                        hoverStyle: {border: {color: '#2b2b2b'}},
                        selectionStyle: {border: {color: '#2b2b2b'}}
                    }
                }},
            gauge: {
                containerBackgroundColor: '#2b2b2b',
                scale: {
                    majorTick: {color: '#303030'},
                    minorTick: {color: '#303030'}
                },
                rangeContainer: {backgroundColor: '#b5b5b5'},
                valueIndicator: {
                    _default: {color: '#b5b5b5'},
                    rangebar: {color: '#84788b'},
                    twocolorneedle: {secondColor: '#ba544d'},
                    twocolorrectangle: {secondColor: '#ba544d'}
                },
                subvalueIndicator: {_default: {color: '#b7918f'}},
                valueIndicators: {
                    _default: {color: '#b5b5b5'},
                    rangebar: {color: '#84788b'},
                    twocolorneedle: {secondColor: '#ba544d'},
                    trianglemarker: {color: '#b7918f'},
                    textcloud: {color: '#ba544d'}
                },
                title: {font: {color: '#929292'}},
                subtitle: {font: {color: '#929292'}},
                loadingIndicator: {backgroundColor: '#2b2b2b'},
                tooltip: {
                    color: '#2b2b2b',
                    border: {color: '#494949'},
                    font: {color: '#929292'}
                }
            },
            barGauge: {
                title: {font: {color: '#929292'}},
                subtitle: {font: {color: '#929292'}},
                tooltip: {
                    color: '#2b2b2b',
                    border: {color: '#494949'},
                    font: {color: '#929292'}
                },
                loadingIndicator: {backgroundColor: '#2b2b2b'}
            },
            rangeSelector: {
                containerBackgroundColor: '#2b2b2b',
                scale: {tick: {
                        color: '#ffffff',
                        opacity: 0.05
                    }},
                loadingIndicator: {backgroundColor: '#2b2b2b'},
                sliderMarker: {
                    color: '#b5b5b5',
                    font: {color: '#303030'}
                },
                sliderHandle: {
                    color: '#ffffff',
                    opacity: 0.35
                },
                shutter: {
                    color: '#2b2b2b',
                    opacity: 0.9
                }
            },
            map: {
                background: {
                    borderColor: '#3f3f3f',
                    color: '#303030'
                },
                area: {
                    borderColor: '#303030',
                    color: '#686868',
                    hoveredBorderColor: '#ffffff',
                    selectedBorderColor: '#ffffff'
                },
                marker: {
                    font: {color: '#ffffff'},
                    _bubble: {
                        hoveredBorderColor: '#ffffff',
                        selectedBorderColor: '#ffffff'
                    },
                    _pie: {
                        hoveredBorderColor: '#ffffff',
                        selectedBorderColor: '#ffffff'
                    }
                },
                controlBar: {
                    borderColor: '#c7c7c7',
                    color: '#303030'
                },
                legend: {
                    border: {color: '#3f3f3f'},
                    backgroundColor: '#303030',
                    font: {color: '#ffffff'}
                },
                tooltip: {
                    color: '#2b2b2b',
                    border: {color: '#494949'},
                    font: {color: '#929292'}
                },
                loadingIndicator: {backgroundColor: '#2b2b2b'}
            },
            sparkline: {
                lineColor: '#c7c7c7',
                firstLastColor: '#c7c7c7',
                barPositiveColor: '#b8b8b8',
                barNegativeColor: '#8e8e8e',
                winColor: '#b8b8b8',
                lossColor: '#8e8e8e',
                pointColor: '#303030',
                tooltip: {
                    color: '#2b2b2b',
                    border: {color: '#494949'},
                    font: {color: '#929292'}
                }
            },
            bullet: {
                targetColor: '#8e8e8e',
                tooltip: {
                    color: '#2b2b2b',
                    border: {color: '#494949'},
                    font: {color: '#929292'}
                }
            }
        }, 'desktop')
    })(jQuery, DevExpress);
    /*! Module viz-core, file android.js */
    (function($, DX, undefined) {
        var baseChartTheme = {
                containerBackgroundColor: '#050506',
                title: {font: {color: '#ffffff'}},
                commonSeriesSettings: {label: {border: {color: '#4c4c4c'}}},
                legend: {
                    font: {
                        color: '#ffffff',
                        size: 11
                    },
                    border: {color: '#4c4c4c'}
                },
                loadingIndicator: {backgroundColor: '#050506'},
                tooltip: {
                    color: '#050506',
                    border: {color: '#4c4c4c'},
                    font: {color: '#ffffff'}
                }
            },
            baseLightChartTheme = {
                containerBackgroundColor: '#e8e8e8',
                title: {font: {color: '#808080'}},
                legend: {font: {
                        color: '#000000',
                        size: 11
                    }},
                loadingIndicator: {backgroundColor: '#e8e8e8'},
                tooltip: {
                    color: '#e8e8e8',
                    font: {color: '#808080'}
                }
            };
        DX.viz.core.registerTheme({
            name: 'android',
            chart: $.extend(true, {}, baseChartTheme, {
                commonSeriesSettings: {candlestick: {innerColor: '#050506'}},
                commonAxisSettings: {
                    color: '#4c4c4c',
                    grid: {color: '#4c4c4c'},
                    tick: {color: '#4c4c4c'},
                    title: {font: {color: '#545455'}},
                    label: {font: {
                            color: '#ffffff',
                            size: 11
                        }}
                },
                commonPaneSettings: {border: {color: '#4c4c4c'}}
            }),
            pie: $.extend(true, {}, baseChartTheme),
            pieIE8: {commonSeriesSettings: {
                    pie: {
                        hoverStyle: {border: {color: '#050506'}},
                        selectionStyle: {border: {color: '#050506'}}
                    },
                    donut: {
                        hoverStyle: {border: {color: '#050506'}},
                        selectionStyle: {border: {color: '#050506'}}
                    },
                    doughnut: {
                        hoverStyle: {border: {color: '#050506'}},
                        selectionStyle: {border: {color: '#050506'}}
                    }
                }},
            gauge: {
                containerBackgroundColor: '#050506',
                title: {font: {color: '#ffffff'}},
                subtitle: {font: {color: '#ffffff'}},
                loadingIndicator: {backgroundColor: '#050506'},
                tooltip: {
                    color: '#050506',
                    border: {color: '#4c4c4c'},
                    font: {color: '#ffffff'}
                }
            },
            barGauge: {
                title: {font: {color: '#ffffff'}},
                subtitle: {font: {color: '#ffffff'}},
                tooltip: {
                    color: '#050506',
                    border: {color: '#4c4c4c'},
                    font: {color: '#ffffff'}
                },
                loadingIndicator: {backgroundColor: '#050506'}
            },
            rangeSelector: {
                containerBackgroundColor: '#050506',
                loadingIndicator: {backgroundColor: '#050506'}
            },
            map: {
                loadingIndicator: {backgroundColor: '#050506'},
                tooltip: {
                    color: '#050506',
                    border: {color: '#4c4c4c'},
                    font: {color: '#ffffff'}
                }
            },
            sparkline: {tooltip: {
                    color: '#050506',
                    border: {color: '#4c4c4c'},
                    font: {color: '#ffffff'}
                }},
            bullet: {tooltip: {
                    color: '#050506',
                    border: {color: '#4c4c4c'},
                    font: {color: '#ffffff'}
                }}
        }, 'desktop-dark');
        DX.viz.core.registerTheme({
            name: 'android-holo-light',
            chart: $.extend(true, {}, baseLightChartTheme, {
                commonSeriesSettings: {candlestick: {innerColor: '#e8e8e8'}},
                commonAxisSettings: {
                    title: {font: {color: '#939393'}},
                    label: {font: {
                            color: '#404040',
                            size: 11
                        }}
                }
            }),
            pie: $.extend(true, {}, baseLightChartTheme),
            pieIE8: {commonSeriesSettings: {
                    pie: {
                        hoverStyle: {border: {color: '#e8e8e8'}},
                        selectionStyle: {border: {color: '#e8e8e8'}}
                    },
                    donut: {
                        hoverStyle: {border: {color: '#e8e8e8'}},
                        selectionStyle: {border: {color: '#e8e8e8'}}
                    },
                    doughnut: {
                        hoverStyle: {border: {color: '#e8e8e8'}},
                        selectionStyle: {border: {color: '#e8e8e8'}}
                    }
                }},
            gauge: {
                containerBackgroundColor: '#e8e8e8',
                title: {font: {color: '#808080'}},
                subtitle: {font: {color: '#808080'}},
                loadingIndicator: {backgroundColor: '#e8e8e8'},
                tooltip: {
                    color: '#e8e8e8',
                    font: {color: '#808080'}
                }
            },
            barGauge: {
                title: {font: {color: '#808080'}},
                subtitle: {font: {color: '#808080'}},
                tooltip: {
                    color: '#e8e8e8',
                    font: {color: '#808080'}
                },
                loadingIndicator: {backgroundColor: '#e8e8e8'}
            },
            rangeSelector: {
                containerBackgroundColor: '#e8e8e8',
                loadingIndicator: {backgroundColor: '#e8e8e8'}
            },
            map: {
                loadingIndicator: {backgroundColor: '#e8e8e8'},
                tooltip: {
                    color: '#e8e8e8',
                    font: {color: '#808080'}
                }
            },
            sparkline: {tooltip: {
                    color: '#e8e8e8',
                    font: {color: '#808080'}
                }},
            bullet: {tooltip: {
                    color: '#e8e8e8',
                    font: {color: '#808080'}
                }}
        }, 'desktop')
    })(jQuery, DevExpress);
    /*! Module viz-core, file ios.js */
    (function($, DX, undefined) {
        var baseChartTheme = {
                containerBackgroundColor: '#cbd0da',
                title: {font: {color: '#808080'}},
                commonSeriesSettings: {label: {border: {color: '#b0b3ba'}}},
                legend: {
                    font: {
                        color: '#000000',
                        size: 11
                    },
                    border: {color: '#b0b3ba'}
                },
                loadingIndicator: {backgroundColor: '#cbd0da'},
                tooltip: {font: {color: '#808080'}}
            },
            baseIos7ChartTheme = {
                containerBackgroundColor: '#ffffff',
                title: {font: {color: '#808080'}},
                commonSeriesSettings: {label: {border: {color: '#d3d3d3'}}},
                legend: {
                    font: {
                        color: '#000000',
                        size: 11
                    },
                    border: {color: '#d3d3d3'}
                },
                loadingIndicator: {backgroundColor: '#ffffff'},
                tooltip: {font: {color: '#808080'}}
            };
        DX.viz.core.registerTheme({
            name: 'ios',
            chart: $.extend(true, {}, baseChartTheme, {
                commonSeriesSettings: {candlestick: {innerColor: '#cbd0da'}},
                commonAxisSettings: {
                    color: '#b0b3ba',
                    grid: {color: '#b0b3ba'},
                    tick: {color: '#b0b3ba'},
                    title: {font: {color: '#939393'}},
                    label: {font: {
                            color: '#000000',
                            size: 11
                        }}
                },
                commonPaneSettings: {border: {color: '#b0b3ba'}}
            }),
            pie: $.extend(true, {}, baseChartTheme),
            pieIE8: {commonSeriesSettings: {
                    pie: {
                        hoverStyle: {border: {color: '#cbd0da'}},
                        selectionStyle: {border: {color: '#cbd0da'}}
                    },
                    donut: {
                        hoverStyle: {border: {color: '#cbd0da'}},
                        selectionStyle: {border: {color: '#cbd0da'}}
                    },
                    doughnut: {
                        hoverStyle: {border: {color: '#cbd0da'}},
                        selectionStyle: {border: {color: '#cbd0da'}}
                    }
                }},
            gauge: {
                title: {font: {color: '#808080'}},
                subtitle: {font: {color: '#808080'}},
                tooltip: {font: {color: '#808080'}}
            },
            barGauge: {
                title: {font: {color: '#808080'}},
                subtitle: {font: {color: '#808080'}},
                tooltip: {font: {color: '#808080'}}
            },
            map: {tooltip: {font: {color: '#808080'}}},
            sparkline: {tooltip: {font: {color: '#808080'}}},
            bullet: {tooltip: {font: {color: '#808080'}}}
        }, 'desktop');
        DX.viz.core.registerTheme({
            name: 'ios:7',
            chart: $.extend(true, {}, baseIos7ChartTheme, {
                commonAxisSettings: {
                    color: '#d3d3d3',
                    grid: {color: '#d3d3d3'},
                    tick: {color: '#d3d3d3'},
                    title: {font: {color: '#939393'}},
                    label: {font: {
                            color: '#000000',
                            size: 11
                        }}
                },
                commonPaneSettings: {border: {color: '#d3d3d3'}}
            }),
            pie: $.extend(true, {}, baseIos7ChartTheme),
            gauge: {
                title: {font: {color: '#808080'}},
                subtitle: {font: {color: '#808080'}},
                tooltip: {font: {color: '#808080'}}
            },
            barGauge: {
                title: {font: {color: '#808080'}},
                subtitle: {font: {color: '#808080'}},
                tooltip: {font: {color: '#808080'}}
            },
            map: {tooltip: {font: {color: '#808080'}}},
            sparkline: {tooltip: {font: {color: '#808080'}}},
            bullet: {tooltip: {font: {color: '#808080'}}}
        }, 'desktop')
    })(jQuery, DevExpress);
    /*! Module viz-core, file win8.js */
    (function($, DX) {
        var baseChartTheme = {
                containerBackgroundColor: '#000000',
                title: {font: {color: '#ffffff'}},
                commonSeriesSettings: {label: {border: {color: '#454545'}}},
                legend: {
                    font: {
                        color: '#ffffff',
                        size: 11
                    },
                    border: {color: '#454545'}
                },
                loadingIndicator: {backgroundColor: '#000000'},
                tooltip: {
                    color: '#000000',
                    font: {color: '#ffffff'}
                }
            },
            baseWhiteChartTheme = {
                title: {font: {color: '#808080'}},
                legend: {font: {
                        color: '#000000',
                        size: 11
                    }},
                tooltip: {font: {color: '#808080'}}
            };
        DX.viz.core.registerTheme({
            name: 'win8',
            chart: $.extend(true, {}, baseChartTheme, {
                commonSeriesSettings: {candlestick: {innerColor: '#000000'}},
                commonAxisSettings: {
                    color: '#454545',
                    grid: {color: '#454545'},
                    tick: {color: '#454545'},
                    title: {font: {color: '#535353'}},
                    label: {font: {
                            color: '#ffffff',
                            size: 11
                        }}
                },
                commonPaneSettings: {border: {color: '#454545'}}
            }),
            pie: $.extend(true, {}, baseChartTheme),
            pieIE8: {commonSeriesSettings: {
                    pie: {
                        hoverStyle: {border: {color: '#000000'}},
                        selectionStyle: {border: {color: '#000000'}}
                    },
                    donut: {
                        hoverStyle: {border: {color: '#000000'}},
                        selectionStyle: {border: {color: '#000000'}}
                    },
                    doughnut: {
                        hoverStyle: {border: {color: '#000000'}},
                        selectionStyle: {border: {color: '#000000'}}
                    }
                }},
            gauge: {
                containerBackgroundColor: '#000000',
                title: {font: {color: '#ffffff'}},
                subtitle: {font: {color: '#ffffff'}},
                loadingIndicator: {backgroundColor: '#000000'},
                tooltip: {
                    color: '#000000',
                    font: {color: '#ffffff'}
                }
            },
            barGauge: {
                title: {font: {color: '#ffffff'}},
                subtitle: {font: {color: '#ffffff'}},
                tooltip: {
                    color: '#000000',
                    font: {color: '#ffffff'}
                },
                loadingIndicator: {backgroundColor: '#000000'}
            },
            rangeSelector: {
                containerBackgroundColor: '#000000',
                loadingIndicator: {backgroundColor: '#000000'}
            },
            map: {
                loadingIndicator: {backgroundColor: '#000000'},
                tooltip: {
                    color: '#000000',
                    font: {color: '#ffffff'}
                }
            },
            sparkline: {tooltip: {
                    color: '#000000',
                    font: {color: '#ffffff'}
                }},
            bullet: {tooltip: {
                    color: '#000000',
                    font: {color: '#ffffff'}
                }}
        }, 'desktop-dark');
        DX.viz.core.registerTheme({
            name: 'win8-white',
            chart: $.extend(true, {}, baseWhiteChartTheme, {commonAxisSettings: {
                    title: {font: {color: '#939393'}},
                    label: {font: {
                            color: '#404040',
                            size: 11
                        }}
                }}),
            pie: $.extend(true, {}, baseWhiteChartTheme),
            gauge: {
                title: {font: {color: '#808080'}},
                subtitle: {font: {color: '#808080'}},
                tooltip: {font: {color: '#808080'}}
            },
            barGauge: {
                title: {font: {color: '#808080'}},
                subtitle: {font: {color: '#808080'}},
                tooltip: {font: {color: '#808080'}}
            },
            map: {tooltip: {font: {color: '#808080'}}},
            sparkline: {tooltip: {font: {color: '#808080'}}},
            bullet: {tooltip: {font: {color: '#808080'}}}
        }, 'desktop')
    })(jQuery, DevExpress);
    /*! Module viz-core, file others.js */
    (function($, DX) {
        DX.viz.core.registerTheme({name: 'generic'}, 'desktop');
        DX.viz.core.registerTheme({name: 'generic-dark'}, 'desktop-dark');
        DX.viz.core.registerTheme({name: 'tizen'}, 'desktop');
        DX.viz.core.registerTheme({name: 'tizen-black'}, 'desktop-dark')
    })(jQuery, DevExpress);
    /*! Module viz-core, file namespaces.js */
    (function(DevExpress) {
        DevExpress.viz.renderers = {}
    })(DevExpress);
    /*! Module viz-core, file svgRenderer.js */
    (function($, DX) {
        var renderers = DX.viz.renderers,
            utils = DX.utils,
            Class = DX.Class,
            doc = document,
            MAX_PIXEL_COUNT = 10000000000;
        function createElement(name) {
            return doc.createElementNS('http://www.w3.org/2000/svg', name)
        }
        function getPatternUrl(id, pathModified) {
            return id !== null ? 'url(' + (pathModified ? window.location.href : '') + '#' + id + ')' : null
        }
        var BaseSvgElement = Class.inherit({
                ctor: function baseSvgElementCtor(renderer, name, params) {
                    this.renderer = renderer;
                    this.element = this.createElement(name);
                    this.$element = $(this.element);
                    this.applySettings($.extend({}, this.defaultSettings(), params));
                    this.__passedParams = params
                },
                defaultSettings: $.noop,
                createElement: function(nodeName) {
                    this._nodeName = nodeName;
                    return createElement(nodeName)
                },
                dispose: function() {
                    this.off();
                    this.remove();
                    this.renderer = null;
                    this.element = null;
                    this.settings = null;
                    this.$element = null;
                    this.transformation = 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
                },
                insertBefore: function(target) {
                    target.element.parentNode.insertBefore(this.element, target.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(key, value) {
                    this.$element.data(key, value);
                    return this
                },
                removeData: function() {
                    this.$element.removeData();
                    return this
                },
                off: function(events) {
                    this.$element.off(events);
                    return this
                },
                getBBox: function() {
                    var that = this,
                        bBox,
                        element = this.element,
                        transformation = that.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 that._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();
                    return this
                },
                detach: function() {
                    this.$element.detach();
                    return this
                },
                animate: function(params, options, complete) {
                    options = options || {};
                    var that = this,
                        animationParams = {};
                    if (complete)
                        $.extend(options, {complete: complete});
                    if (this.renderer.animOptions.enabled) {
                        $.each(params, function(name, to) {
                            switch (name) {
                                case'scale':
                                    animationParams['transform'] = animationParams['transform'] || {};
                                    var scale = that.transformation.scale || {};
                                    animationParams['transform'].scale = {
                                        x: {
                                            from: utils.isDefined(scale.x) ? scale.x : 1,
                                            to: utils.isDefined(to.x) ? to.x : 1
                                        },
                                        y: {
                                            from: utils.isDefined(scale.y) ? scale.y : 1,
                                            to: utils.isDefined(to.y) ? to.y : 1
                                        }
                                    };
                                    break;
                                case'rotate':
                                    animationParams['transform'] = animationParams['transform'] || {};
                                    animationParams['transform'].rotate = {
                                        angle: {
                                            from: that.transformation.rotateAngle || 0,
                                            to: to.angle
                                        },
                                        y: to.y || 0,
                                        x: to.x || 0
                                    };
                                    break;
                                case'translate':
                                    animationParams['transform'] = animationParams['transform'] || {};
                                    animationParams['transform'].translate = {
                                        x: {
                                            from: that.transformation.translateX || 0,
                                            to: to.x || 0
                                        },
                                        y: {
                                            from: that.transformation.translateY || 0,
                                            to: to.y || 0
                                        }
                                    };
                                    break;
                                case'arc':
                                case'points':
                                    animationParams[name] = to;
                                    break;
                                default:
                                    animationParams[name] = {
                                        from: that.settings[name] || 0,
                                        to: to
                                    }
                            }
                        });
                        that.renderer.animateElement(that, animationParams, $.extend({}, this.renderer.animOptions, 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(that, 1, 1);
                            options.complete && options.complete.call(that)
                        }
                        this.applySettings(params)
                    }
                },
                stopAnimation: function(disableComplete) {
                    var that = this;
                    that.animation && that.animation.stop(true, disableComplete);
                    return that
                },
                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);
                    return this
                },
                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,
                        rtl = this.renderer.rtl;
                    for (key in settings) {
                        prop = key,
                        value = settings[prop];
                        if (prop === 'align') {
                            prop = 'text-anchor';
                            value = {
                                left: rtl ? 'end' : 'start',
                                center: 'middle',
                                right: rtl ? 'start' : '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();
                            if (value === 'solid' || value === 'none')
                                value = null;
                            else {
                                value = value.replace(/longdash/g, '8,3,').replace(/dash/g, '4,3,').replace(/dot/g, '1,3,').replace(/,$/, '').split(',');
                                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 = getPatternUrl(value, this.renderer.pathModified)
                        }
                        else if (prop === 'style') {
                            this['_style'] = this['_style'] || {};
                            $.extend(true, this['_style'], value);
                            continue
                        }
                        else if (prop === 'sharpEdges')
                            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.isNumber(scale)) {
                        var value = utils.isDefined(scale) ? scale : 1;
                        transformations.push('scale(' + value + ',' + value + ')');
                        tr.scale = {
                            x: value,
                            y: value
                        }
                    }
                    else if (utils.isObject(scale)) {
                        var valueX = utils.isDefined(scale.x) ? scale.x : 1;
                        var valueY = utils.isDefined(scale.y) ? scale.y : 1;
                        transformations.push('scale(' + valueX + ',' + valueY + ')');
                        tr.scale = {
                            x: valueX,
                            y: valueY
                        }
                    }
                    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)',
                                display: 'block',
                                overflow: 'hidden'
                            },
                            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);
                    return 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;
                    return 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 (!pt)
                                    return null;
                                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
                    }
                },
                _prepareDifferrentPath: function(from, to) {
                    var end = {},
                        constsSeg;
                    if (to.length > from.length)
                        this._makeEqualPath(from, to);
                    else {
                        this.combinePathParams(end);
                        this._makeEqualPath(to, from)
                    }
                    return end.d
                },
                _prepareConstSegment: function(seg) {
                    seg[0] = "L"
                },
                _makeEqualPath: function(short, long) {
                    var constSeg = short[short.length - 1].slice();
                    this._prepareConstSegment(constSeg);
                    for (var i = short.length; i < long.length; i++)
                        short[i] = constSeg
                },
                animate: function(params, options, complete) {
                    var that = this;
                    if (!('points' in params) || !that.renderer.animOptions.enabled)
                        return that.callBase(params, options, complete);
                    var fromPath = that.segments,
                        end;
                    that.prepareSegments(params);
                    delete params.d;
                    if (fromPath.length === that.segments.length)
                        params.points = {
                            from: fromPath,
                            to: that.segments
                        };
                    else
                        end = that._prepareDifferrentPath(fromPath, that.segments);
                    params.points = {
                        from: fromPath,
                        to: that.segments,
                        end: end
                    };
                    that.callBase(params, options, complete)
                },
                sharpEdges: function() {
                    var that = this,
                        segLength = that.segments.length,
                        i = 0,
                        curSeg,
                        nextSeg,
                        curX,
                        curY,
                        nextX,
                        nextY,
                        curXIdx,
                        curYIdx,
                        nextXIdx,
                        nextYIdx,
                        strokeWidth = Math.round(that.settings.strokeWidth || 0),
                        correction = strokeWidth % 2 / 2;
                    for (i; i < segLength - 1; i++) {
                        curSeg = that.segments[i];
                        nextSeg = that.segments[i + 1];
                        if (nextSeg[0] === 'Z' && i)
                            nextSeg = that.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 that = this,
                        settings = that.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 = !!that.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 = !!that.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);
                    return this.callBase(settings)
                }
            });
        var baseAreaElement = {
                defaultSettings: function() {
                    return {points: {
                                x: 0,
                                y: 0
                            }}
                },
                ctor: function(renderer, params) {
                    this.closePath = true;
                    this.callBase(renderer, params)
                },
                _tailIndex: 0,
                _makeEqualPath: function(short, long) {
                    var i,
                        tail,
                        head,
                        constsSeg1,
                        constsSeg2,
                        newTail = [];
                    if ((short.length - 1) % 2 == 0 && (long.length - 1) % 2 == 0) {
                        i = (short.length - 1) / 2 - 1;
                        tail = short.slice(i + 1);
                        head = short.slice(0, i + 1);
                        constsSeg1 = head[head.length - 1];
                        constsSeg2 = tail[this._tailIndex];
                        this._prepareConstSegment(constsSeg1);
                        for (var j = i; j < (long.length - 1) / 2 - 1; j++) {
                            head.push(constsSeg1);
                            newTail.push(constsSeg2)
                        }
                        head = this._concatAnimationSegment(head, newTail, tail);
                        for (i = 0; i < head.length; i++)
                            short[i] = head[i]
                    }
                },
                _concatAnimationSegment: function(head, newTail, tail) {
                    return head.concat(newTail, tail)
                }
            };
        var AreaSvgElement = PathSvgElement.inherit(baseAreaElement);
        var BezierSvgElement = PathSvgElement.inherit({
                defaultSettings: function() {
                    return {points: {
                                x: 0,
                                y: 0
                            }}
                },
                _prepareConstSegment: function(seg) {
                    var x = seg[seg.length - 2],
                        y = seg[seg.length - 1];
                    seg[0] = "C";
                    seg[5] = seg[3] = seg[1] = x;
                    seg[6] = seg[4] = seg[2] = y
                },
                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(baseAreaElement).inherit({
                _concatAnimationSegment: function(head, newTail, tail) {
                    var point = tail.splice(0, 1);
                    return head.concat(point.concat(newTail), tail)
                },
                _tailIndex: 1
            });
        var ArcSvgElement = PathSvgElement.inherit({
                defaultSettings: function() {
                    return {
                            x: 0,
                            y: 0,
                            linejoin: 'round'
                        }
                },
                createArcSegments: function(x, y, innerR, outerR, startAngle, endAngle, isCircle) {
                    var longFlag = Math.floor(Math.abs(endAngle - startAngle) / Math.PI) % 2 ? '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], [isCircle ? 'M' : '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,
                        isCircle;
                    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) {
                                startAngle = 0;
                                endAngle = 360;
                                isCircle = true;
                                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, isCircle)
                        }
                    }
                    this.x = params.x;
                    this.y = params.y;
                    this.outerRadius = params.outerRadius;
                    this.innerRadius = params.innerRadius;
                    this.startAngle = params.startAngle;
                    this.endAngle = params.endAngle;
                    delete params.x;
                    delete params.y;
                    delete params.outerRadius;
                    delete params.innerRadius;
                    delete params.startAngle;
                    delete params.endAngle;
                    this.combinePathParams(params)
                },
                animate: function(params) {
                    var _this = this;
                    if ('x' in params && 'y' in params && 'outerRadius' in params && 'innerRadius' in params && 'startAngle' in params && 'endAngle' in params && this.renderer.animOptions.enabled) {
                        var settings = this.settings;
                        params.arc = {
                            from: {
                                x: this.x,
                                y: this.y,
                                outerRadius: this.outerRadius,
                                innerRadius: this.innerRadius,
                                startAngle: this.startAngle,
                                endAngle: this.endAngle
                            },
                            to: {
                                x: params.x,
                                y: params.y,
                                outerRadius: params.outerRadius,
                                innerRadius: params.innerRadius,
                                startAngle: params.startAngle,
                                endAngle: params.endAngle
                            }
                        };
                        delete params.d;
                        delete params.x;
                        delete params.y;
                        delete params.outerRadius;
                        delete params.innerRadius;
                        delete params.startAngle;
                        delete params.endAngle
                    }
                    this.callBase.apply(this, arguments)
                }
            });
        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 = (parseInt(node.style.fontSize) || node.params.fontSize) + "px";
                                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.style.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.getNextDefsSvgId(),
                        color = params.color,
                        hatching = params.hatching,
                        opacity = hatching.opacity,
                        width = hatching.width || 1,
                        step = hatching.step || 6,
                        direction = hatching.direction,
                        options = {
                            strokeWidth: width,
                            stroke: color
                        };
                    this.callBase(renderer, 'pattern', {
                        id: id,
                        width: step,
                        height: step
                    });
                    this.element.setAttribute('patternUnits', 'userSpaceOnUse');
                    this._rect = renderer.createRect(0, 0, step, step, 0, {
                        fill: color,
                        opacity: opacity
                    }).append(this);
                    this._path = renderer.createPath(0, options).append(this);
                    if (direction === 'right')
                        this._path.applySettings({d: "M " + step / 2 + " " + -step / 2 + " L " + -step / 2 + " " + step / 2 + "M 0 " + step + " L " + step + " 0 M " + step * 1.5 + " " + step / 2 + " L " + step / 2 + " " + step * 1.5});
                    else if (direction === 'left')
                        this._path.applySettings({d: "M 0 0 L " + step + ' ' + step + " M " + -step / 2 + " " + step / 2 + " L " + step / 2 + " " + step * 1.5 + " M " + step / 2 + -step / 2 + " L " + step * 1.5 + " " + step / 2});
                    this.id = getPatternUrl(id, renderer.pathModified)
                },
                append: function() {
                    return this.callBase(this.renderer.getDefsSvg())
                },
                clear: function() {
                    this.callBase();
                    this._path = null
                },
                dispose: function() {
                    this._path = 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.getNextDefsSvgId();
                    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.getDefsSvg())
                },
                updateRectangle: function(settings) {
                    this._rect.applySettings(settings)
                },
                dispose: function() {
                    this._rect = null;
                    this.callBase()
                }
            });
        var BaseFilterSvgElement = BaseSvgElement.inherit({
                ctor: function(renderer) {
                    this.applySettings = $.noop;
                    this.callBase(renderer, 'filter');
                    delete this.applySettings;
                    this.ref = null;
                    this._create()
                },
                append: function() {
                    return this.callBase(this.renderer.getDefsSvg())
                },
                dispose: function() {
                    while (this.element.firstChild)
                        this.element.removeChild(this.element.firstChild);
                    this.callBase();
                    return this
                },
                applySettings: function(settings) {
                    settings = settings || {};
                    settings.id = utils.getNextDefsSvgId();
                    this.$element.attr({
                        id: settings.id,
                        x: settings.x || null,
                        y: settings.y || null,
                        width: settings.width || null,
                        height: settings.height || null
                    });
                    this.ref = settings.id ? getPatternUrl(settings.id, this.renderer.pathModified) : null;
                    this._update(settings);
                    return this
                }
            });
        function setAttributes(element, attr) {
            $.each(attr, function(name, value) {
                element.setAttribute(name, value)
            })
        }
        var ShadowFilterSvgElement = BaseFilterSvgElement.inherit({
                _create: function() {
                    var that = this,
                        gaussianBlur = that._gaussianBlur = createElement('feGaussianBlur'),
                        offset = that._offset = createElement('feOffset'),
                        flood = that._flood = createElement('feFlood'),
                        composite = that._composite = createElement('feComposite'),
                        finalComposite = createElement('feComposite');
                    setAttributes(gaussianBlur, {
                        'in': 'SourceGraphic',
                        result: 'gaussianBlurResult'
                    });
                    setAttributes(offset, {
                        'in': 'gaussianBlurResult',
                        result: 'offsetResult'
                    });
                    setAttributes(flood, {result: 'floodResult'});
                    setAttributes(composite, {
                        'in': 'floodResult',
                        in2: 'offsetResult',
                        operator: 'in',
                        result: 'compositeResult'
                    });
                    setAttributes(finalComposite, {
                        'in': 'SourceGraphic',
                        in2: 'compositeResult',
                        operator: 'over'
                    });
                    that.element.appendChild(gaussianBlur);
                    that.element.appendChild(offset);
                    that.element.appendChild(flood);
                    that.element.appendChild(composite);
                    that.element.appendChild(finalComposite)
                },
                _update: function(settings) {
                    setAttributes(this._gaussianBlur, {stdDeviation: settings.blur || 0});
                    setAttributes(this._offset, {
                        dx: settings.dx || 0,
                        dy: settings.dy || 0
                    });
                    setAttributes(this._flood, {
                        'flood-color': settings.color,
                        'flood-opacity': settings.opacity
                    })
                }
            });
        renderers.SvgRenderer = Class.inherit({
            ctor: function(options) {
                var that = this;
                options = options || {};
                that._setAnimationOptions(options.animation || {});
                that.animationController = new renderers.AnimationController;
                that.pathModified = options.pathModified;
                that.rtl = !!options.rtl;
                that.cssClass = options.cssClass || '';
                that.recreateCanvas(options.width, options.height)
            },
            dispose: function() {
                var that = this;
                that.detachContainer();
                that.svgRoot && (that.svgRoot.remove(), that.svgRoot = null);
                that.animationController.dispose();
                that.animOptions = null;
                that.animationController = 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)
                    this.animOptions.easing = options.easing
            },
            animationEnabled: function() {
                return !!this.animOptions.enabled
            },
            updateAnimationOptions: function(newOptions) {
                this._setAnimationOptions($.extend(this.animOptions || {}, newOptions))
            },
            stopAllAnimations: function(lock) {
                lock ? this.animationController.lock() : this.animationController.stop()
            },
            detachContainer: function() {
                var that = this;
                that.svgRoot && that.svgRoot.detach();
                that.defsSvg && (that.defsSvg.remove(), that.defsSvg = null);
                that.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,
                            direction: this.rtl ? 'rtl' : 'ltr'
                        });
                        this.animationController.element = this.svgRoot.element
                    }
                    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
            },
            animateElement: function(element, params, options) {
                this.animationController.animateElement(element, params, options)
            },
            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
                    };
                return new ClipRectSvgElement(this, attr)
            },
            createPattern: function(color, hatching) {
                hatching = hatching || {};
                hatching.direction = (hatching.direction || '').toLowerCase();
                if (hatching.direction !== 'right' && hatching.direction !== 'left')
                    return {
                            id: color,
                            append: function() {
                                return this
                            },
                            clear: function(){},
                            dispose: function(){}
                        };
                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)
            },
            createSimplePath: function(options) {
                return new BaseSvgElement(this, 'path', options)
            },
            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)
            },
            createFilter: function(type) {
                var filterType = type === 'shadow' ? ShadowFilterSvgElement : null;
                if (filterType)
                    return new filterType(this);
                return null
            },
            getDefsSvg: function() {
                this.defsSvg = this.defsSvg || new BaseSvgElement(this, 'defs').append();
                return this.defsSvg
            },
            svg: function() {
                return this.svgRoot.$element.parent().html()
            }
        });
        function buildPath(points) {
            var i = 0,
                ii = points.length,
                list = [];
            for (; i < ii; )
                list.push('L', points[i++].toFixed(2), points[i++].toFixed(2));
            if (ii) {
                list[0] = 'M';
                list.push('Z');
                list = list.join(' ')
            }
            else
                list = '';
            return list
        }
        function processCircleSettings(x, y, size, borderWidth) {
            var correct = size + ~~borderWidth & 1;
            return {
                    cx: correct ? x + 0.5 : x,
                    cy: correct ? y + 0.5 : y,
                    r: size / 2
                }
        }
        renderers._svgBuildPath = buildPath;
        renderers._svgProcessCircleSettings = processCircleSettings;
        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,
            ShadowFilterSvgElement: ShadowFilterSvgElement
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file vmlRenderer.js */
    (function($, DX) {
        var renderers = DX.viz.renderers,
            utils = DX.utils,
            doc = document,
            svgRendererInternals = renderers._svgRendererInternals,
            documentFragment = doc.createDocumentFragment();
        function createVmlElement(nodeName) {
            var element = doc.createElement(nodeName);
            return documentFragment.appendChild(element)
        }
        var appendTimerID;
        var vmlElementsToAppend = [];
        var CSS_PROPERTIES = ['position', 'display', 'visibility', 'filter', 'margin', 'marginTop', 'marginLeft', 'marginRight', 'marginBottom', 'whiteSpace', 'clip', 'overflow'];
        var INHERITABLE_PROPERTIES = ['stroke', 'fill', 'opacity', 'strokeWidth', 'align', 'dashStyle'];
        var defaultVmlSettings = {
                x: 0,
                y: 0,
                width: 1,
                height: 1,
                position: 'absolute',
                behavior: 'url(#default#VML)',
                display: 'inline-block',
                xmlns: "urn:schemas-microsoft-com:vml"
            };
        var CLIP_RECT_CLASS = "dx-vml-clip-rect";
        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
            };
        function adjustOpacity(value) {
            return value >= 0.002 ? value : value === null ? 1 : 0.002
        }
        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 = adjustOpacity(value);
                if (name === 'joinStyle')
                    if (element.stroke)
                        element.stroke.joinStyle = value;
                if (name === 'opacity' || name === 'strokeOpacity')
                    if (element.stroke)
                        element.stroke.opacity = value >= 0.002 ? value : value === null ? 1 : 0.002;
                if (name === 'dashstyle')
                    if (element.stroke)
                        element.stroke.dashstyle = value
            };
        var getBoundingClientRect = function(element) {
                var i,
                    resultRect,
                    rect,
                    tagName = element.tagName.toLowerCase(),
                    points,
                    value,
                    halfStrokeWidth;
                if (element.className && element.className.indexOf(CLIP_RECT_CLASS) !== -1)
                    return;
                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._fullSettings = null;
                    this.callBase()
                },
                defaultSettings: function(customOptions) {
                    return extendDefaultVmlOptions(customOptions, this.callBase ? this.callBase() : {})
                },
                createElement: function(nodeName) {
                    this._nodeName = nodeName;
                    this.childElements = [];
                    this._fullSettings = {};
                    if (this.isVml()) {
                        var result = createVmlElement('vml:' + nodeName);
                        return result
                    }
                    else
                        return doc.createElement(nodeName)
                },
                append: function(element) {
                    var toElement = element || this.renderer.getRoot();
                    if (toElement) {
                        toElement.element.appendChild(this.element);
                        toElement.childElements.push(this);
                        if (this.parentElement)
                            this.parentElement.childElements.splice($.inArray(this, this.parentElement.childElements), 1);
                        this.parentElement = toElement
                    }
                    if (toElement === this.renderer.getRoot() || toElement._isAppended)
                        this.appendComplete();
                    return this
                },
                insertBefore: function(target) {
                    var parent = target.parentElement;
                    parent.element.insertBefore(this.element, target.element);
                    this.parentElement = parent;
                    parent.childElements.splice($.inArray(target, parent.childElements), 0, this);
                    parent._isAppended && this.appendComplete();
                    return this
                },
                remove: function() {
                    this.callBase.apply(this, arguments);
                    if (this.parentElement) {
                        this.parentElement.childElements.splice($.inArray(this, this.parentElement.childElements), 1);
                        this.parentElement = null
                    }
                    return this
                },
                detach: function() {
                    this.callBase.apply(this, arguments);
                    this._delayAttributes(['opacity']);
                    this._onDetach();
                    if (this.parentElement) {
                        this.parentElement.childElements.splice($.inArray(this, this.parentElement.childElements), 1);
                        this.parentElement = null
                    }
                    return this
                },
                clear: function() {
                    this.callBase.apply(this, arguments);
                    $.each(this.childElements, function(_, element) {
                        element._delayAttributes(['opacity']);
                        element._onDetach();
                        element.parentElement = null
                    });
                    this.childElements = [];
                    return this
                },
                applyStyle: function(style) {
                    this.callBase(style);
                    if (style.opacity)
                        this.element.style.opacity = style.opacity;
                    if (style.clip)
                        try {
                            this.element.style.clip = style.clip
                        }
                        catch(e) {}
                },
                _fillAttributesFromParentAndCurrentStyle: function(attributes) {
                    var element = this.element,
                        parent = this.parentElement,
                        i,
                        settingToStyleMap = {strokeWidth: 'stroke-width'},
                        propertyName,
                        styleName,
                        settingsToApply = {};
                    if (parent)
                        for (i = 0; i < INHERITABLE_PROPERTIES.length; i++) {
                            propertyName = INHERITABLE_PROPERTIES[i];
                            if (!this.settings[propertyName] && parent._fullSettings[propertyName])
                                settingsToApply[propertyName] = parent._fullSettings[propertyName]
                        }
                    if (element.style && element.currentStyle)
                        for (i = 0; i < INHERITABLE_PROPERTIES.length; i++) {
                            propertyName = INHERITABLE_PROPERTIES[i];
                            styleName = settingToStyleMap[propertyName] || propertyName;
                            if (element.currentStyle[styleName])
                                settingsToApply[propertyName] = element.currentStyle[styleName]
                        }
                    $.extend(this._fullSettings, this.settings, settingsToApply);
                    if (this.isVml())
                        $.extend(attributes, this._normalizeSettings(settingsToApply))
                },
                _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 (params && params['class']) {
                        this.element.className = params['class'];
                        delete params['class']
                    }
                    if (!this._isAppended)
                        this._delayedAttributes = params;
                    else {
                        params = params || this._delayedAttributes;
                        if (params) {
                            this._fillAttributesFromParentAndCurrentStyle(params);
                            if (this.isVml()) {
                                for (name in params) {
                                    value = params[name];
                                    if (name === 'opacity' || name === 'fillOpacity' || name === 'strokeOpacity' || name === 'dashstyle' || name === 'joinStyle')
                                        applySubElementAttribute(this, params, name);
                                    else
                                        this.element[name] = value
                                }
                                $.each(this.element.children, function(_, e) {
                                    e.style.behavior = 'url(#default#VML)';
                                    e.style.display = 'inline-block';
                                    e.xmlns = "urn:schemas-microsoft-com:vml"
                                })
                            }
                            this.__appliedSettings = this.isVml() ? params : {};
                            delete this._delayedAttributes
                        }
                    }
                },
                _onDetach: function() {
                    this._isAppended = false;
                    $.each(this.childElements, function(_, child) {
                        child._onDetach()
                    })
                },
                appendComplete: function() {
                    if (this.renderer.isElementAppendedToPage(this)) {
                        this._isAppended = true;
                        this._applyAttributes();
                        $.each(this.childElements, function(_, child) {
                            child.appendComplete()
                        });
                        if (this.parentElement instanceof GroupVmlElement && this.parentElement._clipRect && this.parentElement._clipRect !== this)
                            if (this.parentElement._clipRect._isAppended)
                                this.parentElement._clipRect.toForeground();
                            else
                                this.parentElement._clipRect.append(this.parentElement)
                    }
                    else {
                        vmlElementsToAppend.push(this);
                        $(this.element).data('vmlNeedAppendComplete', true);
                        if (appendTimerID === undefined)
                            appendTimerID = setTimeout(function() {
                                appendTimerID = undefined;
                                var vmlElements = vmlElementsToAppend;
                                vmlElementsToAppend = [];
                                $.each(vmlElements, function() {
                                    if ($(this.element).data('vmlNeedAppendComplete') && !this._isAppended)
                                        this.appendComplete()
                                })
                            }, 200)
                    }
                },
                _delayAttributes: function(attributes) {
                    var attr,
                        val,
                        i,
                        settings = this.settings || {};
                    attributes = attributes || [];
                    this._delayedAttributes = this._delayedAttributes || {};
                    for (i = 0; i < attributes.length; i++) {
                        attr = attributes[i];
                        val = settings[attr];
                        if (val)
                            this._delayedAttributes[attr] = val
                    }
                    $.each(this.childElements || [], function(_, child) {
                        child._delayAttributes(attributes)
                    })
                },
                _normalizeSettings: function(settings) {
                    var key,
                        style = {},
                        normalized = {},
                        clipRect,
                        pos,
                        prop,
                        value;
                    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 === "behavior")
                            style[prop] = value;
                        else if (prop === 'height')
                            style.height = value + 'px';
                        else if (prop === 'align')
                            continue;
                        else if (prop === 'scale')
                            continue;
                        else if ($.inArray(prop, CSS_PROPERTIES) != -1)
                            style[prop] = value !== null ? value : '';
                        else if (prop === 'font') {
                            if (!$.isPlainObject(value))
                                continue;
                            $.each(value, function(fontSetting) {
                                var styleName,
                                    firstChar;
                                switch (fontSetting) {
                                    case'color':
                                        styleName = "fill";
                                        break;
                                    case'opacity':
                                        styleName = "opacity";
                                        break;
                                    case'cursor':
                                        styleName = fontSetting;
                                        break;
                                    default:
                                        firstChar = fontSetting.charAt(0);
                                        styleName = 'font' + fontSetting.replace(firstChar, firstChar.toUpperCase())
                                }
                                if (styleName)
                                    style[styleName] = value[fontSetting]
                            })
                        }
                        else if (prop === 'style')
                            $.extend(true, style, value);
                        else if (prop === 'rotate')
                            this['_rotate'] = 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,
                                    canvasSize = this.renderer._getSize();
                                style.width = canvasSize.width;
                                style.height = canvasSize.height;
                                style.clip = "rect(" + y + "px, " + clipWidth + "px, " + clipHeight + "px, " + x + "px)"
                            }
                        }
                        else if (prop === 'segments')
                            continue;
                        else if (prop === 'fill') {
                            normalized.filled = value === 'none' ? 'f' : 't';
                            normalized.fillcolor = value === 'grey' ? '#808080' : value
                        }
                        else if (prop === 'opacity')
                            normalized.opacity = value < 0.002 ? value : 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 === 'dashStyle') {
                            value = value.toLowerCase();
                            normalized.dashstyle = value
                        }
                        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) || 0);
                            y = y - (parseInt(element.style.top, 10) || 0)
                        }
                    }
                    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'})
                },
                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',
                            stroke: 'none',
                            strokeWidth: 0,
                            fill: 'none'
                        }
                },
                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,
                            fill: 'none',
                            stroke: 'none'
                        })
                },
                adjustSettings: function() {
                    var defaultSettings = this.defaultSettings();
                    this.callBase();
                    if (this.settings.href) {
                        this.settings.src = this.settings.href;
                        delete this.settings.href
                    }
                    this.settings.fill = defaultSettings.fill;
                    this.settings.stroke = defaultSettings.stroke;
                    this.settings.strokeWidth = defaultSettings.strokeWidth
                }
            });
        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 that = this,
                        rotate = settings.rotate,
                        rotateAngle,
                        rotateX,
                        rotateY,
                        oldSegments,
                        radianAngle,
                        cos,
                        sin,
                        x,
                        y,
                        rotatedX,
                        rotatedY,
                        rotateObject;
                    this.callBase(settings);
                    oldSegments = that.segments;
                    rotateObject = parseRotateParameter(rotate, settings.x, settings.y);
                    if (rotateObject) {
                        rotateAngle = rotateObject.angle;
                        rotateX = rotateObject.x;
                        rotateY = rotateObject.y;
                        if (that.segments) {
                            radianAngle = rotateAngle * Math.PI / 180.0;
                            cos = Math.cos(radianAngle);
                            sin = Math.sin(radianAngle);
                            that.segments = $.map(that.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]
                            });
                            that.combinePathParams(settings);
                            that.segments = oldSegments
                        }
                    }
                }});
        var SimplePathVmlElement = svgRendererInternals.BaseSvgElement.inherit(BaseVmlElement).inherit({
                ctor: function(renderer, options) {
                    this.callBase(renderer, 'shape', options)
                },
                defaultSettings: function() {
                    return extendDefaultVmlOptions({coordsize: '1,1'})
                },
                adjustSettings: function() {
                    var settings = this.settings;
                    if (settings.d !== undefined) {
                        settings.path = settings.d;
                        delete settings.d
                    }
                }
            });
        var AreaVmlElement = PathVmlElement.inherit({
                defaultSettings: function() {
                    var baseOptions = this.callBase();
                    return extendDefaultVmlOptions({points: {
                                x: 0,
                                y: 0
                            }}, 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;
                    return this
                }
            });
        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
                            }}, 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, isCircle) {
                    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], [isCircle ? 'wr' : '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,
                        settings = this.settings;
                    if (settings.font) {
                        settings.fill = settings.fill || settings.font.color;
                        settings.opacity = settings.opacity || settings.font.opacity
                    }
                    if ('text' in settings) {
                        text = utils.isDefined(settings.text) ? settings.text : '';
                        text = text.toString().replace(/\r/g, "");
                        text = text.replace(/\n/g, "<br/>");
                        $(this.element).html(text);
                        delete settings.text
                    }
                    if (this.renderer.rtl)
                        $(this.element).css('direction', 'rtl')
                },
                updateText: function(text) {
                    this.applySettings({text: utils.isDefined(text) ? text : ''})
                },
                _applyAttributes: function(settings) {
                    this.callBase(settings);
                    settings = this._fullSettings;
                    var rotate = settings.rotate,
                        rotateAngle = 0,
                        rotateX,
                        rotateY,
                        cos = 1,
                        sin = 0,
                        osin = 0,
                        ocos = 1,
                        angle,
                        otg,
                        rad,
                        y = settings.y + (settings.translateY || 0),
                        x = settings.x + (settings.translateX || 0),
                        align = 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
                        }
                        if (rotateAngle && this.renderer.rtl)
                            marginLeft -= textWidth - (textHeight * Math.abs(sin) + textWidth * Math.abs(cos));
                        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)
                },
                adjustSettings: function() {
                    if (this.settings.clipId || this._clipRect) {
                        var rect = this.renderer.getClipRect(this.settings.clipId, this);
                        if (this._clipRect)
                            if (rect)
                                this._clipRect.applySettings({
                                    x: rect.x,
                                    y: rect.y,
                                    width: rect.width,
                                    height: rect.height
                                });
                            else {
                                this._clipRect.remove();
                                this._clipRect = null
                            }
                        else
                            this._clipRect = this.renderer.createRect(rect.x, rect.y, rect.width, rect.height, 0, {
                                fill: "none",
                                opacity: 0.002,
                                "class": CLIP_RECT_CLASS
                            });
                        if (this._clipRect)
                            this.childElements.length && this._clipRect.append(this)
                    }
                },
                applySettings: function(settings) {
                    var 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;
                    delete settings.x;
                    delete settings.y;
                    this.callBase(settings);
                    $.each(this.childElements || [], function(_, c) {
                        c.applySettings({})
                    });
                    return this
                },
                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 (doc.namespaces && !doc.namespaces.vml) {
                    doc.namespaces.add('vml', 'urn:schemas-microsoft-com:vml');
                    var cssText = 'vml\\:fill, vml\\:path, vml\\:shape, vml\\:stroke, vml\\:rect, vml\\:oval' + '{ behavior:url(#default#VML); display: inline-block; };';
                    try {
                        doc.createStyleSheet().cssText = cssText
                    }
                    catch(e) {
                        doc.styleSheets[0].cssText += cssText
                    }
                }
                this._clipRects = {};
                this.cssClass = options.cssClass || '';
                this.callBase(options)
            },
            dispose: function() {
                this.callBase();
                this._clipRects = null;
                this._size = null
            },
            updateAnimationOptions: $.noop,
            draw: function(container) {
                var root = this.getRoot();
                this.callBase(container);
                if (root)
                    root.appendComplete()
            },
            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 || {}
            },
            isElementAppendedToPage: function(element) {
                return $(element.element).closest(doc.documentElement).length
            },
            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.getNextDefsSvgId(),
                    elements = [],
                    clipRect = {
                        id: clipId,
                        x: x,
                        y: y,
                        width: width,
                        height: height,
                        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 && !options.inh ? 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 && !options.inh ? options : {}, {points: [x1, y1, x2, y2]});
                return new PathVmlElement(this, params)
            },
            createPath: function(points, options) {
                var params = $.extend(true, {}, options && !options.inh ? options : {}, {points: points});
                return new PathVmlElement(this, params)
            },
            createSimplePath: function(options) {
                return new SimplePathVmlElement(this, options)
            },
            createBezierPath: function(points, options) {
                var params = $.extend(true, {}, options && !options.inh ? options : {}, {points: points});
                return new BezierVmlElement(this, params)
            },
            createArea: function(points, options) {
                var params = $.extend(true, {}, options && !options.inh ? options : {}, {points: points});
                return new AreaVmlElement(this, params)
            },
            createBezierArea: function(points, options) {
                var params = $.extend(true, {}, options && !options.inh ? options : {}, {points: points});
                return new BezierAreaVmlElement(this, params)
            },
            createCircle: function(x, y, r, options) {
                var params = $.extend(true, {}, options && !options.inh ? 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 && !options.inh ? 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 && !options.inh ? options : {}, {
                        x: x,
                        y: y,
                        text: text
                    });
                return new TextVmlElement(this, params)
            },
            createGroup: function(options) {
                return new GroupVmlElement(this, options)
            },
            createPattern: function(color, hatching) {
                return {
                        id: color,
                        append: function() {
                            return this
                        },
                        clear: function(){},
                        dispose: function(){}
                    }
            },
            createFilter: function(type) {
                if (type === 'shadow')
                    return {
                            ref: null,
                            append: function() {
                                return this
                            },
                            dispose: function() {
                                return this
                            },
                            applySettings: function() {
                                return this
                            }
                        };
                return null
            },
            svg: function() {
                return ''
            }
        });
        function buildPath(points) {
            var i = 0,
                ii = points.length,
                list = [];
            for (; i < ii; )
                list.push('l', points[i++].toFixed(0), points[i++].toFixed(0));
            if (ii) {
                list[0] = 'm';
                list.push('x e');
                list = list.join(' ')
            }
            else
                list = '';
            return list
        }
        function processCircleSettings(x, y, size) {
            return {
                    cx: x,
                    cy: y,
                    r: size / 2
                }
        }
        renderers._vmlBuildPath = buildPath;
        renderers._vmlProcessCircleSettings = processCircleSettings;
        renderers.__vmlRendererInternals = {
            RootVmlElement: RootVmlElement,
            RectVmlElement: RectVmlElement,
            ImageVmlElement: ImageVmlElement,
            PathVmlElement: PathVmlElement,
            AreaVmlElement: AreaVmlElement,
            BezierVmlElement: BezierVmlElement,
            BezierAreaVmlElement: BezierAreaVmlElement,
            SimplePathVmlElement: SimplePathVmlElement,
            CircleVmlElement: CircleVmlElement,
            TextVmlElement: TextVmlElement,
            GroupVmlElement: GroupVmlElement,
            ArcVmlElement: ArcVmlElement,
            SegmentRectVmlElement: SegmentRectVmlElement
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file renderer.js */
    (function($, DX) {
        var renderers = DX.viz.renderers,
            browser = DX.browser;
        function isSvg() {
            return !(browser.msie && browser.version < 9) || !!document.createElementNS && !!document.createElementNS('http://www.w3.org/2000/svg', "svg").createSVGRect
        }
        if (!isSvg()) {
            renderers.Renderer = renderers.VmlRenderer;
            renderers.buildPath = renderers._vmlBuildPath;
            renderers.processCircleSettings = renderers._vmlProcessCircleSettings
        }
        else {
            renderers.Renderer = renderers.SvgRenderer;
            renderers.buildPath = renderers._svgBuildPath;
            renderers.processCircleSettings = renderers._svgProcessCircleSettings
        }
        renderers.isSvg = isSvg
    })(jQuery, DevExpress);
    /*! Module viz-core, file animation.js */
    (function(DX) {
        var renderers = DX.viz.renderers,
            Class = DX.Class,
            noop = function(){},
            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
                }
            };
        renderers.easingFunctions = easingFunctions;
        renderers.animationSvgStep = {
            points: function(elem, params, progress, easing, currentParams) {
                var from = params.from,
                    to = params.to,
                    path = [],
                    i,
                    j,
                    seg,
                    d;
                for (i = 0; i < from.length; i++) {
                    seg = [from[i][0]];
                    if (from[i].length > 1)
                        for (j = 1; j < from[i].length; j++)
                            seg.push(easing(progress, from[i][j], to[i][j]));
                    path[i] = seg.join(' ')
                }
                d = path.join(' ');
                currentParams.d = params.end && progress === 1 ? params.end : d;
                elem.element.setAttribute('d', d)
            },
            arc: function(elem, params, progress, easing) {
                var from = params.from,
                    to = params.to,
                    current = {};
                for (var i in from)
                    current[i] = easing(progress, from[i], to[i]);
                elem.applySettings(current)
            },
            transform: function(elem, params, progress, easing, currentParams) {
                var translate = params.translate,
                    rotate = params.rotate,
                    scale = params.scale,
                    transformations = [],
                    elemSettings = elem.settings;
                if (translate) {
                    currentParams.translateX = easing(progress, translate.x.from, translate.x.to);
                    currentParams.translateY = easing(progress, translate.y.from, translate.y.to);
                    transformations.push('translate(' + currentParams.translateX + ',' + currentParams.translateY + ')')
                }
                else if (elemSettings.translateX || elemSettings.translateY)
                    transformations.push('translate(' + (elemSettings.translateX || 0) + ',' + (elemSettings.translateY || 0) + ')');
                if (rotate) {
                    currentParams.rotate = {
                        angle: easing(progress, rotate.angle.from, rotate.angle.to),
                        x: rotate.x,
                        y: rotate.y
                    };
                    transformations.push('rotate(' + currentParams.rotate.angle + ',' + rotate.x + ',' + rotate.y + ')')
                }
                else if (elemSettings.rotate)
                    transformations.push('rotate(' + elemSettings.rotate.angle + ',' + (elemSettings.rotate.x || 0) + ',' + (elemSettings.rotate.y || 0) + ')');
                if (scale) {
                    currentParams.scale = {
                        x: easing(progress, scale.x.from, scale.x.to),
                        y: easing(progress, scale.y.from, scale.y.to)
                    };
                    transformations.push('scale(' + currentParams.scale.x + ',' + currentParams.scale.y + ')')
                }
                else if (elemSettings.scale)
                    transformations.push('scale(' + elemSettings.scale.x + ',' + elemSettings.scale.y + ')');
                elem.element.setAttribute('transform', transformations.join())
            },
            base: function(elem, params, progress, easing, currentParams, attributeName) {
                currentParams[attributeName] = easing(progress, params.from, params.to);
                elem.element.setAttribute(attributeName, currentParams[attributeName])
            },
            _: noop,
            complete: function(element, currentSettings) {
                element.applySettings(currentSettings)
            }
        };
        var Animation = Class.inherit({
                ctor: function(element, params, options) {
                    var that = this;
                    that._progress = 0;
                    that.element = element;
                    that.params = params;
                    that.options = options;
                    that.duration = options.partitionDuration ? options.duration * options.partitionDuration : options.duration;
                    that._animateStep = options.animateStep || renderers.animationSvgStep;
                    that._easing = easingFunctions[options.easing] || easingFunctions['easeOutCubic'];
                    that._currentParams = {};
                    that.tick = that._start
                },
                _calcProgress: function(now) {
                    return Math.min(1, (now - this._startTime) / this.duration)
                },
                _step: function(now) {
                    var that = this,
                        animateStep = that._animateStep,
                        attrName;
                    that._progress = that._calcProgress(now);
                    for (attrName in that.params) {
                        if (!that.params.hasOwnProperty(attrName))
                            continue;
                        var anim = animateStep[attrName] || animateStep.base;
                        anim(that.element, that.params[attrName], that._progress, that._easing, that._currentParams, attrName)
                    }
                    that.options.step && that.options.step(that._easing(that._progress, 0, 1), that._progress);
                    if (that._progress === 1)
                        return that.stop();
                    return true
                },
                _start: function(now) {
                    this._startTime = now;
                    this.tick = this._step;
                    return true
                },
                _end: function(disableComplete) {
                    var that = this;
                    that.stop = noop;
                    that.tick = noop;
                    that._animateStep.complete && that._animateStep.complete(that.element, that._currentParams);
                    that.options.complete && !disableComplete && that.options.complete()
                },
                tick: function(now) {
                    return true
                },
                stop: function(breakAnimation, disableComplete) {
                    var options = this.options;
                    if (!breakAnimation && options.repeatCount && --options.repeatCount > 0) {
                        this.tick = this._start;
                        return true
                    }
                    else
                        this._end(disableComplete)
                }
            });
        renderers.AnimationController = Class.inherit(function() {
            var FPS = 1000 / 60,
                requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) {
                    setTimeout(callback, FPS)
                };
            return {
                    ctor: function() {
                        var that = this;
                        that.requestAnimationFrame = requestAnimationFrame;
                        that._animationCount = 0;
                        that._timerId = null;
                        that._animations = {}
                    },
                    _loop: function() {
                        var that = this,
                            animations = that._animations,
                            activeAnimation = 0,
                            now = (new Date).getTime(),
                            an;
                        for (an in animations) {
                            if (!animations.hasOwnProperty(an))
                                continue;
                            if (!animations[an].tick(now))
                                delete animations[an];
                            activeAnimation++
                        }
                        if (activeAnimation === 0) {
                            that.stop();
                            return
                        }
                        that._timerId = that.requestAnimationFrame.call(null, function() {
                            that._loop()
                        }, that.element)
                    },
                    addAnimation: function(animation) {
                        var that = this;
                        that._animations[that._animationCount++] = animation;
                        if (!that._timerId) {
                            clearTimeout(that._startDelay);
                            that._startDelay = setTimeout(function() {
                                that._timerId = 1;
                                that._loop()
                            }, 0)
                        }
                    },
                    animateElement: function(elem, params, options) {
                        if (elem && params && options) {
                            elem.animation && elem.animation.stop(true);
                            this.addAnimation(elem.animation = new Animation(elem, params, options))
                        }
                    },
                    dispose: function() {
                        this.stop();
                        this.element = null
                    },
                    stop: function() {
                        this._animations = {};
                        this._animationCount = 0;
                        clearTimeout(this._startDelay);
                        this._timerId = null
                    },
                    lock: function() {
                        var animations = this._animations;
                        for (var an in animations)
                            animations.hasOwnProperty(an) && animations[an].stop(true, true);
                        this.stop()
                    }
                }
        }());
        renderers.Animation = Animation;
        renderers.noop = noop
    })(DevExpress);
    /*! Module viz-core, file namespaces.js */
    (function(DevExpress) {
        DevExpress.viz.charts = {series: {}}
    })(DevExpress);
    /*! Module viz-core, file chartsConsts.js */
    (function(DX) {
        DX.viz.charts.consts = {
            dataTypes: {
                STRING: 'string',
                NUMERIC: 'numeric',
                DATETIME: 'datetime'
            },
            axisTypes: {
                DISCRETE: 'discrete',
                CONTINUOUS: 'continuous',
                LOGARITHMIC: 'logarithmic'
            }
        }
    })(DevExpress);
    /*! Module viz-core, file dataValidator.js */
    (function($, DX) {
        var viz = DX.viz,
            parseUtils = new viz.core.ParseUtils,
            chartConst = viz.charts.consts,
            dataTypes = chartConst.dataTypes,
            axisTypes = chartConst.axisTypes,
            utils = DX.utils,
            _each = $.each,
            _isDefined = utils.isDefined;
        var mergeSort = function(data, field) {
                function merge_sort(array, low, high, field) {
                    if (low < high) {
                        var mid = Math.floor((low + high) / 2);
                        merge_sort(array, low, mid, field);
                        merge_sort(array, mid + 1, high, field);
                        merge(array, low, mid, high, field)
                    }
                }
                var n = data.length;
                merge_sort(data, 0, n - 1, field);
                return data
            };
        var merge = function(array, low, mid, high, field) {
                var newArray = new Array(high - low + 1),
                    countL = low,
                    countR = mid + 1,
                    k,
                    i = 0;
                while (countL <= mid && countR <= high) {
                    if (array[countL][field] <= array[countR][field] || !_isDefined(array[countR][field])) {
                        newArray[i] = array[countL];
                        countL++
                    }
                    else {
                        newArray[i] = array[countR];
                        countR++
                    }
                    i++
                }
                if (countL > mid)
                    for (k = countR; k <= high; k++, i++)
                        newArray[i] = array[k];
                else
                    for (k = countL; k <= mid; k++, i++)
                        newArray[i] = array[k];
                for (k = 0; k <= high - low; k++)
                    array[k + low] = newArray[k];
                return array
            };
        viz.charts.DataValidator = DX.Class.inherit({
            ctor: function(data, groups, incidentOccured, dataPrepareOptions) {
                var that = this;
                groups = groups || [[]];
                if (!data)
                    that._nullData = true;
                that.groups = groups;
                that.data = data || [];
                that._parsers = {};
                that._errorShowList = {};
                that._skipFields = {};
                that.options = dataPrepareOptions || {};
                that.incidentOccured = incidentOccured;
                that.userArgumentCategories = that.groups.length && that.groups[0].length && that.groups[0][0].getArgumentCategories();
                if (!incidentOccured)
                    that.incidentOccured = $.noop
            },
            validate: function validate() {
                var that = this;
                that._data = that.data;
                if (!utils.isArray(that.data) || that._nullData)
                    that._incorrectDataMessage();
                that.groups.argumentType = null;
                that.groups.argumentAxisType = null;
                $.each(that.groups, function(_, group) {
                    group.valueType = null;
                    group.valueAxisType = null;
                    $.each(group, function(_, series) {
                        series.updateDataType({})
                    })
                });
                that._checkType();
                that._checkAxisType();
                if (that.options.convertToAxisDataType) {
                    that._createParser();
                    that._parse()
                }
                that._groupData();
                that._sort();
                $.each(that._skipFields, function(field, fieldValue) {
                    if (fieldValue === that._data.length)
                        that.incidentOccured("W2002", [field])
                });
                return that._data
            },
            _checkType: function _checkType() {
                var that = this,
                    groupsWithUndefinedValueType = [],
                    groupsWithUndefinedArgumentType = [],
                    checkValueTypeOfGroup = function checkValueTypeOfGroup(group, cell) {
                        $.each(group, function(_, series) {
                            $.each(series.getValueFields(), function(_, field) {
                                group.valueType = that._getType(cell[field], group.valueType)
                            })
                        });
                        if (group.valueType)
                            return true
                    },
                    checkArgumentTypeOfGroup = function checkArgumentTypeOfGroup(group, cell) {
                        $.each(group, function(_, series) {
                            that.groups.argumentType = that._getType(cell[series.getArgumentField()], that.groups.argumentType)
                        });
                        if (that.groups.argumentType)
                            return true
                    };
                $.each(that.groups, function(_, group) {
                    if (!group.length)
                        return null;
                    var options = group[0].getOptions(),
                        valueTypeGroup = options.valueType,
                        argumentTypeGroup = options.argumentType;
                    group.valueType = valueTypeGroup;
                    that.groups.argumentType = argumentTypeGroup;
                    valueTypeGroup ? null : groupsWithUndefinedValueType.push(group);
                    argumentTypeGroup ? null : groupsWithUndefinedArgumentType.push(group)
                });
                if (groupsWithUndefinedValueType.length || groupsWithUndefinedArgumentType.length)
                    $.each(that.data, function(_, cell) {
                        var define = true;
                        if (!utils.isObject(cell))
                            return;
                        $.each(groupsWithUndefinedValueType, function(index, group) {
                            define = define && checkValueTypeOfGroup(group, cell)
                        });
                        $.each(groupsWithUndefinedArgumentType, function(index, group) {
                            define = define && checkArgumentTypeOfGroup(group, cell)
                        });
                        if (!that.options.checkTypeForAllData && define)
                            return false
                    })
            },
            _checkAxisType: function _checkAxisType() {
                var that = this;
                $.each(that.groups, function(_, group) {
                    $.each(group, function(_, series) {
                        var optionsSeries = {},
                            existingSeriesOptions = series.getOptions();
                        optionsSeries.argumentAxisType = that._correctAxisType(that.groups.argumentType, existingSeriesOptions.argumentAxisType, !!that.userArgumentCategories.length);
                        optionsSeries.valueAxisType = that._correctAxisType(group.valueType, existingSeriesOptions.valueAxisType, !!series.getValueCategories().length);
                        that.groups.argumentAxisType = that.groups.argumentAxisType || optionsSeries.argumentAxisType;
                        group.valueAxisType = group.valueAxisType || optionsSeries.valueAxisType;
                        optionsSeries.argumentType = that.groups.argumentType;
                        optionsSeries.valueType = group.valueType;
                        series.updateDataType(optionsSeries)
                    })
                })
            },
            _createParser: function _createParser() {
                var that = this;
                $.each(that.groups, function(index, group) {
                    $.each(group, function(_, series) {
                        that._parsers[series.getArgumentField()] = that._createParserUnit(that.groups.argumentType, that.groups.argumentAxisType === axisTypes.LOGARITHMIC ? that._filterForLogAxis : null);
                        $.each(series.getValueFields(), function(_, field) {
                            that._parsers[field] = that._createParserUnit(group.valueType, group.valueAxisType === axisTypes.LOGARITHMIC ? that._filterForLogAxis : null, series.getOptions().ignoreEmptyPoints)
                        });
                        if (series.getTagField())
                            that._parsers[series.getTagField()] = null
                    })
                })
            },
            _parse: function _parse() {
                var that = this,
                    parsedData = [];
                $.each(that.data, function(_, cell) {
                    var parserObject = {};
                    if (!utils.isObject(cell)) {
                        cell && that._incorrectDataMessage();
                        return
                    }
                    $.each(that._parsers, function(field, parser) {
                        parserObject[field] = parser ? parser(cell[field], field) : cell[field];
                        parserObject['original' + field] = cell[field]
                    });
                    parsedData.push(parserObject)
                });
                this._data = parsedData
            },
            _groupMinSlices: function(argumentField, valueField, smallValuesGrouping) {
                var that = this,
                    smallValuesGrouping = smallValuesGrouping || {},
                    mode = smallValuesGrouping.mode,
                    count = smallValuesGrouping.topCount,
                    threshold = smallValuesGrouping.threshold,
                    name = smallValuesGrouping.groupName || 'others',
                    others = {},
                    data = that._data.slice(),
                    index;
                var groupingValues = function(index) {
                        if (!_isDefined(index) || index < 0)
                            return;
                        _each(data.slice(index), function(_, cell) {
                            if (!_isDefined(cell[valueField]))
                                return;
                            others[valueField] += cell[valueField];
                            cell[valueField] = undefined;
                            cell['original' + valueField] = undefined
                        })
                    };
                if (!mode || mode === 'none')
                    return;
                others[argumentField] = name + '';
                others[valueField] = 0;
                data.sort(function(a, b) {
                    if (_isDefined(b[valueField]) && _isDefined(a[valueField]))
                        return b[valueField] - a[valueField];
                    else if (!_isDefined(b[valueField]) && a[valueField])
                        return -1;
                    else if (!_isDefined(a[valueField]) && b[valueField])
                        return 1
                });
                if (mode === 'smallValueThreshold') {
                    _each(data, function(i, cell) {
                        if (_isDefined(index) || !_isDefined(cell[valueField]))
                            return;
                        if (threshold > cell[valueField])
                            index = i
                    });
                    groupingValues(index)
                }
                else if (mode === 'topN')
                    groupingValues(count);
                others[valueField] && that._data.push(others)
            },
            _groupData: function() {
                var that = this,
                    groups = that.groups,
                    isPie = groups.length && groups[0].length && (groups[0][0].type === 'pie' || groups[0][0].type === 'doughnut' || groups[0][0].type === 'donut'),
                    argumentField,
                    valueFields;
                if (!isPie)
                    return;
                _each(groups, function(_, group) {
                    _each(group, function(_, series) {
                        argumentField = series.getArgumentField();
                        valueFields = series.getValueFields();
                        if (groups.argumentAxisType === axisTypes.DISCRETE)
                            that._groupSameArguments(argumentField, valueFields);
                        that._groupMinSlices(argumentField, valueFields[0], series.getOptions().smallValuesGrouping)
                    })
                })
            },
            _groupSameArguments: function(argumentField, valueFields) {
                var that = this,
                    argument,
                    dataOfArguments = {},
                    parsedData = that._data;
                _each(parsedData, function(i, cell) {
                    if (!_isDefined(cell[argumentField]) || !_isDefined(cell[valueFields[0]]))
                        return;
                    argument = cell[argumentField];
                    if (_isDefined(dataOfArguments[argument])) {
                        var data = parsedData[dataOfArguments[argument]];
                        _each(valueFields, function(_, field) {
                            data[field] += cell[field];
                            cell[field] = undefined;
                            cell['original' + field] = undefined
                        })
                    }
                    else
                        dataOfArguments[argument] = i
                })
            },
            _getType: function _getType(unit, type) {
                if (type === dataTypes.STRING || utils.isString(unit))
                    return dataTypes.STRING;
                if (type === dataTypes.DATETIME || utils.isDate(unit))
                    return dataTypes.DATETIME;
                if (utils.isNumber(unit))
                    return dataTypes.NUMERIC;
                return type
            },
            _correctAxisType: function _correctAxisType(type, axisType, hasCategories) {
                if (type === dataTypes.STRING && (axisType === axisTypes.CONTINUOUS || axisType === axisTypes.LOGARITHMIC))
                    this.incidentOccured("E2002");
                if (axisType === axisTypes.LOGARITHMIC)
                    return axisTypes.LOGARITHMIC;
                axisType = (hasCategories || axisType === axisTypes.DISCRETE || type === dataTypes.STRING) && axisTypes.DISCRETE;
                return axisType || axisTypes.CONTINUOUS
            },
            _filterForLogAxis: function(val, field) {
                if (val <= 0) {
                    this.incidentOccured("E2004", [field]);
                    return null
                }
                return val
            },
            _createParserUnit: function _createParserUnit(type, filter, ignoreEmptyPoints) {
                var that = this,
                    parser = type ? parseUtils.getParser(type, undefined, true) : function(unit) {
                        return unit
                    };
                return function(unit, field) {
                        var parseUnit = parser(unit);
                        if (filter)
                            parseUnit = filter.call(that, parseUnit, field);
                        parseUnit === null && ignoreEmptyPoints && (parseUnit = undefined);
                        if (parseUnit === undefined) {
                            that._addSkipFields(field);
                            that._validUnit(unit, field, type)
                        }
                        return parseUnit
                    }
            },
            _validUnit: function _validUnit(unit, field, type) {
                if (!unit)
                    return;
                if (!utils.isNumber(unit) && !utils.isDate(unit) && !utils.isString(unit)) {
                    this.incidentOccured("E2003", [field]);
                    return
                }
                this.incidentOccured("E2004", [field])
            },
            _sort: function _sort() {
                var that = this,
                    groups = that.groups,
                    hash = {},
                    argumentField = groups.length && groups[0].length && groups[0][0].getArgumentField();
                if (utils.isFunction(that.options.sortingMethod))
                    that._data.sort(that.options.sortingMethod);
                else if (that.userArgumentCategories.length) {
                    $.each(that.userArgumentCategories, function(index, value) {
                        hash[value] = index
                    });
                    that._data.sort(function sortCat(a, b) {
                        a = a[argumentField];
                        b = b[argumentField];
                        return hash[a] - hash[b]
                    })
                }
                else if (that.options.sortingMethod === true && groups.argumentType !== dataTypes.STRING)
                    mergeSort(that._data, argumentField)
            },
            _addSkipFields: function _addSkipFields(field) {
                this._skipFields[field] = (this._skipFields[field] || 0) + 1
            },
            _incorrectDataMessage: function() {
                if (this._erorrDataSource !== true) {
                    this._erorrDataSource = true;
                    this.incidentOccured("E2001")
                }
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file themeManager.js */
    (function($, DX, undefined) {
        var viz = DX.viz,
            Palette = viz.core.Palette,
            utils = DX.utils;
        var HOVER_COLOR_HIGHLIGHTING = 20,
            HIGHLIGHTING_STEP = 50;
        viz.charts.ThemeManager = viz.core.BaseThemeManager.inherit(function() {
            var ctor = function(options, themeGroupName) {
                    var that = this;
                    options = options || {};
                    that._userOptions = options;
                    that._mergeAxisTitleOptions = [];
                    themeGroupName && (that._themeSection = themeGroupName);
                    that._IE8 = DX.browser.msie && DX.browser.version < 9;
                    that.setTheme(options.theme);
                    that.palette = new Palette(options.palette, {
                        stepHighlight: HIGHLIGHTING_STEP,
                        theme: that._themeName
                    })
                };
            var dispose = function() {
                    var that = this;
                    that.palette.dispose();
                    that.palette = that._userOptions = that._mergedSettings = null;
                    that.callBase()
                };
            var initDefaultSeriesTheme = function(that) {
                    var commonSeriesSettings = that._theme.commonSeriesSettings;
                    commonSeriesSettings.point = commonSeriesSettings.point || {};
                    commonSeriesSettings.label = commonSeriesSettings.label || {};
                    that._initializeFont(commonSeriesSettings.label.font)
                };
            var initAxisTheme = function(that) {
                    var axisTheme = that._theme.commonAxisSettings;
                    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 || {};
                        that._initializeFont(axisTheme.label.font);
                        axisTheme.title.font = axisTheme.title.font || {};
                        that._initializeFont(axisTheme.title.font)
                    }
                };
            var resetPalette = function() {
                    this.palette.reset()
                };
            var updatePalette = function(palette) {
                    this.palette = new Palette(palette || this._theme.defaultPalette, {
                        stepHighlight: HIGHLIGHTING_STEP,
                        theme: this.themeName
                    })
                };
            var processTitleOptions = function(options) {
                    return utils.isString(options) ? {text: options} : options
                };
            var processAxisOptions = function(axisOptions, name) {
                    if (!axisOptions)
                        return;
                    axisOptions = $.extend(true, {}, axisOptions);
                    axisOptions.title = processTitleOptions(axisOptions.title);
                    if (axisOptions.type === 'logarithmic' && axisOptions.logarithmBase <= 0 || axisOptions.logarithmBase && !$.isNumeric(axisOptions.logarithmBase)) {
                        axisOptions.logarithmBase = undefined;
                        axisOptions.logarithmBaseError = true
                    }
                    if (axisOptions.label) {
                        if (axisOptions.label.alignment)
                            axisOptions.label['userAlignment'] = true;
                        if (!axisOptions.label.overlappingBehavior) {
                            if (axisOptions.label.staggered)
                                axisOptions.label.overlappingBehavior = {
                                    mode: 'stagger',
                                    staggeringSpacing: axisOptions.label.staggeringSpacing
                                };
                            if (axisOptions.label.rotationAngle)
                                axisOptions.label.overlappingBehavior = {
                                    mode: 'rotate',
                                    rotationAngle: axisOptions.label.rotationAngle
                                }
                        }
                        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 || {}
                    }
                    return axisOptions
                };
            var applyParticularAxisOptions = function(name, userOptions, rotated) {
                    var theme = this._theme,
                        position = !(rotated ^ name === "valueAxis") ? "horizontalAxis" : "verticalAxis",
                        commonAxisSettings = processAxisOptions(this._userOptions["commonAxisSettings"], name);
                    return $.extend(true, {}, theme.commonAxisSettings, theme[position], theme[name], commonAxisSettings, processAxisOptions(userOptions, name))
                };
            var mergeOptions = function(name, userOptions) {
                    userOptions = userOptions || this._userOptions[name];
                    var theme = this._theme[name],
                        result = this._mergedSettings[name];
                    if (result)
                        return result;
                    if ($.isPlainObject(theme) && $.isPlainObject(userOptions))
                        result = $.extend(true, {}, theme, userOptions);
                    else
                        result = utils.isDefined(userOptions) ? userOptions : theme;
                    this._mergedSettings[name] = result;
                    return result
                };
            var applyParticularTheme = {
                    base: mergeOptions,
                    argumentAxis: applyParticularAxisOptions,
                    valueAxisRangeSelector: function() {
                        return mergeOptions.call(this, 'valueAxis')
                    },
                    valueAxis: applyParticularAxisOptions,
                    title: function(name) {
                        var userOptions = processTitleOptions(this._userOptions[name]);
                        return mergeOptions.call(this, name, userOptions)
                    },
                    series: function(name, userOptions, isPie) {
                        var theme = this._theme,
                            userCommonSettings = this._userOptions.commonSeriesSettings || {},
                            themeCommonSettings = theme.commonSeriesSettings,
                            type = ((userOptions.type || userCommonSettings.type || themeCommonSettings.type) + '').toLowerCase(),
                            settings,
                            palette = this.palette,
                            isBar = ~type.indexOf('bar'),
                            isBubble = ~type.indexOf('bubble'),
                            mainSeriesColor,
                            containerBackgroundColor = this.getOptions("containerBackgroundColor");
                        if (isBar || isBubble) {
                            userOptions = $.extend(true, {}, userCommonSettings, userCommonSettings[type], userOptions);
                            var seriesVisibility = userOptions.visible;
                            userCommonSettings = {type: {}};
                            $.extend(true, userOptions, userOptions.point);
                            userOptions.visible = seriesVisibility
                        }
                        settings = $.extend(true, {}, themeCommonSettings, themeCommonSettings[type], userCommonSettings, userCommonSettings[type], userOptions);
                        settings.type = type;
                        settings.containerBackgroundColor = containerBackgroundColor;
                        if (!isPie) {
                            settings.widgetType = 'chart';
                            mainSeriesColor = settings.color || palette.getNextColor()
                        }
                        else {
                            settings.widgetType = 'pieChart';
                            mainSeriesColor = function() {
                                return palette.getNextColor()
                            }
                        }
                        settings.mainSeriesColor = mainSeriesColor;
                        settings._IE8 = this._IE8;
                        return settings
                    },
                    pieSegment: function(name, seriesSettings, segmentSettings) {
                        var settings = $.extend(true, {}, seriesSettings, segmentSettings);
                        var mainColor = new DX.Color(settings.color || this.palette.getNextColor());
                        settings.color = mainColor.toHex();
                        settings.border.color = settings.border.color || mainColor.toHex();
                        settings.hoverStyle.color = settings.hoverStyle.color || this._IE8 && mainColor.highlight(HOVER_COLOR_HIGHLIGHTING) || mainColor.toHex();
                        settings.hoverStyle.border.color = settings.hoverStyle.border.color || mainColor.toHex();
                        settings.selectionStyle.color = settings.selectionStyle.color || this._IE8 && mainColor.highlight(HOVER_COLOR_HIGHLIGHTING) || mainColor.toHex();
                        settings.selectionStyle.border.color = settings.selectionStyle.border.color || mainColor.toHex();
                        return settings
                    },
                    animation: function(name) {
                        var userOptions = this._userOptions[name];
                        userOptions = $.isPlainObject(userOptions) ? userOptions : utils.isDefined(userOptions) ? {enabled: !!userOptions} : {};
                        return mergeOptions.call(this, name, userOptions)
                    }
                };
            return {
                    _themeSection: 'chart',
                    ctor: ctor,
                    dispose: dispose,
                    _initializeTheme: function() {
                        var that = this,
                            theme = this._theme;
                        theme.legend = theme.legend || {};
                        theme.legend.font = theme.legend.font || {};
                        that._initializeFont(theme.legend.font);
                        initDefaultSeriesTheme(that);
                        initAxisTheme(that);
                        theme.title = theme.title || {};
                        theme.title.font = theme.title.font || {};
                        that._initializeFont(theme.title.font);
                        theme.tooltip = theme.tooltip || {};
                        theme.tooltip.font = theme.tooltip.font || {};
                        that._initializeFont(theme.tooltip.font);
                        theme.loadingIndicator = theme.loadingIndicator || {};
                        theme.loadingIndicator.font = theme.loadingIndicator.font || {};
                        that._initializeFont(theme.loadingIndicator.font)
                    },
                    resetPalette: resetPalette,
                    getOptions: function(name) {
                        return (applyParticularTheme[name] || applyParticularTheme["base"]).apply(this, arguments)
                    },
                    setTheme: function(theme) {
                        var that = this;
                        that._mergedSettings = {};
                        that.callBase(theme);
                        that.getOptions('rtlEnabled') && $.extend(true, that._theme, that._theme._rtl)
                    },
                    resetOptions: function(name) {
                        this._mergedSettings[name] = null
                    },
                    update: function(options) {
                        this._userOptions = options
                    },
                    updatePalette: updatePalette
                }
        }())
    })(jQuery, DevExpress);
    /*! Module viz-core, file factory.js */
    (function($, DX) {
        var viz = DX.viz,
            charts = viz.charts,
            series = charts.series;
        charts.factory = function() {
            var createSeriesFamily = function(options) {
                    return new series.SeriesFamily(options)
                };
            var createAxis = function(renderer, options) {
                    return new charts.Axis(renderer, options)
                };
            var createThemeManager = function(options, groupName) {
                    return new charts.ThemeManager(options, groupName)
                };
            var createDataValidator = function(data, groups, incidentOccured, dataPrepareOptions) {
                    return new charts.DataValidator(data, groups, incidentOccured, dataPrepareOptions)
                };
            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(options) {
                    return new charts.LayoutManager(options)
                };
            return {
                    createSeriesFamily: createSeriesFamily,
                    createAxis: createAxis,
                    createThemeManager: createThemeManager,
                    createDataValidator: createDataValidator,
                    createTracker: createTracker,
                    createChartLayoutManager: createChartLayoutManager,
                    createTitle: createTitle
                }
        }()
    })(jQuery, DevExpress);
    /*! Module viz-core, file baseWidget.js */
    (function($, DX, undefined) {
        var core = DX.viz.core,
            utils = DX.utils;
        DX.viz.core.BaseWidget = DX.DOMComponent.inherit({
            NAMESPACE: DX.ui,
            _init: function() {
                this._setRedrawOnResize(this._getOptionRedrawOnResize());
                this._incidentOccured = this._createIncidentOccured();
                this._renderVisiblityChange()
            },
            _optionChanged: function(name, value, prevValue) {
                var that = this;
                switch (name) {
                    case'redrawOnResize':
                        that._setRedrawOnResize(that._getOptionRedrawOnResize());
                        break;
                    case'loadingIndicator':
                        that._updateLoadIndicator(that._getLoadIndicatorOption());
                        break;
                    default:
                        that._invalidate()
                }
                that.callBase(name, value, prevValue)
            },
            _getOptionRedrawOnResize: function() {
                var redrawOnResize = this.option('redrawOnResize');
                redrawOnResize = redrawOnResize !== undefined ? !!redrawOnResize : true;
                return redrawOnResize
            },
            _getLoadIndicatorOption: function() {
                return this.option('loadingIndicator')
            },
            _dispose: function() {
                var that = this;
                if (that._resizeHandlerCallback)
                    that._removeResizeCallbacks();
                that._incidentOccured = null;
                that.callBase()
            },
            _visibilityChanged: function(visible) {
                if (visible)
                    this.render()
            },
            _setRedrawOnResize: function(redrawOnResize) {
                var that = this;
                if (redrawOnResize) {
                    if (!that._resizeHandlerCallback && utils.isFunction(that._resize)) {
                        that._resizeHandlerCallback = DX.utils.createResizeHandler(function() {
                            that._resize()
                        });
                        utils.windowResizeCallbacks.add(that._resizeHandlerCallback)
                    }
                }
                else
                    that._removeResizeCallbacks()
            },
            _removeResizeCallbacks: function() {
                var that = this;
                that._resizeHandlerCallback && that._resizeHandlerCallback.stop();
                utils.windowResizeCallbacks.remove(that._resizeHandlerCallback);
                delete that._resizeHandlerCallback
            },
            _showLoadIndicator: function(options, canvas) {
                var that = this;
                that._loadIndicator = this._loadIndicator || core.CoreFactory.createLoadIndicator(options, that._element());
                that._loadIndicator.show(canvas.width, canvas.height);
                that._initializing && that._loadIndicator.endLoading(undefined, true)
            },
            _updateLoadIndicator: function(options, width, height) {
                this._loadIndicator && this._loadIndicator.applyOptions(options, width, height)
            },
            _endLoading: function(complete) {
                if (this._loadIndicator)
                    this._loadIndicator.endLoading(complete);
                else
                    complete && complete()
            },
            _reappendLoadIndicator: function() {
                this._loadIndicator && this._loadIndicator.toForeground()
            },
            _disposeLoadIndicator: function() {
                this._loadIndicator && this._loadIndicator.dispose();
                this._loadIndicator = null
            },
            _setDefaultOptions: function() {
                this.callBase();
                this.option({incidentOccured: function(options) {
                        var message = "" + options.id + " - " + options.text,
                            majorVerision = options.version.split(".").slice(0, 2).join("_"),
                            url = "http://js.devexpress.com/error/" + majorVerision + "/" + options.id;
                        utils.logger.warn(message + "\n" + url)
                    }})
            },
            _createIncidentOccured: function() {
                var that = this;
                return function(errorOrWarningId, options) {
                        var isError = errorOrWarningId[0] === 'E',
                            type = isError ? "error" : "warning",
                            formattingArray = options ? options.slice(0) : [],
                            text,
                            incidentOccuredFunc = that.option('incidentOccured');
                        formattingArray.unshift(core.errorsWarnings[errorOrWarningId]);
                        text = utils.stringFormat.apply(null, formattingArray);
                        if (utils.isFunction(incidentOccuredFunc))
                            setTimeout(function() {
                                incidentOccuredFunc({
                                    id: errorOrWarningId,
                                    type: type,
                                    args: options,
                                    text: text,
                                    widget: that.NAME,
                                    version: DevExpress.VERSION
                                })
                            })
                    }
            },
            _normalizeHtml: function(html) {
                var re = /xmlns="[\s\S]*?"/gi,
                    first = true;
                html = html.replace(re, function(match) {
                    if (!first)
                        return "";
                    first = false;
                    return match
                });
                return html.replace(/xmlns:NS1="[\s\S]*?"/gi, "").replace(/NS1:xmlns:xlink="([\s\S]*?)"/gi, 'xmlns:xlink="$1"')
            },
            _drawn: function() {
                var that = this,
                    drawnCallback = that.option('drawn');
                utils.isFunction(drawnCallback) && setTimeout(function() {
                    drawnCallback(that)
                })
            },
            showLoadingIndicator: function() {
                this._showLoadIndicator(this.option('loadingIndicator'), this.canvas || {})
            },
            hideLoadingIndicator: function() {
                this._loadIndicator && this._loadIndicator.hide()
            },
            endUpdate: function() {
                if (this._updateLockCount === 1 && !this._requireRefresh)
                    this.hideLoadingIndicator();
                this.callBase()
            },
            svg: function() {
                var renderer = this.renderer || this._renderer;
                return renderer ? this._normalizeHtml(renderer.svg()) : ''
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file CoreFactory.js */
    (function(DX, undefined) {
        var renderers = DX.viz.renderers,
            core = DX.viz.core;
        DX.viz.core.CoreFactory = function() {
            return {
                    createSeries: function(renderer, options) {
                        return new core.series.Series(renderer, options)
                    },
                    createPoint: function(data, options) {
                        return new core.series.points.Point(data, options)
                    },
                    createLabel: function(type, data, options) {
                        if (type === "pie" || type === "doughnut" || type === "donut")
                            return new core.series.points.PieLabel(data, options);
                        else
                            return new core.series.points.Label(data, options)
                    },
                    createRenderer: function(options) {
                        return new renderers.Renderer(options)
                    },
                    createTranslator1D: function(fromValue, toValue, fromAngle, toAngle) {
                        return (new core.Translator1D).setDomain(fromValue, toValue).setCodomain(fromAngle, toAngle)
                    },
                    createTranslator2D: function(range, canvas, options) {
                        return new core.Translator2D(range, canvas, options)
                    },
                    getTickProvider: function() {
                        return core.tickProvider
                    },
                    createTooltip: function(options, group, renderer) {
                        return new core.Tooltip(options, group, renderer)
                    },
                    createLoadIndicator: function(options, group) {
                        return new core.LoadIndicator(options, group)
                    },
                    createLegend: function(data, options, renderer, group) {
                        return new core.Legend(data, options, renderer, group)
                    },
                    createSeriesFamily: function(options) {
                        return new core.series.helpers.SeriesFamily(options)
                    }
                }
        }()
    })(DevExpress);
    DevExpress.MOD_VIZ_CORE = true
}
if (!DevExpress.MOD_VIZ_CHARTS) {
    if (!DevExpress.MOD_VIZ_CORE)
        throw Error('Required module is not referenced: viz-core');
    /*! Module viz-charts, 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
            },
            decreaseGaps = DevExpress.viz.core.utils.decreaseGaps,
            DEFAULT_MARGIN = 10;
        DX.viz.charts.ChartTitle = DX.Class.inherit({
            ctor: function(renderer, options, width, group) {
                var that = this;
                that._init(options, width);
                that.renderer = renderer;
                that.titleGroup = group
            },
            dispose: function() {
                var that = this;
                that.renderer = null;
                that.clipRect = null;
                that.title = null;
                that.innerTitleGroup = null;
                that.titleGroup = null;
                that.options = null
            },
            update: function(options, width) {
                this._init(options, width)
            },
            _init: function(options, width) {
                var that = this;
                if (options) {
                    that._parseAlignments(options);
                    that.horizontalAlignment = options.horizontalAlignment;
                    that.verticalAlignment = options.verticalAlignment;
                    that._parseMargins(options);
                    that.margin = options.margin;
                    that.options = options
                }
                that.setSize({width: width})
            },
            _parseMargins: function(options) {
                options.margin = isDefined(options.margin) ? options.margin : {};
                if (typeof options.margin === 'number') {
                    options.margin = options.margin >= 0 ? options.margin : DEFAULT_MARGIN;
                    options.margin = {
                        top: options.margin,
                        bottom: options.margin,
                        left: options.margin,
                        right: options.margin
                    }
                }
                else {
                    options.margin.top = options.margin.top >= 0 ? options.margin.top : DEFAULT_MARGIN;
                    options.margin.bottom = options.margin.bottom >= 0 ? options.margin.bottom : DEFAULT_MARGIN;
                    options.margin.left = options.margin.left >= 0 ? options.margin.left : DEFAULT_MARGIN;
                    options.margin.right = options.margin.right >= 0 ? options.margin.right : DEFAULT_MARGIN
                }
            },
            _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'
            },
            _setBoundingRect: function() {
                var that = this,
                    options = that.options,
                    margin = that.changedMargin || that.margin,
                    box;
                if (!that.innerTitleGroup)
                    return;
                box = that.innerTitleGroup.getBBox();
                box.height += margin.top + margin.bottom;
                box.width += margin.left + margin.right;
                box.x -= margin.left;
                box.y -= margin.top;
                if (isDefined(options.placeholderSize))
                    box.height = options.placeholderSize;
                that.boundingRect = box
            },
            draw: function() {
                var that = this,
                    titleOptions = that.options,
                    renderer = that.renderer,
                    attr;
                if (!titleOptions.text)
                    return;
                that.changedMargin = null;
                if (!that.innerTitleGroup) {
                    that.innerTitleGroup = renderer.createGroup();
                    that.clipRect = that.createClipRect();
                    that.titleGroup && that.clipRect && that.titleGroup.applySettings({clipId: that.clipRect.id})
                }
                else
                    that.innerTitleGroup.clear();
                that.innerTitleGroup.append(that.titleGroup);
                attr = {
                    font: titleOptions.font,
                    align: that.horizontalAlignment,
                    style: titleOptions.fontStyle
                };
                that.title = renderer.createText(titleOptions.text, 0, 0, attr).append(that.innerTitleGroup);
                that.title.text = titleOptions.text;
                that._correctTitleLength();
                that._setClipRectSettings()
            },
            _correctTitleLength: function() {
                var that = this,
                    text = that.title.text,
                    updateText,
                    lineLength,
                    box;
                that.title.updateText(text);
                that._setBoundingRect();
                box = that.getLayoutOptions();
                if (that._width > box.width || text.indexOf("<br/>") !== -1)
                    return;
                lineLength = text.length * that._width / box.width;
                updateText = text.substr(0, ~~lineLength - 1 - 3) + "...";
                that.title.updateText(updateText);
                that._setBoundingRect()
            },
            changeSize: function(size) {
                var that = this,
                    margin = $.extend(true, {}, that.margin);
                if (margin.top + margin.bottom < size.height) {
                    if (this.innerTitleGroup) {
                        that.options._incidentOccured("W2103");
                        this.innerTitleGroup.remove();
                        this.innerTitleGroup = null
                    }
                    if (that.clipRect) {
                        that.clipRect.remove();
                        that.clipRect = null
                    }
                }
                else if (size.height > 0) {
                    decreaseGaps(margin, ["top", "bottom"], size.height);
                    size.height && (that.changedMargin = margin)
                }
                that._correctTitleLength();
                that._setBoundingRect();
                that._setClipRectSettings()
            },
            getLayoutOptions: function() {
                var options = this.options,
                    boundingRect = this.innerTitleGroup ? this.boundingRect : {
                        width: 0,
                        height: 0,
                        x: 0,
                        y: 0
                    };
                boundingRect.verticalAlignment = options.verticalAlignment;
                boundingRect.horizontalAlignment = options.horizontalAlignment;
                boundingRect.cutLayoutSide = options.verticalAlignment;
                return boundingRect
            },
            setSize: function(size) {
                this._width = size.width || this._width
            },
            shift: function(x, y) {
                var that = this,
                    box = that.getLayoutOptions();
                x -= box.x;
                y -= box.y;
                that.innerTitleGroup && that.innerTitleGroup.move(x, y);
                that.clipRect && that.clipRect.updateRectangle({
                    translateX: x,
                    translateY: y
                })
            },
            createClipRect: function() {
                if (isDefined(this.options.placeholderSize))
                    return this.renderer.createClipRect(0, 0, 0, 0)
            },
            _setClipRectSettings: function() {
                var bbox = this.getLayoutOptions(),
                    clipRect = this.clipRect;
                if (clipRect) {
                    clipRect.append();
                    clipRect.updateRectangle({
                        x: bbox.x,
                        y: bbox.y,
                        width: bbox.width,
                        height: bbox.height
                    })
                }
            }
        });
        DX.viz.charts.ChartTitle.__DEFAULT_MARGIN = DEFAULT_MARGIN
    })(jQuery, DevExpress);
    /*! Module viz-charts, file axis.js */
    (function($, DX, undefined) {
        var utils = DX.utils,
            isDefinedUtils = utils.isDefined,
            isDateUtils = utils.isDate,
            mathAbs = Math.abs,
            core = DX.viz.core,
            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_START = 'canvas_position_start',
            CANVAS_POSITION_END = 'canvas_position_end',
            TOP = 'top',
            BOTTOM = 'bottom',
            LEFT = 'left',
            RIGHT = 'right',
            CENTER = 'center';
        DX.viz.charts.AXIS_STAGGER_OVERLAPPING_KOEF = AXIS_STAGGER_OVERLAPPING_KOEF;
        var processCustomOptions = function(options) {
                var label = options.label,
                    position = options.position;
                if (options.isHorizontal) {
                    if (!(position === BOTTOM || position === TOP))
                        position = BOTTOM
                }
                else if (!(position === LEFT || position === RIGHT))
                    position = LEFT;
                options.position = position;
                if (position === RIGHT && !label.userAlignment)
                    label.alignment = LEFT
            };
        var formatLabel = function(value, options, axisMinMax) {
                var formatObject = {
                        value: value,
                        valueText: DX.formatHelper.format(value, options.format, options.precision) || ''
                    };
                if (axisMinMax) {
                    formatObject.min = axisMinMax.min;
                    formatObject.max = axisMinMax.max
                }
                return options.customizeText ? options.customizeText.call(formatObject, formatObject) : formatObject.valueText
            };
        var nextState = function(state) {
                switch (state) {
                    case'overlap':
                        return 'stagger';
                    case'stagger':
                        return 'rotate';
                    case'rotate':
                    default:
                        return 'end'
                }
            };
        DX.viz.charts.Axis = 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.constantLineStyle, 'constantLineStyle 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)
        };
        $.extend(DX.viz.charts.Axis.prototype, {
            dispose: function() {
                var that = this;
                that._axisElementsGroup && that._axisElementsGroup.dispose();
                $.each(that.labels || [], function(_, label) {
                    label.removeData()
                });
                that.labels = null;
                that.title = null;
                that.stripLabels = null;
                that.stripRects = null;
                that.constantLineLabels = null;
                that.constantLines = null;
                that._axisStripGroup = null;
                that._axisConstantLineGroup = null;
                that._axisLableGroup = null;
                that._axisLineGroup = null;
                that._axisElementsGroup = null;
                that._axisGridGroup = null;
                that._axisGroup = null;
                that.axesContainerGroup = null;
                that.stripsGroup = null;
                that.constantLinesGroup = null;
                that._axisTitleGroup = null;
                that.renderer = null;
                that.translator = null;
                that.orthogonalTranslator = null;
                that.options = null;
                that.textOptions = null;
                that._tickValues = null;
                that._fullTickValues = null;
                that._fullTickPositions = null
            },
            _init: function(options) {
                var that = this,
                    categories = options.categories,
                    labelOptions = options.label;
                options.hoverMode = options.hoverMode ? options.hoverMode.toLowerCase() : 'none';
                that.hasLabelFormat = labelOptions.format !== '' && isDefinedUtils(labelOptions.format);
                that.options = options;
                that.staggered = labelOptions.staggered;
                labelOptions.minSpacing = isDefinedUtils(labelOptions.minSpacing) ? labelOptions.minSpacing : DEFAULT_AXIS_LABEL_SPACING;
                processCustomOptions(options);
                if (categories) {
                    that.labelsNumber = categories.length;
                    that.ticksNumber = that.labelsNumber
                }
                options.range = {
                    min: options.min,
                    max: options.max,
                    categories: options.categories && options.categories.slice(0)
                };
                that.pane = options.pane;
                that.textOptions = {
                    align: labelOptions.alignment,
                    font: labelOptions.font,
                    opacity: labelOptions.opacity,
                    style: labelOptions.style
                };
                if (options.type === 'logarithmic') {
                    if (options.logarithmBaseError) {
                        options.incidentOccured('E2104');
                        delete options.logarithmBaseError
                    }
                    that.calcInterval = function(value, prevValue) {
                        return utils.getLog(value / prevValue, options.logarithmBase)
                    }
                }
            },
            updateSize: function(clearAxis) {
                var that = this,
                    options = that.options,
                    direction = options.isHorizontal ? "horizontal" : "vertical";
                if (that.title && that._axisTitleGroup) {
                    options.incidentOccured('W2105', [direction]);
                    that._axisTitleGroup.remove();
                    that._axisTitleGroup = null
                }
                if (clearAxis && that._axisElementsGroup && that.labels) {
                    options.incidentOccured('W2106', [direction]);
                    that._axisElementsGroup.remove();
                    that._axisElementsGroup = null
                }
                that._setBoundingRect()
            },
            _updateTranslatorInterval: function() {
                var that = this,
                    i,
                    tickValues,
                    businessRange = that.translator.getBusinessRange();
                if (businessRange && businessRange.addRange && !that.options.categories) {
                    tickValues = that.getTickValues();
                    for (i = 0; i < tickValues.length - 1; i++)
                        businessRange.addRange({interval: mathAbs(tickValues[i] - tickValues[i + 1])})
                }
            },
            setTranslator: function(translator, orthogonalTranslator) {
                var that = this;
                var debug = DX.utils.debug;
                debug.assertParam(translator, 'translator was not passed');
                that.translator = translator;
                orthogonalTranslator && (that.orthogonalTranslator = orthogonalTranslator);
                that.resetTicks();
                that._updateTranslatorInterval()
            },
            resetTicks: function() {
                var that = this;
                that._tickValues = that._tickPositions = that._fullTickValues = that._fullTickPositions = null
            },
            setRange: function(range) {
                var debug = DX.utils.debug;
                debug.assertParam(range, 'range was not passed');
                var options = this.options;
                options.min = range.minVisible;
                options.max = range.maxVisible;
                options.categories = range.categories;
                options.stubData = range.stubData;
                this.resetTicks()
            },
            _drawAxis: function() {
                var that = this,
                    translator = that.translator,
                    options = that.options,
                    hasCategories = !!options.categories,
                    axisPosition = that.axisPosition,
                    p11,
                    p12,
                    p21,
                    p22;
                if (!options.visible)
                    return;
                p11 = translator.translateSpecialCase(CANVAS_POSITION_START);
                p21 = translator.translateSpecialCase(CANVAS_POSITION_END);
                if (options.isHorizontal)
                    p12 = p22 = axisPosition;
                else {
                    p12 = p11;
                    p22 = p21;
                    p11 = p21 = axisPosition
                }
                that.renderer.createLine(p11, p12, p21, p22, {
                    strokeWidth: options.width,
                    stroke: options.color,
                    strokeOpacity: options.opacity
                }).append(that._axisLineGroup)
            },
            _getOptimalRotationAngle: function(tick1, tick2, labelOptions) {
                var that = this,
                    translator = that.options.isHorizontal ? that.translator : that.orthogonalTranslator,
                    renderer = that.renderer,
                    outOfScreen = core.outOfScreen,
                    textOptions = that.textOptions,
                    svgElement1 = renderer.createText(formatLabel(tick1, labelOptions), outOfScreen.x + translator.translate(tick1), outOfScreen.y, textOptions).append(),
                    svgElement2 = renderer.createText(formatLabel(tick2, labelOptions), outOfScreen.x + translator.translate(tick2), outOfScreen.y, textOptions).append(),
                    bBox1 = svgElement1.getBBox(),
                    bBox2 = svgElement2.getBBox(),
                    angle = Math.asin((bBox1.height + labelOptions.minSpacing) / (bBox2.x - bBox1.x)) * 180 / Math.PI;
                svgElement1.remove();
                svgElement2.remove();
                return isNaN(angle) ? 90 : Math.ceil(angle)
            },
            _applyOptimalOverlappingBehavior: function(ticks, ticksOptions) {
                var that = this,
                    overlappingBehavior = that.overlappingBehavior,
                    isOverlapped = false,
                    rotationAngle = null,
                    mode = null,
                    options = $.extend({}, ticksOptions),
                    state = 'overlap';
                while (state !== 'end') {
                    isOverlapped = rotationAngle && rotationAngle !== 90 ? false : that.options.tickProvider.isOverlappedTicks(ticks, options);
                    state = nextState(isOverlapped ? state : null);
                    that.testAutoOverlappingState = state;
                    switch (state) {
                        case'stagger':
                            options.screenDelta *= AXIS_STAGGER_OVERLAPPING_KOEF;
                            mode = state;
                            break;
                        case'rotate':
                            rotationAngle = that._getOptimalRotationAngle(ticks[0], ticks[1], that.options.label);
                            that.testAutoOverlappingRotationAngle = rotationAngle;
                            options.screenDelta = ticksOptions.screenDelta;
                            options.textOptions.rotate = rotationAngle;
                            mode = state;
                            break
                    }
                }
                that.testAutoOverlappingOptions = options;
                overlappingBehavior.isOverlapped = isOverlapped;
                overlappingBehavior.mode = mode;
                overlappingBehavior.rotationAngle = rotationAngle
            },
            _getTicksOptions: function() {
                var that = this,
                    options = that.options,
                    translator = that.translator,
                    screenDelta = mathAbs(translator.translateSpecialCase(CANVAS_POSITION_START) - translator.translateSpecialCase(CANVAS_POSITION_END)),
                    min = options.min,
                    max = options.max,
                    digitPosition = utils.getSignificantDigitPosition(mathAbs(max - min) / screenDelta),
                    correctingValue,
                    getText = function() {
                        return ''
                    };
                if (utils.isNumber(min) && options.type !== 'logarithmic') {
                    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 (!options.stubData)
                    getText = function(value) {
                        return formatLabel(value, options.label, {
                                min: min,
                                max: max
                            })
                    };
                return {
                        min: min,
                        max: max,
                        base: options.type === 'logarithmic' ? options.logarithmBase : undefined,
                        axisType: options.type,
                        dataType: options.dataType,
                        customTicks: $.isArray(options.categories) ? options.categories : that._tickValues,
                        useTicksAutoArrangement: false,
                        textOptions: that.textOptions,
                        getText: getText,
                        renderer: that.renderer,
                        textSpacing: options.label.minSpacing,
                        translator: translator,
                        tickInterval: options.stubData ? null : options.tickInterval,
                        screenDelta: screenDelta,
                        gridSpacingFactor: options.axisDivisionFactor,
                        isHorizontal: options.isHorizontal,
                        setTicksAtUnitBeginning: options.setTicksAtUnitBeginning,
                        incidentOccured: options.incidentOccured
                    }
            },
            getTickValues: function() {
                var that = this,
                    correctedScreenDelta,
                    options = that.options,
                    tickProvider = options.tickProvider,
                    labelOptions = options.label,
                    categories = options.categories,
                    ticksOptions = that._getTicksOptions();
                that._fullTickValues = that._tickValues = tickProvider.getTicks(ticksOptions);
                if ((isDateUtils(options.min) || isDateUtils(categories && categories[0])) && !that.hasLabelFormat && that._tickValues.length)
                    labelOptions.format = DX.formatHelper.getDateFormatByTicks(that._tickValues);
                that.overlappingBehavior = labelOptions.overlappingBehavior ? $.extend({}, labelOptions.overlappingBehavior) : null;
                if (that.overlappingBehavior) {
                    if (!options.isHorizontal && that.overlappingBehavior.mode !== 'ignore')
                        that.overlappingBehavior.mode = 'enlargeTickInterval';
                    ticksOptions.useTicksAutoArrangement = that.overlappingBehavior.mode !== 'ignore';
                    if (ticksOptions.useTicksAutoArrangement)
                        that._fullTickValues = that._tickValues = tickProvider.getCorrectedTicks(that._fullTickValues, ticksOptions);
                    if (that.overlappingBehavior.mode === 'auto') {
                        that.textOptions.rotate = 0;
                        that._applyOptimalOverlappingBehavior(that._fullTickValues, ticksOptions);
                        ticksOptions.useTicksAutoArrangement = that.overlappingBehavior.isOverlapped
                    }
                    if (that.overlappingBehavior.mode === 'rotate') {
                        that.textOptions.rotate = that.overlappingBehavior.rotationAngle;
                        if (!labelOptions.userAlignment)
                            that.textOptions.align = LEFT
                    }
                    else if (!labelOptions.userAlignment)
                        that.textOptions.align = labelOptions.alignment
                }
                if (ticksOptions.useTicksAutoArrangement) {
                    correctedScreenDelta = that._tickValues.length ? that.translator.translate(that._tickValues[that._tickValues.length - 1]) - that.translator.translate(that._tickValues[0]) : null;
                    if (correctedScreenDelta) {
                        ticksOptions.screenDelta = mathAbs(correctedScreenDelta);
                        ticksOptions.ticksCount = that._tickValues.length - 1
                    }
                    else
                        ticksOptions.ticksCount = that._tickValues.length;
                    if (that.overlappingBehavior && that.overlappingBehavior.mode === 'stagger')
                        ticksOptions.screenDelta *= AXIS_STAGGER_OVERLAPPING_KOEF;
                    ticksOptions.customTicks = that._tickValues;
                    that._tickValues = tickProvider.getTicks(ticksOptions)
                }
                that._testTKScreenDelta = ticksOptions.screenDelta;
                that._autoArrangementStep = that._tickValues.autoArrangementStep;
                that._useTicksAutoArrangement = ticksOptions.useTicksAutoArrangement;
                if (that.options.stubData) {
                    that._testSkippedFormattingAndOverlapping = true;
                    return that._tickValues
                }
                if (!$.isArray(categories))
                    that._fullTickValues = that._tickValues;
                return that._tickValues
            },
            setTickValues: function(tickValues) {
                this.resetTicks();
                this._fullTickValues = this._tickValues = tickValues
            },
            _prepareLabelsToDraw: function() {
                var that = this,
                    ticksValues = that.getTickValues(),
                    ticks = [],
                    i;
                if (ticksValues.hideLabels || that.options.stubData)
                    ticks.hideLabels = true;
                for (i = 0; i < ticksValues.length; i++)
                    ticks.push({
                        text: ticksValues[i],
                        pos: that.translator.translate(ticksValues[i])
                    });
                return ticks
            },
            _correctTicksPosition: function(ticks) {
                var that = this,
                    options = that.options,
                    tickDelta = that.translator.getInterval() / 2,
                    i;
                if (options.categories && (options.discreteAxisDivisionMode !== 'crossLabels' || !options.discreteAxisDivisionMode)) {
                    if (options.isHorizontal) {
                        if (!options.valueMarginsEnabled)
                            ticks = ticks.slice(0, ticks.length - 1)
                    }
                    else {
                        tickDelta = -tickDelta;
                        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
            },
            _prepareFullTicksToDraw: function() {
                var that = this,
                    ticksValues = that._fullTickValues,
                    ticks = [],
                    i;
                if (!that._fullTickPositions) {
                    if (!ticksValues) {
                        that.getTickValues();
                        ticksValues = that._fullTickValues || []
                    }
                    for (i = 0; i < ticksValues.length; i++)
                        ticks.push({pos: that.translator.translate(ticksValues[i])});
                    that._fullTickPositions = that._correctTicksPosition(ticks)
                }
                return that._fullTickPositions
            },
            _drawTicks: function() {
                var that = this,
                    options = that.options,
                    ticksOptions = options.tick,
                    i,
                    axisPosition = that.axisPosition,
                    tickStart = axisPosition - 4,
                    tickEnd = axisPosition + 4,
                    tick,
                    ticksToDraw;
                if (!ticksOptions.visible)
                    return;
                var drawLine = function(p11, p12, p21, p22) {
                        that.renderer.createLine(p11, p12, p21, p22, {
                            strokeWidth: 1,
                            stroke: ticksOptions.color,
                            strokeOpacity: ticksOptions.opacity
                        }).append(that._axisLineGroup)
                    };
                ticksToDraw = that._prepareFullTicksToDraw();
                if (options.isHorizontal)
                    for (i = 0; i < ticksToDraw.length; i++) {
                        tick = ticksToDraw[i];
                        drawLine(tick.pos, tickStart, tick.pos, tickEnd)
                    }
                else
                    for (i = 0; i < ticksToDraw.length; i++) {
                        tick = ticksToDraw[i];
                        drawLine(tickStart, tick.pos, tickEnd, tick.pos)
                    }
            },
            setPercentLabelFormat: function() {
                var labelOptions = this.options.label;
                if (!this.hasLabelFormat)
                    labelOptions.format = 'percent'
            },
            resetAutoLabelFormat: function() {
                var labelOptions = this.options.label;
                if (!this.hasLabelFormat)
                    delete labelOptions.format
            },
            _drawLabels: function() {
                var that = this,
                    i,
                    options = that.options,
                    renderer = that.renderer,
                    axisPosition = that.axisPosition,
                    labelOptions = options.label,
                    labelOffset = labelOptions.indentFromAxis,
                    labelsToDraw,
                    labelPoint,
                    label,
                    labels = [],
                    createText = options.isHorizontal ? renderer.createText : function(text, y, x, textOptions) {
                        return this.createText(text, x, y, textOptions)
                    },
                    emptyStrRegExp = /^\s+$/,
                    currentLabelConst = options.position === TOP || options.position === LEFT ? axisPosition - labelOffset : axisPosition + labelOffset,
                    text;
                if (!labelOptions.visible || !that._axisElementsGroup)
                    return;
                labelsToDraw = that._prepareLabelsToDraw();
                if (labelsToDraw.length === 0 || labelsToDraw.hideLabels)
                    return true;
                for (i = 0; i < labelsToDraw.length; i++) {
                    labelPoint = labelsToDraw[i];
                    text = formatLabel(labelPoint.text, labelOptions, {
                        min: options.min,
                        max: options.max
                    });
                    if (isDefinedUtils(text) && text !== '' && !emptyStrRegExp.test(text)) {
                        label = createText.call(renderer, text, labelPoint.pos, currentLabelConst, that.textOptions);
                        labels.push(label);
                        label.append(that._axisElementsGroup);
                        label.data({argument: labelPoint.text})
                    }
                }
                that.labels = labels
            },
            getMultipleAxesSpacing: function() {
                return this.options.multipleAxesSpacing || 0
            },
            _drawTitle: function() {
                var that = this,
                    i,
                    options = that.options,
                    renderer = that.renderer,
                    axisPosition = that.axisPosition,
                    titleOptions = options.title,
                    title,
                    attr = {
                        font: titleOptions.font,
                        opacity: titleOptions.opacity,
                        align: CENTER,
                        'class': 'dx-chart-axis-title'
                    },
                    centerPosition = that.translator.translateSpecialCase(CANVAS_POSITION_PREFIX + CENTER),
                    x,
                    y;
                if (!titleOptions.text || !that._axisTitleGroup)
                    return;
                if (options.isHorizontal) {
                    x = centerPosition;
                    y = axisPosition
                }
                else {
                    if (options.position === LEFT)
                        attr.rotate = 270;
                    else
                        attr.rotate = 90;
                    x = axisPosition;
                    y = centerPosition
                }
                that.title = renderer.createText(titleOptions.text, x, y, attr).append(that._axisTitleGroup)
            },
            _drawGrid: function(borderOptions) {
                var that = this,
                    positionsToDraw,
                    options = that.options,
                    gridOptions = options.grid,
                    i;
                if (!gridOptions.visible)
                    return;
                borderOptions = borderOptions || {visible: false};
                var drawLine = function() {
                        var translator = that.translator,
                            orthogonalTranslator = that.orthogonalTranslator,
                            isHorizontal = options.isHorizontal,
                            canvasStart = isHorizontal ? LEFT : TOP,
                            canvasEnd = isHorizontal ? RIGHT : BOTTOM,
                            positionFrom = orthogonalTranslator.translateSpecialCase(CANVAS_POSITION_START),
                            positionTo = orthogonalTranslator.translateSpecialCase(CANVAS_POSITION_END),
                            firstBorderLinePosition = borderOptions.visible && borderOptions[canvasStart] ? translator.translateSpecialCase(CANVAS_POSITION_PREFIX + canvasStart) : undefined,
                            lastBorderLinePosition = borderOptions.visible && borderOptions[canvasEnd] ? translator.translateSpecialCase(CANVAS_POSITION_PREFIX + canvasEnd) : undefined;
                        return function(tick) {
                                if (mathAbs(tick.pos - firstBorderLinePosition) < MAX_GRID_BORDER_ADHENSION || mathAbs(tick.pos - lastBorderLinePosition) < MAX_GRID_BORDER_ADHENSION)
                                    return;
                                var p11 = tick.pos,
                                    p12 = positionFrom,
                                    p21 = tick.pos,
                                    p22 = positionTo;
                                if (!isHorizontal) {
                                    p11 = positionFrom;
                                    p12 = p22 = tick.pos;
                                    p21 = positionTo
                                }
                                that.renderer.createLine(p11, p12, p21, p22, {
                                    strokeWidth: gridOptions.width,
                                    stroke: gridOptions.color,
                                    strokeOpacity: gridOptions.opacity
                                }).append(that._axisGridGroup)
                            }
                    }();
                positionsToDraw = that._prepareFullTicksToDraw();
                for (i = 0; i < positionsToDraw.length; i++)
                    drawLine(positionsToDraw[i])
            },
            _drawConstantLine: function() {
                var that = this,
                    group = that._axisConstantLineGroup,
                    renderer = that.renderer,
                    options = that.options,
                    data = options.constantLines,
                    translator = that.translator,
                    orthogonalTranslator = that.orthogonalTranslator,
                    isHorizontal = options.isHorizontal,
                    i,
                    lines = [],
                    labels = [],
                    positionFrom = orthogonalTranslator.translateSpecialCase(CANVAS_POSITION_START),
                    positionTo = orthogonalTranslator.translateSpecialCase(CANVAS_POSITION_END),
                    canvasStart = translator.translateSpecialCase(CANVAS_POSITION_START),
                    canvasEnd = translator.translateSpecialCase(CANVAS_POSITION_END),
                    range = translator.getBusinessRange();
                var getPos = function(lineValue) {
                        var parsedValue = that.validateUnit(lineValue, "E2105", 'constantLine'),
                            value = translator.translate(parsedValue),
                            isContinous = !!(range.minVisible || range.maxVisible);
                        if (!isContinous && $.inArray(lineValue, range.categories || []) === -1 || !isDefinedUtils(value) || value < Math.min(canvasStart, canvasEnd) || value > Math.max(canvasStart, canvasEnd))
                            return {};
                        return {
                                value: value,
                                parsedValue: parsedValue
                            }
                    };
                var drawLinesAndLabels = function(lineOptions) {
                        if (lineOptions.value === undefined)
                            return;
                        var pos = getPos(lineOptions.value),
                            labelOptions = lineOptions.label || {},
                            value = pos.value,
                            line,
                            attr = {
                                stroke: lineOptions.color,
                                strokeWidth: lineOptions.width,
                                dashStyle: lineOptions.dashStyle
                            };
                        if (!isDefinedUtils(value)) {
                            lines.push(null);
                            if (labelOptions.visible)
                                labels.push(null);
                            return
                        }
                        line = isHorizontal ? renderer.createLine(value, positionTo, value, positionFrom, attr) : renderer.createLine(positionFrom, value, positionTo, value, attr);
                        lines.push(line.append(group));
                        if (labelOptions.visible)
                            labels.push(that._drawConstantLineLabels(pos.parsedValue, labelOptions, value, group));
                        else
                            labels.push(null)
                    };
                for (i = 0; i < data.length; i++)
                    drawLinesAndLabels(data[i]);
                that.constantLines = lines;
                that.constantLineLabels = labels
            },
            _checkAlignmentConstantLineLabels: function(labelOptions) {
                var options = this.options;
                labelOptions.verticalAlignment = (labelOptions.verticalAlignment || '').toLowerCase();
                labelOptions.horizontalAlignment = (labelOptions.horizontalAlignment || '').toLowerCase();
                if (options.isHorizontal && labelOptions.position === 'outside') {
                    labelOptions.verticalAlignment = labelOptions.verticalAlignment === BOTTOM ? BOTTOM : TOP;
                    labelOptions.horizontalAlignment = CENTER
                }
                if (options.isHorizontal && labelOptions.position === 'inside') {
                    labelOptions.verticalAlignment = labelOptions.verticalAlignment === CENTER ? CENTER : labelOptions.verticalAlignment === BOTTOM ? BOTTOM : TOP;
                    labelOptions.horizontalAlignment = labelOptions.horizontalAlignment === LEFT ? LEFT : RIGHT
                }
                if (!options.isHorizontal && labelOptions.position === 'outside') {
                    labelOptions.verticalAlignment = CENTER;
                    labelOptions.horizontalAlignment = labelOptions.horizontalAlignment === LEFT ? LEFT : RIGHT
                }
                if (!options.isHorizontal && labelOptions.position === 'inside') {
                    labelOptions.verticalAlignment = labelOptions.verticalAlignment === BOTTOM ? BOTTOM : TOP;
                    labelOptions.horizontalAlignment = labelOptions.horizontalAlignment === RIGHT ? RIGHT : labelOptions.horizontalAlignment === CENTER ? CENTER : LEFT
                }
            },
            _drawConstantLineLabels: function(parsedValue, lineLabelOptions, value, group) {
                var that = this,
                    text = lineLabelOptions.text,
                    orthogonalTranslator = that.orthogonalTranslator,
                    options = that.options,
                    labelOptions = options.label,
                    attr = {
                        align: CENTER,
                        font: $.extend({}, labelOptions.font, lineLabelOptions.font)
                    },
                    x,
                    y;
                that._checkAlignmentConstantLineLabels(lineLabelOptions);
                text = isDefinedUtils(text) ? text : formatLabel(parsedValue, labelOptions);
                if (options.isHorizontal) {
                    x = value;
                    switch (lineLabelOptions.horizontalAlignment) {
                        case LEFT:
                            attr.align = RIGHT;
                            break;
                        case RIGHT:
                            attr.align = LEFT;
                            break
                    }
                    y = orthogonalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + lineLabelOptions.verticalAlignment)
                }
                else {
                    y = value;
                    x = orthogonalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + lineLabelOptions.horizontalAlignment);
                    switch (lineLabelOptions.horizontalAlignment) {
                        case LEFT:
                            attr.align = lineLabelOptions.position === 'inside' ? LEFT : RIGHT;
                            break;
                        case CENTER:
                            attr.align = CENTER;
                            break;
                        case RIGHT:
                            attr.align = lineLabelOptions.position === 'inside' ? RIGHT : LEFT;
                            break
                    }
                }
                return that.renderer.createText(text, x, y, attr).append(group)
            },
            _adjustConstantLineLabels: function() {
                var that = this,
                    options = that.options,
                    isHorizontal = options.isHorizontal,
                    lines = that.constantLines,
                    labels = that.constantLineLabels,
                    label,
                    line,
                    lineBox,
                    linesOptions,
                    labelOptions,
                    box,
                    x,
                    y,
                    i,
                    padding = isHorizontal ? {
                        top: 0,
                        bottom: 0
                    } : {
                        left: 0,
                        right: 0
                    };
                if (labels === undefined && lines === undefined)
                    return;
                for (i = 0; i < labels.length; i++) {
                    x = y = 0;
                    linesOptions = options.constantLines[i];
                    labelOptions = linesOptions.label;
                    label = labels[i];
                    if (label !== null) {
                        line = lines[i];
                        box = label.getBBox();
                        lineBox = line.getBBox();
                        if (isHorizontal)
                            if (labelOptions.position === 'inside') {
                                switch (labelOptions.horizontalAlignment) {
                                    case LEFT:
                                        x -= linesOptions.paddingLeftRight;
                                        break;
                                    default:
                                        x += linesOptions.paddingLeftRight;
                                        break
                                }
                                switch (labelOptions.verticalAlignment) {
                                    case CENTER:
                                        y += lineBox.y + lineBox.height / 2 - box.y - box.height / 2;
                                        break;
                                    case BOTTOM:
                                        y -= linesOptions.paddingTopBottom;
                                        break;
                                    default:
                                        y += linesOptions.paddingTopBottom + box.height;
                                        break
                                }
                            }
                            else
                                switch (labelOptions.verticalAlignment) {
                                    case BOTTOM:
                                        y += box.height + linesOptions.paddingTopBottom - (box.y + box.height - that.orthogonalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + labelOptions.verticalAlignment));
                                        if (padding[BOTTOM] < box.height + linesOptions.paddingTopBottom)
                                            padding[BOTTOM] = box.height + linesOptions.paddingTopBottom;
                                        break;
                                    default:
                                        y -= linesOptions.paddingTopBottom;
                                        if (padding[TOP] < linesOptions.paddingTopBottom + box.height)
                                            padding[TOP] = linesOptions.paddingTopBottom + box.height;
                                        break
                                }
                        else if (labelOptions.position === 'inside') {
                            switch (labelOptions.horizontalAlignment) {
                                case CENTER:
                                    x += lineBox.x + lineBox.width / 2 - box.x - box.width / 2;
                                    break;
                                case RIGHT:
                                    x -= linesOptions.paddingLeftRight;
                                    break;
                                default:
                                    x += linesOptions.paddingLeftRight;
                                    break
                            }
                            switch (labelOptions.verticalAlignment) {
                                case BOTTOM:
                                    y += lineBox.y - box.y + linesOptions.paddingTopBottom;
                                    break;
                                default:
                                    y -= linesOptions.paddingTopBottom;
                                    break
                            }
                        }
                        else {
                            y += lineBox.y + lineBox.height / 2 - box.y - box.height / 2;
                            switch (labelOptions.horizontalAlignment) {
                                case RIGHT:
                                    x += linesOptions.paddingLeftRight;
                                    if (padding[RIGHT] < linesOptions.paddingLeftRight + box.width)
                                        padding[RIGHT] = linesOptions.paddingLeftRight + box.width;
                                    break;
                                default:
                                    x -= linesOptions.paddingLeftRight;
                                    if (padding[LEFT] < linesOptions.paddingLeftRight + box.width)
                                        padding[LEFT] = linesOptions.paddingLeftRight + box.width;
                                    break
                            }
                        }
                        label.move(x, y)
                    }
                }
                that.padding = padding
            },
            _drawStrip: function() {
                var that = this,
                    renderer = that.renderer,
                    options = that.options,
                    stripData = options.strips,
                    translator = that.translator,
                    orthogonalTranslator = that.orthogonalTranslator,
                    range = translator.getBusinessRange(),
                    i,
                    stripLabels = [],
                    stripRects = [],
                    rect,
                    isHorizontal = options.isHorizontal,
                    stripOptions,
                    positionFrom,
                    positionTo,
                    stripPos,
                    stripLabelOptions,
                    attr;
                if (options.stubData)
                    return;
                var getPos = function(startV, endV) {
                        var isContinous = !!(range.minVisible || range.maxVisible),
                            cateories = range.categories || [],
                            start = translator.translate(that.validateUnit(startV, "E2105", "strip")),
                            end = translator.translate(that.validateUnit(endV, "E2105", "strip")),
                            canvasStart = translator.translateSpecialCase(CANVAS_POSITION_START),
                            canvasEnd = translator.translateSpecialCase(CANVAS_POSITION_END),
                            min = range.minVisible;
                        if (!isContinous && ($.inArray(startV, cateories) === -1 || $.inArray(endV, cateories) === -1))
                            return {
                                    stripFrom: 0,
                                    stripTo: 0
                                };
                        if (!isDefinedUtils(start) && isContinous)
                            start = startV < min ? canvasStart : canvasEnd;
                        if (!isDefinedUtils(end) && isContinous)
                            end = endV < min ? canvasStart : canvasEnd;
                        return start < end ? {
                                stripFrom: start,
                                stripTo: end
                            } : {
                                stripFrom: end,
                                stripTo: start
                            }
                    };
                positionFrom = orthogonalTranslator.translateSpecialCase(CANVAS_POSITION_START);
                positionTo = orthogonalTranslator.translateSpecialCase(CANVAS_POSITION_END);
                for (i = 0; i < stripData.length; i++) {
                    stripOptions = stripData[i];
                    stripLabelOptions = stripOptions.label || {};
                    attr = {fill: stripOptions.color};
                    if (stripOptions.startValue !== undefined && stripOptions.endValue !== undefined && stripOptions.color !== undefined) {
                        stripPos = getPos(stripOptions.startValue, stripOptions.endValue);
                        if (stripPos.stripTo - stripPos.stripFrom === 0 || !stripPos.stripTo && stripPos.stripTo !== 0 || !stripPos.stripFrom && stripPos.stripFrom !== 0) {
                            stripRects.push(null);
                            if (stripLabelOptions.text)
                                stripLabels.push(null);
                            continue
                        }
                        rect = isHorizontal ? renderer.createRect(stripPos.stripFrom, Math.min(positionFrom, positionTo), stripPos.stripTo - stripPos.stripFrom, mathAbs(positionFrom - positionTo), 0, attr) : renderer.createRect(Math.min(positionFrom, positionTo), stripPos.stripFrom, mathAbs(positionFrom - positionTo), stripPos.stripTo - stripPos.stripFrom, 0, attr);
                        stripRects.push(rect.append(that._axisStripGroup));
                        if (stripLabelOptions.text)
                            stripLabels.push(that._drawStripLabel(stripLabelOptions, stripPos.stripFrom, stripPos.stripTo));
                        else
                            stripLabels.push(null)
                    }
                }
                that.stripLabels = stripLabels;
                that.stripRects = stripRects
            },
            _drawStripLabel: function(stripLabelOptions, stripFrom, stripTo) {
                var that = this,
                    orthogonalTranslator = that.orthogonalTranslator,
                    options = that.options,
                    isHorizontal = options.isHorizontal,
                    attr = {
                        align: isHorizontal ? CENTER : LEFT,
                        font: $.extend({}, options.label.font, stripLabelOptions.font)
                    },
                    x,
                    y;
                if (isHorizontal) {
                    if (stripLabelOptions.horizontalAlignment === CENTER) {
                        x = stripFrom + (stripTo - stripFrom) / 2;
                        attr.align = CENTER
                    }
                    else if (stripLabelOptions.horizontalAlignment === LEFT) {
                        x = stripFrom;
                        attr.align = LEFT
                    }
                    else if (stripLabelOptions.horizontalAlignment === RIGHT) {
                        x = stripTo;
                        attr.align = RIGHT
                    }
                    y = orthogonalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + stripLabelOptions.verticalAlignment)
                }
                else {
                    x = orthogonalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + stripLabelOptions.horizontalAlignment);
                    attr.align = stripLabelOptions.horizontalAlignment;
                    if (stripLabelOptions.verticalAlignment === TOP)
                        y = stripFrom;
                    else if (stripLabelOptions.verticalAlignment === CENTER)
                        y = stripTo + (stripFrom - stripTo) / 2;
                    else if (stripLabelOptions.verticalAlignment === BOTTOM)
                        y = stripTo
                }
                return that.renderer.createText(stripLabelOptions.text, x, y, attr).append(that._axisLableGroup)
            },
            _initAxisPositions: function() {
                var that = this,
                    position = that.options.position,
                    delta = 0;
                if (that.delta)
                    delta = that.delta[position] || 0;
                that.axisPosition = that.orthogonalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + position) + delta
            },
            _adjustLabels: function() {
                var that = this,
                    options = that.options,
                    isHorizontal = options.isHorizontal,
                    position = options.position,
                    labels = that.labels,
                    label,
                    labelHeight,
                    isNeedLabelAdjustment,
                    staggeringSpacing,
                    i,
                    xt,
                    shift = that.padding && that.padding[position] || 0,
                    boxAxis = that._axisElementsGroup && that._axisElementsGroup.getBBox() || {},
                    box;
                if (!options.label.visible || !labels || !labels.length)
                    return;
                for (i = 0; i < labels.length; i++) {
                    label = labels[i];
                    box = label.getBBox();
                    if (isHorizontal && position === BOTTOM)
                        label.applySettings({y: 2 * label.settings.y - box.y + shift});
                    else if (!isHorizontal) {
                        if (position === LEFT)
                            if (that.textOptions.align === RIGHT)
                                xt = box.x + box.width - shift;
                            else if (that.textOptions.align === CENTER)
                                xt = box.x + box.width / 2 - shift - (boxAxis.width / 2 || 0);
                            else
                                xt = box.x - shift - (boxAxis.width || 0);
                        else if (that.textOptions.align === CENTER)
                            xt = box.x + box.width / 2 + (boxAxis.width / 2 || 0) + shift;
                        else if (that.textOptions.align === RIGHT)
                            xt = box.x + box.width + (boxAxis.width || 0) + shift;
                        else
                            xt = box.x + shift;
                        label.applySettings({
                            x: xt,
                            y: label.settings.y + ~~(label.settings.y - box.y - box.height / 2)
                        })
                    }
                    else if (isHorizontal && position === TOP)
                        label.applySettings({y: 2 * label.settings.y - box.y - box.height - shift})
                }
                isNeedLabelAdjustment = isHorizontal && that.overlappingBehavior && that.overlappingBehavior.mode === 'stagger';
                that._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 = that.overlappingBehavior.staggeringSpacing;
                    that._testStaggeringSpacing = staggeringSpacing;
                    labelHeight = Math.round(labelHeight) + staggeringSpacing;
                    for (i = 1; i < labels.length; i = i + 2) {
                        label = labels[i];
                        if (position === BOTTOM)
                            label.move(0, labelHeight);
                        else if (position === TOP)
                            label.move(0, -labelHeight)
                    }
                    for (i = 0; i < labels.length; i++)
                        labels[i].rotate(0)
                }
            },
            _adjustStripLabels: function() {
                var that = this,
                    labelOptions,
                    labels = that.stripLabels,
                    rects = that.stripRects,
                    label,
                    i,
                    box,
                    rectBox,
                    stripOptions,
                    x,
                    y;
                if (labels === undefined && rects === undefined)
                    return;
                for (i = 0; i < labels.length; i++) {
                    x = y = 0;
                    stripOptions = that.options.strips[i];
                    labelOptions = stripOptions.label;
                    label = labels[i];
                    if (label !== null) {
                        box = label.getBBox();
                        rectBox = rects[i].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)
                    }
                }
            },
            _adjustTitle: function() {
                var that = this,
                    options = that.options,
                    position = options.position,
                    title = that.title,
                    margin = options.title.margin,
                    boxGroup,
                    boxTitle;
                if (!title || !that._axisElementsGroup)
                    return;
                boxTitle = title.getBBox();
                boxGroup = that._axisElementsGroup.getBBox();
                if (options.isHorizontal)
                    if (position === BOTTOM)
                        title.applySettings({
                            y: boxGroup.isEmpty ? undefined : boxGroup.y + boxGroup.height,
                            translateY: margin + boxTitle.height
                        });
                    else
                        title.applySettings({
                            y: boxGroup.isEmpty ? undefined : boxGroup.y,
                            translateY: -margin
                        });
                else if (position === LEFT)
                    title.applySettings({
                        x: boxGroup.isEmpty ? undefined : boxGroup.x,
                        translateX: -margin
                    });
                else
                    title.applySettings({
                        x: boxGroup.isEmpty ? undefined : boxGroup.x + boxGroup.width,
                        translateX: margin
                    })
            },
            draw: function(externalOptions, adjustAxis) {
                var that = this,
                    options = that.options,
                    isHorizontal = options.isHorizontal,
                    cssClass = isHorizontal ? 'dxc-h-axis' : 'dxc-v-axis',
                    stripClass = isHorizontal ? 'dxc-h-strips' : 'dxc-v-strips',
                    constantLineClass = isHorizontal ? 'dxc-h-constant-lines' : 'dxc-v-constant-lines';
                externalOptions = externalOptions || {};
                var debug = DX.utils.debug;
                debug.assertParam(this.translator, 'translator was not set before Draw call');
                if (that._axisGroup) {
                    that._axisGroup.detach();
                    that._axisStripGroup.detach();
                    that._axisLableGroup.detach();
                    that._axisConstantLineGroup.detach();
                    that._axisTitleGroup ? that._axisTitleGroup.clear() : !adjustAxis && (that._axisTitleGroup = that.renderer.createGroup({'class': 'dxc-title'}).append(that._axisGroup));
                    that._axisGridGroup.clear();
                    that._axisElementsGroup ? that._axisElementsGroup.clear() : !adjustAxis && (that._axisElementsGroup = that.renderer.createGroup({'class': 'dxc-elements'}).append(that._axisGroup));
                    that._axisLineGroup.clear();
                    that._axisStripGroup.clear();
                    that._axisConstantLineGroup.clear();
                    that._axisLableGroup.clear()
                }
                else {
                    that._axisGroup = that.renderer.createGroup({
                        'class': cssClass,
                        clipId: that.clipRectID
                    });
                    that._axisStripGroup = that.renderer.createGroup({'class': stripClass});
                    that._axisGridGroup = that.renderer.createGroup({'class': 'dxc-grid'}).append(that._axisGroup);
                    that._axisElementsGroup = that.renderer.createGroup({'class': 'dxc-elements'}).append(that._axisGroup);
                    that._axisLineGroup = that.renderer.createGroup({'class': 'dxc-line'}).append(that._axisGroup);
                    that._axisTitleGroup = that.renderer.createGroup({'class': 'dxc-title'}).append(that._axisGroup);
                    that._axisConstantLineGroup = that.renderer.createGroup({'class': constantLineClass});
                    that._axisLableGroup = that.renderer.createGroup({'class': 'dxc-axis-labels'})
                }
                that._initAxisPositions();
                if (!that._virtual) {
                    that._drawAxis();
                    that._drawTicks();
                    that._drawLabels();
                    that._drawTitle()
                }
                if (options.strips)
                    that._drawStrip();
                if (options.constantLines)
                    that._drawConstantLine();
                that._drawGrid(externalOptions.borderOptions);
                that._axisStripGroup.append(that.stripsGroup);
                that._axisConstantLineGroup.append(that.constantLinesGroup);
                that._axisGroup.append(that.axesContainerGroup);
                that._axisLableGroup.append(that.labelAxesGroup);
                that._adjustConstantLineLabels();
                that._adjustLabels();
                that._adjustStripLabels();
                that._adjustTitle();
                that._setBoundingRect()
            },
            _setBoundingRect: function() {
                var that = this,
                    options = that.options,
                    axisBox = that._axisElementsGroup ? that._axisElementsGroup.getBBox() : {
                        x: 0,
                        y: 0,
                        width: 0,
                        height: 0,
                        isEmpty: true
                    },
                    lineBox = that._axisLineGroup.getBBox(),
                    placeholderSize = options.placeholderSize,
                    start,
                    isHorizontal = options.isHorizontal,
                    coord = isHorizontal && 'y' || 'x',
                    side = isHorizontal && 'height' || 'width',
                    axisTitleBox = that.title && that._axisTitleGroup ? that._axisTitleGroup.getBBox() : axisBox;
                if (axisBox.isEmpty && axisTitleBox.isEmpty && !placeholderSize) {
                    that.boundingRect = axisBox;
                    return
                }
                start = lineBox[coord] || that.axisPosition;
                if (options.position === (isHorizontal && BOTTOM || RIGHT)) {
                    axisBox[side] = placeholderSize || axisTitleBox[coord] + axisTitleBox[side] - start;
                    axisBox[coord] = start
                }
                else {
                    axisBox[side] = placeholderSize || lineBox[side] + start - axisTitleBox[coord];
                    axisBox[coord] = axisTitleBox.isEmpty ? start : axisTitleBox[coord]
                }
                that.boundingRect = axisBox
            },
            getBoundingRect: function() {
                return this._axisElementsGroup ? this.boundingRect : {
                        x: 0,
                        y: 0,
                        width: 0,
                        height: 0
                    }
            },
            shift: function(x, y) {
                var settings = {};
                if (x)
                    settings.translateX = x;
                if (y)
                    settings.translateY = y;
                this._axisGroup.applySettings(settings)
            },
            applyClipRect: function(clipId) {
                this._axisStripGroup.applySettings({clipId: clipId})
            },
            validate: function(isArgumentAxis, incidentOccured) {
                var that = this,
                    options = that.options,
                    range = options.range,
                    parseUtils = new core.ParseUtils,
                    dataType = isArgumentAxis ? options.argumentType : options.valueType,
                    parser = dataType ? parseUtils.getParser(dataType, 'axis') : function(unit) {
                        return unit
                    };
                that.parser = parser;
                that.incidentOccured = incidentOccured;
                options.dataType = dataType;
                if (options.min)
                    options.min = that.validateUnit(options.min, "E2106");
                if (options.max)
                    options.max = that.validateUnit(options.max, "E2106");
                if (range.min)
                    range.min = that.validateUnit(range.min);
                if (range.max)
                    range.max = that.validateUnit(range.max)
            },
            validateUnit: function(unit, idError, parameters) {
                var that = this,
                    dataType = that.options.dataType;
                unit = that.parser(unit);
                if (unit === undefined && idError)
                    that.incidentOccured(idError, [parameters]);
                return unit
            },
            adjustZoomValues: function(min, max) {
                var that = this,
                    range = that.options.range;
                min = that.validateUnit(min);
                max = that.validateUnit(max);
                if (range && isDefinedUtils(range.min)) {
                    min = isDefinedUtils(min) ? range.min < min ? min : range.min : min;
                    max = isDefinedUtils(max) ? range.min < max ? max : range.min : max
                }
                if (range && isDefinedUtils(range.max)) {
                    max = isDefinedUtils(max) ? range.max > max ? max : range.max : max;
                    min = isDefinedUtils(min) ? range.max > min ? min : range.max : min
                }
                that.minRangeArg = min;
                that.maxRangeArg = max;
                return {
                        min: min,
                        max: max
                    }
            },
            getRangeData: function() {
                var that = this,
                    options = that.options,
                    optionsRange = options.range,
                    range = {},
                    min,
                    max;
                var addValueMarginToRange = function(prefix) {
                        if (options.valueMarginsEnabled) {
                            if (isDefinedUtils(options[prefix])) {
                                range[prefix] = options[prefix];
                                range[prefix + 'Priority'] = AXIS_VALUE_MARGIN_PRIORITY
                            }
                        }
                        else {
                            range[prefix] = 0;
                            range[prefix + 'Priority'] = AXIS_VALUE_MARGIN_PRIORITY
                        }
                    };
                if (isDefinedUtils(optionsRange.min) && isDefinedUtils(optionsRange.max)) {
                    min = optionsRange.min < optionsRange.max ? optionsRange.min : optionsRange.max;
                    max = optionsRange.max > optionsRange.min ? optionsRange.max : optionsRange.min
                }
                else {
                    min = optionsRange.min;
                    max = optionsRange.max
                }
                range.min = min;
                range.max = max;
                addValueMarginToRange('minValueMargin');
                addValueMarginToRange('maxValueMargin');
                range.stick = !options.valueMarginsEnabled;
                range.categories = optionsRange.categories;
                range.dataType = options.dataType;
                range.axisType = options.type;
                if (range.axisType === 'logarithmic')
                    range.base = options.logarithmBase;
                if (options.isHorizontal) {
                    range.minVisible = isDefinedUtils(that.minRangeArg) ? that.minRangeArg : optionsRange.min;
                    range.maxVisible = isDefinedUtils(that.maxRangeArg) ? that.maxRangeArg : optionsRange.max;
                    range.invert = options.inverted
                }
                else {
                    range.minVisible = optionsRange.min;
                    range.maxVisible = optionsRange.max;
                    range.invert = options.inverted || options.type === 'discrete' && options.oppositeDirectionYAxis
                }
                return range
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-charts, file baseChart.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            charts = DX.viz.charts,
            utils = DX.utils,
            TRACKER_RENDERING_DELAY = 1200,
            resizeRedrawOptions = {
                animate: false,
                isResize: true
            },
            ACTIONS_BY_PRIORITY = ['reinit', '_reinitDataSource', '_handleDataSourceChanged', 'force_render'],
            core = DX.viz.core,
            DEFAULT_ANIMATION_OPTIONS = {
                asyncSeriesRendering: true,
                asyncTrackersRendering: true,
                trackerRenderingDelay: TRACKER_RENDERING_DELAY
            };
        charts.BaseChart = core.BaseWidget.inherit({
            _setDefaultOptions: function() {
                this.callBase();
                this.option({
                    done: $.noop,
                    drawn: $.noop,
                    seriesClick: null,
                    pointClick: null,
                    legendClick: null,
                    argumentAxisClick: null,
                    seriesHover: null,
                    pointHover: null,
                    seriesSelected: null,
                    pointSelected: null,
                    seriesSelectionChanged: null,
                    pointSelectionChanged: null,
                    seriesHoverChanged: null,
                    pointHoverChanged: null
                })
            },
            _createThemeManager: function() {
                return charts.factory.createThemeManager(this.option())
            },
            _init: function() {
                this.__TRACKER_RENDERING_DELAY = TRACKER_RENDERING_DELAY;
                var that = this;
                that.callBase();
                that.themeManager = this._createThemeManager();
                that._initRenderer();
                that.canvasClipRect = that.renderer.createClipRect();
                that._createHtmlStructure();
                that._needHandleRenderComplete = true;
                that.layoutManager = charts.factory.createChartLayoutManager(that.themeManager.getOptions("adaptiveLayout"));
                that._reinit();
                that._element().css({webkitUserSelect: 'none'}).on('contextmenu', function(event) {
                    that.eventType = 'contextmenu';
                    if (ui.events.isTouchEvent(event) || ui.events.isPointerEvent(event))
                        event.preventDefault()
                }).on('MSHoldVisual', function(event) {
                    that.eventType = 'MSHoldVisual';
                    event.preventDefault()
                })
            },
            _reinit: function() {
                var that = this;
                that.layoutManager.update(that);
                that._createTracker();
                that._reinitDataSource()
            },
            _createHtmlStructure: function() {
                var that = this,
                    renderer = that.renderer;
                that._panesBackgroundGroup = renderer.createGroup({'class': 'dxc-background'});
                that._titleGroup = renderer.createGroup({'class': 'dxc-title'});
                that._legendGroup = renderer.createGroup({
                    'class': 'dxc-legend',
                    clipId: that._getCanvasClipRectID()
                });
                that._stripsGroup = renderer.createGroup({'class': 'dxc-strips-group'});
                that._constantLinesGroup = renderer.createGroup({'class': 'dxc-constant-lines-group'});
                that._axesGroup = renderer.createGroup({'class': 'dxc-axes-group'});
                that._panesBorderGroup = renderer.createGroup({'class': 'dxc-border'});
                that._labelAxesGroup = renderer.createGroup({'class': 'dxc-strips-labels-group'});
                that._seriesGroup = renderer.createGroup({'class': 'dxc-series-group'});
                that._labelsGroup = renderer.createGroup({'class': 'dxc-labels-group'});
                that._tooltipGroup = renderer.createGroup({'class': 'dxc-tooltip'});
                that._trackerGroup = renderer.createGroup({
                    'class': 'dxc-trackers',
                    opacity: 0.0001,
                    stroke: "gray",
                    fill: "gray"
                });
                that._crosshairTrackerGroup = renderer.createGroup({
                    'class': 'dxc-crosshair-trackers',
                    stroke: 'none',
                    fill: 'grey'
                }).append(that._trackerGroup);
                that._seriesTrackerGroup = renderer.createGroup({'class': 'dxc-series-trackers'}).append(that._trackerGroup);
                that._markerTrackerGroup = renderer.createGroup({
                    'class': 'dxc-markers-trackers',
                    stroke: 'none',
                    fill: 'grey'
                }).append(that._trackerGroup);
                that._crossHairCursorGroup = renderer.createGroup({'class': 'dxc-crosshair-cursor'})
            },
            _cleanHtmlStructure: function() {
                var that = this;
                that._panesBackgroundGroup && that._panesBackgroundGroup.clear();
                that._titleGroup && that._titleGroup.clear();
                that._legendGroup && (that._legendGroup.detach(), that._legendGroup.clear());
                that._stripsGroup && (that._stripsGroup.detach(), that._stripsGroup.clear());
                that._constantLinesGroup && (that._constantLinesGroup.detach(), that._constantLinesGroup.clear());
                that._axesGroup && (that._axesGroup.detach(), that._axesGroup.clear());
                that._labelAxesGroup && (that._labelAxesGroup.detach(), that._labelAxesGroup.clear());
                that._seriesGroup && (that._seriesGroup.detach(), that._seriesGroup.clear());
                that._labelsGroup && (that._labelsGroup.detach(), that._labelsGroup.clear());
                that._trackerGroup && (that._trackerGroup.detach(), that._seriesTrackerGroup.clear(), that._markerTrackerGroup.clear(), that._crosshairTrackerGroup.clear());
                that._panesBorderGroup && that._panesBorderGroup.clear();
                that._tooltipGroup && that._tooltipGroup.clear();
                that._crossHairCursorGroup && (that._crossHairCursorGroup.clear(), that._crossHairCursorGroup.detach())
            },
            _disposeObjectsInArray: function(propName, fieldNames) {
                $.each(this[propName] || [], function(_, item) {
                    if (fieldNames && item)
                        $.each(fieldNames, function(_, field) {
                            item[field] && item[field].dispose()
                        });
                    else
                        item && item.dispose()
                });
                this[propName] = null
            },
            _dispose: function() {
                var that = this,
                    disposeObject = function(propName) {
                        that[propName] && that[propName].dispose(),
                        that[propName] = null
                    },
                    detachGroup = function(groupName) {
                        that[groupName] && that[groupName].detach()
                    },
                    disposeObjectsInArray = this._disposeObjectsInArray;
                clearTimeout(that.delayedRedraw);
                that.callBase();
                disposeObjectsInArray.call(that, "businessRanges", ["arg", "val"]);
                that.translators = null;
                disposeObjectsInArray.call(that, "series");
                disposeObject("layoutManager");
                disposeObject("themeManager");
                disposeObject("renderer");
                disposeObject("tracker");
                disposeObject("tooltip");
                disposeObject("chartTitle");
                that.paneAxis = null;
                that._userOptions = null;
                that.dirtyCanvas = null;
                that.canvas = null;
                detachGroup("_legendGroup");
                detachGroup("_stripsGroup");
                detachGroup("_constantLinesGroup");
                detachGroup("_axesGroup");
                detachGroup("_labelAxesGroup");
                detachGroup("_seriesGroup");
                detachGroup("_labelsGroup");
                detachGroup("_trackerGroup");
                detachGroup("_crossHairCursorGroup");
                disposeObject("canvasClipRect");
                disposeObject("_panesBackgroundGroup");
                disposeObject("_titleGroup");
                disposeObject("_legendGroup");
                disposeObject("_stripsGroup");
                disposeObject("_constantLinesGroup");
                disposeObject("_axesGroup");
                disposeObject("_labelAxesGroup");
                disposeObject("_panesBorderGroup");
                disposeObject("_seriesGroup");
                disposeObject("_labelsGroup");
                disposeObject("_tooltipGroup");
                disposeObject("_crossHairCursorGroup");
                disposeObject("_seriesTrackerGroup");
                disposeObject("_markerTrackerGroup");
                disposeObject("_crosshairTrackerGroup");
                disposeObject("_trackerGroup");
                that._disposeLoadIndicator()
            },
            _clean: function _clean(hideLoadIndicator) {
                this.renderer && this.renderer.stopAllAnimations();
                hideLoadIndicator && this.hideLoadingIndicator();
                this._cleanHtmlStructure();
                this.callBase();
                this._saveDirtyCanvas()
            },
            _getAnimationOptions: function() {
                return $.extend({}, DEFAULT_ANIMATION_OPTIONS, this.themeManager.getOptions("animation"))
            },
            _initRenderer: function _initRenderer() {
                if (this.renderer)
                    return;
                this.renderer = core.CoreFactory.createRenderer({
                    animation: this._getAnimationOptions(),
                    cssClass: 'dxc dxc-chart',
                    pathModified: this.option('pathModified'),
                    rtl: this.themeManager.getOptions('rtlEnabled')
                })
            },
            _initSeries: function() {
                this.series = this.series || this._populateSeries()
            },
            _reinitDataSource: function() {
                this._refreshDataSource()
            },
            _saveDirtyCanvas: function() {
                this.dirtyCanvas = $.extend({}, this.canvas)
            },
            _resize: function() {
                this._render(resizeRedrawOptions)
            },
            _calculateCanvas: function() {
                var canvas = this.themeManager.getOptions('size'),
                    result = {},
                    container = this._element();
                if (!utils.isDefined(canvas.width))
                    result.width = container.width() || 400;
                else
                    result.width = canvas.width < 0 ? 0 : canvas.width;
                if (!utils.isDefined(canvas.height))
                    result.height = container.height() || 400;
                else
                    result.height = canvas.height < 0 ? 0 : canvas.height;
                return $.extend({}, result, this.themeManager.getOptions('margin'))
            },
            _createTracker: function() {
                var that = this,
                    tooltipOptions = that.themeManager.getOptions('tooltip') || {};
                if (that.tracker)
                    that.tracker.dispose();
                that.tracker = charts.factory.createTracker({
                    series: that.series,
                    valueAxis: that._valueAxes,
                    argumentAxis: that._argumentAxes,
                    seriesSelectionMode: that.themeManager.getOptions('seriesSelectionMode'),
                    pointSelectionMode: that.themeManager.getOptions('pointSelectionMode'),
                    tooltipShown: that.option('tooltipShown'),
                    tooltipHidden: that.option('tooltipHidden'),
                    markerTrackerGroup: that._markerTrackerGroup,
                    crossHairOptions: that._crossHairOptions,
                    seriesTrackerGroup: that._seriesTrackerGroup,
                    seriesGroup: that._seriesGroup,
                    tooltipEnabled: tooltipOptions.enabled,
                    renderer: that.renderer,
                    events: {
                        seriesClick: that.option('seriesClick'),
                        pointClick: that.option('pointClick'),
                        argumentAxisClick: that.option('argumentAxisClick'),
                        seriesHover: that.option('seriesHover'),
                        seriesSelected: that.option('seriesSelected'),
                        pointHover: that.option('pointHover'),
                        pointSelected: that.option('pointSelected'),
                        legendClick: that.option('legendClick'),
                        seriesSelectionChanged: that.option('seriesSelectionChanged'),
                        pointSelectionChanged: that.option('pointSelectionChanged'),
                        seriesHoverChanged: that.option('seriesHoverChanged'),
                        pointHoverChanged: that.option('pointHoverChanged')
                    }
                })
            },
            _updateTracker: function() {
                var that = this;
                if (!that.tracker)
                    that._createTracker();
                else
                    that.tracker._reinit({
                        series: that.series,
                        valueAxis: that._valueAxes,
                        argumentAxis: that._argumentAxes,
                        legendGroup: that.legend.getTrackerGroup(),
                        legendCallback: $.proxy(that.legend.getActionCallback, that.legend)
                    })
            },
            _render: function(drawOptions) {
                this._optionsInitializing = false;
                var that = this,
                    renderer = that.renderer,
                    updatedCanvas = that.canvas,
                    container = this._element(),
                    currentDirtyCanvas = that._calculateCanvas(),
                    oldDirtyCanvas = that.dirtyCanvas;
                drawOptions = drawOptions || {recreateCanvas: true};
                drawOptions.recreateCanvas = drawOptions.recreateCanvas || !renderer.isInitialized();
                if (!drawOptions.force && oldDirtyCanvas && oldDirtyCanvas.width === currentDirtyCanvas.width && oldDirtyCanvas.height === currentDirtyCanvas.height && !that.hiddenContainer) {
                    that.stopRedraw = true;
                    return
                }
                clearTimeout(that.delayedRedraw);
                if (drawOptions.recreateCanvas)
                    that.canvas = updatedCanvas = that._calculateCanvas();
                if (updatedCanvas.width && updatedCanvas.height && container.is(':visible'))
                    that.hiddenContainer = false;
                else {
                    that._incidentOccured('W2001', [that.NAME]);
                    that.hiddenContainer = true;
                    that.stopRedraw = true;
                    renderer.detachContainer();
                    return
                }
                if (drawOptions.recreateCanvas) {
                    renderer.recreateCanvas(that.canvas.width, that.canvas.height);
                    renderer.draw(that._element()[0]);
                    that._reappendLoadIndicator();
                    that._updateLoadIndicator(undefined, updatedCanvas.width, updatedCanvas.height);
                    that._updateCanvasClipRect()
                }
                that.renderer.stopAllAnimations(true);
                that.layoutManager.update(that);
                that._cleanGroups(drawOptions);
                that._saveDirtyCanvas()
            },
            _cleanGroups: function(drawOptions) {
                var that = this;
                that._stripsGroup.detach();
                that._constantLinesGroup.detach();
                that._axesGroup.detach();
                that._labelAxesGroup.detach();
                that._labelsGroup.detach();
                that._tooltipGroup.detach();
                that._crossHairCursorGroup.detach();
                if (!drawOptions || drawOptions.drawLegend) {
                    that._legendGroup.detach();
                    that._legendGroup.clear()
                }
                if (!drawOptions || drawOptions.drawTitle) {
                    that._titleGroup.detach();
                    that._titleGroup.clear()
                }
                that._stripsGroup.clear();
                that._constantLinesGroup.clear();
                that._axesGroup.clear();
                that._labelAxesGroup.clear();
                that._labelsGroup.clear();
                that._tooltipGroup.clear();
                that._crossHairCursorGroup.clear();
                that._crosshairTrackerGroup.clear()
            },
            _drawTitle: function() {
                var that = this,
                    options = that.themeManager.getOptions("title"),
                    width = that.canvas.width - that.canvas.left - that.canvas.right;
                options._incidentOccured = that._incidentOccured;
                if (that.chartTitle)
                    that.chartTitle.update(options, width);
                else
                    that.chartTitle = charts.factory.createTitle(that.renderer, options, width, that._titleGroup)
            },
            _createTooltip: function() {
                var that = this,
                    tooltipOptions = $.extend(true, {
                        canvasWidth: that.canvas.width,
                        canvasHeight: that.canvas.height
                    }, that.themeManager.getOptions('tooltip') || {}),
                    tooltipCoords,
                    point = this.tracker.pointAtShownTooltip;
                if (!$.isFunction(tooltipOptions.customizeText) && utils.isDefined(tooltipOptions.customizeText)) {
                    that._incidentOccured("E2103", ['customizeText']);
                    tooltipOptions.customizeText = undefined
                }
                if (that.tooltip)
                    that.tooltip.update(tooltipOptions);
                else
                    that.tooltip = core.CoreFactory.createTooltip(tooltipOptions, that._tooltipGroup, that.renderer);
                that.tracker.setTooltip(that.tooltip);
                if (point) {
                    tooltipCoords = point.getTooltipCoords();
                    that.tooltip.move(~~tooltipCoords.x, ~~tooltipCoords.y, tooltipCoords.offset);
                    that.tooltip.show()
                }
            },
            _prepareDrawOptions: function(drawOptions) {
                var animationOptions = this._getAnimationOptions(),
                    options;
                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 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 that = this;
                that.tracker._clean();
                $.each(that.series || [], function(_, series) {
                    series.dispose()
                });
                that.series = null;
                $.each(that.seriesFamilies || [], function(_, family) {
                    family.dispose()
                });
                that.seriesFamilies = null
            },
            _optionChanged: function(name) {
                var that = this,
                    themeManager = this.themeManager;
                themeManager.resetOptions(name);
                themeManager.update(that._options);
                if (name === 'animation') {
                    that.renderer.updateAnimationOptions(this._getAnimationOptions());
                    return
                }
                clearTimeout(that.delayedRedraw);
                switch (name) {
                    case'dataSource':
                        that._needHandleRenderComplete = true;
                        that._processRefreshData('_reinitDataSource');
                        break;
                    case'palette':
                        that.themeManager.updatePalette(this.option(name));
                        that._disposeSeries();
                        that._needHandleRenderComplete = true;
                        that._processRefreshData('_handleDataSourceChanged');
                        break;
                    case'series':
                    case'commonSeriesSettings':
                    case'containerBackgroundColor':
                    case'dataPrepareSettings':
                        that._disposeSeries();
                        that._needHandleRenderComplete = true;
                        that._processRefreshData('_handleDataSourceChanged');
                        break;
                    case'legend':
                    case'seriesTemplate':
                        that._processRefreshData('_handleDataSourceChanged');
                        break;
                    case'title':
                        that._processRefreshData('force_render');
                        break;
                    case'valueAxis':
                    case'argumentAxis':
                    case'commonAxisSettings':
                        that._needHandleRenderComplete = true;
                        that._processRefreshData('reinit');
                        that._disposeSeries();
                        that.paneAxis = {};
                        break;
                    case'panes':
                    case'defaultPane':
                        that._disposeSeries();
                        that.paneAxis = {};
                        that._needHandleRenderComplete = true;
                        that._processRefreshData('reinit');
                        break;
                    case'size':
                        that._processRefreshData('force_render');
                        break;
                    case'rotated':
                    case'equalBarWidth':
                    case'customizePoint':
                    case'customizeLabel':
                        that._disposeSeries();
                        that._needHandleRenderComplete = true;
                        that._processRefreshData('reinit');
                        break;
                    case'theme':
                        that._disposeSeries();
                        themeManager.setTheme(that.option(name));
                        that._processRefreshData('reinit');
                        break;
                    default:
                        that._processRefreshData('reinit')
                }
                that.callBase.apply(that, arguments)
            },
            _getLoadIndicatorOption: function() {
                return this.themeManager.getOptions("loadingIndicator")
            },
            _refresh: function() {
                var that = this;
                this.renderer.stopAllAnimations(true);
                if (that._currentRefreshData) {
                    switch (that._currentRefreshData) {
                        case'force_render':
                            that._render({force: true});
                            break;
                        case'reinit':
                            that._reinit(true);
                            break;
                        default:
                            that[that._currentRefreshData] && that[that._currentRefreshData]()
                    }
                    delete that._currentRefreshData
                }
                else
                    that._render({force: true})
            },
            _dataSourceOptions: function() {
                return {
                        paginate: false,
                        _preferSync: true
                    }
            },
            _updateCanvasClipRect: function(canvas) {
                var that = this,
                    width,
                    height;
                canvas = canvas || that.canvas;
                width = Math.max(canvas.width - canvas.left - canvas.right, 0);
                height = Math.max(canvas.height - canvas.top - canvas.bottom, 0);
                that.canvasClipRect.updateRectangle({
                    x: canvas.left,
                    y: canvas.top,
                    width: width,
                    height: height
                });
                that.canvasClipRect.append()
            },
            _getCanvasClipRectID: function() {
                return this.canvasClipRect.id
            },
            _handleDataSourceChanged: function() {
                clearTimeout(this.delayedRedraw);
                this._dataSpecificInit(true)
            },
            _groupSeries: function() {
                this._groupedSeries = [this.series]
            },
            _dataSpecificInit: function(needRedraw) {
                this._initSeries();
                this._repopulateSeries();
                this._handleSeriesPopulated(needRedraw)
            },
            _processSingleSeries: function(){},
            _repopulateSeries: function() {
                var that = this,
                    parsedData,
                    data = that._dataSource && that._dataSource.items(),
                    dataValidatorOptions = that.themeManager.getOptions('dataPrepareSettings'),
                    seriesTemplate = that.themeManager.getOptions('seriesTemplate');
                if (that._dataSource && seriesTemplate) {
                    that._templatedSeries = utils.processSeriesTemplate(seriesTemplate, that._dataSource.items());
                    that._populateSeries();
                    delete that._templatedSeries;
                    data = that.teamplateData || data
                }
                that._groupSeries();
                that._dataValidator = charts.factory.createDataValidator(data, that._groupedSeries, that._incidentOccured, dataValidatorOptions);
                parsedData = that._dataValidator.validate();
                that.themeManager.resetPalette();
                $.each(that.series, function(_, singleSeries) {
                    singleSeries.updateData(parsedData);
                    that._processSingleSeries(singleSeries)
                })
            },
            _handleRenderComplete: function() {
                var that = this,
                    userHandle = this.option('done'),
                    allSeriesInited = true;
                if (that._needHandleRenderComplete) {
                    $.each(that.series, function(_, s) {
                        allSeriesInited = allSeriesInited && s.canRenderCompleteHandle()
                    });
                    if (allSeriesInited) {
                        that._needHandleRenderComplete = false;
                        $.isFunction(userHandle) && userHandle.call(that)
                    }
                }
            },
            _renderTitleAndLegend: function(drawOptions, legendHasInsidePosition) {
                var that = this,
                    titleOptions = that.themeManager.getOptions("title"),
                    drawTitle = titleOptions.text && drawOptions.drawTitle,
                    drawLegend = drawOptions.drawLegend && that.legend && !legendHasInsidePosition,
                    drawElements = [];
                if (drawTitle) {
                    that._titleGroup.append();
                    that._drawTitle();
                    drawElements.push(that.chartTitle)
                }
                if (drawLegend) {
                    that._legendGroup.append();
                    drawElements.push(that.legend)
                }
                drawElements.length && that.layoutManager.drawElements(drawElements, that.canvas);
                if (drawTitle)
                    that.layoutManager.correctSizeElement(that.chartTitle, that.canvas)
            },
            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()
            },
            showLoadingIndicator: function() {
                this._showLoadIndicator(this.themeManager.getOptions("loadingIndicator"), this.canvas || {})
            },
            render: function(renderOptions) {
                this._render(renderOptions)
            },
            getSize: function() {
                var canvas = this.canvas || {};
                return {
                        width: canvas.width,
                        height: canvas.height
                    }
            }
        }).include(ui.DataHelperMixin)
    })(jQuery, DevExpress);
    /*! Module viz-charts, file chart.js */
    (function($, DX, undefined) {
        var core = DX.viz.core,
            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,
            ASYNC_SERIES_RENDERING_DELAY = 25,
            _each = $.each;
        function prepareAxis(axisOptions) {
            return $.isArray(axisOptions) ? axisOptions.length === 0 ? [{}] : axisOptions : [axisOptions]
        }
        charts.Chart = charts.BaseChart.inherit({
            _setDefaultOptions: function() {
                this.callBase();
                this.option({
                    defaultPane: DEFAULT_PANE_NAME,
                    panes: [{
                            name: DEFAULT_PANE_NAME,
                            border: {}
                        }]
                })
            },
            _dispose: function() {
                var that = this,
                    disposeObjectsInArray = this._disposeObjectsInArray;
                that.callBase();
                that.panes = null;
                that.legend && (that.legend.dispose(), that.legend = null);
                disposeObjectsInArray.call(that, "panesBackground");
                disposeObjectsInArray.call(that, "panesClipRects");
                disposeObjectsInArray.call(that, "financialPanesClipRects");
                disposeObjectsInArray.call(that, "_argumentAxes");
                disposeObjectsInArray.call(that, "_valueAxes");
                disposeObjectsInArray.call(that, "seriesFamilies");
                _each(that._paneTrackerGroups || [], function(_, groups) {
                    groups.paneSeriesGroup.dispose();
                    groups.paneMarkerGroup.dispose()
                });
                that._paneTrackerGroups = null
            },
            _init: function() {
                this.__ASYNC_SERIES_RENDERING_DELAY = ASYNC_SERIES_RENDERING_DELAY;
                this.paneAxis = {};
                this._crossHairOptions = {};
                this.callBase()
            },
            _reinit: function(needRedraw) {
                var that = this;
                that.translators = {};
                that.panes = that._createPanes();
                that._populateAxes();
                that.callBase();
                delete that._seriesInitializing;
                if (!that.series)
                    that._dataSpecificInit();
                else
                    that._correctValueAxes();
                that._endLoading(function() {
                    needRedraw && that._render({force: true})
                })
            },
            _correctBusinessRange: function(range, tickInterval, setTicksAtUnitBeginning) {
                var min = 'min',
                    max = 'max';
                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.addRange(tickIntervalRange);
                    return true
                }
                return false
            },
            _seriesVisibilityChanged: function() {
                this._processSeriesFamilies();
                this._populateBusinessRange();
                this.renderer.stopAllAnimations(true);
                this._render({
                    force: true,
                    asyncSeriesRendering: false,
                    asyncTrackersRendering: false
                })
            },
            _populateBusinessRange: function(visibleArea) {
                var that = this,
                    businessRanges = [],
                    aggregationRange,
                    minBound,
                    maxBound,
                    i,
                    themeManager = that.themeManager,
                    rotated = themeManager.getOptions('rotated'),
                    singleSeriesRange,
                    valAxes = that._valueAxes,
                    valueAxes = {},
                    argAxes = that._argumentAxes,
                    useAggregation = themeManager.getOptions('useAggregation'),
                    argumentTickInterval,
                    setTicksAtUnitBeginning,
                    paneAxis = that.paneAxis,
                    groupedSeries = that._groupedSeries;
                that._disposeObjectsInArray("businessRanges", ["arg", "val"]);
                var argRange = new core.Range({
                        rotated: !!rotated,
                        minValueMargin: DEFAULT_BUSINESS_RANGE_VALUE_MARGIN,
                        maxValueMargin: DEFAULT_BUSINESS_RANGE_VALUE_MARGIN
                    });
                _each(valAxes, function(_, axis) {
                    valueAxes[axis.name] = axis
                });
                _each(paneAxis, function(paneName, pane) {
                    _each(pane, function(axisName, _) {
                        var seriesForRange = [],
                            firstSeriesForRange,
                            options,
                            valueAxesForRange,
                            valRange = new core.Range({
                                isValueRange: true,
                                rotated: !!rotated,
                                pane: paneName,
                                axis: axisName,
                                minValueMargin: DEFAULT_BUSINESS_RANGE_VALUE_MARGIN,
                                maxValueMargin: DEFAULT_BUSINESS_RANGE_VALUE_MARGIN
                            }),
                            valueType,
                            calcInterval;
                        _each(groupedSeries, function(_, particularSeriesGroup) {
                            if (particularSeriesGroup[0].pane === paneName && particularSeriesGroup[0].axis === axisName)
                                seriesForRange = particularSeriesGroup
                        });
                        _each(valAxes, function(_, axis) {
                            if (axis.pane === paneName && axis.name === axisName) {
                                valueAxesForRange = axis;
                                return false
                            }
                        });
                        firstSeriesForRange = seriesForRange && seriesForRange.length ? seriesForRange[0] : {};
                        _each(argAxes, function(_, axis) {
                            var options = axis.options;
                            options.type = firstSeriesForRange.argumentAxisType || options.type;
                            options.argumentType = firstSeriesForRange.argumentType || options.argumentType;
                            axis.validate(true, that._incidentOccured);
                            argRange = argRange.addRange(axis.getRangeData());
                            argumentTickInterval = options.tickInterval;
                            setTicksAtUnitBeginning = options.setTicksAtUnitBeginning;
                            calcInterval = axis.calcInterval
                        });
                        options = valueAxesForRange.options;
                        options.type = firstSeriesForRange.valueAxisType || options.type;
                        options.valueType = firstSeriesForRange.valueType || options.valueType;
                        valueAxesForRange.validate(false, that._incidentOccured);
                        var axisRange = new core.Range(valueAxesForRange.getRangeData());
                        valueType = valueType || options.valueType === 'datetime' ? 'datetime' : undefined;
                        valRange = valRange.addRange(axisRange);
                        minBound = valRange.min;
                        maxBound = valRange.max;
                        for (i = 0; i < seriesForRange.length; i++) {
                            if (visibleArea) {
                                visibleArea.minVal = minBound;
                                visibleArea.maxVal = maxBound;
                                if (useAggregation && !visibleArea.adjustOnZoom) {
                                    aggregationRange = seriesForRange[i]._originalBusinessRange;
                                    visibleArea.minVal = utils.isDefined(visibleArea.minVal) ? visibleArea.minVal : aggregationRange.val.min;
                                    visibleArea.maxVal = utils.isDefined(visibleArea.maxVal) ? visibleArea.maxVal : aggregationRange.val.max
                                }
                            }
                            singleSeriesRange = seriesForRange[i].getRangeData(visibleArea, calcInterval);
                            valRange = valRange.addRange(singleSeriesRange.val);
                            argRange = argRange.addRange(singleSeriesRange.arg)
                        }
                        if (!valRange.isDefined())
                            valRange.setStubData(valueType);
                        businessRanges.push({val: valRange})
                    })
                });
                if (!argRange.isDefined())
                    argRange.setStubData(argAxes[0].options.argumentType);
                var bussinesRangeCorrectedWithTickInterval = that._correctBusinessRange(argRange, argumentTickInterval, setTicksAtUnitBeginning);
                !bussinesRangeCorrectedWithTickInterval && argRange.applyValueMargins();
                _each(businessRanges, function(_, item) {
                    var range = item.val,
                        vAxis = valueAxes[range.axis];
                    range.applyValueMargins();
                    if (vAxis && vAxis.options.showZero)
                        range.correctValueZeroLevel();
                    item.arg = argRange
                });
                that.businessRanges = businessRanges
            },
            _groupSeries: function() {
                var that = this,
                    panes = that.panes,
                    valAxes = that._valueAxes,
                    paneList = $.map(panes, function(pane) {
                        return pane.name
                    }),
                    series = that.series,
                    paneAxis = that.paneAxis,
                    groupedSeries = that._groupedSeries = [];
                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
                    }
                });
                that._correctValueAxes();
                var hideGridsOnNonFirstValueAxisForPane = function(paneName) {
                        var axesForPane = [],
                            firstShownAxis;
                        _each(valAxes, function(_, axis) {
                            if (axis.pane === paneName)
                                axesForPane.push(axis)
                        });
                        if (axesForPane.length > 1 && that.themeManager.getOptions('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
                            })
                    };
                _each(paneAxis, function(paneName, pane) {
                    hideGridsOnNonFirstValueAxisForPane(paneName);
                    _each(pane, function(axisName, _) {
                        var group = [];
                        _each(series, function(_, particularSeries) {
                            if (particularSeries.pane === paneName && particularSeries.axis === axisName)
                                group.push(particularSeries)
                        });
                        group.length && groupedSeries.push(group)
                    })
                })
            },
            _cleanPanesClipRects: function(clipArrayName) {
                var that = this,
                    clipArray = that[clipArrayName];
                _each(clipArray || [], function(_, clipRect) {
                    clipRect && clipRect.remove()
                });
                that[clipArrayName] = []
            },
            _createPanes: function() {
                var that = this,
                    panes = that.option('panes'),
                    panesNameCounter = 0,
                    bottomPaneName;
                if (panes && utils.isArray(panes) && !panes.length || $.isEmptyObject(panes))
                    panes = that.initialOption("panes");
                that._cleanPanesClipRects('panesClipRects');
                that._cleanPanesClipRects('financialPanesClipRects');
                that.defaultPane = that.option('defaultPane');
                panes = $.isArray(panes) ? panes : panes ? [panes] : [];
                _each(panes, function(_, pane) {
                    pane.name = !utils.isDefined(pane.name) ? DEFAULT_PANE_NAME + panesNameCounter++ : pane.name
                });
                if (!that._doesPaneExists(panes, that.defaultPane) && panes.length > 0) {
                    bottomPaneName = panes[panes.length - 1].name;
                    that._incidentOccured('W2101', [that.defaultPane, bottomPaneName]);
                    that.defaultPane = bottomPaneName
                }
                panes = that.themeManager.getOptions('rotated') ? panes.reverse() : panes;
                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 that = this,
                    themeManager = that.themeManager,
                    hasSeriesTemplate = !!themeManager.getOptions('seriesTemplate'),
                    series = hasSeriesTemplate ? that._templatedSeries : that.option('series'),
                    allSeriesOptions = $.isArray(series) ? series : series ? [series] : [],
                    argumentAxisOptions = that.option('argumentAxis'),
                    valueAxisOptions = that.option('valueAxis'),
                    data,
                    particularSeriesOptions,
                    particularSeries,
                    rotated = themeManager.getOptions('rotated'),
                    i,
                    paneList = $.map(that.panes, function(pane) {
                        return pane.name
                    }),
                    paneName,
                    paneIndex;
                that.teamplateData = [];
                _each(that._paneTrackerGroups || [], function(_, groups) {
                    groups.paneSeriesGroup.remove();
                    groups.paneMarkerGroup.remove()
                });
                that._paneTrackerGroups = [];
                _each(that.panes, function(_, pane) {
                    var paneSeriesTrackerGroup = that.renderer.createGroup({'class': 'dxc-pane-tracker'}),
                        paneMarkerTrackerGroup = that.renderer.createGroup({'class': 'dxc-pane-tracker'});
                    that._paneTrackerGroups.push({
                        paneSeriesGroup: paneSeriesTrackerGroup,
                        paneMarkerGroup: paneMarkerTrackerGroup
                    })
                });
                that._disposeSeries();
                that.series = [];
                themeManager.resetPalette();
                for (i = 0; i < allSeriesOptions.length; i++) {
                    particularSeriesOptions = $.extend(true, {}, allSeriesOptions[i]);
                    if (particularSeriesOptions.type && !utils.isString(particularSeriesOptions.type))
                        particularSeriesOptions.type = '';
                    data = particularSeriesOptions.data;
                    particularSeriesOptions.data = null;
                    particularSeriesOptions.rotated = rotated;
                    particularSeriesOptions.customizePoint = themeManager.getOptions("customizePoint");
                    particularSeriesOptions.customizeLabel = themeManager.getOptions("customizeLabel");
                    particularSeriesOptions.visibilityChanged = $.proxy(this._seriesVisibilityChanged, this);
                    particularSeriesOptions.resolveLabelsOverlapping = themeManager.getOptions("resolveLabelsOverlapping");
                    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;
                                    particularSeriesOptions.showZero = options.showZero
                                }
                            });
                        else {
                            particularSeriesOptions.valueCategories = valueAxisOptions.categories;
                            particularSeriesOptions.valueAxisType = valueAxisOptions.type;
                            particularSeriesOptions.valueType = valueAxisOptions.valueType;
                            particularSeriesOptions.showZero = valueAxisOptions.showZero
                        }
                    particularSeriesOptions.incidentOccured = that._incidentOccured;
                    if (!particularSeriesOptions.name)
                        particularSeriesOptions.name = 'Series ' + (i + 1).toString();
                    var seriesTheme = themeManager.getOptions("series", particularSeriesOptions);
                    seriesTheme.pane = seriesTheme.pane || that.defaultPane;
                    paneName = seriesTheme.pane;
                    paneIndex = that._getPaneIndex(paneName);
                    if ($.inArray(paneName, paneList) === -1)
                        continue;
                    seriesTheme.seriesGroup = that._seriesGroup;
                    seriesTheme.labelsGroup = that._labelsGroup;
                    seriesTheme.trackersGroup = that._paneTrackerGroups[paneIndex].paneSeriesGroup;
                    seriesTheme.markerTrackerGroup = that._paneTrackerGroups[paneIndex].paneMarkerGroup;
                    particularSeries = core.CoreFactory.createSeries(that.renderer, seriesTheme);
                    if (!particularSeries.isUpdated)
                        that._incidentOccured("E2101", [seriesTheme.type]);
                    else {
                        particularSeries.index = i;
                        that.series.push(particularSeries)
                    }
                    if (hasSeriesTemplate) {
                        _each(data, function(_, data) {
                            _each(particularSeries.getTeamplatedFields(), function(_, field) {
                                data[field.teamplateField] = data[field.originalField]
                            });
                            that.teamplateData.push(data)
                        });
                        particularSeries.updateTeamplateFieldNames()
                    }
                }
                return that.series
            },
            _createValueAxis: function(axisOptions, rotated, tickProvider) {
                var that = this,
                    axis;
                axisOptions = that.themeManager.getOptions("valueAxis", $.extend({
                    isHorizontal: rotated,
                    tickProvider: tickProvider,
                    incidentOccured: that._incidentOccured
                }, axisOptions), rotated);
                if (axisOptions.strips)
                    _each(axisOptions.strips, function(i, strips) {
                        axisOptions.strips[i] = $.extend(true, {}, axisOptions.stripStyle, axisOptions.strips[i])
                    });
                if (axisOptions.constantLines)
                    _each(axisOptions.constantLines, function(i, line) {
                        axisOptions.constantLines[i] = $.extend(true, {}, axisOptions.constantLineStyle, line)
                    });
                axis = charts.factory.createAxis(that.renderer, axisOptions);
                axis.name = axisOptions.name;
                axis.pane = axis.pane || axisOptions.pane;
                axis.priority = axisOptions.priority;
                return axis
            },
            _disposeAxes: function() {
                var that = this;
                _each(that._valueAxes || [], function(_, axis) {
                    axis.dispose()
                });
                _each(that._argumentAxes || [], function(_, axis) {
                    axis.dispose()
                });
                that._valueAxes = null;
                that._argumentAxes = null
            },
            _populateAxes: function() {
                var that = this,
                    valueAxes = [],
                    argumentAxes = [],
                    panes = that.panes,
                    themeManager = that.themeManager,
                    rotated = themeManager.getOptions('rotated'),
                    valueAxisOptions = that.option('valueAxis') || {},
                    argumentOption = that.option('argumentAxis') || {},
                    argumentAxesOptions = prepareAxis(argumentOption),
                    valueAxesOptions = prepareAxis(valueAxisOptions),
                    axis,
                    axisNames = [],
                    tickProvider = core.CoreFactory.getTickProvider(),
                    paneWithNonVirtualAxis;
                that._disposeAxes();
                var createArgumentAxis = function(axisOptions, virtual) {
                        axisOptions = that.themeManager.getOptions("argumentAxis", $.extend(true, {
                            isHorizontal: !rotated,
                            tickProvider: tickProvider,
                            pane: that.defaultPane,
                            incidentOccured: that._incidentOccured
                        }, axisOptions), rotated);
                        if (axisOptions.strips)
                            _each(axisOptions.strips, function(i, strips) {
                                axisOptions.strips[i] = $.extend(true, {}, axisOptions.stripStyle, axisOptions.strips[i])
                            });
                        if (axisOptions.constantLines)
                            _each(axisOptions.constantLines, function(i, line) {
                                axisOptions.constantLines[i] = $.extend(true, {}, axisOptions.constantLineStyle, line)
                            });
                        axis = charts.factory.createAxis(that.renderer, axisOptions);
                        axis._virtual = virtual;
                        argumentAxes.push(axis);
                        return 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, {}, argumentAxesOptions[0], {pane: paneName});
                    createArgumentAxis(axisOptions, virtual)
                });
                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) {
                        that._incidentOccured("E2102");
                        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) {
                        valueAxes.push(that._createValueAxis($.extend(true, {}, axisOptions, {
                            name: name || getNextAxisName(),
                            pane: pane,
                            priority: priority
                        }), rotated, tickProvider))
                    })
                });
                that._valueAxes = valueAxes;
                that._argumentAxes = argumentAxes
            },
            _correctValueAxes: function() {
                var that = this,
                    rotated = that.themeManager.getOptions('rotated'),
                    valueAxisOptions = that.option('valueAxis') || {},
                    valueAxesOptions = $.isArray(valueAxisOptions) ? valueAxisOptions : [valueAxisOptions],
                    tickProvider = core.CoreFactory.getTickProvider(),
                    valueAxes = that._valueAxes || [],
                    defaultAxisName = valueAxes[0].name,
                    paneAxis = that.paneAxis || {},
                    panes = that.panes,
                    i,
                    neededAxis = {};
                var getPaneForAxis = function(axisNameWithoutPane) {
                        var result;
                        _each(that.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 = that.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 = valueAxesOptions[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) {
                            that._incidentOccured("W2102", [axisName]);
                            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(that.paneAxis, function(paneName, axisNames) {
                    _each(axisNames, function(axisName, _) {
                        neededAxis[axisName + '-' + paneName] = true;
                        if (!findAxis(paneName, axisName)) {
                            var axisOptions = findAxisOptions(axisName);
                            if (axisOptions)
                                valueAxes.push(that._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
                });
                that._valueAxes = valueAxes
            },
            _processSeriesFamilies: function() {
                var that = this,
                    types = [],
                    families = [],
                    paneSeries,
                    themeManager = that.themeManager,
                    rotated = themeManager.getOptions('rotated');
                if (that.seriesFamilies && that.seriesFamilies.length) {
                    _each(that.seriesFamilies, function(_, family) {
                        family.adjustSeriesValues()
                    });
                    return
                }
                _each(that.series, function(_, item) {
                    if ($.inArray(item.type, types) === -1)
                        types.push(item.type)
                });
                _each(that.panes, function(_, pane) {
                    paneSeries = [];
                    _each(that.series, function(_, oneSeries) {
                        if (oneSeries.pane === pane.name)
                            paneSeries.push(oneSeries)
                    });
                    _each(types, function(_, type) {
                        var family = core.CoreFactory.createSeriesFamily({
                                type: type,
                                pane: pane.name,
                                rotated: rotated,
                                equalBarWidth: themeManager.getOptions('equalBarWidth'),
                                minBubbleSize: themeManager.getOptions('minBubbleSize'),
                                maxBubbleSize: themeManager.getOptions('maxBubbleSize')
                            });
                        family.add(paneSeries);
                        family.adjustSeriesValues();
                        families.push(family)
                    })
                });
                that.seriesFamilies = families
            },
            _createLegend: function() {
                var that = this,
                    legendData = [],
                    legendOptions = that.themeManager.getOptions('legend');
                legendData = $.map(that.series, function(seriesItem) {
                    if (seriesItem.getOptions().showInLegend)
                        return {
                                text: seriesItem.name,
                                color: seriesItem.getColor(),
                                id: seriesItem.index,
                                states: seriesItem.getLegendStyles()
                            }
                });
                legendOptions.containerBackgroundColor = that.themeManager.getOptions("containerBackgroundColor");
                legendOptions._incidentOccured = that._incidentOccured;
                if (that.legend)
                    that.legend.update(legendData, legendOptions);
                else
                    that.legend = core.CoreFactory.createLegend(legendData, legendOptions, that.renderer, that._legendGroup)
            },
            _createTranslator: function(range, canvas, options) {
                return core.CoreFactory.createTranslator2D(range, canvas, options)
            },
            _createPanesBorderOptions: function() {
                var commonBorderOptions = this.themeManager.getOptions('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 that = this,
                    themeManager = that.themeManager,
                    rotated = themeManager.getOptions('rotated'),
                    i,
                    layoutManager = that.layoutManager,
                    panesBorderOptions = that._createPanesBorderOptions(),
                    needHideLoadIndicator,
                    legendHasInsidePosition = that.legend && that.legend.getPosition() === "inside";
                var drawSeries = function drawSeries() {
                        var panes = that.panes,
                            hideLayoutLabels = that.layoutManager.needMoreSpaceForPanesCanvas(that.panes, rotated) && !that.themeManager.getOptions("adaptiveLayout").keepLabels,
                            stackPoints = {};
                        _each(that.seriesFamilies || [], function(_, seriesFamily) {
                            var tr = that._getTranslator(seriesFamily.pane) || {},
                                translators = {};
                            translators[rotated ? 'x' : 'y'] = tr.val;
                            translators[rotated ? 'y' : 'x'] = tr.arg;
                            seriesFamily.updateSeriesValues(translators);
                            seriesFamily.adjustSeriesDimensions(translators)
                        });
                        that._createCrossHairCursor();
                        function applyPaneClipRect(seriesOptions) {
                            var paneIndex = that._getPaneIndex(seriesOptions.pane);
                            seriesOptions.setClippingParams(seriesOptions.isFinancialSeries() ? that.financialPanesClipRects[paneIndex].id : that.panesClipRects[paneIndex].id, that._getPaneBorderVisibility(paneIndex))
                        }
                        function preparePointsForSharedTooltip(singleSeries, stackPoints) {
                            if (!themeManager.getOptions('tooltip').shared)
                                return;
                            var points = singleSeries.getPoints(),
                                stackName = singleSeries.getStackName();
                            _each(points, function(index, point) {
                                var argument = point.argument;
                                if (!stackPoints[argument]) {
                                    stackPoints[argument] = {};
                                    stackPoints[argument][null] = []
                                }
                                if (stackName && !DX.utils.isArray(stackPoints[argument][stackName])) {
                                    stackPoints[argument][stackName] = [];
                                    _each(stackPoints[argument][null], function(_, point) {
                                        if (!point.stackName)
                                            stackPoints[argument][stackName].push(point)
                                    })
                                }
                                if (stackName) {
                                    stackPoints[argument][stackName].push(point);
                                    stackPoints[argument][null].push(point)
                                }
                                else
                                    _each(stackPoints[argument], function(_, stack) {
                                        stack.push(point)
                                    });
                                point.stackPoints = stackPoints[argument][stackName];
                                point.stackName = stackName
                            })
                        }
                        _each(that.series, function(_, particularSeries) {
                            preparePointsForSharedTooltip(particularSeries, stackPoints);
                            applyPaneClipRect(particularSeries);
                            particularSeries.setAdjustSeriesLabels(drawOptions.adjustSeriesLabels);
                            var tr = that._getTranslator(particularSeries.pane, particularSeries.axis),
                                translators = {};
                            translators[rotated ? 'x' : 'y'] = tr.val;
                            translators[rotated ? 'y' : 'x'] = tr.arg;
                            particularSeries.draw(translators, drawOptions.animate && particularSeries.getPoints().length <= drawOptions.animationPointsLimit && that.renderer.animationEnabled(), hideLayoutLabels, that.legend && that.legend.getActionCallback(particularSeries))
                        });
                        that._trackerGroup.append();
                        if (drawOptions.drawLegend && that.legend && legendHasInsidePosition) {
                            var newCanvas = $.extend({}, panes[0].canvas),
                                layoutManager = charts.factory.createChartLayoutManager();
                            newCanvas.right = panes[panes.length - 1].canvas.right;
                            newCanvas.bottom = panes[panes.length - 1].canvas.bottom;
                            that._legendGroup.append();
                            that._tooltipGroup.append();
                            layoutManager.drawElements([that.legend], newCanvas);
                            layoutManager.placeDrawnElements(newCanvas)
                        }
                        needHideLoadIndicator && that.hideLoadingIndicator();
                        that._drawn();
                        var drawChartTrackers = function drawChartTrackers() {
                                var i;
                                for (i = 0; i < that.series.length; i++)
                                    that.series[i].drawTrackers();
                                if (that.legend) {
                                    that.legend.drawTrackers();
                                    legendHasInsidePosition && that._legendGroup.append();
                                    legendHasInsidePosition && that._tooltipGroup.append()
                                }
                                that.tracker._prepare();
                                _each(that._paneTrackerGroups, function(index, paneGroups) {
                                    paneGroups.paneSeriesGroup.append(that._seriesTrackerGroup);
                                    paneGroups.paneMarkerGroup.append(that._markerTrackerGroup)
                                });
                                that._handleRenderComplete()
                            };
                        that._createTooltip();
                        if (drawOptions.asyncTrackersRendering)
                            that.delayedRedraw = setTimeout(drawChartTrackers, drawOptions.trackerRenderingDelay);
                        else
                            drawChartTrackers()
                    };
                drawOptions = that._prepareDrawOptions(drawOptions);
                that.callBase(drawOptions);
                if (that.stopRedraw) {
                    that.stopRedraw = false;
                    return
                }
                that._createPanesBackground();
                that._stripsGroup.append();
                that._axesGroup.append();
                that._constantLinesGroup.append();
                that._labelAxesGroup.append();
                that._createTranslators(drawOptions);
                that._options.useAggregation && _each(that.series, function(_, series) {
                    series._originalBusinessRange = series._originalBusinessRange || series.getRangeData();
                    var tr = that._getTranslator(series.pane, series.axis),
                        translators = {};
                    translators[rotated ? 'x' : 'y'] = tr.val;
                    translators[rotated ? 'y' : 'x'] = tr.arg;
                    series.resamplePoints(translators, that._zoomMinArg, that._zoomMaxArg)
                });
                if (utils.isDefined(that._zoomMinArg) || utils.isDefined(that._zoomMaxArg))
                    that._populateBusinessRange({
                        adjustOnZoom: themeManager.getOptions('adjustOnZoom'),
                        minArg: that._zoomMinArg,
                        maxArg: that._zoomMaxArg
                    });
                if (that._options.useAggregation || utils.isDefined(that._zoomMinArg) || utils.isDefined(that._zoomMaxArg))
                    that._updateTranslators();
                that._renderTitleAndLegend(drawOptions, legendHasInsidePosition);
                if (drawOptions && drawOptions.recreateCanvas)
                    layoutManager.updatePanesCanvases(that.panes, that.canvas, rotated);
                that._drawAxes(panesBorderOptions, drawOptions);
                if (layoutManager.needMoreSpaceForPanesCanvas(that.panes, rotated)) {
                    layoutManager.updateDrawnElements(that._argumentAxes, that._valueAxes, that.canvas, that.dirtyCanvas, that.panes, rotated);
                    if (that.chartTitle)
                        that.layoutManager.correctSizeElement(that.chartTitle, that.canvas);
                    that._updateCanvasClipRect(that.dirtyCanvas);
                    layoutManager.updatePanesCanvases(that.panes, that.canvas, rotated);
                    that._drawAxes(panesBorderOptions, drawOptions, true)
                }
                layoutManager.placeDrawnElements(that.canvas);
                that._drawPanesBorders(panesBorderOptions);
                that._createClipRectsForPanes();
                for (i = 0; i < that._argumentAxes.length; i++)
                    that._argumentAxes[i].applyClipRect(that._getElementsClipRectID(that._argumentAxes[i].pane));
                for (i = 0; i < that._valueAxes.length; i++)
                    that._valueAxes[i].applyClipRect(that._getElementsClipRectID(that._valueAxes[i].pane));
                that._fillPanesBackground();
                that._seriesGroup.append();
                that._labelsGroup.append();
                that._crossHairCursorGroup.append();
                that._legendGroup.append();
                that._tooltipGroup.append();
                needHideLoadIndicator = that._loadIndicator && that._loadIndicator.isShown && that._dataSource && that._dataSource.isLoaded() && !drawOptions.isResize;
                if (drawOptions.asyncSeriesRendering)
                    that.delayedRedraw = setTimeout(drawSeries, ASYNC_SERIES_RENDERING_DELAY);
                else
                    drawSeries()
            },
            _createTranslators: function(drawOptions) {
                var that = this,
                    rotated = that.themeManager.getOptions("rotated"),
                    translators;
                if (!drawOptions.recreateCanvas)
                    return;
                that.translators = translators = {};
                that.layoutManager.updatePanesCanvases(that.panes, that.canvas, rotated);
                _each(that.paneAxis, function(paneName, pane) {
                    translators[paneName] = translators[paneName] || {};
                    _each(pane, function(axisName, _) {
                        var translator = that._createTranslator(new core.Range(that._getBusinessRange(paneName, axisName).val), that._getCanvasForPane(paneName), rotated ? {direction: 'horizontal'} : {});
                        translator.pane = paneName;
                        translator.axis = axisName;
                        translators[paneName][axisName] = {val: translator}
                    })
                });
                _each(that._argumentAxes, function(_, axis) {
                    var translator = that._createTranslator(new core.Range(that._getBusinessRange(axis.pane).arg), that._getCanvasForPane(axis.pane), !rotated ? {direction: 'horizontal'} : {});
                    _each(translators[axis.pane], function(valAxis, paneAsixTran) {
                        paneAsixTran.arg = translator
                    })
                })
            },
            _updateTranslators: function() {
                var that = this;
                _each(that.translators, function(pane, axisTrans) {
                    _each(axisTrans, function(axis, translator) {
                        translator.arg.updateBusinessRange(new core.Range(that._getBusinessRange(pane).arg));
                        delete translator.arg._originalBusinessRange;
                        translator.val.updateBusinessRange(new core.Range(that._getBusinessRange(pane, axis).val));
                        delete translator.val._originalBusinessRange
                    })
                })
            },
            _reinitTranslators: function() {
                var that = this;
                _each(that._argumentAxes, function(_, axis) {
                    var translator = that._getTranslator(axis.pane);
                    if (translator) {
                        translator.arg.reinit();
                        axis.setRange(translator.arg.getBusinessRange());
                        axis.setTranslator(translator.arg, translator.val)
                    }
                });
                _each(that._valueAxes, function(_, axis) {
                    var translator = that._getTranslator(axis.pane, axis.name);
                    if (translator) {
                        translator.val.reinit();
                        axis.setRange(translator.val.getBusinessRange());
                        axis.setTranslator(translator.val, translator.arg)
                    }
                })
            },
            _drawAxes: function(panesBorderOptions, drawOptions, adjustUnits) {
                var that = this,
                    i = 0,
                    layoutManager = that.layoutManager,
                    rotated = that.themeManager.getOptions("rotated"),
                    translators = that.translators,
                    adjustmentCounter = 0,
                    synchronizeMultiAxes = that.themeManager.getOptions('synchronizeMultiAxes');
                that._reinitTranslators();
                do {
                    for (i = 0; i < that._argumentAxes.length; i++)
                        that._argumentAxes[i].resetTicks();
                    for (i = 0; i < that._valueAxes.length; i++)
                        that._valueAxes[i].resetTicks();
                    if (synchronizeMultiAxes)
                        charts.multiAxesSynchronizer.synchronize(that._valueAxes);
                    drawAxes(rotated ? that._valueAxes : that._argumentAxes);
                    layoutManager.requireAxesRedraw = false;
                    if (drawOptions.adjustAxes) {
                        layoutManager.applyHorizontalAxesLayout(rotated ? that._valueAxes : that._argumentAxes);
                        !layoutManager.stopDrawAxes && _each(translators, function(pane, axisTrans) {
                            _each(axisTrans, function(axis, translator) {
                                translator.arg.reinit();
                                translator.val.reinit()
                            })
                        })
                    }
                    drawAxes(rotated ? that._argumentAxes : that._valueAxes);
                    if (drawOptions.adjustAxes && !layoutManager.stopDrawAxes) {
                        layoutManager.applyVerticalAxesLayout(rotated ? that._argumentAxes : that._valueAxes);
                        !layoutManager.stopDrawAxes && _each(translators, function(pane, axisTrans) {
                            _each(axisTrans, function(axis, translator) {
                                translator.arg.reinit();
                                translator.val.reinit()
                            })
                        })
                    }
                    adjustmentCounter = adjustmentCounter + 1
                } while (!layoutManager.stopDrawAxes && layoutManager.requireAxesRedraw && adjustmentCounter < MAX_ADJUSTMENT_ATTEMPTS);
                that.__axisAdjustmentsCount = adjustmentCounter;
                function drawAxes(axes) {
                    _each(axes, function(_, axis) {
                        axis.clipRectID = that._getCanvasClipRectID();
                        axis.stripsGroup = that._stripsGroup;
                        axis.labelAxesGroup = that._labelAxesGroup;
                        axis.constantLinesGroup = that._constantLinesGroup;
                        axis.axesContainerGroup = that._axesGroup;
                        axis.draw({borderOptions: panesBorderOptions[axis.pane]}, adjustUnits)
                    })
                }
            },
            _createCrossHairCursor: function() {
                var that = this,
                    renderer = that.renderer,
                    panes = that.panes,
                    commonCanvas,
                    canvas,
                    options = that.themeManager.getOptions('crosshair') || {},
                    hLine,
                    vLine,
                    attrHLine,
                    attrVLine,
                    i;
                if (!options || !options.enabled)
                    return;
                attrHLine = {
                    stroke: options.horizontalLine.color || options.color,
                    strokeWidth: options.horizontalLine.width || options.width,
                    dashStyle: options.horizontalLine.dashStyle || options.dashStyle,
                    visibility: 'hidden',
                    opacity: options.horizontalLine.opacity || options.opacity
                };
                attrVLine = {
                    stroke: options.verticalLine.color || options.color,
                    strokeWidth: options.verticalLine.width || options.width,
                    dashStyle: options.verticalLine.dashStyle || options.dashStyle,
                    visibility: 'hidden',
                    opacity: options.verticalLine.opacity || options.opacity
                };
                for (i = 0; i < panes.length; i++) {
                    canvas = panes[i].canvas;
                    if (!commonCanvas)
                        commonCanvas = $.extend({}, canvas);
                    else {
                        commonCanvas.right = canvas.right;
                        commonCanvas.bottom = canvas.bottom
                    }
                    renderer.createRect(canvas.left, canvas.top, canvas.width - canvas.right - canvas.left, canvas.height - canvas.bottom - canvas.top, 0).append(this._crosshairTrackerGroup)
                }
                if (options.horizontalLine && options.horizontalLine.visible)
                    hLine = renderer.createLine(commonCanvas.left, commonCanvas.top, commonCanvas.width - commonCanvas.right, commonCanvas.top, attrHLine).append(that._crossHairCursorGroup);
                if (options.verticalLine && options.verticalLine.visible)
                    vLine = renderer.createLine(commonCanvas.left, commonCanvas.top, commonCanvas.left, commonCanvas.height - commonCanvas.bottom, attrVLine).append(that._crossHairCursorGroup);
                that._crossHairOptions.horizontalLine = hLine;
                that._crossHairOptions.verticalLine = vLine;
                that._crossHairOptions.canvas = commonCanvas
            },
            _createPanesBackground: function() {
                var that = this,
                    defaultBackgroundColor = that.themeManager.getOptions('commonPaneSettings').backgroundColor,
                    backgroundColor,
                    renderer = that.renderer,
                    rect,
                    i,
                    rects = [];
                that._panesBackgroundGroup && that._panesBackgroundGroup.clear();
                for (i = 0; i < that.panes.length; i++) {
                    backgroundColor = that.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(that._panesBackgroundGroup);
                    rects.push(rect)
                }
                that.panesBackground = rects;
                that._panesBackgroundGroup.append()
            },
            _fillPanesBackground: function() {
                var that = this,
                    bc;
                _each(that.panes, function(i, pane) {
                    bc = pane.borderCoords;
                    if (that.panesBackground[i] != null)
                        that.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 = Math.max(bc.right - bc.left, 0);
                bc.height = Math.max(bc.bottom - bc.top, 0)
            },
            _drawPanesBorders: function(panesBorderOptions) {
                var that = this,
                    rotated = that.themeManager.getOptions('rotated');
                that._panesBorderGroup && (that._panesBorderGroup.detach(), that._panesBorderGroup.clear());
                _each(that.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
                        };
                    that._calcPaneBorderCoords(pane, rotated);
                    if (!borderOptions.visible)
                        return;
                    bc = pane.borderCoords;
                    that.renderer.createSegmentRect(bc.left, bc.top, bc.width, bc.height, 0, borderOptions, attr).append(that._panesBorderGroup)
                });
                that._panesBorderGroup.append()
            },
            _createClipRect: function(clipArray, index, left, top, width, height) {
                var that = this,
                    clipRect = clipArray[index];
                if (!clipRect) {
                    clipRect = that.renderer.createClipRect(left, top, width, height);
                    clipArray[index] = clipRect
                }
                else
                    clipRect.updateRectangle({
                        x: left,
                        y: top,
                        width: width,
                        height: height
                    });
                clipRect.append()
            },
            _createClipRectsForPanes: function() {
                var that = this,
                    canvas = that.canvas;
                _each(that.panes, function(i, pane) {
                    var hasFinancialSeries = false,
                        bc = pane.borderCoords,
                        left = bc.left,
                        top = bc.top,
                        width = bc.width,
                        height = bc.height;
                    that._createClipRect(that.panesClipRects, i, left, top, width, height);
                    _each(that.series, function(_, series) {
                        if (series.pane === pane.name && series.isFinancialSeries())
                            hasFinancialSeries = true
                    });
                    if (hasFinancialSeries) {
                        if (that.themeManager.getOptions('rotated')) {
                            top = 0;
                            height = canvas.height
                        }
                        else {
                            left = 0;
                            width = canvas.width
                        }
                        that._createClipRect(that.financialPanesClipRects, i, left, top, width, height)
                    }
                    else
                        that.financialPanesClipRects.push(null)
                })
            },
            _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.themeManager.getOptions('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
            },
            _getTranslator: function(paneName, axisName) {
                var paneTrans = this.translators[paneName],
                    foundTranslator = null;
                if (!paneTrans)
                    return foundTranslator;
                foundTranslator = paneTrans[axisName];
                if (!foundTranslator)
                    _each(paneTrans, function(axis, trans) {
                        foundTranslator = trans;
                        return false
                    });
                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].val.pane === paneName && ranges[i].val.axis === axisName) {
                        foundRange = ranges[i];
                        break
                    }
                if (!foundRange)
                    for (i = 0; i < rangesNumber; i++)
                        if (ranges[i].val.pane === paneName) {
                            foundRange = ranges[i];
                            break
                        }
                return foundRange
            },
            _handleSeriesPopulated: function(needRedraw) {
                var that = this;
                that._processSeriesFamilies();
                that._createLegend();
                that._populateBusinessRange();
                that._processValueAxisFormat();
                that._updateTracker();
                that._endLoading(function() {
                    needRedraw && that._render({force: true})
                })
            },
            _processValueAxisFormat: function() {
                var that = this,
                    valueAxes = that._valueAxes,
                    axesWithFullStackedFormat = [];
                _each(that.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();
                    else
                        this.resetAutoLabelFormat()
                })
            },
            zoomArgument: function(min, max) {
                var that = this,
                    zoomArg = that._argumentAxes[0].adjustZoomValues(min, max);
                that._zoomMinArg = zoomArg.min;
                that._zoomMaxArg = zoomArg.max;
                that._render({
                    force: true,
                    drawTitle: false,
                    drawLegend: false,
                    adjustAxes: false,
                    animate: false,
                    adjustSeriesLabels: false,
                    asyncSeriesRendering: false
                })
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-charts, file pieChart.js */
    (function($, DX, undefined) {
        var core = DX.viz.core,
            charts = DX.viz.charts,
            utils = DX.utils;
        charts.PieChart = charts.BaseChart.inherit({
            _createThemeManager: function() {
                return charts.factory.createThemeManager(this.option(), "pie")
            },
            _reinit: function(needRedraw) {
                var that = this;
                that.callBase();
                if (!that.series)
                    that._dataSpecificInit();
                that._endLoading(function() {
                    needRedraw && that._render({force: true})
                })
            },
            _populateBusinessRange: function() {
                var businessRanges = [],
                    series = this.series,
                    singleSeries = series[0],
                    range,
                    singleSeriesRange;
                this._disposeObjectsInArray("businessRanges");
                if (singleSeries) {
                    range = new core.Range({series: singleSeries});
                    singleSeriesRange = singleSeries.getRangeData();
                    range = range.addRange(singleSeriesRange.val);
                    if (!range.isDefined())
                        range.setStubData();
                    businessRanges.push(range)
                }
                this.businessRanges = businessRanges
            },
            _seriesVisibilytyChanged: function() {
                this.series[0].arrangePoints();
                this._populateBusinessRange();
                this._refresh()
            },
            _createTranslator: function(range) {
                return core.CoreFactory.createTranslator1D(range.min, range.max, 360, 0)
            },
            _populateSeries: function() {
                var that = this,
                    renderer = that.renderer,
                    themeManager = that.themeManager,
                    hasSeriesTemplate = !!themeManager.getOptions("seriesTemplate"),
                    seriesOptions = hasSeriesTemplate ? that._templatedSeries : that.option("series"),
                    allSeriesOptions = $.isArray(seriesOptions) ? seriesOptions : seriesOptions ? [seriesOptions] : [],
                    data,
                    particularSeriesOptions,
                    particularSeries,
                    seriesTheme;
                that._disposeSeries();
                that.series = [];
                themeManager.resetPalette();
                if (allSeriesOptions.length) {
                    particularSeriesOptions = $.extend(true, {}, allSeriesOptions[0]);
                    if (particularSeriesOptions.type && !utils.isString(particularSeriesOptions.type))
                        particularSeriesOptions.type = "";
                    data = particularSeriesOptions.data;
                    particularSeriesOptions.data = null;
                    particularSeriesOptions.incidentOccured = that._incidentOccured;
                    seriesTheme = themeManager.getOptions("series", particularSeriesOptions, true);
                    seriesTheme.seriesGroup = that._seriesGroup;
                    seriesTheme.trackerGroup = that._trackerGroup;
                    seriesTheme.seriesLabelsGroup = that._labelsGroup;
                    seriesTheme.seriesTrackerGroup = that._seriesTrackerGroup;
                    seriesTheme.markerTrackerGroup = that._markerTrackerGroup;
                    seriesTheme.visibilityChanged = $.proxy(this._seriesVisibilytyChanged, this);
                    seriesTheme.customizePoint = themeManager.getOptions("customizePoint");
                    seriesTheme.customizeLabel = themeManager.getOptions("customizeLabel");
                    particularSeries = core.CoreFactory.createSeries(renderer, seriesTheme);
                    if (!particularSeries.isUpdated)
                        that._incidentOccured("E2101", [seriesTheme.type]);
                    else {
                        that._processSingleSeries(particularSeries);
                        that.series.push(particularSeries)
                    }
                    particularSeriesOptions.data = data
                }
                return that.series
            },
            _processSingleSeries: function(singleSeries) {
                singleSeries.arrangePoints()
            },
            _handleSeriesPopulated: function(needRedraw) {
                var that = this;
                that._populateBusinessRange();
                that._createLegend();
                that._updateTracker();
                that._endLoading(function() {
                    needRedraw && that._render({
                        force: true,
                        recreateCanvas: true
                    })
                })
            },
            _createLegend: function() {
                var that = this,
                    legendOptions = that.themeManager.getOptions("legend"),
                    data = $.map(that.series[0] ? that.series[0].getPoints() : [], function(item) {
                        return {
                                text: item.argument,
                                color: item.getColor(),
                                id: item.index,
                                states: item.getLegendStyles()
                            }
                    });
                legendOptions._incidentOccured = that._incidentOccured;
                that.legend = core.CoreFactory.createLegend(data, legendOptions, that.renderer, that._legendGroup)
            },
            _render: function(drawOptions) {
                var that = this,
                    singleSeries = that.series && that.series[0],
                    layoutManager = that.layoutManager,
                    hideLayoutLabels;
                drawOptions = that._prepareDrawOptions(drawOptions);
                that.callBase(drawOptions);
                if (that.stopRedraw) {
                    that.stopRedraw = false;
                    return
                }
                that._renderTitleAndLegend(drawOptions);
                if (layoutManager.needMoreSpaceForPanesCanvas([that])) {
                    layoutManager.updateDrawnElements([], [], that.canvas, that.dirtyCanvas, [that]);
                    if (that.chartTitle)
                        that.layoutManager.correctSizeElement(that.chartTitle, that.canvas);
                    that._updateCanvasClipRect(that.dirtyCanvas)
                }
                layoutManager.placeDrawnElements(that.canvas);
                if (singleSeries) {
                    hideLayoutLabels = layoutManager.needMoreSpaceForPanesCanvas([that]) && !that.themeManager.getOptions("adaptiveLayout").keepLabels;
                    layoutManager.applyPieChartSeriesLayout(that.canvas, singleSeries, true);
                    that._seriesGroup.append();
                    that._labelsGroup.append();
                    singleSeries.canvas = that.canvas;
                    singleSeries.resetLabelEllipsis();
                    singleSeries.draw(that._createTranslator(that.businessRanges[0], that.canvas), drawOptions.animate && that.renderer.animationEnabled(), hideLayoutLabels);
                    if (singleSeries.redraw) {
                        that.renderer.stopAllAnimations(true);
                        layoutManager.applyPieChartSeriesLayout(that.canvas, singleSeries, hideLayoutLabels);
                        singleSeries.draw(that._createTranslator(that.businessRanges[0], that.canvas), drawOptions.animate && that.renderer.animationEnabled(), hideLayoutLabels)
                    }
                    that._tooltipGroup.append();
                    that._trackerGroup.append();
                    that._createTooltip();
                    singleSeries.drawTrackers();
                    that.tracker._prepare("pieChart")
                }
                that._dataSource && that._dataSource.isLoaded() && !drawOptions.isResize && that.hideLoadingIndicator();
                that._drawn();
                that._handleRenderComplete()
            },
            getSeries: function getSeries() {
                return this.series && this.series[0]
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-charts, file layoutManager.js */
    (function($, DX, undefined) {
        var isNumber = DX.utils.isNumber,
            math = Math,
            decreaseGaps = DevExpress.viz.core.utils.decreaseGaps,
            CONNECTOR_MARGIN = 10,
            round = math.round;
        DX.viz.charts.LayoutManager = DX.Class.inherit(function() {
            var ctor = function(options) {
                    this.verticalElements = [];
                    this.horizontalElements = [];
                    this._options = options
                };
            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 placeElementAndCutCanvas = function(elements, canvas) {
                    $.each(elements, function(_, element) {
                        var shiftX,
                            shiftY,
                            options = element.getLayoutOptions(),
                            length = getLength(options.cutLayoutSide);
                        if (!options.width)
                            return;
                        switch (options.horizontalAlignment) {
                            case"left":
                                shiftX = canvas.left;
                                break;
                            case"center":
                                shiftX = (canvas.width - canvas.left - canvas.right - options.width) / 2 + canvas.left;
                                break;
                            case"right":
                                shiftX = canvas.width - canvas.right - options.width;
                                break
                        }
                        switch (options.verticalAlignment) {
                            case"top":
                                shiftY = canvas.top;
                                break;
                            case"bottom":
                                shiftY = canvas.height - canvas.bottom - options.height;
                                break
                        }
                        element.shift(round(shiftX), round(shiftY));
                        canvas[options.cutLayoutSide] += options[length];
                        setCanvasValues(canvas)
                    })
                };
            var drawElements = function(elements, canvas) {
                    var that = this,
                        verticalElements = that.verticalElements = [],
                        horizontalElements = that.horizontalElements = [];
                    $.each(elements, function(_, element) {
                        var freeHeight = canvas.height - canvas.top - canvas.bottom,
                            freeWidth = canvas.width - canvas.left - canvas.right,
                            options,
                            length,
                            arrayElements;
                        element.setSize({
                            height: freeHeight,
                            width: freeWidth
                        });
                        element.draw();
                        options = element.getLayoutOptions();
                        length = getLength(options.cutLayoutSide);
                        arrayElements = length === "width" ? horizontalElements : verticalElements;
                        arrayElements.push(element);
                        canvas[options.cutLayoutSide] += options[length];
                        setCanvasValues(canvas)
                    })
                };
            var getLength = function(side) {
                    var length = "height";
                    if (side === "left" || side === "right")
                        length = "width";
                    return length
                };
            var updatePanesCanvases = function(panes, canvas, rotated) {
                    var pane,
                        i,
                        paneSpaceHeight = canvas.height - canvas.top - canvas.bottom,
                        paneSpaceWidth = canvas.width - canvas.left - canvas.right,
                        weightSum = 0,
                        padding = panes.padding || 10;
                    for (i = 0; i < panes.length; i++) {
                        pane = panes[i];
                        pane.weight = pane.weight || 1;
                        weightSum = weightSum + pane.weight
                    }
                    rotated ? createPanes(panes, paneSpaceWidth, "left", "right") : createPanes(panes, paneSpaceHeight, "top", "bottom");
                    function createPanes(panes, paneSpace, startName, endName) {
                        var distributedSpace = 0,
                            oneWeight = (paneSpace - padding * (panes.length - 1)) / weightSum;
                        $.each(panes, function(_, pane) {
                            var calcLength = round(pane.weight * oneWeight);
                            pane.canvas = pane.canvas || {};
                            $.extend(pane.canvas, {
                                deltaLeft: 0,
                                deltaRight: 0,
                                deltaTop: 0,
                                deltaBottom: 0
                            }, canvas);
                            pane.canvas[startName] = canvas[startName] + distributedSpace;
                            pane.canvas[endName] = canvas[endName] + (paneSpace - calcLength - distributedSpace);
                            distributedSpace = distributedSpace + calcLength + padding;
                            setCanvasValues(pane.canvas)
                        })
                    }
                };
            var applyPieChartSeriesLayout = function(canvas, singleSeries, hideLayoutLabels) {
                    var paneSpaceHeight = canvas.height - canvas.top - canvas.bottom,
                        paneSpaceWidth = canvas.width - canvas.left - canvas.right,
                        paneCenterX = paneSpaceWidth / 2 + canvas.left,
                        paneCenterY = paneSpaceHeight / 2 + canvas.top,
                        accessibleRadius = Math.min(paneSpaceWidth, paneSpaceHeight) / 2,
                        minR = 0.7 * accessibleRadius,
                        innerRadius = getInnerRadius(singleSeries);
                    if (!hideLayoutLabels)
                        $.each(singleSeries.getPoints(), function(_, point) {
                            if (point._label.hasText() && point.isVisible()) {
                                var labelBBox = point._label._getOutsideGroupLabelPosition(),
                                    nearestX = getNearestCoord(labelBBox.x, labelBBox.x + labelBBox.width, paneCenterX),
                                    nearestY = getNearestCoord(labelBBox.y, labelBBox.y + labelBBox.height, paneCenterY),
                                    minRadiusWithLabels = Math.max(getLengthFromCenter(nearestX, nearestY) - CONNECTOR_MARGIN, minR);
                                accessibleRadius = Math.min(accessibleRadius, minRadiusWithLabels)
                            }
                            point._label.setPosition(point._label.originalPosition)
                        });
                    else
                        $.each(singleSeries.getPoints(), function(_, point) {
                            if (singleSeries.getOptions().label.position === "inside")
                                return false;
                            point._label.originalPosition = point._label.getPosition();
                            point._label.setPosition('outside')
                        });
                    singleSeries.correctPosition({
                        centerX: math.floor(paneCenterX),
                        centerY: math.floor(paneCenterY),
                        radiusInner: math.floor(accessibleRadius * innerRadius),
                        radiusOuter: math.floor(accessibleRadius)
                    });
                    function getNearestCoord(firstCoord, secondCoord, pointCenterCoord) {
                        var nearestCoord;
                        if (pointCenterCoord < firstCoord)
                            nearestCoord = firstCoord;
                        else if (secondCoord < pointCenterCoord)
                            nearestCoord = secondCoord;
                        else
                            nearestCoord = pointCenterCoord;
                        return nearestCoord
                    }
                    function getLengthFromCenter(x, y) {
                        return Math.sqrt(Math.pow(x - paneCenterX, 2) + Math.pow(y - paneCenterY, 2))
                    }
                    function getInnerRadius(series) {
                        var innerRadius;
                        if (singleSeries.type === 'pie')
                            innerRadius = 0;
                        else {
                            innerRadius = singleSeries.innerRadius;
                            if (!isNumber(innerRadius))
                                innerRadius = 0.5;
                            else {
                                innerRadius = Number(innerRadius);
                                if (innerRadius < 0.2)
                                    innerRadius = 0.2;
                                if (innerRadius > 0.8)
                                    innerRadius = 0.8
                            }
                        }
                        return innerRadius
                    }
                };
            var isValidBox = function isValidBox(box) {
                    return !!(box.x || box.y || box.width || box.height)
                };
            var correctDeltaMarginValue = function(panes, marginSides) {
                    var axisPanePosition,
                        canvasCell,
                        canvas,
                        deltaSide,
                        requireAxesRedraw;
                    $.each(panes, function(_, pane) {
                        canvas = pane.canvas;
                        $.each(marginSides, function(_, side) {
                            deltaSide = 'delta' + side;
                            canvas[deltaSide] = Math.max(canvas[deltaSide] - (canvas[side.toLowerCase()] - canvas['original' + side]), 0);
                            if (canvas[deltaSide] > 0)
                                requireAxesRedraw = true
                        })
                    });
                    return requireAxesRedraw
                };
            var getPane = function getPane(name, panes) {
                    var findPane = panes[0];
                    $.each(panes, function(_, pane) {
                        if (name === pane.name)
                            findPane = pane
                    });
                    return findPane
                };
            var applyAxesLayout = function(axes, panes, rotated) {
                    var that = this,
                        canvas,
                        axisPanePosition,
                        axisPosition,
                        canvasCell,
                        box,
                        delta,
                        axis,
                        axisLength,
                        direction,
                        directionMultiplier,
                        someDirection = [],
                        pane,
                        i;
                    $.each(panes, function(_, pane) {
                        $.extend(pane.canvas, {
                            deltaLeft: 0,
                            deltaRight: 0,
                            deltaTop: 0,
                            deltaBottom: 0
                        })
                    });
                    for (i = 0; i < axes.length; i++) {
                        axis = axes[i];
                        axisPosition = axis.options.position || 'left';
                        axis.delta = {};
                        box = axis.getBoundingRect();
                        pane = getPane(axis.pane, panes);
                        canvas = pane.canvas;
                        if (!isValidBox(box))
                            continue;
                        direction = "delta" + axisPosition.slice(0, 1).toUpperCase() + axisPosition.slice(1);
                        switch (axisPosition) {
                            case"right":
                                directionMultiplier = 1;
                                canvas.deltaLeft += axis.padding ? axis.padding.left : 0;
                                break;
                            case"left":
                                directionMultiplier = -1;
                                canvas.deltaRight += axis.padding ? axis.padding.right : 0;
                                break;
                            case"top":
                                directionMultiplier = -1;
                                canvas.deltaBottom += axis.padding ? axis.padding.bottom : 0;
                                break;
                            case"bottom":
                                directionMultiplier = 1;
                                canvas.deltaTop += axis.padding ? axis.padding.top : 0;
                                break
                        }
                        switch (axisPosition) {
                            case"right":
                            case"left":
                                if (!box.isEmpty) {
                                    delta = box.y + box.height - (canvas.height - canvas.originalBottom);
                                    if (delta > 0) {
                                        that.requireAxesRedraw = true;
                                        canvas.deltaBottom += delta
                                    }
                                    delta = canvas.originalTop - box.y;
                                    if (delta > 0) {
                                        that.requireAxesRedraw = true;
                                        canvas.deltaTop += delta
                                    }
                                }
                                axisLength = box.width;
                                someDirection = ['Left', 'Right'];
                                break;
                            case"top":
                            case"bottom":
                                if (!box.isEmpty) {
                                    delta = box.x + box.width - (canvas.width - canvas.originalRight);
                                    if (delta > 0) {
                                        that.requireAxesRedraw = true;
                                        canvas.deltaRight += delta
                                    }
                                    delta = canvas.originalLeft - box.x;
                                    if (delta > 0) {
                                        that.requireAxesRedraw = true;
                                        canvas.deltaLeft += delta
                                    }
                                }
                                someDirection = ['Bottom', 'Top'];
                                axisLength = box.height;
                                break
                        }
                        if (!axis.delta[axisPosition] && canvas[direction] > 0)
                            canvas[direction] += axis.getMultipleAxesSpacing();
                        axis.delta[axisPosition] = axis.delta[axisPosition] || 0;
                        axis.delta[axisPosition] += canvas[direction] * directionMultiplier;
                        canvas[direction] += axisLength
                    }
                    that.requireAxesRedraw = correctDeltaMarginValue(panes, someDirection) || that.requireAxesRedraw;
                    this.stopDrawAxes = applyFoundExceedings(panes, rotated)
                };
            var applyVerticalAxesLayout = function(axes) {
                    var chart = this.chart;
                    this.applyAxesLayout(axes, chart.panes, chart.option('rotated'))
                };
            var applyHorizontalAxesLayout = function(axes) {
                    var chart = this.chart;
                    axes.reverse();
                    this.applyAxesLayout(axes, chart.panes, chart.option('rotated'));
                    axes.reverse()
                };
            var placeDrawnElements = function(canvas) {
                    var that = this,
                        horizontalElements = that.horizontalElements,
                        verticalElements = that.verticalElements;
                    correctElementsPosition(horizontalElements, 'width');
                    placeElementAndCutCanvas(horizontalElements, canvas);
                    correctElementsPosition(verticalElements, 'height');
                    placeElementAndCutCanvas(verticalElements, canvas);
                    function correctElementsPosition(elements, direction) {
                        $.each(elements, function(_, element) {
                            var options = element.getLayoutOptions(),
                                side = options.cutLayoutSide;
                            canvas[side] -= options[direction]
                        })
                    }
                };
            var needMoreSpaceForPanesCanvas = function(panes, rotated) {
                    var that = this,
                        needHorizontalSpace = 0,
                        needVerticalSpace = 0;
                    $.each(panes, function(_, pane) {
                        var paneCanvas = pane.canvas,
                            needPaneHorizonralSpace = that._options.width - (paneCanvas.width - paneCanvas.left - paneCanvas.right),
                            needPaneVerticalSpace = that._options.height - (paneCanvas.height - paneCanvas.top - paneCanvas.bottom);
                        if (rotated) {
                            needHorizontalSpace += needPaneHorizonralSpace > 0 ? needPaneHorizonralSpace : 0;
                            needVerticalSpace = Math.max(needPaneVerticalSpace > 0 ? needPaneVerticalSpace : 0, needVerticalSpace)
                        }
                        else {
                            needHorizontalSpace = Math.max(needPaneHorizonralSpace > 0 ? needPaneHorizonralSpace : 0, needHorizontalSpace);
                            needVerticalSpace += needPaneVerticalSpace > 0 ? needPaneVerticalSpace : 0
                        }
                    });
                    return needHorizontalSpace > 0 || needVerticalSpace > 0 ? {
                            width: needHorizontalSpace,
                            height: needVerticalSpace
                        } : false
                };
            var updateDrawnElements = function(argumentAxis, valueAxis, canvas, dirtyCanvas, panes, rotated) {
                    var that = this,
                        needRemoveSpace,
                        saveDirtyCanvas = $.extend({}, dirtyCanvas),
                        verticalAxes = rotated ? argumentAxis : valueAxis,
                        horizontalAxes = rotated ? valueAxis : argumentAxis;
                    needRemoveSpace = this.needMoreSpaceForPanesCanvas(panes, rotated);
                    if (!needRemoveSpace)
                        return;
                    needRemoveSpace.height = decreaseGaps(dirtyCanvas, ["top", "bottom"], needRemoveSpace.height);
                    needRemoveSpace.width = decreaseGaps(dirtyCanvas, ["left", "right"], needRemoveSpace.width);
                    canvas.top -= saveDirtyCanvas.top - dirtyCanvas.top;
                    canvas.bottom -= saveDirtyCanvas.bottom - dirtyCanvas.bottom;
                    canvas.left -= saveDirtyCanvas.left - dirtyCanvas.left;
                    canvas.right -= saveDirtyCanvas.right - dirtyCanvas.right;
                    updateElements(that.horizontalElements, "width", "height");
                    updateElements(that.verticalElements, "height", "width");
                    updateAxis(verticalAxes, "width");
                    updateAxis(horizontalAxes, "height");
                    function updateAxis(axes, side) {
                        if (axes && needRemoveSpace[side] > 0) {
                            $.each(axes, function(i, axis) {
                                var bbox = axis.getBoundingRect();
                                axis.updateSize();
                                needRemoveSpace[side] -= bbox[side] - axis.getBoundingRect()[side]
                            });
                            if (needRemoveSpace[side] > 0)
                                $.each(axes, function(_, axis) {
                                    axis.updateSize(true)
                                })
                        }
                    }
                    function updateElements(elements, length, otherLength) {
                        $.each(elements, function(_, element) {
                            var options = element.getLayoutOptions(),
                                side = options.cutLayoutSide,
                                freeSpaceWidth = dirtyCanvas.width - dirtyCanvas.left - dirtyCanvas.right,
                                freeSpaceHeight = dirtyCanvas.height - dirtyCanvas.top - dirtyCanvas.bottom,
                                updateObject = {};
                            element.setSize({
                                width: freeSpaceWidth,
                                height: freeSpaceHeight
                            });
                            updateObject[otherLength] = 0;
                            updateObject[length] = needRemoveSpace[length];
                            element.changeSize(updateObject);
                            canvas[side] -= options[length] - element.getLayoutOptions()[length];
                            needRemoveSpace[length] -= options[length] - element.getLayoutOptions()[length]
                        })
                    }
                };
            var correctSizeElement = function(element, canvas) {
                    element.setSize({
                        width: canvas.width - canvas.right - canvas.left,
                        height: canvas.width - canvas.right - canvas.left
                    });
                    element.changeSize({
                        width: 0,
                        height: 0
                    })
                };
            var applyFoundExceedings = function applyFoundExceedings(panes, rotated) {
                    var col,
                        row,
                        stopDrawAxes,
                        maxLeft = 0,
                        maxRight = 0,
                        maxTop = 0,
                        maxBottom = 0,
                        maxColNumber = 0;
                    $.each(panes, function(_, pane) {
                        maxLeft = Math.max(maxLeft, pane.canvas.deltaLeft);
                        maxRight = Math.max(maxRight, pane.canvas.deltaRight);
                        maxTop = Math.max(maxTop, pane.canvas.deltaTop);
                        maxBottom = Math.max(maxBottom, pane.canvas.deltaBottom)
                    });
                    if (rotated)
                        $.each(panes, function(_, pane) {
                            pane.canvas.top += maxTop;
                            pane.canvas.bottom += maxBottom;
                            pane.canvas.right += pane.canvas.deltaRight;
                            pane.canvas.left += pane.canvas.deltaLeft
                        });
                    else
                        $.each(panes, function(_, pane) {
                            pane.canvas.top += pane.canvas.deltaTop;
                            pane.canvas.bottom += pane.canvas.deltaBottom;
                            pane.canvas.right += maxRight;
                            pane.canvas.left += maxLeft
                        });
                    $.each(panes, function(_, pane) {
                        if (pane.canvas.top + pane.canvas.bottom > pane.canvas.height)
                            stopDrawAxes = true;
                        if (pane.canvas.left + pane.canvas.right > pane.canvas.width)
                            stopDrawAxes = true
                    });
                    return stopDrawAxes
                };
            return {
                    ctor: ctor,
                    update: update,
                    drawElements: drawElements,
                    updatePanesCanvases: updatePanesCanvases,
                    applyVerticalAxesLayout: applyVerticalAxesLayout,
                    applyHorizontalAxesLayout: applyHorizontalAxesLayout,
                    applyAxesLayout: applyAxesLayout,
                    applyPieChartSeriesLayout: applyPieChartSeriesLayout,
                    dispose: dispose,
                    updateDrawnElements: updateDrawnElements,
                    placeDrawnElements: placeDrawnElements,
                    needMoreSpaceForPanesCanvas: needMoreSpaceForPanesCanvas,
                    correctSizeElement: correctSizeElement
                }
        }())
    })(jQuery, DevExpress);
    /*! Module viz-charts, file multiAxesSynchronizer.js */
    (function($, DX, undefined) {
        var Range = DX.viz.core.Range,
            utils = DX.utils,
            adjustValueUtils = utils.adjustValue,
            applyPrecisionByMinDeltaUtils = utils.applyPrecisionByMinDelta,
            isDefinedUtils = utils.isDefined,
            math = Math,
            mathFloor = math.floor,
            mathMax = math.max,
            MIN_RANGE_FOR_ADJUST_BOUNDS = 0.1;
        var getValueAxesPerPanes = function(valueAxes) {
                var result = {};
                $.each(valueAxes, function(_, axis) {
                    var pane = axis.pane;
                    if (!result[pane])
                        result[pane] = [];
                    result[pane].push(axis)
                });
                return result
            };
        var restoreOriginalBusinessRange = function(axis) {
                var businessRange;
                if (!axis.translator._originalBusinessRange)
                    axis.translator._originalBusinessRange = new Range(axis.translator.getBusinessRange());
                else {
                    businessRange = new Range(axis.translator._originalBusinessRange);
                    axis.translator.updateBusinessRange(businessRange);
                    axis.setRange(businessRange)
                }
            };
        var linearConvertor = {
                transform: function(v, b) {
                    return utils.getLog(v, b)
                },
                addInterval: function(v, i) {
                    return v + i
                },
                getInterval: function(base, tickInterval) {
                    return tickInterval
                },
                adjustValue: mathFloor
            };
        var logConvertor = {
                transform: function(v, b) {
                    return utils.raiseTo(v, b)
                },
                addInterval: function(v, i) {
                    return v * i
                },
                getInterval: function(base, tickInterval) {
                    return math.pow(base, tickInterval)
                },
                adjustValue: adjustValueUtils
            };
        var convertAxisInfo = function(axisInfo, convertor) {
                if (!axisInfo.isLogarithmic)
                    return;
                var base = axisInfo.logarithmicBase,
                    tickValues = axisInfo.tickValues,
                    tick,
                    ticks = [],
                    interval;
                axisInfo.minValue = convertor.transform(axisInfo.minValue, base);
                axisInfo.oldMinValue = convertor.transform(axisInfo.oldMinValue, base);
                axisInfo.maxValue = convertor.transform(axisInfo.maxValue, base);
                axisInfo.oldMaxValue = convertor.transform(axisInfo.oldMaxValue, base);
                axisInfo.tickInterval = math.round(axisInfo.tickInterval);
                if (axisInfo.tickInterval < 1)
                    axisInfo.tickInterval = 1;
                interval = convertor.getInterval(base, axisInfo.tickInterval);
                for (tick = convertor.adjustValue(convertor.transform(tickValues[0], base)); ticks.length < tickValues.length; tick = convertor.addInterval(tick, interval))
                    ticks.push(tick);
                ticks.tickInterval = axisInfo.tickInterval;
                axisInfo.tickValues = ticks
            };
        var populateAxesInfo = function(axes) {
                return $.map(axes, function(axis) {
                        restoreOriginalBusinessRange(axis);
                        var tickValues = axis.getTickValues(),
                            options = axis.options,
                            minValue,
                            maxValue,
                            axisInfo = null,
                            businessRange;
                        if (tickValues && tickValues.length > 0 && utils.isNumber(tickValues[0]) && options.type !== 'discrete') {
                            businessRange = axis.translator.getBusinessRange();
                            minValue = businessRange.minVisible;
                            maxValue = businessRange.maxVisible;
                            axisInfo = {
                                axis: axis,
                                isLogarithmic: options.type === 'logarithmic',
                                logarithmicBase: businessRange.base,
                                tickValues: tickValues,
                                minValue: minValue,
                                oldMinValue: minValue,
                                maxValue: maxValue,
                                oldMaxValue: maxValue,
                                inverted: businessRange.invert,
                                tickInterval: tickValues.tickInterval,
                                synchronizedValue: options.synchronizedValue
                            };
                            if (businessRange.stubData) {
                                axisInfo.stubData = true;
                                axisInfo.tickInterval = axisInfo.tickInterval || options.tickInterval;
                                axisInfo.isLogarithmic = false
                            }
                            convertAxisInfo(axisInfo, linearConvertor);
                            DX.utils.debug.assert(axisInfo.tickInterval !== undefined && axisInfo.tickInterval !== null, 'tickInterval was not provided')
                        }
                        return axisInfo
                    })
            };
        var updateTickValues = function(axesInfo) {
                var maxTicksCount = 0;
                $.each(axesInfo, function(_, axisInfo) {
                    maxTicksCount = mathMax(maxTicksCount, axisInfo.tickValues.length)
                });
                $.each(axesInfo, function(_, axisInfo) {
                    var ticksMultiplier,
                        ticksCount,
                        additionalStartTicksCount = 0,
                        synchronizedValue = axisInfo.synchronizedValue,
                        tickValues = axisInfo.tickValues,
                        tickInterval = axisInfo.tickInterval;
                    if (isDefinedUtils(synchronizedValue)) {
                        axisInfo.baseTickValue = synchronizedValue;
                        axisInfo.invertedBaseTickValue = synchronizedValue;
                        axisInfo.tickValues = [axisInfo.baseTickValue]
                    }
                    else {
                        if (tickValues.length > 1 && tickInterval) {
                            ticksMultiplier = mathFloor((maxTicksCount + 1) / tickValues.length);
                            ticksCount = ticksMultiplier > 1 ? mathFloor((maxTicksCount + 1) / ticksMultiplier) : maxTicksCount;
                            additionalStartTicksCount = mathFloor((ticksCount - tickValues.length) / 2);
                            while (additionalStartTicksCount > 0 && tickValues[0] !== 0) {
                                tickValues.unshift(applyPrecisionByMinDeltaUtils(tickValues[0], tickInterval, tickValues[0] - tickInterval));
                                additionalStartTicksCount--
                            }
                            while (tickValues.length < ticksCount)
                                tickValues.push(applyPrecisionByMinDeltaUtils(tickValues[0], tickInterval, tickValues[tickValues.length - 1] + tickInterval));
                            axisInfo.tickInterval = tickInterval / ticksMultiplier
                        }
                        axisInfo.baseTickValue = tickValues[0];
                        axisInfo.invertedBaseTickValue = tickValues[tickValues.length - 1]
                    }
                })
            };
        var getAxisRange = function(axisInfo) {
                return axisInfo.maxValue - axisInfo.minValue
            };
        var getMainAxisInfo = function(axesInfo) {
                for (var 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(_, axisInfo) {
                    var scale,
                        move,
                        mainAxisBaseValueOffset;
                    if (axisInfo !== mainAxisInfo) {
                        if (mainAxisInfo.tickInterval && axisInfo.tickInterval) {
                            if (axisInfo.stubData && isDefinedUtils(axisInfo.synchronizedValue)) {
                                axisInfo.oldMinValue = axisInfo.minValue = axisInfo.baseTickValue - (mainAxisInfo.baseTickValue - mainAxisInfo.minValue) / mainAxisInfo.tickInterval * axisInfo.tickInterval;
                                axisInfo.oldMaxValue = axisInfo.maxValue = axisInfo.baseTickValue - (mainAxisInfo.baseTickValue - mainAxisInfo.maxValue) / mainAxisInfo.tickInterval * axisInfo.tickInterval
                            }
                            scale = mainAxisInfo.tickInterval / getAxisRange(mainAxisInfo) / axisInfo.tickInterval * getAxisRange(axisInfo);
                            axisInfo.maxValue = axisInfo.minValue + getAxisRange(axisInfo) / scale
                        }
                        if (mainAxisInfo.inverted && !axisInfo.inverted || !mainAxisInfo.inverted && axisInfo.inverted)
                            mainAxisBaseValueOffset = mainAxisInfo.maxValue - mainAxisInfo.invertedBaseTickValue;
                        else
                            mainAxisBaseValueOffset = mainAxisInfo.baseTickValue - mainAxisInfo.minValue;
                        move = (mainAxisBaseValueOffset / getAxisRange(mainAxisInfo) - (axisInfo.baseTickValue - axisInfo.minValue) / getAxisRange(axisInfo)) * getAxisRange(axisInfo);
                        axisInfo.minValue -= move;
                        axisInfo.maxValue -= move
                    }
                })
            };
        var calculatePaddings = function(axesInfo) {
                var minPadding,
                    maxPadding,
                    startPadding = 0,
                    endPadding = 0;
                $.each(axesInfo, function(_, axisInfo) {
                    var inverted = axisInfo.inverted;
                    minPadding = axisInfo.minValue > axisInfo.oldMinValue ? (axisInfo.minValue - axisInfo.oldMinValue) / getAxisRange(axisInfo) : 0;
                    maxPadding = axisInfo.maxValue < axisInfo.oldMaxValue ? (axisInfo.oldMaxValue - axisInfo.maxValue) / getAxisRange(axisInfo) : 0;
                    startPadding = mathMax(startPadding, inverted ? maxPadding : minPadding);
                    endPadding = mathMax(endPadding, inverted ? minPadding : maxPadding)
                });
                return {
                        start: startPadding,
                        end: endPadding
                    }
            };
        var correctMinMaxValuesByPaddings = function(axesInfo, paddings) {
                $.each(axesInfo, function(_, info) {
                    var range = getAxisRange(info),
                        inverted = info.inverted;
                    info.minValue -= paddings[inverted ? 'end' : 'start'] * range;
                    info.maxValue += paddings[inverted ? 'start' : 'end'] * range;
                    if (range > MIN_RANGE_FOR_ADJUST_BOUNDS) {
                        info.minValue = math.min(info.minValue, adjustValueUtils(info.minValue));
                        info.maxValue = mathMax(info.maxValue, adjustValueUtils(info.maxValue))
                    }
                })
            };
        var updateTickValuesIfSyncronizedValueUsed = function(axesInfo) {
                var hasSyncronizedValue = false;
                $.each(axesInfo, function(_, info) {
                    hasSyncronizedValue = hasSyncronizedValue || isDefinedUtils(info.synchronizedValue)
                });
                $.each(axesInfo, function(_, info) {
                    var lastTickValue,
                        tickInterval = info.tickInterval,
                        tickValues = info.tickValues,
                        maxValue = info.maxValue,
                        minValue = info.minValue;
                    if (hasSyncronizedValue && tickInterval) {
                        while (tickValues[0] - tickInterval >= minValue)
                            tickValues.unshift(adjustValueUtils(tickValues[0] - tickInterval));
                        lastTickValue = tickValues[tickValues.length - 1];
                        while ((lastTickValue = lastTickValue + tickInterval) <= maxValue)
                            tickValues.push(utils.isExponential(lastTickValue) ? adjustValueUtils(lastTickValue) : utils.applyPrecisionByMinDelta(minValue, tickInterval, lastTickValue))
                    }
                    while (tickValues[0] < minValue)
                        tickValues.shift();
                    while (tickValues[tickValues.length - 1] > maxValue)
                        tickValues.pop()
                })
            };
        var applyMinMaxValues = function(axesInfo) {
                $.each(axesInfo, function(_, info) {
                    var axis = info.axis,
                        range = axis.translator.getBusinessRange();
                    if (range.min === range.minVisible)
                        range.min = info.minValue;
                    if (range.max === range.maxVisible)
                        range.max = info.maxValue;
                    range.minVisible = info.minValue;
                    range.maxVisible = info.maxValue;
                    if (isDefinedUtils(info.stubData))
                        range.stubData = info.stubData;
                    if (range.min > range.minVisible)
                        range.min = range.minVisible;
                    if (range.max < range.maxVisible)
                        range.max = range.maxVisible;
                    axis.translator.updateBusinessRange(range);
                    axis.setRange(range);
                    axis.setTickValues(info.tickValues)
                })
            };
        DX.viz.charts.multiAxesSynchronizer = {synchronize: function(valueAxes) {
                $.each(getValueAxesPerPanes(valueAxes), function(_, axes) {
                    var axesInfo,
                        paddings;
                    if (axes.length > 1) {
                        axesInfo = populateAxesInfo(axes);
                        if (axesInfo.length === 0 || !getMainAxisInfo(axesInfo))
                            return;
                        updateTickValues(axesInfo);
                        correctMinMaxValues(axesInfo);
                        paddings = calculatePaddings(axesInfo);
                        correctMinMaxValuesByPaddings(axesInfo, paddings);
                        updateTickValuesIfSyncronizedValueUsed(axesInfo);
                        $.each(axesInfo, function() {
                            convertAxisInfo(this, logConvertor)
                        });
                        applyMinMaxValues(axesInfo)
                    }
                })
            }}
    })(jQuery, DevExpress);
    /*! Module viz-charts, file tracker.js */
    (function($, DX) {
        var charts = DX.viz.charts,
            eventsConsts = DX.viz.core.series.helpers.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,
            HOVER_START_DELAY = 100,
            HOVER_HOLD_DELAY = 200,
            TOOLTIP_HOLD_TIMEOUT = 400,
            NONE_MODE = 'none';
        var processMode = function(mode) {
                return (mode + "").toLowerCase()
            };
        charts.Tracker = DX.Class.inherit({
            ctor: function(options) {
                this.__HOVER_HOLD_DELAY = HOVER_HOLD_DELAY;
                this.__TOOLTIP_HOLD_TIMEOUT = TOOLTIP_HOLD_TIMEOUT;
                this.__HOVER_START_DELAY = HOVER_START_DELAY;
                var that = this,
                    events = options.events = options.events || {},
                    getEventHandler = function(func) {
                        return func && func.call ? function() {
                                var eventContext = this,
                                    eventArgs = arguments;
                                setTimeout(function() {
                                    func.apply(eventContext, eventArgs)
                                })
                            } : null
                    };
                that._reinit(options);
                that.pointSelectionMode = that._prepareMode(options.pointSelectionMode);
                that.seriesSelectionMode = that._prepareMode(options.seriesSelectionMode);
                that.hoverStartDelay = 0;
                that.sensitivity = 7;
                if (that.pointSelectionMode === MULTIPLE_MODE) {
                    that._releaseSelectedPoint = that._releaseSelectedPointMultiMode;
                    that.selectedPoint = []
                }
                else
                    that._releaseSelectedPoint = that._releaseSelectedPointSingleMode;
                if (that.seriesSelectionMode === MULTIPLE_MODE) {
                    that._releaseSelectedSeries = that._releaseSelectedSeriesMultiMode;
                    that.selectedSeries = []
                }
                else
                    that._releaseSelectedSeries = that._releaseSelectedSeriesSingleMode;
                that.tooltipEnabled = options.tooltipEnabled;
                that.tooltipShown = options.tooltipShown;
                that.tooltipHidden = options.tooltipHidden;
                that.seriesClick = getEventHandler(events.seriesClick);
                that.pointClick = getEventHandler(events.pointClick);
                that.legendClick = getEventHandler(events.legendClick);
                that.argumentAxisClick = getEventHandler(events.argumentAxisClick);
                that.seriesHover = getEventHandler(events.seriesHover);
                that.seriesSelected = getEventHandler(events.seriesSelected);
                that.pointHover = getEventHandler(events.pointHover);
                that.seriesSelectionChanged = getEventHandler(events.seriesSelectionChanged);
                that.pointSelectionChanged = getEventHandler(events.pointSelectionChanged);
                that.seriesHoverChanged = getEventHandler(events.seriesHoverChanged);
                that.pointHoverChanged = getEventHandler(events.pointHoverChanged);
                that.pointSelected = getEventHandler(events.pointSelected);
                that.renderer = options.renderer;
                that.seriesTrackerGroup = options.seriesTrackerGroup;
                that.markerTrackerGroup = options.markerTrackerGroup;
                that.seriesGroup = options.seriesGroup;
                that.seriesGroup.on(eventsConsts.selectSeries, {tracker: that}, that._selectSeries);
                that.seriesGroup.on(eventsConsts.deselectSeries, {tracker: that}, that._deselectSeries);
                that.seriesGroup.on(eventsConsts.selectPoint, {tracker: that}, that._selectPoint);
                that.seriesGroup.on(eventsConsts.deselectPoint, {tracker: that}, that._deselectPoint);
                that.seriesGroup.on(eventsConsts.showPointTooltip, {tracker: that}, that._showPointTooltip);
                that.seriesGroup.on(eventsConsts.hidePointTooltip, {tracker: that}, that._hidePointTooltip);
                that.crossHairOptions = options.crossHairOptions
            },
            _clean: function() {
                var that = this;
                that.selectedPoint = that.pointSelectionMode === MULTIPLE_MODE ? [] : null;
                that.selectedSeries = that.seriesSelectionMode === MULTIPLE_MODE ? [] : null;
                that.hoveredPoint = null;
                that.hoveredSeries = null;
                that._hideTooltip(that.pointAtShownTooltip);
                that._clearTimeouts()
            },
            _reinit: function(options) {
                var that = this;
                options = options || {};
                if (that.storedSeries !== options.series) {
                    that.storedSeries = options.series || [];
                    that._clean()
                }
                else if (isDefined(that.storedSeries)) {
                    that._clearPointSelection();
                    that._clearHover(that);
                    that._clearTimeouts()
                }
                that.argumentAxis = options.argumentAxis || [];
                that.legendGroup = options.legendGroup;
                that.legendCallback = options.legendCallback || $.noop
            },
            _clearTimeouts: function() {
                var that = this,
                    _clearTimeout = clearTimeout;
                _clearTimeout(that.tooltipHoldTimeout);
                _clearTimeout(that.cmpCoordTimeout);
                _clearTimeout(that.hoverStartTimeOut);
                _clearTimeout(that.hoverHoldTimeOut)
            },
            dispose: function() {
                var that = this;
                that._clearTimeouts();
                clearTimeout(that.unlockMouseTimer);
                clearTimeout(that.lockClickTimer);
                $.each(that.argumentAxis, function(_, axis) {
                    axis._axisElementsGroup && axis._axisElementsGroup.off()
                });
                that.seriesTrackerGroup.off();
                that.markerTrackerGroup.off();
                that.legendGroup && that.legendGroup.off();
                that.seriesGroup.off();
                that.rootTracker && that.rootTracker.off();
                that.argumentAxis = null;
                that.seriesTrackerGroup = null;
                that.markerTrackerGroup = null;
                that.legendGroup = null;
                that.legendCallback = null;
                that.seriesGroup = null;
                that.crossHairOptions = null;
                that.selectedPoint = null;
                that.selectedSeries = null;
                that.hoveredSeries = null;
                that.hoveredPoint = null;
                that.storedSeries = null;
                that.argumentAxis = null;
                that.hoveredObject = null;
                that.pointAtShownTooltip = null
            },
            _prepareMode: function(mode) {
                mode = (mode || '').toLowerCase();
                return mode = mode !== SINGLE_MODE && mode !== MULTIPLE_MODE ? SINGLE_MODE : mode
            },
            _prepare: function(typeChart) {
                var that = this;
                that.rootTracker = that.renderer.getRoot();
                $.each(that.argumentAxis, function(_, axis) {
                    axis._axisElementsGroup && that._eventHandler(axis._axisElementsGroup, {
                        parser: that._getOptionsAxis,
                        condition: that._axisCondition,
                        execute: that._axisEvent
                    }, {
                        tracker: that,
                        axis: axis
                    })
                });
                that._eventHandler(that.seriesTrackerGroup, {
                    parser: that._getOptionsPointSeries,
                    condition: that._seriesCondition,
                    execute: that._seriesEvent
                }, {tracker: that});
                that._eventHandler(that.markerTrackerGroup, {
                    parser: that._getOptionsPointSeries,
                    condition: that._pointCondition,
                    execute: that._pointEvent
                }, {tracker: that});
                that.legendGroup && that._eventHandler(that.legendGroup, {
                    parser: that._getLegendData(typeChart),
                    condition: that._seriesCondition,
                    execute: that._getLegendEvent(typeChart)
                }, {tracker: that});
                that._eventHandler(that.rootTracker, {
                    parser: that._getOptionsCrossHair,
                    execute: that._crossHairEvent
                }, {tracker: that})
            },
            _getLegendData: function(typeChart) {
                return function(event) {
                        var target = $(event.target),
                            itemIndex = target.data('itemIndex'),
                            that = event.data.tracker,
                            mode = utils.isNumber(itemIndex) && target.data('mode');
                        if (event.type === 'mousemove')
                            return [that, event.pageX, event.pageY, event.offsetX, event.offsetY];
                        if (!utils.isNumber(itemIndex))
                            return null;
                        if (typeChart === 'pieChart')
                            return [that, that.storedSeries[0].getPoints()[itemIndex], mode, event];
                        else
                            return [that, that.storedSeries[itemIndex], mode, event]
                    }
            },
            _getLegendEvent: function(typeChart) {
                var that = this,
                    legendEvent;
                if (typeChart === 'pieChart')
                    legendEvent = $.extend({}, this._pointEvent, {
                        touchend: function(that, point, mode, event) {
                            if (!that.showHoldTooltip)
                                that._legendClick(that, point, true, event) || that._pointClick(that, point, true, event);
                            clearTimeout(that.tooltipHoldTimeout);
                            that._clickLock(that);
                            that._clearHover(that)
                        },
                        click: function(that, point, mode, event) {
                            that._legendClick(that, point, false, event) || that._pointClick(that, point, false, event)
                        }
                    });
                else
                    legendEvent = $.extend({}, this._seriesEvent, {
                        click: function(that, series, mode, event) {
                            that._legendClick(that, series, false, event) || that._seriesClick(that, series, false, event)
                        },
                        touchend: function(that, series, mode, event) {
                            that._legendClick(that, series, true, event) || that._seriesClick(that, series, true, event);
                            that._clickLock(that)
                        }
                    });
                this.__legendEvent = legendEvent;
                return legendEvent
            },
            _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
            },
            _getOptionsCrossHair: function(event) {
                var that = event.data.tracker;
                var rootOffset = utils.getRootOffset(that.renderer);
                var xe = event.pageX - rootOffset.left;
                var ye = event.pageY - rootOffset.top;
                return [that, xe, ye]
            },
            _getOptionsPointSeries: function(event) {
                var object = $(event.target).data('point') || $(event.target).data('series'),
                    that = event.data.tracker,
                    mode = object && processMode($(event.target).data('mode') || object.getOptions().hoverMode);
                if (event.type === 'mousemove')
                    return [that, event.pageX, event.pageY, event.offsetX, event.offsetY];
                if (!object)
                    return null;
                return [that, object, mode, event]
            },
            _getOptionsAxis: function(event) {
                var that = 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 [that, event.pageX, event.pageY];
                if (!axis)
                    return null;
                return [that, axis, mode, argument, event]
            },
            _pointEvent: {
                mouseover: function(that, point, mode) {
                    if (that.mouseLocked)
                        return;
                    that._setHoveredPoint(point, mode);
                    if (that.tooltipEnabled && point && point.getOptions())
                        that._compareCoords(that, function() {
                            that._showTooltip(that.tooltip, point)
                        })
                },
                mouseout: function(that, point, mode) {
                    if (that.mouseLocked)
                        return;
                    that._clearHover(that)
                },
                touchmove: function(that, point, mode) {
                    clearTimeout(that.tooltipHoldTimeout);
                    that.tooltipHoldTimeout = null;
                    that.showHoldTooltip = true
                },
                mousemove: function(that, pageX, pageY, offsetX, offsetY) {
                    that._setCurCoords(that, pageX, pageY)
                },
                touchstart: function(that, point, mode) {
                    that.showHoldTooltip = false;
                    that._mouseLock(that);
                    if (that.tooltipEnabled)
                        that.tooltipHoldTimeout = setTimeout(function() {
                            that.showHoldTooltip = true;
                            that._showTooltip(that.tooltip, point)
                        }, TOOLTIP_HOLD_TIMEOUT)
                },
                touchend: function(that, point, mode, event) {
                    if (!that.showHoldTooltip)
                        that._pointClick(that, point, true, event);
                    clearTimeout(that.tooltipHoldTimeout);
                    that._clickLock(that);
                    that._clearHover(that)
                },
                click: function(that, point, mode, event) {
                    that._pointClick(that, point, false, event)
                },
                mousedown: function(that, point, mode) {
                    that._pointEvent.touchstart(that, point, mode)
                },
                mouseup: function(that, point, mode, event) {
                    that._pointEvent.touchend(that, point, mode, event)
                }
            },
            _pointCondition: {
                mouseover: function(that, point, mode, event, func) {
                    if (mode === ALL_ARGUMENTS_POINTS_MODE && that.hoveredPoint && that.hoveredPoint.argument === point.argument) {
                        that.hoverHoldTimeOut = clearTimeout(that.hoverHoldTimeOut);
                        that.hoveredObject = point;
                        func(that, point, mode);
                        return
                    }
                    that._setHover(that, point, mode, func)
                },
                mouseout: function(that, point, mode, event, func) {
                    that._releaseHover(that, point, mode, func)
                },
                touchstart: !msPointerEnabled,
                touchend: !msPointerEnabled,
                mousedown: msPointerEnabled,
                mouseup: msPointerEnabled
            },
            _seriesEvent: {
                mouseover: function(that, series, mode) {
                    if (that.mouseLocked)
                        return;
                    that._setHoveredSeries(series, mode)
                },
                mouseout: function(that, series, mode) {
                    that._clearHover(that)
                },
                mousemove: function(that, pageX, pageY, offsetX, offsetY) {
                    that._setCurCoords(that, pageX, pageY)
                },
                touchstart: function(that) {
                    that._mouseLock(that)
                },
                touchend: function(that, series, _, event) {
                    that._seriesClick(that, series, true, event);
                    that._clickLock(that)
                },
                click: function(that, series, mode, event) {
                    that._seriesClick(that, series, false, event)
                },
                mousedown: function(that, point, mode) {
                    that._seriesEvent.touchstart(that, point, mode)
                },
                mouseup: function(that, point, mode) {
                    that._seriesEvent.touchend(that, point, mode)
                }
            },
            _crossHairEvent: {
                mousemove: function(that, x, y) {
                    if (!that.eventType) {
                        that.eventType = 'mouse';
                        return
                    }
                    else if (that.eventType === 'touch')
                        return;
                    else if (that.eventType === 'mouse') {
                        that._moveCrossHair(that, x, y);
                        that.eventType = null
                    }
                },
                mouseout: function(that) {
                    that._hideCrossHair(that);
                    that.eventType = null
                },
                touchstart: function(that, x, y) {
                    that.eventType = 'touch'
                },
                touchend: function(that, x, y) {
                    that.eventType = null
                },
                mousedown: function(that, x, y) {
                    that._crossHairEvent.touchstart(that, x, y)
                },
                mouseup: function(that, x, y) {
                    that._crossHairEvent.touchend(that, x, y)
                }
            },
            _hideCrossHair: function(that) {
                if (!that.crossHairOptions)
                    return;
                var horizontalLine = that.crossHairOptions.horizontalLine,
                    verticalLine = that.crossHairOptions.verticalLine;
                horizontalLine && horizontalLine.applySettings({visibility: 'hidden'});
                verticalLine && verticalLine.applySettings({visibility: 'hidden'})
            },
            _moveCrossHair: function(that, x, y) {
                if (!that.crossHairOptions)
                    return;
                var horizontalLine = that.crossHairOptions.horizontalLine,
                    verticalLine = that.crossHairOptions.verticalLine,
                    canvas = that.crossHairOptions.canvas || {};
                if (x > canvas.left && x < canvas.width - canvas.right && y > canvas.top && y < canvas.height - canvas.bottom) {
                    horizontalLine && horizontalLine.applySettings({visibility: 'visible'});
                    verticalLine && verticalLine.applySettings({visibility: 'visible'});
                    horizontalLine && horizontalLine.applySettings({translateY: y - canvas.top});
                    verticalLine && verticalLine.applySettings({translateX: x - canvas.left})
                }
                else {
                    horizontalLine && horizontalLine.applySettings({visibility: 'hidden'});
                    verticalLine && verticalLine.applySettings({visibility: 'hidden'})
                }
            },
            _seriesCondition: {
                mouseover: function(that, series, mode, event, func) {
                    that.hoverStartDelay = 0;
                    that._setHover(that, series, mode, func)
                },
                mouseout: function(that, series, mode, event, func) {
                    that.hoverStartDelay = HOVER_START_DELAY;
                    that._releaseHover(that, series, mode, func)
                },
                touchstart: !msPointerEnabled,
                touchend: !msPointerEnabled,
                mousedown: msPointerEnabled,
                mouseup: msPointerEnabled
            },
            _axisEvent: {
                mouseover: function(that, axis, argument) {
                    if (that.mouseLocked || isDefined(that.hoveredArgument) && that.hoveredArgument === argument)
                        return;
                    that._clearHover(that);
                    if (isDefined(that.hoveredArgument))
                        that._toAllArgumentPoints(that.hoveredArgument, 'releasePointHoverState');
                    that._toAllArgumentPoints(argument, 'setPointHoverState');
                    that.hoveredArgument = argument
                },
                mouseout: function(that, axis) {
                    if (that.mouseLocked || !isDefined(that.hoveredArgument))
                        return;
                    that._toAllArgumentPoints(that.hoveredArgument, 'releasePointHoverState');
                    that.hoveredArgument = null
                },
                mousemove: function(that, pageX, pageY) {
                    that._setCurCoords(that, pageX, pageY)
                },
                touchstart: function(that) {
                    that._mouseLock(that)
                },
                touchend: function(that, axis, mode, argument, event) {
                    that._argumentAxisClick(that, axis, argument, true, event);
                    that._clearHover(that);
                    that._clickLock(that)
                },
                click: function(that, axis, mode, argument, event) {
                    that._clearHover(that);
                    that._argumentAxisClick(that, axis, argument, false, event)
                },
                mousedown: function(that) {
                    that._axisEvent.touchstart(that)
                },
                mouseup: function(that, axis, mode, argument, event) {
                    that._axisEvent.touchend(that, axis, mode, argument, event)
                }
            },
            _axisCondition: {
                mouseover: function(that, axis, mode, argument, event, func) {
                    that._hideCrossHair(that);
                    if (mode === ALL_ARGUMENTS_POINTS_MODE)
                        that._setHover(that, axis, argument, func)
                },
                mouseout: function(that, axis, mode, argument, event, func) {
                    that._releaseHover(that, axis, argument, func)
                },
                touchstart: !msPointerEnabled,
                touchend: !msPointerEnabled,
                mousedown: msPointerEnabled,
                mouseup: msPointerEnabled
            },
            _setHover: function(that, object, mode, func) {
                if (object === that.hoveredObject) {
                    that.hoverHoldTimeOut = clearTimeout(that.hoverHoldTimeOut);
                    if (mode === object.lastHoverMode)
                        return
                }
                if (that.mouseLocked)
                    return;
                clearTimeout(that.cmpCoordTimeout);
                clearTimeout(that.hoverStartTimeOut);
                that.hoverStartTimeOut = setTimeout(function() {
                    clearTimeout(that.hoverHoldTimeOut);
                    that.hoveredObject = object;
                    func(that, object, mode)
                }, that.hoverStartDelay)
            },
            _releaseHover: function(that, object, mode, func) {
                if (that.mouseLocked)
                    return;
                clearTimeout(that.cmpCoordTimeout);
                clearTimeout(that.hoverStartTimeOut);
                if (object === that.hoveredObject)
                    that.hoverHoldTimeOut = setTimeout(function() {
                        that.hoveredObject = null;
                        func(that, object, mode);
                        that.hoverStartDelay = 0
                    }, HOVER_HOLD_DELAY)
            },
            _compareCoords: function(that, func) {
                clearTimeout(that.cmpCoordTimeout);
                if (Math.abs(that.pX - that.cX) + Math.abs(that.pY - that.cY) < that.sensitivity) {
                    if (that.mouseLocked)
                        return;
                    func()
                }
                else {
                    that.pX = that.cX;
                    that.pY = that.cY;
                    that.cmpCoordTimeout = setTimeout(function() {
                        that._compareCoords(that, func)
                    }, that.hoverStartDelay === 0 ? HOVER_START_DELAY : 0)
                }
            },
            _seriesClick: function(that, series, touchEvent, event) {
                if (that.lockClick && !touchEvent)
                    return;
                that.seriesClick && that.seriesClick.call(series, series, event)
            },
            _legendClick: function(that, series, touchEvent, event) {
                var legendClick = that.legendClick;
                if (that.lockClick && !touchEvent)
                    return true;
                if (legendClick) {
                    legendClick.call(series, series, event);
                    return true
                }
                return false
            },
            _pointClick: function(that, point, touchEvent, event) {
                var series = point.series;
                if (that.lockClick && !touchEvent)
                    return;
                if (that.pointClick) {
                    that.pointClick.call(point, point, event);
                    return
                }
                that.seriesClick && that.seriesClick.call(series, series, event);
                return
            },
            _argumentAxisClick: function(that, axis, argument, touchEvent, event) {
                if (that.lockClick && !touchEvent)
                    return;
                that.argumentAxisClick && that.argumentAxisClick.call(axis, axis, argument, event)
            },
            _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 that = event.data.tracker;
                that._showTooltip(that.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();
                if (this.pointAtShownTooltip) {
                    this.pointAtShownTooltip = null;
                    isFunction(this.tooltipHidden) && this.tooltipHidden.call(point, point)
                }
            },
            _showTooltip: function(tooltip, point) {
                var tooltipFormatObject = point.getTooltipFormatObject(tooltip);
                if (!isDefined(tooltipFormatObject.valueText) && !tooltipFormatObject.points || !point.isVisible())
                    return;
                this.pointAtShownTooltip && this._hideTooltip(this.pointAtShownTooltip);
                if (point && point.getOptions()) {
                    var tooltipCoords = point.getTooltipCoords();
                    if (!tooltip.prepare(tooltipFormatObject, {
                        x: tooltipCoords.x,
                        y: tooltipCoords.y,
                        offset: tooltipCoords.offset
                    }))
                        return;
                    tooltip.show();
                    !this.pointAtShownTooltip && isFunction(this.tooltipShown) && this.tooltipShown.call(point, point);
                    this.pointAtShownTooltip = point
                }
            },
            _setHoveredSeries: function(series, mode) {
                var that = this;
                if (mode !== NONE_MODE && that.hoveredSeries !== series || series.lastHoverMode !== mode) {
                    that._clearHover(that);
                    that.hoveredSeries = series;
                    series.setHoverState(mode, that.legendCallback(series));
                    that.seriesHover && that.seriesHover.call(series, series);
                    that.seriesHoverChanged && that.seriesHoverChanged.call(series, series)
                }
                if (mode === NONE_MODE)
                    $(series).trigger('NoneMode')
            },
            _setSelectedSeries: function(series, mode) {
                var that = this,
                    seriesContain = false;
                if (this.seriesSelectionMode === MULTIPLE_MODE)
                    $.each(that.selectedSeries, function(_, sr) {
                        if (sr == series) {
                            seriesContain = true;
                            return false
                        }
                    });
                else if (that.selectedSeries == series)
                    seriesContain = true;
                if (!seriesContain || series.lastSelectionMode !== mode) {
                    if (that.seriesSelectionMode === SINGLE_MODE) {
                        this._releaseSelectedSeries();
                        that.selectedSeries = series
                    }
                    else
                        that.selectedSeries.push(series);
                    series.setSelectedState(mode, that.legendCallback(series));
                    that.seriesSelected && that.seriesSelected.call(series, series);
                    that.seriesSelectionChanged && that.seriesSelectionChanged.call(series, series)
                }
            },
            _setHoveredPoint: function(point, mode) {
                var that = this;
                var debug = DX.utils.debug;
                debug.assert(point.series, 'series was not assigned to point or empty');
                if (that.hoveredPoint === point && !point.series)
                    return;
                that._clearHover(that);
                that.hoveredPoint = point;
                if (point && point.getOptions())
                    that._setHoverStylePointWithMode(point, 'setPointHoverState', mode || processMode(point.getOptions().hoverMode), that.pointHoverChanged, that.legendCallback(point));
                that.pointHover && that.pointHover.call(point, point)
            },
            _toAllArgumentPoints: function(argument, func, callBack) {
                var that = this;
                $.each(that.storedSeries, function(_, series) {
                    var neighborPoint = series.getPointByArg(argument);
                    if (neighborPoint) {
                        series[func](neighborPoint);
                        callBack && callBack.call(neighborPoint, neighborPoint)
                    }
                })
            },
            _setHoverStylePointWithMode: function(point, func, mode, callBack, legendCallback) {
                var that = this;
                switch (mode) {
                    case ALL_ARGUMENTS_POINTS_MODE:
                        this._toAllArgumentPoints(point.argument, func, callBack);
                        break;
                    case ALL_SERIES_POINTS_MODE:
                        $.each(point.series.getPoints(), function(_, point) {
                            point.series[func](point);
                            callBack && callBack.call(point, point)
                        });
                        break;
                    case NONE_MODE:
                        break;
                    default:
                        point.series[func](point, legendCallback);
                        callBack && callBack.call(point, point)
                }
            },
            _setSelectedPoint: function(point) {
                var that = this,
                    pointContain = false;
                if (this.pointSelectionMode === MULTIPLE_MODE) {
                    $.each(that.selectedPoint, function(_, pt) {
                        if (pt == point) {
                            pointContain = true;
                            return false
                        }
                    });
                    !pointContain && that.selectedPoint.push(point)
                }
                else if (that.selectedPoint !== point) {
                    this._releaseSelectedPoint();
                    that.selectedPoint = point
                }
                else
                    pointContain = true;
                if (!pointContain) {
                    that._setHoverStylePointWithMode(point, 'setPointSelectedState', processMode(point.getOptions().selectionMode), that.pointSelectionChanged, that.legendCallback(point));
                    that.pointSelected && that.pointSelected.call(point, point)
                }
            },
            _releaseHoveredSeries: function() {
                var that = this;
                if (!that.hoveredSeries)
                    return;
                that.hoveredSeries.releaseHoverState(undefined, that.legendCallback(that.hoveredSeries));
                that.seriesHoverChanged && that.seriesHoverChanged.call(that.hoveredSeries, that.hoveredSeries);
                that.hoveredSeries = null
            },
            _releaseSelectedSeriesMultiMode: function(series) {
                var that = this;
                if (!that.selectedSeries)
                    return;
                series.releaseSelectedState(undefined, that.legendCallback(series));
                that.seriesSelectionChanged && that.seriesSelectionChanged.call(series, series);
                that.selectedSeries = $.map(that.selectedSeries, function(sr) {
                    if (sr !== series)
                        return sr
                })
            },
            _releaseSelectedSeriesSingleMode: function() {
                var that = this,
                    series = this.selectedSeries;
                if (!series)
                    return;
                series.releaseSelectedState(undefined, that.legendCallback(series));
                that.seriesSelectionChanged && that.seriesSelectionChanged.call(series, series);
                that.selectedSeries = null
            },
            _releaseHoveredPoint: function() {
                var that = this,
                    point = that.hoveredPoint,
                    mode;
                if (!point || !point.getOptions())
                    return;
                mode = processMode(point.getOptions().hoverMode);
                if (mode === ALL_SERIES_POINTS_MODE)
                    $.each(point.series.getPoints(), function(_, point) {
                        point.series.releasePointHoverState(point);
                        that.pointHoverChanged && that.pointHoverChanged.call(point, point)
                    });
                else if (mode === ALL_ARGUMENTS_POINTS_MODE)
                    that._toAllArgumentPoints(point.argument, 'releasePointHoverState', that.pointHoverChanged);
                else {
                    point.releaseHoverState(that.legendCallback(point));
                    that.pointHoverChanged && that.pointHoverChanged.call(point, point)
                }
                if (that.tooltipEnabled && !that.showHoldTooltip)
                    that._hideTooltip(point);
                that.hoveredPoint = null
            },
            _releaseSelectedPointMultiMode: function(point) {
                var that = this,
                    points = that.selectedPoint;
                if (!points)
                    return;
                that._setHoverStylePointWithMode(point, 'releasePointSelectedState', processMode(point.getOptions().selectionMode), that.pointSelectionChanged, that.legendCallback(point));
                this.selectedPoint = $.map(this.selectedPoint, function(pt) {
                    if (pt !== point)
                        return pt
                })
            },
            _releaseSelectedPointSingleMode: function() {
                var that = this,
                    point = that.selectedPoint;
                if (!point)
                    return;
                that._setHoverStylePointWithMode(point, 'releasePointSelectedState', processMode(point.getOptions().selectionMode), that.pointSelectionChanged, that.legendCallback(point));
                this.selectedPoint = null
            },
            _clearPointSelection: function() {
                var that = this;
                if (that.pointSelectionMode === SINGLE_MODE)
                    that._releaseSelectedPoint();
                else
                    $.each(that.selectedPoint || [], function(_, point) {
                        that._releaseSelectedPoint(point)
                    })
            },
            clearSelection: function() {
                var that = this;
                that._clearPointSelection();
                if (that.seriesSelectionMode === SINGLE_MODE)
                    that._releaseSelectedSeries();
                else
                    $.each(that.selectedSeries, function(_, series) {
                        that._releaseSelectedSeries(series)
                    })
            },
            setTooltip: function(tooltip) {
                this.tooltip = tooltip
            },
            _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)
            },
            _setCurCoords: function(that, pageX, pageY) {
                that.cX = pageX;
                that.cY = pageY
            },
            _clearHover: function(that) {
                that._releaseHoveredSeries();
                that._releaseHoveredPoint()
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-charts, file dxChart.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            viz = DX.viz;
        DX.registerComponent("dxChart", viz.charts.Chart)
    })(jQuery, DevExpress);
    /*! Module viz-charts, file dxPieChart.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            viz = DX.viz;
        DX.registerComponent("dxPieChart", viz.charts.PieChart)
    })(jQuery, DevExpress);
    DevExpress.MOD_VIZ_CHARTS = true
}
if (!DevExpress.MOD_VIZ_GAUGES) {
    if (!DevExpress.MOD_VIZ_CORE)
        throw Error('Required module is not referenced: viz-core');
    /*! Module viz-gauges, file namespaces.js */
    (function(DX) {
        DX.viz.gauges = {__internals: {
                circularNeedles: {},
                circularMarkers: {},
                linearNeedles: {},
                linearMarkers: {}
            }};
        DX.viz.gauges.__tests = {}
    })(DevExpress);
    /*! Module viz-gauges, file factory.js */
    (function(DX, $, undefined) {
        var internals = DX.viz.gauges.__internals,
            circularNeedles = internals.circularNeedles,
            circularMarkers = internals.circularMarkers,
            linearNeedles = internals.linearNeedles,
            linearMarkers = internals.linearMarkers;
        var _String = window.String,
            _isString = DX.utils.isString;
        DX.viz.gauges.__factory = {
            createCircularValueIndicator: function(type) {
                var indicatorType = circularNeedles.RectangleNeedle;
                switch (_String(type).toLowerCase()) {
                    case'rectangleneedle':
                    case'rectangle':
                        indicatorType = circularNeedles.RectangleNeedle;
                        break;
                    case'triangleneedle':
                    case'triangle':
                        indicatorType = circularNeedles.TriangleNeedle;
                        break;
                    case'twocolorneedle':
                    case'twocolorrectangle':
                        indicatorType = circularNeedles.TwoColorRectangleNeedle;
                        break;
                    case'rangebar':
                        indicatorType = internals.CircularRangeBar;
                        break
                }
                return new indicatorType
            },
            createLinearValueIndicator: function(type) {
                var indicatorType = internals.LinearRangeBar;
                switch (_String(type).toLowerCase()) {
                    case'rectangle':
                        indicatorType = linearNeedles.RectangleNeedle;
                        break;
                    case'rhombus':
                        indicatorType = linearNeedles.RhombusNeedle;
                        break;
                    case'circle':
                        indicatorType = linearNeedles.CircleNeedle;
                        break;
                    case'rangebar':
                        indicatorType = internals.LinearRangeBar;
                        break
                }
                return new indicatorType
            },
            createCircularSubvalueIndicator: function(type) {
                var indicatorType = circularMarkers.TriangleMarker;
                switch (_String(type).toLowerCase()) {
                    case'trianglemarker':
                    case'triangle':
                        indicatorType = circularMarkers.TriangleMarker;
                        break;
                    case'textcloud':
                        indicatorType = circularMarkers.TextCloudMarker;
                        break
                }
                return new indicatorType
            },
            createLinearSubvalueIndicator: function(type) {
                var indicatorType = linearMarkers.TriangleMarker;
                switch (_String(type).toLowerCase()) {
                    case'trianglemarker':
                    case'triangle':
                        indicatorType = linearMarkers.TriangleMarker;
                        break;
                    case'textcloud':
                        indicatorType = linearMarkers.TextCloudMarker;
                        break
                }
                return new indicatorType
            },
            createCircularValueIndicatorInHardMode: function(type) {
                var indicatorType = null;
                switch (_String(type).toLowerCase()) {
                    case'rectangleneedle':
                        indicatorType = circularNeedles.RectangleNeedle;
                        break;
                    case'triangleneedle':
                        indicatorType = circularNeedles.TriangleNeedle;
                        break;
                    case'twocolorneedle':
                        indicatorType = circularNeedles.TwoColorRectangleNeedle;
                        break;
                    case'rangebar':
                        indicatorType = internals.CircularRangeBar;
                        break;
                    case'trianglemarker':
                        indicatorType = circularMarkers.TriangleMarker;
                        break;
                    case'textcloud':
                        indicatorType = circularMarkers.TextCloudMarker;
                        break
                }
                return indicatorType ? new indicatorType : null
            },
            createLinearValueIndicatorInHardMode: function(type) {
                var indicatorType = null;
                switch (_String(type).toLowerCase()) {
                    case'rectangle':
                        indicatorType = linearNeedles.RectangleNeedle;
                        break;
                    case'rhombus':
                        indicatorType = linearNeedles.RhombusNeedle;
                        break;
                    case'circle':
                        indicatorType = linearNeedles.CircleNeedle;
                        break;
                    case'rangebar':
                        indicatorType = internals.LinearRangeBar;
                        break;
                    case'trianglemarker':
                        indicatorType = linearMarkers.TriangleMarker;
                        break;
                    case'textcloud':
                        indicatorType = linearMarkers.TextCloudMarker;
                        break
                }
                return indicatorType ? new indicatorType : null
            },
            createCircularNeedle: function(type) {
                switch (_String(type).toLowerCase()) {
                    case'rectangleneedle':
                    case'rectangle':
                        return new circularNeedles.RectangleNeedle;
                    case'twocolorneedle':
                    case'twocolorrectangle':
                        return new circularNeedles.TwoColorRectangleNeedle;
                    case'triangleneedle':
                    case'triangle':
                        return new circularNeedles.TriangleNeedle;
                    case'rangebar':
                        return new internals.CircularRangeBar
                }
                return undefined
            },
            createLinearNeedle: function(type) {
                switch (_String(type).toLowerCase()) {
                    case'rectangle':
                        return new linearNeedles.RectangleNeedle;
                    case'rhombus':
                        return new linearNeedles.RhombusNeedle;
                    case'circle':
                        return new linearNeedles.CircleNeedle;
                    case'rangebar':
                        return new internals.LinearRangeBar
                }
                return undefined
            },
            createCircularMarker: function(type) {
                switch (_String(type).toLowerCase()) {
                    case'trianglemarker':
                    case'triangle':
                        return new circularMarkers.TriangleMarker;
                    case'textcloud':
                        return new circularMarkers.TextCloudMarker
                }
                return undefined
            },
            createLinearMarker: function(type) {
                switch (_String(type).toLowerCase()) {
                    case'trianglemarker':
                    case'triangle':
                        return new linearMarkers.TriangleMarker;
                    case'textcloud':
                        return new linearMarkers.TextCloudMarker
                }
                return undefined
            },
            createCircularRangeBar: function(parameters) {
                return new internals.CircularRangeBar(parameters)
            },
            createLinearRangeBar: function(parameters) {
                return new internals.LinearRangeBar(parameters)
            },
            createCircularScale: function(parameters) {
                return new internals.CircularScale(parameters)
            },
            createLinearScale: function(parameters) {
                return new internals.LinearScale(parameters)
            },
            createCircularRangeContainer: function(parameters) {
                return new internals.CircularRangeContainer(parameters)
            },
            createLinearRangeContainer: function(parameters) {
                return new internals.LinearRangeContainer(parameters)
            },
            createTitle: function(parameters) {
                return new internals.Title(parameters)
            },
            createIndicator: function() {
                return internals.Indicator && new internals.Indicator || null
            },
            createLayoutManager: function() {
                return new internals.LayoutManager
            },
            createThemeManager: function(options) {
                return new internals.ThemeManager(options)
            },
            createTracker: function(parameters) {
                return new internals.Tracker(parameters)
            }
        };
        var _isFunction = DX.utils.isFunction,
            _String = window.String,
            _extend = $.extend;
        var _formatHelper = DX.formatHelper;
        internals.formatValue = function(value, options, extra) {
            options = options || {};
            var text = _formatHelper.format(value, options.format, options.precision),
                context;
            if (_isFunction(options.customizeText)) {
                var context = _extend({
                        value: value,
                        valueText: text
                    }, extra);
                return _String(options.customizeText.call(context, context))
            }
            return text
        };
        internals.getSampleText = function(translator, options) {
            var text1 = internals.formatValue(translator.getDomainStart(), options),
                text2 = internals.formatValue(translator.getDomainEnd(), options);
            return text1.length >= text2.length ? text1 : text2
        }
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file scale.js */
    (function(DX, $, undefined) {
        var _Number = Number,
            _String = String,
            _isFinite = isFinite,
            _min = Math.min,
            _max = Math.max,
            _abs = Math.abs,
            _atan = Math.atan,
            _acos = Math.acos,
            _ceil = Math.ceil,
            _isFunction = DX.utils.isFunction,
            _isArray = DX.utils.isArray,
            _getCosAndSin = DX.utils.getCosAndSin,
            _normalizeAngle = DX.utils.normalizeAngle,
            _convertAngleToRendererSpace = DX.utils.convertAngleToRendererSpace,
            _map = $.map;
        var _formatHelper = DX.formatHelper,
            _tickProvider = DX.viz.core.tickProvider;
        var PI_DIV_180 = Math.PI / 180;
        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
        }
        function sortAsc(x, y) {
            return x - y
        }
        function sortDes(x, y) {
            return y - x
        }
        DX.viz.gauges.__internals.BaseScale = DX.Class.inherit({
            ctor: function(parameters) {
                var that = this;
                that._renderer = parameters.renderer;
                that._container = parameters.container;
                that._translator = parameters.translator;
                that._root = that._renderer.createGroup({'class': 'dxg-scale'});
                that._majorTicks = that._renderer.createGroup({'class': 'dxg-major-ticks'});
                that._minorTicks = that._renderer.createGroup({'class': 'dxg-minor-ticks'});
                that._labels = that._renderer.createGroup({'class': 'dxg-labels'})
            },
            dispose: function() {
                var that = this;
                that._renderer = that._container = that._renderer = that._root = that._majorTicks = that._minorTicks = that._labels = null;
                return that
            },
            clean: function() {
                var that = this;
                that._root.detach();
                that._majorTicks.detach().clear();
                that._minorTicks.detach().clear();
                that._labels.detach().clear();
                that._majorTicksEnabled = that._minorTicksEnabled = that._labelsEnabled = that._options = that.enabled = null;
                return that
            },
            render: function(options) {
                var that = this;
                that._options = options;
                that._processOptions(options);
                if (that._majorTicksEnabled || that._minorTicksEnabled || that._labelsEnabled) {
                    that.enabled = true;
                    that._root.append(that._container);
                    if (that._majorTicksEnabled)
                        that._majorTicks.append(that._root);
                    if (that._minorTicksEnabled)
                        that._minorTicks.append(that._root);
                    if (that._labelsEnabled) {
                        that._labels.append(that._root);
                        that._measureText()
                    }
                }
                return that
            },
            _processOptions: function(options) {
                var that = this;
                that._majorTicksEnabled = options.majorTick.visible && options.majorTick.length > 0 && options.majorTick.width > 0;
                that._minorTicksEnabled = options.minorTick.visible && options.minorTick.length > 0 && options.minorTick.width > 0;
                that._labelsEnabled = options.label.visible && _Number(options.label.indentFromTick) !== 0;
                that._setupOrientation()
            },
            _getSampleText: function() {
                var that = this,
                    domain = that._translator.getDomain(),
                    texts = [],
                    i,
                    ii,
                    text,
                    maxLength = 0,
                    maxText = '';
                var ticks = _tickProvider.getTicks({
                        min: domain[0],
                        max: domain[1],
                        tickInterval: that._options.majorTick.tickInterval > 0 ? _Number(that._options.majorTick.tickInterval) : undefined,
                        screenDelta: that._options.approximateScreenDelta,
                        gridSpacingFactor: that._getGridSpacingFactor().majorTicks
                    });
                for (i = 0, ii = ticks.length; i < ii; ++i) {
                    text = that._formatValue(ticks[i]);
                    text.length > maxLength && (maxText = text) && (maxLength = text.length)
                }
                return maxText
            },
            _measureText: function() {
                var that = this,
                    value = that._getSampleText(),
                    text = that._renderer.createText(value, 0, 0, {font: that._options.label.font}).append(that._labels),
                    bbox = text.getBBox();
                text.remove();
                that._textVerticalOffset = -bbox.y - bbox.height / 2;
                that._textWidth = bbox.width;
                that._textHeight = bbox.height;
                that._textLength = value.length
            },
            _formatValue: function(value) {
                var options = this._options.label,
                    text = _formatHelper.format(value, options.format, options.precision);
                if (_isFunction(options.customizeText)) {
                    text = {
                        value: value,
                        valueText: text
                    };
                    text = _String(options.customizeText.call(text, text))
                }
                return text
            },
            _setupOrientation: null,
            _getCustomValues: function(values, compare) {
                var translator = this._translator,
                    result = [];
                if (_isArray(values)) {
                    result = _map(values, function(x) {
                        return _isFinite(translator.translate(x)) ? _Number(x) : null
                    }).sort(compare);
                    result = _map(result, function(x, i) {
                        return x !== result[i - 1] ? x : null
                    })
                }
                return result
            },
            _generateTicks: function(layout) {
                var that = this,
                    majorTicksOptions = {
                        tickInterval: that._options.majorTick.tickInterval > 0 ? _Number(that._options.majorTick.tickInterval) : undefined,
                        gridSpacingFactor: that._getGridSpacingFactor().majorTicks,
                        numberMultipliers: [1, 2, 5]
                    },
                    minorTicksOptions = {
                        tickInterval: that._options.minorTick.tickInterval > 0 ? _Number(that._options.minorTick.tickInterval) : undefined,
                        gridSpacingFactor: that._getGridSpacingFactor().minorTicks,
                        numberMultipliers: [1, 2, 5]
                    };
                if (that._options.majorTick.useTicksAutoArrangement) {
                    majorTicksOptions.useTicksAutoArrangement = true;
                    majorTicksOptions.renderer = that._renderer;
                    majorTicksOptions.translator = that._translator;
                    majorTicksOptions.getCustomAutoArrangementStep = function(values) {
                        return that._getCuttingFactor(values.length, {
                                width: that._textWidth,
                                height: that._textHeight
                            }, layout)
                    }
                }
                return _tickProvider.getFullTicks(that._translator.getDomain()[0], that._translator.getDomain()[1], that._getScreenDelta(layout), majorTicksOptions, minorTicksOptions)
            },
            _getTicks: function(layout) {
                var that = this,
                    compareCallback = that._translator.getDomain()[0] < that._translator.getDomain()[1] ? sortAsc : sortDes,
                    info = that._generateTicks(layout);
                var majorValues = that._options.majorTick.showCalculatedTicks ? info.majorTicks : [];
                var customMajorValues = that._getCustomValues(that._options.majorTick.customTickValues, compareCallback);
                customMajorValues = _map(customMajorValues, function(value) {
                    return binarySearch(value, majorValues) === -1 ? value : null
                });
                var minorValues = that._options.minorTick.showCalculatedTicks ? info.minorTicks : [];
                minorValues = _map(minorValues, function(value) {
                    return binarySearch(value, customMajorValues) === -1 ? value : null
                });
                var customMinorValues = that._getCustomValues(that._options.minorTick.customTickValues, compareCallback);
                var list = majorValues.concat(minorValues, customMajorValues).sort(compareCallback);
                customMinorValues = _map(customMinorValues, function(value) {
                    return binarySearch(value, list) === -1 ? value : null
                });
                return {
                        major: _map(majorValues.concat(customMajorValues), function(value) {
                            return {
                                    value: value,
                                    position: that._translator.translate(value)
                                }
                        }),
                        minor: _map(minorValues.concat(customMinorValues), function(value) {
                            return {
                                    value: value,
                                    position: that._translator.translate(value)
                                }
                        })
                    }
            },
            _createMajorTicks: function(ticks, layout) {
                var that = this;
                that._majorTicks.clear().applySettings({fill: that._options.majorTick.color});
                var points = that._getTickPoints(_Number(that._options.majorTick.length), _Number(that._options.majorTick.width), layout);
                if (points) {
                    var i = 0,
                        ii = ticks.length,
                        element;
                    that._options.hideFirstTick && ++i;
                    that._options.hideLastTick && --ii;
                    for (; i < ii; ++i) {
                        element = that._renderer.createArea(points);
                        that._moveTick(element, ticks[i], layout);
                        element.append(that._majorTicks)
                    }
                }
            },
            _createMinorTicks: function(ticks, layout) {
                var that = this;
                that._minorTicks.clear().applySettings({fill: that._options.minorTick.color});
                var points = that._getTickPoints(_Number(that._options.minorTick.length), _Number(that._options.minorTick.width), layout);
                if (points) {
                    var i = 0,
                        ii = ticks.length,
                        element;
                    for (; i < ii; ++i) {
                        element = that._renderer.createArea(points);
                        that._moveTick(element, ticks[i], layout);
                        element.append(that._minorTicks)
                    }
                }
            },
            _createLabels: function(ticks, layout) {
                var that = this,
                    indentFromTick = _Number(that._options.label.indentFromTick);
                that._labels.clear().applySettings({
                    align: that._getLabelAlign(indentFromTick),
                    font: that._options.label.font
                });
                var textPosition = that._getLabelPosition(that._majorTicksEnabled ? _Number(that._options.majorTick.length) : 0, indentFromTick, layout);
                if (textPosition) {
                    var i = 0,
                        ii = ticks.length,
                        points,
                        text;
                    that._options.hideFirstLabel && ++i;
                    that._options.hideLastLabel && --ii;
                    for (; i < ii; ++i) {
                        text = that._formatValue(ticks[i].value);
                        points = that._getLabelOptions(text, textPosition, indentFromTick, ticks[i], layout);
                        that._renderer.createText(text, points.x, points.y + that._textVerticalOffset).append(that._labels)
                    }
                }
            },
            resize: function(layout) {
                var that = this,
                    ticks = that._getTicks(layout);
                if (that._majorTicksEnabled)
                    that._createMajorTicks(ticks.major, layout);
                if (that._minorTicksEnabled)
                    that._createMinorTicks(ticks.minor, layout);
                if (that._labelsEnabled)
                    that._createLabels(ticks.major, layout);
                return that
            }
        });
        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(layout) {
                return (this._translator.getCodomainStart() - this._translator.getCodomainEnd()) * layout.radius * PI_DIV_180
            },
            _getCuttingFactor: function(ticksCount, maxLabelSize, layout) {
                var that = this,
                    options = that._options,
                    startAngle = that._translator.getCodomainStart(),
                    endAngle = that._translator.getCodomainEnd(),
                    radius = that._getLabelPosition(that._majorTicksEnabled ? _Number(that._options.majorTick.length) : 0, _Number(that._options.label.indentFromTick), layout),
                    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) / PI_DIV_180);
                cosOfHeightBasedAngle = baseAngleCosSin.cos - maxLabelSize.height / radius;
                heightBasedAngle = -1 > cosOfHeightBasedAngle || cosOfHeightBasedAngle > 1 ? 90 : _abs(baseAngle - _acos(cosOfHeightBasedAngle) / PI_DIV_180);
                minAngleBetweenTicks = widthBasedAngle < heightBasedAngle ? widthBasedAngle : heightBasedAngle;
                if (degreesPerTick < minAngleBetweenTicks)
                    cuttingBackFactor = _ceil(minAngleBetweenTicks / degreesPerTick);
                return _max(1, cuttingBackFactor)
            },
            _setupOrientation: function() {
                var that = this;
                that._inner = that._outer = 0;
                switch (that._options.orientation) {
                    case'inside':
                        that._inner = 1;
                        break;
                    case'center':
                        that._inner = that._outer = 0.5;
                        break;
                    default:
                        that._outer = 1;
                        break
                }
            },
            _getTickPoints: function(length, width, layout) {
                var x1 = layout.x - width / 2,
                    x2 = layout.x + width / 2,
                    y1 = layout.y - layout.radius - length * this._outer,
                    y2 = layout.y - layout.radius + length * this._inner;
                return y1 > 0 && y2 > 0 ? [x1, y1, x2, y1, x2, y2, x1, y2] : null
            },
            _moveTick: function(element, tick, layout) {
                element.rotate(_convertAngleToRendererSpace(tick.position), layout.x, layout.y)
            },
            _getLabelPosition: function(tickLength, textIndent, layout) {
                var position = layout.radius + tickLength * (textIndent >= 0 ? this._outer : -this._inner) + textIndent;
                return position > 0 ? position : null
            },
            _getLabelAlign: function() {
                return 'center'
            },
            _getLabelOptions: function(textValue, textPosition, textIndent, tick, layout) {
                var cossin = _getCosAndSin(tick.position),
                    x = layout.x + cossin.cos * textPosition,
                    y = layout.y - cossin.sin * textPosition,
                    dx = cossin.cos * (textValue.length / this._textLength) * this._textWidth / 2,
                    dy = cossin.sin * this._textHeight / 2;
                if (textIndent > 0) {
                    x += dx;
                    y -= dy
                }
                else {
                    x -= dx;
                    y += dy
                }
                return {
                        x: x,
                        y: y
                    }
            },
            measure: function(layout) {
                var that = this,
                    result = {
                        min: layout.radius,
                        max: layout.radius
                    };
                if (that._majorTicksEnabled) {
                    result.min = _min(result.min, layout.radius - that._inner * that._options.majorTick.length);
                    result.max = _max(result.max, layout.radius + that._outer * that._options.majorTick.length)
                }
                if (that._minorTicksEnabled) {
                    result.min = _min(result.min, layout.radius - that._inner * that._options.minorTick.length);
                    result.max = _max(result.max, layout.radius + that._outer * that._options.minorTick.length)
                }
                if (that._labelsEnabled) {
                    if (that._options.label.indentFromTick > 0) {
                        result.horizontalOffset = _Number(that._options.label.indentFromTick) + that._textWidth;
                        result.verticalOffset = _Number(that._options.label.indentFromTick) + that._textHeight
                    }
                    else {
                        result.horizontalOffset = result.verticalOffset = 0;
                        result.min -= -_Number(that._options.label.indentFromTick) + _max(that._textWidth, that._textHeight)
                    }
                    result.inverseHorizontalOffset = that._textWidth / 2;
                    result.inverseVerticalOffset = that._textHeight / 2
                }
                return result
            }
        });
        DX.viz.gauges.__internals.LinearScale = DX.viz.gauges.__internals.BaseScale.inherit({
            _getGridSpacingFactor: function() {
                return {
                        majorTicks: 25,
                        minorTicks: 5
                    }
            },
            _getScreenDelta: function(layout) {
                return _abs(this._translator.getCodomainEnd() - this._translator.getCodomainStart())
            },
            _getCuttingFactor: function(ticksCount, maxLabelSize, layout) {
                var that = this,
                    labelSize = that.vertical ? maxLabelSize.height : maxLabelSize.width,
                    screenSize = _abs(that._translator.getCodomainEnd() - that._translator.getCodomainStart());
                return _max(1, _ceil(ticksCount * labelSize / (screenSize + labelSize)))
            },
            _setupOrientation: function() {
                var that = this;
                that.vertical = that._options.vertical;
                that._inner = that._outer = 0;
                if (that.vertical)
                    switch (that._options.horizontalOrientation) {
                        case'left':
                            that._inner = 1;
                            break;
                        case'center':
                            that._inner = that._outer = 0.5;
                            break;
                        default:
                            that._outer = 1;
                            break
                    }
                else
                    switch (that._options.verticalOrientation) {
                        case'top':
                            that._inner = 1;
                            break;
                        case'middle':
                            that._inner = that._outer = 0.5;
                            break;
                        default:
                            that._outer = 1;
                            break
                    }
            },
            _getTickPoints: function(length, width, layout) {
                var that = this,
                    x1,
                    x2,
                    y1,
                    y2;
                if (that.vertical) {
                    x1 = layout.x - length * that._inner;
                    x2 = layout.x + length * that._outer;
                    y1 = -width / 2;
                    y2 = +width / 2
                }
                else {
                    x1 = -width / 2;
                    x2 = +width / 2;
                    y1 = layout.y - length * that._inner;
                    y2 = layout.y + length * that._outer
                }
                return [x1, y1, x2, y1, x2, y2, x1, y2]
            },
            _moveTick: function(element, tick, layout) {
                var x = 0,
                    y = 0;
                if (this.vertical)
                    y = tick.position;
                else
                    x = tick.position;
                element.move(x, y)
            },
            _getLabelPosition: function(tickLength, textIndent, layout) {
                var position = tickLength * (textIndent >= 0 ? this._outer : -this._inner) + textIndent;
                if (this.vertical)
                    position += layout.x;
                else
                    position += layout.y + (textIndent >= 0 ? 1 : -1) * this._textVerticalOffset;
                return position
            },
            _getLabelAlign: function(textIndent) {
                return this.vertical ? textIndent > 0 ? 'left' : 'right' : 'center'
            },
            _getLabelOptions: function(textValue, textPosition, textIndent, tick, layout) {
                var x,
                    y;
                if (this.vertical) {
                    x = textPosition;
                    y = tick.position
                }
                else {
                    x = tick.position;
                    y = textPosition
                }
                return {
                        x: x,
                        y: y
                    }
            },
            measure: function(layout) {
                var that = this,
                    p = layout[that.vertical ? 'x' : 'y'],
                    result = {
                        min: p,
                        max: p
                    };
                if (that._majorTicksEnabled) {
                    result.min = _min(result.min, p - that._inner * that._options.majorTick.length);
                    result.max = _max(result.max, p + that._outer * that._options.majorTick.length)
                }
                if (that._minorTicksEnabled) {
                    result.min = _min(result.min, p - that._inner * that._options.minorTick.length);
                    result.max = _max(result.max, p + that._outer * that._options.minorTick.length)
                }
                if (that._labelsEnabled) {
                    if (that._options.label.indentFromTick > 0)
                        result.max += +_Number(that._options.label.indentFromTick) + that[that.vertical ? '_textWidth' : '_textHeight'];
                    else
                        result.min -= -_Number(that._options.label.indentFromTick) + that[that.vertical ? '_textWidth' : '_textHeight'];
                    result.indent = that[that.vertical ? '_textHeight' : '_textWidth'] / 2
                }
                return result
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file baseIndicator.js */
    (function(DX, $, undefined) {
        var _isFinite = isFinite,
            _Number = Number,
            _extend = $.extend;
        DX.viz.gauges.__internals.BaseIndicator = DX.Class.inherit({
            setup: function(parameters) {
                var that = this;
                that._renderer = parameters.renderer;
                that._translator = parameters.translator;
                that._owner = parameters.owner;
                that._tracker = parameters.tracker;
                that._className = parameters.className;
                that._options = {};
                that._rootElement = that._createRoot();
                that._trackerElement = that._createTracker();
                return that
            },
            dispose: function() {
                var that = this;
                that._renderer = that._owner = that._translator = that._tracker = that._options = that._rootElement = that._trackerElement = null;
                return that
            },
            _setupAnimation: function() {
                var that = this;
                if (that._options.animation)
                    that._animation = {
                        step: function(pos) {
                            that._actualValue = that._animation.start + that._animation.delta * pos;
                            that._actualPosition = that._translator.translate(that._actualValue);
                            that._move()
                        },
                        duration: that._options.animation.duration > 0 ? _Number(that._options.animation.duration) : 0,
                        easing: that._options.animation.easing
                    }
            },
            _runAnimation: function(value) {
                var that = this,
                    animation = that._animation;
                animation.start = that._actualValue;
                animation.delta = value - that._actualValue;
                that._rootElement.animate({_: 0}, {
                    step: animation.step,
                    duration: animation.duration,
                    easing: animation.easing
                })
            },
            _createRoot: function() {
                return this._renderer.createGroup({'class': this._className})
            },
            _createTracker: function() {
                return this._renderer.createArea()
            },
            _getTrackerSettings: function(){},
            clean: function() {
                var that = this;
                that._animation && that._rootElement.stopAnimation();
                that._rootElement.detach();
                that._rootElement.clear();
                that._clear();
                that._tracker.detach(that._trackerElement);
                that._options = that.enabled = that._animation = null;
                return that
            },
            render: function(options) {
                var that = this;
                that.type = options.type;
                that._options = options;
                that._actualValue = that._currentValue = that._translator.adjust(that._options.currentValue);
                that.enabled = that._isEnabled();
                if (that.enabled) {
                    that._setupAnimation();
                    that._rootElement.applySettings({fill: that._options.color}).append(that._owner);
                    that._tracker.attach(that._trackerElement, that, that._trackerInfo)
                }
                return that
            },
            resize: function(layout) {
                var that = this;
                that._rootElement.clear();
                that._clear();
                that.visible = that._isVisible(layout);
                if (that.visible) {
                    _extend(that._options, layout);
                    that._actualPosition = that._translator.translate(that._actualValue);
                    that._render();
                    that._trackerElement.applySettings(that._getTrackerSettings());
                    that._move()
                }
                return that
            },
            value: function(arg, _noAnimation) {
                var that = this;
                if (arg !== undefined) {
                    var val = that._translator.adjust(arg);
                    if (that._currentValue !== val && _isFinite(val)) {
                        that._currentValue = val;
                        if (that.visible)
                            if (that._animation && !_noAnimation)
                                that._runAnimation(val);
                            else {
                                that._actualValue = val;
                                that._actualPosition = that._translator.translate(val);
                                that._move()
                            }
                    }
                    return that
                }
                return that._currentValue
            },
            _isEnabled: null,
            _isVisible: null,
            _render: null,
            _clear: null,
            _move: null
        })
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file baseMarker.js */
    (function(DX, undefined) {
        var TextCloud = DX.viz.core.TextCloud;
        var formatValue = DX.viz.gauges.__internals.formatValue,
            getSampleText = DX.viz.gauges.__internals.getSampleText;
        DX.viz.gauges.__internals.BaseTextCloudMarker = DX.viz.gauges.__internals.BaseIndicator.inherit({
            _move: function() {
                var that = this,
                    bbox,
                    info = new TextCloud,
                    textCloudOptions = that._getTextCloudOptions();
                that._text.applySettings({text: formatValue(that._actualValue, that._options.text)});
                bbox = that._text.getBBox();
                info.setup({
                    x: textCloudOptions.x,
                    y: textCloudOptions.y,
                    textWidth: bbox.width,
                    textHeight: bbox.height,
                    horMargin: that._options.horizontalOffset,
                    verMargin: that._options.verticalOffset,
                    tailLength: that._options.arrowLength,
                    type: textCloudOptions.type
                });
                that._text.applySettings({
                    x: info.cx(),
                    y: info.cy() + that._textVerticalOffset
                });
                that._cloud.applySettings({points: info.points()});
                that._trackerElement && that._trackerElement.applySettings({points: info.points()})
            },
            _measureText: function() {
                var that = this,
                    root,
                    text,
                    bbox;
                if (!that._textVerticalOffset) {
                    root = that._createRoot().append(that._owner);
                    text = that._renderer.createText(getSampleText(that._translator, that._options.text), 0, 0, {
                        align: 'center',
                        font: that._options.text.font
                    }).append(root);
                    bbox = text.getBBox();
                    root.remove();
                    that._textVerticalOffset = -bbox.y - bbox.height / 2;
                    that._textWidth = bbox.width;
                    that._textHeight = bbox.height;
                    that._textFullWidth = that._textWidth + 2 * that._options.horizontalOffset;
                    that._textFullHeight = that._textHeight + 2 * that._options.verticalOffset
                }
            },
            _render: function() {
                var that = this;
                that._measureText();
                that._cloud = that._cloud || that._renderer.createArea().append(that._rootElement);
                that._text = that._text || that._renderer.createText().append(that._rootElement);
                that._text.applySettings({
                    align: 'center',
                    font: that._options.text.font
                })
            },
            _clear: function() {
                delete this._cloud;
                delete this._text
            },
            getTooltipParameters: function() {
                var position = this._getTextCloudOptions();
                return {
                        x: position.x,
                        y: position.y,
                        value: this._currentValue,
                        color: this._options.color
                    }
            }
        })
    })(DevExpress);
    /*! Module viz-gauges, file baseRangeBar.js */
    (function(DX, $, undefined) {
        var $extend = $.extend;
        var formatValue = DX.viz.gauges.__internals.formatValue,
            getSampleText = DX.viz.gauges.__internals.getSampleText;
        DX.viz.gauges.__internals.BaseRangeBar = DX.viz.gauges.__internals.BaseIndicator.inherit({
            _measureText: function() {
                var that = this,
                    root,
                    text,
                    bbox;
                that._hasText = that._isTextVisible();
                if (that._hasText && !that._textVerticalOffset) {
                    root = that._createRoot().append(that._owner);
                    text = that._renderer.createText(getSampleText(that._translator, that._options.text), 0, 0, {
                        'class': 'dxg-text',
                        align: 'center',
                        font: that._options.text.font
                    }).append(root);
                    bbox = text.getBBox();
                    root.remove();
                    that._textVerticalOffset = -bbox.y - bbox.height / 2;
                    that._textWidth = bbox.width;
                    that._textHeight = bbox.height
                }
            },
            _move: function() {
                var that = this;
                that._updateBarItemsPositions();
                if (that._hasText) {
                    that._text.applySettings({text: formatValue(that._actualValue, that._options.text)});
                    that._updateTextPosition();
                    that._updateLinePosition()
                }
            },
            _updateBarItems: function() {
                var that = this,
                    options = that._options,
                    backgroundColor,
                    spaceColor;
                that._setBarSides();
                that._startPosition = that._translator.translate(that._translator.getDomainStart());
                that._endPosition = that._translator.translate(that._translator.getDomainEnd());
                that._basePosition = that._translator.translate(options.baseValue);
                that._space = that._getSpace();
                backgroundColor = options.backgroundColor || 'none';
                if (backgroundColor !== 'none' && that._space > 0)
                    spaceColor = options.containerBackgroundColor || 'none';
                else {
                    that._space = 0;
                    spaceColor = 'none'
                }
                that._backItem1.applySettings({fill: backgroundColor});
                that._backItem2.applySettings({fill: backgroundColor});
                that._spaceItem1.applySettings({fill: spaceColor});
                that._spaceItem2.applySettings({fill: spaceColor})
            },
            _getSpace: function() {
                return 0
            },
            _updateTextItems: function() {
                var that = this;
                if (that._hasText) {
                    that._line = that._line || that._renderer.createPath([], {'class': 'dxg-main-bar'}).append(that._rootElement);
                    that._text = that._text || that._renderer.createText('', 0, 0, {'class': 'dxg-text'}).append(that._rootElement);
                    that._text.applySettings({
                        align: that._getTextAlign(),
                        font: that._getFontOptions()
                    });
                    that._setTextItemsSides()
                }
                else {
                    if (that._line) {
                        that._line.remove();
                        delete that._line
                    }
                    if (that._text) {
                        that._text.remove();
                        delete that._text
                    }
                }
            },
            _isTextVisible: function() {
                return false
            },
            _getTextAlign: function() {
                return 'center'
            },
            _getFontOptions: function() {
                var options = this._options,
                    font = options.text.font;
                if (!font || !font.color)
                    font = $extend({}, font, {color: options.color});
                return font
            },
            _updateBarItemsPositions: function() {
                var that = this,
                    positions = that._getPositions();
                that._backItem1.applySettings(that._buildItemSettings(positions.start, positions.back1));
                that._backItem2.applySettings(that._buildItemSettings(positions.back2, positions.end));
                that._spaceItem1.applySettings(that._buildItemSettings(positions.back1, positions.main1));
                that._spaceItem2.applySettings(that._buildItemSettings(positions.main2, positions.back2));
                that._mainItem.applySettings(that._buildItemSettings(positions.main1, positions.main2));
                that._trackerElement && that._trackerElement.applySettings(that._buildItemSettings(positions.main1, positions.main2))
            },
            _render: function() {
                var that = this;
                that._measureText();
                if (!that._backItem1) {
                    that._backItem1 = that._createBarItem();
                    that._backItem1.applySettings({'class': 'dxg-back-bar'})
                }
                if (!that._backItem2) {
                    that._backItem2 = that._createBarItem();
                    that._backItem2.applySettings({'class': 'dxg-back-bar'})
                }
                if (!that._spaceItem1) {
                    that._spaceItem1 = that._createBarItem();
                    that._spaceItem1.applySettings({'class': 'dxg-space-bar'})
                }
                if (!that._spaceItem2) {
                    that._spaceItem2 = that._createBarItem();
                    that._spaceItem2.applySettings({'class': 'dxg-space-bar'})
                }
                if (!that._mainItem) {
                    that._mainItem = that._createBarItem();
                    that._mainItem.applySettings({'class': 'dxg-main-bar'})
                }
                that._updateBarItems();
                that._updateTextItems()
            },
            _clear: function() {
                var that = this;
                delete that._backItem1;
                delete that._backItem2;
                delete that._spaceItem1;
                delete that._spaceItem2;
                delete that._mainItem;
                delete that._hasText;
                delete that._line;
                delete that._text
            },
            getTooltipParameters: function() {
                var position = this._getTooltipPosition();
                return {
                        x: position.x,
                        y: position.y,
                        value: this._currentValue,
                        color: this._options.color,
                        offset: 0
                    }
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file circularNeedle.js */
    (function(DX, undefined) {
        var circularNeedles = DX.viz.gauges.__internals.circularNeedles;
        var _Number = Number;
        circularNeedles.SimpleIndicator = DX.viz.gauges.__internals.BaseIndicator.inherit({
            _move: function() {
                var that = this,
                    options = that._options,
                    angle = DX.utils.convertAngleToRendererSpace(that._actualPosition);
                that._rootElement.rotate(angle, options.x, options.y);
                that._trackerElement && that._trackerElement.rotate(angle, options.x, options.y)
            },
            _isEnabled: function() {
                return this._options.width > 0
            },
            _isVisible: function(layout) {
                return layout.radius - _Number(this._options.indentFromCenter) > 0
            },
            _getTrackerSettings: function() {
                var options = this._options,
                    x = options.x,
                    y = options.y - (options.radius + _Number(options.indentFromCenter)) / 2,
                    width = options.width / 2,
                    length = (options.radius - _Number(options.indentFromCenter)) / 2;
                width > 10 || (width = 10);
                length > 10 || (length = 10);
                return {points: [x - width, y - length, x - width, y + length, x + width, y + length, x + width, y - length]}
            },
            _renderSpindle: function() {
                var that = this,
                    options = that._options,
                    gapSize;
                if (options.spindleSize > 0) {
                    gapSize = _Number(options.spindleGapSize) || 0;
                    if (gapSize > 0)
                        gapSize = gapSize <= options.spindleSize ? gapSize : _Number(options.spindleSize);
                    that._spindleOuter = that._spindleOuter || that._renderer.createCircle().append(that._rootElement);
                    that._spindleInner = that._spindleInner || that._renderer.createCircle().append(that._rootElement);
                    that._spindleOuter.applySettings({
                        'class': 'dxg-spindle-border',
                        cx: options.x,
                        cy: options.y,
                        r: options.spindleSize / 2
                    });
                    that._spindleInner.applySettings({
                        'class': 'dxg-spindle-hole',
                        cx: options.x,
                        cy: options.y,
                        r: gapSize / 2,
                        fill: options.containerBackgroundColor
                    })
                }
            },
            _render: function() {
                var that = this;
                that._renderPointer();
                that._renderSpindle()
            },
            _clearSpindle: function() {
                delete this._spindleOuter;
                delete this._spindleInner
            },
            _clearPointer: function() {
                delete this._element
            },
            _clear: function() {
                this._clearPointer();
                this._clearSpindle()
            },
            measure: function(layout) {
                var result = {max: layout.radius};
                if (this._options.indentFromCenter < 0)
                    result.inverseHorizontalOffset = result.inverseVerticalOffset = -_Number(this._options.indentFromCenter);
                return result
            },
            getTooltipParameters: function() {
                var options = this._options,
                    cossin = DX.utils.getCosAndSin(this._actualPosition),
                    r = (options.radius + _Number(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({_renderPointer: function() {
                var that = this,
                    options = that._options,
                    y2 = options.y - options.radius,
                    y1 = options.y - _Number(options.indentFromCenter),
                    x1 = options.x - options.width / 2,
                    x2 = x1 + _Number(options.width);
                that._element = that._element || that._renderer.createArea().append(that._rootElement);
                that._element.applySettings({points: [x1, y1, x1, y2, x2, y2, x2, y1]})
            }});
        circularNeedles.TriangleNeedle = circularNeedles.SimpleIndicator.inherit({_renderPointer: function() {
                var that = this,
                    options = that._options,
                    y2 = options.y - options.radius,
                    y1 = options.y - _Number(options.indentFromCenter),
                    x1 = options.x - options.width / 2,
                    x2 = options.x + options.width / 2;
                that._element = that._element || that._renderer.createArea().append(that._rootElement);
                that._element.applySettings({points: [x1, y1, options.x, y2, x2, y1]})
            }});
        circularNeedles.TwoColorRectangleNeedle = circularNeedles.SimpleIndicator.inherit({
            _renderPointer: function() {
                var that = this,
                    options = that._options,
                    x1 = options.x - options.width / 2,
                    x2 = options.x + options.width / 2,
                    y4 = options.y - options.radius,
                    y1 = options.y - _Number(options.indentFromCenter),
                    fraction = _Number(options.secondFraction) || 0,
                    y2,
                    y3;
                if (fraction >= 1)
                    y2 = y3 = y1;
                else if (fraction <= 0)
                    y2 = y3 = y2;
                else {
                    y3 = y4 + (y1 - y4) * fraction;
                    y2 = y3 + options.space
                }
                that._firstElement = that._firstElement || that._renderer.createArea().append(that._rootElement);
                that._spaceElement = that._spaceElement || that._renderer.createArea().append(that._rootElement);
                that._secondElement = that._secondElement || that._renderer.createArea().append(that._rootElement);
                that._firstElement.applySettings({points: [x1, y1, x1, y2, x2, y2, x2, y1]});
                that._spaceElement.applySettings({
                    points: [x1, y2, x1, y3, x2, y3, x2, y2],
                    'class': 'dxg-hole',
                    fill: options.containerBackgroundColor
                });
                that._secondElement.applySettings({
                    points: [x1, y3, x1, y4, x2, y4, x2, y3],
                    'class': 'dxg-part',
                    fill: options.secondColor
                })
            },
            _clearPointer: function() {
                delete this._firstElement;
                delete this._secondElement;
                delete this._spaceElement
            }
        })
    })(DevExpress);
    /*! Module viz-gauges, file linearNeedle.js */
    (function(DX, undefined) {
        var linearNeedles = DX.viz.gauges.__internals.linearNeedles;
        var _Number = Number;
        linearNeedles.SimpleIndicator = DX.viz.gauges.__internals.BaseIndicator.inherit({
            _move: function() {
                var that = this,
                    delta = that._actualPosition - that._zeroPosition;
                that._rootElement.move(that.vertical ? 0 : delta, that.vertical ? delta : 0);
                that._trackerElement && that._trackerElement.move(that.vertical ? 0 : delta, that.vertical ? delta : 0)
            },
            _isEnabled: function() {
                this.vertical = this._options.vertical;
                return this._options.length > 0 && this._options.width > 0
            },
            _isVisible: function(layout) {
                return true
            },
            _getTrackerSettings: function() {
                var options = this._options,
                    x1,
                    x2,
                    y1,
                    y2,
                    width = options.width / 2,
                    length = options.length / 2,
                    p = this._zeroPosition;
                width > 10 || (width = 10);
                length > 10 || (length = 10);
                if (this.vertical) {
                    x1 = options.x - length;
                    x2 = options.x + length;
                    y1 = p + width;
                    y2 = p - width
                }
                else {
                    x1 = p - width;
                    x2 = p + width;
                    y1 = options.y + length;
                    y2 = options.y - length
                }
                return {points: [x1, y1, x1, y2, x2, y2, x2, y1]}
            },
            _render: function() {
                var that = this;
                that._zeroPosition = that._translator.getCodomainStart()
            },
            _clear: function() {
                delete this._element
            },
            measure: function(layout) {
                var p = this.vertical ? layout.x : layout.y;
                return {
                        min: p - this._options.length / 2,
                        max: p + this._options.length / 2
                    }
            },
            getTooltipParameters: function() {
                var that = this,
                    options = that._options,
                    p = that._actualPosition,
                    parameters = {
                        x: p,
                        y: p,
                        value: that._currentValue,
                        color: options.color,
                        offset: options.width / 2
                    };
                that.vertical ? parameters.x = options.x : parameters.y = options.y;
                return parameters
            }
        });
        linearNeedles.RectangleNeedle = linearNeedles.SimpleIndicator.inherit({_render: function() {
                var that = this,
                    options = that._options,
                    p,
                    x1,
                    x2,
                    y1,
                    y2;
                that.callBase();
                p = that._zeroPosition;
                if (that.vertical) {
                    x1 = options.x - options.length / 2;
                    x2 = options.x + options.length / 2;
                    y1 = p + options.width / 2;
                    y2 = p - options.width / 2
                }
                else {
                    x1 = p - options.width / 2;
                    x2 = p + options.width / 2;
                    y1 = options.y + options.length / 2;
                    y2 = options.y - options.length / 2
                }
                that._element = that._element || that._renderer.createArea().append(that._rootElement);
                that._element.applySettings({points: [x1, y1, x1, y2, x2, y2, x2, y1]})
            }});
        linearNeedles.RhombusNeedle = linearNeedles.SimpleIndicator.inherit({_render: function() {
                var that = this,
                    options = that._options,
                    x,
                    y,
                    dx,
                    dy;
                that.callBase();
                if (that.vertical) {
                    x = options.x;
                    y = that._zeroPosition;
                    dx = options.length / 2 || 0;
                    dy = options.width / 2 || 0
                }
                else {
                    x = that._zeroPosition;
                    y = options.y;
                    dx = options.width / 2 || 0;
                    dy = options.length / 2 || 0
                }
                that._element = that._element || that._renderer.createArea().append(that._rootElement);
                that._element.applySettings({points: [x - dx, y, x, y - dy, x + dx, y, x, y + dy]})
            }});
        linearNeedles.CircleNeedle = linearNeedles.SimpleIndicator.inherit({_render: function() {
                var that = this,
                    options = that._options,
                    x,
                    y,
                    r;
                that.callBase();
                if (that.vertical) {
                    x = options.x;
                    y = that._zeroPosition
                }
                else {
                    x = that._zeroPosition;
                    y = options.y
                }
                r = options.length / 2 || 0;
                that._element = that._element || that._renderer.createCircle().append(that._rootElement);
                that._element.applySettings({
                    cx: x,
                    cy: y,
                    r: r
                })
            }})
    })(DevExpress);
    /*! Module viz-gauges, file circularMarker.js */
    (function(DX, undefined) {
        var circularMarkers = DX.viz.gauges.__internals.circularMarkers;
        var _Number = Number;
        circularMarkers.TriangleMarker = DX.viz.gauges.__internals.circularNeedles.SimpleIndicator.inherit({
            _isEnabled: function() {
                return this._options.length > 0 && this._options.width > 0
            },
            _isVisible: function(layout) {
                return layout.radius > 0
            },
            _render: function() {
                var that = this,
                    options = that._options,
                    x = options.x,
                    y1 = options.y - options.radius,
                    dx = options.width / 2 || 0,
                    y2 = y1 - _Number(options.length),
                    settings;
                that._element = that._element || that._renderer.createArea().append(that._rootElement);
                settings = {
                    points: [x, y1, x - dx, y2, x + dx, y2],
                    stroke: 'none',
                    strokeWidth: 0
                };
                if (options.space > 0) {
                    settings.strokeWidth = Math.min(options.space, options.width / 4) || 0;
                    settings.stroke = settings.strokeWidth > 0 ? options.containerBackgroundColor || 'none' : 'none'
                }
                that._element.applySettings(settings)
            },
            _clear: function() {
                delete this._element
            },
            _getTrackerSettings: function() {
                var options = this._options,
                    x = options.x,
                    y = options.y - options.radius - options.length / 2,
                    width = options.width / 2,
                    length = options.length / 2;
                width > 10 || (width = 10);
                length > 10 || (length = 10);
                return {points: [x - width, y - length, x - width, y + length, x + width, y + length, x + width, y - length]}
            },
            measure: function(layout) {
                return {
                        min: layout.radius,
                        max: layout.radius + _Number(this._options.length)
                    }
            },
            getTooltipParameters: function() {
                var options = this._options,
                    cossin = DX.utils.getCosAndSin(this._actualPosition),
                    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({
            _isEnabled: function() {
                return true
            },
            _isVisible: function(layout) {
                return layout.radius > 0
            },
            _getTextCloudOptions: function() {
                var that = this,
                    cossin = DX.utils.getCosAndSin(that._actualPosition),
                    nangle = DX.utils.normalizeAngle(that._actualPosition);
                return {
                        x: that._options.x + cossin.cos * that._options.radius,
                        y: that._options.y - cossin.sin * that._options.radius,
                        type: nangle > 270 ? 'left-top' : nangle > 180 ? 'top-right' : nangle > 90 ? 'right-bottom' : 'bottom-left'
                    }
            },
            measure: function(layout) {
                var that = this;
                that._measureText();
                return {
                        min: layout.radius,
                        max: layout.radius,
                        horizontalOffset: that._textFullWidth + (_Number(that._options.arrowLength) || 0),
                        verticalOffset: that._textFullHeight + (_Number(that._options.arrowLength) || 0)
                    }
            }
        })
    })(DevExpress);
    /*! Module viz-gauges, file linearMarker.js */
    (function(DX, undefined) {
        var linearMarkers = DX.viz.gauges.__internals.linearMarkers;
        var _Number = Number,
            _String = String;
        linearMarkers.TriangleMarker = DX.viz.gauges.__internals.linearNeedles.SimpleIndicator.inherit({
            _isEnabled: function() {
                var that = this;
                that.vertical = that._options.vertical;
                that._inverted = that.vertical ? _String(that._options.horizontalOrientation).toLowerCase() === 'right' : _String(that._options.verticalOrientation).toLowerCase() === 'bottom';
                return that._options.length > 0 && that._options.width > 0
            },
            _isVisible: function(layout) {
                return true
            },
            _render: function() {
                var that = this,
                    options = that._options,
                    x1,
                    x2,
                    y1,
                    y2,
                    settings = {
                        stroke: 'none',
                        strokeWidth: 0
                    };
                that.callBase();
                if (that.vertical) {
                    x1 = options.x;
                    y1 = that._zeroPosition;
                    x2 = x1 + _Number(that._inverted ? options.length : -options.length);
                    settings.points = [x1, y1, x2, y1 - options.width / 2, x2, y1 + options.width / 2]
                }
                else {
                    y1 = options.y;
                    x1 = that._zeroPosition;
                    y2 = y1 + _Number(that._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 = Math.min(options.space, options.width / 4) || 0;
                    settings.stroke = settings.strokeWidth > 0 ? options.containerBackgroundColor || 'none' : 'none'
                }
                that._element = that._element || that._renderer.createArea().append(that._rootElement);
                that._element.applySettings(settings)
            },
            _getTrackerSettings: function() {
                var that = this,
                    options = that._options,
                    width = options.width / 2,
                    length = _Number(options.length),
                    x1,
                    x2,
                    y1,
                    y2,
                    result;
                width > 10 || (width = 10);
                length > 20 || (length = 20);
                if (that.vertical) {
                    x1 = x2 = options.x;
                    x2 = x1 + (that._inverted ? length : -length);
                    y1 = that._zeroPosition + width;
                    y2 = that._zeroPosition - width;
                    result = [x1, y1, x2, y1, x2, y2, x1, y2]
                }
                else {
                    y1 = options.y;
                    y2 = y1 + (that._inverted ? length : -length);
                    x1 = that._zeroPosition - width;
                    x2 = that._zeroPosition + width;
                    result = [x1, y1, x1, y2, x2, y2, x2, y1]
                }
                return {points: result}
            },
            measure: function(layout) {
                var that = this,
                    length = _Number(that._options.length),
                    minbound,
                    maxbound;
                if (that.vertical) {
                    minbound = maxbound = layout.x;
                    if (that._inverted)
                        maxbound = minbound + length;
                    else
                        minbound = maxbound - length
                }
                else {
                    minbound = maxbound = layout.y;
                    if (that._inverted)
                        maxbound = minbound + length;
                    else
                        minbound = maxbound - length
                }
                return {
                        min: minbound,
                        max: maxbound,
                        indent: that._options.width / 2
                    }
            },
            getTooltipParameters: function() {
                var that = this,
                    options = that._options,
                    s = (that._inverted ? options.length : -options.length) / 2,
                    parameters = that.callBase();
                that.vertical ? parameters.x += s : parameters.y += s;
                parameters.offset = options.length / 2;
                return parameters
            }
        });
        linearMarkers.TextCloudMarker = DX.viz.gauges.__internals.BaseTextCloudMarker.inherit({
            _isEnabled: function() {
                var that = this;
                that.vertical = that._options.vertical;
                that._inverted = that.vertical ? _String(that._options.horizontalOrientation).toLowerCase() === 'right' : _String(that._options.verticalOrientation).toLowerCase() === 'bottom';
                return true
            },
            _isVisible: function(layout) {
                return true
            },
            _getTextCloudOptions: function() {
                var that = this,
                    x = that._actualPosition,
                    y = that._actualPosition,
                    type;
                if (that.vertical) {
                    x = that._options.x;
                    type = that._inverted ? 'top-left' : 'top-right'
                }
                else {
                    y = that._options.y;
                    type = that._inverted ? 'right-top' : 'right-bottom'
                }
                return {
                        x: x,
                        y: y,
                        type: type
                    }
            },
            measure: function(layout) {
                var that = this,
                    minbound,
                    maxbound,
                    arrowLength = _Number(that._options.arrowLength) || 0,
                    indent;
                that._measureText();
                if (that.vertical) {
                    indent = that._textFullHeight;
                    if (that._inverted) {
                        minbound = layout.x;
                        maxbound = layout.x + arrowLength + that._textFullWidth
                    }
                    else {
                        minbound = layout.x - arrowLength - that._textFullWidth;
                        maxbound = layout.x
                    }
                }
                else {
                    indent = that._textFullWidth;
                    if (that._inverted) {
                        minbound = layout.y;
                        maxbound = layout.y + arrowLength + that._textFullHeight
                    }
                    else {
                        minbound = layout.y - arrowLength - that._textFullHeight;
                        maxbound = layout.y
                    }
                }
                return {
                        min: minbound,
                        max: maxbound,
                        indent: indent
                    }
            }
        })
    })(DevExpress);
    /*! Module viz-gauges, file circularRangeBar.js */
    (function(DX, undefined) {
        var _Number = Number,
            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({
            _isEnabled: function() {
                return this._options.size > 0
            },
            _isVisible: function(layout) {
                return layout.radius - _Number(this._options.size) > 0
            },
            _createBarItem: function() {
                return this._renderer.createArc().append(this._rootElement)
            },
            _createTracker: function() {
                return this._renderer.createArc()
            },
            _setBarSides: function() {
                var that = this;
                that._maxSide = that._options.radius;
                that._minSide = that._maxSide - _Number(that._options.size)
            },
            _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
            },
            _setTextItemsSides: function() {
                var that = this,
                    options = that._options;
                that._lineFrom = options.y - options.radius;
                that._lineTo = that._lineFrom - _Number(options.text.indent);
                that._textRadius = options.radius + _Number(options.text.indent)
            },
            _getPositions: function() {
                var that = this,
                    basePosition = that._basePosition,
                    actualPosition = that._actualPosition,
                    mainPosition1,
                    mainPosition2;
                if (basePosition >= actualPosition) {
                    mainPosition1 = basePosition;
                    mainPosition2 = actualPosition
                }
                else {
                    mainPosition1 = actualPosition;
                    mainPosition2 = basePosition
                }
                return {
                        start: that._startPosition,
                        end: that._endPosition,
                        main1: mainPosition1,
                        main2: mainPosition2,
                        back1: min(mainPosition1 + that._space, that._startPosition),
                        back2: max(mainPosition2 - that._space, that._endPosition)
                    }
            },
            _buildItemSettings: function(from, to) {
                var that = this;
                return {
                        x: that._options.x,
                        y: that._options.y,
                        innerRadius: that._minSide,
                        outerRadius: that._maxSide,
                        startAngle: to,
                        endAngle: from
                    }
            },
            _updateTextPosition: function() {
                var that = this,
                    cossin = getCosAndSin(that._actualPosition),
                    x = that._options.x + that._textRadius * cossin.cos,
                    y = that._options.y - that._textRadius * cossin.sin;
                x += cossin.cos * that._textWidth * 0.6;
                y -= cossin.sin * that._textHeight * 0.6;
                that._text.applySettings({
                    x: x,
                    y: y + that._textVerticalOffset
                })
            },
            _updateLinePosition: function() {
                var that = this,
                    x = that._options.x,
                    x1,
                    x2;
                if (that._basePosition > that._actualPosition) {
                    x1 = x - 2;
                    x2 = x
                }
                else if (that._basePosition < that._actualPosition) {
                    x1 = x;
                    x2 = x + 2
                }
                else {
                    x1 = x - 1;
                    x2 = x + 1
                }
                that._line.applySettings({points: [x1, that._lineFrom, x1, that._lineTo, x2, that._lineTo, x2, that._lineFrom]});
                that._line.rotate(convertAngleToRendererSpace(that._actualPosition), x, that._options.y)
            },
            _getTooltipPosition: function() {
                var that = this,
                    cossin = getCosAndSin((that._basePosition + that._actualPosition) / 2),
                    r = (that._minSide + that._maxSide) / 2;
                return {
                        x: that._options.x + cossin.cos * r,
                        y: that._options.y - cossin.sin * r
                    }
            },
            measure: function(layout) {
                var that = this,
                    result = {
                        min: layout.radius - _Number(that._options.size),
                        max: layout.radius
                    };
                that._measureText();
                if (that._hasText) {
                    result.max += _Number(that._options.text.indent);
                    result.horizontalOffset = that._textWidth;
                    result.verticalOffset = that._textHeight
                }
                return result
            }
        })
    })(DevExpress);
    /*! Module viz-gauges, file linearRangeBar.js */
    (function(DX, undefined) {
        var _Number = Number,
            _String = String;
        DX.viz.gauges.__internals.LinearRangeBar = DX.viz.gauges.__internals.BaseRangeBar.inherit({
            _isEnabled: function() {
                var that = this;
                that.vertical = that._options.vertical;
                that._inverted = that.vertical ? _String(that._options.horizontalOrientation).toLowerCase() === 'right' : _String(that._options.verticalOrientation).toLowerCase() === 'bottom';
                return that._options.size > 0
            },
            _isVisible: function(layout) {
                return true
            },
            _createBarItem: function() {
                return this._renderer.createArea().append(this._rootElement)
            },
            _createTracker: function() {
                return this._renderer.createArea()
            },
            _setBarSides: function() {
                var that = this,
                    options = that._options,
                    size = _Number(options.size),
                    minSide,
                    maxSide;
                if (that.vertical)
                    if (that._inverted) {
                        minSide = options.x;
                        maxSide = options.x + size
                    }
                    else {
                        minSide = options.x - size;
                        maxSide = options.x
                    }
                else if (that._inverted) {
                    minSide = options.y;
                    maxSide = options.y + size
                }
                else {
                    minSide = options.y - size;
                    maxSide = options.y
                }
                that._minSide = minSide;
                that._maxSide = maxSide;
                that._minBound = minSide;
                that._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 that = this,
                    indent = _Number(that._options.text.indent);
                if (indent > 0) {
                    that._lineStart = that._maxSide;
                    that._lineEnd = that._maxSide + indent;
                    that._textPosition = that._lineEnd + (that.vertical ? 2 : that._textHeight / 2);
                    that._maxBound = that._textPosition + (that.vertical ? that._textWidth : that._textHeight / 2)
                }
                else if (indent < 0) {
                    that._lineStart = that._minSide;
                    that._lineEnd = that._minSide + indent;
                    that._textPosition = that._lineEnd - (that.vertical ? 2 : that._textHeight / 2);
                    that._minBound = that._textPosition - (that.vertical ? that._textWidth : that._textHeight / 2)
                }
            },
            _getPositions: function() {
                var that = this,
                    options = that._options,
                    startPosition = that._startPosition,
                    endPosition = that._endPosition,
                    space = that._space,
                    basePosition = that._basePosition,
                    actualPosition = that._actualPosition,
                    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 that = this,
                    side1 = that._minSide,
                    side2 = that._maxSide;
                var points = that.vertical ? [side1, from, side1, to, side2, to, side2, from] : [from, side1, from, side2, to, side2, to, side1];
                return {points: points}
            },
            _updateTextPosition: function() {
                var that = this;
                that._text.applySettings(that.vertical ? {
                    x: that._textPosition,
                    y: that._actualPosition + that._textVerticalOffset
                } : {
                    x: that._actualPosition,
                    y: that._textPosition + that._textVerticalOffset
                })
            },
            _updateLinePosition: function() {
                var that = this,
                    actualPosition = that._actualPosition,
                    side1,
                    side2,
                    points;
                if (that.vertical) {
                    if (that._basePosition >= actualPosition) {
                        side1 = actualPosition;
                        side2 = actualPosition + 2
                    }
                    else {
                        side1 = actualPosition - 2;
                        side2 = actualPosition
                    }
                    points = [that._lineStart, side1, that._lineStart, side2, that._lineEnd, side2, that._lineEnd, side1]
                }
                else {
                    if (that._basePosition <= actualPosition) {
                        side1 = actualPosition - 2;
                        side2 = actualPosition
                    }
                    else {
                        side1 = actualPosition;
                        side2 = actualPosition + 2
                    }
                    points = [side1, that._lineStart, side1, that._lineEnd, side2, that._lineEnd, side2, that._lineStart]
                }
                that._line.applySettings({points: points})
            },
            _getTooltipPosition: function() {
                var that = this,
                    crossCenter = (that._minSide + that._maxSide) / 2,
                    alongCenter = (that._basePosition + that._actualPosition) / 2,
                    position = {};
                if (that.vertical)
                    position = {
                        x: crossCenter,
                        y: alongCenter
                    };
                else
                    position = {
                        x: alongCenter,
                        y: crossCenter
                    };
                return position
            },
            measure: function(layout) {
                var that = this,
                    size = _Number(that._options.size),
                    textIndent = _Number(that._options.text.indent),
                    minbound,
                    maxbound,
                    indent;
                that._measureText();
                if (that.vertical) {
                    minbound = maxbound = layout.x;
                    if (that._inverted)
                        maxbound = maxbound + size;
                    else
                        minbound = minbound - size;
                    if (that._hasText) {
                        indent = that._textHeight / 2;
                        if (textIndent > 0)
                            maxbound += textIndent + that._textWidth;
                        if (textIndent < 0)
                            minbound += textIndent - that._textWidth
                    }
                }
                else {
                    minbound = maxbound = layout.y;
                    if (that._inverted)
                        maxbound = maxbound + size;
                    else
                        minbound = minbound - size;
                    if (that._hasText) {
                        indent = that._textWidth / 2;
                        if (textIndent > 0)
                            maxbound += textIndent + that._textHeight;
                        if (textIndent < 0)
                            minbound += textIndent - that._textHeight
                    }
                }
                return {
                        min: minbound,
                        max: maxbound,
                        indent: indent
                    }
            }
        })
    })(DevExpress);
    /*! Module viz-gauges, file rangeContainer.js */
    (function(DX, $, undefined) {
        var _Number = Number,
            _String = String,
            _max = Math.max,
            _abs = Math.abs,
            _isString = DX.utils.isString,
            _isArray = DX.utils.isArray,
            _isFinite = isFinite,
            _each = $.each,
            _map = $.map;
        var _Palette = DX.viz.core.Palette;
        DX.viz.gauges.__internals.BaseRangeContainer = DX.Class.inherit({
            ctor: function(parameters) {
                var that = this;
                that._renderer = parameters.renderer;
                that._container = parameters.container;
                that._translator = parameters.translator;
                that._root = that._renderer.createGroup({'class': 'dxg-range-container'})
            },
            dispose: function() {
                var that = this;
                that._renderer = that._container = that._translator = that._root = null
            },
            clean: function() {
                this._root.detach().clear();
                this._options = this.enabled = null;
                return this
            },
            _getRanges: function() {
                var that = this,
                    options = that._options,
                    translator = that._translator,
                    totalStart = translator.getDomain()[0],
                    totalEnd = translator.getDomain()[1],
                    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 = new _Palette(options.palette, {
                        type: 'indicatingSet',
                        theme: options.themeName
                    }),
                    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 !== undefined && !_isArray(options.ranges))
                    return null;
                if (!(startWidth >= 0 && endWidth >= 0 && startWidth + endWidth > 0))
                    return null;
                list = _map(_isArray(options.ranges) ? options.ranges : [], function(rangeOptions, i) {
                    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,
                            classIndex: i
                        } : null
                });
                _each(list, function(i, item) {
                    var paletteColor = palette.getNextColor();
                    item.color = _isString(item.color) && item.color || paletteColor || 'none';
                    item.className = 'dxg-range dxg-range-' + item.classIndex;
                    delete item.classIndex
                });
                _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) && (sub.className = range.className) && newRanges.push(sub);
                        (sub = subs[1]) && (sub.color = range.color) && (sub.className = range.className) && 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.className = 'dxg-range dxg-background-range';
                    ranges.push(range)
                });
                _each(ranges, function(_, range) {
                    range.startWidth = (range.start - totalStart) / totalDelta * deltaWidth + startWidth;
                    range.endWidth = (range.end - totalStart) / totalDelta * deltaWidth + startWidth
                });
                return ranges
            },
            render: function(options) {
                var that = this;
                that._options = options;
                that._processOptions();
                that._ranges = that._getRanges();
                if (that._ranges) {
                    that.enabled = true;
                    that._root.append(that._container)
                }
                return that
            },
            resize: function(layout) {
                var that = this;
                that._root.clear();
                if (that._isVisible(layout))
                    _each(that._ranges, function(_, range) {
                        that._createRange(range, layout).applySettings({
                            fill: range.color,
                            'class': range.className
                        }).append(that._root)
                    });
                return that
            },
            _processOptions: null,
            _isVisible: null,
            _createRange: null
        });
        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.CircularRangeContainer = DX.viz.gauges.__internals.BaseRangeContainer.inherit({
            _processOptions: function() {
                var that = this;
                that._inner = that._outer = 0;
                switch (_String(that._options.orientation).toLowerCase()) {
                    case'inside':
                        that._inner = 1;
                        break;
                    case'center':
                        that._inner = that._outer = 0.5;
                        break;
                    default:
                        that._outer = 1;
                        break
                }
            },
            _isVisible: function(layout) {
                var width = this._options.width;
                width = _Number(width) || _max(_Number(width.start), _Number(width.end));
                return layout.radius - this._inner * width > 0
            },
            _createRange: function(range, layout) {
                var that = this,
                    width = (range.startWidth + range.endWidth) / 2;
                return that._renderer.createArc(layout.x, layout.y, layout.radius + that._outer * width, layout.radius - that._inner * width, that._translator.translate(range.end), that._translator.translate(range.start))
            },
            measure: function(layout) {
                var width = this._options.width;
                width = _Number(width) || _max(_Number(width.start), _Number(width.end));
                return {
                        min: layout.radius - this._inner * width,
                        max: layout.radius + this._outer * width
                    }
            }
        });
        DX.viz.gauges.__internals.LinearRangeContainer = DX.viz.gauges.__internals.BaseRangeContainer.inherit({
            _processOptions: function() {
                var that = this;
                that.vertical = that._options.vertical;
                that._inner = that._outer = 0;
                if (that.vertical)
                    switch (_String(that._options.horizontalOrientation).toLowerCase()) {
                        case'left':
                            that._inner = 1;
                            break;
                        case'center':
                            that._inner = that._outer = 0.5;
                            break;
                        default:
                            that._outer = 1;
                            break
                    }
                else
                    switch (_String(that._options.verticalOrientation).toLowerCase()) {
                        case'top':
                            that._inner = 1;
                            break;
                        case'middle':
                            that._inner = that._outer = 0.5;
                            break;
                        default:
                            that._outer = 1;
                            break
                    }
            },
            _isVisible: function(layout) {
                return true
            },
            _createRange: function(range, layout) {
                var that = this,
                    inner = that._inner,
                    outer = that._outer,
                    startPosition = that._translator.translate(range.start),
                    endPosition = that._translator.translate(range.end),
                    points;
                if (that.vertical)
                    points = [layout.x - range.startWidth * inner, startPosition, layout.x - range.endWidth * inner, endPosition, layout.x + range.endWidth * outer, endPosition, layout.x + range.startWidth * outer, startPosition];
                else
                    points = [startPosition, layout.y + range.startWidth * outer, startPosition, layout.y - range.startWidth * inner, endPosition, layout.y - range.endWidth * inner, endPosition, layout.y + range.endWidth * outer];
                return that._renderer.createArea(points)
            },
            measure: function(layout) {
                var result = {};
                result.min = result.max = layout[this.vertical ? 'x' : 'y'];
                var width = this._options.width;
                width = _Number(width) || _max(_Number(width.start), _Number(width.end));
                result.min -= this._inner * width;
                result.max += this._outer * width;
                return result
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file title.js */
    (function(DX, $, undefined) {
        var _isString = DX.utils.isString,
            _max = Math.max,
            _extend = $.extend;
        DX.viz.gauges.__internals.Title = DX.Class.inherit({
            ctor: function(parameters) {
                this._renderer = parameters.renderer;
                this._container = parameters.container
            },
            dispose: function() {
                this._renderer = this._container = null;
                return this
            },
            clean: function() {
                var that = this;
                if (that._root) {
                    that._root.detach().clear();
                    that._root = that._layout = null
                }
                return that
            },
            render: function(titleOptions, subtitleOptions) {
                var that = this,
                    hasTitle = _isString(titleOptions.text) && titleOptions.text.length > 0,
                    hasSubtitle = _isString(subtitleOptions.text) && subtitleOptions.text.length > 0;
                if (!hasTitle && !hasSubtitle)
                    return that;
                that._root = that._renderer.createGroup({'class': 'dxg-title'}).append(that._container);
                var title = hasTitle ? that._renderer.createText(titleOptions.text, 0, 0, {
                        align: 'center',
                        font: titleOptions.font
                    }).append(that._root) : null,
                    subtitle = hasSubtitle ? that._renderer.createText(subtitleOptions.text, 0, 0, {
                        align: 'center',
                        font: subtitleOptions.font
                    }).append(that._root) : null,
                    titleBox = title ? title.getBBox() : {},
                    subtitleBox = subtitle ? subtitle.getBBox() : {},
                    y = 0;
                if (title) {
                    y += -titleBox.y;
                    title.applySettings({
                        x: 0,
                        y: y
                    })
                }
                if (subtitle) {
                    y += -subtitleBox.y;
                    subtitle.applySettings({
                        x: 0,
                        y: y
                    })
                }
                that._layout = _extend({
                    width: _max(titleBox.width || 0, subtitleBox.width || 0),
                    height: title && subtitle ? -titleBox.y + subtitleBox.height : titleBox.height || subtitleBox.height
                }, titleOptions.layout);
                return that
            },
            getLayoutOptions: function() {
                return this._layout
            },
            locate: function(left, top) {
                this._root.applySettings({
                    translateX: left + this._layout.width / 2,
                    translateY: top
                });
                return this
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file tooltip.js */
    (function(DX, $, undefined) {
        var _extend = $.extend;
        DX.viz.gauges.__internals.Tooltip = DX.viz.core.Tooltip.inherit({
            ctor: function(parameters) {
                var that = this;
                that._container = parameters.container;
                that._tracker = parameters.tracker;
                that._root = parameters.renderer.createGroup({'class': 'dxg-tooltip'});
                that.callBase(null, that._root, parameters.renderer);
                that._setTrackerCallbacks()
            },
            dispose: function() {
                var that = this;
                that._container = that._tracker = that._root = null;
                return that._shadow ? that.callBase.apply(that, arguments) : that
            },
            _setTrackerCallbacks: function() {
                var that = this;
                function prepareCallback(target, info) {
                    var tooltipParameters = target.getTooltipParameters(),
                        formatObject = _extend({
                            value: tooltipParameters.value,
                            valueText: that.formatValue(tooltipParameters.value),
                            color: tooltipParameters.color
                        }, info);
                    return that.prepare(formatObject, {
                            x: tooltipParameters.x,
                            y: tooltipParameters.y,
                            offset: tooltipParameters.offset
                        })
                }
                function showCallback() {
                    return that.show()
                }
                function hideCallback() {
                    return that.hide()
                }
                that._tracker.setCallbacks({
                    'tooltip-prepare': prepareCallback,
                    'tooltip-show': showCallback,
                    'tooltip-hide': hideCallback
                })
            },
            clean: function() {
                this._root.detach();
                return this
            },
            render: function(options, size) {
                var that = this;
                options.canvasWidth = size.width;
                options.canvasHeight = size.height;
                options.text = {'class': 'dxg-text'};
                that.update(options);
                that._tracker.setTooltipState(that.enabled());
                that.enabled() && that._root.append(that._container);
                return that
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file layoutManager.js */
    (function(DX, $, undefined) {
        var _Number = Number,
            _String = String,
            _min = Math.min,
            _max = Math.max,
            _each = $.each;
        function patchLayoutOptions(options) {
            if (options.position) {
                var position = _String(options.position).toLowerCase().split('-');
                options.verticalAlignment = position[0];
                options.horizontalAlignment = position[1]
            }
        }
        DX.viz.gauges.__internals.LayoutManager = DX.Class.inherit({
            setRect: function(rect) {
                this._currentRect = rect.clone();
                return this
            },
            getRect: function() {
                return this._currentRect.clone()
            },
            beginLayout: function(rect) {
                this._rootRect = rect.clone();
                this._currentRect = rect.clone();
                this._cache = [];
                return this
            },
            applyLayout: function(target) {
                var options = target.getLayoutOptions();
                if (!options)
                    return this;
                var currentRect = this._currentRect,
                    verticalOverlay = _Number(options.overlay) || 0;
                patchLayoutOptions(options);
                switch (_String(options.verticalAlignment).toLowerCase()) {
                    case'bottom':
                        currentRect.bottom -= _max(options.height - verticalOverlay, 0);
                        break;
                    default:
                        currentRect.top += _max(options.height - verticalOverlay, 0);
                        break
                }
                this._cache.push({
                    target: target,
                    options: options
                });
                return this
            },
            endLayout: function() {
                var that = this,
                    rootRect = that._rootRect,
                    currentRect = that._currentRect;
                _each(that._cache, function(_, cacheItem) {
                    var options = cacheItem.options,
                        left,
                        top,
                        verticalOverlay = _Number(options.overlay) || 0;
                    switch (_String(options.verticalAlignment).toLowerCase()) {
                        case'bottom':
                            top = currentRect.bottom - verticalOverlay;
                            currentRect.bottom += _max(options.height - verticalOverlay, 0);
                            break;
                        default:
                            top = currentRect.top - options.height + verticalOverlay;
                            currentRect.top -= _max(options.height - verticalOverlay, 0);
                            break
                    }
                    switch (_String(options.horizontalAlignment).toLowerCase()) {
                        case'left':
                            left = rootRect.left;
                            break;
                        case'right':
                            left = rootRect.right - options.width;
                            break;
                        default:
                            left = rootRect.horizontalMiddle() - options.width / 2;
                            break
                    }
                    cacheItem.target.locate(left, top)
                });
                that._cache = null;
                return that
            },
            selectRectByAspectRatio: function(aspectRatio, margins) {
                var rect = this._currentRect.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._currentRect.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-gauges, file themeManager.js */
    (function(DX, $, undefined) {
        var _extend = $.extend;
        DX.viz.gauges.__internals.ThemeManager = DX.viz.core.BaseThemeManager.inherit({
            _themeSection: 'gauge',
            _initializeTheme: function() {
                var that = this;
                if (that._subTheme) {
                    var subTheme = _extend(true, {}, that._theme[that._subTheme], that._theme);
                    _extend(true, that._theme, subTheme)
                }
                that._initializeFont(that._theme.scale.label.font);
                that._initializeFont(that._theme.valueIndicator.rangebar.text.font);
                that._initializeFont(that._theme.subvalueIndicator.textcloud.text.font);
                that._initializeFont(that._theme.valueIndicators.rangebar.text.font);
                that._initializeFont(that._theme.valueIndicators.textcloud.text.font);
                that._initializeFont(that._theme.title.font);
                that._initializeFont(that._theme.subtitle.font);
                that._initializeFont(that._theme.tooltip.font);
                that._initializeFont(that._theme.indicator.text.font);
                that._initializeFont(that._theme.loadingIndicator.font)
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file presetManager.js */
    /*! Module viz-gauges, file baseGauge.js */
    (function(DX, $, undefined) {
        var _Number = Number,
            _isNumber = DX.utils.isNumber,
            _isString = DX.utils.isString,
            _getAppropriateFormat = DX.utils.getAppropriateFormat,
            _extend = $.extend,
            _each = $.each;
        DX.viz.gauges.__internals.BaseGauge = DX.viz.core.BaseWidget.inherit({
            _init: function() {
                var that = this;
                that.callBase.apply(that, arguments);
                that._renderer = that._factory.createRenderer({
                    width: 1,
                    height: 1,
                    pathModified: that.option('pathModified'),
                    rtl: that.option('rtlEnabled')
                });
                that._root = that._renderer.getRoot();
                that._root.applySettings({'class': 'dxg ' + that._rootClass});
                that._translator = that._factory.createTranslator();
                that._themeManager = that._factory.createThemeManager();
                that._tracker = that._factory.createTracker({
                    renderer: that._renderer,
                    container: that._root
                });
                that._layoutManager = that._factory.createLayoutManager();
                that._tooltip = that._factory.createTooltip({
                    renderer: that._renderer,
                    container: that._root,
                    tracker: that._tracker
                });
                that._title = that._factory.createTitle({
                    renderer: that._renderer,
                    container: that._root
                });
                that._deltaIndicator = that._factory.createDeltaIndicator({
                    renderer: that._renderer,
                    container: that._root
                });
                that._setupDomain();
                that._themeManager.setTheme(that.option('theme'))
            },
            _dispose: function() {
                var that = this;
                that.callBase.apply(that, arguments);
                that._renderer.dispose();
                that._themeManager.dispose();
                that._tracker.dispose();
                that._title.dispose();
                that._deltaIndicator && that._deltaIndicator.dispose();
                that._tooltip.dispose();
                that._disposeLoadIndicator();
                that._renderer = that._root = that._translator = that._themeManager = that._tracker = that._layoutManager = that._title = that._tooltip = null
            },
            _refresh: function() {
                var that = this,
                    callBase = that.callBase;
                that._endLoading(function() {
                    callBase.call(that)
                })
            },
            _clean: function() {
                this._cleanCore()
            },
            _render: function() {
                var that = this;
                that._setupCodomain();
                that._setupAnimationSettings();
                if (that._calculateSize() && that._checkDomain()) {
                    that._renderer.draw(that._element()[0]);
                    that._setupDefaultFormat();
                    that._renderCore()
                }
                that._drawn()
            },
            _cleanCore: function() {
                var that = this;
                that._tooltip.clean();
                that._title.clean();
                that._deltaIndicator && that._deltaIndicator.clean();
                that._tracker.deactivate();
                that._cleanContent()
            },
            _renderCore: function() {
                var that = this;
                that._title.render(_extend(true, {}, that._themeManager.theme()['title'], processTitleOptions(that.option('title'))), _extend(true, {}, that._themeManager.theme()['subtitle'], processTitleOptions(that.option('subtitle'))));
                that._deltaIndicator && that._deltaIndicator.render(_extend(true, {}, that._themeManager.theme()['indicator'], that.option('indicator')));
                that._layoutManager.beginLayout(that._rootRect);
                _each([that._deltaIndicator, that._title], function(_, item) {
                    item && that._layoutManager.applyLayout(item)
                });
                that._mainRect = that._layoutManager.getRect();
                that._renderContent();
                that._layoutManager.endLayout();
                that._tooltip.render(_extend(true, {}, that._themeManager.theme()['tooltip'], that.option('tooltip')), {
                    width: that._width,
                    height: that._height
                });
                that._tracker.activate();
                that._updateLoadIndicator(undefined, that._width, that._height);
                that._noAnimation = null;
                that.option('debugMode') === true && that._renderDebugInfo();
                that._debug_rendered && that._debug_rendered()
            },
            _renderDebugInfo: function() {
                var that = this,
                    group = that._debugGroup || that._renderer.createGroup({'class': 'debug-info'}).append(),
                    rect;
                group.clear();
                rect = that._rootRect;
                that._renderer.createRect(rect.left, rect.top, rect.width(), rect.height(), 0, {
                    stroke: '#000000',
                    strokeWidth: 1,
                    fill: 'none'
                }).append(group);
                rect = that._mainRect;
                that._renderer.createRect(rect.left, rect.top, rect.width(), rect.height(), 0, {
                    stroke: '#0000FF',
                    strokeWidth: 1,
                    fill: 'none'
                }).append(group);
                rect = that._layoutManager.getRect();
                rect && that._renderer.createRect(rect.left, rect.top, rect.width(), rect.height(), 0, {
                    stroke: '#FF0000',
                    strokeWidth: 1,
                    fill: 'none'
                }).append(group);
                rect = that._title.getLayoutOptions() ? that._title._root.getBBox() : null;
                rect && that._renderer.createRect(rect.x, rect.y, rect.width, rect.height, 0, {
                    stroke: '#00FF00',
                    strokeWidth: 1,
                    fill: 'none'
                }).append(group);
                rect = that._deltaIndicator && that._deltaIndicator.getLayoutOptions() ? that._deltaIndicator._root.getBBox() : null;
                rect && that._renderer.createRect(rect.x, rect.y, rect.width, rect.height, 0, {
                    stroke: '#00FF00',
                    strokeWidth: 1,
                    fill: 'none'
                }).append(group)
            },
            _resize: function() {
                var that = this;
                if (that._calculateSize()) {
                    that._resizing = that._noAnimation = true;
                    that._cleanCore();
                    that._renderCore();
                    that._resizing = null
                }
            },
            render: function(options) {
                options && options.animate !== undefined && !options.animate && (this._noAnimation = true);
                this._refresh();
                return this
            },
            showLoadingIndicator: function() {
                this._showLoadIndicator(this._getLoadIndicatorOption(), {
                    width: this._width,
                    height: this._height
                })
            },
            _getLoadIndicatorOption: function() {
                return _extend(true, {}, this._themeManager.theme()['loadingIndicator'], this.option('loadingIndicator'))
            },
            _optionChanged: function(name, newv, oldv) {
                var that = this;
                switch (name) {
                    case'theme':
                        that._themeManager.setTheme(newv);
                        that._invalidate();
                        break;
                    case'startValue':
                    case'endValue':
                        that._setupDomain();
                        that._invalidate();
                        break;
                    default:
                        that.callBase.apply(that, arguments);
                        break
                }
            },
            _calculateSize: function() {
                var that = this;
                that._calculateSizeCore();
                if (that._width === 0 || that._height === 0 || !that._element().is(':visible')) {
                    that._incidentOccured('W2001', [that.NAME]);
                    return false
                }
                else {
                    that._renderer.resize(that._width, that._height);
                    return true
                }
            },
            _checkDomain: function() {
                var that = this,
                    domain = that._translator.getDomain(),
                    isValid = isFinite(1 / (domain[1] - domain[0]));
                if (!isValid)
                    that._incidentOccured('W2301');
                return isValid
            },
            _setupAnimationSettings: function() {
                var that = this,
                    option = that.option('animation');
                that._animationSettings = null;
                if (option === undefined || option) {
                    if (option === undefined)
                        option = {
                            enabled: that.option('animationEnabled'),
                            duration: that.option('animationDuration')
                        };
                    option = _extend({
                        enabled: true,
                        duration: 1000,
                        easing: 'easeOutCubic'
                    }, option);
                    if (option.enabled && option.duration > 0)
                        that._animationSettings = {
                            duration: _Number(option.duration),
                            easing: option.easing
                        }
                }
                that._containerBackgroundColor = that.option('containerBackgroundColor') || that._themeManager.theme().containerBackgroundColor
            },
            _setupDefaultFormat: function() {
                var domain = this._translator.getDomain();
                this._defaultFormatOptions = _getAppropriateFormat(domain[0], domain[1], this._getApproximateScreenRange())
            },
            _setupDomain: null,
            _calculateSizeCore: null,
            _cleanContent: null,
            _renderContent: null,
            _setupCodomain: null,
            _getApproximateScreenRange: null,
            _factory: {
                createRenderer: DX.viz.core.CoreFactory.createRenderer,
                createTranslator: function() {
                    return new DX.viz.core.Translator1D
                },
                createTracker: function(parameters) {
                    return new DX.viz.gauges.__internals.Tracker(parameters)
                },
                createLayoutManager: function() {
                    return new DX.viz.gauges.__internals.LayoutManager
                },
                createTitle: function(parameters) {
                    return new DX.viz.gauges.__internals.Title(parameters)
                },
                createDeltaIndicator: function(parameters) {
                    return DX.viz.gauges.__internals.DeltaIndicator ? new DX.viz.gauges.__internals.DeltaIndicator(parameters) : null
                },
                createTooltip: function(parameters) {
                    return new DX.viz.gauges.__internals.Tooltip(parameters)
                }
            }
        });
        function processTitleOptions(options) {
            return _isString(options) ? {text: options} : options || {}
        }
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file gauge.js */
    (function(DX, $, undefined) {
        var _Rectangle = DX.viz.core.Rectangle;
        var _isDefined = DX.utils.isDefined,
            _isArray = DX.utils.isArray,
            _isNumber = DX.utils.isNumber,
            _isFinite = isFinite,
            _Number = Number,
            _String = String,
            _abs = Math.abs,
            _extend = $.extend,
            _each = $.each,
            _map = $.map,
            _noop = $.noop;
        var OPTION_VALUE = 'value',
            OPTION_SUBVALUES = 'subvalues';
        DX.viz.gauges.Gauge = DX.viz.gauges.__internals.BaseGauge.inherit({
            _init: function() {
                var that = this;
                that.__value = that.option(OPTION_VALUE);
                that.__subvalues = that.option(OPTION_SUBVALUES);
                if (!_isArray(that.__subvalues))
                    that.__subvalues = _isNumber(that.__subvalues) ? [that.__subvalues] : null;
                that._selectMode();
                that.callBase.apply(that, arguments);
                that._scale = that._createScale({
                    renderer: that._renderer,
                    container: that._root,
                    translator: that._translator
                });
                that._rangeContainer = that._createRangeContainer({
                    renderer: that._renderer,
                    container: that._root,
                    translator: that._translator
                })
            },
            _dispose: function() {
                var that = this;
                that.callBase.apply(that, arguments);
                that._scale.dispose();
                that._rangeContainer.dispose();
                that._disposeValueIndicators();
                that._scale = that._rangeContainer = null
            },
            _disposeValueIndicators: function() {
                var that = this;
                that._valueIndicator && that._valueIndicator.dispose();
                that._subvalueIndicatorsSet && that._subvalueIndicatorsSet.dispose();
                that._valueIndicator = that._subvalueIndicatorsSet = null
            },
            _selectMode: function() {
                var that = this;
                if (that.option(OPTION_VALUE) === undefined && that.option(OPTION_SUBVALUES) === undefined)
                    if (that.option('needles') !== undefined || that.option('markers') !== undefined || that.option('rangeBars') !== undefined) {
                        disableDefaultMode(that);
                        selectObsoleteMode(that)
                    }
                    else if (that.option('valueIndicators') !== undefined) {
                        disableDefaultMode(that);
                        selectHardMode(that)
                    }
            },
            _setupDomain: function() {
                var that = this,
                    scaleOption = that.option('scale') || {},
                    startValue = that.option('startValue'),
                    endValue = that.option('endValue');
                startValue = _isNumber(startValue) ? _Number(startValue) : _isNumber(scaleOption.startValue) ? _Number(scaleOption.startValue) : 0;
                endValue = _isNumber(endValue) ? _Number(endValue) : _isNumber(scaleOption.endValue) ? _Number(scaleOption.endValue) : 100;
                that._baseValue = startValue < endValue ? startValue : endValue;
                that._translator.setDomain(startValue, endValue);
                that._setupValueState()
            },
            _setupValueState: function() {
                this._setupValue();
                this.__subvalues !== null && this._setupSubvalues()
            },
            _calculateSizeCore: function() {
                var that = this,
                    size = that.option('size') || {},
                    margin = that.option('margin') || {};
                if (_Number(size.width) === 0 || _Number(size.height) === 0) {
                    that._width = that._height = 0;
                    that._rootRect = new _Rectangle
                }
                else {
                    var width = size.width > 0 ? _Number(size.width) : that._element().width() || that._getDefaultContainerSize().width,
                        height = size.height > 0 ? _Number(size.height) : that._element().height() || that._getDefaultContainerSize().height,
                        marginL = margin.left > 0 ? _Number(margin.left) : 0,
                        marginR = margin.right > 0 ? _Number(margin.right) : 0,
                        marginT = margin.top > 0 ? _Number(margin.top) : 0,
                        marginB = margin.bottom > 0 ? _Number(margin.bottom) : 0;
                    marginL + marginR >= width && (marginL = marginR = 0);
                    marginT + marginB >= height && (marginT = marginB = 0);
                    that._width = width;
                    that._height = height;
                    that._rootRect = new _Rectangle({
                        left: marginL,
                        top: marginT,
                        right: width - marginR,
                        bottom: height - marginB
                    })
                }
            },
            _cleanContent: function() {
                var that = this;
                that._rangeContainer.clean();
                that._scale.clean();
                that._cleanValueIndicators()
            },
            _renderContent: function() {
                var that = this;
                that._rangeContainer.render(_extend(true, {}, that._themeManager.theme().rangeContainer, that.option('rangeContainer'), {
                    themeName: that._themeManager.themeName(),
                    vertical: that._area.vertical
                }));
                that._scale.render(_extend(true, {}, that._themeManager.theme().scale, that.option('scale'), {
                    approximateScreenDelta: that._getApproximateScreenRange(),
                    offset: 0,
                    vertical: that._area.vertical
                }));
                var elements = that._prepareValueIndicators();
                elements = _map([that._scale, that._rangeContainer].concat(elements), function(element) {
                    return element && element.enabled ? element : null
                });
                that._applyMainLayout(elements);
                _each(elements, function(_, element) {
                    that._updateElementPosition(element)
                });
                that._updateActiveElements()
            },
            _updateIndicatorSettings: function(settings) {
                var that = this;
                settings.currentValue = settings.baseValue = _isFinite(that._translator.translate(settings.baseValue)) ? _Number(settings.baseValue) : that._baseValue;
                settings.vertical = that._area.vertical;
                if (settings.text && !settings.text.format && !settings.text.precision) {
                    settings.text.format = that._defaultFormatOptions.format;
                    settings.text.precision = that._defaultFormatOptions.precision
                }
            },
            _prepareValueIndicatorSettings: function() {
                var that = this,
                    options = that.option('valueIndicator') || {},
                    defaultOptions = _extend(true, {}, that._themeManager.theme().valueIndicator),
                    type = _String(options.type || defaultOptions.type).toLowerCase();
                that._valueIndicatorSettings = _extend(true, defaultOptions._default, defaultOptions[type], options, {
                    type: type,
                    animation: that._animationSettings,
                    containerBackgroundColor: that._containerBackgroundColor
                });
                that._updateIndicatorSettings(that._valueIndicatorSettings)
            },
            _prepareSubvalueIndicatorSettings: function() {
                var that = this,
                    options = that.option('subvalueIndicator') || {},
                    defaultOptions = _extend(true, {}, that._themeManager.theme().subvalueIndicator),
                    type = _String(options.type || defaultOptions.type).toLowerCase();
                that._subvalueIndicatorSettings = _extend(true, defaultOptions._default, defaultOptions[type], options, {
                    type: type,
                    animation: that._animationSettings,
                    containerBackgroundColor: that._containerBackgroundColor
                });
                that._updateIndicatorSettings(that._subvalueIndicatorSettings)
            },
            _cleanValueIndicators: function() {
                this._valueIndicator && this._valueIndicator.clean();
                this._subvalueIndicatorsSet && this._subvalueIndicatorsSet.clean()
            },
            _prepareValueIndicators: function() {
                var that = this;
                that._prepareValueIndicator();
                that.__subvalues !== null && that._prepareSubvalueIndicators();
                return [that._valueIndicator, that._subvalueIndicatorsSet]
            },
            _updateActiveElements: function() {
                this._updateValueIndicator();
                this._updateSubvalueIndicators()
            },
            _prepareValueIndicator: function() {
                var that = this,
                    indicator = that._valueIndicator,
                    currentValue;
                that._prepareValueIndicatorSettings();
                indicator && that._valueIndicatorType !== that._valueIndicatorSettings.type && indicator.dispose() && (indicator = null);
                that._valueIndicatorType = that._valueIndicatorSettings.type;
                if (!indicator) {
                    indicator = that._valueIndicator = that._createValueIndicator(that._valueIndicatorType);
                    if (indicator) {
                        indicator.setup({
                            renderer: that._renderer,
                            translator: that._translator,
                            owner: that._root,
                            tracker: that._tracker,
                            className: 'dxg-value-indicator'
                        });
                        indicator._trackerInfo = {type: 'value-indicator'}
                    }
                }
                indicator.render(that._valueIndicatorSettings)
            },
            _prepareSubvalueIndicators: function() {
                var that = this,
                    subvalueIndicatorsSet = that._subvalueIndicatorsSet;
                if (!subvalueIndicatorsSet)
                    subvalueIndicatorsSet = that._subvalueIndicatorsSet = new DX.viz.gauges.__internals.ValueIndicatorsSet({
                        renderer: that._renderer,
                        translator: that._translator,
                        owner: that._root,
                        tracker: that._tracker,
                        className: 'dxg-subvalue-indicators',
                        indicatorClassName: 'dxg-subvalue-indicator',
                        trackerType: 'subvalue-indicator',
                        createIndicator: function() {
                            return that._createSubvalueIndicator(that._subvalueIndicatorType)
                        }
                    });
                that._prepareSubvalueIndicatorSettings();
                var isRecreate = that._subvalueIndicatorSettings.type !== that._subvalueIndicatorType;
                that._subvalueIndicatorType = that._subvalueIndicatorSettings.type;
                if (that._createSubvalueIndicator(that._subvalueIndicatorType))
                    subvalueIndicatorsSet.render(that._subvalueIndicatorSettings, isRecreate)
            },
            _processValue: function(value, fallbackValue) {
                var _value = this._translator.adjust(value !== undefined ? value : this.__value);
                return _isFinite(_value) ? _value : fallbackValue
            },
            _setupValue: function(value) {
                this.__value = this._processValue(value, this.__value)
            },
            _setupSubvalues: function(subvalues) {
                var _subvalues = subvalues === undefined ? this.__subvalues : _isArray(subvalues) ? subvalues : _isNumber(subvalues) ? [subvalues] : null;
                if (_subvalues === null)
                    return;
                var i = 0,
                    ii = _subvalues.length,
                    list = [];
                for (; i < ii; ++i)
                    list.push(this._processValue(_subvalues[i], this.__subvalues[i]));
                this.__subvalues = list
            },
            _updateValueIndicator: function() {
                var that = this;
                that._valueIndicator && that._valueIndicator.value(that.__value, that._noAnimation);
                that._resizing || that.hideLoadingIndicator()
            },
            _updateSubvalueIndicators: function() {
                var that = this;
                that._subvalueIndicatorsSet && that._subvalueIndicatorsSet.values(that.__subvalues, that._noAnimation);
                that._resizing || that.hideLoadingIndicator()
            },
            value: function(arg) {
                var that = this;
                if (arg !== undefined) {
                    that._setupValue(arg);
                    that._updateValueIndicator();
                    that.option(OPTION_VALUE, that.__value);
                    return that
                }
                return that.__value
            },
            subvalues: function(arg) {
                var that = this;
                if (arg !== undefined) {
                    if (that.__subvalues !== null) {
                        that._setupSubvalues(arg);
                        that._updateSubvalueIndicators();
                        that.option(OPTION_SUBVALUES, that.__subvalues)
                    }
                    return that
                }
                return that.__subvalues !== null ? that.__subvalues.slice() : undefined
            },
            _handleValueChanged: function(name, newv, oldv) {
                var that = this;
                switch (name) {
                    case OPTION_VALUE:
                        that._setupValue(newv);
                        that._updateValueIndicator();
                        that.option(OPTION_VALUE, that.__value);
                        return true;
                    case OPTION_SUBVALUES:
                        if (that.__subvalues !== null) {
                            that._setupSubvalues(newv);
                            that._updateSubvalueIndicators();
                            that.option(OPTION_SUBVALUES, that.__subvalues);
                            return true
                        }
                        return false;
                    default:
                        return false
                }
            },
            _optionChanged: function(name, newValue, oldValue) {
                var that = this;
                if (that._handleValueChanged(name, newValue, oldValue))
                    return;
                switch (name) {
                    case'scale':
                        that._setupDomain();
                        that._invalidate();
                        break;
                    default:
                        that.callBase.apply(that, arguments);
                        break
                }
            },
            _optionValuesEqual: function(name, oldValue, newValue) {
                switch (name) {
                    case OPTION_VALUE:
                        return oldValue === newValue;
                    case OPTION_SUBVALUES:
                        return compareArrays(oldValue, newValue);
                    default:
                        return this.callBase.apply(this, arguments)
                }
            },
            _getDefaultContainerSize: null,
            _applyMainLayout: null,
            _updateElementPosition: null,
            _createScale: null,
            _createRangeContainer: null,
            _createValueIndicator: null,
            _createSubvalueIndicator: null,
            _getApproximateScreenRange: null
        });
        DX.viz.gauges.Gauge.prototype._factory = DX.utils.clone(DX.viz.gauges.__internals.BaseGauge.prototype._factory);
        DX.viz.gauges.Gauge.prototype._factory.createThemeManager = function() {
            return new DX.viz.gauges.__internals.ThemeManager
        };
        function valueGetter(arg) {
            return arg.value
        }
        function setupValues(that, fieldName, optionItems) {
            var currentValues = that[fieldName],
                newValues = _isArray(optionItems) ? _map(optionItems, valueGetter) : [],
                i = 0,
                ii = newValues.length,
                list = [];
            for (; i < ii; ++i)
                list.push(that._processValue(newValues[i], currentValues[i]));
            that[fieldName] = list
        }
        function disableDefaultMode(that) {
            that.value = that.subvalues = _noop;
            that._setupValue = that._setupSubvalues = that._updateValueIndicator = that._updateSubvalueIndicators = null
        }
        function selectObsoleteMode(that) {
            that._needleValues = _map(that.option('needles') || [], valueGetter);
            that._markerValues = _map(that.option('markers') || [], valueGetter);
            that._rangeBarValues = _map(that.option('rangeBars') || [], valueGetter);
            that._needles = [];
            that._markers = [];
            that._rangeBars = [];
            that._setupValueState = function() {
                var that = this;
                setupValues(that, '_needleValues', that.option('needles'));
                setupValues(that, '_markerValues', that.option('markers'));
                setupValues(that, '_rangeBarValues', that.option('rangeBars'))
            };
            that._handleValueChanged = function(name, newv, oldv) {
                var that = this,
                    result = false;
                switch (name) {
                    case'needles':
                        setupValues(that, '_needleValues', newv);
                        result = true;
                        break;
                    case'markers':
                        setupValues(that, '_markerValues', newv);
                        result = true;
                        break;
                    case'rangeBars':
                        setupValues(that, '_rangeBarValues', newv);
                        result = true;
                        break
                }
                result && that._invalidate();
                return result
            };
            that._updateActiveElements = function() {
                var that = this;
                _each(that._needles, function(_, needle) {
                    needle.value(that._needleValues[needle._index], that._noAnimation)
                });
                _each(that._markers, function(_, marker) {
                    marker.value(that._markerValues[marker._index], that._noAnimation)
                });
                _each(that._rangeBars, function(_, rangeBar) {
                    rangeBar.value(that._rangeBarValues[rangeBar._index], that._noAnimation)
                });
                that._resizing || that.hideLoadingIndicator()
            };
            that._prepareValueIndicators = function() {
                return prepareObsoleteElements(this)
            };
            that._disposeValueIndicators = function() {
                var that = this;
                _each([].concat(that._needles, that._markers, that._rangeBars), function(_, pointer) {
                    pointer.dispose()
                });
                that._needles = that._markers = that._rangeBars = null
            };
            that._cleanValueIndicators = function() {
                _each([].concat(this._needles, this._markers, this._rangeBars), function(_, pointer) {
                    pointer.clean()
                })
            };
            that.needleValue = function(index, value) {
                return accessPointerValue(this, this._needles, this._needleValues, index, value)
            };
            that.markerValue = function(index, value) {
                return accessPointerValue(this, this._markers, this._markerValues, index, value)
            };
            that.rangeBarValue = function(index, value) {
                return accessPointerValue(this, this._rangeBars, this._rangeBarValues, index, value)
            }
        }
        function selectHardMode(that) {
            that._indicatorValues = [];
            that._valueIndicators = [];
            that._setupValueState = function() {
                setupValues(this, '_indicatorValues', this.option('valueIndicators'))
            };
            that._handleValueChagned = function(name, newv, oldv) {
                if (name === 'valueIndicators') {
                    setupValues(this, '_indicatorValues', newv);
                    this._invalidate();
                    return true
                }
                return false
            };
            that._updateActiveElements = function() {
                var that = this;
                _each(that._valueIndicators, function(_, valueIndicator) {
                    valueIndicator.value(that._indicatorValues[valueIndicator._index], that._noAnimation)
                });
                that._resizing || that.hideLoadingIndicator()
            };
            that._prepareValueIndicators = function() {
                return prepareValueIndicatorsInHardMode(this)
            };
            that._disposeValueIndicators = function() {
                _each(this._valueIndicators, function(_, valueIndicator) {
                    valueIndicator.dispose()
                });
                this._valueIndicators = null
            };
            that._cleanValueIndicators = function() {
                _each(this._valueIndicators, function(_, valueIndicator) {
                    valueIndicator.clean()
                })
            };
            that.indicatorValue = function(index, value) {
                return accessPointerValue(this, this._valueIndicators, this._indicatorValues, index, value)
            }
        }
        function prepareValueIndicatorsInHardMode(that) {
            var valueIndicators = that._valueIndicators || [],
                userOptions = that.option('valueIndicators'),
                optionList = [],
                i = 0,
                ii;
            for (ii = _isArray(userOptions) ? userOptions.length : 0; i < ii; ++i)
                optionList.push(userOptions[i]);
            for (ii = valueIndicators.length; i < ii; ++i)
                optionList.push(null);
            var themeSettings = that._themeManager.theme().valueIndicators,
                parameters = {
                    renderer: that._renderer,
                    owner: that._root,
                    translator: that._translator,
                    tracker: that._tracker
                },
                newValueIndicators = [];
            _each(optionList, function(i, userSettings) {
                var valueIndicator = valueIndicators[i];
                if (!userSettings) {
                    valueIndicator && valueIndicator.dispose();
                    return
                }
                var type = _String(userSettings.type || themeSettings._type).toLowerCase();
                if (valueIndicator && type !== valueIndicator.type) {
                    valueIndicator.dispose();
                    valueIndicator = null
                }
                if (!valueIndicator) {
                    valueIndicator = that._createValueIndicatorInHardMode(type);
                    valueIndicator && valueIndicator.setup(parameters)
                }
                if (valueIndicator) {
                    var settings = _extend(true, {}, themeSettings._default, themeSettings[type], userSettings, {
                            type: type,
                            animation: that._animationSettings,
                            containerBackgroundColor: that._containerBackgroundColor
                        });
                    that._updateIndicatorSettings(settings);
                    valueIndicator.render(settings);
                    valueIndicator._index = i;
                    valueIndicator._trackerInfo = {index: i};
                    newValueIndicators.push(valueIndicator)
                }
            });
            that._valueIndicators = newValueIndicators;
            return that._valueIndicators
        }
        function prepareObsoleteElements(that) {
            var rangeBars = prepareObsoletePointers(that, '_rangeBars', '_createRangeBar', {
                    user: that.option('rangeBars'),
                    common: that.option('commonRangeBarSettings'),
                    theme: that._themeManager.theme().valueIndicator,
                    preset: {},
                    type: 'rangebar',
                    className: 'dxg-value-indicator'
                });
            var needles = prepareObsoletePointers(that, '_needles', '_createNeedle', {
                    user: that.option('needles'),
                    common: that.option('commonNeedleSettings'),
                    theme: that._themeManager.theme().valueIndicator,
                    preset: that._getPreset().commonNeedleSettings,
                    className: 'dxg-value-indicator'
                });
            var markers = prepareObsoletePointers(that, '_markers', '_createMarker', {
                    user: that.option('markers'),
                    common: that.option('commonMarkerSettings'),
                    theme: that._themeManager.theme().subvalueIndicator,
                    preset: that._getPreset().commonMarkerSettings,
                    className: 'dxg-subvalue-indicator'
                });
            var spindle = that._prepareObsoleteSpindle && that._prepareObsoleteSpindle();
            return [].concat(rangeBars, needles, markers, [spindle])
        }
        function prepareObsoletePointers(that, fieldName, methodName, options) {
            var pointers = that[fieldName],
                userOptions = [],
                i = 0,
                ii;
            for (ii = _isArray(options.user) ? options.user.length : 0; i < ii; ++i)
                userOptions.push(options.user[i]);
            for (ii = pointers.length; i < ii; ++i)
                userOptions.push(null);
            var themeOption = options.theme,
                presetOption = options.preset,
                commonOption = options.common || {},
                parameters = {
                    renderer: that._renderer,
                    owner: that._root,
                    translator: that._translator,
                    tracker: that._tracker,
                    className: options.className
                },
                newPointers = [];
            _each(userOptions, function(i, pointerOption) {
                var pointer = pointers[i];
                if (!pointerOption) {
                    pointer && pointer.dispose();
                    return
                }
                var type = _String(pointerOption.type || commonOption.type || presetOption.type || themeOption.type).toLowerCase(),
                    settings;
                if (pointer && pointer.type !== type) {
                    pointer.dispose();
                    pointer = null
                }
                if (!pointer) {
                    pointer = that[methodName](type);
                    pointer.setup(parameters)
                }
                if (pointer) {
                    type = options.type || type;
                    settings = _extend(true, {}, themeOption._default, themeOption[type], commonOption, pointerOption),
                    settings.spindleSize = null;
                    settings.animation = that._animationSettings;
                    settings.containerBackgroundColor = that._containerBackgroundColor;
                    that._updateIndicatorSettings(settings);
                    pointer.render(settings);
                    pointer._index = i;
                    pointer._trackerInfo = {index: i};
                    newPointers.push(pointer)
                }
            });
            that[fieldName] = newPointers;
            return newPointers
        }
        function accessPointerValue(that, pointers, values, index, value) {
            if (value !== undefined) {
                if (values[index] !== undefined) {
                    values[index] = that._processValue(value, values[index]);
                    pointers[index] && pointers[index].value(values[index]);
                    that._resizing || that.hideLoadingIndicator()
                }
                return that
            }
            else
                return values[index]
        }
        function compareArrays(array1, array2) {
            if (array1 === array2)
                return true;
            if (_isArray(array1) && _isArray(array2) && array1.length === array2.length) {
                for (var i = 0, ii = array1.length; i < ii; ++i)
                    if (_abs(array1[i] - array2[i]) > 1E-8)
                        return false;
                return true
            }
            return false
        }
        DX.viz.gauges.__internals.ValueIndicatorsSet = DX.Class.inherit({
            ctor: function(parameters) {
                var that = this;
                that._parameters = parameters;
                that._createIndicator = that._parameters.createIndicator || _noop;
                that._root = that._parameters.renderer.createGroup({'class': that._parameters.className});
                that._indicatorParameters = that._indicatorParameters || {
                    renderer: that._parameters.renderer,
                    translator: that._parameters.translator,
                    owner: that._root,
                    tracker: that._parameters.tracker,
                    className: that._parameters.indicatorClassName
                };
                that._indicators = []
            },
            dispose: function() {
                var that = this;
                _each(that._indicators, function(_, indicator) {
                    indicator.dispose()
                });
                that._parameters = that._createIndicator = that._root = that._options = that._indicators = that._colorPalette = that._palette = null;
                return that
            },
            clean: function() {
                var that = this;
                that._root.detach();
                that._sample && that._sample.clean().dispose();
                _each(that._indicators, function(_, indicator) {
                    indicator.clean()
                });
                that._sample = that._options = that._palette = null;
                return that
            },
            render: function(options, isRecreate) {
                var that = this;
                that._options = options;
                that._sample = that._createIndicator();
                that._sample && that._sample.setup(that._indicatorParameters).render(options);
                that.enabled = that._sample && that._sample.enabled;
                that._palette = _isDefined(options.palette) ? new DX.viz.core.Palette(options.palette) : null;
                if (that.enabled) {
                    that._root.append(that._parameters.owner);
                    that._generatePalette(that._indicators.length);
                    that._indicators = _map(that._indicators, function(indicator, i) {
                        if (isRecreate) {
                            indicator.dispose();
                            indicator = that._createIndicator();
                            indicator.setup(that._indicatorParameters);
                            indicator._trackerInfo = {
                                type: that._parameters.trackerType,
                                index: i
                            }
                        }
                        indicator.render(that._getIndicatorOptions(i));
                        return indicator
                    })
                }
                return that
            },
            resize: function(layout) {
                var that = this;
                that._layout = layout;
                _each(that._indicators, function(_, indicator) {
                    indicator.resize(layout)
                });
                return that
            },
            measure: function(layout) {
                return this._sample.measure(layout)
            },
            _getIndicatorOptions: function(index) {
                var result = this._options;
                if (this._colorPalette)
                    result = _extend({}, result, {color: this._colorPalette[index]});
                return result
            },
            _generatePalette: function(count) {
                var that = this,
                    colors = null;
                if (that._palette) {
                    colors = [];
                    that._palette.reset();
                    var i = 0;
                    for (; i < count; ++i)
                        colors.push(that._palette.getNextColor())
                }
                that._colorPalette = colors
            },
            _adjustIndicatorsCount: function(count) {
                var that = this,
                    indicators = that._indicators,
                    i,
                    ii,
                    indicatorOptions,
                    indicator,
                    indicatorsLen = indicators.length,
                    palette = that._parameters.palette;
                if (indicatorsLen > count) {
                    for (i = count, ii = indicatorsLen; i < ii; ++i)
                        indicators[i].clean().dispose();
                    that._indicators = indicators.slice(0, count);
                    that._generatePalette(indicators.length)
                }
                else if (indicatorsLen < count) {
                    that._generatePalette(count);
                    for (i = indicatorsLen, ii = count; i < ii; ++i) {
                        indicator = that._createIndicator();
                        indicator.setup(that._indicatorParameters);
                        indicator._trackerInfo = {
                            type: that._parameters.trackerType,
                            index: i
                        };
                        indicator.render(that._getIndicatorOptions(i)).resize(that._layout);
                        indicators.push(indicator)
                    }
                }
            },
            values: function(arg, _noAnimation) {
                var that = this;
                if (!that.enabled)
                    return;
                if (arg !== undefined) {
                    if (!_isArray(arg))
                        arg = _isFinite(arg) ? [Number(arg)] : null;
                    if (arg) {
                        that._adjustIndicatorsCount(arg.length);
                        _each(that._indicators, function(i, indicator) {
                            indicator.value(arg[i], _noAnimation)
                        })
                    }
                    return that
                }
                return _map(that._indicators, function(indicator) {
                        return indicator.value()
                    })
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file circularGauge.js */
    (function(DX, $, undefined) {
        var factory = DX.viz.gauges.__factory;
        var isFinite = window.isFinite,
            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;
        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({
            _rootClass: 'dxg-circular-gauge',
            _selectMode: function() {
                this.callBase.apply(this, arguments);
                if (typeof this.indicatorValue === 'function')
                    this._createValueIndicatorInHardMode = function(type) {
                        return factory.createCircularValueIndicatorInHardMode(type)
                    }
            },
            _setupCodomain: function() {
                var that = this,
                    geometry = that.option('geometry') || {},
                    startAngle = geometry.startAngle,
                    endAngle = geometry.endAngle,
                    sides;
                startAngle = isFinite(startAngle) ? normalizeAngle(startAngle) : 225;
                endAngle = isFinite(endAngle) ? normalizeAngle(endAngle) : -45;
                if (abs(startAngle - endAngle) < 1) {
                    endAngle -= 360;
                    sides = {
                        left: -1,
                        up: -1,
                        right: 1,
                        down: 1
                    }
                }
                else {
                    startAngle < endAngle && (endAngle -= 360);
                    sides = getSides(startAngle, endAngle)
                }
                that._area = {
                    x: 0,
                    y: 0,
                    radius: 100,
                    startCoord: startAngle,
                    endCoord: endAngle,
                    scaleRadius: geometry.scaleRadius > 0 ? Number(geometry.scaleRadius) : undefined,
                    sides: sides
                };
                that._translator.setCodomain(startAngle, endAngle)
            },
            _measureMainElements: function(elements) {
                var that = this,
                    maxRadius = 0,
                    minRadius = Infinity,
                    maxHorizontalOffset = 0,
                    maxVerticalOffset = 0,
                    maxInverseHorizontalOffset = 0,
                    maxInverseVerticalOffset = 0;
                $each(elements, function(_, element) {
                    var bounds = element.measure({radius: that._area.radius - (Number(element._options.offset) || 0)});
                    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(elements) {
                var that = this,
                    measurements = that._measureMainElements(elements),
                    area = that._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 = that._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;
                var scaler = (measurements.maxRadius - area.radius + area.scaleRadius) / radius;
                if (0 < scaler && scaler < 1) {
                    rect = rect.scale(scaler);
                    radius *= scaler
                }
                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;
                that._layoutManager.setRect(rect)
            },
            _updateElementPosition: function(element) {
                element.resize({
                    x: this._area.x,
                    y: this._area.y,
                    radius: round(this._area.radius - (Number(element._options.offset) || 0))
                })
            },
            _createScale: function(parameters) {
                return factory.createCircularScale(parameters)
            },
            _createRangeContainer: function(parameters) {
                return factory.createCircularRangeContainer(parameters)
            },
            _createValueIndicator: function(type) {
                return factory.createCircularValueIndicator(type)
            },
            _createSubvalueIndicator: function(type) {
                return factory.createCircularSubvalueIndicator(type)
            },
            _getApproximateScreenRange: function() {
                var that = this,
                    area = that._area,
                    r = min(that._width / (area.sides.right - area.sides.left), that._height / (area.sides.down - area.sides.up));
                r > area.totalRadius && (r = area.totalRadius);
                r = 0.8 * r;
                return -that._translator.getCodomainRange() * r * PI / 180
            },
            _getDefaultContainerSize: function() {
                return {
                        width: 300,
                        height: 300
                    }
            },
            _getPreset: function() {
                var preset = this.option('preset'),
                    result;
                if (preset === 'preset2')
                    result = {
                        commonNeedleSettings: {type: 'twocolorrectangle'},
                        commonMarkerSettings: {type: 'triangle'}
                    };
                else if (preset === 'preset3')
                    result = {
                        commonNeedleSettings: {type: 'rectangle'},
                        commonMarkerSettings: {type: 'triangle'}
                    };
                else
                    result = {
                        commonNeedleSettings: {type: 'rectangle'},
                        commonMarkerSettings: {type: 'textcloud'}
                    };
                return result
            },
            _createNeedle: function(type) {
                return factory.createCircularNeedle(type)
            },
            _createMarker: function(type) {
                return factory.createCircularMarker(type)
            },
            _createRangeBar: function() {
                return factory.createCircularRangeBar()
            },
            _prepareObsoleteSpindle: function() {
                var that = this,
                    spindleOption = that.option('spindle') || {},
                    visible = that._needles && ('visible' in spindleOption ? !!spindleOption.visible : true);
                if (visible) {
                    var themeOption = that._themeManager.theme().valueIndicator._default,
                        size = spindleOption.size || themeOption.spindleSize;
                    visible = size > 0
                }
                if (visible) {
                    var gapSize = spindleOption.gapSize || themeOption.spindleGapSize,
                        color = spindleOption.color || themeOption.color;
                    gapSize = gapSize <= size ? gapSize : size;
                    that._spindle = that._spindle || that._renderer.createGroup({'class': 'dxg-value-indicator'});
                    that._spindle.append(that._root);
                    that._spindleOuter = that._spindleOuter || that._renderer.createCircle(0, 0, 0, {
                        'class': 'dxg-spindle-border',
                        stroke: 'none',
                        strokeWidth: 0
                    }).append(that._spindle);
                    that._spindleInner = that._spindleInner || that._renderer.createCircle(0, 0, 0, {
                        'class': 'dxg-spindle-hole',
                        stroke: 'none',
                        strokeWidth: 0
                    }).append(that._spindle);
                    that._spindleOuter.applySettings({
                        cx: that._area.x,
                        cy: that._area.y,
                        r: size / 2,
                        fill: color
                    });
                    that._spindleInner.applySettings({
                        cx: that._area.x,
                        cy: that._area.y,
                        r: gapSize / 2,
                        fill: that._containerBackgroundColor
                    });
                    return {
                            enabled: true,
                            _options: {offset: 0},
                            measure: function(layout) {
                                return {}
                            },
                            resize: function(layout) {
                                that._spindleOuter.applySettings({
                                    cx: layout.x,
                                    cy: layout.y
                                });
                                that._spindleInner.applySettings({
                                    cx: layout.x,
                                    cy: layout.y
                                });
                                return that
                            }
                        }
                }
                else {
                    that._spindle && that._spindle.remove();
                    delete that._spindle;
                    delete that._spindleOuter;
                    delete that._spindleInner;
                    return null
                }
            }
        });
        DX.viz.gauges.CircularGauge.prototype._factory = DX.utils.clone(DX.viz.gauges.__internals.BaseGauge.prototype._factory);
        DX.viz.gauges.CircularGauge.prototype._factory.createThemeManager = function() {
            var themeManager = new DX.viz.gauges.__internals.ThemeManager;
            themeManager._subTheme = '_circular';
            return themeManager
        }
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file linearGauge.js */
    (function(DX, $, undefined) {
        var factory = DX.viz.gauges.__factory;
        var _String = String,
            _Number = Number,
            max = Math.max,
            min = Math.min,
            round = Math.round,
            slice = Array.prototype.slice,
            $extend = $.extend,
            $each = $.each;
        DX.viz.gauges.LinearGauge = DX.viz.gauges.Gauge.inherit({
            _rootClass: 'dxg-linear-gauge',
            _selectMode: function() {
                this.callBase.apply(this, arguments);
                if (typeof this.indicatorValue === 'function')
                    this._createValueIndicatorInHardMode = function(type) {
                        return factory.createLinearValueIndicatorInHardMode(type)
                    }
            },
            _setupCodomain: function() {
                var that = this,
                    geometry = that.option('geometry') || {},
                    vertical = _String(geometry.orientation).toLowerCase() === 'vertical';
                that._area = {
                    vertical: vertical,
                    x: 0,
                    y: 0,
                    startCoord: -100,
                    endCoord: 100,
                    scaleSize: geometry.scaleSize > 0 ? _Number(geometry.scaleSize) : undefined
                };
                that._scale.vertical = vertical;
                that._rangeContainer.vertical = vertical
            },
            _measureMainElements: function(elements) {
                var that = this,
                    minBound = 1000,
                    maxBound = 0,
                    indent = 0;
                $each(elements, function(_, element) {
                    var bounds = element.measure({
                            x: that._area.x + (_Number(element._options.offset) || 0),
                            y: that._area.y + (_Number(element._options.offset) || 0)
                        });
                    maxBound = max(maxBound, bounds.max);
                    minBound = min(minBound, bounds.min);
                    bounds.indent > 0 && (indent = max(indent, bounds.indent))
                });
                return {
                        minBound: minBound,
                        maxBound: maxBound,
                        indent: indent
                    }
            },
            _applyMainLayout: function(elements) {
                var that = this,
                    measurements = that._measureMainElements(elements),
                    area = that._area,
                    rect,
                    offset,
                    counterSize = area.scaleSize + 2 * measurements.indent;
                if (area.vertical) {
                    rect = that._layoutManager.selectRectBySizes({
                        width: measurements.maxBound - measurements.minBound,
                        height: counterSize
                    });
                    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 = that._layoutManager.selectRectBySizes({
                        height: measurements.maxBound - measurements.minBound,
                        width: counterSize
                    });
                    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)
                }
                that._translator.setCodomain(area.startCoord, area.endCoord);
                that._layoutManager.setRect(rect)
            },
            _updateElementPosition: function(element) {
                element.resize({
                    x: round(this._area.x + (_Number(element._options.offset) || 0)),
                    y: round(this._area.y + (_Number(element._options.offset) || 0))
                })
            },
            _createScale: function(parameters) {
                return factory.createLinearScale(parameters)
            },
            _createRangeContainer: function(parameters) {
                return factory.createLinearRangeContainer(parameters)
            },
            _createValueIndicator: function(type) {
                return factory.createLinearValueIndicator(type)
            },
            _createSubvalueIndicator: function(type) {
                return factory.createLinearSubvalueIndicator(type)
            },
            _getApproximateScreenRange: function() {
                var that = this,
                    area = that._area,
                    s = area.vertical ? that._height : that._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
                        }
            },
            _getPreset: function() {
                var preset = this.option('preset'),
                    result;
                if (preset === 'preset2')
                    result = {
                        commonNeedleSettings: {type: 'rhombus'},
                        commonMarkerSettings: {type: 'triangle'}
                    };
                else
                    result = {
                        commonNeedleSettings: {type: 'circle'},
                        commonMarkerSettings: {type: 'textcloud'}
                    };
                return result
            },
            _createNeedle: function(type) {
                return factory.createLinearNeedle(type)
            },
            _createMarker: function(type) {
                return factory.createLinearMarker(type)
            },
            _createRangeBar: function() {
                return factory.createLinearRangeBar()
            }
        });
        DX.viz.gauges.LinearGauge.prototype._factory = DX.utils.clone(DX.viz.gauges.__internals.BaseGauge.prototype._factory);
        DX.viz.gauges.LinearGauge.prototype._factory.createThemeManager = function() {
            var themeManager = new DX.viz.gauges.__internals.ThemeManager;
            themeManager._subTheme = '_linear';
            return themeManager
        }
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file barGauge.js */
    (function(DX, $, undefined) {
        var PI = Math.PI;
        var _Number = window.Number,
            _isFinite = window.isFinite,
            _abs = Math.abs,
            _round = Math.round,
            _floor = Math.floor,
            _min = Math.min,
            _max = Math.max,
            _isArray = DX.utils.isArray,
            _convertAngleToRendererSpace = DX.utils.convertAngleToRendererSpace,
            _getCosAndSin = DX.utils.getCosAndSin,
            _noop = $.noop,
            _extend = $.extend,
            _getSampleText = DX.viz.gauges.__internals.getSampleText,
            _formatValue = DX.viz.gauges.__internals.formatValue;
        var _Rectangle = DX.viz.core.Rectangle,
            _Palette = DX.viz.core.Palette;
        DX.viz.gauges.BarGauge = DX.viz.gauges.__internals.BaseGauge.inherit({
            _rootClass: 'dxbg-bar-gauge',
            _init: function() {
                var that = this;
                that.callBase.apply(that, arguments);
                that._barsGroup = that._renderer.createGroup({'class': 'dxbg-bars'});
                that._values = [];
                that._context = {
                    renderer: that._renderer,
                    translator: that._translator,
                    tracker: that._tracker,
                    group: that._barsGroup
                };
                that._animateStep = function(pos) {
                    var bars = that._bars,
                        i = 0,
                        ii = bars.length;
                    for (; i < ii; ++i)
                        bars[i].animate(pos)
                };
                that._animateComplete = function() {
                    var bars = that._bars,
                        i = 0,
                        ii = bars.length;
                    for (; i < ii; ++i)
                        bars[i].endAnimation()
                }
            },
            _dispose: function() {
                var that = this;
                that.callBase.apply(that, arguments);
                that._barsGroup = that._values = that._context = that._animateStep = that._animateComplete = null
            },
            _setupDomain: function() {
                var that = this,
                    startValue = that.option('startValue'),
                    endValue = that.option('endValue');
                _isFinite(startValue) || (startValue = 0);
                _isFinite(endValue) || (endValue = 100);
                that._translator.setDomain(startValue, endValue);
                that._baseValue = that._translator.adjust(that.option('baseValue'));
                _isFinite(that._baseValue) || (that._baseValue = startValue < endValue ? startValue : endValue)
            },
            _calculateSizeCore: function() {
                var that = this,
                    size = that.option('size') || {};
                if (_Number(size.width) === 0 || _Number(size.height) === 0) {
                    that._width = that._height = 0;
                    that._rootRect = new _Rectangle
                }
                else {
                    that._width = size.width > 0 ? _Number(size.width) : that._element().width() || 300;
                    that._height = size.height > 0 ? _Number(size.height) : that._element().height() || 300;
                    that._rootRect = new _Rectangle({
                        left: 0,
                        top: 0,
                        right: that._width,
                        bottom: that._height
                    })
                }
            },
            _setupCodomain: DX.viz.gauges.CircularGauge.prototype._setupCodomain,
            _getApproximateScreenRange: function() {
                var that = this,
                    sides = that._area.sides,
                    width = that._width / (sides.right - sides.left),
                    height = that._height / (sides.down - sides.up),
                    r = width < height ? width : height;
                return -that._translator.getCodomainRange() * r * PI / 180
            },
            _setupAnimationSettings: function() {
                this.callBase();
                if (this._animationSettings)
                    _extend(this._animationSettings, {
                        step: this._animateStep,
                        complete: this._animateComplete
                    })
            },
            _cleanContent: function() {
                var that = this;
                that._barsGroup.detach();
                that._animationSettings && that._barsGroup.stopAnimation();
                var i = 0,
                    ii = that._bars ? that._bars.length : 0;
                for (; i < ii; ++i)
                    that._bars[i].dispose();
                that._palette = that._bars = null
            },
            _renderContent: function() {
                var that = this,
                    labelOptions = that.option('label');
                that._barsGroup.append(that._root);
                that._context.textEnabled = labelOptions === undefined || labelOptions && (!('visible' in labelOptions) || labelOptions.visible);
                if (that._context.textEnabled) {
                    that._context.textColor = labelOptions && labelOptions.font && labelOptions.font.color || null;
                    labelOptions = _extend(true, {}, that._themeManager.theme().label, labelOptions);
                    that._context.formatOptions = {
                        format: labelOptions.format !== undefined || labelOptions.precision !== undefined ? labelOptions.format : that._defaultFormatOptions.format,
                        precision: labelOptions.format !== undefined || labelOptions.precision !== undefined ? labelOptions.precision : that._defaultFormatOptions.precision,
                        customizeText: labelOptions.customizeText
                    };
                    that._context.textOptions = {
                        font: _extend({}, that._themeManager.theme().label.font, labelOptions.font, {color: null}),
                        align: 'center'
                    };
                    that._textIndent = labelOptions.indent > 0 ? _Number(labelOptions.indent) : 0;
                    that._context.lineWidth = labelOptions.connectorWidth > 0 ? _Number(labelOptions.connectorWidth) : 0;
                    that._context.lineColor = labelOptions.connectorColor || null;
                    var text = that._renderer.createText(_getSampleText(that._translator, that._context.formatOptions), 0, 0, that._context.textOptions).append(that._barsGroup),
                        bbox = text.getBBox();
                    text.detach();
                    that._context.textVerticalOffset = -bbox.y - bbox.height / 2;
                    that._context.textWidth = bbox.width;
                    that._context.textHeight = bbox.height
                }
                DX.viz.gauges.CircularGauge.prototype._applyMainLayout.call(that);
                that._renderBars()
            },
            _measureMainElements: function() {
                var result = {maxRadius: this._area.radius};
                if (this._context.textEnabled) {
                    result.horizontalMargin = this._context.textWidth;
                    result.verticalMargin = this._context.textHeight
                }
                return result
            },
            _renderBars: function() {
                var that = this,
                    options = _extend({}, that._themeManager.theme(), that.option());
                that._palette = new _Palette(options.palette, {
                    stepHighlight: 50,
                    theme: that._themeManager.themeName()
                });
                var relativeInnerRadius = options.relativeInnerRadius > 0 && options.relativeInnerRadius < 1 ? _Number(options.relativeInnerRadius) : 0.1,
                    radius = that._area.radius;
                if (that._context.textEnabled) {
                    that._textIndent = _round(_min(that._textIndent, radius / 2));
                    radius -= that._textIndent
                }
                that._outerRadius = _round(radius);
                that._innerRadius = _round(radius * relativeInnerRadius);
                that._barSpacing = options.barSpacing > 0 ? _Number(options.barSpacing) : 0;
                _extend(that._context, {
                    backgroundColor: options.backgroundColor,
                    x: that._area.x,
                    y: that._area.y,
                    startAngle: that._area.startCoord,
                    endAngle: that._area.endCoord,
                    baseAngle: that._translator.translate(that._baseValue)
                });
                that._bars = [];
                that._updateValues(that.option('values'))
            },
            _arrangeBars: function(count) {
                var that = this,
                    radius = that._outerRadius - that._innerRadius;
                that._context.barSize = count > 0 ? _max((radius - (count - 1) * that._barSpacing) / count, 1) : 0;
                var spacing = count > 1 ? _max(_min((radius - count * that._context.barSize) / (count - 1), that._barSpacing), 0) : 0,
                    _count = _min(_floor((radius + spacing) / that._context.barSize), count);
                that._setBarsCount(_count);
                radius = that._outerRadius;
                that._context.textRadius = radius + that._textIndent;
                that._palette.reset();
                var unitOffset = that._context.barSize + spacing,
                    i = 0;
                for (; i < _count; ++i, radius -= unitOffset)
                    that._bars[i].arrange({
                        radius: radius,
                        color: that._palette.getNextColor()
                    })
            },
            _setBarsCount: function(count) {
                var that = this,
                    i,
                    ii;
                if (that._bars.length > count) {
                    for (i = count, ii = that._bars.length; i < ii; ++i)
                        that._bars[i].dispose();
                    that._bars.splice(count, ii - count)
                }
                else if (that._bars.length < count)
                    for (i = that._bars.length, ii = count; i < ii; ++i)
                        that._bars.push(new BarWrapper(i, that._context));
                if (that._bars.length > 0) {
                    if (that._dummyBackground) {
                        that._dummyBackground.detach();
                        that._dummyBackground = null
                    }
                }
                else {
                    if (!that._dummyBackground)
                        that._dummyBackground = that._renderer.createArc().append(that._barsGroup);
                    that._dummyBackground.applySettings({
                        x: that._context.x,
                        y: that._context.y,
                        outerRadius: that._outerRadius,
                        innerRadius: that._innerRadius,
                        startAngle: that._context.endAngle,
                        endAngle: that._context.startAngle,
                        fill: that._context.backgroundColor
                    })
                }
            },
            _updateBars: function() {
                var that = this,
                    i = 0,
                    ii = that._bars.length;
                for (; i < ii; ++i)
                    that._bars[i].setValue(that._values[i])
            },
            _animateBars: function() {
                var that = this,
                    i = 0,
                    ii = that._bars.length;
                if (ii > 0) {
                    for (; i < ii; ++i)
                        that._bars[i].beginAnimation(that._values[i]);
                    that._barsGroup.animate({_: 0}, that._animationSettings)
                }
            },
            _updateValues: function(values, noAnimation) {
                var that = this,
                    list = _isArray(values) && values || _isFinite(values) && [values] || [],
                    i = 0,
                    ii = list.length,
                    value;
                that._values = [];
                for (; i < ii; ++i) {
                    value = that._translator.adjust(list[i]);
                    _isFinite(value) && that._values.push(value)
                }
                that._animationSettings && that._barsGroup.stopAnimation();
                if (that._bars) {
                    that._arrangeBars(that._values.length);
                    if (that._animationSettings && !that._noAnimation)
                        that._animateBars();
                    else
                        that._updateBars()
                }
                if (!that._resizing) {
                    that.option('values', that._values);
                    that.hideLoadingIndicator()
                }
            },
            values: function(arg) {
                if (arg !== undefined) {
                    this._updateValues(arg);
                    return this
                }
                else
                    return this._values.slice(0)
            },
            _optionChanged: function(name, newValue, oldValue) {
                switch (name) {
                    case'values':
                        this._updateValues(newValue);
                        break;
                    default:
                        this.callBase.apply(this, arguments);
                        break
                }
            },
            _optionValuesEqual: function(name, oldValue, newValue) {
                switch (name) {
                    case'values':
                        return compareArrays(oldValue, newValue);
                    default:
                        return this.callBase.apply(this, arguments)
                }
            }
        });
        var ThemeManager = DX.viz.gauges.__internals.ThemeManager.inherit({
                _themeSection: 'barGauge',
                _initializeTheme: function() {
                    var that = this;
                    that._initializeFont(that._theme.label.font);
                    that._initializeFont(that._theme.title.font);
                    that._initializeFont(that._theme.tooltip.font);
                    that._initializeFont(that._theme.loadingIndicator.font)
                }
            });
        DX.viz.gauges.BarGauge.prototype._factory = DX.utils.clone(DX.viz.gauges.__internals.BaseGauge.prototype._factory);
        DX.viz.gauges.BarGauge.prototype._factory.createThemeManager = function() {
            return new ThemeManager
        };
        function BarWrapper(index, context) {
            var that = this;
            that._context = context;
            that._background = context.renderer.createArc().append(context.group);
            that._background.applySettings({fill: context.backgroundColor});
            that._bar = context.renderer.createArc().append(context.group);
            if (context.textEnabled) {
                that._line = context.renderer.createPath([], {strokeWidth: context.lineWidth}).append(context.group);
                that._text = context.renderer.createText('', 0, 0, context.textOptions).append(context.group)
            }
            that._tracker = context.renderer.createArc();
            context.tracker.attach(that._tracker, that, {index: index});
            that._index = index;
            that._angle = context.baseAngle;
            that._settings = {
                x: context.x,
                y: context.y,
                startAngle: context.baseAngle,
                endAngle: context.baseAngle
            }
        }
        _extend(BarWrapper.prototype, {
            dispose: function() {
                var that = this;
                that._background.detach();
                that._bar.detach();
                if (that._context.textEnabled) {
                    that._line.detach();
                    that._text.detach()
                }
                that._context.tracker.detach(that._tracker);
                that._context = that._settings = that._background = that._bar = that._line = that._text = that._tracker = null;
                return that
            },
            arrange: function(options) {
                var that = this;
                that._settings.outerRadius = options.radius;
                that._settings.innerRadius = options.radius - that._context.barSize;
                that._background.applySettings(_extend({}, that._settings, {
                    startAngle: that._context.endAngle,
                    endAngle: that._context.startAngle
                }));
                that._bar.applySettings(that._settings);
                that._tracker.applySettings(that._settings);
                that._color = options.color;
                that._bar.applySettings({fill: options.color});
                if (that._context.textEnabled) {
                    that._line.applySettings({
                        points: [that._context.x, that._context.y - that._settings.innerRadius, that._context.x, that._context.y - that._context.textRadius],
                        stroke: that._context.lineColor || options.color
                    });
                    that._text.applySettings({font: {color: that._context.textColor || options.color}})
                }
                return that
            },
            getTooltipParameters: function() {
                var that = this,
                    cossin = _getCosAndSin((that._angle + that._context.baseAngle) / 2);
                return {
                        x: _round(that._context.x + (that._settings.outerRadius + that._settings.innerRadius) / 2 * cossin.cos),
                        y: _round(that._context.y - (that._settings.outerRadius + that._settings.innerRadius) / 2 * cossin.sin),
                        offset: 0,
                        color: that._color,
                        value: that._value
                    }
            },
            setAngle: function(angle) {
                var that = this;
                that._angle = angle;
                setAngles(that._settings, that._context.baseAngle, that._angle);
                that._bar.applySettings(that._settings);
                that._tracker.applySettings(that._settings);
                if (that._context.textEnabled) {
                    that._line.rotate(_convertAngleToRendererSpace(that._angle), that._context.x, that._context.y);
                    var cossin = _getCosAndSin(that._angle);
                    that._text.applySettings({
                        text: _formatValue(that._value, that._context.formatOptions, {index: that._index}),
                        x: that._context.x + (that._context.textRadius + that._context.textWidth * 0.6) * cossin.cos,
                        y: that._context.y - (that._context.textRadius + that._context.textHeight * 0.6) * cossin.sin + that._context.textVerticalOffset
                    })
                }
                return that
            },
            setValue: function(value) {
                this._value = value;
                return this.setAngle(this._context.translator.translate(value))
            },
            beginAnimation: function(value) {
                var that = this;
                that._value = value;
                var angle = that._context.translator.translate(value);
                if (!compareFloats(that._angle, angle)) {
                    that._start = that._angle;
                    that._delta = angle - that._angle;
                    that._tracker.applySettings({visibility: 'hidden'});
                    if (that._context.textEnabled) {
                        that._line.applySettings({visibility: 'hidden'});
                        that._text.applySettings({visibility: 'hidden'})
                    }
                }
                else
                    that.animate = _noop
            },
            animate: function(pos) {
                var that = this;
                that._angle = that._start + that._delta * pos;
                setAngles(that._settings, that._context.baseAngle, that._angle);
                that._bar.applySettings(that._settings)
            },
            endAnimation: function() {
                var that = this;
                if (that._delta !== undefined) {
                    if (compareFloats(that._angle, that._start + that._delta)) {
                        that._tracker.applySettings({visibility: null});
                        if (that._context.textEnabled) {
                            that._line.applySettings({visibility: null});
                            that._text.applySettings({visibility: null})
                        }
                        that.setAngle(that._angle)
                    }
                }
                else
                    delete that.animate;
                delete that._start;
                delete that._delta
            }
        });
        function setAngles(target, angle1, angle2) {
            target.startAngle = angle1 < angle2 ? angle1 : angle2;
            target.endAngle = angle1 < angle2 ? angle2 : angle1
        }
        function compareFloats(value1, value2) {
            return _abs(value1 - value2) < 0.0001
        }
        function compareArrays(array1, array2) {
            if (array1 === array2)
                return true;
            if (_isArray(array1) && _isArray(array2) && array1.length === array2.length) {
                for (var i = 0, ii = array1.length; i < ii; ++i)
                    if (!compareFloats(array1[i], array2[i]))
                        return false;
                return true
            }
            return false
        }
        var __BarWrapper = BarWrapper;
        DX.viz.gauges.__tests.BarWrapper = __BarWrapper;
        DX.viz.gauges.__tests.stubBarWrapper = function(barWrapperType) {
            BarWrapper = barWrapperType
        };
        DX.viz.gauges.__tests.restoreBarWrapper = function() {
            BarWrapper = __BarWrapper
        };
        DX.registerComponent('dxBarGauge', DX.viz.gauges.BarGauge)
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file tracker.js */
    (function(DX, $, undefined) {
        var _setTimeout = window.setTimeout,
            _clearTimeout = window.clearTimeout,
            _extend = $.extend,
            _abs = Math.abs;
        var TOOLTIP_SHOW_DELAY = 300,
            TOOLTIP_HIDE_DELAY = 300,
            TOOLTIP_TOUCH_SHOW_DELAY = 400,
            TOOLTIP_TOUCH_HIDE_DELAY = 300;
        DX.viz.gauges.__internals.Tracker = DX.Class.inherit({
            ctor: function(parameters) {
                DX.utils.debug.assertParam(parameters, 'parameters');
                DX.utils.debug.assertParam(parameters.renderer, 'parameters.renderer');
                DX.utils.debug.assertParam(parameters.container, 'parameters.container');
                var that = this;
                that._container = parameters.container;
                that._element = parameters.renderer.createGroup({
                    'class': 'dxg-tracker',
                    stroke: 'none',
                    strokeWidth: 0,
                    fill: '#000000',
                    opacity: 0.0001
                });
                that._showTooltipCallback = function() {
                    that._showTooltipTimeout = null;
                    var target = that._tooltipEvent.target;
                    that._targetEvent = null;
                    if (that._tooltipTarget !== target) {
                        that._tooltipTarget = target;
                        that._callbacks['tooltip-show']()
                    }
                };
                that._hideTooltipCallback = function() {
                    that._hideTooltipTimeout = null;
                    that._targetEvent = null;
                    if (that._tooltipTarget) {
                        that._callbacks['tooltip-hide']();
                        that._tooltipTarget = null
                    }
                };
                that._dispose = function() {
                    that._showTooltipCallback = that._hideTooltipCallback = that._dispose = null
                };
                that._DEBUG_showTooltipTimeoutSet = that._DEBUG_showTooltipTimeoutCleared = that._DEBUG_hideTooltipTimeoutSet = that._DEBUG_hideTooltipTimeoutCleared = 0
            },
            dispose: function() {
                var that = this;
                that._dispose();
                that.deactivate();
                that._element.off();
                that._container = that._element = that._context = that._callbacks = null;
                return that
            },
            activate: function() {
                this._element.append(this._container);
                return this
            },
            deactivate: function() {
                this._element.detach();
                this._element.clear();
                return this
            },
            attach: function(element, target, info) {
                element.data({
                    target: target,
                    info: info
                });
                element.append(this._element);
                return this
            },
            detach: function(element) {
                element.detach();
                element.removeData();
                return this
            },
            setTooltipState: function(state) {
                var that = this,
                    data;
                that._element.off(tooltipMouseEvents).off(tooltipTouchEvents);
                if (state) {
                    data = {tracker: that};
                    that._element.on(tooltipMouseEvents, data).on(tooltipTouchEvents, data)
                }
                return that
            },
            setCallbacks: function(callbacks) {
                this._callbacks = callbacks;
                return this
            },
            _showTooltip: function(event, delay) {
                var that = this,
                    data = $(event.target).data();
                if (that._tooltipTarget === event.target || that._callbacks['tooltip-prepare'](data.target, data.info)) {
                    that._hideTooltipTimeout && ++that._DEBUG_hideTooltipTimeoutCleared;
                    _clearTimeout(that._hideTooltipTimeout);
                    that._hideTooltipTimeout = null;
                    _clearTimeout(that._showTooltipTimeout);
                    that._tooltipEvent = event;
                    ++that._DEBUG_showTooltipTimeoutSet;
                    that._showTooltipTimeout = _setTimeout(that._showTooltipCallback, delay)
                }
            },
            _hideTooltip: function(delay) {
                var that = this;
                that._showTooltipTimeout && ++that._DEBUG_showTooltipTimeoutCleared;
                _clearTimeout(that._showTooltipTimeout);
                that._showTooltipTimeout = null;
                _clearTimeout(that._hideTooltipTimeout);
                ++that._DEBUG_hideTooltipTimeoutSet;
                that._hideTooltipTimeout = _setTimeout(that._hideTooltipCallback, delay)
            }
        });
        var tooltipMouseEvents = {
                'mouseover.gauge-tooltip': handleTooltipMouseOver,
                'mouseout.gauge-tooltip': handleTooltipMouseOut
            };
        var tooltipMouseMoveEvents = {'mousemove.gauge-tooltip': handleTooltipMouseMove};
        var tooltipTouchEvents = {'touchstart.gauge-tooltip': handleTooltipTouchStart};
        function handleTooltipMouseOver(event) {
            var tracker = event.data.tracker;
            tracker._x = event.pageX;
            tracker._y = event.pageY;
            tracker._element.off(tooltipMouseMoveEvents).on(tooltipMouseMoveEvents, event.data);
            tracker._showTooltip(event, TOOLTIP_SHOW_DELAY)
        }
        function handleTooltipMouseMove(event) {
            var tracker = event.data.tracker;
            if (tracker._showTooltipTimeout && _abs(event.pageX - tracker._x) > 4 || _abs(event.pageY - tracker._y) > 4) {
                tracker._x = event.pageX;
                tracker._y = event.pageY;
                tracker._showTooltip(event, TOOLTIP_SHOW_DELAY)
            }
        }
        function handleTooltipMouseOut(event) {
            var tracker = event.data.tracker;
            tracker._element.off(tooltipMouseMoveEvents);
            tracker._hideTooltip(TOOLTIP_HIDE_DELAY)
        }
        var active_touch_tooltip_tracker = null;
        DX.viz.gauges.__internals.Tracker._DEBUG_reset = function() {
            active_touch_tooltip_tracker = null
        };
        function handleTooltipTouchStart(event) {
            event.preventDefault();
            var tracker = active_touch_tooltip_tracker;
            if (tracker && tracker !== event.data.tracker)
                tracker._hideTooltip(TOOLTIP_TOUCH_HIDE_DELAY);
            tracker = active_touch_tooltip_tracker = event.data.tracker;
            tracker._showTooltip(event, TOOLTIP_TOUCH_SHOW_DELAY);
            tracker._touch = true
        }
        function handleTooltipDocumentTouchStart(event) {
            var tracker = active_touch_tooltip_tracker;
            if (tracker) {
                if (!tracker._touch) {
                    tracker._hideTooltip(TOOLTIP_TOUCH_HIDE_DELAY);
                    active_touch_tooltip_tracker = null
                }
                tracker._touch = null
            }
        }
        function handleTooltipDocumentTouchEnd(event) {
            var tracker = active_touch_tooltip_tracker;
            if (tracker)
                if (tracker._showTooltipTimeout) {
                    tracker._hideTooltip(TOOLTIP_TOUCH_HIDE_DELAY);
                    active_touch_tooltip_tracker = null
                }
        }
        $(window.document).on({
            'touchstart.gauge-tooltip': handleTooltipDocumentTouchStart,
            'touchend.gauge-tooltip': handleTooltipDocumentTouchEnd
        })
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file dxCircularGauge.js */
    (function(DX, undefined) {
        DX.registerComponent("dxCircularGauge", DX.viz.gauges.CircularGauge)
    })(DevExpress);
    /*! Module viz-gauges, file dxLinearGauge.js */
    (function(DX, undefined) {
        DX.registerComponent("dxLinearGauge", DX.viz.gauges.LinearGauge)
    })(DevExpress);
    DevExpress.MOD_VIZ_GAUGES = true
}
if (!DevExpress.MOD_VIZ_RANGESELECTOR) {
    if (!DevExpress.MOD_VIZ_CORE)
        throw Error('Required module is not referenced: viz-core');
    /*! Module viz-rangeselector, file namespaces.js */
    (function(DevExpress) {
        DevExpress.viz.rangeSelector = {utils: {}}
    })(DevExpress);
    /*! Module viz-rangeselector, 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) {
                return dxUtils.getRootOffset(renderer).left || 0
            };
        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-rangeselector, 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 that = this;
                if (!that._isDrawn) {
                    that._isDrawn = !(that._draw(group || that._group) === false);
                    if (group)
                        that._group = group
                }
                else
                    that._update(group || that._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-rangeselector, file rangeSelector.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            utils = DX.utils,
            dataUtils = DX.data.utils,
            rangeSelectorUtils = rangeSelector.utils,
            ParseUtils = DX.viz.core.ParseUtils,
            formatHelper = DX.formatHelper,
            core = DX.viz.core;
        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(utils.isFunction(formatOptions.customizeText) ? formatOptions.customizeText.call(formatObject, formatObject) : formatObject.valueText)
        };
        rangeSelector.RangeSelector = core.BaseWidget.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
                            }
                        },
                        logarithmBase: 10
                    },
                    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'
                        }
                    },
                    dataSource: undefined,
                    dataSourceField: 'arg',
                    redrawOnResize: true,
                    theme: undefined,
                    selectedRangeChanged: null
                };
            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,
                        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(that) {
                    return that._element()
                };
            var createRangeContainer = function(rangeContainerOptions) {
                    return rangeSelector.rangeSelectorFactory.createRangeContainer(rangeContainerOptions)
                };
            var createTranslator = function(range, canvas) {
                    return {
                            x: core.CoreFactory.createTranslator2D(range.arg, canvas, {direction: "horizontal"}),
                            y: core.CoreFactory.createTranslator2D(range.val, 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(that) {
                    var renderer = that.option('renderer');
                    if (renderer)
                        return renderer;
                    return core.CoreFactory.createRenderer({
                            pathModified: that.option('pathModified'),
                            rtl: that.option('rtlEnabled')
                        })
                };
            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(that) {
                    var seriesDataSource,
                        dataSource = that._dataSource && that._dataSource.items(),
                        scaleOptions = that.option('scale'),
                        chartOptions = that.option('chart') || {},
                        valueType = scaleOptions.valueType;
                    if (!valueType)
                        valueType = calculateValueType(scaleOptions.startValue, scaleOptions.endValue);
                    if (dataSource || chartOptions.series) {
                        seriesDataSource = new rangeSelector.SeriesDataSource({
                            renderer: that.renderer,
                            dataSource: dataSource,
                            valueType: (valueType || '').toLowerCase(),
                            axisType: scaleOptions.type,
                            chart: chartOptions,
                            dataSourceField: that.option('dataSourceField'),
                            backgroundColor: that._userBackgroundColor,
                            incidentOccured: that._incidentOccured
                        });
                        checkLogarithmicOptions(chartOptions.valueAxis, seriesDataSource.themeManager.theme().valueAxis.logarithmBase, that._incidentOccured)
                    }
                    return seriesDataSource
                };
            var calculateTranslatorRange = function(that, seriesDataSource, scaleOptions) {
                    var translatorRange,
                        minValue,
                        maxValue,
                        inverted = false,
                        isEqualDates;
                    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() : {
                        arg: new core.Range,
                        val: new core.Range({isValueRange: true})
                    };
                    isEqualDates = utils.isDate(minValue) && utils.isDate(maxValue) && minValue.getTime() === maxValue.getTime();
                    if (minValue !== maxValue && !isEqualDates)
                        translatorRange.arg.addRange({
                            invert: inverted,
                            min: minValue,
                            max: maxValue,
                            minVisible: minValue,
                            maxVisible: maxValue,
                            dataType: scaleOptions.valueType
                        });
                    translatorRange.arg.addRange({
                        base: scaleOptions.logarithmBase,
                        axisType: scaleOptions.type
                    });
                    if (!translatorRange.arg.isDefined()) {
                        if (isEqualDates)
                            scaleOptions.valueType = 'numeric';
                        translatorRange.arg.setStubData(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(that, scaleOptions, translators, screenDelta) {
                    var isEmpty = scaleOptions.isEmpty,
                        tickProvider = core.CoreFactory.getTickProvider(),
                        minorTicksOptions,
                        majorTicksOptions,
                        startValue,
                        endValue,
                        businessRange = translators.x.getBusinessRange();
                    minorTicksOptions = {
                        tickInterval: isEmpty ? 0 : that.option('scale').minorTickInterval,
                        showCustomBoundaryTicks: scaleOptions.showCustomBoundaryTicks,
                        minorTickCount: scaleOptions.minorTickCount
                    };
                    majorTicksOptions = {
                        textOptions: {
                            align: 'center',
                            font: scaleOptions.label.font
                        },
                        renderer: that.renderer,
                        getText: function(value) {
                            return rangeSelector.formatValue(value, scaleOptions.label)
                        },
                        translator: translators.x,
                        isStartTickGenerated: !utils.isDefined(that.option('scale').majorTickInterval),
                        tickInterval: scaleOptions.majorTickInterval,
                        textSpacing: SCALE_TEXT_SPACING,
                        setTicksAtUnitBeginning: scaleOptions.setTicksAtUnitBeginning,
                        useTicksAutoArrangement: scaleOptions.useTicksAutoArrangement,
                        hideLabels: isEmpty
                    };
                    startValue = isEmpty ? businessRange.min : scaleOptions.startValue;
                    endValue = isEmpty ? businessRange.max : scaleOptions.endValue;
                    return tickProvider.getFullTicks(startValue, endValue, screenDelta, majorTicksOptions, minorTicksOptions, {
                            axisType: scaleOptions.type,
                            dataType: scaleOptions.valueType,
                            base: scaleOptions.logarithmBase
                        })
                };
            var updateTickIntervals = function(scaleOptions, screenDelta, incidentOccured) {
                    var tickProvider = core.CoreFactory.getTickProvider(),
                        tickIntervals = tickProvider.getTickIntervals(scaleOptions.startValue, scaleOptions.endValue, screenDelta, {
                            tickInterval: scaleOptions.majorTickInterval,
                            incidentOccured: incidentOccured
                        }, {
                            tickInterval: scaleOptions.minorTickInterval,
                            incidentOccured: incidentOccured
                        }, {
                            axisType: scaleOptions.type,
                            dataType: scaleOptions.valueType,
                            base: scaleOptions.logarithmBase
                        });
                    scaleOptions.minorTickInterval = tickIntervals.minorTickInterval;
                    scaleOptions.majorTickInterval = tickIntervals.majorTickInterval
                };
            var updateScaleOptions = function(that, seriesDataSource, translatorRange, screenDelta, scaleOptions) {
                    var minVisibleX = utils.isDefined(translatorRange.arg.minVisible) ? translatorRange.arg.minVisible : translatorRange.arg.min,
                        maxVisibleX = utils.isDefined(translatorRange.arg.maxVisible) ? translatorRange.arg.maxVisible : translatorRange.arg.max,
                        isEmptyInterval;
                    if (seriesDataSource && !seriesDataSource.isEmpty()) {
                        scaleOptions.startValue = scaleOptions.inverted ? maxVisibleX : minVisibleX;
                        scaleOptions.endValue = scaleOptions.inverted ? minVisibleX : maxVisibleX
                    }
                    isEmptyInterval = utils.isDate(scaleOptions.startValue) && utils.isDate(scaleOptions.endValue) && scaleOptions.startValue.getTime() === scaleOptions.endValue.getTime() || scaleOptions.startValue === scaleOptions.endValue;
                    scaleOptions.isEmpty = !utils.isDefined(scaleOptions.startValue) || !utils.isDefined(scaleOptions.endValue) || isEmptyInterval || scaleOptions.valueType === 'string';
                    if (scaleOptions.isEmpty)
                        scaleOptions.startValue = scaleOptions.endValue = undefined;
                    else {
                        updateTickIntervals(scaleOptions, screenDelta, that._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(that, scaleOptions, screenDelta) {
                    var sliderMarkerOptions = $.extend(true, {}, that.option('sliderMarker')),
                        businessInterval;
                    if (!sliderMarkerOptions.format) {
                        if (!that.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) {
                                if (utils.isDefined(scaleOptions.startValue) && utils.isDefined(scaleOptions.endValue))
                                    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.arg.addRange({interval: intervalX})
                };
            var checkLogarithmicOptions = function(options, logarithmBase, incidentOccured) {
                    if (!options)
                        return;
                    if (options.type === 'logarithmic' && options.logarithmBase <= 0 || options.logarithmBase && !$.isNumeric(options.logarithmBase)) {
                        options.logarithmBase = logarithmBase;
                        incidentOccured('E2104')
                    }
                    else if (options.type !== 'logarithmic')
                        options.logarithmBase = undefined
                };
            var prepareScaleOptions = function(that, seriesDataSource) {
                    var scaleOptions = $.extend(true, {}, that.option('scale')),
                        incidentOccured = that._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') {
                        that._incidentOccured("E2201");
                        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;
                            that._incidentOccured("E2202", ["start"])
                        }
                    }
                    if (utils.isDefined(scaleOptions.endValue)) {
                        parsedValue = parser(scaleOptions.endValue);
                        if (utils.isDefined(parsedValue))
                            scaleOptions.endValue = parsedValue;
                        else {
                            scaleOptions.endValue = undefined;
                            that._incidentOccured("E2202", ["end"])
                        }
                    }
                    checkLogarithmicOptions(scaleOptions, defaultRangeSelectorOptions.scale.logarithmBase, that._incidentOccured);
                    if (!scaleOptions.type)
                        scaleOptions.type = 'continuous';
                    scaleOptions.parser = parser;
                    return scaleOptions
                };
            var correctSizeOptions = function(that, sizeOptions, scaleOptions) {
                    var size = that.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(that) {
                    var rangeContainerCanvas,
                        seriesDataSource,
                        translatorRange,
                        scaleLabelsAreaHeight,
                        sizeOptions,
                        sliderMarkerSpacing,
                        sliderMarkerOptions,
                        selectedRange,
                        $container = that.container;
                    that._isUpdating = true;
                    sizeOptions = calculateSize(that);
                    that._actualSize = sizeOptions;
                    seriesDataSource = createSeriesDataSource(that);
                    that._scaleOptions = prepareScaleOptions(that, seriesDataSource);
                    correctSizeOptions(that, sizeOptions, that._scaleOptions);
                    if (!sizeOptions.width || !sizeOptions.height || !$container.is(':visible')) {
                        that.stopRedraw = true;
                        that._incidentOccured("W2001", [that.NAME]);
                        return
                    }
                    else
                        that.stopRedraw = false;
                    updateRendererSize(that, sizeOptions);
                    that._updateLoadIndicator(undefined, that.canvas.width, that.canvas.height);
                    translatorRange = calculateTranslatorRange(that, seriesDataSource, that._scaleOptions);
                    updateScaleOptions(that, seriesDataSource, translatorRange, sizeOptions.width, that._scaleOptions);
                    updateTranslatorRangeInterval(translatorRange, that._scaleOptions);
                    sliderMarkerOptions = prepareSliderMarkersOptions(that, that._scaleOptions, sizeOptions.width);
                    selectedRange = initSelection(that, that._scaleOptions);
                    sliderMarkerSpacing = calculateSliderMarkersSpacing(that.renderer, sizeOptions, that._scaleOptions, sliderMarkerOptions);
                    rangeContainerCanvas = calculateRangeContainerCanvas(sizeOptions, that.option('margin'), sliderMarkerSpacing);
                    scaleLabelsAreaHeight = calculateScaleAreaHeight(that.renderer, that._scaleOptions, showScaleMarkers(that._scaleOptions));
                    that.translators = createTranslator(translatorRange, createTranslatorCanvas(sizeOptions, rangeContainerCanvas, scaleLabelsAreaHeight));
                    that._scaleOptions.ticksInfo = getTicksInfo(that, that._scaleOptions, that.translators, rangeContainerCanvas.width);
                    that._testTicksInfo = that._scaleOptions.ticksInfo;
                    that._selectedRange = selectedRange;
                    if (seriesDataSource)
                        seriesDataSource.adjustSeriesDimensions(that.translators);
                    that.rangeContainer.applyOptions({
                        canvas: rangeContainerCanvas,
                        scaleLabelsAreaHeight: scaleLabelsAreaHeight,
                        sliderMarkerSpacing: sliderMarkerSpacing,
                        translators: that.translators,
                        selectedRange: selectedRange,
                        scale: that._scaleOptions,
                        behavior: that.option('behavior'),
                        background: that.option('background'),
                        chart: that.option('chart'),
                        seriesDataSource: seriesDataSource,
                        sliderMarker: sliderMarkerOptions,
                        sliderHandle: that.option('sliderHandle'),
                        shutter: that.option('shutter'),
                        selectedRangeChanged: createSelectedRangeChangedFunction(that),
                        setSelectedRange: function(selectedRange) {
                            that.setSelectedRange(selectedRange)
                        }
                    });
                    that._isUpdating = false
                };
            var createSelectedRangeChangedFunction = function(that) {
                    return function(selectedRange, blockSelectedRangeChanged) {
                            var selectedRangeChanged = that.option('selectedRangeChanged');
                            that.option('selectedRange', selectedRange);
                            if (selectedRangeChanged && !blockSelectedRangeChanged)
                                setTimeout(function() {
                                    selectedRangeChanged.call(null, selectedRange)
                                })
                        }
                };
            var calculateSize = function(that) {
                    var $container = that.container,
                        size = that.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()
                    }
                    that.canvas = result;
                    return result
                };
            var updateRendererSize = function(that, size) {
                    var renderer = that.renderer;
                    if (renderer.isInitialized())
                        renderer.getRoot().applySettings({
                            width: size.width,
                            height: size.height
                        });
                    else {
                        renderer.recreateCanvas(size.width, size.height);
                        renderer.draw(that.container[0])
                    }
                };
            var prepareChartThemeOptions = function(that, options) {
                    var chartTheme,
                        chartOption = that.option('chart') || {};
                    if (!chartOption.theme && options && options.theme) {
                        chartTheme = options.theme;
                        if (chartTheme) {
                            if (typeof chartTheme === 'object') {
                                chartTheme = chartTheme.chart || {};
                                chartTheme.name = options.theme.name
                            }
                            chartOption.theme = chartTheme
                        }
                    }
                };
            var initSelection = function(that, scaleOptions) {
                    var selectedRangeOptions = that.option('selectedRange'),
                        startValue,
                        endValue,
                        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))
                                that._incidentOccured("E2203", [entity]);
                            else
                                result = parsedValue;
                            return result
                        };
                    if (!selectedRangeOptions)
                        return {
                                startValue: scaleOptions.startValue,
                                endValue: scaleOptions.endValue
                            };
                    else {
                        startValue = parseValue(selectedRangeOptions.startValue, 'startValue');
                        startValue = that.rangeContainer.slidersContainer.truncateSelectedRange(startValue, scaleOptions);
                        endValue = parseValue(selectedRangeOptions.endValue, 'endValue');
                        endValue = that.rangeContainer.slidersContainer.truncateSelectedRange(endValue, scaleOptions);
                        return {
                                startValue: startValue,
                                endValue: endValue
                            }
                    }
                };
            var _isSizeChanged = function(that) {
                    var actualSize = that._actualSize,
                        newSize = calculateSize(that);
                    return actualSize && (actualSize.width !== newSize.width || actualSize.height !== newSize.height)
                };
            return {
                    isSizeChanged: function() {
                        return _isSizeChanged(this)
                    },
                    _setDefaultOptions: function() {
                        this.callBase();
                        this.option(defaultRangeSelectorOptions)
                    },
                    _dataSourceOptions: function() {
                        return {
                                paginate: false,
                                _preferSync: true
                            }
                    },
                    _init: function() {
                        var that = this;
                        that.container = getContainer(that);
                        clearContainer(that.container);
                        that.renderer = createRenderer(that);
                        that.rangeContainer = createRangeContainer(that.renderer);
                        that.callBase();
                        that._reinitDataSource()
                    },
                    _reinitDataSource: function() {
                        this._refreshDataSource()
                    },
                    _dispose: function() {
                        var that = this,
                            disposeObject = function(propName) {
                                that[propName] && that[propName].dispose(),
                                that[propName] = null
                            };
                        that.callBase();
                        disposeObject("renderer");
                        that.translators = null;
                        disposeObject("rangeContainer")
                    },
                    _initOptions: function(options) {
                        var that = this,
                            themeManager;
                        that._optionsInitializing = true;
                        options = options || {};
                        that._userOptions = $.extend(true, {}, options);
                        themeManager = createThemeManager(options.theme);
                        themeManager.setBackgroundColor(options.containerBackgroundColor);
                        that.option(themeManager.applyRangeSelectorTheme(options));
                        prepareChartThemeOptions(that, options);
                        if (options.background)
                            that._userBackgroundColor = options.background.color
                    },
                    _refresh: function() {
                        var that = this,
                            callBase = that.callBase;
                        that._endLoading(function() {
                            callBase.call(that)
                        })
                    },
                    _render: function(isResizing) {
                        var that = this,
                            currentAnimationEnabled,
                            behaviorOptions;
                        that._optionsInitializing = false;
                        applyOptions(that);
                        if (!that.stopRedraw) {
                            if (isResizing) {
                                behaviorOptions = that.option('behavior');
                                currentAnimationEnabled = behaviorOptions.animationEnabled;
                                behaviorOptions.animationEnabled = false;
                                that.rangeContainer.redraw();
                                behaviorOptions.animationEnabled = currentAnimationEnabled
                            }
                            else
                                that.rangeContainer.redraw();
                            !isResizing && (!that._dataSource || that._dataSource && that._dataSource.isLoaded()) && that.hideLoadingIndicator()
                        }
                        that._drawn();
                        that.__rendered && that.__rendered()
                    },
                    _optionChanged: function(name, value, prevValue) {
                        var that = this;
                        if (!that._optionsInitializing)
                            dataUtils.compileSetter(name)(that._userOptions, value, {
                                functionsAsIs: true,
                                merge: true
                            });
                        if (name === "dataSource") {
                            that._reinitDataSource();
                            that._invalidate()
                        }
                        else if (name === "selectedRange")
                            that.setSelectedRange(that.option('selectedRange'));
                        else if (name === "selectedRangeChanged")
                            that.rangeContainer.slidersContainer.selectedRangeChanged = createSelectedRangeChangedFunction(that);
                        else if (name === 'containerBackgroundColor' || name === 'theme') {
                            that._initOptions(that._userOptions);
                            that._invalidate()
                        }
                        else
                            that.callBase(name, value, prevValue)
                    },
                    _resize: function() {
                        if (_isSizeChanged(this))
                            this._render(true)
                    },
                    _handleDataSourceChanged: function() {
                        var that = this;
                        that._endLoading(function() {
                            if (that.renderer.isInitialized())
                                that._render()
                        })
                    },
                    getSelectedRange: function() {
                        var that = this;
                        var selectedRange = that.rangeContainer.slidersContainer.getSelectedRange();
                        return {
                                startValue: selectedRange.startValue,
                                endValue: selectedRange.endValue
                            }
                    },
                    setSelectedRange: function(selectedRange) {
                        var that = this;
                        if (that._isUpdating || !selectedRange)
                            return;
                        var oldSelectedRange = that.rangeContainer.slidersContainer.getSelectedRange();
                        if (oldSelectedRange && oldSelectedRange.startValue === selectedRange.startValue && oldSelectedRange.endValue === selectedRange.endValue)
                            return;
                        that.rangeContainer.slidersContainer.setSelectedRange(selectedRange)
                    },
                    resetSelectedRange: function(blockSelectedRangeChanged) {
                        var that = this;
                        that.setSelectedRange({
                            startValue: that._scaleOptions.startValue,
                            endValue: that._scaleOptions.endValue,
                            blockSelectedRangeChanged: blockSelectedRangeChanged
                        })
                    },
                    render: function(isResizing) {
                        this._render(isResizing);
                        return this
                    }
                }
        }()).include(DX.ui.DataHelperMixin)
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, 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 that = 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
                        };
                    that._viewCanvas = viewCanvas;
                    that.slidersContainer.applyOptions({
                        canvas: viewCanvas,
                        translator: options.translators.x,
                        scale: options.scale,
                        selectedRange: options.selectedRange,
                        sliderMarker: options.sliderMarker,
                        sliderHandle: options.sliderHandle,
                        shutter: options.shutter,
                        behavior: options.behavior,
                        selectedRangeChanged: options.selectedRangeChanged,
                        isEmpty: isEmpty
                    });
                    that.rangeView.applyOptions({
                        canvas: viewCanvas,
                        translators: options.translators,
                        background: options.background,
                        chart: options.chart,
                        seriesDataSource: options.seriesDataSource,
                        behavior: options.behavior,
                        isEmpty: isEmpty
                    });
                    that.scale.applyOptions({
                        canvas: options.canvas,
                        translator: options.translators.x,
                        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 that = this,
                        containerGroup,
                        rangeViewGroup,
                        slidersContainerGroup,
                        scaleGroup,
                        trackersGroup,
                        clipRectCanvas = _createClipRectCanvas(that._options.canvas, that._options.sliderMarkerSpacing),
                        viewCanvas = that._viewCanvas;
                    that._clipRect = that._renderer.createClipRect(clipRectCanvas.left, clipRectCanvas.top, clipRectCanvas.width, clipRectCanvas.height).append();
                    containerGroup = that._renderer.createGroup({
                        'class': 'rangeContainer',
                        clipId: that._clipRect.id
                    }).append();
                    that._viewClipRect = that._renderer.createClipRect(viewCanvas.left, viewCanvas.top, viewCanvas.width, viewCanvas.height).append();
                    rangeViewGroup = that._renderer.createGroup({
                        'class': 'view',
                        clipId: that._viewClipRect.id
                    });
                    rangeViewGroup.append(containerGroup);
                    that.rangeView.redraw(rangeViewGroup);
                    slidersContainerGroup = that._renderer.createGroup({'class': 'slidersContainer'});
                    slidersContainerGroup.append(containerGroup);
                    that.slidersContainer.redraw(slidersContainerGroup);
                    scaleGroup = that._renderer.createGroup({'class': 'scale'});
                    scaleGroup.append(containerGroup);
                    that.scale.redraw(scaleGroup);
                    trackersGroup = that._renderer.createGroup({'class': 'trackers'});
                    trackersGroup.append(containerGroup);
                    that._trackersGroup = trackersGroup;
                    that.slidersContainer.appendTrackers(trackersGroup)
                };
            var _update = function() {
                    var that = this,
                        clipRectCanvas = _createClipRectCanvas(that._options.canvas, that._options.sliderMarkerSpacing),
                        viewCanvas = that._viewCanvas;
                    that._clipRect.updateRectangle({
                        x: clipRectCanvas.left,
                        y: clipRectCanvas.top,
                        width: clipRectCanvas.width,
                        height: clipRectCanvas.height
                    });
                    that._viewClipRect.updateRectangle({
                        x: viewCanvas.left,
                        y: viewCanvas.top,
                        width: viewCanvas.width,
                        height: viewCanvas.height
                    });
                    that.rangeView.redraw();
                    that.slidersContainer.redraw();
                    that.slidersContainer.appendTrackers(that._trackersGroup);
                    that.scale.redraw()
                };
            var dispose = function() {
                    this.slidersContainer.dispose();
                    this.slidersContainer = null
                };
            var prototypeObject = {
                    createSlidersContainer: createSlidersContainer,
                    createScale: createScale,
                    ctor: ctor,
                    dispose: dispose,
                    _applyOptions: _applyOptions,
                    _draw: _draw,
                    _update: _update
                };
            return prototypeObject
        }())
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, 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)
                            if (majorTickInterval.hasOwnProperty(key)) {
                                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.translate(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 = {},
                    i,
                    position;
                for (i = 0; i < markerDatePositions.length; i++) {
                    position = markerDatePositions[i];
                    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 that = 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 = that._renderer.createRect(that._options.canvas.left, markersAreaTop, that._options.canvas.width, that._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(that._renderer);
                        posX = rangeSelector.utils.getEventPageX(e) - svgOffsetLeft;
                        selectedRange = that._calculateRangeByMarkerPosition(posX, markerDatePositions, that._options.scale);
                        that._options.setSelectedRange(selectedRange)
                    });
                    that._markersTracker = markersTracker
                }
            },
            _getLabel: function(value, options) {
                var formatObject = {
                        value: value,
                        valueText: formatHelper.format(value, options.format, options.precision)
                    };
                return String(utils.isFunction(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.translate(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.translate(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 that = this,
                    scaleOptions = that._options.scale,
                    ticksGroup = that._renderer.createGroup(),
                    labelsGroup = that._renderer.createGroup().append(group),
                    majorTicks = scaleOptions.ticksInfo.majorTicks,
                    minorTicks = scaleOptions.ticksInfo.minorTicks,
                    customBoundaryTicks = scaleOptions.ticksInfo.customBoundaryTicks,
                    hideLabels = that._options.hideLabels || majorTicks.hideLabels || !scaleOptions.label.visible,
                    i;
                for (i = 0; i < majorTicks.length; i++) {
                    if (!hideLabels)
                        that._drawLabel(majorTicks[i], labelsGroup);
                    that._drawTick(majorTicks[i], ticksGroup)
                }
                if (scaleOptions.showMinorTicks)
                    for (i = 0; i < minorTicks.length; i++)
                        that._drawTick(minorTicks[i], ticksGroup);
                for (i = 0; i < customBoundaryTicks.length; i++)
                    that._drawTick(customBoundaryTicks[i], ticksGroup);
                ticksGroup.append(group);
                that._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-rangeselector, file rangeFactory.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            renderers = DX.viz.renderers;
        rangeSelector.rangeSelectorFactory = function() {
            return {
                    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-rangeselector, 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 that = this,
                            areaTracker,
                            selectedAreaTracker;
                        areaTracker = that._renderer.createRect(that._options.canvas.left, that._options.canvas.top, that._options.canvas.width, that._options.canvas.height, 0, {
                            fill: 'grey',
                            stroke: 'grey',
                            opacity: 0.0001
                        });
                        areaTracker.append(group);
                        selectedAreaTracker = that._renderer.createRect(that._options.canvas.left, that._options.canvas.top, that._options.canvas.width, that._options.canvas.height, 0, {
                            fill: 'grey',
                            stroke: 'grey',
                            opacity: 0.0001,
                            style: {cursor: 'pointer'}
                        });
                        selectedAreaTracker.append(group);
                        that._controller.setAreaTrackers(areaTracker, selectedAreaTracker)
                    },
                    dispose: function() {
                        this._eventsManager.dispose();
                        this._eventManager = null
                    },
                    _processSelectionChanged: function(moving, blockSelectedRangeChanged) {
                        var that = this,
                            equalLastSelectedRange = function(selectedRange) {
                                return selectedRange && that._lastSelectedRange.startValue === selectedRange.startValue && that._lastSelectedRange.endValue === selectedRange.endValue
                            },
                            selectedRange = that.getSelectedRange();
                        if ((!moving || (that._options.behavior.callSelectedRangeChanged || '').toLowerCase() === "onmoving") && that._options.selectedRangeChanged && !equalLastSelectedRange(selectedRange)) {
                            that._updateLastSelectedRange(selectedRange);
                            if (typeof that._options.selectedRangeChanged === 'function')
                                that._options.selectedRangeChanged.call(null, selectedRange, blockSelectedRangeChanged);
                            if (!moving && !equalLastSelectedRange(selectedRange))
                                that.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 that = this;
                        return rangeSelector.rangeSelectorFactory.createSlidersEventsManager(that._renderer, controller, function(moving) {
                                that._processSelectionChanged(moving)
                            })
                    },
                    ctor: function(renderer) {
                        var that = this,
                            sliders;
                        that.callBase(renderer);
                        sliders = [that._createSlider(START_VALUE_INDEX), that._createSlider(END_VALUE_INDEX)];
                        that._controller = that._createSlidersController(sliders);
                        that._eventsManager = that._createSlidersEventsManager(that._controller);
                        that._lastSelectedRange = {}
                    },
                    getSelectedRange: function() {
                        return this._controller.getSelectedRange()
                    },
                    truncateSelectedRange: function(value, scaleOptions) {
                        var min = scaleOptions.startValue > scaleOptions.endValue ? scaleOptions.endValue : scaleOptions.startValue,
                            max = scaleOptions.startValue > scaleOptions.endValue ? scaleOptions.startValue : scaleOptions.endValue;
                        if (value < min)
                            value = min;
                        if (value > max)
                            value = max;
                        return value
                    },
                    setSelectedRange: function(selectedRange) {
                        var that = this,
                            scale = that._options.scale,
                            startValue,
                            endValue,
                            currentSelectedRange = that._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;
                        currentSelectedRange.startValue = that.truncateSelectedRange(currentSelectedRange.startValue, scale);
                        currentSelectedRange.endValue = that.truncateSelectedRange(currentSelectedRange.endValue, scale);
                        that._controller.applySelectedRange(currentSelectedRange);
                        that._controller.applyPosition();
                        that._processSelectionChanged(false, selectedRange && selectedRange.blockSelectedRangeChanged)
                    },
                    appendTrackers: function(group) {
                        this._controller.appendTrackers(group)
                    },
                    _applyOptions: function(options) {
                        var that = this;
                        that._controller.applyOptions({
                            translator: options.translator,
                            canvas: options.canvas,
                            sliderMarker: options.sliderMarker,
                            sliderHandle: options.sliderHandle,
                            shutter: options.shutter,
                            scale: options.scale,
                            behavior: options.behavior
                        });
                        that._eventsManager.applyOptions({behavior: options.behavior})
                    },
                    _draw: function(group) {
                        var that = this,
                            rootElement;
                        if (msPointerEnabled) {
                            rootElement = that._renderer.getRoot();
                            rootElement && (rootElement.element.style.msTouchAction = "pinch-zoom")
                        }
                        that._controller.redraw(group);
                        that._drawAreaTracker(group);
                        that._eventsManager.initialize();
                        that._update()
                    },
                    _update: function() {
                        var that = this,
                            isEmpty = that._options.isEmpty;
                        that._eventsManager.setEnabled(!isEmpty);
                        that._controller.applySelectedRange(isEmpty ? {} : that._options.selectedRange);
                        that._controller.applyPosition(that.isDrawn());
                        that._updateLastSelectedRange();
                        that._controller.redraw()
                    }
                };
            return prototypeObject
        }())
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, 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 that = this,
                            values = null;
                        that._options = options;
                        that.getSlider(START_VALUE_INDEX).applyOptions(options);
                        that.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()
                        }
                        that.getSlider(START_VALUE_INDEX).setAvailableValues(values);
                        that.getSlider(END_VALUE_INDEX).setAvailableValues(values)
                    },
                    processDocking: function(sliderIndex) {
                        var that = this;
                        if (sliderIndex !== undefined)
                            that.getSlider(sliderIndex).processDocking();
                        else {
                            that.getSlider(START_VALUE_INDEX).processDocking();
                            that.getSlider(END_VALUE_INDEX).processDocking()
                        }
                        that.setTrackersCursorStyle('default');
                        that.applyAreaTrackersPosition()
                    },
                    getSelectedRangeInterval: function() {
                        var that = this,
                            type = that._options.scale.type,
                            base = that._options.scale.logarithmBase,
                            startValue = that.getSlider(START_VALUE_INDEX).getValue(),
                            endValue = that.getSlider(END_VALUE_INDEX).getValue();
                        if (type === 'logarithmic')
                            return rangeSelector.utils.getInterval(utils.getLog(startValue, base), utils.getLog(endValue, base));
                        else
                            return rangeSelector.utils.getInterval(startValue, endValue)
                    },
                    moveSliders: function(postitionDelta, selectedRangeInterval) {
                        var that = this;
                        that.getSlider(START_VALUE_INDEX).setPosition(that.getSlider(START_VALUE_INDEX).getPosition() + postitionDelta, false, selectedRangeInterval);
                        that.applyPosition(true)
                    },
                    moveSlider: function(sliderIndex, fastSwap, position, offsetPosition, startOffsetPosition, startOffsetPositionChangedCallback) {
                        var that = this,
                            slider = that.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) {
                                    that.swapSliders();
                                    anotherSlider.applyPosition(true)
                                }
                            }
                        slider.setPosition(position, true);
                        slider.applyPosition(true);
                        that.applyAreaTrackersPosition();
                        that.setTrackersCursorStyle('w-resize')
                    },
                    applySelectedAreaCenterPosition: function(pos) {
                        var that = this,
                            slidersContainerHalfWidth = (that.getSlider(END_VALUE_INDEX).getPosition() - that.getSlider(START_VALUE_INDEX).getPosition()) / 2,
                            selectedRangeInterval = that.getSelectedRangeInterval();
                        that.getSlider(START_VALUE_INDEX).setPosition(pos - slidersContainerHalfWidth, false, selectedRangeInterval);
                        that.applyPosition();
                        that.processDocking()
                    },
                    processManualSelection: function(startPosition, endPosition, eventArgs) {
                        var that = 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;
                        that.getSlider(movingSliderIndex).setPosition(positionRange[movingSliderIndex]);
                        that.getSlider(animateSliderIndex).setPosition(positionRange[animateSliderIndex]);
                        that.getSlider(movingSliderIndex).setPosition(positionRange[movingSliderIndex], true);
                        that.getSlider(movingSliderIndex).startEventHandler(eventArgs);
                        that.getSlider(animateSliderIndex).processDocking();
                        that.getSlider(movingSliderIndex).applyPosition(true)
                    },
                    applySelectedRange: function(selectedRange) {
                        var that = this,
                            inverted = that._options.scale.inverted;
                        utils.debug.assertParam(selectedRange, 'selectedRange not passed');
                        if (!inverted && selectedRange.startValue > selectedRange.endValue || inverted && selectedRange.startValue < selectedRange.endValue) {
                            that.getSlider(START_VALUE_INDEX).setValue(selectedRange.endValue);
                            that.getSlider(END_VALUE_INDEX).setValue(selectedRange.startValue)
                        }
                        else {
                            that.getSlider(START_VALUE_INDEX).setValue(selectedRange.startValue);
                            that.getSlider(END_VALUE_INDEX).setValue(selectedRange.endValue)
                        }
                    },
                    getSelectedRange: function() {
                        var that = this;
                        return {
                                startValue: that.getSlider(START_VALUE_INDEX).getValue(),
                                endValue: that.getSlider(END_VALUE_INDEX).getValue()
                            }
                    },
                    swapSliders: function() {
                        var that = this;
                        that._sliders.reverse();
                        that.getSlider(START_VALUE_INDEX).changeLocation();
                        that.getSlider(END_VALUE_INDEX).changeLocation()
                    },
                    applyAreaTrackersPosition: function() {
                        var that = this,
                            selectedRange = that.getSelectedRange(),
                            scaleOptions = that._options.scale,
                            width = that.getSlider(END_VALUE_INDEX).getPosition() - that.getSlider(START_VALUE_INDEX).getPosition(),
                            options = {
                                x: that.getSlider(START_VALUE_INDEX).getPosition(),
                                width: width < 0 ? 0 : width,
                                y: that._options.canvas.top,
                                height: that._options.canvas.height,
                                style: {cursor: scaleOptions.endValue - scaleOptions.startValue === selectedRange.endValue - selectedRange.startValue ? 'default' : 'pointer'}
                            };
                        that._selectedAreaTracker.applySettings(options);
                        that._areaTracker.applySettings({
                            x: that._options.canvas.left,
                            width: that._options.canvas.width,
                            y: that._options.canvas.top,
                            height: that._options.canvas.height
                        })
                    },
                    applyPosition: function(disableAnimation) {
                        var that = this;
                        that.getSlider(START_VALUE_INDEX).applyPosition(disableAnimation);
                        that.getSlider(END_VALUE_INDEX).applyPosition(disableAnimation);
                        that.applyAreaTrackersPosition()
                    },
                    redraw: function(group) {
                        var that = this;
                        that.getSlider(START_VALUE_INDEX).redraw(group);
                        that.getSlider(END_VALUE_INDEX).redraw(group)
                    },
                    appendTrackers: function(group) {
                        var that = this;
                        if (that._areaTracker && that._selectedAreaTracker) {
                            that._areaTracker.append(group);
                            that._selectedAreaTracker.append(group)
                        }
                        that.getSlider(START_VALUE_INDEX).appendTrackers(group);
                        that.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 that = this;
                        that._selectedAreaTracker.applySettings({style: {cursor: style}});
                        that._areaTracker.applySettings({style: {cursor: style}})
                    }
                }
        }())
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file slidersEventsManager.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            utils = DX.utils,
            MIN_MANUAL_SELECTING_WIDTH = 10,
            START_VALUE_INDEX = 0,
            END_VALUE_INDEX = 1,
            addNamespace = DX.ui.events.addNamespace,
            setEvents = function() {
                var win = window;
                win = DX.viz.rangeSelector.mockWindow || window;
                var touchSupport = "ontouchstart" in win,
                    msPointerEnabled = win.navigator.msPointerEnabled,
                    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"
                }
            },
            _SlidersEventManager,
            getEventPageX = rangeSelector.utils.getEventPageX,
            rangeSelectorCount = 0;
        setEvents();
        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 isMultiTouches = function(event) {
                var originalEvent = event.originalEvent,
                    touches = event.touches,
                    eventTouches = originalEvent ? originalEvent.touches : false;
                return touches && touches.length > 1 || eventTouches && eventTouches.length > 1 || null
            };
        var isTouchEventArgs = function(e) {
                return e && e.type && e.type.indexOf('touch') === 0
            };
        _SlidersEventManager = rangeSelector.SlidersEventsManager = function(renderer, slidersController, processSelectionChanged) {
            var that = this,
                uniqueNS = that._uniqueNS = 'dx-range-selector_' + rangeSelectorCount++,
                rangeSelectorEvents = rangeSelector.events;
            that._renderer = renderer;
            that._slidersController = slidersController;
            that._processSelectionChanged = processSelectionChanged;
            that._enabled = true;
            that._eventsNames = {
                start: addNamespace(rangeSelectorEvents.start, uniqueNS),
                move: addNamespace(rangeSelectorEvents.move, uniqueNS),
                end: addNamespace(rangeSelectorEvents.end, uniqueNS)
            }
        };
        _SlidersEventManager.prototype = {
            constructor: _SlidersEventManager,
            _getRootOffsetLeft: function() {
                return rangeSelector.utils.getRootOffsetLeft(this._renderer)
            },
            _initializeSliderEvents: function(sliderIndex) {
                var that = this,
                    renderer = that._renderer,
                    isTouchEvent,
                    slidersController = that._slidersController,
                    processSelectionChanged = that._processSelectionChanged,
                    slider = slidersController.getSlider(sliderIndex),
                    anotherSlider = slider.getAnotherSlider(),
                    fastSwap,
                    startOffsetPosition,
                    splitterMoving,
                    sliderEndHandler = function(e) {
                        if (splitterMoving) {
                            splitterMoving = false;
                            slidersController.processDocking();
                            processSelectionChanged(false)
                        }
                    },
                    sliderMoveHandler = function(e) {
                        var doSwap,
                            pageX,
                            offsetPosition,
                            svgOffsetLeft = that._getRootOffsetLeft(),
                            position,
                            sliderIndex = slider.getIndex();
                        if (isTouchEvent !== isTouchEventArgs(e))
                            return;
                        if (!isLeftButtonPressed(e, true) && splitterMoving) {
                            splitterMoving = false;
                            slidersController.processDocking();
                            processSelectionChanged(false)
                        }
                        else if (splitterMoving) {
                            if (!isMultiTouches(e)) {
                                this.preventedDefault = true;
                                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)
                        }
                    },
                    eventsNames = that._eventsNames;
                slider.startEventHandler = function(e) {
                    if (!that._enabled || !isLeftButtonPressed(e) || splitterMoving)
                        return;
                    fastSwap = this === slider.getSliderTracker().element;
                    splitterMoving = true;
                    isTouchEvent = isTouchEventArgs(e);
                    startOffsetPosition = getEventPageX(e) - slider.getPosition() - that._getRootOffsetLeft();
                    if (!isMultiTouches(e)) {
                        this.preventedDefault = true;
                        e.stopPropagation();
                        e.preventDefault()
                    }
                };
                slider.on(eventsNames.start, slider.startEventHandler);
                $(document).on(eventsNames.end, sliderEndHandler).on(eventsNames.move, sliderMoveHandler);
                slider.__moveEventHandler = sliderMoveHandler
            },
            _initializeAreaEvents: function() {
                var that = this,
                    renderer = that._renderer,
                    isTouchEvent,
                    slidersController = that._slidersController,
                    processSelectionChanged = that._processSelectionChanged,
                    areaTracker = slidersController.getAreaTracker(),
                    unselectedAreaProcessing = false,
                    splitterMoving = false,
                    startPageX,
                    areaEndHandler = function(e) {
                        var pageX;
                        if (unselectedAreaProcessing) {
                            pageX = getEventPageX(e);
                            if (that._options.behavior.moveSelectedRangeByClick && Math.abs(startPageX - pageX) < MIN_MANUAL_SELECTING_WIDTH)
                                slidersController.applySelectedAreaCenterPosition(pageX - that._getRootOffsetLeft());
                            unselectedAreaProcessing = false;
                            processSelectionChanged(false)
                        }
                    },
                    areaMoveHandler = function(e) {
                        var pageX,
                            startPosition,
                            endPosition,
                            svgOffsetLeft = that._getRootOffsetLeft();
                        if (isTouchEvent !== isTouchEventArgs(e))
                            return;
                        if (unselectedAreaProcessing && !isLeftButtonPressed(e)) {
                            unselectedAreaProcessing = false;
                            processSelectionChanged(false)
                        }
                        if (unselectedAreaProcessing) {
                            pageX = getEventPageX(e);
                            if (that._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)
                            }
                        }
                    },
                    eventsNames = that._eventsNames;
                areaTracker.on(eventsNames.start, function(e) {
                    if (!that._enabled || !isLeftButtonPressed(e) || unselectedAreaProcessing)
                        return;
                    unselectedAreaProcessing = true;
                    isTouchEvent = isTouchEventArgs(e);
                    startPageX = getEventPageX(e)
                });
                $(document).on(eventsNames.end, areaEndHandler).on(eventsNames.move, areaMoveHandler);
                that.__areaMoveEventHandler = areaMoveHandler
            },
            _initializeSelectedAreaEvents: function() {
                var that = this,
                    renderer = that._renderer,
                    isTouchEvent,
                    slidersController = that._slidersController,
                    processSelectionChanged = that._processSelectionChanged,
                    selectedAreaTracker = slidersController.getSelectedAreaTracker(),
                    selectedAreaMoving = false,
                    offsetStartPosition,
                    selectedRangeInterval,
                    selectedAreaEndHandler = function(e) {
                        if (selectedAreaMoving) {
                            selectedAreaMoving = false;
                            slidersController.processDocking();
                            processSelectionChanged(false)
                        }
                    },
                    selectedAreaMoveHandler = function(e) {
                        var positionDelta,
                            pageX;
                        if (isTouchEvent !== isTouchEventArgs(e))
                            return;
                        if (selectedAreaMoving && !isLeftButtonPressed(e)) {
                            selectedAreaMoving = false;
                            slidersController.processDocking();
                            processSelectionChanged(false)
                        }
                        if (selectedAreaMoving) {
                            if (!isMultiTouches(e)) {
                                this.preventedDefault = true;
                                e.preventDefault()
                            }
                            pageX = getEventPageX(e);
                            positionDelta = pageX - slidersController.getSlider(START_VALUE_INDEX).getPosition() - offsetStartPosition;
                            slidersController.moveSliders(positionDelta, selectedRangeInterval);
                            processSelectionChanged(true)
                        }
                    },
                    eventsNames = that._eventsNames;
                selectedAreaTracker.on(eventsNames.start, function(e) {
                    if (!that._enabled || !isLeftButtonPressed(e) || selectedAreaMoving)
                        return;
                    selectedAreaMoving = true;
                    isTouchEvent = isTouchEventArgs(e);
                    offsetStartPosition = getEventPageX(e) - slidersController.getSlider(START_VALUE_INDEX).getPosition();
                    selectedRangeInterval = slidersController.getSelectedRangeInterval();
                    if (!isMultiTouches(e)) {
                        this.preventedDefault = true;
                        e.stopPropagation();
                        e.preventDefault()
                    }
                });
                $(document).on(eventsNames.end, selectedAreaEndHandler).on(eventsNames.move, selectedAreaMoveHandler);
                that.__selectedAreaMoveEventHandler = selectedAreaMoveHandler
            },
            applyOptions: function(options) {
                this._options = options
            },
            dispose: function() {
                $(document).off('.' + this._uniqueNS)
            },
            initialize: function() {
                var that = this;
                if (!that._renderer.isInitialized())
                    return;
                that._initializeSelectedAreaEvents(that);
                that._initializeAreaEvents();
                that._initializeSliderEvents(START_VALUE_INDEX);
                that._initializeSliderEvents(END_VALUE_INDEX)
            },
            setEnabled: function(enabled) {
                this._enabled = enabled
            }
        };
        rangeSelector.__setEvents = setEvents
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, 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 that = this,
                            sliderHandle,
                            sliderGroup,
                            sliderHandleOptions = that._options.sliderHandle;
                        sliderGroup = that._renderer.createGroup({'class': 'slider'});
                        sliderGroup.applySettings({
                            translateX: that._options.canvas.left,
                            translateY: that._options.canvas.top
                        });
                        sliderHandle = that._renderer.createLine(0, 0, 0, that._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 ? that._options.sliderHandle.color : that._options.sliderMarker.invalidRangeColor})
                        };
                        sliderGroup.updateHeight = function() {
                            sliderHandle.applySettings({points: [0, 0, 0, that._options.canvas.height]})
                        };
                        sliderGroup.applyOptions = function(options) {
                            sliderHandle.applySettings(options)
                        };
                        sliderGroup.__line = sliderHandle;
                        return sliderGroup
                    },
                    _createSliderTracker: function() {
                        var that = this,
                            sliderHandleWidth = that._options.sliderHandle.width,
                            splitterWidth = SPLITTER_WIDTH < sliderHandleWidth ? sliderHandleWidth : SPLITTER_WIDTH,
                            sliderWidth = touchSupport || msPointerEnabled ? TOUCH_SPLITTER_WIDTH : splitterWidth,
                            sliderTracker,
                            sliderTrackerGroup;
                        sliderTracker = that._renderer.createRect(-sliderWidth / 2, 0, sliderWidth, that._options.canvas.height, 0, {
                            fill: 'grey',
                            stroke: 'grey',
                            opacity: 0.0001,
                            style: {cursor: 'w-resize'}
                        });
                        sliderTrackerGroup = that._renderer.createGroup({'class': 'sliderTracker'});
                        sliderTrackerGroup.applySettings({
                            translateX: 0,
                            translateY: that._options.canvas.top
                        });
                        sliderTracker.append(sliderTrackerGroup);
                        sliderTrackerGroup.updateHeight = function() {
                            sliderTracker.applySettings({height: that._options.canvas.height})
                        };
                        sliderTrackerGroup.__rect = sliderTracker;
                        return sliderTrackerGroup
                    },
                    _drawSliderTracker: function(group) {
                        var that = this,
                            sliderTracker = that._createSliderTracker();
                        if (sliderTracker) {
                            sliderTracker.append(group);
                            that._sliderTracker = sliderTracker
                        }
                    },
                    _createSliderMarker: function(options) {
                        return rangeSelector.rangeSelectorFactory.createSliderMarker(options)
                    },
                    _setPosition: function(position, correctByMinMaxRange) {
                        var that = this,
                            correctedPosition = that._correctPosition(position),
                            value = that._options.translator.untranslate(correctedPosition);
                        that.setValue(value, correctByMinMaxRange, false);
                        that._position = correctedPosition
                    },
                    _setPositionForBothSliders: function(startPosition, interval) {
                        var that = this,
                            anotherSlider,
                            startValue,
                            endValue,
                            endPosition,
                            type = that._options.scale.type,
                            base = that._options.scale.logarithmBase,
                            inverted = that._options.scale.inverted;
                        var getNextValue = function(value, isNegative) {
                                var lgPower;
                                if (type === 'logarithmic') {
                                    lgPower = utils.addInterval(utils.adjustValue(utils.getLog(value, base)), interval, isNegative);
                                    return utils.raiseTo(lgPower, base)
                                }
                                else
                                    return utils.addInterval(value, interval, isNegative)
                            };
                        anotherSlider = that.getAnotherSlider();
                        startPosition = that._correctBounds(startPosition);
                        startValue = that._options.translator.untranslate(startPosition);
                        endValue = getNextValue(startValue);
                        if (!inverted && endValue > that._options.scale.endValue || inverted && endValue < that._options.scale.endValue) {
                            endValue = that._options.scale.endValue;
                            endPosition = that._options.canvas.left + that._options.canvas.width;
                            startValue = getNextValue(endValue, true);
                            startPosition = that._options.translator.translate(startValue)
                        }
                        else
                            endPosition = that._options.translator.translate(endValue);
                        if (that._values)
                            if (!inverted ? startValue < that._values[0] : startValue > that._values[that._values.length - 1]) {
                                startValue = that._correctBusinessValueByAvailableValues(startValue, false);
                                endValue = getNextValue(startValue)
                            }
                            else {
                                endValue = that._correctBusinessValueByAvailableValues(endValue, false);
                                startValue = getNextValue(endValue, true)
                            }
                        anotherSlider.setValue(endValue, undefined, false);
                        that.setValue(startValue, undefined, false);
                        that._position = startPosition;
                        anotherSlider._position = endPosition
                    },
                    _correctPosition: function(position) {
                        var that = this,
                            correctedPosition = that._correctInversion(position);
                        correctedPosition = that._correctBounds(correctedPosition);
                        return correctedPosition
                    },
                    _correctInversion: function(position) {
                        var that = this,
                            correctedPosition = position,
                            anotherSliderPosition = that.getAnotherSlider().getPosition(),
                            slidersInverted = that.getIndex() === START_VALUE_INDEX ? position > anotherSliderPosition : position < anotherSliderPosition;
                        if (slidersInverted)
                            correctedPosition = anotherSliderPosition;
                        return correctedPosition
                    },
                    _correctBounds: function(position) {
                        var that = this,
                            correctedPosition = position,
                            canvas = that._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, skipCorrection) {
                        var that = this,
                            result = that._correctBusinessValueByAvailableValues(businessValue, skipCorrection);
                        if (correctByMinMaxRange)
                            result = that._correctBusinessValueByMinMaxRangeFromAnotherSlider(result);
                        result = that._correctBusinessValueByMinRangeFromStartEndValues(result);
                        return result
                    },
                    _correctBusinessValueByAvailableValues: function(businessValue, skipCorrection) {
                        var values = this._values;
                        if (!skipCorrection && values)
                            return rangeSelector.utils.findNearValue(values, businessValue);
                        return businessValue
                    },
                    _correctBusinessValueByMinMaxRangeFromAnotherSlider: function(businessValue) {
                        var that = this,
                            result = businessValue,
                            scale = that._options.scale,
                            values = that._values,
                            sliderIndex = that.getIndex(),
                            anotherBusinessValue = that.getAnotherSlider().getValue(),
                            isValid = true,
                            minValue,
                            maxValue;
                        if (!scale.inverted && sliderIndex === START_VALUE_INDEX || scale.inverted && sliderIndex === END_VALUE_INDEX) {
                            if (scale.maxRange)
                                minValue = that._addInterval(anotherBusinessValue, scale.maxRange, true);
                            if (scale.minRange)
                                maxValue = that._addInterval(anotherBusinessValue, scale.minRange, true)
                        }
                        else {
                            if (scale.maxRange)
                                maxValue = that._addInterval(anotherBusinessValue, scale.maxRange);
                            if (scale.minRange)
                                minValue = that._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
                        }
                        that._setValid(isValid);
                        return result
                    },
                    _addInterval: function(value, interval, isNegative) {
                        var result,
                            type = this._options.scale.type,
                            base = type === "logarithmic" && this._options.scale.logarithmBase;
                        if (base) {
                            var power = utils.addInterval(utils.getLog(value, base), interval, isNegative);
                            result = Math.pow(base, power)
                        }
                        else
                            result = utils.addInterval(value, interval, isNegative);
                        return result
                    },
                    _correctBusinessValueByMinRangeFromStartEndValues: function(businessValue) {
                        var that = this,
                            values = that._values,
                            startValue,
                            endValue,
                            isValid = true,
                            scale = that._options.scale,
                            result = businessValue;
                        if (scale.minRange)
                            if (that.getIndex() === END_VALUE_INDEX) {
                                startValue = that._addInterval(scale.startValue, scale.minRange, scale.inverted);
                                if (!scale.inverted && result < startValue || scale.inverted && result > startValue)
                                    result = startValue
                            }
                            else if (that.getIndex() === START_VALUE_INDEX) {
                                endValue = that._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 that = this,
                            isAnimation = that._options.behavior.animationEnabled && !disableAnimation,
                            top = that._options.canvas.top,
                            slider = that._slider;
                        if (isAnimation || slider.inAnimation) {
                            slider.inAnimation = true;
                            slider.animate({translate: {
                                    x: position,
                                    y: top
                                }}, isAnimation ? animationOptions : {duration: 0}, function() {
                                slider.inAnimation = false
                            });
                            that._sliderTracker.animate({translate: {
                                    x: position,
                                    y: top
                                }}, isAnimation ? animationOptions : {duration: 0})
                        }
                        else {
                            that._slider.applySettings({
                                translateX: position,
                                translateY: top
                            });
                            that._sliderTracker.applySettings({
                                translateX: position,
                                translateY: top
                            })
                        }
                        that._sliderTracker.updateHeight();
                        that._slider.updateHeight()
                    },
                    _applyShutterPosition: function(position, disableAnimation) {
                        var that = this,
                            shutterSettings,
                            shutter = that._shutter,
                            isAnimation = that._options.behavior.animationEnabled && !disableAnimation,
                            sliderIndex = that.getIndex();
                        if (sliderIndex == START_VALUE_INDEX)
                            shutterSettings = {
                                x: that._options.canvas.left,
                                y: that._options.canvas.top,
                                width: position - that._options.canvas.left,
                                height: that._options.canvas.height
                            };
                        else if (sliderIndex == END_VALUE_INDEX)
                            shutterSettings = {
                                x: position + 1,
                                y: that._options.canvas.top,
                                width: that._options.canvas.left + that._options.canvas.width - position,
                                height: that._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 that = this;
                        if (that._marker)
                            that._marker.setValid(isValid);
                        that._slider.setValid(isValid)
                    },
                    _setText: function(text) {
                        var that = this;
                        if (that._marker)
                            that._marker.setText(text)
                    },
                    ctor: function(renderer, index) {
                        var that = this;
                        that.callBase(renderer);
                        that._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 that = this;
                        if (that._sliderTracker)
                            that._sliderTracker.append(group)
                    },
                    getSliderTracker: function() {
                        return this._sliderTracker
                    },
                    changeLocation: function() {
                        var that = this;
                        if (that._marker)
                            that._marker.changeLocation();
                        that._index = this._index === START_VALUE_INDEX ? END_VALUE_INDEX : START_VALUE_INDEX;
                        that._lastPosition = null
                    },
                    setPosition: function(position, correctByMinMaxRange, selectedRangeInterval) {
                        var that = this,
                            slider;
                        if (selectedRangeInterval !== undefined) {
                            slider = that.getIndex() === START_VALUE_INDEX ? that : that.getAnotherSlider();
                            slider._setPositionForBothSliders(position, selectedRangeInterval)
                        }
                        else
                            that._setPosition(position, correctByMinMaxRange)
                    },
                    getPosition: function() {
                        return this._position
                    },
                    _applyOptions: function(options) {
                        this._lastPosition = null
                    },
                    setValue: function(value, correctByMinMaxRange, skipCorrection) {
                        var that = this;
                        if (value === undefined) {
                            that._value = undefined;
                            that._valuePosition = that._position = that.getIndex() === START_VALUE_INDEX ? that._options.canvas.left : that._options.canvas.left + that._options.canvas.width;
                            that._setText(rangeSelector.consts.emptySliderMarkerText)
                        }
                        else {
                            that._value = that._correctBusinessValue(value, correctByMinMaxRange, utils.isDefined(skipCorrection) ? !!skipCorrection : true);
                            that._valuePosition = that._position = that._options.translator.translate(that._value);
                            that._setText(rangeSelector.formatValue(that._value, that._options.sliderMarker))
                        }
                    },
                    getValue: function() {
                        return this._value
                    },
                    canSwap: function() {
                        var that = this,
                            scale = that._options.scale,
                            startValue,
                            endValue,
                            anotherSliderValue;
                        if (that._options.behavior.allowSlidersSwap) {
                            if (scale.minRange) {
                                anotherSliderValue = that.getAnotherSlider().getValue();
                                if (that.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 that = this;
                        that._position = that._valuePosition;
                        that.applyPosition(false);
                        that._setValid(true)
                    },
                    applyPosition: function(disableAnimation) {
                        var that = this,
                            position = that.getPosition();
                        if (that._lastPosition !== position) {
                            that._applySliderPosition(position, disableAnimation);
                            that._applyShutterPosition(position, disableAnimation);
                            that._lastPosition = position
                        }
                    },
                    on: function(event, handler) {
                        var that = this;
                        that._sliderTracker.on(event, handler);
                        if (that._marker)
                            that._marker.getTracker().on(event, handler)
                    },
                    _update: function() {
                        var that = this;
                        that._marker && that._marker.applyOptions(that._options.sliderMarker);
                        that._shutter && that._shutter.applySettings({
                            fill: that._options.shutter.color,
                            fillOpacity: that._options.shutter.opacity
                        });
                        that._slider && that._slider.applyOptions({
                            strokeWidth: that._options.sliderHandle.width,
                            stroke: that._options.sliderHandle.color,
                            strokeOpacity: that._options.sliderHandle.opacity
                        })
                    },
                    _draw: function(group) {
                        var that = this,
                            slider,
                            marker,
                            sliderAreaGroup,
                            shutter,
                            startPos,
                            startWidth,
                            index = that.getIndex();
                        sliderAreaGroup = that._renderer.createGroup({'class': 'sliderArea'});
                        sliderAreaGroup.append(group);
                        if (index === START_VALUE_INDEX)
                            shutter = that._renderer.createRect(that._options.canvas.left, that._options.canvas.top, 0, that._options.canvas.height, 0);
                        else if (index === END_VALUE_INDEX)
                            shutter = that._renderer.createRect(that._options.canvas.left, that._options.canvas.top, that._options.canvas.width, that._options.canvas.height, 0);
                        if (shutter) {
                            shutter.append(sliderAreaGroup);
                            slider = that._createSlider();
                            if (slider)
                                slider.append(sliderAreaGroup);
                            if (that._options.sliderMarker.visible) {
                                marker = that._createSliderMarker({
                                    renderer: that._renderer,
                                    isLeftPointer: index === END_VALUE_INDEX,
                                    sliderMarkerOptions: that._options.sliderMarker
                                });
                                marker.draw(slider)
                            }
                            that._shutter = shutter;
                            that._slider = slider;
                            that._marker = marker
                        }
                        that._drawSliderTracker(group)
                    }
                }
        }())
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, 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(that, textSize) {
                    return {
                            width: Math.round(2 * that._options.padding + textSize.width),
                            height: Math.round(2 * that._options.padding + textSize.height * rangeSelector.consts.fontHeightRatio)
                        }
                };
            var initializeAreaPoints = function(that, textSize) {
                    var rectSize = getRectSize(that, textSize);
                    that._points = [];
                    if (that._isLeftPointer) {
                        that._points.push({
                            x: 0,
                            y: 0
                        });
                        that._points.push({
                            x: rectSize.width,
                            y: 0
                        });
                        that._points.push({
                            x: rectSize.width,
                            y: rectSize.height
                        });
                        that._points.push({
                            x: that._options.pointerSize,
                            y: rectSize.height
                        });
                        that._points.push({
                            x: 0,
                            y: rectSize.height + that._options.pointerSize
                        })
                    }
                    else {
                        that._points.push({
                            x: 0,
                            y: 0
                        });
                        that._points.push({
                            x: rectSize.width,
                            y: 0
                        });
                        that._points.push({
                            x: rectSize.width,
                            y: rectSize.height + that._options.pointerSize
                        });
                        that._points.push({
                            x: rectSize.width - that._options.pointerSize,
                            y: rectSize.height
                        });
                        that._points.push({
                            x: 0,
                            y: rectSize.height
                        })
                    }
                };
            var getPointerPosition = function(that, textSize) {
                    var rectSize = getRectSize(that, textSize);
                    if (that._isLeftPointer)
                        return {
                                x: 0,
                                y: rectSize.height + that._options.pointerSize
                            };
                    else
                        return {
                                x: rectSize.width - 1,
                                y: rectSize.height + that._options.pointerSize
                            }
                };
            var draw = function(group) {
                    var that = this;
                    var padding = that._options.padding;
                    that._sliderMarkerGroup = that._renderer.createGroup({'class': 'sliderMarker'});
                    that._sliderMarkerGroup.append(group);
                    that._area = that._renderer.createArea(that.points, {fill: that._options.color});
                    that._area.append(that._sliderMarkerGroup);
                    that._label = that._renderer.createText(that._text, padding, padding, {
                        font: that._options.font,
                        align: 'left',
                        style: {'-webkit-user-select': 'none'}
                    });
                    that._label.append(that._sliderMarkerGroup);
                    that._tracker = that._renderer.createRect(0, 0, 2 * padding, 2 * padding + that._options.pointerSize, 0, {
                        fill: 'grey',
                        stroke: 'grey',
                        opacity: 0.0001,
                        style: {cursor: 'pointer'}
                    });
                    that._tracker.append(that._sliderMarkerGroup);
                    that._drawn = true;
                    that.update()
                };
            var getTextSize = function(that) {
                    var textSize = that._label.getBBox();
                    if (!that._textHeight && isFinite(textSize.height))
                        that._textHeight = textSize.height;
                    return {
                            width: textSize.width,
                            height: that._textHeight
                        }
                };
            var update = function(stop) {
                    var that = this,
                        textSize,
                        rectSize,
                        pointerPosition;
                    that._interval && clearInterval(that._interval);
                    delete that._interval;
                    if (!that._drawn)
                        return;
                    that._label.updateText(that._text);
                    textSize = getTextSize(that);
                    if (!stop) {
                        that._textSize = that._textSize || textSize;
                        that._textSize = textSize.width > that._textSize.width || textSize.height > that._textSize.height ? textSize : that._textSize;
                        textSize = that._textSize;
                        that._interval = setInterval(function() {
                            update.call(that, [true])
                        }, 75)
                    }
                    else {
                        delete that._textSize;
                        that._textSize = textSize
                    }
                    rectSize = getRectSize(that, textSize);
                    pointerPosition = getPointerPosition(that, textSize);
                    that._sliderMarkerGroup.applySettings({
                        translateX: -pointerPosition.x,
                        translateY: -pointerPosition.y
                    });
                    initializeAreaPoints(that, textSize);
                    that._area.applySettings({
                        points: that._points,
                        fill: that._isValid ? that._options.color : that._options.invalidRangeColor
                    });
                    that._tracker.applySettings({
                        width: rectSize.width,
                        height: rectSize.height + that._options.pointerSize
                    });
                    that._label.applySettings({
                        x: that._options.padding,
                        y: rectSize.height - that._options.padding
                    })
                };
            var getText = function() {
                    var that = this;
                    return that._text
                };
            var setText = function(value) {
                    var that = this;
                    if (that._text !== value) {
                        that._text = value;
                        that.update()
                    }
                };
            var setValid = function(isValid) {
                    var that = this;
                    that._isValid = isValid;
                    that.update()
                };
            var changeLocation = function() {
                    var that = this;
                    that._isLeftPointer = !that._isLeftPointer;
                    that.update()
                };
            var getTracker = function() {
                    var that = this;
                    return that._tracker
                };
            return {
                    ctor: ctor,
                    draw: draw,
                    update: update,
                    getText: getText,
                    setText: setText,
                    changeLocation: changeLocation,
                    applyOptions: applyOptions,
                    getTracker: getTracker,
                    setValid: setValid
                }
        }())
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file rangeView.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector;
        rangeSelector.RangeView = rangeSelector.BaseVisualElement.inherit(function() {
            return {_draw: function(group) {
                        var that = this,
                            viewRect,
                            viewImage,
                            backgroundColor,
                            series,
                            i,
                            showChart,
                            canvas,
                            options = that._options,
                            seriesOptions,
                            isEmpty = options.isEmpty;
                        showChart = options.seriesDataSource && options.seriesDataSource.isShowChart() && !isEmpty;
                        canvas = options.canvas;
                        if (showChart)
                            backgroundColor = options.seriesDataSource.getBackgroundColor();
                        else if (!isEmpty && options.background.visible)
                            backgroundColor = options.background.color;
                        if (options.background.visible && backgroundColor) {
                            viewRect = that._renderer.createRect(canvas.left, canvas.top, canvas.width + 1, canvas.height, 0, {
                                fill: backgroundColor,
                                'class': 'dx-range-selector-background'
                            });
                            viewRect.append(group)
                        }
                        if (options.background.visible && options.background.image && options.background.image.url) {
                            viewImage = that._renderer.createImage(canvas.left, canvas.top, canvas.width + 1, canvas.height, options.background.image.url, {location: options.background.image.location});
                            viewImage.append(group)
                        }
                        if (showChart) {
                            series = options.seriesDataSource.getSeries();
                            options.seriesDataSource.adjustSeriesDimensions(options.translators, options.chart.useAggregation);
                            for (i = 0; i < series.length; i++) {
                                seriesOptions = series[i].getOptions();
                                seriesOptions.seriesGroup = group;
                                seriesOptions.labelsGroup = group;
                                series[i].draw(options.translators, options.behavior && options.behavior.animationEnabled && that._renderer.animationEnabled())
                            }
                        }
                    }}
        }())
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file seriesDataSource.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            charts = DX.viz.charts,
            core = DX.viz.core,
            coreFactory = core.CoreFactory,
            utils = DX.utils;
        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 && (utils.isNumber(data[0]) || utils.isDate(data[0]))
                };
            var convertToArrayOfObjects = function(data) {
                    return $.map(data, function(item, i) {
                            return {
                                    arg: item,
                                    val: i
                                }
                        })
                };
            var calculateSeries = function(that, options, templatedSeries) {
                    var series = [],
                        particularSeriesOptions,
                        seriesTheme,
                        data,
                        parsedData,
                        chartThemeManager = that.themeManager,
                        hasSeriesTemplate = !!chartThemeManager.getOptions('seriesTemplate'),
                        allSeriesOptions = hasSeriesTemplate ? templatedSeries : options.chart.series,
                        seriesValueType = options.chart.valueAxis && options.chart.valueAxis.valueType,
                        dataSourceField,
                        i;
                    that.teamplateData = [];
                    if (options.dataSource && !allSeriesOptions) {
                        if (isArrayOfSimpleTypes(options.dataSource))
                            options.dataSource = convertToArrayOfObjects(options.dataSource);
                        dataSourceField = options.dataSourceField || 'arg';
                        allSeriesOptions = {
                            argumentField: dataSourceField,
                            valueField: dataSourceField
                        };
                        that._hideChart = true
                    }
                    allSeriesOptions = $.isArray(allSeriesOptions) ? allSeriesOptions : allSeriesOptions ? [allSeriesOptions] : [];
                    that._backgroundColor = options.backgroundColor !== undefined ? options.backgroundColor : chartThemeManager.getOptions("backgroundColor");
                    for (i = 0; i < allSeriesOptions.length; i++) {
                        particularSeriesOptions = $.extend(true, {
                            argumentType: options.valueType,
                            argumentAxisType: options.axisType,
                            valueType: dataSourceField ? options.valueType : seriesValueType,
                            incidentOccured: options.incidentOccured
                        }, allSeriesOptions[i]);
                        particularSeriesOptions.rotated = false;
                        data = particularSeriesOptions.data || options.dataSource;
                        seriesTheme = chartThemeManager.getOptions("series", particularSeriesOptions);
                        seriesTheme.argumentField = seriesTheme.argumentField || options.dataSourceField;
                        if (data && data.length > 0) {
                            var newSeries = coreFactory.createSeries(options.renderer, seriesTheme);
                            series.push(newSeries)
                        }
                        if (hasSeriesTemplate) {
                            $.each(data, function(_, data) {
                                $.each(newSeries.getTeamplatedFields(), function(_, field) {
                                    data[field.teamplateField] = data[field.originalField]
                                });
                                that.teamplateData.push(data)
                            });
                            newSeries.updateTeamplateFieldNames()
                        }
                    }
                    data = hasSeriesTemplate ? that.teamplateData : data;
                    that._dataValidator = charts.factory.createDataValidator(data, [series], options.incidentOccured, chartThemeManager.getOptions("dataPrepareSettings"));
                    parsedData = that._dataValidator.validate();
                    for (i = 0; i < series.length; i++) {
                        var particularSeries = series[i];
                        particularSeries.updateData(parsedData)
                    }
                    return series
                };
            var processSeriesFamilies = function(series, equalBarWidth, minBubbleSize, maxBubbleSize) {
                    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 coreFactory.createSeriesFamily({
                                type: type,
                                equalBarWidth: equalBarWidth,
                                minBubbleSize: minBubbleSize,
                                maxBubbleSize: maxBubbleSize
                            });
                        family.add(series);
                        family.adjustSeriesValues();
                        families.push(family)
                    });
                    return families
                };
            var prototypeObject = {
                    ctor: function(options) {
                        var that = this,
                            templatedSeries,
                            seriesTemplate,
                            themeManager = that.themeManager = createThemeManager(options.chart),
                            topIndent = themeManager.getOptions('topIndent'),
                            bottomIndent = themeManager.getOptions('bottomIndent');
                        that._indent = {
                            top: topIndent >= 0 && topIndent < 1 ? topIndent : 0,
                            bottom: bottomIndent >= 0 && bottomIndent < 1 ? bottomIndent : 0
                        };
                        that._valueAxis = themeManager.getOptions('valueAxisRangeSelector') || {};
                        that._hideChart = false;
                        seriesTemplate = themeManager.getOptions('seriesTemplate');
                        if (options.dataSource && seriesTemplate)
                            templatedSeries = utils.processSeriesTemplate(seriesTemplate, options.dataSource);
                        that._series = calculateSeries(that, options, templatedSeries);
                        that._seriesFamilies = processSeriesFamilies(that._series, themeManager.getOptions('equalBarWidth'), themeManager.getOptions('minBubbleSize'), themeManager.getOptions('maxBubbleSize'))
                    },
                    adjustSeriesDimensions: function(translators, useAggregation) {
                        var that = this;
                        if (useAggregation)
                            $.each(that._series || [], function(_, s) {
                                s.resamplePoints(translators)
                            });
                        $.each(that._seriesFamilies, function() {
                            this.adjustSeriesDimensions(translators)
                        })
                    },
                    getBoundRange: function() {
                        var that = this,
                            rangeData,
                            valueAxisMin = that._valueAxis.min,
                            valueAxisMax = that._valueAxis.max,
                            valRange = new core.Range({
                                isValueRange: true,
                                min: valueAxisMin,
                                minVisible: valueAxisMin,
                                max: valueAxisMax,
                                maxVisible: valueAxisMax,
                                axisType: that._valueAxis.type,
                                base: that._valueAxis.logarithmBase
                            }),
                            argRange = new core.Range({}),
                            rangeYSize,
                            rangeVisibleSizeY,
                            i,
                            minIndent,
                            maxIndent;
                        for (i = 0; i < that._series.length; i++) {
                            rangeData = that._series[i].getRangeData();
                            valRange.addRange(rangeData.val);
                            argRange.addRange(rangeData.arg)
                        }
                        if (valRange.isDefined() && argRange.isDefined()) {
                            minIndent = that._valueAxis.inverted ? that._indent.top : that._indent.bottom;
                            maxIndent = that._valueAxis.inverted ? that._indent.bottom : that._indent.top;
                            rangeYSize = valRange.max - valRange.min;
                            rangeVisibleSizeY = ($.isNumeric(valRange.maxVisible) ? valRange.maxVisible : valRange.max) - ($.isNumeric(valRange.minVisible) ? valRange.minVisible : valRange.min);
                            if (utils.isDate(valRange.min))
                                valRange.min = new Date(valRange.min.valueOf() - rangeYSize * minIndent);
                            else
                                valRange.min -= rangeYSize * minIndent;
                            if (utils.isDate(valRange.max))
                                valRange.max = new Date(valRange.max.valueOf() + rangeYSize * maxIndent);
                            else
                                valRange.max += rangeYSize * maxIndent;
                            if ($.isNumeric(rangeVisibleSizeY)) {
                                valRange.maxVisible = valRange.maxVisible ? valRange.maxVisible + rangeVisibleSizeY * maxIndent : undefined;
                                valRange.minVisible = valRange.minVisible ? valRange.minVisible - rangeVisibleSizeY * minIndent : undefined
                            }
                            valRange.invert = that._valueAxis.inverted
                        }
                        return {
                                arg: argRange,
                                val: valRange
                            }
                    },
                    getSeries: function() {
                        var that = this;
                        return that._series
                    },
                    getBackgroundColor: function() {
                        var that = this;
                        return that._backgroundColor
                    },
                    isEmpty: function() {
                        var that = this;
                        return that.getSeries().length === 0
                    },
                    isShowChart: function() {
                        var that = this;
                        return !that.isEmpty() && !that._hideChart
                    },
                    getCalculatedValueType: function() {
                        var that = this,
                            result;
                        if (that._series.length)
                            result = that._series[0].argumentType;
                        return result
                    }
                };
            return prototypeObject
        }())
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file themeManager.js */
    (function($, DX, undefined) {
        DX.viz.rangeSelector = DX.viz.rangeSelector;
        DX.viz.rangeSelector.ThemeManager = DX.viz.core.BaseThemeManager.inherit({
            _themeSection: 'rangeSelector',
            ctor: function(userTheme) {
                this.setTheme(userTheme)
            },
            _initializeTheme: function() {
                this._initializeFont(this._theme.scale.label.font);
                this._initializeFont(this._theme.sliderMarker.font);
                this._initializeFont(this._theme.loadingIndicator.font)
            },
            applyRangeSelectorTheme: function(userOptions) {
                var that = this,
                    chart = userOptions.chart,
                    dataSource = userOptions.dataSource,
                    result;
                delete userOptions.dataSource;
                delete userOptions.chart;
                result = $.extend(true, {}, that._theme, userOptions);
                result.dataSource = dataSource;
                if (chart)
                    result.chart = chart;
                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-rangeselector, file dxRangeSelector.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            viz = DX.viz;
        DX.registerComponent("dxRangeSelector", viz.rangeSelector.RangeSelector)
    })(jQuery, DevExpress);
    DevExpress.MOD_VIZ_RANGESELECTOR = true
}
if (!DevExpress.MOD_VIZ_VECTORMAP) {
    if (!DevExpress.MOD_VIZ_CORE)
        throw Error('Required module is not referenced: viz-core');
    /*! Module viz-vectormap, file map.js */
    (function(DX, $, undefined) {
        DX.viz.map = {};
        var _Number = window.Number,
            _isFunction = DX.utils.isFunction,
            _getRootOffset = DX.utils.getRootOffset;
        var DEFAULT_WIDTH = 800,
            DEFAULT_HEIGHT = 400;
        var DATA_KEY = DX.viz.map.__DATA_KEY = 'vectormap-data';
        DX.viz.map.Map = DX.viz.core.BaseWidget.inherit({
            _init: function() {
                var that = this;
                that.callBase.apply(that, arguments);
                that.renderer = that._renderer = that._factory.createRenderer({
                    width: 1,
                    height: 1,
                    pathModified: that.option('pathModified'),
                    rtl: that.option('rtlEnabled')
                });
                that.renderer.draw(that._element().get(0));
                that._root = that._renderer.getRoot();
                that._root.applySettings({
                    'class': 'dxm',
                    stroke: 'none',
                    strokeWidth: 0,
                    fill: 'none',
                    align: 'center',
                    cursor: 'default',
                    style: {overflow: 'hidden'}
                });
                that._themeManager = that._factory.createThemeManager();
                that._projection = that._factory.createProjection();
                that._tracker = that._factory.createTracker({root: that._root});
                that._background = that._renderer.createRect(0, 0, 0, 0, 0, {'class': 'dxm-background'}).data(DATA_KEY, {type: 'background'});
                that._areasManager = that._factory.createAreasManager({
                    container: that._root,
                    renderer: that._renderer,
                    projection: that._projection,
                    themeManager: that._themeManager,
                    tracker: that._tracker,
                    ready: function() {
                        that.hideLoadingIndicator()
                    }
                });
                that._areasManager.setData(that.option('mapData'));
                that._markersManager = that._factory.createMarkersManager({
                    container: that._root,
                    renderer: that._renderer,
                    projection: that._projection,
                    themeManager: that._themeManager,
                    tracker: that._tracker
                });
                that._markersManager.setData(that.option('markers'));
                that._controlBar = that._factory.createControlBar({
                    container: that._root,
                    renderer: that._renderer,
                    context: that,
                    resetCallback: controlResetCallback,
                    beginMoveCallback: controlBeginMoveCallback,
                    endMoveCallback: controlEndMoveCallback,
                    moveCallback: controlMoveCallback,
                    zoomCallback: controlZoomCallback
                });
                that._legend = that._factory.createLegend({
                    container: that._root,
                    renderer: that._renderer,
                    themeManager: that._themeManager
                });
                that._tooltip = that._factory.createTooltip({
                    container: that._root,
                    renderer: that._renderer,
                    tracker: that._tracker
                });
                that._projection.setBounds(that.option('bounds')).setMaxZoom(that.option('maxZoomFactor')).setZoom(that.option('zoomFactor')).setCenter(that.option('center'));
                that._themeManager.setTheme(that.option('theme'));
                that._themeManager.patchRtlSettings(that.option('rtlEnabled'));
                that._setClickCallback(that.option('click'));
                that._setCenterChangedCallback(that.option('centerChanged'));
                that._setZoomFactorChangedCallback(that.option('zoomFactorChanged'));
                that._setTrackerCallbacks()
            },
            _dispose: function() {
                var that = this;
                that.callBase.apply(that, arguments);
                that._resetTrackerCallbacks();
                that._themeManager.dispose();
                that._tracker.dispose();
                that._areasManager.dispose();
                that._markersManager.dispose();
                that._controlBar.dispose();
                that._legend.dispose();
                that._tooltip.dispose();
                that._renderer.dispose();
                that._disposeLoadIndicator();
                that._renderer = that._themeManager = that._projection = that._tracker = that._root = that._background = that._areasManager = that._markersManager = that._controlBar = that._legend = that._tooltip = that._centerChangedCallback = that._zoomFactorChangedCallback = null
            },
            _setTrackerCallbacks: function() {
                var that = this,
                    renderer = that._renderer,
                    managers = {
                        area: that._areasManager,
                        marker: that._markersManager
                    },
                    projection = that._projection,
                    controlBar = that._controlBar,
                    tooltip = that._tooltip,
                    xdrag,
                    ydrag,
                    isControlDrag = false;
                that._tracker.setCallbacks({
                    click: function(arg) {
                        var offset = _getRootOffset(renderer);
                        arg.$event.x = arg.x - offset.left;
                        arg.$event.y = arg.y - offset.top;
                        var manager = managers[arg.data.type];
                        if (manager)
                            manager.raiseClick(arg.data.index, arg.$event);
                        if (manager || arg.data.type === 'background')
                            that._raiseClick(arg.$event)
                    },
                    start: function(arg) {
                        isControlDrag = arg.data.type === 'control-bar';
                        if (isControlDrag) {
                            arg.data = arg.data.index;
                            controlBar.processStart(arg)
                        }
                        else {
                            xdrag = arg.x;
                            ydrag = arg.y;
                            projection.snapCenter()
                        }
                    },
                    move: function(arg) {
                        if (isControlDrag) {
                            arg.data = arg.data.index;
                            controlBar.processMove(arg)
                        }
                        else {
                            projection.moveCenter(xdrag - arg.x, ydrag - arg.y);
                            xdrag = arg.x;
                            ydrag = arg.y;
                            that._applyTranslate()
                        }
                    },
                    end: function(arg) {
                        if (isControlDrag) {
                            arg.data = arg.data.index;
                            controlBar.processEnd(arg)
                        }
                        else
                            projection.isCenterChanged() && that._raiseCenterChanged();
                        isControlDrag = false
                    },
                    zoom: function(arg) {
                        controlBar.processZoom(arg)
                    },
                    'hover-on': function(arg) {
                        var manager = managers[arg.data.type];
                        if (manager)
                            manager.hoverItem(arg.data.index, true)
                    },
                    'hover-off': function(arg) {
                        var manager = managers[arg.data.type];
                        if (manager)
                            manager.hoverItem(arg.data.index, false)
                    },
                    'focus-on': function(arg, done) {
                        var result = false;
                        if (tooltip.enabled()) {
                            var proxy = managers[arg.data.type] ? managers[arg.data.type].getProxyItem(arg.data.index) : null;
                            if (!!proxy && tooltip.prepare(proxy, {offset: 12})) {
                                var offset = _getRootOffset(renderer);
                                tooltip.show().move(arg.x - offset.left, arg.y - offset.top);
                                result = true
                            }
                        }
                        done(result)
                    },
                    'focus-move': function(arg) {
                        var offset = _getRootOffset(renderer);
                        tooltip.move(arg.x - offset.left, arg.y - offset.top)
                    },
                    'focus-off': function(arg) {
                        tooltip.hide()
                    }
                });
                that._resetTrackerCallbacks = function() {
                    that._resetTrackerCallbacks = that = renderer = managers = projection = controlBar = tooltip = null
                }
            },
            _adjustSize: function(force) {
                var that = this,
                    size = that.option('size') || {},
                    width = size.width >= 0 ? _Number(size.width) : that._element().width(),
                    height = size.height >= 0 ? _Number(size.height) : that._element().height(),
                    hidden = false;
                if (width === 0)
                    if (_Number(size.width) === 0)
                        hidden = true;
                    else
                        width = DEFAULT_WIDTH;
                if (height === 0)
                    if (_Number(size.height) === 0)
                        hidden = true;
                    else
                        height = DEFAULT_HEIGHT;
                if (hidden || !that._element().is(':visible')) {
                    that._incidentOccured("W2001", [that.NAME]);
                    that._width = that._height = 0;
                    return false
                }
                var needResize = that._width !== width || that._height !== height || force;
                if (needResize) {
                    that._width = width;
                    that._height = height;
                    that._renderer.resize(width, height);
                    that._projection.setSize(width, height);
                    that._legend.applyLayout(width, height);
                    that._tooltip.setSize(width, height);
                    that._background.applySettings({
                        x: 0,
                        y: 0,
                        width: width,
                        height: height
                    });
                    that._applyTranslate();
                    that._updateLoadIndicator(undefined, width, height)
                }
                return needResize
            },
            _clean: function() {
                var that = this;
                that._tracker.clean();
                that._background.detach();
                that._areasManager.clean();
                that._markersManager.clean();
                that._controlBar.clean();
                that._legend.clean();
                that._tooltip.clean()
            },
            _render: function() {
                var that = this;
                if (!that._adjustSize(true))
                    return;
                that._tooltip.update(that._themeManager.getTooltipSettings(that.option('tooltip')));
                that._tracker.setOptions(that.option('interaction') || {});
                that._controlBar.setZoomPartition(that._projection.getZoomScalePartition()).setZoom(that._projection.getScaledZoom()).setOptions(that._themeManager.getControlBarSettings(that.option('controlBar')), that.option('interaction'));
                that._background.applySettings(that._themeManager.getBackgroundSettings(that.option('background')));
                that._background.append(that._root);
                that._areasManager.render(that.option('areaSettings'));
                that._markersManager.render(that.option('markerSettings'));
                that._controlBar.render();
                that._legend.render(that._themeManager.getLegendSettings(that.option('legend')));
                that._tooltip.render();
                that._tracker.render();
                that._drawn()
            },
            _optionChanged: function(name, value) {
                var that = this;
                switch (name) {
                    case'theme':
                        that._themeManager.setTheme(value);
                        that._themeManager.patchRtlSettings(that.option('rtlEnabled'));
                        that._invalidate();
                        break;
                    case'click':
                        that._setClickCallback(value);
                        break;
                    case'centerChanged':
                        that._setCenterChangedCallback(value);
                        break;
                    case'zoomFactorChanged':
                        that._setZoomFactorChangedCallback(value);
                        break;
                    case'mapData':
                        that._areasManager.setData(value);
                        break;
                    case'markers':
                        that._markersManager.setData(value);
                        break;
                    case'bounds':
                        that._projection.setBounds(value);
                        that._invalidate();
                        break;
                    case'maxZoomFactor':
                        that._projection.setMaxZoom(value);
                        that._invalidate();
                        break;
                    case'zoomFactor':
                        that._updateZoomFactor(value);
                        break;
                    case'center':
                        that._updateCenter(value);
                        break;
                    default:
                        that.callBase.apply(that, arguments);
                        break
                }
            },
            _getLoadIndicatorOption: function() {
                return this._themeManager.getLoadIndicatorSettings(this.option('loadingIndicator'))
            },
            _setClickCallback: function(callback) {
                this._clickCallback = _isFunction(callback) ? callback : null
            },
            _setCenterChangedCallback: function(callback) {
                var that = this;
                that._centerChangedCallback = _isFunction(callback) ? function() {
                    that._centerChangedCallback && callback.call(that, that._projection.getCenter())
                } : null
            },
            _setZoomFactorChangedCallback: function(callback) {
                var that = this;
                that._zoomFactorChangedCallback = _isFunction(callback) ? function() {
                    that._zoomFactorChangedCallback && callback.call(that, that._projection.getZoom())
                } : null
            },
            _raiseClick: function(arg) {
                var that = this;
                that._clickCallback && setTimeout(function() {
                    that._clickCallback && that._clickCallback.call(that, arg)
                }, 0)
            },
            _raiseCenterChanged: function() {
                this._centerChangedCallback && setTimeout(this._centerChangedCallback, 0)
            },
            _raiseZoomFactorChanged: function() {
                this._zoomFactorChangedCallback && setTimeout(this._zoomFactorChangedCallback, 0)
            },
            _updateCenter: function(center, _noEvent) {
                this._projection.snapCenter().setCenter(center);
                if (this._projection.isCenterChanged()) {
                    this._applyTransform();
                    _noEvent || this._raiseCenterChanged()
                }
            },
            _updateZoomFactor: function(zoomFactor, _noEvent) {
                var that = this;
                that._projection.snapZoom().setZoom(zoomFactor);
                if (that._projection.isZoomChanged()) {
                    that._controlBar.setZoom(that._projection.getScaledZoom());
                    that._applyTransform(true);
                    _noEvent || that._raiseZoomFactorChanged()
                }
            },
            _updateViewport: function(viewport, _noEvent) {
                var that = this;
                that._projection.snapCenter().snapZoom().setViewport(viewport);
                that._applyTransform(that._projection.isZoomChanged());
                if (that._projection.isCenterChanged())
                    _noEvent || that._raiseCenterChanged();
                if (that._projection.isZoomChanged()) {
                    that._controlBar.setZoom(that._projection.getScaledZoom());
                    _noEvent || that._raiseZoomFactorChanged()
                }
            },
            _resize: function() {
                if (this._adjustSize())
                    this._applyTransform(true)
            },
            _applyTranslate: function() {
                var transform = this._projection.getTransform();
                this._areasManager.transform(transform);
                this._markersManager.transform(transform)
            },
            _applyTransform: function(redraw, _noTrackerReset) {
                _noTrackerReset || this._tracker.reset();
                this._applyTranslate();
                if (redraw) {
                    this._areasManager.redraw();
                    this._markersManager.redraw()
                }
            },
            _refresh: function() {
                var that = this,
                    callBase = that.callBase;
                that._endLoading(function() {
                    callBase.call(that)
                })
            },
            render: function() {
                var that = this;
                if (that._width === 0 && that._height === 0)
                    that._refresh();
                else
                    that._resize();
                return that
            },
            getAreas: function() {
                return this._areasManager.getProxyItems()
            },
            getMarkers: function() {
                return this._markersManager.getProxyItems()
            },
            clearAreaSelection: function(_noEvent) {
                this._areasManager.clearSelection(_noEvent);
                return this
            },
            clearMarkerSelection: function(_noEvent) {
                this._markersManager.clearSelection(_noEvent);
                return this
            },
            clearSelection: function(_noEvent) {
                return this.clearAreaSelection(_noEvent).clearMarkerSelection(_noEvent)
            },
            center: function(value, _noEvent) {
                if (value === undefined)
                    return this._projection.getCenter();
                else {
                    this._updateCenter(value, _noEvent);
                    return this
                }
            },
            zoomFactor: function(value, _noEvent) {
                if (value === undefined)
                    return this._projection.getZoom();
                else {
                    this._updateZoomFactor(value, _noEvent);
                    return this
                }
            },
            viewport: function(value, _noEvent) {
                if (value === undefined)
                    return this._projection.getViewport();
                else {
                    this._updateViewport(value, _noEvent);
                    return this
                }
            },
            convertCoordinates: function(x, y) {
                return this._projection.fromScreenPointStrict(x, y)
            },
            showLoadingIndicator: function() {
                this._showLoadIndicator(this._themeManager.getLoadIndicatorSettings(this.option('loadingIndicator')), {
                    width: this._width,
                    height: this._height
                })
            },
            _factory: {
                createRenderer: function(options) {
                    return new DX.viz.renderers.Renderer(options)
                },
                createTooltip: function(parameters) {
                    return new Tooltip(parameters)
                },
                createLegend: function(parameters) {
                    return new Legend(parameters)
                }
            }
        });
        var Tooltip = DX.viz.core.Tooltip.inherit({
                ctor: function(parameters) {
                    var that = this;
                    that._container = parameters.container;
                    that._root = parameters.renderer.createGroup({'class': 'dxm-tooltip'});
                    that.callBase(null, that._root, parameters.renderer);
                    that._tracker = parameters.tracker;
                    that._enabled = false
                },
                dispose: function() {
                    var that = this;
                    that._container = that._root = that._tracker = null;
                    return that.callBase.apply(that, arguments)
                },
                clean: function() {
                    this._root.detach();
                    return this
                },
                render: function() {
                    this._root.append(this._container);
                    return this
                }
            });
        var Legend = DX.viz.core.Legend.inherit({
                ctor: function(parameters) {
                    var that = this;
                    that._container = parameters.container;
                    that._root = parameters.renderer.createGroup({'class': 'dxm-legend'});
                    that._themeManager = parameters.themeManager;
                    that.callBase(null, null, parameters.renderer, that._root)
                },
                dispose: function() {
                    var that = this;
                    that._container = that._root = that._themeManager = null;
                    return that.callBase.apply(that, arguments)
                },
                clean: function() {
                    this._root.detach();
                    return this
                },
                render: function(options) {
                    var that = this,
                        items = [],
                        i = 0,
                        ii = options.items ? options.items.length : 0;
                    for (; i < ii; ++i)
                        items.push(that._themeManager.getLegendItemSettings(options.items[i] || {}));
                    that.update(items, options);
                    that._root.append(that._container);
                    return that.applyLayout(that._size.width, that._size.height)
                },
                applyLayout: function(width, height) {
                    var that = this,
                        layoutOptions;
                    that.setSize({
                        width: width,
                        height: height
                    });
                    that.draw();
                    layoutOptions = that.getLayoutOptions();
                    if (layoutOptions) {
                        var left,
                            top;
                        if (layoutOptions.horizontalAlignment === 'left')
                            left = 0;
                        else if (layoutOptions.horizontalAlignment === 'center')
                            left = width / 2 - layoutOptions.width / 2;
                        else
                            left = width - layoutOptions.width;
                        if (layoutOptions.verticalAlignment === 'top')
                            top = 0;
                        else
                            top = height - layoutOptions.height;
                        that.shift(left, top)
                    }
                    return that
                }
            });
        function projectAreaDefault(dataItem) {
            return this._projection.projectArea(dataItem.coordinates)
        }
        function projectAreaGeoJson(dataItem) {
            if (dataItem.geometry) {
                var type = dataItem.geometry.type,
                    coordinates = dataItem.geometry.coordinates;
                if (coordinates && (type === 'Polygon' || type === 'MultiPolygon')) {
                    type === 'MultiPolygon' && (coordinates = [].concat.apply([], coordinates));
                    return this._projection.projectArea(coordinates)
                }
            }
            return []
        }
        function controlResetCallback() {
            var projection = this._projection,
                isCenterChanged,
                isZoomChanged;
            projection.snapCenter().snapZoom().setCenter(null).setZoom(null);
            isCenterChanged = projection.isCenterChanged();
            isZoomChanged = projection.isZoomChanged();
            if (isCenterChanged || isZoomChanged)
                this._applyTransform(isZoomChanged, true);
            isCenterChanged && this._raiseCenterChanged();
            isZoomChanged && this._raiseZoomFactorChanged()
        }
        function controlBeginMoveCallback() {
            this._projection.snapCenter()
        }
        function controlEndMoveCallback() {
            this._projection.isCenterChanged() && this._raiseCenterChanged()
        }
        function controlMoveCallback(dx, dy) {
            this._projection.moveCenter(dx, dy);
            this._applyTranslate()
        }
        function controlZoomCallback(zoom, x, y) {
            var that = this,
                keepPosition = x !== undefined && y !== undefined,
                coords,
                screenPosition;
            if (keepPosition) {
                screenPosition = _getRootOffset(that._renderer);
                screenPosition = [x - screenPosition.left, y - screenPosition.top];
                coords = that._projection.fromScreenPoint(screenPosition[0], screenPosition[1])
            }
            that._projection.snapZoom().setScaledZoom(zoom);
            if (that._projection.isZoomChanged()) {
                keepPosition && that._projection.snapCenter().setCenterByPoint(coords, screenPosition);
                that._applyTransform(true, true);
                that._raiseZoomFactorChanged();
                keepPosition && that._projection.isCenterChanged() && that._raiseCenterChanged()
            }
        }
        DX.registerComponent('dxVectorMap', DX.viz.map.Map);
        DX.viz.map._internal = {};
        DX.viz.map.sources = {};
        DX.viz.map._tests = {};
        DX.viz.map._tests.Legend = Legend;
        DX.viz.map._tests.Tooltip = Tooltip
    })(DevExpress, jQuery);
    /*! Module viz-vectormap, file projection.js */
    (function(DX, $, undefined) {
        var _Number = Number,
            _isFinite = isFinite,
            _min = Math.min,
            _max = Math.max,
            _abs = Math.abs,
            _tan = Math.tan,
            _atan = Math.atan,
            _exp = Math.exp,
            _round = Math.round,
            _ln = Math.log,
            _pow = Math.pow,
            _isArray = DX.utils.isArray,
            _buildPath = DX.viz.renderers.buildPath;
        var PI = Math.PI,
            QUARTER_PI = PI / 4,
            PI_TO_360 = PI / 360,
            TWO_TO_LN2 = 2 / Math.LN2;
        var DEFAULT_MIN_ZOOM = 1,
            DEFAULT_MAX_ZOOM = 1 << 8;
        var MERCATOR_MIN_LON = -180,
            MERCATOR_MAX_LON = 180,
            MERCATOR_MIN_LAT = -85.0511,
            MERCATOR_MAX_LAT = 85.0511;
        var mercator = {
                aspectRatio: 1,
                project: function(coordinates) {
                    var lon = coordinates[0],
                        lat = coordinates[1];
                    return [lon <= MERCATOR_MIN_LON ? -1 : lon >= MERCATOR_MAX_LON ? +1 : lon / 180, lat <= MERCATOR_MIN_LAT ? +1 : lat >= MERCATOR_MAX_LAT ? -1 : -_ln(_tan(QUARTER_PI + lat * PI_TO_360)) / PI]
                },
                unproject: function(coordinates) {
                    var x = coordinates[0],
                        y = coordinates[1];
                    return [x <= -1 ? MERCATOR_MIN_LON : x >= +1 ? MERCATOR_MAX_LON : 180 * x, y <= -1 ? MERCATOR_MAX_LAT : y >= +1 ? MERCATOR_MIN_LAT : (_atan(_exp(-PI * coordinates[1])) - QUARTER_PI) / PI_TO_360]
                }
            };
        function createProjectUnprojectMethods(p1, p2, delta) {
            var x0 = (p1[0] + p2[0]) / 2 - delta / 2,
                y0 = (p1[1] + p2[1]) / 2 - delta / 2,
                k = 2 / delta;
            return {
                    project: function(coordinates) {
                        var p = mercator.project(coordinates);
                        return [-1 + (p[0] - x0) * k, -1 + (p[1] - y0) * k]
                    },
                    unproject: function(coordinates) {
                        var p = [x0 + (coordinates[0] + 1) / k, y0 + (coordinates[1] + 1) / k];
                        return mercator.unproject(p)
                    }
                }
        }
        function floatsEqual(f1, f2) {
            return _abs(f1 - f2) < 1E-8
        }
        function truncate(value, min, max, fallback) {
            var _value = _Number(value);
            if (_value < min)
                _value = min;
            else if (_value > max)
                _value = max;
            else if (!(min <= _value && _value <= max))
                _value = fallback;
            return _value
        }
        function truncateQuad(quad, min, max) {
            return {
                    lt: [truncate(quad[0], min[0], max[0], min[0]), truncate(quad[1], min[1], max[1], min[1])],
                    rb: [truncate(quad[2], min[0], max[0], max[0]), truncate(quad[3], min[1], max[1], max[1])]
                }
        }
        function parseBounds(bounds) {
            var p1 = mercator.unproject([-1, -1]),
                p2 = mercator.unproject([+1, +1]),
                min = [_min(p1[0], p2[0]), _min(p1[1], p2[1])],
                max = [_max(p1[0], p2[0]), _max(p1[1], p2[1])],
                quad = bounds;
            if (quad && quad.minLon)
                quad = [quad.minLon, quad.minLat, quad.maxLon, quad.maxLat];
            if (quad)
                quad = truncateQuad(quad, min, max);
            return {
                    minBase: min,
                    maxBase: max,
                    min: quad ? [_min(quad.lt[0], quad.rb[0]), _min(quad.lt[1], quad.rb[1])] : min,
                    max: quad ? [_max(quad.lt[0], quad.rb[0]), _max(quad.lt[1], quad.rb[1])] : max
                }
        }
        function selectCenterValue(value1, value2, center1, center2) {
            var result;
            if (value1 > -1 && value2 >= +1)
                result = center1;
            else if (value1 <= -1 && value2 < +1)
                result = center2;
            else
                result = (center1 + center2) / 2;
            return result
        }
        function Projection() {
            this.setBounds(null)
        }
        Projection.prototype = {
            constructor: Projection,
            _minZoom: DEFAULT_MIN_ZOOM,
            _maxZoom: DEFAULT_MAX_ZOOM,
            _zoom: DEFAULT_MIN_ZOOM,
            setSize: function(width, height) {
                var that = this;
                that._x0 = width / 2;
                that._y0 = height / 2;
                if (width / height <= mercator.aspectRatio) {
                    that._xradius = width / 2;
                    that._yradius = width / 2 / mercator.aspectRatio
                }
                else {
                    that._xradius = height / 2 * mercator.aspectRatio;
                    that._yradius = height / 2
                }
                return that
            },
            setBounds: function(bounds) {
                var that = this,
                    _bounds = parseBounds(bounds);
                that._minBase = _bounds.minBase;
                that._maxBase = _bounds.maxBase;
                that._minBound = _bounds.min;
                that._maxBound = _bounds.max;
                var p1 = mercator.project(_bounds.min),
                    p2 = mercator.project(_bounds.max),
                    delta = _min(truncate(_abs(p2[0] - p1[0]), 0.1, 2, 2), truncate(_abs(p2[1] - p1[1]), 0.1, 2, 2)),
                    methods = delta < 2 ? createProjectUnprojectMethods(p1, p2, delta) : mercator;
                that._project = methods.project;
                that._unproject = methods.unproject;
                var minv = that._project(_bounds.minBase),
                    maxv = that._project(_bounds.maxBase);
                that._minv = [_min(minv[0], maxv[0]), _min(minv[1], maxv[1])];
                that._maxv = [_max(minv[0], maxv[0]), _max(minv[1], maxv[1])];
                that._defaultCenter = that._unproject([0, 0]);
                return that.setCenter(that._defaultCenter)
            },
            _toScreen: function(coordinates) {
                return [this._x0 + this._xradius * coordinates[0], this._y0 + this._yradius * coordinates[1]]
            },
            _fromScreen: function(coordinates) {
                return [(coordinates[0] - this._x0) / this._xradius, (coordinates[1] - this._y0) / this._yradius]
            },
            _toTransformed: function(coordinates) {
                return [coordinates[0] * this._zoom + this._dxcenter, coordinates[1] * this._zoom + this._dycenter, ]
            },
            _toTransformedFast: function(coordinates) {
                return [coordinates[0] * this._zoom, coordinates[1] * this._zoom]
            },
            _fromTransformed: function(coordinates) {
                return [(coordinates[0] - this._dxcenter) / this._zoom, (coordinates[1] - this._dycenter) / this._zoom]
            },
            _adjustCenter: function() {
                var that = this,
                    center = that._project(that._center);
                that._dxcenter = -center[0] * that._zoom;
                that._dycenter = -center[1] * that._zoom
            },
            projectArea: function(coordinates) {
                var i = 0,
                    ii = _isArray(coordinates) ? coordinates.length : 0,
                    subcoords,
                    j,
                    jj,
                    subresult,
                    result = [];
                for (; i < ii; ++i) {
                    subcoords = coordinates[i];
                    subresult = [];
                    for (j = 0, jj = _isArray(subcoords) ? subcoords.length : 0; j < jj; ++j)
                        subresult.push(this._project(subcoords[j]));
                    result.push(subresult)
                }
                return result
            },
            projectPoint: function(coordinates) {
                return coordinates ? this._project(coordinates) : []
            },
            getAreaCoordinates: function(data) {
                var k = 0,
                    kk = data.length,
                    partialData,
                    i,
                    ii,
                    list = [],
                    partialPath,
                    point;
                for (; k < kk; ++k) {
                    partialData = data[k];
                    partialPath = [];
                    for (i = 0, ii = partialData.length; i < ii; ++i) {
                        point = this._toScreen(this._toTransformedFast(partialData[i]));
                        partialPath.push(point[0], point[1])
                    }
                    list.push(_buildPath(partialPath))
                }
                return list.join(' ')
            },
            getPointCoordinates: function(data) {
                var point = this._toScreen(this._toTransformedFast(data));
                return {
                        x: _round(point[0]),
                        y: _round(point[1])
                    }
            },
            getZoom: function() {
                return this._zoom
            },
            setZoom: function(zoom) {
                var that = this;
                that._zoom = truncate(zoom, that._minZoom, that._maxZoom, that._minZoom);
                that._adjustCenter();
                return that
            },
            getScaledZoom: function() {
                return _round((this._scale.length - 1) * _ln(this._zoom) / _ln(this._maxZoom))
            },
            setScaledZoom: function(scaledZoom) {
                return this.setZoom(this._scale[_round(scaledZoom)])
            },
            getZoomScalePartition: function() {
                return this._scale.length - 1
            },
            _setupScaling: function() {
                var that = this,
                    k = _round(TWO_TO_LN2 * _ln(that._maxZoom));
                k = k > 4 ? k : 4;
                var step = _pow(that._maxZoom, 1 / k),
                    zoom = that._minZoom,
                    i = 1;
                that._scale = [zoom];
                for (; i <= k; ++i)
                    that._scale.push(zoom *= step)
            },
            setMaxZoom: function(maxZoom) {
                var that = this;
                that._minZoom = DEFAULT_MIN_ZOOM;
                that._maxZoom = truncate(maxZoom, that._minZoom, _Number.MAX_VALUE, DEFAULT_MAX_ZOOM);
                that._setupScaling();
                if (that._zoom > that._maxZoom)
                    that.setZoom(that._maxZoom);
                return that
            },
            getMinZoom: function() {
                return this._minZoom
            },
            getMaxZoom: function() {
                return this._maxZoom
            },
            getCenter: function() {
                return [this._center[0], this._center[1]]
            },
            setCenter: function(center) {
                var _center = _isArray(center) ? center : null;
                _center = _center || center && (center.lon || center.lat) && [center.lon, center.lat] || [];
                var that = this;
                that._center = [truncate(_center[0], that._minBound[0], that._maxBound[0], that._defaultCenter[0]), truncate(_center[1], that._minBound[1], that._maxBound[1], that._defaultCenter[1])];
                that._adjustCenter();
                return that
            },
            setCenterByPoint: function(coordinates, screenPosition) {
                var that = this,
                    p = that._project(coordinates),
                    q = that._fromScreen(screenPosition);
                return that.setCenter(that._unproject([-q[0] / that._zoom + p[0], -q[1] / that._zoom + p[1]]))
            },
            moveCenter: function(screenDx, screenDy) {
                var that = this,
                    current = that._toScreen(that._toTransformed(that._project(that._center))),
                    center = that._unproject(that._fromTransformed(that._fromScreen([current[0] + screenDx, current[1] + screenDy])));
                return that.setCenter(center)
            },
            getViewport: function() {
                var p1 = this._unproject(this._fromTransformed([-1, -1])),
                    p2 = this._unproject(this._fromTransformed([+1, +1]));
                return [p1[0], p1[1], p2[0], p2[1]]
            },
            setViewport: function(viewport) {
                var that = this;
                if (!_isArray(viewport))
                    return that.setZoom(that._minZoom).setCenter(that._defaultCenter);
                var _viewport = truncateQuad(viewport, that._minBase, that._maxBase),
                    lt = that._project(_viewport.lt),
                    rb = that._project(_viewport.rb),
                    l = _min(lt[0], rb[0]),
                    t = _min(lt[1], rb[1]),
                    r = _max(lt[0], rb[0]),
                    b = _max(lt[1], rb[1]),
                    zoom = 2 / _max(r - l, b - t),
                    xc = selectCenterValue(l, r, -1 - zoom * l, +1 - zoom * r),
                    yc = selectCenterValue(t, b, -1 - zoom * t, +1 - zoom * b);
                return that.setZoom(zoom).setCenter(that._unproject([-xc / zoom, -yc / zoom]))
            },
            getTransform: function() {
                return {
                        translateX: this._dxcenter * this._xradius,
                        translateY: this._dycenter * this._yradius
                    }
            },
            fromScreenPoint: function(x, y) {
                return this._unproject(this._fromTransformed(this._fromScreen([x, y])))
            },
            fromScreenPointStrict: function(x, y) {
                var that = this,
                    p = that._fromTransformed(that._fromScreen([x, y])),
                    q = that._unproject(p);
                return [p[0] >= that._minv[0] && p[0] <= that._maxv[0] ? q[0] : NaN, p[1] >= that._minv[1] && p[1] <= that._maxv[1] ? q[1] : NaN]
            },
            snapCenter: function() {
                this._snappedCenter = this.getCenter();
                return this
            },
            isCenterChanged: function() {
                var center = this.getCenter();
                return !floatsEqual(this._snappedCenter[0], center[0]) || !floatsEqual(this._snappedCenter[1], center[1])
            },
            snapZoom: function() {
                this._snappedZoom = this.getZoom();
                return this
            },
            isZoomChanged: function() {
                return !floatsEqual(this._snappedZoom, this.getZoom())
            }
        };
        DX.viz.map._tests.Projection = Projection;
        DX.viz.map._tests.mercator = mercator;
        DX.viz.map._tests._DEBUG_stubMercator = function(stub) {
            mercator = stub
        };
        DX.viz.map._tests._DEBUG_restoreMercator = function() {
            mercator = DX.viz.map._tests.mercator
        };
        DX.viz.map.Map.prototype._factory.createProjection = function() {
            return new Projection
        }
    })(DevExpress, jQuery);
    /*! Module viz-vectormap, file controlBar.js */
    (function(DX, undefined) {
        var _buildPath = DX.viz.renderers.buildPath,
            _setTimeout = setTimeout,
            _clearTimeout = clearTimeout,
            _round = Math.round,
            _pow = Math.pow,
            _ln = Math.log;
        var _LN2 = Math.LN2;
        var COMMAND_RESET = 'command-reset',
            COMMAND_MOVE_UP = 'command-move-up',
            COMMAND_MOVE_RIGHT = 'command-move-right',
            COMMAND_MOVE_DOWN = 'command-move-down',
            COMMAND_MOVE_LEFT = 'command-move-left',
            COMMAND_ZOOM_IN = 'command-zoom-in',
            COMMAND_ZOOM_OUT = 'command-zoom-out',
            COMMAND_ZOOM_DRAG = 'command-zoom-drag';
        var _DATA_KEY = DX.viz.map.__DATA_KEY,
            EVENT_TARGET_TYPE = 'control-bar';
        var COMMAND_TO_TYPE_MAP = {};
        COMMAND_TO_TYPE_MAP[COMMAND_RESET] = ResetCommand;
        COMMAND_TO_TYPE_MAP[COMMAND_MOVE_UP] = COMMAND_TO_TYPE_MAP[COMMAND_MOVE_RIGHT] = COMMAND_TO_TYPE_MAP[COMMAND_MOVE_DOWN] = COMMAND_TO_TYPE_MAP[COMMAND_MOVE_LEFT] = MoveCommand;
        COMMAND_TO_TYPE_MAP[COMMAND_ZOOM_IN] = COMMAND_TO_TYPE_MAP[COMMAND_ZOOM_OUT] = ZoomCommand;
        COMMAND_TO_TYPE_MAP[COMMAND_ZOOM_DRAG] = ZoomDragCommand;
        var ControlBar = DX.Class.inherit({
                ctor: function(parameters) {
                    var that = this;
                    that._container = parameters.container;
                    that._createElements(parameters.renderer);
                    var context = parameters.context,
                        resetCallback = parameters.resetCallback,
                        beginMoveCallback = parameters.beginMoveCallback,
                        endMoveCallback = parameters.endMoveCallback,
                        moveCallback = parameters.moveCallback,
                        zoomCallback = parameters.zoomCallback;
                    parameters = null;
                    that._reset = function() {
                        resetCallback.call(context)
                    };
                    that._beginMove = function() {
                        beginMoveCallback.call(context)
                    };
                    that._endMove = function() {
                        endMoveCallback.call(context)
                    };
                    that._move = function(dx, dy) {
                        moveCallback.call(context, dx, dy)
                    };
                    that._zoom = function(zoom, x, y) {
                        zoomCallback.call(context, zoom, x, y)
                    };
                    that._dispose = function() {
                        this._reset = this._move = this._zoom = this._dispose = context = resetCallback = moveCallback = zoomCallback = null
                    }
                },
                _createElements: function(renderer) {
                    var that = this;
                    that._root = renderer.createGroup({'class': 'dxm-control-bar'});
                    that._buttonsGroup = renderer.createGroup({'class': 'dxm-control-buttons'}).append(that._root);
                    that._trackersGroup = renderer.createGroup({
                        stroke: 'none',
                        strokeWidth: 0,
                        fill: '#000000',
                        opacity: 0.0001,
                        cursor: 'pointer'
                    }).append(that._root);
                    var options = {
                            bigCircleSize: 58,
                            smallCircleSize: 28,
                            buttonSize: 10,
                            arrowButtonOffset: 20,
                            incdecButtonSize: 11,
                            incButtonOffset: 66,
                            decButtonOffset: 227,
                            sliderLineStartOffset: 88.5,
                            sliderLineEndOffset: 205.5,
                            sliderLength: 20,
                            sliderWidth: 8,
                            trackerGap: 4
                        };
                    that._createButtons(renderer, options);
                    that._createTrackers(renderer, options);
                    that._root.applySettings({
                        translateX: 50.5,
                        translateY: 50.5
                    })
                },
                _createButtons: function(renderer, options) {
                    var group = this._buttonsGroup,
                        size = options.buttonSize / 2,
                        offset1 = options.arrowButtonOffset - size,
                        offset2 = options.arrowButtonOffset,
                        incdecButtonSize = options.incdecButtonSize / 2;
                    renderer.createCircle(0, 0, options.bigCircleSize / 2).append(group);
                    renderer.createCircle(0, 0, size).append(group);
                    renderer.createPath([-size, -offset1, 0, -offset2, size, -offset1]).append(group);
                    renderer.createPath([offset1, -size, offset2, 0, offset1, size]).append(group);
                    renderer.createPath([size, offset1, 0, offset2, -size, offset1]).append(group);
                    renderer.createPath([-offset1, size, -offset2, 0, -offset1, -size]).append(group);
                    renderer.createCircle(0, options.incButtonOffset, options.smallCircleSize / 2).append(group);
                    renderer.createSimplePath({d: _buildPath([-incdecButtonSize, options.incButtonOffset, incdecButtonSize, options.incButtonOffset]) + ' ' + _buildPath([0, options.incButtonOffset - incdecButtonSize, 0, options.incButtonOffset + incdecButtonSize])}).append(group);
                    renderer.createCircle(0, options.decButtonOffset, options.smallCircleSize / 2).append(group);
                    renderer.createSimplePath({d: _buildPath([-incdecButtonSize, options.decButtonOffset, incdecButtonSize, options.decButtonOffset])}).append(group);
                    renderer.createSimplePath({d: _buildPath([0, options.sliderLineStartOffset, 0, options.sliderLineEndOffset])}).append(group);
                    this._zoomDrag = renderer.createRect(-options.sliderLength / 2, options.sliderLineEndOffset - options.sliderWidth / 2, options.sliderLength, options.sliderWidth).append(group);
                    this._sliderLineLength = options.sliderLineEndOffset - options.sliderLineStartOffset
                },
                _createTrackers: function(renderer, options) {
                    var group = this._trackersGroup,
                        size = _round((options.arrowButtonOffset - options.trackerGap) / 2),
                        offset1 = options.arrowButtonOffset - size,
                        offset2 = _round(_pow(options.bigCircleSize * options.bigCircleSize / 4 - size * size, 0.5)),
                        size2 = offset2 - offset1,
                        element;
                    renderer.createRect(-size, -size, size * 2, size * 2).append(group).data(_DATA_KEY, {
                        index: COMMAND_RESET,
                        type: EVENT_TARGET_TYPE
                    });
                    renderer.createRect(-size, -offset2, size * 2, size2).append(group).data(_DATA_KEY, {
                        index: COMMAND_MOVE_UP,
                        type: EVENT_TARGET_TYPE
                    });
                    renderer.createRect(offset1, -size, size2, size * 2).append(group).data(_DATA_KEY, {
                        index: COMMAND_MOVE_RIGHT,
                        type: EVENT_TARGET_TYPE
                    });
                    renderer.createRect(-size, offset1, size * 2, size2).append(group).data(_DATA_KEY, {
                        index: COMMAND_MOVE_DOWN,
                        type: EVENT_TARGET_TYPE
                    });
                    renderer.createRect(-offset2, -size, size2, size * 2).append(group).data(_DATA_KEY, {
                        index: COMMAND_MOVE_LEFT,
                        type: EVENT_TARGET_TYPE
                    });
                    renderer.createCircle(0, options.incButtonOffset, options.smallCircleSize / 2).append(group).data(_DATA_KEY, {
                        index: COMMAND_ZOOM_IN,
                        type: EVENT_TARGET_TYPE
                    });
                    renderer.createCircle(0, options.decButtonOffset, options.smallCircleSize / 2).append(group).data(_DATA_KEY, {
                        index: COMMAND_ZOOM_OUT,
                        type: EVENT_TARGET_TYPE
                    });
                    this._zoomDragCover = renderer.createRect(-options.sliderLength / 2, options.sliderLineEndOffset - options.sliderWidth / 2, options.sliderLength, options.sliderWidth).append(group).data(_DATA_KEY, {
                        index: COMMAND_ZOOM_DRAG,
                        type: EVENT_TARGET_TYPE
                    })
                },
                dispose: function() {
                    var that = this;
                    delete that._container;
                    that._dispose();
                    that._root.clear();
                    delete that._root;
                    delete that._buttonsGroup;
                    delete that._zoomDrag;
                    delete that._zoomDragCover;
                    return that
                },
                setZoomPartition: function(partition) {
                    this._zoomPartition = partition;
                    this._sliderUnitLength = this._sliderLineLength / partition;
                    return this
                },
                setZoom: function(zoom) {
                    this._adjustZoom(zoom);
                    return this
                },
                setOptions: function(options, interactionOptions) {
                    options = options || {};
                    interactionOptions = interactionOptions || {};
                    this._dragAndZoomEnabled = interactionOptions.dragAndZoomEnabled !== undefined ? !!interactionOptions.dragAndZoomEnabled : true;
                    this._enabled = this._dragAndZoomEnabled && (options.enabled !== undefined ? !!options.enabled : true);
                    this._buttonsGroup.applySettings(options.shape);
                    return this
                },
                clean: function() {
                    this._enabled && this._root.detach();
                    return this
                },
                render: function() {
                    this._enabled && this._root.append(this._container);
                    return this
                },
                _adjustZoom: function(zoom) {
                    var that = this;
                    that._zoomFactor = _round(zoom);
                    that._zoomFactor >= 0 || (that._zoomFactor = 0);
                    that._zoomFactor <= that._zoomPartition || (that._zoomFactor = that._zoomPartition);
                    var transform = {translateY: -that._zoomFactor * that._sliderUnitLength};
                    that._zoomDrag.applySettings(transform);
                    that._zoomDragCover.applySettings(transform)
                },
                _applyZoom: function(x, y) {
                    this._zoom(this._zoomFactor, x, y)
                },
                processStart: function(arg) {
                    if (this._dragAndZoomEnabled) {
                        var commandType = COMMAND_TO_TYPE_MAP[arg.data];
                        this._command = new commandType(this, arg)
                    }
                    return this
                },
                processMove: function(arg) {
                    if (this._dragAndZoomEnabled)
                        this._command.update(arg);
                    return this
                },
                processEnd: function(arg) {
                    if (this._dragAndZoomEnabled)
                        this._command.finish(arg);
                    return this
                },
                processZoom: function(arg) {
                    var that = this,
                        zoomFactor;
                    if (that._dragAndZoomEnabled) {
                        if (arg.delta)
                            zoomFactor = arg.delta;
                        else if (arg.ratio)
                            zoomFactor = _ln(arg.ratio) / _LN2;
                        that._adjustZoom(that._zoomFactor + zoomFactor);
                        that._applyZoom(arg.x, arg.y)
                    }
                    return that
                }
            });
        function disposeCommand(command) {
            delete command._owner;
            command.update = function(){};
            command.finish = function(){}
        }
        function ResetCommand(owner, arg) {
            this._owner = owner;
            this._command = arg.data
        }
        ResetCommand.prototype.update = function(arg) {
            arg.data !== this._command && disposeCommand(this)
        };
        ResetCommand.prototype.finish = function() {
            this._owner._reset();
            this._owner._adjustZoom(0);
            disposeCommand(this)
        };
        function MoveCommand(owner, arg) {
            this._command = arg.data;
            var timeout = null,
                interval = 100,
                dx = 0,
                dy = 0;
            switch (this._command) {
                case COMMAND_MOVE_UP:
                    dy = -10;
                    break;
                case COMMAND_MOVE_RIGHT:
                    dx = 10;
                    break;
                case COMMAND_MOVE_DOWN:
                    dy = 10;
                    break;
                case COMMAND_MOVE_LEFT:
                    dx = -10;
                    break
            }
            function callback() {
                owner._move(dx, dy);
                timeout = _setTimeout(callback, interval)
            }
            this._stop = function() {
                _clearTimeout(timeout);
                owner._endMove();
                this._stop = owner = callback = null;
                return this
            };
            arg = null;
            owner._beginMove();
            callback()
        }
        MoveCommand.prototype.update = function(arg) {
            this._command !== arg.data && this.finish()
        };
        MoveCommand.prototype.finish = function() {
            disposeCommand(this._stop())
        };
        function ZoomCommand(owner, arg) {
            this._owner = owner;
            this._command = arg.data;
            var timeout = null,
                interval = 150,
                dzoom = this._command === COMMAND_ZOOM_IN ? 1 : -1;
            function callback() {
                owner._adjustZoom(owner._zoomFactor + dzoom);
                timeout = _setTimeout(callback, interval)
            }
            this._stop = function() {
                _clearTimeout(timeout);
                this._stop = owner = callback = null;
                return this
            };
            arg = null;
            callback()
        }
        ZoomCommand.prototype.update = function(arg) {
            this._command !== arg.data && this.finish()
        };
        ZoomCommand.prototype.finish = function() {
            this._owner._applyZoom();
            disposeCommand(this._stop())
        };
        function ZoomDragCommand(owner, arg) {
            this._owner = owner;
            this._zoomFactor = owner._zoomFactor;
            this._pos = arg.y
        }
        ZoomDragCommand.prototype.update = function(arg) {
            var owner = this._owner;
            owner._adjustZoom(this._zoomFactor + owner._zoomPartition * (this._pos - arg.y) / owner._sliderLineLength)
        };
        ZoomDragCommand.prototype.finish = function() {
            this._owner._applyZoom();
            disposeCommand(this)
        };
        DX.viz.map._tests.ControlBar = ControlBar;
        DX.viz.map.Map.prototype._factory.createControlBar = function(parameters) {
            return new ControlBar(parameters)
        }
    })(DevExpress);
    /*! Module viz-vectormap, file tracker.js */
    (function(DX, $, undefined) {
        var _addNamespace = DX.ui.events.addNamespace,
            _abs = Math.abs,
            _sqrt = Math.sqrt,
            _round = Math.round,
            _max = Math.max,
            _min = Math.min,
            _now = $.now,
            _extend = $.extend;
        var _NAME = DX.viz.map.Map.prototype.NAME,
            _DATA_KEY = DX.viz.map.__DATA_KEY;
        var $doc = $(document);
        var EVENTS = {};
        setupEvents();
        var EVENT_START = 'start',
            EVENT_MOVE = 'move',
            EVENT_END = 'end',
            EVENT_ZOOM = 'zoom',
            EVENT_HOVER_ON = 'hover-on',
            EVENT_HOVER_OFF = 'hover-off',
            EVENT_CLICK = 'click',
            EVENT_FOCUS_ON = 'focus-on',
            EVENT_FOCUS_MOVE = 'focus-move',
            EVENT_FOCUS_OFF = 'focus-off';
        var CLICK_TIME_THRESHOLD = 500,
            CLICK_COORD_THRESHOLD = 5,
            DRAG_COORD_THRESHOLD_MOUSE = 5,
            DRAG_COORD_THRESHOLD_TOUCH = 10,
            FOCUS_ON_DELAY_MOUSE = 300,
            FOCUS_OFF_DELAY_MOUSE = 300,
            FOCUS_ON_DELAY_TOUCH = 300,
            FOCUS_OFF_DELAY_TOUCH = 400,
            FOCUS_COORD_THRESHOLD_MOUSE = 5;
        function Tracker(parameters) {
            this._root = parameters.root;
            this._callbacks = {};
            this._createEventHandlers();
            this._focus = new Focus(this._callbacks)
        }
        _extend(Tracker.prototype, {
            dispose: function() {
                var that = this;
                that._focus.dispose();
                that._root = that._callbacks = that._focus = that._rootClickEvents = that._$docClickEvents = that._rootZoomEvents = that._$docZoomEvents = that._rootHoverEvents = that._$docHoverEvents = that._rootFocusEvents = that._$docFocusEvents = null;
                return that
            },
            _createEventHandlers: function() {
                var that = this;
                that._rootClickEvents = {};
                that._rootClickEvents[EVENTS.start] = function(event) {
                    var isTouch = isTouchEvent(event);
                    if (isTouch && !that._isTouchEnabled)
                        return;
                    event.preventDefault();
                    var coords = getEventCoords(event);
                    that._clickState = {
                        x: coords.x,
                        y: coords.y,
                        time: _now()
                    }
                };
                that._$docClickEvents = {};
                that._$docClickEvents[EVENTS.end] = function(event) {
                    var state = that._clickState;
                    if (!state)
                        return;
                    var isTouch = isTouchEvent(event);
                    if (isTouch && !that._isTouchEnabled)
                        return;
                    if (_now() - state.time <= CLICK_TIME_THRESHOLD) {
                        var coords = getEventCoords(event);
                        if (_abs(coords.x - state.x) <= CLICK_COORD_THRESHOLD && _abs(coords.y - state.y) <= CLICK_COORD_THRESHOLD)
                            that._callbacks[EVENT_CLICK]({
                                data: $(event.target).data(_DATA_KEY) || {},
                                x: coords.x,
                                y: coords.y,
                                $event: event
                            })
                    }
                    that._clickState = null
                };
                that._rootDragEvents = {};
                that._rootDragEvents[EVENTS.start] = function(event) {
                    var isTouch = isTouchEvent(event);
                    if (isTouch && !that._isTouchEnabled)
                        return;
                    var coords = getEventCoords(event);
                    that._dragState = {
                        x: coords.x,
                        y: coords.y,
                        data: $(event.target).data(_DATA_KEY) || {}
                    };
                    if (that._isDragEnabled)
                        that._callbacks[EVENT_START]({
                            data: that._dragState.data,
                            x: coords.x,
                            y: coords.y
                        })
                };
                that._$docDragEvents = {};
                that._$docDragEvents[EVENTS.move] = function(event) {
                    var state = that._dragState;
                    if (!state)
                        return;
                    var isTouch = isTouchEvent(event);
                    if (isTouch && !that._isTouchEnabled)
                        return;
                    var coords = getEventCoords(event),
                        threshold = isTouch ? DRAG_COORD_THRESHOLD_TOUCH : DRAG_COORD_THRESHOLD_MOUSE;
                    if (state.active || _abs(coords.x - state.x) > threshold || _abs(coords.y - state.y) > threshold) {
                        state.x = coords.x;
                        state.y = coords.y;
                        state.active = true;
                        state.data = $(event.target).data(_DATA_KEY) || {};
                        if (that._isDragEnabled)
                            that._callbacks[EVENT_MOVE]({
                                data: state.data,
                                x: coords.x,
                                y: coords.y
                            })
                    }
                };
                that._$docDragEvents[EVENTS.end] = function(event) {
                    var state = that._dragState;
                    if (!state)
                        return;
                    var isTouch = isTouchEvent(event);
                    if (isTouch && !that._isTouchEnabled)
                        return;
                    that._endDragging()
                };
                that._rootZoomEvents = {};
                that._rootZoomEvents[EVENTS.wheel] = function(event) {
                    if (!that._isWheelEnabled)
                        return;
                    event.preventDefault();
                    if (that._zoomState)
                        return;
                    var delta = event.originalEvent.wheelDelta / 120 || event.originalEvent.detail / -3 || 0;
                    if (delta === 0)
                        return;
                    delta = delta > 0 ? _min(_round(delta) || +1, +4) : _max(_round(delta) || -1, -4);
                    var coords = getEventCoords(event);
                    if (that._isZoomEnabled)
                        that._callbacks[EVENT_ZOOM]({
                            delta: delta,
                            x: coords.x,
                            y: coords.y
                        });
                    that._zoomState = setTimeout(function() {
                        that._zoomState = null
                    }, 50)
                };
                that._rootZoomEvents[EVENTS.start] = function(event) {
                    var isTouch = isTouchEvent(event);
                    if (!isTouch || !that._isTouchEnabled)
                        return;
                    var state = that._zoomState = that._zoomState || {};
                    if (state.pointer1 && state.pointer2)
                        return;
                    var coords;
                    if (state.pointer1 === undefined) {
                        state.pointer1 = getPointerId(event) || 0;
                        coords = getMultitouchEventCoords(event, state.pointer1);
                        state.x1 = state.x1_0 = coords.x;
                        state.y1 = state.y1_0 = coords.y
                    }
                    if (state.pointer2 === undefined) {
                        var pointer2 = getPointerId(event) || 1;
                        if (pointer2 !== state.pointer1) {
                            coords = getMultitouchEventCoords(event, pointer2);
                            if (coords) {
                                state.x2 = state.x2_0 = coords.x;
                                state.y2 = state.y2_0 = coords.y;
                                state.pointer2 = pointer2;
                                state.ready = true;
                                that._endDragging()
                            }
                        }
                    }
                };
                that._$docZoomEvents = {};
                that._$docZoomEvents[EVENTS.move] = function(event) {
                    var state = that._zoomState;
                    if (!state)
                        return;
                    var isTouch = isTouchEvent(event);
                    if (!isTouch || !that._isTouchEnabled)
                        return;
                    var coords;
                    if (state.pointer1 !== undefined) {
                        coords = getMultitouchEventCoords(event, state.pointer1);
                        if (coords) {
                            state.x1 = coords.x;
                            state.y1 = coords.y
                        }
                    }
                    if (state.pointer2 !== undefined) {
                        coords = getMultitouchEventCoords(event, state.pointer2);
                        if (coords) {
                            state.x2 = coords.x;
                            state.y2 = coords.y
                        }
                    }
                };
                that._$docZoomEvents[EVENTS.end] = function(event) {
                    var state = that._zoomState;
                    if (!state)
                        return;
                    var isTouch = isTouchEvent(event);
                    if (!isTouch || !that._isTouchEnabled)
                        return;
                    if (state.ready) {
                        var startDistance = getDistance(state.x1_0, state.y1_0, state.x2_0, state.y2_0),
                            currentDistance = getDistance(state.x1, state.y1, state.x2, state.y2);
                        if (that._isZoomEnabled)
                            that._callbacks[EVENT_ZOOM]({
                                ratio: currentDistance / startDistance,
                                x: (state.x1_0 + state.x2_0) / 2,
                                y: (state.y1_0 + state.y2_0) / 2
                            })
                    }
                    that._zoomState = null
                };
                that._rootHoverEvents = {};
                that._rootHoverEvents[EVENTS.over] = function(event) {
                    if (that._hoverTarget === event.target)
                        return;
                    var isTouch = isTouchEvent(event);
                    if (isTouch)
                        return;
                    var data = $(event.target).data(_DATA_KEY);
                    if (!data)
                        return;
                    that._hoverTarget && that._endHovering();
                    that._hoverTarget = event.target;
                    that._hoverState = {data: data};
                    that._callbacks[EVENT_HOVER_ON]({data: data})
                };
                that._$docHoverEvents = {};
                that._$docHoverEvents[EVENTS.out] = function(event) {
                    var state = that._hoverState;
                    if (!state)
                        return;
                    var isTouch = isTouchEvent(event);
                    if (isTouch)
                        return;
                    var data = $(event.target).data(_DATA_KEY);
                    if (!data)
                        return;
                    that._endHovering()
                };
                that._rootFocusEvents = {};
                that._rootFocusEvents[EVENTS.start] = function(event) {
                    var isTouch = isTouchEvent(event);
                    if (!isTouch || !that._isTouchEnabled)
                        return;
                    var data = $(event.target).data(_DATA_KEY);
                    if (!data)
                        return;
                    that._focus.turnOff(FOCUS_OFF_DELAY_TOUCH);
                    that._focus.turnOn(event.target, data, getEventCoords(event), FOCUS_ON_DELAY_TOUCH);
                    that._skip$docEvent = true
                };
                that._rootFocusEvents[EVENTS.over] = function(event) {
                    if (that._focusTarget === event.target)
                        return;
                    that._focusTarget = event.target;
                    var isTouch = isTouchEvent(event);
                    if (isTouch)
                        return;
                    var data = $(event.target).data(_DATA_KEY);
                    if (!data)
                        return;
                    if (that._focusTarget)
                        that._focus.turnOff(FOCUS_OFF_DELAY_MOUSE);
                    var coords = getEventCoords(event);
                    if (that._focus.active)
                        that._focus.move(event.target, data, coords);
                    else
                        that._focus.turnOn(event.target, data, coords, FOCUS_ON_DELAY_MOUSE)
                };
                that._$docFocusEvents = {};
                that._$docFocusEvents[EVENTS.start] = function(event) {
                    that._focusTarget = event.target;
                    var isTouch = isTouchEvent(event);
                    if (!isTouch || !that._isTouchEnabled)
                        return;
                    if (!that._skip$docEvent)
                        that._focus.turnOff(FOCUS_OFF_DELAY_TOUCH);
                    that._skip$docEvent = null
                };
                that._$docFocusEvents[EVENTS.move] = function(event) {
                    if (that._focus.disabled)
                        return;
                    if (that._focusTarget !== event.target)
                        return;
                    var isTouch = isTouchEvent(event);
                    if (isTouch && !that._isTouchEnabled)
                        return;
                    var data = $(event.target).data(_DATA_KEY);
                    if (!data)
                        return;
                    var coords = getEventCoords(event);
                    if (isTouch) {
                        if (that._dragState && that._dragState.active || that._zoomState && that._zoomState.ready)
                            that._focus.cancel()
                    }
                    else if (that._focus.active)
                        if (that._dragState && that._dragState.active) {
                            that._focus.cancel();
                            that._focus.turnOn(event.target, data, coords, FOCUS_ON_DELAY_MOUSE * 4)
                        }
                        else
                            that._focus.move(event.target, data, coords);
                    else if (_abs(coords.x - that._focus.x) > FOCUS_COORD_THRESHOLD_MOUSE || _abs(coords.y - that._focus.y) > FOCUS_COORD_THRESHOLD_MOUSE)
                        that._focus.turnOn(event.target, data, coords, FOCUS_ON_DELAY_MOUSE)
                };
                that._$docFocusEvents[EVENTS.end] = function(event) {
                    if (that._focus.disabled)
                        return;
                    var isTouch = isTouchEvent(event);
                    if (!isTouch || !that._isTouchEnabled)
                        return;
                    that._focusTarget = null;
                    if (!that._focus.active)
                        that._focus.turnOff(FOCUS_OFF_DELAY_TOUCH);
                    else if (that._focus.changing)
                        that._focus.cancel()
                };
                that._$docFocusEvents[EVENTS.out] = function(event) {
                    if (that._focus.disabled)
                        return;
                    var isTouch = isTouchEvent(event);
                    if (isTouch)
                        return;
                    that._focusTarget = null;
                    var data = $(event.target).data(_DATA_KEY);
                    if (!data)
                        return;
                    that._focus.turnOff(FOCUS_OFF_DELAY_MOUSE)
                }
            },
            _endDragging: function() {
                var that = this,
                    state = that._dragState;
                that._dragState = null;
                if (state && that._isDragEnabled)
                    that._callbacks[EVENT_END]({
                        data: state.data,
                        x: state.x,
                        y: state.y
                    })
            },
            _endHovering: function() {
                var that = this,
                    state = that._hoverState;
                that._hoverState = that._hoverTarget = null;
                if (state)
                    that._callbacks[EVENT_HOVER_OFF]({data: state.data})
            },
            reset: function() {
                var that = this;
                that._clickState = null;
                that._endDragging();
                that._endHovering();
                that._focus.cancel();
                that._focusTarget = null;
                return that
            },
            setCallbacks: function(callbacks) {
                _extend(this._callbacks, callbacks);
                return this
            },
            setOptions: function(options) {
                this._isTouchEnabled = options.touchEnabled === undefined || !!options.touchEnabled;
                this._isWheelEnabled = options.wheelEnabled === undefined || !!options.wheelEnabled;
                this._isDragEnabled = options.dragAndZoomEnabled === undefined || !!options.dragAndZoomEnabled;
                this._isZoomEnabled = options.dragAndZoomEnabled === undefined || !!options.dragAndZoomEnabled;
                return this
            },
            clean: function() {
                var that = this;
                if (that._isTouchEnabled) {
                    that._root.applySettings({style: {
                            'touch-action': '',
                            '-ms-touch-action': '',
                            '-webkit-user-select': ''
                        }});
                    that._root.off(_addNamespace('MSHoldVisual', _NAME)).off(_addNamespace('contextmenu', _NAME))
                }
                that._detachEventHandlers();
                that.reset();
                return that
            },
            render: function() {
                var that = this;
                if (that._isTouchEnabled) {
                    that._root.applySettings({style: {
                            'touch-action': 'none',
                            '-ms-touch-action': 'none',
                            '-webkit-user-select': 'none'
                        }});
                    that._root.on(_addNamespace('MSHoldVisual', _NAME), function(event) {
                        event.preventDefault()
                    }).on(_addNamespace('contextmenu', _NAME), function(event) {
                        isTouchEvent(event) && event.preventDefault()
                    })
                }
                that._attachEventHandlers();
                return that
            },
            _attachEventHandlers: function() {
                var that = this;
                that._root.on(that._rootClickEvents).on(that._rootDragEvents).on(that._rootZoomEvents).on(that._rootHoverEvents).on(that._rootFocusEvents);
                $doc.on(that._$docClickEvents).on(that._$docDragEvents).on(that._$docZoomEvents).on(that._$docHoverEvents).on(that._$docFocusEvents)
            },
            _detachEventHandlers: function() {
                var that = this;
                that._root.off(that._rootClickEvents).off(that._rootDragEvents).off(that._rootZoomEvents).off(that._rootHoverEvents).off(that._rootFocusEvents);
                $doc.off(that._$docClickEvents).off(that._$docDragEvents).off(that._$docZoomEvents).off(that._$docHoverEvents).off(that._$docFocusEvents)
            }
        });
        function Focus(callbacks) {
            this._callbacks = callbacks;
            this.disabled = true
        }
        _extend(Focus.prototype, {
            dispose: function() {
                var that = this;
                clearTimeout(that._onTimer);
                clearTimeout(that._offTimer);
                that._callbacks = that._onTimer = that._offTimer = that.active = that._data = null
            },
            _createCallback: function(target, data, coords) {
                var that = this;
                return function() {
                        if (that.active === target) {
                            that._callbacks[EVENT_FOCUS_MOVE]({
                                data: that._data,
                                x: coords.x,
                                y: coords.y
                            });
                            onCheck(true)
                        }
                        else
                            that._callbacks[EVENT_FOCUS_ON]({
                                data: data,
                                x: coords.x,
                                y: coords.y
                            }, onCheck)
                    };
                function onCheck(result) {
                    that.changing = null;
                    that.disabled = !result;
                    if (result) {
                        that._data = data;
                        that.active = target;
                        clearTimeout(that._offTimer);
                        that._offTimer = null
                    }
                }
            },
            turnOn: function(target, data, coords, timeout) {
                var that = this;
                that.disabled = false;
                that.x = coords.x;
                that.y = coords.y;
                clearTimeout(that._onTimer);
                that.changing = true;
                that._onTimer = setTimeout(that._createCallback(target, data, coords), timeout)
            },
            move: function(target, data, coords) {
                this.x = coords.x;
                this.y = coords.y;
                this._createCallback(target, data, coords)()
            },
            turnOff: function(timeout) {
                var that = this;
                if (that.active)
                    that._offTimer = that._offTimer || setTimeout(function() {
                        that._offTimer = null;
                        that._callbacks[EVENT_FOCUS_OFF]({data: that._data});
                        that._data = that.active = null;
                        that.disabled = true
                    }, timeout);
                else {
                    clearTimeout(that._onTimer);
                    that._onTimer = null;
                    that.disabled = true
                }
            },
            cancel: function() {
                var that = this;
                if (that.active)
                    that._callbacks[EVENT_FOCUS_OFF]({data: that._data});
                clearTimeout(that._onTimer);
                clearTimeout(that._offTimer);
                that._data = that.active = that._onTimer = that._offTimer = null;
                that.disabled = true
            }
        });
        DX.viz.map._tests.Tracker = Tracker;
        DX.viz.map._tests._DEBUG_forceEventMode = function(mode) {
            setupEvents(mode)
        };
        DX.viz.map._tests.Focus = Focus;
        DX.viz.map._tests._DEBUG_stubFocusType = function(focusType) {
            Focus = focusType
        };
        DX.viz.map._tests._DEBUG_restoreFocusType = function() {
            Focus = DX.viz.map._tests.Focus
        };
        DX.viz.map.Map.prototype._factory.createTracker = function(parameters) {
            return new Tracker(parameters)
        };
        function getDistance(x1, y1, x2, y2) {
            return _sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
        }
        function isTouchEvent(event) {
            var type = event.originalEvent.type,
                pointerType = event.originalEvent.pointerType;
            return /^touch/.test(type) || /^MSPointer/.test(type) && pointerType !== 4 || /^pointer/.test(type) && pointerType !== 'mouse'
        }
        function selectItem(flags, items) {
            var i = 0,
                ii = flags.length,
                item;
            for (; i < ii; ++i)
                if (flags[i]) {
                    item = items[i];
                    break
                }
            return _addNamespace(item || items[i], _NAME)
        }
        function setupEvents() {
            var flags = [navigator.pointerEnabled, navigator.msPointerEnabled, 'ontouchstart' in window];
            if (arguments.length)
                flags = [arguments[0] === 'pointer', arguments[0] === 'MSPointer', arguments[0] === 'touch'];
            EVENTS = {
                start: selectItem(flags, ['pointerdown', 'MSPointerDown', 'touchstart mousedown', 'mousedown']),
                move: selectItem(flags, ['pointermove', 'MSPointerMove', 'touchmove mousemove', 'mousemove']),
                end: selectItem(flags, ['pointerup', 'MSPointerUp', 'touchend mouseup', 'mouseup']),
                over: selectItem(flags, ['pointerover', 'MSPointerOver', 'mouseover', 'mouseover']),
                out: selectItem(flags, ['pointerout', 'MSPointerOut', 'mouseout', 'mouseout']),
                wheel: selectItem([], ['mousewheel DOMMouseScroll'])
            }
        }
        function getEventCoords(event) {
            var originalEvent = event.originalEvent,
                touch = originalEvent.touches && originalEvent.touches[0] || {};
            return {
                    x: touch.pageX || originalEvent.pageX || event.pageX,
                    y: touch.pageY || originalEvent.pageY || event.pageY
                }
        }
        function getPointerId(event) {
            return event.originalEvent.pointerId
        }
        function getMultitouchEventCoords(event, pointerId) {
            var originalEvent = event.originalEvent;
            if (originalEvent.pointerId !== undefined)
                originalEvent = originalEvent.pointerId === pointerId ? originalEvent : null;
            else
                originalEvent = originalEvent.touches[pointerId];
            return originalEvent ? {
                    x: originalEvent.pageX || event.pageX,
                    y: originalEvent.pageY || event.pageY
                } : null
        }
    })(DevExpress, jQuery);
    /*! Module viz-vectormap, file themeManager.js */
    (function(DX, $, undefined) {
        var _Number = Number,
            _extend = $.extend,
            _each = $.each;
        var ThemeManager = DX.viz.core.BaseThemeManager.inherit({
                _themeSection: 'map',
                _initializeTheme: function() {
                    var that = this;
                    that._initializeFont(that._theme.marker.font);
                    that._initializeFont(that._theme.tooltip.font);
                    that._initializeFont(that._theme.legend.font);
                    that._initializeFont(that._theme.loadingIndicator.font)
                },
                dispose: function() {
                    var that = this;
                    that.callBase.apply(that, arguments);
                    that._areasPalette = that._markersPalette = null;
                    return that
                },
                getBackgroundSettings: function(options) {
                    var theme = this._theme.background,
                        merged = _extend({}, theme, options);
                    return {
                            strokeWidth: merged.borderWidth,
                            stroke: merged.borderColor,
                            fill: merged.color
                        }
                },
                getCommonAreaSettings: function(options) {
                    var settings = _extend({}, this._theme.area, options);
                    this._areasPalette = new DX.viz.core.GradientPalette(settings.palette, settings.paletteSize);
                    this._DEBUG_areasPalette = this._areasPalette;
                    return settings
                },
                getAreaSettings: function(commonSettings, options) {
                    options = options || {};
                    var settings = _extend({}, commonSettings, options);
                    settings.borderWidth = _Number(settings.borderWidth) || 0;
                    settings.borderColor = settings.borderColor || null;
                    if (options.color === undefined && options.paletteIndex >= 0)
                        settings.color = this._areasPalette.getColor(options.paletteIndex);
                    settings.color = settings.color || null;
                    settings.hoveredBorderWidth = _Number(settings.hoveredBorderWidth) || settings.borderWidth;
                    settings.hoveredBorderColor = settings.hoveredBorderColor || settings.borderColor;
                    settings.hoveredColor = settings.hoveredColor || settings.color;
                    settings.selectedBorderWidth = _Number(settings.selectedBorderWidth) || settings.borderWidth;
                    settings.selectedBorderColor = settings.selectedBorderColor || settings.borderColor;
                    settings.selectedColor = settings.selectedColor || settings.color;
                    return settings
                },
                getCommonMarkerSettings: function(options) {
                    options = options || {};
                    var theme = this._theme.marker,
                        allSettings = {};
                    _each(theme, function(name) {
                        if (name[0] === '_') {
                            var partialTheme = theme[name] || {},
                                partialOptions = options[name] || {},
                                settings = _extend({}, theme, partialTheme, options, partialOptions);
                            settings.font = _extend({}, theme.font, partialTheme.font, options.font, partialOptions.font);
                            allSettings[name.substr(1)] = settings
                        }
                    });
                    this._markersPalette = new DX.viz.core.Palette(options.palette || theme.palette, {
                        stepHighlight: 50,
                        theme: this.themeName()
                    });
                    this._DEBUG_markersPalette = this._markersPalette;
                    return allSettings
                },
                getMarkerSettings: function(commonSettings, options, type) {
                    options = options || {};
                    var common = commonSettings[type],
                        settings = _extend({}, common, options);
                    settings.font = _extend({}, common.font, options.font);
                    settings.borderWidth = _Number(settings.borderWidth) || 0;
                    settings.borderColor = settings.borderColor || null;
                    settings.color = settings.color || null;
                    settings.opacity = settings.opacity || null;
                    settings.hoveredBorderWidth = _Number(settings.hoveredBorderWidth) || settings.borderWidth;
                    settings.hoveredBorderColor = settings.hoveredBorderColor || settings.borderColor;
                    settings.hoveredColor = settings.hoveredColor || settings.color;
                    settings.hoveredOpacity = settings.hoveredOpacity || settings.opacity;
                    settings.selectedBorderWidth = _Number(settings.selectedBorderWidth) || settings.borderWidth;
                    settings.selectedBorderColor = settings.selectedBorderColor || settings.borderColor;
                    settings.selectedColor = settings.selectedColor || settings.color;
                    settings.selectedOpacity = settings.selectedOpacity || settings.opacity;
                    return settings
                },
                getMarkerColors: function(count) {
                    var i = 0,
                        colors = [];
                    for (; i < count; ++i)
                        colors.push(this._markersPalette.getNextColor());
                    this._markersPalette.reset();
                    return colors
                },
                getControlBarSettings: function(options) {
                    var theme = this._theme.controlBar,
                        merged = _extend({}, theme, options);
                    return _extend({}, options, {shape: {
                                strokeWidth: merged.borderWidth,
                                stroke: merged.borderColor,
                                fill: merged.color
                            }})
                },
                getLoadIndicatorSettings: function(options) {
                    var theme = this._theme.loadingIndicator;
                    return _extend(true, {}, theme, options)
                },
                getTooltipSettings: function(options) {
                    var theme = this._theme.tooltip,
                        merged = _extend({}, theme, options),
                        borderOptions = _extend({}, theme.border, options && options.border, options && !options.border && {color: options.borderColor});
                    return _extend({}, options, {
                            color: merged.color,
                            border: borderOptions,
                            text: {
                                strokeWidth: 0,
                                stroke: 'none',
                                fill: 'none',
                                font: _extend({}, theme.font, merged.font),
                                'class': 'dxm-tooltip-text'
                            },
                            arrowLength: merged.arrowLength,
                            paddingLeftRight: merged.paddingLeftRight,
                            paddingTopBottom: merged.paddingTopBottom,
                            opacity: merged.opacity,
                            shadow: _extend({}, theme.shadow, merged.shadow)
                        })
                },
                getLegendSettings: function(options) {
                    return _extend(true, {}, this._theme.legend, options)
                },
                getLegendItemSettings: function(item) {
                    var color = item.color;
                    if (color === undefined && item.paletteIndex >= 0)
                        color = this._areasPalette.getColor(item.paletteIndex);
                    return {
                            text: item.text,
                            color: color
                        }
                },
                patchRtlSettings: function(rtlEnabledOption) {
                    var theme = this._theme;
                    if (rtlEnabledOption || theme.rtlEnabled && rtlEnabledOption !== false)
                        $.extend(true, theme, theme._rtl)
                }
            });
        DX.viz.map._tests.ThemeManager = ThemeManager;
        DX.viz.map.Map.prototype._factory.createThemeManager = function() {
            return new ThemeManager
        }
    })(DevExpress, jQuery);
    /*! Module viz-vectormap, file mapItemsManager.js */
    (function(DX, $, undefined) {
        var _String = String,
            _isString = DX.utils.isString,
            _isArray = DX.utils.isArray,
            _isFunction = DX.utils.isFunction,
            _extend = $.extend,
            _each = $.each,
            _map = $.map;
        var SELECTION_MODE_NONE = 'none',
            SELECTION_MODE_SINGLE = 'single',
            SELECTION_MODE_MULTIPLE = 'multiple';
        var MapItemsManager = DX.Class.inherit({
                _rootClass: null,
                ctor: function(parameters) {
                    var that = this;
                    that._container = parameters.container;
                    that._renderer = parameters.renderer;
                    that._projection = parameters.projection;
                    that._themeManager = parameters.themeManager;
                    that._tracker = parameters.tracker;
                    that._ready = parameters.ready;
                    that._root = that._renderer.createGroup({'class': that._rootClass});
                    that._items = [];
                    that._context = {
                        renderer: that._renderer,
                        root: that._root,
                        projection: that._projection,
                        selectItem: function(index, state, noCallback) {
                            that.selectItem(index, state, noCallback)
                        }
                    }
                },
                dispose: function() {
                    var that = this;
                    that._container = that._renderer = that._projection = that._themeManager = that._tracker = that._ready = that._root = that._source = that._context = null;
                    return that
                },
                clean: function() {
                    var that = this;
                    that._rendered = false;
                    that._root.detach();
                    that._customizeCallback = that._clickCallback = that._selectionChangedCallback = null;
                    that._destroyItems();
                    return that
                },
                render: function(options) {
                    options = options || {};
                    var that = this;
                    that._rendered = true;
                    that._customizeCallback = _isFunction(options.customize) ? options.customize : null;
                    that._clickCallback = _isFunction(options.click) ? options.click : null;
                    that._selectionChangedCallback = _isFunction(options.selectionChanged) ? options.selectionChanged : null;
                    that._hoverEnabled = 'hoverEnabled' in options ? !!options.hoverEnabled : true;
                    var selectionMode = _String(options.selectionMode).toLowerCase();
                    that._selectionMode = selectionMode === SELECTION_MODE_NONE || selectionMode === SELECTION_MODE_SINGLE || selectionMode === SELECTION_MODE_MULTIPLE ? selectionMode : SELECTION_MODE_SINGLE;
                    that._root.append(that._container);
                    if (that._source !== null)
                        that._createItems();
                    return that
                },
                _destroyItems: function() {
                    var that = this;
                    that._root.clear();
                    _each(that._items, function(_, item) {
                        item.clean().dispose()
                    });
                    that._items = [];
                    that._selectedItems = null
                },
                _getItemSettings: null,
                _createItem: null,
                _isItemSelected: null,
                _arrangeItems: null,
                _createItems: function() {
                    var that = this;
                    that._selectedItems = that._selectionMode === SELECTION_MODE_MULTIPLE ? {} : null;
                    var selectedList = [];
                    _each(_isArray(that._source) ? that._source : [], function(i, dataItem) {
                        dataItem = dataItem || {};
                        var settings = that._customizeCallback && that._customizeCallback.call(dataItem, dataItem) || {};
                        var source = {
                                item: dataItem,
                                coords: that._getItemCoordinates(dataItem),
                                attrs: that._getItemAttributes(dataItem)
                            };
                        settings = that._getItemSettings(source, settings);
                        var item = that._createItem(settings);
                        item.init(that._context, source, i).render(settings).locate();
                        that._items.push(item);
                        if (that._isItemSelected(source, settings))
                            selectedList.push(i)
                    });
                    if (that._selectionMode !== SELECTION_MODE_NONE && selectedList.length > 0) {
                        if (that._selectionMode === SELECTION_MODE_SINGLE)
                            selectedList = [selectedList[selectedList.length - 1]];
                        _each(selectedList, function(_, index) {
                            that.selectItem(index, true, true)
                        })
                    }
                    that._arrangeItems();
                    that._ready && that._ready()
                },
                _processSource: null,
                setData: function(data) {
                    var that = this;
                    that._source = null;
                    if (_isString(data))
                        $.getJSON(data).done(updateSource).fail(function(_0, _1, error) {
                            updateSource(null)
                        });
                    else
                        updateSource(data);
                    return that;
                    function updateSource(source) {
                        that._source = that._processSource(source) || 0;
                        if (that._rendered) {
                            that._tracker.reset();
                            that._destroyItems();
                            that._createItems()
                        }
                    }
                },
                transform: function(transform) {
                    this._root.applySettings(transform);
                    return this
                },
                redraw: function() {
                    _each(this._items, function(_, item) {
                        item.locate()
                    });
                    return this
                },
                hoverItem: function(index, state) {
                    if (this._hoverEnabled)
                        this._items[index].setHovered(!!state);
                    return this
                },
                _raiseSelectionChanged: function(item) {
                    var that = this;
                    if (that._selectionChangedCallback)
                        setTimeout(function() {
                            that._selectionChangedCallback && that._selectionChangedCallback.call(item.proxy, item.proxy)
                        }, 0)
                },
                selectItem: function(index, state, noCallback) {
                    var that = this;
                    if (that._selectionMode === SELECTION_MODE_NONE)
                        return that;
                    var item = that._items[index],
                        previous = item.selected;
                    item.setSelected(!!state);
                    if (item.selected === previous)
                        return that;
                    if (!noCallback)
                        that._raiseSelectionChanged(item);
                    if (item.selected && that._selectionMode === SELECTION_MODE_SINGLE && that._selectedItems) {
                        that._selectedItems.setSelected(false);
                        if (!noCallback)
                            that._raiseSelectionChanged(that._selectedItems);
                        that._selectedItems = null
                    }
                    if (that._selectionMode === SELECTION_MODE_SINGLE)
                        that._selectedItems = item.selected ? item : null;
                    else if (item.selected)
                        that._selectedItems[index] = item;
                    else
                        delete that._selectedItems[index];
                    return that
                },
                clearSelection: function() {
                    var that = this;
                    if (that._selectionMode === SELECTION_MODE_NONE)
                        return that;
                    if (that._selectionMode === SELECTION_MODE_SINGLE) {
                        if (that._selectedItems) {
                            that._selectedItems.setSelected(false);
                            that._raiseSelectionChanged(that._selectedItems);
                            that._selectedItems = null
                        }
                    }
                    else
                        _each(that._selectedItems, function(i, item) {
                            item.setSelected(false);
                            that._raiseSelectionChanged(item);
                            delete that._selectedItems[i]
                        });
                    return that
                },
                raiseClick: function(index, $event) {
                    var that = this,
                        item = that._items[index];
                    if (that._clickCallback)
                        setTimeout(function() {
                            that._clickCallback && that._clickCallback.call(item.proxy, item.proxy, $event)
                        }, 0);
                    return that
                },
                getProxyItems: function() {
                    return _map(this._items, function(item) {
                            return item.proxy
                        })
                },
                getProxyItem: function(index) {
                    return this._items[index].proxy
                }
            });
        DX.viz.map._internal.mapItemBehavior = {
            init: function(ctx, src, index) {
                var that = this;
                that._ctx = ctx;
                that._src = src;
                that._coords = that._project(ctx.projection, src.coords);
                that._data = {
                    index: index,
                    type: that._type
                };
                that.hovered = that.selected = false;
                that.proxy = createProxy(that, src.attrs, ctx.selectItem);
                that.proxy.type = that._type;
                that._init();
                return that
            },
            dispose: function() {
                disposeItem(this.proxy);
                disposeItem(this);
                return this
            },
            locate: function() {
                var that = this;
                that._locate(that._transform(that._ctx.projection, that._coords));
                return that
            },
            clean: function() {
                this._root.detach();
                return this
            },
            render: function(settings) {
                var that = this;
                that._root = that._createRoot().append(that._ctx.root);
                that._render(settings);
                return that
            },
            setHovered: function(state) {
                var that = this;
                that.hovered = !!state;
                that._onHover();
                if (!that.selected)
                    if (that.hovered)
                        that._setHoveredState();
                    else
                        that._setDefaultState();
                return that
            },
            setSelected: function(state) {
                var that = this;
                that.selected = !!state;
                if (that.selected)
                    that._setSelectedState();
                else
                    that.setHovered(that.hovered);
                return that
            }
        };
        function createProxy(item, attributes, selectItem) {
            attributes = attributes || {};
            return {
                    attribute: function(name) {
                        return name !== undefined ? attributes[name] : _extend({}, attributes)
                    },
                    selected: function(state, _noEvent) {
                        if (state !== undefined) {
                            if (item.selected !== !!state)
                                selectItem(item._data.index, !!state, _noEvent);
                            return this
                        }
                        else
                            return item.selected
                    }
                }
        }
        function disposeItem(item) {
            _each(item, function(name) {
                item[name] = null
            })
        }
        DX.viz.map._tests.MapItemsManager = MapItemsManager;
        DX.viz.map.Map.prototype._factory.MapItemsManager = MapItemsManager
    })(DevExpress, jQuery);
    /*! Module viz-vectormap, file areasManager.js */
    (function(DX, $, undefined) {
        var _DATA_KEY = DX.viz.map.__DATA_KEY;
        var AreasManager = DX.viz.map.Map.prototype._factory.MapItemsManager.inherit({
                _rootClass: 'dxm-areas',
                _processSource: function(source) {
                    var isGeoJson = source && source.type === 'FeatureCollection';
                    this._getItemCoordinates = isGeoJson ? getCoordinatesGeoJson : getCoordinatesDefault;
                    this._getItemAttributes = isGeoJson ? getAttributesGeoJson : getAttributesDefault;
                    return isGeoJson ? source.features : source
                },
                clean: function() {
                    this._commonSettings = null;
                    return this.callBase.apply(this, arguments)
                },
                render: function(options) {
                    this._commonSettings = this._themeManager.getCommonAreaSettings(options || {});
                    return this.callBase.apply(this, arguments)
                },
                _getItemSettings: function(_, options) {
                    return this._themeManager.getAreaSettings(this._commonSettings, options)
                },
                _createItem: function() {
                    return new Area
                },
                _isItemSelected: function(source, settings) {
                    return source.attrs.isSelected || settings.isSelected
                },
                _arrangeItems: $.noop
            });
        function getCoordinatesDefault(dataItem) {
            return dataItem.coordinates
        }
        function getCoordinatesGeoJson(dataItem) {
            var coordinates;
            if (dataItem.geometry) {
                var type = dataItem.geometry.type;
                coordinates = dataItem.geometry.coordinates;
                if (coordinates && (type === 'Polygon' || type === 'MultiPolygon'))
                    type === 'MultiPolygon' && (coordinates = [].concat.apply([], coordinates));
                else
                    coordinates = undefined
            }
            return coordinates
        }
        function getAttributesDefault(dataItem) {
            return dataItem.attributes
        }
        function getAttributesGeoJson(dataItem) {
            return dataItem.properties
        }
        function Area(){}
        $.extend(Area.prototype, DX.viz.map._internal.mapItemBehavior, {
            _type: 'area',
            _project: function(projection, coords) {
                return projection.projectArea(coords)
            },
            _init: $.noop,
            _createRoot: function() {
                return this._ctx.renderer.createSimplePath()
            },
            _render: function(settings) {
                var that = this;
                that._styles = {
                    normal: {
                        'class': 'dxm-area',
                        stroke: settings.borderColor,
                        strokeWidth: settings.borderWidth,
                        fill: settings.color
                    },
                    hovered: {
                        'class': 'dxm-area dxm-area-hovered',
                        stroke: settings.hoveredBorderColor,
                        strokeWidth: settings.hoveredBorderWidth,
                        fill: settings.hoveredColor
                    },
                    selected: {
                        'class': 'dxm-area dxm-area-selected',
                        stroke: settings.selectedBorderColor,
                        strokeWidth: settings.selectedBorderWidth,
                        fill: settings.selectedColor
                    }
                };
                that._root.applySettings(that._styles.normal).data(_DATA_KEY, that._data);
                return that
            },
            _transform: function(projection, coords) {
                return projection.getAreaCoordinates(coords)
            },
            _locate: function(coords) {
                this._root.applySettings({d: coords})
            },
            _onHover: $.noop,
            _setDefaultState: function() {
                this._root.applySettings(this._styles.normal).toBackground()
            },
            _setHoveredState: function() {
                this._root.applySettings(this._styles.hovered).toForeground()
            },
            _setSelectedState: function() {
                this._root.applySettings(this._styles.selected).toForeground()
            }
        });
        DX.viz.map._tests.AreasManager = AreasManager;
        DX.viz.map._tests.Area = Area;
        DX.viz.map.Map.prototype._factory.createAreasManager = function(parameters) {
            return new AreasManager(parameters)
        }
    })(DevExpress, jQuery);
    /*! Module viz-vectormap, file markersManager.js */
    (function(DX, $, undefined) {
        var _Number = Number,
            _String = String,
            _isFinite = isFinite,
            _round = Math.round,
            _max = Math.max,
            _min = Math.min,
            _extend = $.extend,
            _isArray = DX.utils.isArray,
            _processCircleSettings = DX.viz.renderers.processCircleSettings;
        var CLASS_DEFAULT = 'dxm-marker',
            CLASS_HOVERED = 'dxm-marker dxm-marker-hovered',
            CLASS_SELECTED = 'dxm-marker dxm-marker-selected',
            TRACKER_SETTINGS = {
                stroke: 'none',
                strokeWidth: 0,
                fill: '#000000',
                opacity: 0.0001
            };
        var _DATA_KEY = DX.viz.map.__DATA_KEY;
        var DEFAULT_MARKER_TYPE = 'dot',
            MARKER_TYPES = {};
        var MarkersManager = DX.viz.map.Map.prototype._factory.MapItemsManager.inherit({
                _rootClass: 'dxm-markers',
                ctor: function() {
                    var that = this;
                    that.callBase.apply(that, arguments);
                    that._context.getColors = function(count) {
                        return that._themeManager.getMarkerColors(count)
                    };
                    that._filter = that._renderer.createFilter('shadow').applySettings({
                        x: '-40%',
                        y: '-40%',
                        width: '180%',
                        height: '200%',
                        color: '#000000',
                        opacity: 0.2,
                        dx: 0,
                        dy: 1,
                        blur: 1
                    }).append()
                },
                dispose: function() {
                    this._filter.dispose();
                    this._filter = null;
                    return this.callBase.apply(this, arguments)
                },
                _getItemCoordinates: function(dataItem) {
                    return dataItem.coordinates
                },
                _getItemAttributes: function(dataItem) {
                    return dataItem.attributes
                },
                _processSource: function(source) {
                    return source
                },
                clean: function() {
                    var that = this;
                    that._commonSettings = null;
                    return that.callBase.apply(that, arguments)
                },
                render: function(options) {
                    var that = this;
                    that._commonSettings = that._themeManager.getCommonMarkerSettings(options);
                    that._commonSettings._filter = that._filter.ref;
                    that._commonType = parseMarkerType(options && options.type);
                    return that.callBase.apply(that, arguments)
                },
                _arrangeBubbles: function() {
                    var markers = this._items,
                        bubbles = [],
                        i,
                        ii = markers.length,
                        marker,
                        values = [];
                    for (i = 0; i < ii; ++i) {
                        marker = markers[i];
                        if (marker.type === 'bubble') {
                            bubbles.push(marker);
                            if (marker.value !== null)
                                values.push(marker.value)
                        }
                    }
                    var minValue = _min.apply(null, values),
                        maxValue = _max.apply(null, values),
                        deltaValue = maxValue - minValue || 1;
                    for (i = 0, ii = bubbles.length; i < ii; ++i) {
                        marker = bubbles[i];
                        marker.setSize(marker.value !== null ? (marker.value - minValue) / deltaValue : 0)
                    }
                },
                _getItemSettings: function(source, options) {
                    var type = parseMarkerType(source.item.type, this._commonType),
                        style = _extend(source.item.style, options);
                    style = this._themeManager.getMarkerSettings(this._commonSettings, style, type);
                    _extend(source.item, {text: source.item.text || style.text});
                    style._type = type;
                    return style
                },
                _createItem: function(settings) {
                    return new MARKER_TYPES[settings._type]
                },
                _isItemSelected: function(source, settings) {
                    return source.item.isSelected || settings.isSelected
                },
                _arrangeItems: function() {
                    this._arrangeBubbles()
                },
                addMarker: function(dataItem) {
                    var that = this,
                        index = that._items.length,
                        marker = that._createItem(dataItem, index);
                    that._items.push(marker);
                    if (marker._selected)
                        that.selectItem(index, true, true);
                    that._arrangeItems();
                    return that
                }
            });
        var baseMarkerBehavior = _extend({}, DX.viz.map._internal.mapItemBehavior, {
                _type: 'marker',
                _project: function(projection, coords) {
                    return projection.projectPoint(coords)
                },
                _init: function() {
                    this.proxy.coordinates = createCoordinatesGetter(this._src.coords);
                    this.proxy.text = this._src.item.text
                },
                _createRoot: function() {
                    return this._ctx.renderer.createGroup()
                },
                _render: function(settings) {
                    var that = this;
                    that._root.applySettings({'class': CLASS_DEFAULT});
                    that._create(settings, that._ctx.renderer, that._root);
                    that._createText(settings, that._ctx.renderer, that._root);
                    return that
                },
                _createText: function(settings, renderer, root) {
                    var that = this;
                    if (!that._src.item.text)
                        return;
                    var rootbox = that._root.getBBox(),
                        text = renderer.createText(that._src.item.text, 0, 0, {
                            align: 'center',
                            font: settings.font
                        }).append(root),
                        textBox = text.getBBox(),
                        x = _round(-textBox.x + rootbox.width / 2) + 2,
                        y = _round(-textBox.y - textBox.height / 2) - 1;
                    text.applySettings({
                        x: x,
                        y: y
                    });
                    renderer.createRect(x + textBox.x - 1, y + textBox.y - 1, textBox.width + 2, textBox.height + 2, 0, TRACKER_SETTINGS).data(_DATA_KEY, that._data).append(root)
                },
                _transform: function(projection, coords) {
                    return projection.getPointCoordinates(coords)
                },
                _locate: function(coords) {
                    this._root.applySettings({
                        translateX: coords.x,
                        translateY: coords.y
                    })
                },
                _onHover: function() {
                    this.hovered && this._root.toForeground()
                },
                _setDefaultState: function() {
                    this._root.applySettings({'class': CLASS_DEFAULT}).toBackground();
                    this._applyDefault()
                },
                _setHoveredState: function() {
                    this._root.applySettings({'class': CLASS_HOVERED});
                    this._applyHovered()
                },
                _setSelectedState: function() {
                    this._root.applySettings({'class': CLASS_SELECTED}).toForeground();
                    this._applySelected()
                }
            });
        function createCoordinatesGetter(coordinates) {
            return function() {
                    return [_Number(coordinates[0]), _Number(coordinates[1])]
                }
        }
        function DotMarker(){}
        _extend(DotMarker.prototype, baseMarkerBehavior, {
            type: 'dot',
            _create: function(style, renderer, root) {
                var that = this,
                    size = style.size > 0 ? _Number(style.size) : 0,
                    hoveredSize = size,
                    selectedSize = size + (style.selectedStep > 0 ? _Number(style.selectedStep) : 0),
                    hoveredBackSize = hoveredSize + (style.backStep > 0 ? _Number(style.backStep) : 0),
                    selectedBackSize = selectedSize + (style.backStep > 0 ? _Number(style.backStep) : 0),
                    settings = _processCircleSettings(0, 0, size, style.borderWidth);
                that._dotDefault = {
                    cx: settings.cx,
                    cy: settings.cy,
                    r: settings.r,
                    stroke: style.borderColor,
                    strokeWidth: style.borderWidth,
                    fill: style.color,
                    filter: style.shadow ? style._filter : null
                };
                that._dotHovered = {
                    cx: settings.cx,
                    cy: settings.cy,
                    r: hoveredSize / 2,
                    stroke: style.hoveredBorderColor,
                    strokeWidth: style.hoveredBorderWidth,
                    fill: style.hoveredColor
                };
                that._dotSelected = {
                    cx: settings.cx,
                    cy: settings.cy,
                    r: selectedSize / 2,
                    stroke: style.selectedBorderColor,
                    strokeWidth: style.selectedBorderWidth,
                    fill: style.selectedColor
                };
                that._backDefault = {
                    cx: settings.cx,
                    cy: settings.cy,
                    r: settings.r,
                    stroke: 'none',
                    strokeWidth: 0,
                    fill: style.backColor,
                    opacity: style.backOpacity
                };
                that._backHovered = {
                    cx: settings.cx,
                    cy: settings.cy,
                    r: hoveredBackSize / 2,
                    stroke: 'none',
                    strokeWidth: 0,
                    fill: style.backColor,
                    opacity: style.backOpacity
                };
                that._backSelected = {
                    cx: settings.cx,
                    cy: settings.cy,
                    r: selectedBackSize / 2,
                    stroke: 'none',
                    strokeWidth: 0,
                    fill: style.backColor,
                    opacity: style.backOpacity
                };
                that._back = renderer.createCircle().applySettings(that._backDefault).data(_DATA_KEY, that._data).append(root);
                that._dot = renderer.createCircle().applySettings(that._dotDefault).data(_DATA_KEY, that._data).append(root)
            },
            _destroy: function() {
                this._back = this._dot = null
            },
            _applyDefault: function() {
                this._back.applySettings(this._backDefault);
                this._dot.applySettings(this._dotDefault)
            },
            _applyHovered: function() {
                this._back.applySettings(this._backHovered);
                this._dot.applySettings(this._dotHovered)
            },
            _applySelected: function() {
                this._back.applySettings(this._backSelected);
                this._dot.applySettings(this._dotSelected)
            }
        });
        function BubbleMarker(){}
        _extend(BubbleMarker.prototype, baseMarkerBehavior, {
            type: 'bubble',
            _create: function(style, renderer, root) {
                var that = this;
                that._minSize = style.minSize > 0 ? _Number(style.minSize) : 0;
                that._maxSize = style.maxSize > that._minSize ? _Number(style.maxSize) : that._minSize;
                that.value = _isFinite(that._src.item.value) ? _Number(that._src.item.value) : null;
                that._default = {
                    stroke: style.borderColor,
                    strokeWidth: style.borderWidth,
                    fill: style.color,
                    opacity: style.opacity
                };
                that._hovered = {
                    stroke: style.hoveredBorderColor,
                    strokeWidth: style.hoveredBorderWidth,
                    fill: style.hoveredColor,
                    opacity: style.hoveredOpacity
                };
                that._selected = {
                    stroke: style.selectedBorderColor,
                    strokeWidth: style.selectedBorderWidth,
                    fill: style.selectedColor,
                    opacity: style.selectedOpacity
                };
                that._bubble = renderer.createCircle(0, 0, style.maxSize / 2).applySettings(that._default).data(_DATA_KEY, that._data).append(root)
            },
            _destroy: function() {
                this._bubble = null
            },
            _applyDefault: function() {
                this._bubble.applySettings(this._default)
            },
            _applyHovered: function() {
                this._bubble.applySettings(this._hovered)
            },
            _applySelected: function() {
                this._bubble.applySettings(this._selected)
            },
            setSize: function(ratio) {
                var that = this,
                    settings = _processCircleSettings(0, 0, that._minSize + ratio * (that._maxSize - that._minSize), that._default.strokeWidth);
                that._default.cx = that._hovered.cx = that._selected.cx = settings.cx;
                that._default.cy = that._hovered.cy = that._selected.cy = settings.cy;
                that._default.r = that._hovered.r = that._selected.r = settings.r;
                that._bubble.applySettings(settings);
                return that
            }
        });
        function PieMarker(){}
        _extend(PieMarker.prototype, baseMarkerBehavior, {
            type: 'pie',
            _create: function(style, renderer, root) {
                var that = this,
                    settings = _processCircleSettings(0, 0, style.size > 0 ? _Number(style.size) : 0, style.borderWidth);
                that._pieDefault = {opacity: style.opacity};
                that._pieHovered = {opacity: style.hoveredOpacity};
                that._pieSelected = {opacity: style.selectedOpacity};
                that._borderDefault = {
                    stroke: style.borderColor,
                    strokeWidth: style.borderWidth
                };
                that._borderHovered = {
                    stroke: style.hoveredBorderColor,
                    strokeWidth: style.hoveredBorderWidth
                };
                that._borderSelected = {
                    stroke: style.selectedBorderColor,
                    strokeWidth: style.selectedBorderWidth
                };
                var srcValues = that._src.item.values,
                    i = 0,
                    ii = _isArray(srcValues) ? srcValues.length : 0,
                    values = [],
                    value,
                    sum = 0;
                for (; i < ii; ++i) {
                    value = _Number(srcValues[i]);
                    if (_isFinite(value)) {
                        values.push(value);
                        sum += value
                    }
                }
                that._pie = renderer.createGroup(that._pieDefault);
                var translator = new DX.viz.core.Translator1D(0, sum, 90, 450),
                    startAngle = translator.translate(0),
                    endAngle,
                    colors = that._ctx.getColors(values.length);
                for (value = 0, i = 0, ii = values.length; i < ii; ++i) {
                    value += values[i];
                    endAngle = translator.translate(value);
                    renderer.createArc(settings.cx, settings.cy, settings.r, 0, startAngle, endAngle, {fill: colors[i]}).data(_DATA_KEY, that._data).append(that._pie);
                    startAngle = endAngle
                }
                that._pie.append(root);
                that._border = renderer.createCircle(settings.cx, settings.cy, settings.r, that._borderDefault).data(_DATA_KEY, that._data).append(root)
            },
            _destroy: function() {
                this._pie = this._border = null
            },
            _applyDefault: function() {
                this._pie.applySettings(this._pieDefault);
                this._border.applySettings(this._borderDefault)
            },
            _applyHovered: function() {
                this._pie.applySettings(this._pieHovered);
                this._border.applySettings(this._borderHovered)
            },
            _applySelected: function() {
                this._pie.applySettings(this._pieSelected);
                this._border.applySettings(this._borderSelected)
            }
        });
        function ImageMarker(){}
        _extend(ImageMarker.prototype, baseMarkerBehavior, {
            type: 'image',
            _create: function(style, renderer, root) {
                var that = this,
                    size = style.size > 0 ? _Number(style.size) : 0,
                    hoveredSize = size + (style.hoveredStep > 0 ? _Number(style.hoveredStep) : 0),
                    selectedSize = size + (style.selectedStep > 0 ? _Number(style.selectedStep) : 0);
                that._default = {
                    x: -size / 2,
                    y: -size / 2,
                    width: size,
                    height: size
                };
                that._hovered = {
                    x: -hoveredSize / 2,
                    y: -hoveredSize / 2,
                    width: hoveredSize,
                    height: hoveredSize
                };
                that._selected = {
                    x: -selectedSize / 2,
                    y: -selectedSize / 2,
                    width: selectedSize,
                    height: selectedSize
                };
                that._image = renderer.createImage().applySettings(that._default).applySettings({
                    href: that._src.item.url,
                    location: 'center'
                }).append(root);
                that._tracker = renderer.createRect().applySettings(that._default).applySettings(TRACKER_SETTINGS).data(_DATA_KEY, that._data).append(root)
            },
            _destroy: function() {
                this._image = this._tracker = null
            },
            _applyDefault: function() {
                this._image.applySettings(this._default);
                this._tracker.applySettings(this._default)
            },
            _applyHovered: function() {
                this._image.applySettings(this._hovered);
                this._tracker.applySettings(this._hovered)
            },
            _applySelected: function() {
                this._image.applySettings(this._selected);
                this._tracker.applySettings(this._selected)
            }
        });
        MARKER_TYPES['dot'] = DotMarker;
        MARKER_TYPES['bubble'] = BubbleMarker;
        MARKER_TYPES['pie'] = PieMarker;
        MARKER_TYPES['image'] = ImageMarker;
        function parseMarkerType(type, defaultType) {
            return MARKER_TYPES[type] && type || defaultType || DEFAULT_MARKER_TYPE
        }
        var __originalDefaultMarkerType = DEFAULT_MARKER_TYPE,
            __originalMarkerTypes = $.extend({}, MARKER_TYPES);
        DX.viz.map._tests.stubMarkerTypes = function(markerTypes, defaultMarkerType) {
            DEFAULT_MARKER_TYPE = defaultMarkerType;
            MARKER_TYPES = markerTypes
        };
        DX.viz.map._tests.restoreMarkerTypes = function() {
            DEFAULT_MARKER_TYPE = __originalDefaultMarkerType;
            MARKER_TYPES = __originalMarkerTypes
        };
        DX.viz.map._tests.baseMarkerBehavior = baseMarkerBehavior;
        DX.viz.map._tests.MarkersManager = MarkersManager;
        DX.viz.map._tests.DotMarker = DotMarker;
        DX.viz.map._tests.BubbleMarker = BubbleMarker;
        DX.viz.map._tests.PieMarker = PieMarker;
        DX.viz.map._tests.ImageMarker = ImageMarker;
        DX.viz.map.Map.prototype._factory.createMarkersManager = function(parameters) {
            return new MarkersManager(parameters)
        }
    })(DevExpress, jQuery);
    DevExpress.MOD_VIZ_VECTORMAP = true
}
if (!DevExpress.MOD_VIZ_SPARKLINES) {
    if (!DevExpress.MOD_VIZ_CORE)
        throw Error('Required module is not referenced: viz-core');
    /*! Module viz-sparklines, file baseSparkline.js */
    (function($, DX) {
        var TOOLTIP_MARGIN = 100,
            TOOLTIP_ARROW_MARGIN = 10,
            DEFAULT_LINE_SPACING = 6,
            DEFAULT_EVENTS_DELAY = 200,
            TOUCH_EVENTS_DELAY = 1000,
            _extend = $.extend,
            _abs = Math.abs,
            _Number = Number,
            _round = Math.round,
            core = DX.viz.core,
            CoreFactory = core.CoreFactory;
        function DEFAULT_CUSTOMIZE_TOOLTIP(customizeObject) {
            return {text: customizeObject.valueText.join('<br/>')}
        }
        DX.viz.sparklines = {};
        DX.viz.sparklines.DEFAULT_CUSTOMIZE_TOOLTIP = DEFAULT_CUSTOMIZE_TOOLTIP;
        DX.viz.sparklines.BaseSparkline = core.BaseWidget.inherit({
            render: function() {
                this._refresh();
                return this
            },
            _rendererType: DX.viz.renderers.Renderer,
            _clean: function() {
                if (this._tooltipShown) {
                    this._tooltip.dispose();
                    this._tooltip = null;
                    this._tooltipShown = null;
                    this._tooltipGroup.clear()
                }
                this._tooltipContainer.detach();
                this._cleanWidgetElements()
            },
            _optionChanged: function(optionName, value) {
                if (optionName === 'size' && this._allOptions) {
                    this._clean();
                    this._canvas = this._calculateCanvas();
                    this._renderer.resize(this._canvas.width, this._canvas.height);
                    if (!this._isContainerVisible())
                        return;
                    this._allOptions.size = value;
                    this._redrawWidgetElements();
                    this._prepareTooltipContainer()
                }
                else if (optionName === 'dataSource' && this._allOptions)
                    this._refreshDataSource();
                else
                    this.callBase.apply(this, arguments)
            },
            _init: function() {
                this.callBase();
                this._canvas = this._calculateCanvas();
                this._renderer = new this._rendererType({
                    cssClass: this._widgetClass + ' ' + this._widgetClass + '-' + this._widgetType,
                    pathModified: this.option('pathModified'),
                    rtl: this.option('rtlEnabled')
                });
                this._renderer.recreateCanvas(this._canvas.width, this._canvas.height);
                this._createHtmlElements();
                this._createTooltipGroups();
                this._initTooltipEvents();
                this._drawContainer()
            },
            _dispose: function() {
                var that = this;
                that.callBase();
                that._disposeWidgetElements();
                that._disposeTooltipEvents();
                that._renderer.dispose();
                that._tooltipRenderer.dispose();
                that._translatorX = null;
                that._translatorY = null;
                delete that._renderer;
                delete that._tooltipRenderer;
                delete that._tooltipTrackerGroup;
                delete that._tooltipGroup;
                delete that._tooltipContainer
            },
            _render: function() {
                var that = this;
                that._canvas = that._calculateCanvas();
                that._renderer.resize(that._canvas.width, that._canvas.height);
                if (!that._isContainerVisible()) {
                    that._incidentOccured('W2001', [that.NAME]);
                    return
                }
                that._prepareOptions();
                that._createWidgetElements();
                that._drawWidgetElements();
                that._drawn()
            },
            _isContainerVisible: function() {
                var that = this,
                    canvas = that._canvas,
                    enoughWidth = canvas.width - canvas.left - canvas.right > 0,
                    enoughHeight = canvas.height - canvas.top - canvas.bottom > 0;
                return canvas.height && canvas.width && enoughHeight && enoughWidth
            },
            _createWidgetElements: function() {
                this._createRange();
                this._createTranslator()
            },
            _prepareOptions: function(defaultOptions) {
                var that = this,
                    userOptions = that.option() || {},
                    options,
                    defaultTheme,
                    theme;
                defaultTheme = core.findTheme('default');
                defaultTheme = defaultTheme[this._widgetType];
                options = _extend(true, {}, defaultOptions, userOptions);
                if (typeof options.theme === 'string') {
                    theme = core.findTheme(options.theme);
                    theme = theme[this._widgetType]
                }
                else
                    theme = options.theme;
                return _extend(true, {}, defaultTheme, theme, options)
            },
            _calculateCanvas: function() {
                var that = this,
                    canvas = {},
                    sizeOptions = that.option('size') || {},
                    marginOptions = that.option('margin') || {},
                    defaultSize = that._defaultSize,
                    container = that._element(),
                    width = sizeOptions.width >= 0 ? _Number(sizeOptions.width) : container.width(),
                    height = sizeOptions.height >= 0 ? _Number(sizeOptions.height) : container.height();
                if (!width && _Number(sizeOptions.width) !== 0)
                    width = defaultSize.width;
                if (!height && _Number(sizeOptions.height) !== 0)
                    height = defaultSize.height;
                return {
                        width: width,
                        height: height,
                        top: _Number(marginOptions.top) || defaultSize.top,
                        bottom: _Number(marginOptions.bottom) || defaultSize.bottom,
                        left: _Number(marginOptions.left) || defaultSize.left,
                        right: _Number(marginOptions.right) || defaultSize.right
                    }
            },
            _createTooltipGroups: function() {
                var that = this,
                    renderer,
                    root,
                    widgetClass = that._widgetClass;
                that._tooltipRenderer = renderer = new that._rendererType({
                    cssClass: widgetClass + ' ' + widgetClass + '-tooltip',
                    pathModified: this.option('pathModified'),
                    rtl: this.option('rtlEnabled')
                });
                renderer.recreateCanvas(1, 1);
                that._tooltipContainer = $('<div style="position: relative">');
                renderer.draw(that._tooltipContainer[0]);
                root = renderer.getRoot();
                that._tooltipGroup = renderer.createGroup({
                    'class': widgetClass + '-tooltip-group',
                    style: {'z-index': '1'}
                }).append(root);
                that._tooltipTrackerGroup = renderer.createGroup({'class': widgetClass + '-tooltip-tracker-group'}).append(root);
                that._tooltipTracker = that._createTooltipTracker().append(that._tooltipTrackerGroup)
            },
            _createTooltipTracker: function() {
                return this._tooltipRenderer.createRect(0, 0, 0, 0, 0, {
                        fill: 'grey',
                        opacity: 0
                    })
            },
            _initTooltipEvents: function() {
                var that = this,
                    data = {
                        widget: that,
                        container: that._tooltipTracker
                    };
                that._showTooltipCallback = function() {
                    that._showTooltipTimeout = null;
                    if (!that._tooltipShown) {
                        that._tooltipShown = true;
                        that._showTooltip()
                    }
                    that._DEBUG_showCallback && that._DEBUG_showCallback()
                };
                that._hideTooltipCallback = function() {
                    that._hideTooltipTimeout = null;
                    if (that._tooltipShown) {
                        that._tooltipShown = false;
                        that._hideTooltip()
                    }
                    that._DEBUG_hideCallback && that._DEBUG_hideCallback()
                };
                that._disposeCallbacks = function() {
                    that = that._showTooltipCallback = that._hideTooltipCallback = that._disposeCallbacks = null
                };
                that._tooltipTracker.on(mouseEvents, data).on(touchEvents, data);
                that._tooltipTracker.on(menuEvents)
            },
            _disposeTooltipEvents: function() {
                clearTimeout(this._showTooltipTimeout);
                clearTimeout(this._hideTooltipTimeout);
                this._showTooltipTimeout = this._showTooltipTimeout = null;
                this._tooltipTracker.off();
                this._disposeCallbacks()
            },
            _drawContainer: function() {
                this._renderer.draw(this._element()[0])
            },
            _createTranslator: function() {
                this._translatorX = CoreFactory.createTranslator2D(this._ranges.arg, this._canvas, {direction: "horizontal"});
                this._translatorY = CoreFactory.createTranslator2D(this._ranges.val, this._canvas)
            },
            _prepareTooltipOptions: function() {
                var that = this,
                    canvas = that._canvas,
                    tooltipOpt = that._allOptions.tooltip,
                    size = that._getTooltipSize(true),
                    defaultOptions = {
                        canvasWidth: size.width,
                        canvasHeight: size.height,
                        paddingLeftRight: tooltipOpt.paddingLeftRight,
                        paddingTopBottom: tooltipOpt.paddingTopBottom,
                        arrowLength: tooltipOpt.arrowLength,
                        cloudHorizontalPosition: tooltipOpt.horizontalAlignment,
                        cloudVerticalPosition: tooltipOpt.verticalAlignment,
                        lineSpacing: tooltipOpt.font.lineSpacing !== undefined && tooltipOpt.font.lineSpacing !== null ? tooltipOpt.font.lineSpacing : DEFAULT_LINE_SPACING
                    },
                    autoJustify = !$.isFunction(that._allOptions.tooltip.customizeText) && !$.isFunction(that._allOptions.tooltip.customizeTooltip),
                    options = $.extend(defaultOptions, that._allOptions.tooltip, {
                        customizeTooltip: autoJustify ? DEFAULT_CUSTOMIZE_TOOLTIP : that._allOptions.tooltip.customizeTooltip,
                        _justify: that._allOptions.tooltip._justify || autoJustify,
                        _rtl: that.option('rtlEnabled')
                    });
                that._tooltipOptions = {
                    size: size,
                    options: options
                };
                return options
            },
            _prepareTooltipContainer: function() {
                var that = this,
                    canvas = that._canvas,
                    width = canvas.width,
                    height = canvas.height,
                    renderer = that._tooltipRenderer;
                that._updateTooltipSizeToNormal();
                that._tooltipTracker.applySettings({
                    width: width,
                    height: height
                });
                that._tooltipContainer.appendTo(that._element());
                that._tooltipInitializated = false;
                that._canShowTooltip = that._allOptions.tooltip.enabled
            },
            _isTooltipVisible: function() {
                return this._tooltip.enabled() && this._tooltip.prepare(this._getTooltipData(), {offset: 0})
            },
            _createTooltip: function() {
                var that = this;
                that._tooltip = CoreFactory.createTooltip(that._prepareTooltipOptions(), that._tooltipGroup, that._tooltipRenderer);
                if (that._isTooltipVisible()) {
                    that._tooltip.show();
                    that._updateTooltipSizeToWide();
                    that._checkTooltipSize();
                    that._updateTooltipSizeToNormal()
                }
                else
                    that._canShowTooltip = false
            },
            _doShowTooltip: function(delay) {
                var that = this;
                if (!that._canShowTooltip)
                    return;
                ++that._DEBUG_clearHideTooltipTimeout;
                clearTimeout(that._hideTooltipTimeout);
                that._hideTooltipTimeout = null;
                clearTimeout(that._showTooltipTimeout);
                ++that._DEBUG_showTooltipTimeoutSet;
                that._showTooltipTimeout = setTimeout(that._showTooltipCallback, delay)
            },
            _doHideTooltip: function(delay) {
                var that = this;
                if (!that._canShowTooltip)
                    return;
                ++that._DEBUG_clearShowTooltipTimeout;
                clearTimeout(that._showTooltipTimeout);
                that._showTooltipTimeout = null;
                clearTimeout(that._hideTooltipTimeout);
                ++that._DEBUG_hideTooltipTimeoutSet;
                that._hideTooltipTimeout = setTimeout(that._hideTooltipCallback, delay)
            },
            _getNormalTooltipSize: function() {
                var size = {};
                size.width = this._canvas.width;
                size.left = 0;
                size.tooltipLeft = _round(size.width / 2);
                return size
            },
            _getWideTooltipSize: function(leftWidthDelta, rightWidthDelta) {
                var that = this,
                    canvas = that._canvas,
                    horizontalPos = that._allOptions.tooltip.horizontalAlignment,
                    widthDelta = leftWidthDelta + rightWidthDelta,
                    size = {};
                size.width = canvas.width + widthDelta;
                size.left = -leftWidthDelta;
                if (horizontalPos === 'right')
                    size.tooltipLeft = _round(canvas.width / 2);
                else if (horizontalPos === 'left')
                    size.tooltipLeft = _round(canvas.width / 2) + widthDelta;
                else
                    size.tooltipLeft = _round(size.width / 2);
                return size
            },
            _getTooltipSize: function(isNormal, leftWidthDelta, rightWidthDelta, heightDelta) {
                var that = this,
                    canvas = that._canvas,
                    isVerticalPosTop = !(that._allOptions.tooltip.verticalAlignment === 'bottom'),
                    size = !isNormal && (leftWidthDelta || rightWidthDelta) ? that._getWideTooltipSize(leftWidthDelta, rightWidthDelta) : that._getNormalTooltipSize(),
                    yDelta = heightDelta > 0 ? heightDelta + TOOLTIP_MARGIN : TOOLTIP_MARGIN;
                size.height = canvas.height + yDelta;
                size.top = isVerticalPosTop ? -size.height : -canvas.height;
                size.trackerY = isVerticalPosTop ? yDelta : 0;
                size.tooltipY = isVerticalPosTop ? _round(canvas.height / 2) + yDelta - TOOLTIP_ARROW_MARGIN : _round(canvas.height / 2);
                return size
            },
            _checkTooltipSize: function() {
                var that = this,
                    tooltip = that._tooltip,
                    options = that._tooltipOptions.options,
                    tooltipBBox = tooltip.getBBox(),
                    getWide = that._allOptions.tooltip.allowContainerResizing,
                    leftDelta = -tooltipBBox.x,
                    rightDelta = tooltipBBox.x + tooltipBBox.width - that._canvas.width,
                    topDelta = tooltipBBox.height - TOOLTIP_MARGIN,
                    size;
                if (leftDelta > 0 || rightDelta > 0 || topDelta > 0)
                    if (getWide) {
                        that._tooltipOptions.size = size = that._getTooltipSize(false, leftDelta > 0 ? leftDelta : 0, rightDelta > 0 ? rightDelta : 0, topDelta > 0 ? topDelta : 0);
                        tooltip.setSize(size.width, size.height);
                        that._updateTooltipSizeToWide()
                    }
                    else {
                        that._canShowTooltip = false;
                        tooltip.hide()
                    }
            },
            _updateTooltipSizeToWide: function() {
                var that = this,
                    size = that._tooltipOptions.size,
                    renderer = that._tooltipRenderer;
                renderer.resize(size.width, size.height);
                renderer.getRoot().applySettings({style: {
                        left: size.left,
                        top: size.top,
                        position: 'absolute',
                        overflow: 'hidden'
                    }});
                that._tooltipTracker.applySettings({
                    y: size.trackerY,
                    x: -size.left
                });
                that._tooltip.move(size.tooltipLeft, size.tooltipY)
            },
            _updateTooltipSizeToNormal: function() {
                var that = this,
                    renderer = that._tooltipRenderer,
                    canvas = that._canvas;
                renderer.resize(canvas.width, canvas.height);
                renderer.getRoot().applySettings({style: {
                        left: 0,
                        top: -canvas.height,
                        position: 'absolute'
                    }});
                that._tooltipTracker.applySettings({
                    y: 0,
                    x: 0
                })
            },
            _showTooltip: function() {
                if (!this._tooltipInitializated) {
                    this._createTooltip();
                    this._tooltipInitializated = true;
                    if (!this._canShowTooltip)
                        return
                }
                this._updateTooltipSizeToWide();
                this._tooltip.show()
            },
            _hideTooltip: function() {
                this._updateTooltipSizeToNormal();
                this._tooltip.hide()
            },
            showLoadingIndicator: $.noop
        });
        var menuEvents = {
                'contextmenu.sparkline-tooltip': function(event) {
                    if (DX.ui.events.isTouchEvent(event) || DX.ui.events.isPointerEvent(event))
                        event.preventDefault()
                },
                'MSHoldVisual.sparkline-tooltip': function(event) {
                    event.preventDefault()
                }
            };
        var mouseEvents = {
                'mouseover.sparkline-tooltip': function(event) {
                    isPointerDownCalled = false;
                    var widget = event.data.widget;
                    widget._x = event.pageX;
                    widget._y = event.pageY;
                    widget._tooltipTracker.off(mouseMoveEvents).on(mouseMoveEvents, event.data);
                    widget._doShowTooltip(DEFAULT_EVENTS_DELAY)
                },
                'mouseout.sparkline-tooltip': function(event) {
                    if (isPointerDownCalled)
                        return;
                    var widget = event.data.widget;
                    widget._tooltipTracker.off(mouseMoveEvents);
                    widget._doHideTooltip(DEFAULT_EVENTS_DELAY)
                }
            };
        var mouseMoveEvents = {'mousemove.sparkline-tooltip': function(event) {
                    var widget = event.data.widget;
                    if (widget._showTooltipTimeout && (_abs(widget._x - event.pageX) > 3 || _abs(widget._y - event.pageY) > 3)) {
                        widget._x = event.pageX;
                        widget._y = event.pageY;
                        widget._doShowTooltip(DEFAULT_EVENTS_DELAY)
                    }
                }};
        var active_touch_tooltip_widget = null,
            touchstartTooltipProcessing = function(event) {
                event.preventDefault();
                var widget = active_touch_tooltip_widget;
                if (widget && widget !== event.data.widget)
                    widget._doHideTooltip(DEFAULT_EVENTS_DELAY);
                widget = active_touch_tooltip_widget = event.data.widget;
                widget._doShowTooltip(TOUCH_EVENTS_DELAY);
                widget._touch = true
            },
            touchstartDocumentProcessing = function() {
                var widget = active_touch_tooltip_widget;
                if (widget) {
                    if (!widget._touch) {
                        widget._doHideTooltip(DEFAULT_EVENTS_DELAY);
                        active_touch_tooltip_widget = null
                    }
                    widget._touch = null
                }
            },
            touchendDocumentProcessing = function() {
                var widget = active_touch_tooltip_widget;
                if (widget)
                    if (widget._showTooltipTimeout) {
                        widget._doHideTooltip(DEFAULT_EVENTS_DELAY);
                        active_touch_tooltip_widget = null
                    }
            },
            isPointerDownCalled = false;
        var touchEvents = {
                'pointerdown.sparkline-tooltip': function(event) {
                    touchstartTooltipProcessing(event)
                },
                'touchstart.sparkline-tooltip': function(event) {
                    touchstartTooltipProcessing(event)
                }
            };
        $(document).on({
            'pointerdown.sparkline-tooltip': function() {
                isPointerDownCalled = true;
                touchstartDocumentProcessing()
            },
            'touchstart.sparkline-tooltip': function() {
                touchstartDocumentProcessing()
            },
            'pointerup.sparkline-tooltip': function() {
                touchendDocumentProcessing()
            },
            'touchend.sparkline-tooltip': function() {
                touchendDocumentProcessing()
            }
        });
        DX.viz.sparklines.BaseSparkline._DEBUG_reset = function() {
            active_touch_tooltip_widget = null
        }
    })(jQuery, DevExpress);
    /*! Module viz-sparklines, file sparkline.js */
    (function($, DX) {
        var viz = DX.viz,
            charts = viz.charts,
            core = viz.core,
            MIN_BAR_WIDTH = 1,
            MAX_BAR_WIDTH = 50,
            DEFAULT_BAR_INTERVAL = 4,
            DEFAULT_CANVAS_WIDTH = 250,
            DEFAULT_CANVAS_HEIGHT = 30,
            DEFAULT_HORIZONTAL_MARGIN = 5,
            DEFAULT_VERTICAL_MARGIN = 3,
            DEFAULT_OPTIONS = {
                disabled: false,
                theme: 'default',
                dataSource: [],
                size: {},
                margin: {},
                type: 'line',
                argumentField: 'arg',
                valueField: 'val',
                winlossThreshold: 0,
                showFirstLast: true,
                showMinMax: false,
                redrawOnResize: false
            },
            ALLOWED_TYPES = {
                line: true,
                spline: true,
                stepline: true,
                area: true,
                steparea: true,
                splinearea: true,
                bar: true,
                winloss: true
            },
            _map = $.map,
            _extend = $.extend,
            _abs = Math.abs,
            _round = Math.round,
            _isFinite = isFinite,
            _Number = Number,
            _String = String;
        viz.sparklines.Sparkline = viz.sparklines.BaseSparkline.inherit({
            _widgetType: 'sparkline',
            _widgetClass: 'dxsl',
            _defaultSize: {
                width: DEFAULT_CANVAS_WIDTH,
                height: DEFAULT_CANVAS_HEIGHT,
                left: DEFAULT_HORIZONTAL_MARGIN,
                right: DEFAULT_HORIZONTAL_MARGIN,
                top: DEFAULT_VERTICAL_MARGIN,
                bottom: DEFAULT_VERTICAL_MARGIN
            },
            _init: function() {
                this.callBase();
                this._refreshDataSource()
            },
            _handleDataSourceChanged: function() {
                if (this._initialized) {
                    this._clean();
                    this._createWidgetElements();
                    this._drawWidgetElements()
                }
            },
            _dataSourceOptions: function() {
                return {
                        paginate: false,
                        _preferSync: true
                    }
            },
            _redrawWidgetElements: function() {
                this._createTranslator();
                this._correctPoints();
                this._series.draw({
                    x: this._translatorX,
                    y: this._translatorY
                });
                this._seriesGroup.append(this._renderer.getRoot())
            },
            _disposeWidgetElements: function() {
                delete this._seriesGroup;
                delete this._seriesLabelGroup
            },
            _cleanWidgetElements: function() {
                this._seriesGroup.detach();
                this._seriesLabelGroup.detach();
                this._seriesGroup.clear();
                this._seriesLabelGroup.clear()
            },
            _createWidgetElements: function() {
                this._createSeries();
                this.callBase()
            },
            _drawWidgetElements: function() {
                if (this._dataSource && this._dataSource.isLoaded())
                    this._drawSeries()
            },
            _prepareOptions: function() {
                this._allOptions = this.callBase(DEFAULT_OPTIONS);
                this._allOptions.type = _String(this._allOptions.type).toLowerCase();
                if (!ALLOWED_TYPES[this._allOptions.type])
                    this._allOptions.type = 'line'
            },
            _createHtmlElements: function() {
                this._seriesGroup = this._renderer.createGroup({'class': 'dxsl-series'});
                this._seriesLabelGroup = this._renderer.createGroup({'class': 'dxsl-series-labels'})
            },
            _createSeries: function() {
                var that = this,
                    renderer = that._renderer,
                    dataValidator;
                that._prepareDataSource();
                that._prepareSeriesOptions();
                that._series = core.CoreFactory.createSeries(renderer, that._seriesOptions);
                dataValidator = charts.factory.createDataValidator(that._simpleDataSource, [[that._series]], that._incidentOccured, {
                    checkTypeForAllData: false,
                    convertToAxisDataType: true,
                    sortingMethod: true
                });
                that._simpleDataSource = dataValidator.validate();
                that._series._options.customizePoint = that._getCustomizeFunction();
                that._series.updateData(that._simpleDataSource)
            },
            _parseNumericDataSource: function(data, argField, valField) {
                var ignoreEmptyPoints = this.option('ignoreEmptyPoints');
                return _map(data, function(dataItem, index) {
                        var item = null,
                            isDataNumber,
                            value;
                        if (dataItem !== undefined) {
                            item = {};
                            isDataNumber = _isFinite(dataItem);
                            item[argField] = isDataNumber ? _String(index) : dataItem[argField];
                            value = isDataNumber ? dataItem : dataItem[valField];
                            item[valField] = value === null ? ignoreEmptyPoints ? undefined : value : _Number(value);
                            item = item[argField] !== undefined && item[valField] !== undefined ? item : null
                        }
                        return item
                    })
            },
            _parseWinlossDataSource: function(data, argField, valField) {
                var lowBarValue = -1,
                    zeroBarValue = 0,
                    highBarValue = 1,
                    delta = 0.0001,
                    target = this._allOptions.winlossThreshold;
                return _map(data, function(dataItem) {
                        var item = {};
                        item[argField] = dataItem[argField];
                        if (_abs(dataItem[valField] - target) < delta)
                            item[valField] = zeroBarValue;
                        else if (dataItem[valField] > target)
                            item[valField] = highBarValue;
                        else
                            item[valField] = lowBarValue;
                        return item
                    })
            },
            _prepareDataSource: function() {
                var that = this,
                    options = that._allOptions,
                    argField = options.argumentField,
                    valField = options.valueField,
                    dataSource = that._dataSource ? that._dataSource.items() : [],
                    data = that._parseNumericDataSource(dataSource, argField, valField);
                if (options.type === 'winloss') {
                    that._winlossDataSource = data;
                    that._simpleDataSource = that._parseWinlossDataSource(data, argField, valField)
                }
                else
                    that._simpleDataSource = data
            },
            _prepareSeriesOptions: function() {
                var that = this,
                    options = that._allOptions,
                    defaultPointOptions = {
                        border: {},
                        hoverStyle: {border: {}},
                        selectionStyle: {border: {}}
                    },
                    customPointOptions = {
                        size: options.pointSize,
                        symbol: options.pointSymbol,
                        border: {
                            visible: true,
                            width: 2
                        },
                        color: options.pointColor
                    };
                that._seriesOptions = {
                    visible: true,
                    argumentField: options.argumentField,
                    valueField: options.valueField,
                    color: options.lineColor,
                    width: options.lineWidth,
                    widgetType: "chart"
                };
                that._seriesOptions.border = {
                    color: that._seriesOptions.color,
                    width: that._seriesOptions.width,
                    visible: true
                };
                that._seriesOptions.type = options.type === 'winloss' ? 'bar' : options.type;
                if (options.type === 'winloss' || options.type === 'bar') {
                    that._seriesOptions.argumentAxisType = 'discrete';
                    that._seriesOptions.border.visible = false
                }
                if (~~options.type.indexOf('area') !== -1)
                    that._seriesOptions.opacity = that._allOptions.areaOpacity;
                that._seriesOptions.seriesGroup = that._seriesGroup;
                that._seriesOptions.seriesLabelsGroup = that._seriesLabelGroup;
                that._seriesOptions.point = _extend(defaultPointOptions, customPointOptions);
                that._seriesOptions.point.visible = false
            },
            _createBarCustomizeFunction: function(pointIndexes) {
                var that = this,
                    options = that._allOptions,
                    winlossData = that._winlossDataSource;
                return function() {
                        var index = this.index,
                            isWinloss = options.type === 'winloss',
                            target = isWinloss ? options.winlossThreshold : 0,
                            value = isWinloss ? winlossData[index][options.valueField] : this.value,
                            positiveColor = isWinloss ? options.winColor : options.barPositiveColor,
                            negativeColor = isWinloss ? options.lossColor : options.barNegativeColor,
                            color;
                        if (value >= target)
                            color = positiveColor;
                        else
                            color = negativeColor;
                        if (index === pointIndexes.first || index === pointIndexes.last)
                            color = options.firstLastColor;
                        if (index === pointIndexes.min)
                            color = options.minColor;
                        if (index === pointIndexes.max)
                            color = options.maxColor;
                        return {color: color}
                    }
            },
            _createLineCustomizeFunction: function(pointIndexes) {
                var that = this,
                    options = that._allOptions;
                return function() {
                        var color,
                            index = this.index;
                        if (index === pointIndexes.first || index === pointIndexes.last)
                            color = options.firstLastColor;
                        if (index === pointIndexes.min)
                            color = options.minColor;
                        if (index === pointIndexes.max)
                            color = options.maxColor;
                        return color ? {
                                visible: true,
                                border: {color: color}
                            } : {}
                    }
            },
            _getCustomizeFunction: function() {
                var that = this,
                    options = that._allOptions,
                    dataSource = that._winlossDataSource || that._simpleDataSource,
                    drawnPointIndexes = that._getExtremumPointsIndexes(dataSource),
                    customizeFunction;
                if (options.type === 'winloss' || options.type === 'bar')
                    customizeFunction = that._createBarCustomizeFunction(drawnPointIndexes);
                else
                    customizeFunction = that._createLineCustomizeFunction(drawnPointIndexes);
                return customizeFunction
            },
            _getExtremumPointsIndexes: function(data) {
                var that = this,
                    options = that._allOptions,
                    lastIndex = data.length - 1,
                    indexes = {};
                that._minMaxIndexes = that._findMinMax(data);
                if (options.showFirstLast) {
                    indexes.first = 0;
                    indexes.last = lastIndex
                }
                if (options.showMinMax) {
                    indexes.min = that._minMaxIndexes.minIndex;
                    indexes.max = that._minMaxIndexes.maxIndex
                }
                return indexes
            },
            _findMinMax: function(data) {
                var that = this,
                    valField = that._allOptions.valueField,
                    firstItem = data[0] || {},
                    firstValue = firstItem[valField] || 0,
                    min = firstValue,
                    max = firstValue,
                    minIndex = 0,
                    maxIndex = 0,
                    dataLength = data.length,
                    value,
                    i;
                for (i = 1; i < dataLength; i++) {
                    value = data[i][valField];
                    if (value < min) {
                        min = value;
                        minIndex = i
                    }
                    if (value > max) {
                        max = value;
                        maxIndex = i
                    }
                }
                return {
                        minIndex: minIndex,
                        maxIndex: maxIndex
                    }
            },
            _createRange: function() {
                var that = this,
                    series = that._series,
                    isBarType = series.type === 'bar',
                    DEFAULT_VALUE_RANGE_MARGIN = 0.15,
                    DEFAULT_ARGUMENT_RANGE_MARGIN = isBarType ? 0.1 : 0,
                    rangeData = series.getRangeData();
                that._ranges = {
                    arg: new core.Range({
                        stick: !isBarType && series.getPoints().length > 1,
                        minValueMargin: DEFAULT_ARGUMENT_RANGE_MARGIN,
                        maxValueMargin: DEFAULT_ARGUMENT_RANGE_MARGIN
                    }),
                    val: new core.Range({
                        isValueRange: true,
                        keepValueMargins: true,
                        minValueMargin: DEFAULT_VALUE_RANGE_MARGIN,
                        maxValueMargin: DEFAULT_VALUE_RANGE_MARGIN
                    })
                };
                that._ranges.arg.addRange(rangeData.arg);
                that._ranges.val.addRange(rangeData.val);
                that._ranges.arg.applyValueMargins();
                that._ranges.val.applyValueMargins()
            },
            _getBarWidth: function(pointsCount) {
                var that = this,
                    canvas = that._canvas,
                    intervalWidth = pointsCount * DEFAULT_BAR_INTERVAL,
                    rangeWidth = canvas.width - canvas.left - canvas.right - intervalWidth,
                    width = _round(rangeWidth / pointsCount);
                if (width < MIN_BAR_WIDTH)
                    width = MIN_BAR_WIDTH;
                if (width > MAX_BAR_WIDTH)
                    width = MAX_BAR_WIDTH;
                return width
            },
            _correctPoints: function() {
                var that = this,
                    seriesType = that._allOptions.type,
                    seriesPoints = that._series.getPoints(),
                    pointsLength = seriesPoints.length,
                    barWidth,
                    i;
                if (seriesType === 'bar' || seriesType === 'winloss') {
                    barWidth = that._getBarWidth(pointsLength);
                    for (i = 0; i < pointsLength; i++)
                        seriesPoints[i].correctCoordinates({
                            width: barWidth,
                            offset: 0
                        })
                }
            },
            _drawSeries: function() {
                var that = this;
                if (that._simpleDataSource.length !== 0) {
                    that._correctPoints();
                    that._series.draw({
                        x: that._translatorX,
                        y: that._translatorY
                    });
                    that._seriesGroup.append(that._renderer.getRoot());
                    that._prepareTooltipContainer()
                }
            },
            _isTooltipVisible: function() {
                return this.callBase() && this._dataSource.length !== 0
            },
            _getTooltipData: function() {
                var that = this,
                    options = that._allOptions,
                    dataSource = that._winlossDataSource || that._simpleDataSource,
                    tooltip = that._tooltip;
                if (dataSource.length === 0)
                    return {};
                var minMax = that._minMaxIndexes,
                    valueField = options.valueField,
                    first = dataSource[0][valueField],
                    last = dataSource[dataSource.length - 1][valueField],
                    min = dataSource[minMax.minIndex][valueField],
                    max = dataSource[minMax.maxIndex][valueField],
                    formattedFirst = tooltip.formatValue(first),
                    formattedLast = tooltip.formatValue(last),
                    formattedMin = tooltip.formatValue(min),
                    formattedMax = tooltip.formatValue(max),
                    customizeObject = {
                        firstValue: formattedFirst,
                        lastValue: formattedLast,
                        minValue: formattedMin,
                        maxValue: formattedMax,
                        originalFirstValue: first,
                        originalLastValue: last,
                        originalMinValue: min,
                        originalMaxValue: max,
                        valueText: ['Start:', formattedFirst, 'End:', formattedLast, 'Min:', formattedMin, 'Max:', formattedMax]
                    };
                if (options.type === 'winloss') {
                    customizeObject.originalThresholdValue = options.winlossThreshold;
                    customizeObject.thresholdValue = tooltip.formatValue(options.winlossThreshold)
                }
                return customizeObject
            }
        }).include(DX.ui.DataHelperMixin)
    })(jQuery, DevExpress);
    /*! Module viz-sparklines, file bullet.js */
    (function($, DX) {
        var charts = DX.viz.charts,
            TARGET_MIN_Y = 0.02,
            TARGET_MAX_Y = 0.98,
            BAR_VALUE_MIN_Y = 0.1,
            BAR_VALUE_MAX_Y = 0.9,
            DEFAULT_CANVAS_WIDTH = 300,
            DEFAULT_CANVAS_HEIGHT = 30,
            DEFAULT_HORIZONTAL_MARGIN = 1,
            DEFAULT_VERTICAL_MARGIN = 2,
            DEFAULT_OPTIONS = {
                disabled: false,
                theme: 'default',
                size: {},
                margin: {}
            },
            _String = String,
            _Number = Number,
            _round = Math.round,
            _isFinite = isFinite;
        DX.viz.sparklines.Bullet = DX.viz.sparklines.BaseSparkline.inherit({
            _widgetType: 'bullet',
            _widgetClass: 'dxb',
            _defaultSize: {
                width: DEFAULT_CANVAS_WIDTH,
                height: DEFAULT_CANVAS_HEIGHT,
                left: DEFAULT_HORIZONTAL_MARGIN,
                right: DEFAULT_HORIZONTAL_MARGIN,
                top: DEFAULT_VERTICAL_MARGIN,
                bottom: DEFAULT_VERTICAL_MARGIN
            },
            _disposeWidgetElements: function() {
                delete this._zeroLevelPath;
                delete this._targetPath;
                delete this._barValuePath
            },
            _redrawWidgetElements: function() {
                this._createTranslator();
                this._drawBarValue();
                this._drawTarget();
                this._drawZeroLevel()
            },
            _cleanWidgetElements: function() {
                this._zeroLevelPath.detach();
                this._targetPath.detach();
                this._barValuePath.detach()
            },
            _drawWidgetElements: function() {
                this._drawBullet()
            },
            _createHtmlElements: function() {
                var renderer = this._renderer;
                this._zeroLevelPath = renderer.createPath(undefined, {'class': 'dxb-zero-level'});
                this._targetPath = renderer.createPath(undefined, {'class': 'dxb-target'});
                this._barValuePath = renderer.createPath(undefined, {'class': 'dxb-bar-value'})
            },
            _prepareOptions: function() {
                var that = this,
                    options,
                    startScaleValue,
                    endScaleValue,
                    level,
                    value,
                    target;
                that._allOptions = options = that.callBase(DEFAULT_OPTIONS);
                if (that._allOptions.value === undefined)
                    that._allOptions.value = 0;
                if (that._allOptions.target === undefined)
                    that._allOptions.target = 0;
                options.value = value = _Number(options.value);
                options.target = target = _Number(options.target);
                if (that._allOptions.startScaleValue === undefined) {
                    that._allOptions.startScaleValue = target < value ? target : value;
                    that._allOptions.startScaleValue = that._allOptions.startScaleValue < 0 ? that._allOptions.startScaleValue : 0
                }
                if (that._allOptions.endScaleValue === undefined)
                    that._allOptions.endScaleValue = target > value ? target : value;
                options.startScaleValue = startScaleValue = _Number(options.startScaleValue);
                options.endScaleValue = endScaleValue = _Number(options.endScaleValue);
                if (endScaleValue < startScaleValue) {
                    level = endScaleValue;
                    that._allOptions.endScaleValue = startScaleValue;
                    that._allOptions.startScaleValue = level;
                    that._allOptions.inverted = true
                }
            },
            _createRange: function() {
                var that = this,
                    options = that._allOptions;
                that._ranges = {
                    arg: {
                        invert: options.inverted,
                        min: options.startScaleValue,
                        max: options.endScaleValue,
                        axisType: "continuous",
                        dataType: "numeric"
                    },
                    val: {
                        min: 0,
                        max: 1,
                        axisType: "continuous",
                        dataType: "numeric"
                    }
                }
            },
            _drawBullet: function() {
                var that = this,
                    options = that._allOptions,
                    isValidBounds = options.startScaleValue !== options.endScaleValue,
                    isValidMin = _isFinite(options.startScaleValue),
                    isValidMax = _isFinite(options.endScaleValue),
                    isValidValue = _isFinite(options.value),
                    isValidTarget = _isFinite(options.target);
                if (isValidBounds && isValidMax && isValidMin && isValidTarget && isValidValue) {
                    this._drawBarValue();
                    this._drawTarget();
                    this._drawZeroLevel();
                    this._prepareTooltipContainer()
                }
            },
            _getTargetParams: function() {
                var that = this,
                    options = that._allOptions,
                    translatorX = that._translatorX,
                    translatorY = that._translatorY,
                    minY = translatorY.translate(TARGET_MIN_Y),
                    maxY = translatorY.translate(TARGET_MAX_Y),
                    x = translatorX.translate(options.target),
                    points = [{
                            x: x,
                            y: minY
                        }, {
                            x: x,
                            y: maxY
                        }];
                return {
                        points: points,
                        stroke: options.targetColor,
                        strokeWidth: options.targetWidth
                    }
            },
            _getBarValueParams: function() {
                var that = this,
                    options = that._allOptions,
                    translatorX = that._translatorX,
                    translatorY = that._translatorY,
                    startLevel = options.startScaleValue,
                    endLevel = options.endScaleValue,
                    value = options.value,
                    y2 = translatorY.translate(BAR_VALUE_MIN_Y),
                    y1 = translatorY.translate(BAR_VALUE_MAX_Y),
                    x1,
                    x2;
                if (value > 0) {
                    x1 = startLevel <= 0 ? 0 : startLevel;
                    x2 = value >= endLevel ? endLevel : value
                }
                else {
                    x1 = endLevel >= 0 ? 0 : endLevel;
                    x2 = value >= startLevel ? value : startLevel
                }
                x1 = translatorX.translate(x1);
                x2 = translatorX.translate(x2);
                return {
                        points: [{
                                x: x1,
                                y: y1
                            }, {
                                x: x2,
                                y: y1
                            }, {
                                x: x2,
                                y: y2
                            }, {
                                x: x1,
                                y: y2
                            }],
                        fill: options.color
                    }
            },
            _getZeroLevelParams: function() {
                var that = this,
                    options = that._allOptions,
                    translatorX = that._translatorX,
                    translatorY = that._translatorY,
                    minY = translatorY.translate(TARGET_MIN_Y),
                    maxY = translatorY.translate(TARGET_MAX_Y),
                    x = translatorX.translate(0);
                return {
                        points: [{
                                x: x,
                                y: minY
                            }, {
                                x: x,
                                y: maxY
                            }],
                        stroke: options.targetColor,
                        strokeWidth: 1
                    }
            },
            _drawZeroLevel: function() {
                var that = this,
                    options = that._allOptions,
                    params;
                if (0 > options.endScaleValue || 0 < options.startScaleValue || !options.showZeroLevel)
                    return;
                params = that._getZeroLevelParams();
                that._zeroLevelPath.applySettings(params);
                that._zeroLevelPath.append(that._renderer.getRoot())
            },
            _drawTarget: function() {
                var that = this,
                    options = that._allOptions,
                    target = options.target,
                    startLevel = options.startScaleValue,
                    endLevel = options.endScaleValue,
                    params;
                if (target > endLevel || target < startLevel || !options.showTarget)
                    return;
                params = that._getTargetParams();
                that._targetPath.applySettings(params);
                that._targetPath.append(that._renderer.getRoot())
            },
            _drawBarValue: function() {
                var that = this,
                    params = that._getBarValueParams();
                that._barValuePath.applySettings(params);
                that._barValuePath.append(that._renderer.getRoot())
            },
            _getTooltipData: function() {
                var that = this,
                    tooltip = that._tooltip,
                    options = that._allOptions,
                    value = options.value,
                    target = options.target;
                return {
                        originalValue: value,
                        originalTarget: target,
                        value: tooltip.formatValue(value),
                        target: tooltip.formatValue(target),
                        valueText: ['Actual Value:', value, 'Target Value:', target]
                    }
            },
            _getNormalTooltipSize: function() {
                var size = {},
                    bbox = this._barValuePath.getBBox();
                size.width = this._canvas.width;
                size.left = 0;
                size.tooltipLeft = bbox.x + _round(bbox.width / 2);
                return size
            },
            _getWideTooltipSize: function(leftWidthDelta, rightWidthDelta) {
                var that = this,
                    bbox = that._barValuePath.getBBox(),
                    horizontalPos = that._allOptions.tooltip.horizontalAlignment,
                    size = {};
                size.width = leftWidthDelta + rightWidthDelta + that._canvas.width;
                size.left = -leftWidthDelta;
                if (horizontalPos === 'right')
                    size.tooltipLeft = bbox.x + _round(bbox.width / 2);
                else if (horizontalPos === 'left')
                    size.tooltipLeft = _round(bbox.width / 2) + leftWidthDelta + rightWidthDelta + bbox.x;
                else
                    size.tooltipLeft = _round(bbox.width / 2) + bbox.x + leftWidthDelta;
                return size
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-sparklines, file dxSparkline.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            viz = DX.viz;
        DX.registerComponent("dxSparkline", viz.sparklines.Sparkline)
    })(jQuery, DevExpress);
    /*! Module viz-sparklines, file dxBullet.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            viz = DX.viz;
        DX.registerComponent("dxBullet", viz.sparklines.Bullet)
    })(jQuery, DevExpress);
    DevExpress.MOD_VIZ_SPARKLINES = true
}
