").addClass("dx-empty-message");
                        this._$nodata.appendTo(this._itemContainer()).html(noDataText);
                        this.setAria("label", noDataText)
                    }
                    this.element().toggleClass(EMPTY_COLLECTION, !hideNoData)
                },
                _itemJQueryEventHandler: function(jQueryEvent, handlerOptionName, actionArgs, actionConfig) {
                    this._itemEventHandler(jQueryEvent.target, handlerOptionName, $.extend(actionArgs, {jQueryEvent: jQueryEvent}), actionConfig)
                },
                _itemEventHandler: function(initiator, handlerOptionName, actionArgs, actionConfig) {
                    var action = this._createActionByOption(handlerOptionName, $.extend({validatingTargetName: "itemElement"}, actionConfig));
                    return this._itemEventHandlerImpl(initiator, action, actionArgs)
                },
                _itemEventHandlerByHandler: function(initiator, handler, actionArgs, actionConfig) {
                    var action = this._createAction(handler, $.extend({validatingTargetName: "itemElement"}, actionConfig));
                    return this._itemEventHandlerImpl(initiator, action, actionArgs)
                },
                _itemEventHandlerImpl: function(initiator, action, actionArgs) {
                    var $itemElement = this._closestItemElement($(initiator));
                    return action($.extend(this._extendActionArgs($itemElement), actionArgs))
                },
                _extendActionArgs: function($itemElement) {
                    return {
                            itemElement: $itemElement,
                            itemIndex: $itemElement.index(this._itemSelector()),
                            itemData: this._getItemData($itemElement)
                        }
                },
                _closestItemElement: function($element) {
                    return $($element).closest(this._itemSelector())
                },
                _getItemData: function(itemElement) {
                    return $(itemElement).data(this._itemDataKey())
                },
                getFocusedItemId: function() {
                    if (!this._focusedItemId)
                        this._focusedItemId = new DevExpress.data.Guid;
                    return this._focusedItemId
                },
                itemElements: function() {
                    return this._itemElements()
                },
                itemsContainer: function() {
                    return this._itemContainer()
                }
            }).include(ui.DataHelperMixin);
        ui.CollectionWidget = CollectionWidget
    })(jQuery, DevExpress);
    /*! Module core, file ui.CollectionWidget.edit.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            utils = DX.utils;
        var ITEM_DELETING_DATA_KEY = "dxItemDeleting";
        var CollectionWidget = ui.CollectionWidget.inherit({
                _setOptionsByReference: function() {
                    this.callBase();
                    $.extend(this._optionsByReference, {selectedItem: true})
                },
                _setDeprecatedOptions: function() {
                    this.callBase();
                    $.extend(this._deprecatedOptions, {itemSelectAction: {
                            since: "14.2",
                            message: "Use the 'onSelectionChanged' option instead"
                        }})
                },
                _setDefaultOptions: function() {
                    this.callBase();
                    this.option({
                        selectionMode: 'none',
                        selectionRequired: false,
                        selectionByClick: true,
                        selectedItems: [],
                        selectedIndex: -1,
                        selectedItem: null,
                        onSelectionChanged: null,
                        onItemReordered: null,
                        onItemDeleting: null,
                        onItemDeleted: null
                    })
                },
                _init: function() {
                    this.callBase();
                    this._initEditStrategy();
                    this._selectedItemIndices = []
                },
                _initEditStrategy: function() {
                    var strategy = ui.CollectionWidget.PlainEditStrategy;
                    this._editStrategy = new strategy(this)
                },
                _render: function() {
                    this._syncSelectionOptions();
                    this._normalizeSelectedItems();
                    this._initSelectedItems();
                    this.callBase();
                    this._renderSelection(this._selectedItemIndices, [])
                },
                _syncSelectionOptions: function(byOption) {
                    byOption = byOption || this._chooseSelectOption();
                    var selectedItem,
                        selectedItems;
                    switch (byOption) {
                        case"selectedIndex":
                            selectedItem = this._editStrategy.getItemDataByIndex(this.option("selectedIndex"));
                            if (utils.isDefined(selectedItem)) {
                                this._setOptionSilent("selectedItems", [selectedItem]);
                                this._setOptionSilent("selectedItem", selectedItem)
                            }
                            else {
                                this._setOptionSilent("selectedItems", []);
                                this._setOptionSilent("selectedItem", null)
                            }
                            break;
                        case"selectedItems":
                            selectedItems = this.option("selectedItems") || [];
                            this._setOptionSilent("selectedItem", selectedItems[0]);
                            this._setOptionSilent("selectedIndex", this._editStrategy.getIndexByItemData(selectedItems[0]));
                            break;
                        case"selectedItem":
                            selectedItem = this.option("selectedItem");
                            if (utils.isDefined(selectedItem)) {
                                this._setOptionSilent("selectedItems", [selectedItem]);
                                this._setOptionSilent("selectedIndex", this._editStrategy.getIndexByItemData(selectedItem))
                            }
                            else {
                                this._setOptionSilent("selectedItems", []);
                                this._setOptionSilent("selectedIndex", -1)
                            }
                            break
                    }
                },
                _chooseSelectOption: function() {
                    var optionName = "selectedIndex";
                    if (this.option("selectedItems").length)
                        optionName = "selectedItems";
                    else if (utils.isDefined(this.option("selectedItem")))
                        optionName = "selectedItem";
                    return optionName
                },
                _normalizeSelectedItems: function() {
                    if (this.option("selectionMode") === "none") {
                        this._setOptionSilent("selectedItems", []);
                        this._syncSelectionOptions("selectedItems")
                    }
                    else if (this.option("selectionMode") === "single") {
                        var newSelection = this._editStrategy.selectedItemIndices(this.option("selectedItems"));
                        if (newSelection.length > 1 || !newSelection.length && this.option("selectionRequired") && this.option("items") && this.option("items").length) {
                            var normalizedSelection = [newSelection[0] || this._selectedItemIndices[0] || 0];
                            this._setOptionSilent("selectedItems", this._editStrategy.fetchSelectedItems(normalizedSelection));
                            this._syncSelectionOptions("selectedItems")
                        }
                    }
                },
                _initSelectedItems: function() {
                    this._selectedItemIndices = this._editStrategy.selectedItemIndices(this.option("selectedItems"))
                },
                _renderSelection: $.noop,
                _itemClickHandler: function(e) {
                    this._createAction($.proxy(function(e) {
                        this._itemSelectHandler(e.jQueryEvent)
                    }, this), {validatingTargetName: "itemElement"})({
                        itemElement: $(e.currentTarget),
                        jQueryEvent: e
                    });
                    this.callBase.apply(this, arguments)
                },
                _itemSelectHandler: function(e) {
                    if (!this.option("selectionByClick"))
                        return;
                    var $itemElement = e.currentTarget;
                    if (this.isItemSelected($itemElement))
                        this.unselectItem(e.currentTarget);
                    else
                        this.selectItem(e.currentTarget)
                },
                _selectedItemElement: function(index) {
                    return this._itemElements().eq(index)
                },
                _postprocessRenderItem: function(args) {
                    var $itemElement = $(args.itemElement);
                    if (this._isItemSelected(this._editStrategy.getNormalizedIndex($itemElement))) {
                        $itemElement.addClass(this._selectedItemClass());
                        this._setAriaSelected($itemElement, "true")
                    }
                    else
                        this._setAriaSelected($itemElement, "false")
                },
                _updateSelectedItems: function() {
                    var oldSelection = this._selectedItemIndices.slice(),
                        newSelection = this._editStrategy.selectedItemIndices(),
                        addedSelection = utils.removeDublicates(newSelection, oldSelection),
                        removedSelection = utils.removeDublicates(oldSelection, newSelection);
                    $.each(removedSelection, $.proxy(function(_, normalizedIndex) {
                        this._removeSelection(normalizedIndex)
                    }, this));
                    $.each(addedSelection, $.proxy(function(_, normalizedIndex) {
                        this._addSelection(normalizedIndex)
                    }, this));
                    if (removedSelection.length || addedSelection.length) {
                        var selectionChangePromise = this._selectionChangePromise;
                        this._updateSelection(addedSelection, removedSelection);
                        $.when(selectionChangePromise).done($.proxy(function() {
                            this._fireSelectItemEvent(addedSelection, removedSelection);
                            this._fireSelectionChangeEvent(addedSelection, removedSelection)
                        }, this))
                    }
                },
                _fireSelectionChangeEvent: function(addedSelection, removedSelection) {
                    this._createActionByOption("onSelectionChanged", {excludeValidators: ["disabled", "readOnly"]})({
                        addedItems: this._editStrategy.fetchSelectedItems(addedSelection),
                        removedItems: this._editStrategy.fetchSelectedItems(removedSelection)
                    })
                },
                _fireSelectItemEvent: function(addedSelection, removedSelection) {
                    if (this.NAME === "dxList" && this.option("selectionMode") !== "single")
                        return;
                    this._itemEventHandler(this._selectedItemElement(addedSelection[0]), "itemSelectAction", {
                        selectedIndex: addedSelection[0],
                        previousIndex: removedSelection[0]
                    }, {excludeValidators: ["disabled", "readOnly"]})
                },
                _updateSelection: function() {
                    this._renderSelection.apply(this, arguments)
                },
                _setAriaSelected: function($target, value) {
                    this.setAria("selected", value, $target)
                },
                _removeSelection: function(normalizedIndex) {
                    var $itemElement = this._editStrategy.getItemElement(normalizedIndex),
                        itemSelectionIndex = $.inArray(normalizedIndex, this._selectedItemIndices);
                    if (itemSelectionIndex > -1) {
                        $itemElement.removeClass(this._selectedItemClass());
                        this._setAriaSelected($itemElement, "false");
                        this._selectedItemIndices.splice(itemSelectionIndex, 1);
                        $itemElement.triggerHandler("stateChanged");
                        if (this.NAME === "dxList")
                            this._itemEventHandler($itemElement, "itemUnselectAction", {}, {excludeValidators: ["disabled", "readOnly"]})
                    }
                },
                _addSelection: function(normalizedIndex) {
                    var $itemElement = this._editStrategy.getItemElement(normalizedIndex);
                    if (normalizedIndex > -1 && !this._isItemSelected(normalizedIndex)) {
                        $itemElement.addClass(this._selectedItemClass());
                        this._setAriaSelected($itemElement, "true");
                        this._selectedItemIndices.push(normalizedIndex);
                        $itemElement.triggerHandler("stateChanged");
                        if (this.NAME === "dxList")
                            this._itemEventHandler($itemElement, "itemSelectAction", {}, {excludeValidators: ["disabled", "readOnly"]})
                    }
                },
                _isItemSelected: function(index) {
                    return $.inArray(index, this._selectedItemIndices) > -1
                },
                _optionChanged: function(args) {
                    if (this._cancelOptionChange)
                        return;
                    switch (args.name) {
                        case"items":
                            if (args.previousValue && args.previousValue.length > 0)
                                this._clearSelectedItems();
                            this.callBase(args);
                            break;
                        case"selectionMode":
                            this._invalidate();
                            break;
                        case"selectedIndex":
                        case"selectedItem":
                        case"selectedItems":
                            this._syncSelectionOptions(args.name);
                            this._normalizeSelectedItems();
                            this._updateSelectedItems();
                            break;
                        case"selectionRequired":
                            this._normalizeSelectedItems();
                            this._updateSelectedItems();
                            break;
                        case"selectionByClick":
                        case"onSelectionChanged":
                        case"onItemDeleting":
                        case"onItemDeleted":
                        case"onItemReordered":
                        case"itemSelectAction":
                        case"itemUnselectAction":
                            break;
                        default:
                            this.callBase(args)
                    }
                },
                _clearSelectedItems: function() {
                    this._selectedItemIndices = [];
                    this.option("selectedItems", [])
                },
                _setOptionSilent: function(name, value) {
                    this._cancelOptionChange = true;
                    this.option(name, value);
                    this._cancelOptionChange = false
                },
                _waitDeletingPrepare: function($itemElement) {
                    if ($itemElement.data(ITEM_DELETING_DATA_KEY))
                        return $.Deferred().resolve().promise();
                    $itemElement.data(ITEM_DELETING_DATA_KEY, true);
                    var deferred = $.Deferred(),
                        deletePromise = this._itemEventHandler($itemElement, "onItemDeleting", {}, {excludeValidators: ["disabled", "readOnly"]});
                    $.when(deletePromise).always($.proxy(function(value) {
                        var deletePromiseExists = !deletePromise,
                            deletePromiseResolved = !deletePromiseExists && deletePromise.state() === "resolved",
                            argumentsSpecified = !!arguments.length,
                            shouldDelete = deletePromiseExists || deletePromiseResolved && !argumentsSpecified || deletePromiseResolved && value;
                        $itemElement.data(ITEM_DELETING_DATA_KEY, false);
                        shouldDelete ? deferred.resolve() : deferred.reject()
                    }, this));
                    return deferred.promise()
                },
                _deleteItemFromDS: function($item) {
                    if (!this._dataSource)
                        return $.Deferred().resolve().promise();
                    var deferred = $.Deferred(),
                        disabledState = this.option("disabled"),
                        dataStore = this._dataSource.store();
                    this.option("disabled", true);
                    if (!dataStore.remove)
                        throw DX.Error("E1011");
                    dataStore.remove(dataStore.keyOf(this._getItemData($item))).done(function(key) {
                        if (key !== undefined)
                            deferred.resolve();
                        else
                            deferred.reject()
                    }).fail(function() {
                        deferred.reject()
                    });
                    deferred.always($.proxy(function() {
                        this.option("disabled", disabledState)
                    }, this));
                    return deferred
                },
                _tryRefreshLastPage: function() {
                    var deferred = $.Deferred();
                    if (this._isLastPage() || this.option("grouped"))
                        deferred.resolve();
                    else
                        this._refreshLastPage().done(function() {
                            deferred.resolve()
                        });
                    return deferred.promise()
                },
                _refreshLastPage: function() {
                    this._expectLastItemLoading();
                    return this._dataSource.load()
                },
                _updateSelectionAfterDelete: function(fromIndex) {
                    var itemIndex = $.inArray(fromIndex, this._selectedItemIndices);
                    if (itemIndex > -1)
                        this._selectedItemIndices.splice(itemIndex, 1);
                    this._editStrategy.updateSelectionAfterDelete(fromIndex);
                    this.option("selectedItems", this._editStrategy.fetchSelectedItems())
                },
                _simulateOptionChange: function(optionName) {
                    var optionValue = this.option(optionName);
                    if (optionValue instanceof DX.data.DataSource)
                        return;
                    this.fireEvent("optionChanged", [{
                            name: optionName,
                            fullName: optionName,
                            value: optionValue
                        }])
                },
                isItemSelected: function(itemElement) {
                    return this._isItemSelected(this._editStrategy.getNormalizedIndex(itemElement))
                },
                selectItem: function(itemElement) {
                    var itemIndex = this._editStrategy.getNormalizedIndex(itemElement);
                    if (itemIndex === -1)
                        return;
                    var itemSelectionIndex = $.inArray(itemIndex, this._selectedItemIndices);
                    if (itemSelectionIndex !== -1)
                        return;
                    if (this.option("selectionMode") === "single")
                        this.option("selectedItems", this._editStrategy.fetchSelectedItems([itemIndex]));
                    else {
                        var newSelectedIndices = this._selectedItemIndices.slice();
                        newSelectedIndices.push(itemIndex);
                        this.option("selectedItems", this._editStrategy.fetchSelectedItems(newSelectedIndices))
                    }
                },
                unselectItem: function(itemElement) {
                    var itemIndex = this._editStrategy.getNormalizedIndex(itemElement);
                    if (itemIndex === -1)
                        return;
                    var itemSelectionIndex = $.inArray(itemIndex, this._selectedItemIndices);
                    if (itemSelectionIndex === -1)
                        return;
                    var newSelectedIndices = this._selectedItemIndices.slice();
                    newSelectedIndices.splice(itemSelectionIndex, 1);
                    if (this.option("selectionRequired") && newSelectedIndices.length === 0)
                        return;
                    this.option("selectedItems", this._editStrategy.fetchSelectedItems(newSelectedIndices))
                },
                deleteItem: function(itemElement) {
                    var that = this,
                        deferred = $.Deferred(),
                        $item = this._editStrategy.getItemElement(itemElement),
                        index = this._editStrategy.getNormalizedIndex(itemElement),
                        changingOption = this._dataSource ? "dataSource" : "items",
                        itemResponseWaitClass = this._itemResponseWaitClass();
                    if (index > -1)
                        this._waitDeletingPrepare($item).done(function() {
                            $item.addClass(itemResponseWaitClass);
                            that._deleteItemFromDS($item).done(function() {
                                that._editStrategy.deleteItemAtIndex(index);
                                that._simulateOptionChange(changingOption);
                                that._updateSelectionAfterDelete(index);
                                that._itemEventHandler($item, "onItemDeleted", {}, {
                                    beforeExecute: function() {
                                        $item.detach()
                                    },
                                    excludeValidators: ["disabled", "readOnly"]
                                });
                                that._renderEmptyMessage();
                                that._tryRefreshLastPage().done(function() {
                                    deferred.resolveWith(that)
                                })
                            }).fail(function() {
                                $item.removeClass(itemResponseWaitClass);
                                deferred.rejectWith(that)
                            })
                        }).fail(function() {
                            deferred.rejectWith(that)
                        });
                    else
                        deferred.rejectWith(that);
                    return deferred.promise()
                },
                reorderItem: function(itemElement, toItemElement) {
                    var deferred = $.Deferred(),
                        that = this,
                        strategy = this._editStrategy,
                        $movingItem = strategy.getItemElement(itemElement),
                        $destinationItem = strategy.getItemElement(toItemElement),
                        movingIndex = strategy.getNormalizedIndex(itemElement),
                        destinationIndex = strategy.getNormalizedIndex(toItemElement),
                        changingOption;
                    var canMoveItems = movingIndex > -1 && destinationIndex > -1 && movingIndex !== destinationIndex;
                    if (canMoveItems)
                        if (this._dataSource) {
                            changingOption = "dataSource";
                            deferred.resolveWith(this)
                        }
                        else {
                            changingOption = "items";
                            deferred.resolveWith(this)
                        }
                    else
                        deferred.rejectWith(this);
                    return deferred.promise().done(function() {
                            $destinationItem[strategy.itemPlacementFunc(movingIndex, destinationIndex)]($movingItem);
                            var newSelectedItems = strategy.getSelectedItemsAfterReorderItem(movingIndex, destinationIndex);
                            strategy.moveItemAtIndexToIndex(movingIndex, destinationIndex);
                            that._selectedItemIndices = strategy.selectedItemIndices(newSelectedItems);
                            that.option("selectedItems", strategy.fetchSelectedItems());
                            that._simulateOptionChange(changingOption);
                            that._itemEventHandler($movingItem, "onItemReordered", {
                                fromIndex: strategy.getIndex(movingIndex),
                                toIndex: strategy.getIndex(destinationIndex)
                            }, {excludeValidators: ["disabled", "readOnly"]})
                        })
                }
            });
        ui.CollectionWidget = CollectionWidget
    })(jQuery, DevExpress);
    /*! Module core, file ui.collectionWidget.edit.strategy.js */
    (function($, DX, undefined) {
        var ui = DX.ui;
        ui.CollectionWidget.EditStrategy = DX.Class.inherit({
            ctor: function(collectionWidget) {
                this._collectionWidget = collectionWidget
            },
            getIndexByItemData: DX.abstract,
            getItemDataByIndex: DX.abstract,
            getNormalizedIndex: function(value) {
                if (this._isNormalisedItemIndex(value))
                    return value;
                if (this._isItemIndex(value))
                    return this._normalizeItemIndex(value);
                return this._getNormalizedItemIndex(value)
            },
            getIndex: function(value) {
                if (this._isNormalisedItemIndex(value))
                    return this._denormalizeItemIndex(value);
                if (this._isItemIndex(value))
                    return value;
                return this._denormalizeItemIndex(this._getNormalizedItemIndex(value))
            },
            getItemElement: function(value) {
                if (this._isNormalisedItemIndex(value))
                    return this._getItemByNormalizedIndex(value);
                if (this._isItemIndex(value))
                    return this._getItemByNormalizedIndex(this._normalizeItemIndex(value));
                return $(value)
            },
            deleteItemAtIndex: DX.abstract,
            updateSelectionAfterDelete: DX.abstract,
            fetchSelectedItems: DX.abstract,
            selectedItemIndices: DX.abstract,
            itemPlacementFunc: function(movingIndex, destinationIndex) {
                return this._itemsFromSameParent(movingIndex, destinationIndex) && movingIndex < destinationIndex ? "after" : "before"
            },
            moveItemAtIndexToIndex: DX.abstract,
            getSelectedItemsAfterReorderItem: function() {
                return this._collectionWidget.option("selectedItems")
            },
            _isNormalisedItemIndex: function(index) {
                return $.isNumeric(index)
            },
            _isItemIndex: DX.abstract,
            _getNormalizedItemIndex: DX.abstract,
            _normalizeItemIndex: DX.abstract,
            _denormalizeItemIndex: DX.abstract,
            _getItemByNormalizedIndex: DX.abstract,
            _itemsFromSameParent: DX.abstract
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.collectionWidget.edit.strategy.plain.js */
    (function($, DX, undefined) {
        var ui = DX.ui;
        ui.CollectionWidget.PlainEditStrategy = ui.CollectionWidget.EditStrategy.inherit({
            _getPlainItems: function() {
                return this._collectionWidget.option("items") || []
            },
            getIndexByItemData: function(itemData) {
                return $.inArray(itemData, this._getPlainItems())
            },
            getItemDataByIndex: function(index) {
                return this._getPlainItems()[index]
            },
            deleteItemAtIndex: function(index) {
                this._getPlainItems().splice(index, 1)
            },
            updateSelectionAfterDelete: function(fromIndex) {
                var selectedItemIndices = this._collectionWidget._selectedItemIndices;
                $.each(selectedItemIndices, function(i, index) {
                    if (index > fromIndex)
                        selectedItemIndices[i] -= 1
                })
            },
            fetchSelectedItems: function(indices) {
                indices = indices || this._collectionWidget._selectedItemIndices;
                var items = this._getPlainItems(),
                    selectedItems = [];
                $.each(indices, function(_, index) {
                    selectedItems.push(items[index])
                });
                return selectedItems
            },
            selectedItemIndices: function() {
                var selectedIndices = [],
                    items = this._getPlainItems(),
                    selected = this._collectionWidget.option("selectedItems");
                $.each(selected, function(_, selectedItem) {
                    var index = $.inArray(selectedItem, items);
                    if (index !== -1)
                        selectedIndices.push(index);
                    else
                        DX.log("W1002", selectedItem)
                });
                return selectedIndices
            },
            moveItemAtIndexToIndex: function(movingIndex, destinationIndex) {
                var items = this._getPlainItems(),
                    movedItemData = items[movingIndex];
                items.splice(movingIndex, 1);
                items.splice(destinationIndex, 0, movedItemData)
            },
            _isItemIndex: function(index) {
                return $.isNumeric(index)
            },
            _getNormalizedItemIndex: function(itemElement) {
                return this._collectionWidget._itemElements().index(itemElement)
            },
            _normalizeItemIndex: function(index) {
                return index
            },
            _denormalizeItemIndex: function(index) {
                return index
            },
            _getItemByNormalizedIndex: function(index) {
                return this._collectionWidget._itemElements().eq(index)
            },
            _itemsFromSameParent: function() {
                return true
            }
        })
    })(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 $("
").html(content).appendTo(DX.viewPort()).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($, DX) {
        $.extend(DX.ERROR_MESSAGES, {
            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",
            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"
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file numericTickManager.js */
    (function($, DX, undefined) {
        var core = DX.viz.core,
            utils = DX.utils,
            _isDefined = utils.isDefined,
            _adjustValue = utils.adjustValue,
            _math = Math,
            _abs = _math.abs,
            _ceil = _math.ceil,
            _floor = _math.floor,
            _noop = $.noop,
            MINOR_TICKS_COUNT_LIMIT = 200,
            DEFAULT_MINOR_NUMBER_MULTIPLIERS = [2, 4, 5, 8, 10];
        core.outOfScreen = {
            x: -1000,
            y: -1000
        };
        core.tickManager = {};
        core.tickManager.continuous = {
            _hasUnitBeginningTickCorrection: _noop,
            _removeBoundedOverlappingDates: _noop,
            _correctInterval: function(step) {
                this._tickInterval *= step
            },
            _correctMax: function(tickInterval) {
                this._max = this._adjustNumericTickValue(_ceil(this._max / tickInterval) * tickInterval, tickInterval, this._min)
            },
            _correctMin: function(tickInterval) {
                this._min = this._adjustNumericTickValue(_floor(this._min / tickInterval) * tickInterval, tickInterval, this._min)
            },
            _findBusinessDelta: function(min, max) {
                return _adjustValue(_abs(min - max))
            },
            _findTickIntervalForCustomTicks: function() {
                return _abs(this._customTicks[1] - this._customTicks[0])
            },
            _getBoundInterval: function() {
                var that = this,
                    boundCoef = that._options.boundCoef;
                return _isDefined(boundCoef) && isFinite(boundCoef) ? that._tickInterval * _abs(boundCoef) : that._tickInterval / 2
            },
            _getInterval: function(deltaCoef, numberMultipliers) {
                var interval = deltaCoef || this._getDeltaCoef(this._screenDelta, this._businessDelta, this._options.gridSpacingFactor),
                    multipliers = numberMultipliers || this._options.numberMultipliers,
                    factor,
                    result = 0,
                    newResult,
                    hasResult = false,
                    i;
                if (interval > 1.0)
                    for (factor = 1; !hasResult; factor *= 10)
                        for (i = 0; i < multipliers.length; i++) {
                            result = multipliers[i] * factor;
                            if (interval <= result) {
                                hasResult = true;
                                break
                            }
                        }
                else if (interval > 0) {
                    result = 1;
                    for (factor = 0.1; !hasResult; factor /= 10)
                        for (i = multipliers.length - 1; i >= 0; i--) {
                            newResult = multipliers[i] * factor;
                            if (interval > newResult) {
                                hasResult = true;
                                break
                            }
                            result = newResult
                        }
                }
                return _adjustValue(result)
            },
            _getMarginValue: function(min, max, margin) {
                return utils.applyPrecisionByMinDelta(min, margin, _abs(max - min) * margin)
            },
            _getDefaultMinorInterval: function(screenDelta, businessDelta) {
                var deltaCoef = this._getDeltaCoef(screenDelta, businessDelta, this._options.minorGridSpacingFactor),
                    multipliers = DEFAULT_MINOR_NUMBER_MULTIPLIERS,
                    i = multipliers.length - 1,
                    result;
                for (i; i >= 0; i--) {
                    result = businessDelta / multipliers[i];
                    if (deltaCoef <= result)
                        return _adjustValue(result)
                }
                return 0
            },
            _getMinorInterval: function(screenDelta, businessDelta) {
                var that = this,
                    options = that._options,
                    minorTickInterval = options.minorTickInterval,
                    minorTickCount = options.minorTickCount,
                    interval,
                    intervalsCount,
                    count;
                if (isFinite(minorTickInterval) && that._isTickIntervalCorrect(minorTickInterval, MINOR_TICKS_COUNT_LIMIT, businessDelta)) {
                    interval = minorTickInterval;
                    count = interval < businessDelta ? _ceil(businessDelta / interval) - 1 : 0
                }
                else if (_isDefined(minorTickCount)) {
                    intervalsCount = _isDefined(minorTickCount) ? minorTickCount + 1 : _floor(screenDelta / options.minorGridSpacingFactor);
                    count = intervalsCount - 1;
                    interval = count > 0 ? businessDelta / intervalsCount : 0
                }
                else {
                    interval = that._getDefaultMinorInterval(screenDelta, businessDelta);
                    count = interval < businessDelta ? _floor(businessDelta / interval) - 1 : 0
                }
                that._minorTickInterval = interval;
                that._minorTickCount = count
            },
            _getNextTickValue: function(value, tickInterval, isTickIntervalNegative) {
                tickInterval = _isDefined(isTickIntervalNegative) && isTickIntervalNegative ? -tickInterval : tickInterval;
                value += tickInterval;
                return this._adjustNumericTickValue(value, tickInterval, this._min)
            },
            _isTickIntervalValid: function(tickInterval) {
                return _isDefined(tickInterval) && isFinite(tickInterval) && tickInterval !== 0
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file datetimeTickManager.js */
    (function($, DX, undefined) {
        var core = DX.viz.core,
            utils = DX.utils,
            _isDefined = utils.isDefined,
            _convertDateUnitToMilliseconds = utils.convertDateUnitToMilliseconds,
            _correctDateWithUnitBeginning = utils.correctDateWithUnitBeginning,
            _dateToMilliseconds = utils.dateToMilliseconds,
            _convertMillisecondsToDateUnits = utils.convertMillisecondsToDateUnits,
            _math = Math,
            _abs = _math.abs,
            _ceil = _math.ceil,
            _floor = _math.floor,
            _round = _math.round,
            MINOR_TICKS_COUNT_LIMIT = 50,
            DEFAULT_DATETIME_MULTIPLIERS = {
                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]
            };
        core.tickManager.datetime = $.extend({}, core.tickManager.continuous, {
            _correctInterval: function(step) {
                var tickIntervalInMs = _dateToMilliseconds(this._tickInterval);
                this._tickInterval = _convertMillisecondsToDateUnits(tickIntervalInMs * step)
            },
            _correctMax: function(tickInterval) {
                var interval = _dateToMilliseconds(tickInterval);
                this._max = new Date(_ceil(this._max / interval) * interval)
            },
            _correctMin: function(tickInterval) {
                var interval = _dateToMilliseconds(tickInterval);
                this._min = new Date(_floor(this._min / interval) * interval);
                if (this._options.setTicksAtUnitBeginning)
                    _correctDateWithUnitBeginning(this._min, tickInterval)
            },
            _findTickIntervalForCustomTicks: function() {
                return _convertMillisecondsToDateUnits(_abs(this._customTicks[1] - this._customTicks[0]))
            },
            _getBoundInterval: function() {
                var that = this,
                    interval = that._tickInterval,
                    intervalInMs = _dateToMilliseconds(interval),
                    boundCoef = that._options.boundCoef,
                    boundIntervalInMs = _isDefined(boundCoef) && isFinite(boundCoef) ? intervalInMs * _abs(boundCoef) : intervalInMs / 2;
                return _convertMillisecondsToDateUnits(boundIntervalInMs)
            },
            _getInterval: function(deltaCoef) {
                var interval = deltaCoef || this._getDeltaCoef(this._screenDelta, this._businessDelta, this._options.gridSpacingFactor),
                    multipliers = this._options.numberMultipliers,
                    result = {},
                    factor,
                    i,
                    key,
                    specificMultipliers,
                    yearsCount;
                if (interval > 0 && interval < 1.0)
                    return {milliseconds: 1};
                if (interval === 0)
                    return 0;
                for (key in DEFAULT_DATETIME_MULTIPLIERS)
                    if (DEFAULT_DATETIME_MULTIPLIERS.hasOwnProperty(key)) {
                        specificMultipliers = DEFAULT_DATETIME_MULTIPLIERS[key];
                        for (i = 0; i < specificMultipliers.length; i++)
                            if (interval <= _convertDateUnitToMilliseconds(key, specificMultipliers[i])) {
                                result[key + 's'] = specificMultipliers[i];
                                return result
                            }
                    }
                for (factor = 1; ; factor *= 10)
                    for (i = 0; i < multipliers.length; i++) {
                        yearsCount = factor * multipliers[i];
                        if (interval <= _convertDateUnitToMilliseconds('year', yearsCount))
                            return {years: yearsCount}
                    }
                return 0
            },
            _getMarginValue: function(min, max, margin) {
                return _convertMillisecondsToDateUnits(_round(_abs(max - min) * margin))
            },
            _getMinorInterval: function(screenDelta, businessDelta) {
                var that = this,
                    options = that._options,
                    interval,
                    intervalInMs,
                    intervalsCount,
                    count;
                if (_isDefined(options.minorTickInterval) && that._isTickIntervalCorrect(options.minorTickInterval, MINOR_TICKS_COUNT_LIMIT, businessDelta)) {
                    interval = options.minorTickInterval;
                    intervalInMs = _dateToMilliseconds(interval);
                    count = intervalInMs < businessDelta ? _ceil(businessDelta / intervalInMs) - 1 : 0
                }
                else {
                    intervalsCount = _isDefined(options.minorTickCount) ? options.minorTickCount + 1 : _floor(screenDelta / options.minorGridSpacingFactor);
                    count = intervalsCount - 1;
                    interval = count > 0 ? _convertMillisecondsToDateUnits(businessDelta / intervalsCount) : 0
                }
                that._minorTickInterval = interval;
                that._minorTickCount = count
            },
            _getNextTickValue: function(value, tickInterval, isTickIntervalNegative, isTickIntervalWithPow, withCorrection) {
                var newValue = utils.addInterval(value, tickInterval, isTickIntervalNegative);
                if (this._options.setTicksAtUnitBeginning && withCorrection !== false) {
                    _correctDateWithUnitBeginning(newValue, tickInterval, true);
                    this._correctDateWithUnitBeginningCalled = true
                }
                return newValue
            },
            _getUnitBeginningMinorTicks: function(minorTicks) {
                var that = this,
                    ticks = that._ticks,
                    tickInterval = that._findMinorTickInterval(ticks[1], ticks[2]),
                    isTickIntervalNegative = true,
                    isTickIntervalWithPow = false,
                    needCorrectTick = false,
                    startTick = that._getNextTickValue(ticks[1], tickInterval, isTickIntervalNegative, isTickIntervalWithPow, needCorrectTick);
                if (that._isTickIntervalValid(tickInterval))
                    minorTicks = that._createTicks(minorTicks, tickInterval, startTick, ticks[0], isTickIntervalNegative, isTickIntervalWithPow, needCorrectTick);
                return minorTicks
            },
            _hasUnitBeginningTickCorrection: function() {
                var ticks = this._ticks;
                if (ticks.length < 3)
                    return false;
                return ticks[1] - ticks[0] !== ticks[2] - ticks[1] && this._options.setTicksAtUnitBeginning && this._options.minorTickCount
            },
            _isTickIntervalValid: function(tickInterval) {
                return _isDefined(tickInterval) && _dateToMilliseconds(tickInterval) !== 0
            },
            _removeBoundedOverlappingDates: function() {
                var dates = this._ticks;
                if (dates.length > 2 && this.getOverlappingBehavior().mode !== "stagger" && !this._areDisplayValuesValid(dates[0], dates[1]))
                    dates.splice(1, 1)
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file logarithmicTickManager.js */
    (function($, DX, undefined) {
        var core = DX.viz.core,
            utils = DX.utils,
            _isDefined = utils.isDefined,
            _addInterval = utils.addInterval,
            _adjustValue = utils.adjustValue,
            _getLog = utils.getLog,
            _raiseTo = utils.raiseTo,
            _math = Math,
            _abs = _math.abs,
            _ceil = _math.ceil,
            _floor = _math.floor,
            _round = _math.round;
        core.tickManager.logarithmic = $.extend({}, core.tickManager.continuous, {
            _correctMax: function() {
                var base = this._options.base;
                this._max = _adjustValue(_raiseTo(_ceil(_adjustValue(_getLog(this._max, base))), base))
            },
            _correctMin: function() {
                var base = this._options.base;
                this._min = _adjustValue(_raiseTo(_floor(_adjustValue(_getLog(this._min, base))), base))
            },
            _findBusinessDelta: function(min, max, isTickIntervalWithPow) {
                var delta;
                if (min <= 0 || max <= 0)
                    return 0;
                if (isTickIntervalWithPow === false)
                    delta = core.tickManager.continuous._findBusinessDelta(min, max);
                else
                    delta = _round(_abs(_getLog(min, this._options.base) - _getLog(max, this._options.base)));
                return delta
            },
            _findTickIntervalForCustomTicks: function() {
                return _adjustValue(_getLog(this._customTicks[1] / this._customTicks[0], this._options.base))
            },
            _getInterval: function(deltaCoef) {
                var interval = deltaCoef || this._getDeltaCoef(this._screenDelta, this._businessDelta, this._options.gridSpacingFactor),
                    multipliers = this._options.numberMultipliers,
                    factor,
                    result = 0,
                    hasResult = false,
                    i;
                if (interval !== 0)
                    for (factor = 1; !hasResult; factor *= 10)
                        for (i = 0; i < multipliers.length; i++) {
                            result = multipliers[i] * factor;
                            if (interval <= result) {
                                hasResult = true;
                                break
                            }
                        }
                return _adjustValue(result)
            },
            _getMinorInterval: function(screenDelta, businessDelta) {
                var that = this,
                    options = that._options,
                    minorTickCount = options.minorTickCount,
                    intervalsCount = _isDefined(minorTickCount) ? minorTickCount + 1 : _floor(screenDelta / options.minorGridSpacingFactor),
                    count = intervalsCount - 1,
                    interval = count > 0 ? businessDelta / intervalsCount : 0;
                that._minorTickInterval = interval;
                that._minorTickCount = count
            },
            _getMarginValue: function() {
                return null
            },
            _getNextTickValue: function(value, tickInterval, isTickIntervalNegative, isTickIntervalWithPow) {
                var that = this,
                    pow,
                    nextTickValue;
                tickInterval = _isDefined(isTickIntervalNegative) && isTickIntervalNegative ? -tickInterval : tickInterval;
                if (isTickIntervalWithPow === false)
                    nextTickValue = value + tickInterval;
                else {
                    pow = _addInterval(_getLog(value, that._options.base), tickInterval, that._min > that._max);
                    nextTickValue = _adjustValue(_raiseTo(pow, that._options.base))
                }
                return nextTickValue
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file tickOverlappingManager.js */
    (function($, DX, undefined) {
        var core = DX.viz.core,
            coreTickManager = core.tickManager,
            utils = DX.utils,
            _isDefined = utils.isDefined,
            _isNumber = utils.isNumber,
            _math = Math,
            _abs = _math.abs,
            _ceil = _math.ceil,
            _floor = _math.floor,
            _atan = _math.atan,
            _max = _math.max,
            _each = $.each,
            _map = $.map,
            _noop = $.noop,
            _isFunction = $.isFunction,
            SCREEN_DELTA_KOEF = 4,
            AXIS_STAGGER_OVERLAPPING_KOEF = 2,
            STAGGER = "stagger",
            ROTATE = "rotate",
            MIN_ARRANGEMENT_TICKS_COUNT = 2;
        function nextState(state) {
            switch (state) {
                case"overlap":
                    return STAGGER;
                case STAGGER:
                    return ROTATE;
                default:
                    return "end"
            }
        }
        function defaultGetTextFunc(value) {
            return value.toString()
        }
        coreTickManager.overlappingMethods = {};
        coreTickManager.overlappingMethods.base = {
            _applyOverlappingBehavior: function() {
                var that = this,
                    options = that._options,
                    overlappingBehavior = options && options.overlappingBehavior;
                if (overlappingBehavior && overlappingBehavior.mode !== "ignore") {
                    that._useAutoArrangement = true;
                    that._correctTicks();
                    if (overlappingBehavior.mode === "auto") {
                        that._applyAutoOverlappingBehavior();
                        that._useAutoArrangement = options.overlappingBehavior.isOverlapped
                    }
                    if (that._useAutoArrangement) {
                        if (overlappingBehavior.mode === STAGGER)
                            that._screenDelta *= AXIS_STAGGER_OVERLAPPING_KOEF;
                        that._applyAutoArrangement()
                    }
                }
            },
            _checkBoundedTicksOverlapping: function() {
                this._removeBoundedOverlappingDates();
                this._applyStartEndTicksCorrection()
            },
            getMaxLabelParams: function(ticks) {
                var that = this,
                    getText = that._options.getText || defaultGetTextFunc,
                    tickWithMaxLength,
                    tickTextWithMaxLength,
                    maxLength = 0,
                    bbox;
                ticks = ticks || that._getMajorTicks();
                if (!ticks.length)
                    return {
                            width: 0,
                            height: 0,
                            length: 0,
                            y: 0
                        };
                _each(ticks, function(_, item) {
                    var text = getText(item, that._options.labelOptions),
                        length = text.length;
                    if (maxLength < length) {
                        maxLength = length;
                        tickWithMaxLength = item;
                        tickTextWithMaxLength = text
                    }
                });
                bbox = that._getTextElementBbox(tickWithMaxLength, tickTextWithMaxLength);
                return {
                        width: bbox.width,
                        height: bbox.height,
                        y: bbox.y,
                        length: maxLength
                    }
            },
            _applyAutoArrangement: function() {
                var that = this,
                    options = that._options,
                    arrangementStep,
                    maxDisplayValueSize;
                if (that._useAutoArrangement) {
                    maxDisplayValueSize = that._getTicksSize();
                    arrangementStep = that._getAutoArrangementStep(maxDisplayValueSize);
                    if (arrangementStep > 1)
                        if (_isDefined(that._tickInterval) || _isDefined(that._customTicks))
                            that._ticks = that._getAutoArrangementTicks(arrangementStep);
                        else {
                            options.gridSpacingFactor = maxDisplayValueSize;
                            that._ticks = that._createTicks([], that._findTickInterval(), that._min, that._max)
                        }
                }
            },
            _getAutoArrangementTicks: function(step) {
                var that = this,
                    ticks = that._ticks,
                    ticksLength = ticks.length,
                    resultTicks = ticks,
                    decimatedTicks = that._decimatedTicks || [],
                    i;
                if (step > 1) {
                    resultTicks = [];
                    for (i = 0; i < ticksLength; i++)
                        if (i % step === 0)
                            resultTicks.push(ticks[i]);
                        else
                            decimatedTicks.push(ticks[i]);
                    that._correctInterval(step)
                }
                return resultTicks
            },
            _isOverlappedTicks: function(screenDelta) {
                return this._getAutoArrangementStep(this._getTicksSize(), screenDelta, -1) > 1
            },
            _areDisplayValuesValid: function(value1, value2) {
                var that = this,
                    options = that._options,
                    getText = options.getText || defaultGetTextFunc,
                    rotationAngle = options.overlappingBehavior && _isNumber(options.overlappingBehavior.rotationAngle) ? options.overlappingBehavior.rotationAngle : 0,
                    bBox1 = that._getTextElementBbox(value1, getText(value1, options.labelOptions)),
                    bBox2 = that._getTextElementBbox(value2, getText(value2, options.labelOptions)),
                    horizontalInverted = bBox1.x > bBox2.x,
                    verticalInverted = bBox1.y > bBox2.y,
                    hasHorizontalOverlapping,
                    hasVerticalOverlapping,
                    result;
                if (rotationAngle !== 0)
                    result = that._getDistanceByAngle(bBox1.height, rotationAngle) <= _abs(bBox2.x - bBox1.x);
                else {
                    hasHorizontalOverlapping = !horizontalInverted ? bBox1.x + bBox1.width > bBox2.x : bBox2.x + bBox2.width > bBox1.x;
                    hasVerticalOverlapping = !verticalInverted ? bBox1.y + bBox1.height > bBox2.y : bBox2.y + bBox2.height > bBox1.y;
                    result = !(hasHorizontalOverlapping && hasVerticalOverlapping)
                }
                return result
            }
        };
        coreTickManager.overlappingMethods.circular = $.extend({}, coreTickManager.overlappingMethods.base, {
            _correctTicks: _noop,
            _applyAutoOverlappingBehavior: function() {
                this._options.overlappingBehavior.isOverlapped = true
            },
            _getTextElementBbox: function(value, text) {
                var textOptions = $.extend({}, this._options.textOptions, {rotate: 0}),
                    delta = _isFunction(this._options.translate) ? this._options.translate(value) : {
                        x: 0,
                        y: 0
                    },
                    bbox;
                text = this._options.renderText(text, delta.x, delta.y).css(this._options.textFontStyles).attr(textOptions);
                bbox = text.getBBox();
                text.remove();
                return bbox
            },
            _getTicksSize: function() {
                return this.getMaxLabelParams(this._ticks)
            },
            _applyStartEndTicksCorrection: function() {
                var ticks = this._ticks,
                    lastTick = ticks[ticks.length - 1];
                if (ticks.length > 1 && !this._areDisplayValuesValid(ticks[0], lastTick))
                    ticks.pop()
            },
            _getAutoArrangementStep: function(maxDisplayValueSize) {
                var that = this,
                    options = that._options,
                    radius = options.circularRadius,
                    startAngle = options.circularStartAngle,
                    endAngle = options.circularEndAngle,
                    circleDelta = startAngle === endAngle ? 360 : _abs(startAngle - endAngle),
                    businessDelta = that._businessDelta || that._ticks.length,
                    degreesPerTick = that._tickInterval * circleDelta / businessDelta,
                    width = maxDisplayValueSize.width,
                    height = maxDisplayValueSize.height,
                    angle1 = _abs(2 * _atan(height / (2 * radius - width)) * 180 / _math.PI),
                    angle2 = _abs(2 * _atan(width / (2 * radius - height)) * 180 / _math.PI),
                    minAngleForTick = _max(angle1, angle2),
                    step = 1;
                if (degreesPerTick < minAngleForTick)
                    step = _ceil(minAngleForTick / degreesPerTick);
                return _max(1, step)
            }
        });
        coreTickManager.overlappingMethods.linear = $.extend({}, coreTickManager.overlappingMethods.base, {
            _correctTicks: function() {
                var getIntervalFunc = coreTickManager.continuous._getInterval,
                    arrangementStep;
                if (this._testingGetIntervalFunc)
                    getIntervalFunc = this._testingGetIntervalFunc;
                arrangementStep = _ceil(getIntervalFunc.call(this, this._getDeltaCoef(this._screenDelta * SCREEN_DELTA_KOEF, this._ticks.length))) || this._ticks.length;
                this._appliedArrangementStep = arrangementStep;
                this._ticks = this._getAutoArrangementTicks(arrangementStep)
            },
            _getTextElementBbox: function(value, text) {
                var textOptions = $.extend({}, this._options.textOptions, {rotate: 0}),
                    x = 0,
                    y = 0,
                    delta = _isFunction(this._options.translate) ? this._options.translate(value) : 0,
                    bbox;
                if (this._options.isHorizontal)
                    x += delta;
                else
                    y += delta;
                text = this._options.renderText(text, x, y).css(this._options.textFontStyles).attr(textOptions);
                bbox = text.getBBox();
                text.remove();
                return bbox
            },
            _applyStartEndTicksCorrection: _noop,
            _getAutoArrangementStep: function(maxDisplayValueSize, screenDelta, minArrangementTicksStep) {
                var that = this,
                    options = that._options,
                    requiredValuesCount,
                    textSpacing = options.textSpacing || 0,
                    addedSpacing = options.isHorizontal ? textSpacing : 0;
                screenDelta = screenDelta || that._screenDelta;
                minArrangementTicksStep = _isDefined(minArrangementTicksStep) ? minArrangementTicksStep : 1;
                if (options.getCustomAutoArrangementStep)
                    return options.getCustomAutoArrangementStep(that._ticks, options);
                if (maxDisplayValueSize > 0) {
                    requiredValuesCount = _floor((screenDelta + textSpacing) / (maxDisplayValueSize + addedSpacing));
                    requiredValuesCount = requiredValuesCount <= minArrangementTicksStep ? MIN_ARRANGEMENT_TICKS_COUNT : requiredValuesCount;
                    return _ceil((options.ticksCount || that._ticks.length) / requiredValuesCount)
                }
                return 1
            },
            _getOptimalRotationAngle: function() {
                var that = this,
                    options = that._options,
                    tick1 = that._ticks[0],
                    tick2 = that._ticks[1],
                    outOfScreen = core.outOfScreen,
                    textOptions = that._textOptions,
                    getText = options.getText || defaultGetTextFunc,
                    textFontStyles = options.textFontStyles,
                    svgElement1 = options.renderText(getText(tick1, options.labelOptions), outOfScreen.x + options.translate(tick1, !options.isHorizontal), outOfScreen.y).css(textFontStyles).attr(textOptions),
                    svgElement2 = options.renderText(getText(tick2, options.labelOptions), outOfScreen.x + options.translate(tick2, !options.isHorizontal), outOfScreen.y).css(textFontStyles).attr(textOptions),
                    bBox1 = svgElement1.getBBox(),
                    bBox2 = svgElement2.getBBox(),
                    angle = _math.asin((bBox1.height + options.textSpacing) / (bBox2.x - bBox1.x)) * 180 / Math.PI;
                svgElement1.remove();
                svgElement2.remove();
                return isNaN(angle) ? 90 : _ceil(angle)
            },
            _applyAutoOverlappingBehavior: function() {
                var that = this,
                    overlappingBehavior = that._options.overlappingBehavior,
                    screenDelta = that._screenDelta,
                    isOverlapped = false,
                    rotationAngle = null,
                    mode = null,
                    state = "overlap";
                while (state !== "end") {
                    isOverlapped = rotationAngle && rotationAngle !== 90 ? false : that._isOverlappedTicks(screenDelta);
                    state = nextState(isOverlapped ? state : null);
                    switch (state) {
                        case STAGGER:
                            screenDelta *= AXIS_STAGGER_OVERLAPPING_KOEF;
                            mode = state;
                            break;
                        case ROTATE:
                            rotationAngle = that._getOptimalRotationAngle();
                            screenDelta = that._screenDelta;
                            mode = state;
                            break
                    }
                }
                overlappingBehavior.isOverlapped = isOverlapped;
                overlappingBehavior.mode = mode;
                overlappingBehavior.rotationAngle = rotationAngle
            },
            _getDistanceByAngle: function(elementHeight, rotationAngle) {
                return elementHeight / _abs(_math.sin(rotationAngle * (_math.PI / 180)))
            },
            _getTicksSize: function() {
                var that = this,
                    options = that._options,
                    ticks = that._ticks,
                    ticksString,
                    rotationAngle = options.overlappingBehavior ? options.overlappingBehavior.rotationAngle : 0,
                    bBox,
                    result,
                    getText = options.getText || defaultGetTextFunc,
                    isRotate = _isNumber(rotationAngle) && rotationAngle !== 0,
                    joinNeeded = !isRotate && options.isHorizontal;
                if (ticks.length === 0)
                    return 0;
                ticksString = joinNeeded ? _map(ticks, function(tick) {
                    return getText(tick, options.labelOptions)
                }).join("\n") : getText(ticks[0], options.labelOptions);
                bBox = that._getTextElementBbox(ticksString, ticksString);
                result = isRotate ? that._getDistanceByAngle(bBox.height, rotationAngle) : options.isHorizontal ? bBox.width : bBox.height;
                return _ceil(result)
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file baseTickManager.js */
    (function($, DX, undefined) {
        var core = DX.viz.core,
            coreTickManager = core.tickManager,
            utils = DX.utils,
            _isDefined = utils.isDefined,
            _isNumber = utils.isNumber,
            _addInterval = utils.addInterval,
            _adjustValue = utils.adjustValue,
            _each = $.each,
            _map = $.map,
            _inArray = $.inArray,
            _noop = $.noop,
            DEFAULT_GRID_SPACING_FACTOR = 30,
            DEFAULT_MINOR_GRID_SPACING_FACTOR = 15,
            DEFAULT_NUMBER_MULTIPLIERS = [1, 2, 3, 5],
            TICKS_COUNT_LIMIT = 2000,
            MIN_ARRANGEMENT_TICKS_COUNT = 2;
        function concatAndSort(array1, array2) {
            var array = array1.concat(array2).sort(function(x, y) {
                    return _isDefined(x) && _isDefined(y) && x.valueOf() - y.valueOf()
                }),
                length = array.length,
                i;
            for (i = length - 1; i > 0; i--)
                if (_isDefined(array[i]) && _isDefined(array[i - 1]) && array[i].valueOf() === array[i - 1].valueOf())
                    array.splice(i, 1);
            return array
        }
        coreTickManager.discrete = $.extend({}, coreTickManager.continuous, {
            _getMinorTicks: _noop,
            _findTickInterval: _noop,
            _createTicks: function() {
                return []
            },
            _getMarginValue: _noop,
            _generateBounds: _noop,
            _correctMin: _noop,
            _correctMax: _noop,
            _findBusinessDelta: _noop,
            _addBoundedTicks: _noop,
            getFullTicks: function() {
                return this._customTicks
            },
            getMinorTicks: function() {
                return this._decimatedTicks || []
            },
            _findTickIntervalForCustomTicks: function() {
                return 1
            }
        });
        coreTickManager.TickManager = DX.Class.inherit({
            ctor: function(types, data, options) {
                options = options || {};
                this.update(types || {}, data || {}, options);
                this._initOverlappingMethods(options.overlappingBehaviorType)
            },
            dispose: function() {
                this._ticks = null;
                this._minorTicks = null;
                this._decimatedTicks = null;
                this._boundaryTicks = null;
                this._options = null
            },
            update: function(types, data, options) {
                this._updateOptions(options || {});
                this._min = data.min;
                this._updateTypes(types || {});
                this._updateData(data || {})
            },
            _updateMinMax: function(data) {
                var min = data.min || 0,
                    max = data.max || 0,
                    newMinMax = this._applyMinMaxMargins(min, max);
                this._min = this._originalMin = newMinMax.min;
                this._max = this._originalMax = newMinMax.max;
                this._updateBusinessDelta()
            },
            _updateBusinessDelta: function() {
                this._businessDelta = this._findBusinessDelta && this._findBusinessDelta(this._min, this._max)
            },
            _updateTypes: function(types) {
                var that = this,
                    axisType = that._validateAxisType(types.axisType),
                    dataType = that._validateDataType(types.dataType);
                that._resetMethods();
                this._axisType = axisType;
                this._dataType = dataType;
                this._initMethods()
            },
            _updateData: function(data) {
                data = $.extend({}, data);
                data.min = _isDefined(data.min) ? data.min : this._originalMin;
                data.max = _isDefined(data.max) ? data.max : this._originalMax;
                this._updateMinMax(data);
                this._customTicks = data.customTicks && data.customTicks.slice();
                this._customMinorTicks = data.customMinorTicks;
                this._screenDelta = data.screenDelta || 0
            },
            _updateOptions: function(options) {
                var opt;
                this._options = opt = options;
                this._useAutoArrangement = !!this._options.useTicksAutoArrangement;
                opt.gridSpacingFactor = opt.gridSpacingFactor || DEFAULT_GRID_SPACING_FACTOR;
                opt.minorGridSpacingFactor = opt.minorGridSpacingFactor || DEFAULT_MINOR_GRID_SPACING_FACTOR;
                opt.numberMultipliers = opt.numberMultipliers || DEFAULT_NUMBER_MULTIPLIERS
            },
            getTickBounds: function() {
                return {
                        minVisible: this._minBound,
                        maxVisible: this._maxBound
                    }
            },
            getTicks: function(withoutOverlappingBehavior) {
                var that = this,
                    options = that._options;
                that._ticks = that._getMajorTicks();
                that._checkLabelFormat();
                that._decimatedTicks = [];
                that._applyAutoArrangement();
                !withoutOverlappingBehavior && that._applyOverlappingBehavior();
                that._generateBounds();
                if (options.showMinorTicks)
                    that._minorTicks = that._customMinorTicks || that._getMinorTicks();
                that._addBoundedTicks();
                !withoutOverlappingBehavior && that._checkBoundedTicksOverlapping();
                return that._ticks
            },
            getMinorTicks: function() {
                var that = this,
                    decimatedTicks = that._decimatedTicks || [],
                    options = that._options || {},
                    hasDecimatedTicks = decimatedTicks.length,
                    hasMinorTickOptions = _isDefined(options.minorTickInterval) || _isDefined(options.minorTickCount),
                    hasCustomMinorTicks = that._customMinorTicks && that._customMinorTicks.length,
                    hasMinorTicks = options.showMinorTicks && (hasMinorTickOptions || hasCustomMinorTicks),
                    ticks = hasDecimatedTicks && !hasMinorTicks ? decimatedTicks : that._minorTicks || [];
                return concatAndSort(ticks, [])
            },
            getDecimatedTicks: function() {
                return concatAndSort(this._decimatedTicks || [], [])
            },
            getFullTicks: function() {
                return concatAndSort(this._ticks || [], this.getMinorTicks(), this._axisType)
            },
            getBoundaryTicks: function() {
                return concatAndSort(this._boundaryTicks || [], [])
            },
            getTickInterval: function() {
                return this._tickInterval
            },
            getMinorTickInterval: function() {
                return this._minorTickInterval
            },
            getOverlappingBehavior: function() {
                return this._options.overlappingBehavior
            },
            getOptions: function() {
                return this._options
            },
            _getMajorTicks: function() {
                var ticks;
                if (this._customTicks) {
                    ticks = this._customTicks.slice();
                    this._tickInterval = ticks.length > 1 ? this._findTickIntervalForCustomTicks() : 0
                }
                else
                    ticks = this._createTicks([], this._findTickInterval(), this._min, this._max);
                return ticks
            },
            _applyMargin: function(margin, min, max, isNegative) {
                var coef,
                    value = min;
                if (isFinite(margin)) {
                    coef = this._getMarginValue(min, max, margin);
                    if (coef)
                        value = this._getNextTickValue(min, coef, isNegative, false)
                }
                return value
            },
            _applyMinMaxMargins: function(min, max) {
                var options = this._options,
                    newMin = min > max ? max : min,
                    newMax = max > min ? max : min;
                this._minCorrectionEnabled = this._getCorrectionEnabled(min, "min");
                this._maxCorrectionEnabled = this._getCorrectionEnabled(max, "max");
                if (options && !options.stick) {
                    newMin = this._applyMargin(options.minValueMargin, min, max, true);
                    newMax = this._applyMargin(options.maxValueMargin, max, min, false)
                }
                return {
                        min: newMin,
                        max: newMax
                    }
            },
            _checkBoundedTickInArray: function(value, array) {
                var arrayValues = _map(array || [], function(item) {
                        return item.valueOf()
                    }),
                    minorTicksIndex = _inArray(value.valueOf(), arrayValues);
                if (minorTicksIndex !== -1)
                    array.splice(minorTicksIndex, 1)
            },
            _checkLabelFormat: function() {
                var options = this._options;
                if (this._dataType === "datetime" && !options.hasLabelFormat && this._ticks.length)
                    options.labelOptions.format = DX.formatHelper.getDateFormatByTicks(this._ticks)
            },
            _generateBounds: function() {
                var that = this,
                    interval = that._getBoundInterval(),
                    stick = that._options.stick,
                    minStickValue = that._options.minStickValue,
                    maxStickValue = that._options.maxStickValue,
                    minBound = that._minCorrectionEnabled && !stick ? that._getNextTickValue(that._min, interval, true) : that._originalMin,
                    maxBound = that._maxCorrectionEnabled && !stick ? that._getNextTickValue(that._max, interval) : that._originalMax;
                that._minBound = minBound < minStickValue ? minStickValue : minBound;
                that._maxBound = maxBound > maxStickValue ? maxStickValue : maxBound
            },
            _initOverlappingMethods: function(type) {
                this._initMethods(coreTickManager.overlappingMethods[type || "linear"])
            },
            _addBoundedTicks: function() {
                var that = this,
                    tickValues = _map(that._ticks, function(tick) {
                        return tick.valueOf()
                    }),
                    min = that._originalMin,
                    max = that._originalMax,
                    addMinMax = that._options.addMinMax || {};
                that._boundaryTicks = [];
                if (addMinMax.min && _inArray(min.valueOf(), tickValues) === -1) {
                    that._ticks.splice(0, 0, min);
                    that._boundaryTicks.push(min);
                    that._checkBoundedTickInArray(min, that._minorTicks);
                    that._checkBoundedTickInArray(min, that._decimatedTicks)
                }
                if (addMinMax.max && _inArray(max.valueOf(), tickValues) === -1) {
                    that._ticks.push(max);
                    that._boundaryTicks.push(max);
                    that._checkBoundedTickInArray(max, that._minorTicks);
                    that._checkBoundedTickInArray(max, that._decimatedTicks)
                }
            },
            _getCorrectionEnabled: function(value, marginSelector) {
                var options = this._options || {},
                    hasPercentStick = options.percentStick && value === 1,
                    hasValueMargin = options[marginSelector + "ValueMargin"];
                return !hasPercentStick && !hasValueMargin
            },
            _validateAxisType: function(type) {
                var defaultType = "continuous",
                    allowedTypes = {
                        continuous: true,
                        discrete: true,
                        logarithmic: true
                    };
                return allowedTypes[type] ? type : defaultType
            },
            _validateDataType: function(type) {
                var allowedTypes = {
                        numeric: true,
                        datetime: true,
                        string: true
                    };
                if (!allowedTypes[type])
                    type = _isDefined(this._min) ? this._getDataType(this._min) : "numeric";
                return type
            },
            _getDataType: function(value) {
                return utils.isDate(value) ? 'datetime' : 'numeric'
            },
            _getMethods: function() {
                var methods;
                if (this._axisType === "continuous")
                    methods = this._dataType === "datetime" ? coreTickManager.datetime : coreTickManager.continuous;
                else
                    methods = coreTickManager[this._axisType] || coreTickManager.continuous;
                return methods
            },
            _resetMethods: function() {
                var that = this,
                    methods = that._getMethods();
                _each(methods, function(name) {
                    if (that[name])
                        delete that[name]
                })
            },
            _initMethods: function(methods) {
                var that = this;
                methods = methods || that._getMethods();
                _each(methods, function(name, func) {
                    that[name] = func
                })
            },
            _getDeltaCoef: function(screenDelta, businessDelta, gridSpacingFactor) {
                var count;
                gridSpacingFactor = gridSpacingFactor || this._options.gridSpacingFactor;
                screenDelta = screenDelta || this._screenDelta;
                businessDelta = businessDelta || this._businessDelta;
                count = screenDelta / gridSpacingFactor;
                count = count <= 1 ? MIN_ARRANGEMENT_TICKS_COUNT : count;
                return businessDelta / count
            },
            _adjustNumericTickValue: function(value, interval, min) {
                return utils.isExponential(value) ? _adjustValue(value) : utils.applyPrecisionByMinDelta(min, interval, value)
            },
            _isTickIntervalCorrect: function(tickInterval, tickCountLimit, businessDelta) {
                var date;
                businessDelta = businessDelta || this._businessDelta;
                if (!_isNumber(tickInterval)) {
                    date = new Date;
                    tickInterval = _addInterval(date, tickInterval) - date;
                    if (!tickInterval)
                        return false
                }
                if (_isNumber(tickInterval))
                    if (tickInterval > 0 && businessDelta / tickInterval > tickCountLimit) {
                        if (this._options.incidentOccured)
                            this._options.incidentOccured('W2003')
                    }
                    else
                        return true;
                return false
            },
            _correctValue: function(valueTypeSelector, tickInterval, correctionMethod) {
                var that = this,
                    correctionEnabledSelector = "_" + valueTypeSelector + "CorrectionEnabled",
                    spaceCorrectionSelector = valueTypeSelector + "SpaceCorrection",
                    valueSelector = "_" + valueTypeSelector,
                    minStickValue = that._options.minStickValue,
                    maxStickValue = that._options.maxStickValue;
                if (that[correctionEnabledSelector]) {
                    if (that._options[spaceCorrectionSelector])
                        that[valueSelector] = that._getNextTickValue(that[valueSelector], tickInterval, valueTypeSelector === "min");
                    correctionMethod.call(this, tickInterval)
                }
                if (valueTypeSelector === "min")
                    that[valueSelector] = that[valueSelector] < minStickValue ? minStickValue : that[valueSelector];
                if (valueTypeSelector === "max")
                    that[valueSelector] = that[valueSelector] > maxStickValue ? maxStickValue : that[valueSelector]
            },
            _findTickInterval: function() {
                var that = this,
                    options = that._options,
                    tickInterval;
                tickInterval = that._isTickIntervalValid(options.tickInterval) && that._isTickIntervalCorrect(options.tickInterval, TICKS_COUNT_LIMIT) ? options.tickInterval : that._getInterval();
                if (that._isTickIntervalValid(tickInterval)) {
                    that._correctValue("min", tickInterval, that._correctMin);
                    that._correctValue("max", tickInterval, that._correctMax);
                    that._updateBusinessDelta()
                }
                that._tickInterval = tickInterval;
                return tickInterval
            },
            _findMinorTickInterval: function(firstTick, secondTick) {
                var that = this,
                    ticks = that._ticks,
                    intervals = that._options.stick ? ticks.length - 1 : ticks.length;
                if (intervals < 1)
                    intervals = 1;
                that._getMinorInterval(that._screenDelta / intervals, that._findBusinessDelta(firstTick, secondTick, false));
                return that._minorTickInterval
            },
            _createMinorTicks: function(ticks, firstTick, secondTick) {
                var that = this,
                    tickInterval = that._findMinorTickInterval(firstTick, secondTick),
                    isTickIntervalNegative = false,
                    isTickIntervalWithPow = false,
                    needCorrectTick = false,
                    startTick = that._getNextTickValue(firstTick, tickInterval, isTickIntervalNegative, isTickIntervalWithPow, needCorrectTick);
                if (that._isTickIntervalValid(tickInterval))
                    ticks = that._createCountedTicks(ticks, tickInterval, startTick, secondTick, that._minorTickCount, isTickIntervalNegative, isTickIntervalWithPow, needCorrectTick);
                return ticks
            },
            _getMinorTicks: function() {
                var that = this,
                    minorTicks = [],
                    ticks = that._ticks,
                    ticksLength = ticks.length,
                    hasUnitBeginningTick = that._hasUnitBeginningTickCorrection(),
                    i = hasUnitBeginningTick ? 1 : 0;
                if (ticks.length) {
                    minorTicks = that._getBoundedMinorTicks(minorTicks, that._minBound, ticks[0], true);
                    if (hasUnitBeginningTick)
                        minorTicks = that._getUnitBeginningMinorTicks(minorTicks);
                    for (i; i < ticksLength - 1; i++)
                        minorTicks = that._createMinorTicks(minorTicks, ticks[i], ticks[i + 1]);
                    minorTicks = that._getBoundedMinorTicks(minorTicks, that._maxBound, ticks[ticksLength - 1])
                }
                else
                    minorTicks = that._createMinorTicks(minorTicks, that._minBound, that._maxBound);
                return minorTicks
            },
            _createCountedTicks: function(ticks, tickInterval, min, max, count, isTickIntervalWithPow, needMax) {
                var value = min,
                    i;
                for (i = 0; i < count; i++) {
                    if (!(needMax === false && value.valueOf() === max.valueOf()))
                        ticks.push(value);
                    value = this._getNextTickValue(value, tickInterval, false, isTickIntervalWithPow, false)
                }
                return ticks
            },
            _createTicks: function(ticks, tickInterval, min, max, isTickIntervalNegative, isTickIntervalWithPow, withCorrection) {
                var that = this,
                    value = min,
                    newValue = min,
                    leftBound,
                    rightBound,
                    boundedRule;
                if (that._isTickIntervalValid(tickInterval)) {
                    boundedRule = min - max < 0;
                    do {
                        value = newValue;
                        if (that._options.stick) {
                            if (value >= that._originalMin && value <= that._originalMax)
                                ticks.push(value)
                        }
                        else
                            ticks.push(value);
                        newValue = that._getNextTickValue(value, tickInterval, isTickIntervalNegative, isTickIntervalWithPow, withCorrection);
                        if (value.valueOf() === newValue.valueOf())
                            break;
                        leftBound = newValue - min >= 0;
                        rightBound = max - newValue >= 0
                    } while (boundedRule === leftBound && boundedRule === rightBound)
                }
                else
                    ticks.push(value);
                return ticks
            },
            _getBoundedMinorTicks: function(minorTicks, boundedTick, tick, isNegative) {
                var that = this,
                    needCorrectTick = false,
                    nextTick = that._tickInterval ? this._getNextTickValue(tick, that._tickInterval, isNegative, true, needCorrectTick) : boundedTick,
                    tickInterval = that._findMinorTickInterval(tick, nextTick),
                    isTickIntervalCorrect = that._isTickIntervalCorrect(tickInterval, TICKS_COUNT_LIMIT, that._findBusinessDelta(tick, boundedTick, false)),
                    startTick,
                    endTick,
                    boundedTickValue = boundedTick.valueOf();
                if (isTickIntervalCorrect && that._isTickIntervalValid(tickInterval) && that._minorTickCount > 0) {
                    if (isNegative) {
                        if (tick.valueOf() <= boundedTickValue)
                            return minorTicks;
                        while (nextTick.valueOf() < boundedTickValue)
                            nextTick = this._getNextTickValue(nextTick, tickInterval, false, false, needCorrectTick);
                        startTick = nextTick;
                        endTick = that._getNextTickValue(tick, tickInterval, true, false, false)
                    }
                    else {
                        startTick = that._getNextTickValue(tick, tickInterval, false, false, false);
                        endTick = boundedTick
                    }
                    minorTicks = that._createTicks(minorTicks, tickInterval, startTick, endTick, false, false, needCorrectTick)
                }
                return minorTicks
            },
            getTypes: function() {
                return {
                        axisType: this._axisType,
                        dataType: this._dataType
                    }
            },
            getData: function() {
                return {
                        min: this._min,
                        max: this._max,
                        customTicks: this._customTicks,
                        customMinorTicks: this._customMinorTicks,
                        screenDelta: this._screenDelta
                    }
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file numericTranslator.js */
    (function($, DX, undefined) {
        var utils = DX.utils,
            isDefined = utils.isDefined,
            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 that._conversionValue(that._calculateProjection((bp - canvasOptions.rangeMinVisible) * canvasOptions.ratioOfCanvasRange))
            },
            untranslate: function(pos, _directionOffset, enableOutOfCanvas) {
                var canvasOptions = this._canvasOptions,
                    startPoint = canvasOptions.startPoint;
                if (!enableOutOfCanvas && (pos < startPoint || pos > canvasOptions.endPoint) || !isDefined(canvasOptions.rangeMin) || !isDefined(canvasOptions.rangeMax))
                    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)))
            },
            _getValue: function(val) {
                return val
            },
            zoom: function(translate, scale) {
                var that = this,
                    canvasOptions = that._canvasOptions,
                    startPoint = canvasOptions.startPoint,
                    endPoint = canvasOptions.endPoint,
                    newStart = (startPoint + translate) / scale,
                    newEnd = (endPoint + translate) / scale,
                    minPoint = Math.min(that.translate(that._getValue(canvasOptions.rangeMin)), that.translate(that._getValue(canvasOptions.rangeMax))),
                    maxPoint = Math.max(that.translate(that._getValue(canvasOptions.rangeMin)), that.translate(that._getValue(canvasOptions.rangeMax)));
                if (minPoint > newStart) {
                    newEnd -= newStart - minPoint;
                    newStart = minPoint
                }
                if (maxPoint < newEnd) {
                    newStart -= newEnd - maxPoint;
                    newEnd = maxPoint
                }
                if (maxPoint - minPoint < newEnd - newStart) {
                    newStart = minPoint;
                    newEnd = maxPoint
                }
                translate = (endPoint - startPoint) * newStart / (newEnd - newStart) - startPoint;
                scale = (startPoint + translate) / newStart || 1;
                return {
                        min: that.untranslate(newStart, undefined, true),
                        max: that.untranslate(newEnd, undefined, true),
                        translate: translate,
                        scale: scale
                    }
            },
            getMinScale: function(zoom) {
                return zoom ? 1.1 : 0.9
            },
            getScale: function(val1, val2) {
                var canvasOptions = this._canvasOptions;
                val1 = isDefined(val1) ? val1 : canvasOptions.rangeMin;
                val2 = isDefined(val2) ? val2 : canvasOptions.rangeMax;
                return (canvasOptions.rangeMax - canvasOptions.rangeMin) / Math.abs(val1 - val2)
            }
        }
    })(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() {
                var result = numericTranslator.untranslate.apply(this, arguments);
                return result === null ? result : new Date(result)
            },
            _getValue: numericTranslator._getValue,
            getInterval: numericTranslator.getInterval,
            zoom: numericTranslator.zoom,
            getMinScale: numericTranslator.getMinScale,
            getScale: numericTranslator.getScale
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file categoryTranslator.js */
    (function($, DX, undefined) {
        var isDefined = DX.utils.isDefined,
            round = Math.round;
        DX.viz.core.categoryTranslatorFunctions = {
            translate: function(category, directionOffset) {
                var that = this,
                    canvasOptions = that._canvasOptions,
                    categoryRecord = that._categoriesToPoints[category],
                    stickDelta,
                    specialValue = that.translateSpecialCase(category),
                    startPointIndex = canvasOptions.startPointIndex || 0,
                    stickInterval = that._businessRange.stick ? 0 : 0.5;
                if (isDefined(specialValue))
                    return specialValue;
                if (!categoryRecord)
                    return null;
                directionOffset = directionOffset || 0;
                directionOffset = canvasOptions.invert ? -directionOffset : directionOffset;
                stickDelta = categoryRecord.index + stickInterval - startPointIndex + directionOffset * 0.5;
                return round(canvasOptions.startPoint + canvasOptions.interval * stickDelta)
            },
            untranslate: function(pos, directionOffset, enableOutOfCanvas) {
                var that = this,
                    canvasOptions = that._canvasOptions,
                    startPoint = canvasOptions.startPoint,
                    categories = that.visibleCategories || that._categories,
                    categoriesLength = categories.length,
                    result = 0,
                    stickInterval = that._businessRange.stick ? 0.5 : 0;
                if (!enableOutOfCanvas && (pos < startPoint || pos > canvasOptions.endPoint))
                    return null;
                directionOffset = directionOffset || 0;
                result = round((pos - startPoint) / canvasOptions.interval + stickInterval - 0.5 - directionOffset * 0.5);
                if (categoriesLength === result)
                    result--;
                if (result === -1)
                    result = 0;
                if (canvasOptions.invert)
                    result = categoriesLength - result - 1;
                return categories[result]
            },
            getInterval: function() {
                return this._canvasOptions.interval
            },
            zoom: function(translate, scale) {
                var that = this,
                    canvasOptions = that._canvasOptions,
                    interval = canvasOptions.interval * scale,
                    translateCaltegories = translate / interval,
                    stick = that._businessRange.stick,
                    startCategoryIndex = parseInt((canvasOptions.startPointIndex || 0) + translateCaltegories + 0.5),
                    categoriesLength = parseInt(canvasOptions.canvasLength / interval + (stick ? 1 : 0)) || 1,
                    endCategoryIndex,
                    newVisibleCategories,
                    categories = that._categories,
                    newInterval;
                canvasOptions.invert && (categories = categories.slice().reverse());
                if (startCategoryIndex < 0)
                    startCategoryIndex = 0;
                endCategoryIndex = startCategoryIndex + categoriesLength;
                if (endCategoryIndex > categories.length) {
                    endCategoryIndex = categories.length;
                    startCategoryIndex = endCategoryIndex - categoriesLength;
                    if (startCategoryIndex < 0)
                        startCategoryIndex = 0
                }
                newVisibleCategories = categories.slice(parseInt(startCategoryIndex), parseInt(endCategoryIndex));
                newInterval = that._getDiscreteInterval(newVisibleCategories.length, canvasOptions);
                scale = newInterval / canvasOptions.interval;
                translate = that.translate(newVisibleCategories[0]) * scale - (canvasOptions.startPoint + (stick ? 0 : newInterval / 2));
                return {
                        min: !canvasOptions.invert ? newVisibleCategories[0] : newVisibleCategories[newVisibleCategories.length - 1],
                        max: !canvasOptions.invert ? newVisibleCategories[newVisibleCategories.length - 1] : newVisibleCategories[0],
                        translate: translate,
                        scale: scale
                    }
            },
            getMinScale: function(zoom) {
                var that = this,
                    canvasOptions = that._canvasOptions,
                    categoriesLength = (that.visibleCategories || that._categories).length;
                categoriesLength += (parseInt(categoriesLength * 0.1) || 1) * (zoom ? -2 : 2);
                return canvasOptions.canvasLength / (Math.max(categoriesLength, 1) * canvasOptions.interval)
            },
            getScale: function(min, max) {
                var that = this,
                    canvasOptions = that._canvasOptions,
                    visibleArea = that.getCanvasVisibleArea(),
                    stickOffset = !that._businessRange.stick && 1,
                    minPoint = that.translate(min, -stickOffset),
                    maxPoint = that.translate(max, +stickOffset);
                if (!isDefined(minPoint))
                    minPoint = canvasOptions.invert ? visibleArea.max : visibleArea.min;
                if (!isDefined(maxPoint))
                    maxPoint = canvasOptions.invert ? visibleArea.min : visibleArea.max;
                return that.canvasLength / Math.abs(maxPoint - minPoint)
            }
        }
    })(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() {
                var result = numericTranslator.untranslate.apply(this, arguments);
                return result === null ? result : raiseTo(result, this._businessRange.base)
            },
            getInterval: numericTranslator.getInterval,
            _getValue: function(value) {
                return Math.pow(this._canvasOptions.base, value)
            },
            zoom: numericTranslator.zoom,
            getMinScale: numericTranslator.getMinScale,
            getScale: function(val1, val2) {
                var base = this._businessRange.base;
                val1 = utils.isDefined(val1) ? getLog(val1, base) : undefined;
                val2 = utils.isDefined(val2) ? getLog(val2, base) : undefined;
                return numericTranslator.getScale.call(this, val1, val2)
            }
        }
    })(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,
            isDefined = utils.isDefined,
            _abs = Math.abs,
            CANVAS_PROP = ["width", "height", "left", "top", "bottom", "right"],
            NUMBER_EQUALITY_CORRECTION = 1,
            DATETIME_EQUALITY_CORRECTION = 60000,
            _noop = $.noop,
            _Translator2d;
        var validateCanvas = function(canvas) {
                $.each(CANVAS_PROP, function(_, prop) {
                    canvas[prop] = parseInt(canvas[prop]) || 0
                });
                return canvas
            };
        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
            };
        _Translator2d = core.Translator2D = function(businessRange, canvas, options) {
            this.update(businessRange, canvas, options)
        };
        _Translator2d.prototype = {
            constructor: _Translator2d,
            reinit: function() {
                var that = this,
                    range = that._businessRange,
                    categories = range.categories || [],
                    script = {},
                    canvasOptions = that._prepareCanvasOptions(),
                    visibleCategories = utils.getCategoriesInfo(categories, range.minVisible, range.maxVisible).categories,
                    categoriesLength = (visibleCategories || categories).length;
                switch (range.axisType) {
                    case"logarithmic":
                        script = core.logarithmicTranslatorFunctions;
                        break;
                    case"discrete":
                        script = core.categoryTranslatorFunctions;
                        that._categories = categories;
                        canvasOptions.interval = that._getDiscreteInterval(range.addSpiderCategory ? categoriesLength + 1 : categoriesLength, canvasOptions);
                        that._categoriesToPoints = makeCategoriesToPoints(categories, canvasOptions.invert);
                        if (visibleCategories && visibleCategories.length) {
                            canvasOptions.startPointIndex = that._categoriesToPoints[visibleCategories[canvasOptions.invert ? visibleCategories.length - 1 : 0]].index;
                            that.visibleCategories = visibleCategories
                        }
                        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;
                that.zoom = script.zoom;
                that.getMinScale = script.getMinScale;
                that._getValue = script._getValue;
                that.getScale = script.getScale;
                that._conversionValue = that._options.conversionValue ? function(value) {
                    return value
                } : function(value) {
                    return Math.round(value)
                }
            },
            _getDiscreteInterval: function(categoriesLength, canvasOptions) {
                var correctedCategoriesCount = categoriesLength - (this._businessRange.stick ? 1 : 0);
                return correctedCategoriesCount > 0 ? canvasOptions.canvasLength / correctedCategoriesCount : canvasOptions.canvasLength
            },
            _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 (range.axisType === 'logarithmic') {
                    maxVisible = getLog(maxVisible, base);
                    minVisible = getLog(minVisible, base);
                    min = getLog(min, base);
                    max = getLog(max, base)
                }
                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
                    }
                }
                return {
                        base: base,
                        rangeMin: min,
                        rangeMax: max,
                        rangeMinVisible: minVisible,
                        rangeMaxVisible: maxVisible
                    }
            },
            _prepareCanvasOptions: function() {
                var that = this,
                    businessRange = that._businessRange,
                    canvasOptions = that._canvasOptions = that._getCanvasBounds(businessRange),
                    length,
                    canvas = that._canvas;
                if (that._options.direction === "horizontal") {
                    canvasOptions.startPoint = canvas.left;
                    length = canvas.width;
                    canvasOptions.endPoint = canvas.width - canvas.right;
                    canvasOptions.invert = businessRange.invert
                }
                else {
                    canvasOptions.startPoint = canvas.top;
                    length = canvas.height;
                    canvasOptions.endPoint = canvas.height - 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()
            },
            update: function(businessRange, canvas, options) {
                var that = this;
                that._options = $.extend(that._options || {}, options);
                that._canvas = validateCanvas(canvas);
                that.updateBusinessRange(businessRange)
            },
            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 = canvasOptions.invert ? endPoint : startPoint;
                        break;
                    case"canvas_position_end":
                        result = canvasOptions.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
            },
            getVisibleCategories: function() {
                return this.visibleCategories
            },
            getMinBarSize: function(minBarSize) {
                var visibleArea = this.getCanvasVisibleArea(),
                    minValue = this.untranslate(visibleArea.min + minBarSize);
                return _abs(this.untranslate(visibleArea.min) - (!isDefined(minValue) ? this.untranslate(visibleArea.max) : minValue))
            },
            translate: _noop,
            untranslate: _noop,
            getInterval: _noop,
            zoom: _noop,
            getMinScale: _noop
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file polarTranslator.js */
    (function($, DX, undefined) {
        var utils = DX.utils,
            SHIFT_ANGLE = 90,
            _round = Math.round;
        function PolarTranslator(businessRange, canvas, options) {
            var that = this;
            that._argCanvas = {
                left: 0,
                right: 0,
                width: this._getAngle()
            };
            that._valCanvas = {
                left: 0,
                right: 0
            };
            that.canvas = canvas;
            that._init();
            that._arg = new DX.viz.core.Translator2D(businessRange.arg, that._argCanvas, {
                direction: "horizontal",
                conversionValue: true
            });
            that._val = new DX.viz.core.Translator2D(businessRange.val, that._valCanvas, {direction: "horizontal"});
            that._businessRange = businessRange;
            that.startAngle = utils.isNumber(options.startAngle) ? options.startAngle : 0
        }
        PolarTranslator.prototype = {
            constructor: PolarTranslator,
            _init: function() {
                var canvas = this.canvas;
                this._setCoords({
                    x: canvas.left + (canvas.width - canvas.right - canvas.left) / 2,
                    y: canvas.top + (canvas.height - canvas.top - canvas.bottom) / 2,
                    r: Math.min(canvas.width - canvas.left - canvas.right, canvas.height - canvas.top - canvas.bottom) / 2
                });
                this._valCanvas.width = this._rad
            },
            reinit: function() {
                this._init();
                this._arg.reinit();
                this._val.reinit()
            },
            _setCoords: function(coord) {
                this._x0 = coord.x;
                this._y0 = coord.y;
                this._rad = coord.r < 0 ? 0 : coord.r
            },
            getBusinessRange: function() {
                return this._businessRange
            },
            translate: function(arg, val, offsets) {
                var that = this,
                    argTranslate = that._arg.translate(arg, offsets && offsets[0]),
                    radius = that._val.translate(val, offsets && offsets[1]),
                    angle = utils.isDefined(argTranslate) ? argTranslate + that.startAngle - SHIFT_ANGLE : null,
                    cossin = utils.getCosAndSin(angle),
                    x,
                    y;
                y = _round(that._y0 + radius * cossin.sin);
                x = _round(that._x0 + radius * cossin.cos);
                return {
                        x: x,
                        y: y,
                        angle: angle,
                        radius: radius
                    }
            },
            getValLength: function() {
                return this._rad
            },
            getCenter: function() {
                return {
                        x: this._x0,
                        y: this._y0
                    }
            },
            getBaseAngle: function() {
                return this.startAngle - SHIFT_ANGLE
            },
            getInterval: function() {
                return this._arg.getInterval()
            },
            getValInterval: function() {
                return this._val.getInterval()
            },
            _getAngle: function() {
                return 360
            },
            getStartAngle: function() {
                return this.startAngle
            },
            getComponent: function(type) {
                var that = this,
                    translator = this["_" + type];
                translator.getRadius = function() {
                    return that.getValLength()
                };
                translator.getCenter = function() {
                    return that.getCenter()
                };
                translator.getStartAngle = function() {
                    return that.getStartAngle()
                };
                return translator
            },
            _untranslate: function(x, y) {
                var radius = utils.getDistance(this._x0, this._y0, x, y),
                    angle = Math.atan2(y - this._y0, x - this._x0);
                return {
                        r: radius,
                        phi: angle
                    }
            },
            untranslate: function(x, y) {
                var pos = this._untranslate(x, y);
                pos.phi = _round(utils.normalizeAngle(pos.phi * 180 / Math.PI));
                pos.r = _round(pos.r);
                return pos
            },
            getVisibleCategories: $.noop,
            getCanvasVisibleArea: function() {
                return {}
            },
            getMinBarSize: function(minBarSize) {
                return this._val.getMinBarSize(minBarSize)
            }
        };
        DX.viz.core.PolarTranslator = PolarTranslator
    })(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 layoutElement.js */
    (function($, DX, undefined) {
        var core = DX.viz.core,
            _round = Math.round;
        var _splitPair = DX.utils.splitPair;
        var defaultPosition = ["center", "center"],
            defaultOffset = [0, 0];
        var getAlignFactor = function(align) {
                switch (align) {
                    case"center":
                        return 0.5;
                    case"right":
                    case"bottom":
                        return 1;
                    default:
                        return 0
                }
            };
        function WrapperLayoutElement(renderElement, bbox) {
            this._renderElement = renderElement;
            this._cacheBBox = bbox
        }
        WrapperLayoutElement.prototype = {
            position: function(options) {
                var that = this,
                    ofBBox = options.of.getBBox ? options.of.getBBox() : options.of,
                    myBBox = this.getBBox(),
                    at = _splitPair(options.at) || defaultPosition,
                    my = _splitPair(options.my) || defaultPosition,
                    offset = _splitPair(options.offset) || defaultOffset,
                    shiftX = -getAlignFactor(my[0]) * myBBox.width + ofBBox.x - myBBox.x + getAlignFactor(at[0]) * ofBBox.width + parseInt(offset[0]),
                    shiftY = -getAlignFactor(my[1]) * myBBox.height + ofBBox.y - myBBox.y + getAlignFactor(at[1]) * ofBBox.height + parseInt(offset[1]);
                that._renderElement.move(_round(shiftX), _round(shiftY))
            },
            getBBox: function() {
                return this._cacheBBox || this._renderElement.getBBox()
            },
            draw: function(){}
        };
        core.WrapperLayoutElement = WrapperLayoutElement
    })(jQuery, DevExpress);
    /*! Module viz-core, file themes.js */
    (function(DX, $, undefined) {
        var themes = {},
            themesMapping = {},
            themesSchemeMapping = {},
            _extend = $.extend,
            _each = $.each,
            currentThemeName = null,
            nextCacheUid = 0,
            widgetsCache = {};
        function normalizeName(name) {
            return name ? String(name).toLowerCase() : null
        }
        function findTheme(themeName) {
            var name = normalizeName(themeName);
            return themes[name] || themes[themesMapping[name] || currentThemeName]
        }
        function findThemeNameByName(name, scheme) {
            return themesMapping[name + '.' + scheme] || themesSchemeMapping[name + '.' + scheme] || themesMapping[name]
        }
        function findThemeNameByPlatform(platform, version, scheme) {
            return findThemeNameByName(platform + version, scheme) || findThemeNameByName(platform, scheme)
        }
        function currentTheme(themeName, colorScheme) {
            if (!arguments.length)
                return currentThemeName;
            var scheme = normalizeName(colorScheme);
            currentThemeName = (themeName && themeName.platform ? findThemeNameByPlatform(normalizeName(themeName.platform), themeName.version, scheme) : findThemeNameByName(normalizeName(themeName), scheme)) || currentThemeName;
            return this
        }
        function getThemeInfo(themeName, splitter) {
            var k = themeName.indexOf(splitter);
            return k > 0 ? {
                    name: themeName.substring(0, k),
                    scheme: themeName.substring(k + 1)
                } : null
        }
        function registerThemeName(themeName, targetThemeName) {
            var themeInfo = getThemeInfo(themeName, '.') || getThemeInfo(themeName, '-') || {name: themeName},
                name = themeInfo.name,
                scheme = themeInfo.scheme;
            if (scheme) {
                themesMapping[name] = themesMapping[name] || targetThemeName;
                themesMapping[name + '.' + scheme] = themesMapping[name + '-' + scheme] = targetThemeName
            }
            else
                themesMapping[name] = targetThemeName
        }
        function registerTheme(theme, baseThemeName) {
            var themeName = normalizeName(theme && theme.name);
            if (themeName) {
                registerThemeName(themeName, themeName);
                themes[themeName] = _extend(true, {}, findTheme(baseThemeName), patchTheme(theme))
            }
        }
        function registerThemeAlias(alias, theme) {
            registerThemeName(normalizeName(alias), normalizeName(theme))
        }
        function registerThemeSchemeAlias(from, to) {
            themesSchemeMapping[from] = to
        }
        function mergeScalar(target, field, source, sourceValue) {
            var _value = source ? source[field] : sourceValue;
            if (_value !== undefined && target[field] === undefined)
                target[field] = _value
        }
        function mergeObject(target, field, source, sourceValue) {
            var _value = source ? source[field] : sourceValue;
            if (_value !== undefined)
                target[field] = _extend(true, {}, _value, target[field])
        }
        function patchTheme(theme) {
            theme = _extend(true, {
                loadingIndicator: {font: {}},
                legend: {
                    font: {},
                    border: {}
                },
                title: {font: {}},
                tooltip: {font: {}},
                "chart:common": {},
                "chart:common:axis": {
                    grid: {},
                    minorGrid: {},
                    tick: {},
                    minorTick: {},
                    title: {font: {}},
                    label: {font: {}}
                },
                chart: {commonSeriesSettings: {candlestick: {}}},
                pie: {},
                polar: {},
                gauge: {scale: {
                        majorTick: {},
                        minorTick: {},
                        label: {font: {}}
                    }},
                barGauge: {},
                map: {background: {}},
                rangeSelector: {
                    scale: {label: {font: {}}},
                    chart: {}
                },
                sparkline: {},
                bullet: {}
            }, theme);
            mergeScalar(theme.loadingIndicator, "backgroundColor", theme);
            mergeScalar(theme.chart.commonSeriesSettings.candlestick, "innerColor", null, theme.backgroundColor);
            mergeScalar(theme.map.background, "color", null, theme.backgroundColor);
            mergeScalar(theme.title.font, "color", null, theme.primaryTitleColor);
            mergeScalar(theme.legend.font, "color", null, theme.secondaryTitleColor);
            mergeScalar(theme.legend.border, "color", null, theme.axisColor);
            patchAxes(theme);
            _each(["chart", "pie", "polar", "gauge", "barGauge", "map", "rangeSelector", "sparkline", "bullet"], function(_, section) {
                mergeScalar(theme[section], "redrawOnResize", theme);
                mergeScalar(theme[section], "containerBackgroundColor", null, theme.backgroundColor);
                mergeObject(theme[section], "tooltip", theme)
            });
            _each(["chart", "pie", "polar", "gauge", "barGauge", "map", "rangeSelector"], function(_, section) {
                mergeObject(theme[section], "loadingIndicator", theme);
                mergeObject(theme[section], "legend", theme)
            });
            _each(["chart", "pie", "polar", "gauge", "barGauge"], function(_, section) {
                mergeObject(theme[section], "title", theme)
            });
            _each(["gauge", "barGauge"], function(_, section) {
                mergeObject(theme[section], "subtitle", null, theme.title)
            });
            _each(["chart", "pie", "polar"], function(_, section) {
                mergeObject(theme, section, null, theme["chart:common"])
            });
            _each(["chart", "polar"], function(_, section) {
                theme[section] = theme[section] || {};
                mergeObject(theme[section], "commonAxisSettings", null, theme["chart:common:axis"])
            });
            mergeObject(theme.rangeSelector.chart, "commonSeriesSettings", theme.chart);
            mergeObject(theme.rangeSelector.chart, "dataPrepareSettings", theme.chart);
            mergeScalar(theme.map.legend, "backgroundColor", theme);
            return theme
        }
        function patchAxes(theme) {
            var commonAxisSettings = theme["chart:common:axis"],
                colorFieldName = "color";
            _each([commonAxisSettings, commonAxisSettings.grid, commonAxisSettings.minorGrid, commonAxisSettings.tick, commonAxisSettings.minorTick], function(_, obj) {
                mergeScalar(obj, colorFieldName, null, theme.axisColor)
            });
            mergeScalar(commonAxisSettings.title.font, colorFieldName, null, theme.secondaryTitleColor);
            mergeScalar(commonAxisSettings.label.font, colorFieldName, null, theme.axisLabelColor);
            mergeScalar(theme.gauge.scale.label.font, colorFieldName, null, theme.axisLabelColor);
            mergeScalar(theme.gauge.scale.majorTick, colorFieldName, null, theme.backgroundColor);
            mergeScalar(theme.gauge.scale.minorTick, colorFieldName, null, theme.backgroundColor);
            mergeScalar(theme.rangeSelector.scale.label.font, colorFieldName, null, theme.axisLabelColor)
        }
        function addCacheItem(target) {
            var cacheUid = ++nextCacheUid;
            target._cache = cacheUid;
            widgetsCache[cacheUid] = target
        }
        function removeCacheItem(target) {
            delete widgetsCache[target._cache]
        }
        function refreshAll() {
            _each(widgetsCache, function() {
                this.refresh()
            });
            return this
        }
        _extend(DX.viz.core, {
            findTheme: findTheme,
            currentTheme: currentTheme,
            registerTheme: registerTheme,
            registerThemeAlias: registerThemeAlias,
            registerThemeSchemeAlias: registerThemeSchemeAlias,
            refreshAll: refreshAll,
            addCacheItem: addCacheItem,
            removeCacheItem: removeCacheItem
        });
        _extend(DX.viz.core, {
            themes: themes,
            themesMapping: themesMapping,
            themesSchemeMapping: themesSchemeMapping,
            widgetsCache: widgetsCache
        })
    })(DevExpress, jQuery);
    /*! Module viz-core, file palette.js */
    (function(DX, $, undefined) {
        var _String = window.String,
            _floor = Math.floor,
            _ceil = Math.ceil,
            _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, size) : [];
            this.getColor = function(index) {
                return palette[index] || null
            };
            this._DEBUG_source = source;
            this._DEBUG_size = size
        }
        function createGradientColors(source, count) {
            var ncolors = count - 1,
                nsource = source.length - 1,
                colors = [],
                gradient = [],
                i;
            for (i = 0; i <= nsource; ++i)
                colors.push(new _Color(source[i]));
            if (ncolors > 0)
                for (i = 0; i <= ncolors; ++i)
                    addColor(i / ncolors);
            else
                addColor(0.5);
            return gradient;
            function addColor(pos) {
                var k = nsource * pos,
                    kl = _floor(k),
                    kr = _ceil(k);
                gradient.push(colors[kl].blend(colors[kr], k - kl).toHex())
            }
        }
        _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 utils.js */
    (function(DX, $, undefined) {
        var _ceil = Math.ceil,
            _min = Math.min,
            _round = Math.round;
        function selectByKeys(object, keys) {
            return $.map(keys, function(key) {
                    return object[key] ? object[key] : null
                })
        }
        function decreaseFields(object, keys, eachDecrease, decrease) {
            var dec = decrease;
            $.each(keys, function(_, key) {
                if (object[key]) {
                    object[key] -= eachDecrease;
                    dec -= eachDecrease
                }
            });
            return dec
        }
        DX.viz.core.utils = {
            decreaseGaps: function(object, keys, decrease) {
                var arrayGaps;
                do {
                    arrayGaps = selectByKeys(object, keys);
                    arrayGaps.push(_ceil(decrease / arrayGaps.length));
                    decrease = decreaseFields(object, keys, _min.apply(null, arrayGaps), decrease)
                } while (decrease > 0 && arrayGaps.length > 1);
                return decrease
            },
            parseScalar: function(value, defaultValue) {
                return value !== undefined ? value : defaultValue
            },
            enumParser: function(values) {
                var stored = {},
                    i,
                    ii;
                for (i = 0, ii = values.length; i < ii; ++i)
                    stored[String(values[i]).toLowerCase()] = 1;
                return function(value, defaultValue) {
                        var _value = String(value).toLowerCase();
                        return stored[_value] ? _value : defaultValue
                    }
            },
            patchFontOptions: function(options) {
                var fontOptions = {};
                $.each(options || {}, function(key, value) {
                    if (/^(cursor|opacity)$/i.test(key));
                    else if (key === "color")
                        key = "fill";
                    else
                        key = "font-" + key;
                    fontOptions[key] = value
                });
                return fontOptions
            },
            convertPolarToXY: function(centerCoords, startAngle, angle, radius) {
                var shiftAngle = 90,
                    cossin;
                angle = DX.utils.isDefined(angle) ? angle + startAngle - shiftAngle : 0;
                cossin = DX.utils.getCosAndSin(angle);
                return {
                        x: _round(centerCoords.x + radius * cossin.cos),
                        y: _round(centerCoords.y + radius * cossin.sin)
                    }
            },
            convertXYToPolar: function(centerCoords, x, y) {
                var radius = DX.utils.getDistance(centerCoords.x, centerCoords.y, x, y),
                    angle = Math.atan2(y - centerCoords.y, x - centerCoords.x);
                return {
                        phi: _round(DX.utils.normalizeAngle(angle * 180 / Math.PI)),
                        r: _round(radius)
                    }
            }
        }
    })(DevExpress, jQuery);
    /*! Module viz-core, file baseThemeManager.js */
    (function(DX, $, undefined) {
        var _isString = DX.utils.isString,
            _parseScalar = DX.viz.core.utils.parseScalar,
            _findTheme = DX.viz.core.findTheme,
            _addCacheItem = DX.viz.core.addCacheItem,
            _removeCacheItem = DX.viz.core.removeCacheItem,
            _extend = $.extend,
            _each = $.each;
        function getThemePart(theme, path) {
            var _theme = theme;
            path && _each(path.split('.'), function(_, pathItem) {
                return _theme = _theme[pathItem]
            });
            return _theme
        }
        DX.viz.core.BaseThemeManager = DX.Class.inherit({
            ctor: function() {
                _addCacheItem(this)
            },
            dispose: function() {
                var that = this;
                _removeCacheItem(that);
                that._callback = that._theme = that._font = null;
                return that
            },
            setCallback: function(callback) {
                this._callback = callback;
                return this
            },
            setTheme: function(theme, rtl) {
                this._current = theme;
                this._rtl = rtl;
                return this.refresh()
            },
            refresh: function() {
                var that = this,
                    current = that._current || {},
                    theme = _findTheme(current.name || current);
                that._themeName = theme.name;
                that._font = _extend({}, theme.font, current.font);
                that._themeSection && _each(that._themeSection.split('.'), function(_, path) {
                    theme = _extend(true, {}, theme[path], that._IE8 ? theme[path + 'IE8'] : {})
                });
                that._theme = _extend(true, {}, theme, _isString(current) ? {} : current);
                that._initializeTheme();
                if (_parseScalar(that._rtl, that._theme.rtlEnabled))
                    _extend(true, that._theme, that._theme._rtl);
                that._callback();
                return that
            },
            theme: function(path) {
                return getThemePart(this._theme, path)
            },
            themeName: function() {
                return this._themeName
            },
            _initializeTheme: function() {
                var that = this;
                _each(that._fontFields || [], function(_, path) {
                    that._initializeFont(getThemePart(that._theme, path))
                })
            },
            _initializeFont: function(font) {
                _extend(font, this._font, _extend({}, font))
            }
        })
    })(DevExpress, jQuery);
    /*! 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({
                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) {
                    return this._parsers[this.correctValueType(valueType)] || $.noop
                }
            });
        core.ParseUtils = parseUtils
    })(jQuery, DevExpress);
    /*! Module viz-core, file loadIndicator.js */
    (function(DX, $, undefined) {
        var _patchFontOptions = DX.viz.core.utils.patchFontOptions;
        var STATE_HIDE = 0,
            STATE_SHOW = 1,
            STATE_ENDLOADING = 2;
        function LoadIndicator(parameters) {
            var that = this;
            that._$widgetContainer = parameters.container;
            that._$container = $("
", {css: {
                    position: "relative",
                    height: 0,
                    padding: 0,
                    margin: 0,
                    border: 0
                }}).appendTo(that._$widgetContainer).hide();
            that._renderer = new DX.viz.renderers.Renderer({animation: {
                    easing: "linear",
                    duration: 150
                }});
            that._renderer.draw(that._$container[0]);
            that._rect = that._renderer.rect().attr({opacity: 0}).append(that._renderer.root);
            that._text = that._renderer.text().attr({
                align: "center",
                visibility: "hidden"
            }).append(that._renderer.root);
            that._createStates(parameters.eventTrigger)
        }
        LoadIndicator.prototype = {
            constructor: LoadIndicator,
            _createStates: function(eventTrigger) {
                var that = this;
                that._states = {};
                that._states[STATE_HIDE] = {
                    o: 0,
                    c: function() {
                        that._$container.hide();
                        eventTrigger("loadingIndicatorReady")
                    }
                };
                that._states[STATE_SHOW] = {
                    o: 0.85,
                    c: function() {
                        eventTrigger("loadingIndicatorReady")
                    }
                };
                that._states[STATE_ENDLOADING] = {
                    o: 1,
                    c: function() {
                        var onEndLoading = that._onEndLoading;
                        that._onEndLoading = null;
                        that._noHiding = true;
                        onEndLoading && onEndLoading();
                        that._noHiding = false;
                        that._onCompleteAction && that[that._onCompleteAction]()
                    }
                }
            },
            applyCanvas: function(canvas) {
                var width = canvas.width,
                    height = canvas.height;
                this._renderer.resize(width, height);
                this._rect.attr({
                    width: width,
                    height: height
                });
                this._text.attr({
                    x: width / 2,
                    y: height / 2
                })
            },
            applyOptions: function(options) {
                this._rect.attr({fill: options.backgroundColor});
                this._text.css(_patchFontOptions(options.font)).attr({text: options.text})
            },
            dispose: function() {
                var that = this;
                that._$container.remove();
                that._renderer.dispose();
                that._$widgetContainer = that._$container = that._renderer = that._rect = that._text = that._states = null
            },
            toForeground: function() {
                this._$container.appendTo(this._$widgetContainer)
            },
            forceShow: function() {
                this._rect.stopAnimation(false).attr({opacity: 1})
            },
            _transit: function(stateId) {
                var state = this._states[stateId];
                this._rect.stopAnimation(true).animate({opacity: state.o}, {complete: state.c})
            },
            show: function() {
                var that = this;
                that._isHiding = false;
                if (that._onEndLoading)
                    that._onCompleteAction = "show";
                else {
                    that._onCompleteAction = null;
                    if (!that._visible) {
                        that._visible = true;
                        that._$container.show();
                        that._renderer.root.css({
                            position: "absolute",
                            left: 0,
                            top: that._$widgetContainer.offset().top - that._$container.offset().top
                        });
                        that._text.attr({visibility: "visible"})
                    }
                    that._transit(STATE_SHOW)
                }
            },
            endLoading: function(complete) {
                var that = this;
                if (!that._onEndLoading)
                    if (that._visible) {
                        that._onEndLoading = complete;
                        that._transit(STATE_ENDLOADING)
                    }
                    else
                        complete && complete()
            },
            hide: function() {
                var that = this;
                that._isHiding = false;
                if (that._onEndLoading)
                    that._onCompleteAction = "hide";
                else {
                    that._onCompleteAction = null;
                    if (that._visible) {
                        that._visible = false;
                        that._text.attr({visibility: "hidden"});
                        that._transit(STATE_HIDE)
                    }
                }
            },
            scheduleHiding: function() {
                if (!this._noHiding) {
                    this._isHiding = true;
                    this._onCompleteAction = null
                }
            },
            fulfillHiding: function() {
                var isHiding = this._isHiding;
                isHiding && this.hide();
                return isHiding
            }
        };
        DX.viz.core.LoadIndicator = LoadIndicator
    })(DevExpress, jQuery);
    /*! Module viz-core, file tooltip.js */
    (function(DX, $, doc, undefined) {
        var HALF_ARROW_WIDTH = 10,
            FORMAT_PRECISION = {
                argument: ["argumentFormat", "argumentPrecision"],
                percent: ["percent", "percentPrecision"],
                value: ["format", "precision"]
            },
            formatHelper = DX.formatHelper,
            mathCeil = Math.ceil;
        function hideElement($element) {
            $element.css({left: "-9999px"}).detach()
        }
        function Tooltip(params) {
            var that = this,
                renderer,
                root;
            that._eventTrigger = params.eventTrigger;
            that._wrapper = $("
").css({
                position: "absolute",
                overflow: "visible",
                width: 0,
                height: 0
            }).addClass(params.cssClass);
            that._renderer = renderer = new DX.viz.renderers.Renderer({});
            root = renderer.root;
            root.attr({"pointer-events": "none"});
            renderer.draw(that._wrapper.get(0));
            that._cloud = renderer.path([], "area").sharp().append(root);
            that._shadow = renderer.shadowFilter();
            that._textGroup = renderer.g().attr({align: "center"}).append(root);
            that._text = renderer.text(undefined, 0, 0).append(that._textGroup);
            that._textGroupHtml = $("
").css({
                position: "absolute",
                width: 0,
                padding: 0,
                margin: 0,
                border: "0px solid transparent"
            }).appendTo(that._wrapper);
            that._textHtml = $("
").css({
                position: "relative",
                display: "inline-block",
                padding: 0,
                margin: 0,
                border: "0px solid transparent"
            }).appendTo(that._textGroupHtml)
        }
        Tooltip.prototype = {
            constructor: Tooltip,
            dispose: function() {
                this._wrapper.remove();
                this._renderer.dispose();
                this._options = null
            },
            setOptions: function(options) {
                options = options || {};
                var that = this,
                    cloudSettings = that._cloudSettigns = {
                        opacity: options.opacity,
                        filter: that._shadow.ref,
                        "stroke-width": null,
                        stroke: null
                    },
                    borderOptions = options.border || {};
                that._shadowSettigns = $.extend({
                    x: "-50%",
                    y: "-50%",
                    width: "200%",
                    height: "200%"
                }, options.shadow);
                that._options = options;
                if (borderOptions.visible)
                    $.extend(cloudSettings, {
                        "stroke-width": borderOptions.width,
                        stroke: borderOptions.color,
                        "stroke-opacity": borderOptions.opacity,
                        dashStyle: borderOptions.dashStyle
                    });
                that._textFontStyles = DX.viz.core.utils.patchFontOptions(options.font);
                that._textFontStyles.color = options.font.color;
                that._wrapper.css({"z-index": options.zIndex});
                that._customizeTooltip = $.isFunction(options.customizeTooltip) ? options.customizeTooltip : null;
                return that
            },
            setRendererOptions: function(options) {
                this._renderer.setOptions(options);
                this._textGroupHtml.css({direction: options.rtl ? "rtl" : "ltr"});
                return this
            },
            render: function() {
                var that = this;
                hideElement(that._wrapper);
                that._cloud.attr(that._cloudSettigns);
                that._shadow.attr(that._shadowSettigns);
                that._textGroupHtml.css(that._textFontStyles);
                that._textGroup.css(that._textFontStyles);
                that._text.css(that._textFontStyles);
                that._eventData = null;
                return that
            },
            update: function(options) {
                return this.setOptions(options).render()
            },
            _prepare: function(formatObject, state) {
                var options = this._options,
                    customize = {};
                if (this._customizeTooltip) {
                    customize = this._customizeTooltip.call(formatObject, formatObject);
                    customize = $.isPlainObject(customize) ? customize : {};
                    if ("text" in customize)
                        state.text = DX.utils.isDefined(customize.text) ? String(customize.text) : "";
                    if ("html" in customize)
                        state.html = DX.utils.isDefined(customize.html) ? String(customize.html) : ""
                }
                if (!("text" in state) && !("html" in state))
                    state.text = formatObject.valueText || "";
                state.color = customize.color || options.color;
                state.borderColor = customize.borderColor || (options.border || {}).color;
                state.textColor = customize.fontColor || (options.font || {}).color;
                return !!state.text || !!state.html
            },
            show: function(formatObject, params, eventData) {
                var that = this,
                    state = {},
                    options = that._options,
                    plr = options.paddingLeftRight,
                    ptb = options.paddingTopBottom,
                    textGroupHtml = that._textGroupHtml,
                    textHtml = that._textHtml,
                    bBox,
                    contentSize,
                    ss = that._shadowSettigns,
                    xOff = ss.offsetX,
                    yOff = ss.offsetY,
                    blur = ss.blur * 2 + 1;
                if (!that._prepare(formatObject, state))
                    return false;
                that._state = state;
                state.tc = {};
                that._wrapper.appendTo($("body"));
                that._cloud.attr({
                    fill: state.color,
                    stroke: state.borderColor
                });
                if (state.html) {
                    that._text.attr({text: ""});
                    textGroupHtml.css({
                        color: state.textColor,
                        width: that._getCanvas().width
                    });
                    textHtml.html(state.html);
                    bBox = textHtml.get(0).getBoundingClientRect();
                    bBox = {
                        x: 0,
                        y: 0,
                        width: mathCeil(bBox.right - bBox.left),
                        height: mathCeil(bBox.bottom - bBox.top)
                    };
                    textGroupHtml.width(bBox.width);
                    textGroupHtml.height(bBox.height)
                }
                else {
                    textHtml.html("");
                    that._text.css({fill: state.textColor}).attr({text: state.text});
                    bBox = that._textGroup.css({fill: state.textColor}).getBBox()
                }
                contentSize = state.contentSize = {
                    x: bBox.x - plr,
                    y: bBox.y - ptb,
                    width: bBox.width + 2 * plr,
                    height: bBox.height + 2 * ptb,
                    lm: blur - xOff > 0 ? blur - xOff : 0,
                    rm: blur + xOff > 0 ? blur + xOff : 0,
                    tm: blur - yOff > 0 ? blur - yOff : 0,
                    bm: blur + yOff > 0 ? blur + yOff : 0
                };
                contentSize.fullWidth = contentSize.width + contentSize.lm + contentSize.rm;
                contentSize.fullHeight = contentSize.height + contentSize.tm + contentSize.bm + options.arrowLength;
                that.move(params.x, params.y, params.offset);
                that._eventData && that._eventTrigger("tooltipHidden", that._eventData);
                that._eventData = eventData;
                that._eventTrigger("tooltipShown", that._eventData);
                return true
            },
            hide: function() {
                var that = this;
                hideElement(that._wrapper);
                that._eventData && that._eventTrigger("tooltipHidden", that._eventData);
                that._eventData = null
            },
            move: function(x, y, offset) {
                offset = offset || 0;
                var that = this,
                    canvas = that._getCanvas(),
                    state = that._state,
                    coords = state.tc,
                    contentSize = state.contentSize;
                if (that._calculatePosition(x, y, offset)) {
                    that._cloud.attr({points: coords.cloudPoints}).move(contentSize.lm, contentSize.tm);
                    if (state.html)
                        that._textGroupHtml.css({
                            left: -contentSize.x + contentSize.lm,
                            top: -contentSize.y + contentSize.tm + coords.correction
                        });
                    else
                        that._textGroup.move(-contentSize.x + contentSize.lm, -contentSize.y + contentSize.tm + coords.correction);
                    that._renderer.resize(coords.hp === "out" ? canvas.fullWidth - canvas.left : contentSize.fullWidth, coords.vp === "out" ? canvas.fullHeight - canvas.top : contentSize.fullHeight)
                }
                that._wrapper.css({
                    left: coords.x,
                    top: coords.y
                })
            },
            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)
            },
            getLocation: function() {
                return (this._options.location + "").toLowerCase()
            },
            isEnabled: function() {
                return !!this._options.enabled
            },
            isShared: function() {
                return !!this._options.shared
            },
            _calculatePosition: function(x, y, offset) {
                var that = this,
                    canvas = that._getCanvas(),
                    options = that._options,
                    arrowLength = options.arrowLength,
                    state = that._state,
                    coords = state.tc,
                    contentSize = state.contentSize,
                    contentWidth = contentSize.width,
                    halfContentWidth = contentWidth / 2,
                    contentHeight = contentSize.height,
                    cTop = y - canvas.top,
                    cBottom = canvas.top + canvas.height - y,
                    cLeft = x - canvas.left,
                    cRight = canvas.width + canvas.left - x,
                    tTop = contentHeight + arrowLength + offset + contentSize.tm,
                    tBottom = contentHeight + arrowLength + offset + contentSize.bm,
                    tLeft = contentWidth + contentSize.lm,
                    tRight = contentWidth + contentSize.rm,
                    tHalfLeft = halfContentWidth + contentSize.lm,
                    tHalfRight = halfContentWidth + contentSize.rm,
                    correction = 0,
                    cloudPoints,
                    arrowPoints = [6, 0],
                    x1 = halfContentWidth + HALF_ARROW_WIDTH,
                    x2 = halfContentWidth,
                    x3 = halfContentWidth - HALF_ARROW_WIDTH,
                    y1,
                    y3,
                    y2 = contentHeight + arrowLength,
                    hp = "center",
                    vp = "bottom",
                    hasDeprecatedPosition;
                y1 = y3 = contentHeight;
                switch (options.verticalAlignment) {
                    case"top":
                        vp = "bottom";
                        hasDeprecatedPosition = true;
                        break;
                    case"bottom":
                        vp = "top";
                        hasDeprecatedPosition = true;
                        break
                }
                if (!hasDeprecatedPosition)
                    if (tTop > cTop && tBottom > cBottom)
                        vp = "out";
                    else if (tTop > cTop)
                        vp = "top";
                hasDeprecatedPosition = false;
                switch (options.horizontalAlignment) {
                    case"left":
                        hp = "right";
                        hasDeprecatedPosition = true;
                        break;
                    case"center":
                        hp = "center";
                        hasDeprecatedPosition = true;
                        break;
                    case"right":
                        hp = "left";
                        hasDeprecatedPosition = true;
                        break
                }
                if (!hasDeprecatedPosition)
                    if (tLeft > cLeft && tRight > cRight)
                        hp = "out";
                    else if (tHalfLeft > cLeft && tRight < cRight)
                        hp = "left";
                    else if (tHalfRight > cRight && tLeft < cLeft)
                        hp = "right";
                if (hp === "out")
                    x = canvas.left;
                else if (hp === "left") {
                    x1 = HALF_ARROW_WIDTH;
                    x2 = x3 = 0
                }
                else if (hp === "right") {
                    x1 = x2 = contentWidth;
                    x3 = contentWidth - HALF_ARROW_WIDTH;
                    x = x - contentWidth
                }
                else if (hp === "center")
                    x = x - halfContentWidth;
                if (vp === "out")
                    y = canvas.top;
                else if (vp === "top") {
                    hp !== "out" && (correction = arrowLength);
                    arrowPoints[0] = 2;
                    y1 = y3 = arrowLength;
                    y2 = x1;
                    x1 = x3;
                    x3 = y2;
                    y2 = 0;
                    y = y + offset
                }
                else
                    y = y - (contentHeight + arrowLength + offset);
                coords.x = x - contentSize.lm;
                coords.y = y - contentSize.tm;
                coords.correction = correction;
                if (hp === coords.hp && vp === coords.vp)
                    return false;
                coords.hp = hp;
                coords.vp = vp;
                cloudPoints = [0, 0 + correction, contentWidth, 0 + correction, contentWidth, contentHeight + correction, 0, contentHeight + correction];
                if (hp !== "out" && vp !== "out") {
                    arrowPoints.splice(2, 0, x1, y1, x2, y2, x3, y3);
                    cloudPoints.splice.apply(cloudPoints, arrowPoints)
                }
                coords.cloudPoints = cloudPoints;
                return true
            },
            _getCanvas: function() {
                var html = doc.documentElement,
                    body = doc.body,
                    win = window;
                return {
                        left: win.pageXOffset || html.scrollLeft || 0,
                        top: win.pageYOffset || html.scrollTop || 0,
                        width: html.clientWidth || 0,
                        height: html.clientHeight || 0,
                        fullWidth: Math.max(body.scrollWidth, html.scrollWidth, body.offsetWidth, html.offsetWidth, body.clientWidth, html.clientWidth),
                        fullHeight: Math.max(body.scrollHeight, html.scrollHeight, body.offsetHeight, html.offsetHeight, body.clientHeight, html.clientHeight)
                    }
            }
        };
        DX.viz.core.Tooltip = Tooltip
    })(DevExpress, jQuery, document);
    /*! Module viz-core, file legend.js */
    (function(DX, $, undefined) {
        var core = DX.viz.core,
            coreUtils = core.utils,
            WrapperLayoutElement = core.WrapperLayoutElement,
            _Number = Number,
            _String = String,
            _math = Math,
            _round = _math.round,
            _max = _math.max,
            _min = _math.min,
            _ceil = _math.ceil,
            utils = DX.utils,
            _isDefined = utils.isDefined,
            _isFunction = utils.isFunction,
            _enumParser = coreUtils.enumParser,
            _extend = $.extend,
            _each = $.each,
            _map = $.map,
            DEFAULT_MARGIN = 10,
            DEFAULT_MARKER_HATCHING_WIDTH = 2,
            DEFAULT_MARKER_HATCHING_STEP = 5,
            CENTER = "center",
            RIGHT = "right",
            LEFT = "left",
            TOP = "top",
            BOTTOM = "bottom",
            HORIZONTAL = "horizontal",
            VERTICAL = "vertical",
            INSIDE = "inside",
            OUTSIDE = "outside",
            NONE = "none",
            HEIGHT = "height",
            WIDTH = "width",
            parseHorizontalAlignment = _enumParser([LEFT, CENTER, RIGHT]),
            parseVerticalAlignment = _enumParser([TOP, BOTTOM]),
            parseOrientation = _enumParser([VERTICAL, HORIZONTAL]),
            parseItemTextPosition = _enumParser([LEFT, RIGHT, TOP, BOTTOM]),
            parsePosition = _enumParser([OUTSIDE, INSIDE]),
            parseItemsAlignment = _enumParser([LEFT, CENTER, RIGHT]);
        function getPattern(renderer, states, action, color) {
            if (!states || !states[action])
                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.pattern(color, hatching)
        }
        function parseMargins(options) {
            var margin = options.margin;
            if (margin >= 0) {
                margin = _Number(options.margin);
                margin = {
                    top: margin,
                    bottom: margin,
                    left: margin,
                    right: margin
                }
            }
            else
                margin = {
                    top: margin.top >= 0 ? _Number(margin.top) : DEFAULT_MARGIN,
                    bottom: margin.bottom >= 0 ? _Number(margin.bottom) : DEFAULT_MARGIN,
                    left: margin.left >= 0 ? _Number(margin.left) : DEFAULT_MARGIN,
                    right: margin.right >= 0 ? _Number(margin.right) : DEFAULT_MARGIN
                };
            options.margin = margin
        }
        function getSizeItem(options, markerSize, labelBBox) {
            var defaultXMargin = 7,
                defaultTopMargin = 4,
                width,
                height;
            switch (options.itemTextPosition) {
                case LEFT:
                case RIGHT:
                    width = markerSize + defaultXMargin + labelBBox.width;
                    height = _max(markerSize, labelBBox.height);
                    break;
                case TOP:
                case BOTTOM:
                    width = _max(markerSize, labelBBox.width);
                    height = markerSize + defaultTopMargin + labelBBox.height;
                    break
            }
            return {
                    width: width,
                    height: height
                }
        }
        function calculateBboxLabelAndMarker(markerBBox, labelBBox) {
            var bbox = {};
            bbox.left = _min(markerBBox.x, labelBBox.x);
            bbox.top = _min(markerBBox.y, labelBBox.y);
            bbox.right = _max(markerBBox.x + markerBBox.width, labelBBox.x + labelBBox.width);
            bbox.bottom = _max(markerBBox.y + markerBBox.height, labelBBox.y + labelBBox.height);
            return bbox
        }
        function applyMarkerState(id, idToIndexMap, items, stateName) {
            var item = idToIndexMap && items[idToIndexMap[id]];
            if (item)
                item.marker.attr(item.states[stateName])
        }
        function parseOptions(options, textField) {
            if (!options)
                return null;
            DX.utils.debug.assertParam(options.visible, "Visibility was not passed");
            DX.utils.debug.assertParam(options.markerSize, "markerSize was not passed");
            DX.utils.debug.assertParam(options.font.color, "fontColor was not passed");
            DX.utils.debug.assertParam(options.font.family, "fontFamily was not passed");
            DX.utils.debug.assertParam(options.font.size, "fontSize was not passed");
            DX.utils.debug.assertParam(options.paddingLeftRight, "paddingLeftRight was not passed");
            DX.utils.debug.assertParam(options.paddingTopBottom, "paddingTopBottom was not passed");
            DX.utils.debug.assertParam(options.columnItemSpacing, "columnItemSpacing was not passed");
            DX.utils.debug.assertParam(options.rowItemSpacing, "rowItemSpacing was not passed");
            parseMargins(options);
            options.horizontalAlignment = parseHorizontalAlignment(options.horizontalAlignment, RIGHT);
            options.verticalAlignment = parseVerticalAlignment(options.verticalAlignment, options.horizontalAlignment === CENTER ? BOTTOM : TOP);
            options.orientation = parseOrientation(options.orientation, options.horizontalAlignment === CENTER ? HORIZONTAL : VERTICAL);
            options.itemTextPosition = parseItemTextPosition(options.itemTextPosition, options.orientation === HORIZONTAL ? BOTTOM : RIGHT);
            options.position = parsePosition(options.position, OUTSIDE);
            options.itemsAlignment = parseItemsAlignment(options.itemsAlignment, null);
            options.hoverMode = _String(options.hoverMode || "").toLowerCase();
            options.customizeText = _isFunction(options.customizeText) ? options.customizeText : function() {
                return this[textField]
            };
            options.customizeHint = _isFunction(options.customizeHint) ? options.customizeHint : $.noop;
            return options
        }
        function createSquareMarker(renderer, size) {
            return renderer.rect(0, 0, size, size)
        }
        function createCircleMarker(renderer, size) {
            return renderer.circle(size / 2, size / 2, size / 2)
        }
        function isCircle(type) {
            return _String(type).toLowerCase() === "circle"
        }
        function getMarkerCreator(type) {
            return isCircle(type) ? createCircleMarker : createSquareMarker
        }
        function inRect(rect, x, y) {
            return x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom
        }
        function checkLinesSize(lines, layoutOptions, countItems) {
            var position = {
                    x: 0,
                    y: 0
                },
                maxMeasureLength = 0,
                maxOrtMeasureLength = 0;
            $.each(lines, function(i, line) {
                var firstItem = line[0];
                $.each(line, function(_, item) {
                    var offset = item.offset || layoutOptions.spacing;
                    position[layoutOptions.direction] += item[layoutOptions.measure] + offset;
                    maxMeasureLength = _max(maxMeasureLength, position[layoutOptions.direction])
                });
                position[layoutOptions.direction] = 0;
                position[layoutOptions.ortDirection] += firstItem[layoutOptions.ortMeasure] + firstItem.ortOffset || layoutOptions.ortSpacing;
                maxOrtMeasureLength = _max(maxOrtMeasureLength, position[layoutOptions.ortDirection])
            });
            if (maxMeasureLength > layoutOptions.length) {
                layoutOptions.countItem = decreaseItemCount(layoutOptions, countItems);
                return true
            }
        }
        function decreaseItemCount(layoutOptions, countItems) {
            layoutOptions.ortCountItem++;
            return _ceil(countItems / layoutOptions.ortCountItem)
        }
        function getLineLength(line, layoutOptions) {
            var lineLength = 0;
            $.each(line, function(_, item) {
                var offset = item.offset || layoutOptions.spacing;
                lineLength += item[layoutOptions.measure] + offset
            });
            return lineLength
        }
        function getMaxLineLength(lines, layoutOptions) {
            var maxLineLength = 0;
            $.each(lines, function(_, line) {
                maxLineLength = _max(maxLineLength, getLineLength(line, layoutOptions))
            });
            return maxLineLength
        }
        function getInitPositionForDirection(line, layoutOptions, maxLineLength) {
            var lineLength = getLineLength(line, layoutOptions),
                initPosition;
            switch (layoutOptions.itemsAlignment) {
                case RIGHT:
                    initPosition = maxLineLength - lineLength;
                    break;
                case CENTER:
                    initPosition = (maxLineLength - lineLength) / 2;
                    break;
                default:
                    initPosition = 0
            }
            return initPosition
        }
        function getPos(layoutOptions) {
            switch (layoutOptions.itemTextPosition) {
                case BOTTOM:
                    return CENTER + " " + TOP;
                case TOP:
                    return CENTER + " " + BOTTOM;
                case LEFT:
                    return RIGHT + " " + CENTER;
                case RIGHT:
                    return LEFT + " " + CENTER
            }
        }
        function getLines(lines, layoutOptions, itemIndex) {
            var tableLine = {};
            if (itemIndex % layoutOptions.countItem === 0)
                if (layoutOptions.markerOffset)
                    lines.push([], []);
                else
                    lines.push([]);
            if (layoutOptions.markerOffset) {
                tableLine.firstLine = lines[lines.length - 1];
                tableLine.secondLine = lines[lines.length - 2]
            }
            else
                tableLine.firstLine = tableLine.secondLine = lines[lines.length - 1];
            return tableLine
        }
        function setMaxInLine(line, mesuare) {
            var maxLineSize = 0;
            $.each(line, function(_, item) {
                if (!item)
                    return;
                maxLineSize = _max(maxLineSize, item[mesuare])
            });
            $.each(line, function(_, item) {
                if (!item)
                    return;
                item[mesuare] = maxLineSize
            })
        }
        function transpose(array) {
            var width = array.length,
                height = array[0].length,
                i,
                j,
                transposeArray = [];
            for (i = 0; i < height; i++) {
                transposeArray[i] = [];
                for (j = 0; j < width; j++)
                    transposeArray[i][j] = array[j][i]
            }
            return transposeArray
        }
        function getAlign(position) {
            switch (position) {
                case TOP:
                case BOTTOM:
                    return CENTER;
                case LEFT:
                    return RIGHT;
                case RIGHT:
                    return LEFT
            }
        }
        var _Legend = DX.viz.core.Legend = function(settings) {
                var that = this;
                that._renderer = settings.renderer;
                that._legendGroup = settings.group;
                that._backgroundClass = settings.backgroundClass;
                that._itemGroupClass = settings.itemGroupClass;
                that._textField = settings.textField;
                that._getCustomizeObject = settings.getFormatObject;
                that._patterns = []
            };
        _Legend.prototype = {
            constructor: _Legend,
            update: function(data, options) {
                var that = this;
                that._data = data;
                that._boundingRect = {
                    width: 0,
                    height: 0,
                    x: 0,
                    y: 0
                };
                that._options = parseOptions(options, that._textField);
                return that
            },
            setSize: function(size) {
                this._size = {
                    width: size.width,
                    height: size.height
                };
                return this
            },
            draw: function(size) {
                var that = this,
                    options = that._options,
                    renderer = that._renderer,
                    items = that._data;
                size && that.setSize(size);
                that.erase();
                if (!(options && options.visible && items && items.length))
                    return that;
                that._insideLegendGroup = renderer.g().append(that._legendGroup);
                that._createBackground();
                that._createItems(that._getItemData());
                that._locateElements(options);
                that._finalUpdate(options);
                return that
            },
            _createItems: function(items) {
                var that = this,
                    options = that._options,
                    initMarkerSize = options.markerSize,
                    renderer = that._renderer,
                    markersOptions = [],
                    maxMarkerSize = 0,
                    i = 0,
                    bbox,
                    maxBboxWidth = 0,
                    maxBboxHeight = 0,
                    createMarker = getMarkerCreator(options.markerType);
                _each(items, function(_i, item) {
                    maxMarkerSize = _max(maxMarkerSize, _Number(item.size > 0 ? item.size : initMarkerSize))
                });
                that._markersId = {};
                for (; i < that._patterns.length; i++)
                    that._patterns[i].dispose();
                that._patterns = [];
                that._items = _map(items, function(dataItem, i) {
                    var group = that._insideLegendGroup,
                        markerSize = _Number(dataItem.size > 0 ? dataItem.size : initMarkerSize),
                        stateOfDataItem = dataItem.states,
                        normalState = stateOfDataItem.normal,
                        normalStateFill = normalState.fill,
                        marker = createMarker(renderer, markerSize).attr({
                            fill: normalStateFill || options.markerColor,
                            opacity: normalState.opacity
                        }).append(group),
                        label = that._createLabel(dataItem, group),
                        hoverPattern = getPattern(renderer, stateOfDataItem, "hover", normalStateFill),
                        selectionPattern = getPattern(renderer, stateOfDataItem, "selection", normalStateFill),
                        states = {normal: {fill: normalStateFill}},
                        labelBBox = label.getBBox();
                    if (hoverPattern) {
                        states.hovered = {fill: hoverPattern.id};
                        that._patterns.push(hoverPattern)
                    }
                    if (selectionPattern) {
                        states.selected = {fill: selectionPattern.id};
                        that._patterns.push(selectionPattern)
                    }
                    if (dataItem.id !== undefined)
                        that._markersId[dataItem.id] = i;
                    bbox = getSizeItem(options, markerSize, labelBBox);
                    maxBboxWidth = _max(maxBboxWidth, bbox.width);
                    maxBboxHeight = _max(maxBboxHeight, bbox.height);
                    markersOptions.push({
                        size: markerSize,
                        marker: marker
                    });
                    that._createHint(dataItem, label);
                    return {
                            label: label,
                            labelBBox: labelBBox,
                            group: group,
                            bbox: bbox,
                            marker: marker,
                            markerSize: markerSize,
                            tracker: {id: dataItem.id},
                            states: states,
                            itemTextPosition: options.itemTextPosition,
                            markerOffset: 0,
                            bboxs: []
                        }
                });
                if (options.equalRowHeight)
                    $.each(that._items, function(_, item) {
                        item.bbox.height = maxBboxHeight
                    })
            },
            _getItemData: function() {
                var items = this._data;
                if (this._options.inverted)
                    items = items.slice().reverse();
                return items
            },
            _finalUpdate: function(options) {
                this._adjustBackgroundSettings(options);
                this._setBoundingRect(options.margin)
            },
            erase: function() {
                var that = this,
                    insideLegendGroup = that._insideLegendGroup;
                insideLegendGroup && insideLegendGroup.dispose();
                that._insideLegendGroup = that._x1 = that._x2 = that._y2 = that._y2 = null;
                return that
            },
            _locateElements: function(locationOptions) {
                this._moveInInitialValues();
                this._locateRowsColumns(locationOptions)
            },
            _moveInInitialValues: function() {
                var that = this;
                that._legendGroup && that._legendGroup.move(0, 0);
                that._background && that._background.attr({
                    x: 0,
                    y: 0,
                    width: 0,
                    height: 0
                })
            },
            applySelected: function(id) {
                applyMarkerState(id, this._markersId, this._items, "selected");
                return this
            },
            applyHover: function(id) {
                applyMarkerState(id, this._markersId, this._items, "hovered");
                return this
            },
            resetItem: function(id) {
                applyMarkerState(id, this._markersId, this._items, "normal");
                return this
            },
            _createLabel: function(data, group) {
                var labelFormatObject = this._getCustomizeObject(data),
                    align = getAlign(this._options.itemTextPosition),
                    text = this._options.customizeText.call(labelFormatObject, labelFormatObject),
                    fontStyle = _isDefined(data.textOpacity) ? _extend({}, this._options.font, {opacity: data.textOpacity}) : this._options.font;
                return this._renderer.text(text, 0, 0).css(coreUtils.patchFontOptions(fontStyle)).attr({align: align}).append(group)
            },
            _createHint: function(data, label) {
                var labelFormatObject = this._getCustomizeObject(data),
                    text = this._options.customizeHint.call(labelFormatObject, labelFormatObject);
                if (_isDefined(text) && text !== "")
                    label.setTitle(text)
            },
            _createBackground: function() {
                var that = this,
                    isInside = that._options.position === INSIDE,
                    color = that._options.backgroundColor,
                    fill = color || (isInside ? that._options.containerBackgroundColor : NONE);
                if (that._options.border.visible || (isInside || color) && color !== NONE)
                    that._background = that._renderer.rect(0, 0, 0, 0).attr({
                        fill: fill,
                        'class': that._backgroundClass
                    }).append(that._insideLegendGroup)
            },
            _locateRowsColumns: function() {
                var that = this,
                    iteration = 0,
                    layoutOptions = that._getItemsLayoutOptions(),
                    countItems = that._items.length,
                    lines;
                do {
                    lines = [];
                    that._createLines(lines, layoutOptions);
                    that._alignLines(lines, layoutOptions);
                    iteration++
                } while (checkLinesSize(lines, layoutOptions, countItems) && iteration < countItems);
                that._applyItemPosition(lines, layoutOptions)
            },
            _createLines: function(lines, layoutOptions) {
                $.each(this._items, function(i, item) {
                    var tableLine = getLines(lines, layoutOptions, i),
                        labelBox = {
                            width: item.labelBBox.width,
                            height: item.labelBBox.height,
                            element: item.label,
                            bbox: item.labelBBox,
                            pos: getPos(layoutOptions),
                            itemIndex: i
                        },
                        markerBox = {
                            width: item.markerSize,
                            height: item.markerSize,
                            element: item.marker,
                            bbox: {
                                width: item.markerSize,
                                height: item.markerSize,
                                x: 0,
                                y: 0
                            },
                            itemIndex: i
                        },
                        firstItem,
                        secondItem,
                        offsetDirection = layoutOptions.markerOffset ? "ortOffset" : "offset";
                    if (layoutOptions.inverseLabelPosition) {
                        firstItem = labelBox;
                        secondItem = markerBox
                    }
                    else {
                        firstItem = markerBox;
                        secondItem = labelBox
                    }
                    firstItem[offsetDirection] = layoutOptions.labelOffset;
                    tableLine.secondLine.push(firstItem);
                    tableLine.firstLine.push(secondItem)
                })
            },
            _alignLines: function(lines, layoutOptions) {
                var i,
                    measure = layoutOptions.ortMeasure;
                _each(lines, processLine);
                measure = layoutOptions.measure;
                if (layoutOptions.itemsAlignment) {
                    if (layoutOptions.markerOffset)
                        for (i = 0; i < lines.length; )
                            _each(transpose([lines[i++], lines[i++]]), processLine)
                }
                else
                    _each(transpose(lines), processLine);
                function processLine(_, line) {
                    setMaxInLine(line, measure)
                }
            },
            _applyItemPosition: function(lines, layoutOptions) {
                var that = this,
                    position = {
                        x: 0,
                        y: 0
                    },
                    maxLineLength = getMaxLineLength(lines, layoutOptions),
                    itemIndex = 0;
                $.each(lines, function(i, line) {
                    var firstItem = line[0],
                        ortOffset = firstItem.ortOffset || layoutOptions.ortSpacing;
                    position[layoutOptions.direction] = getInitPositionForDirection(line, layoutOptions, maxLineLength);
                    $.each(line, function(_, item) {
                        var offset = item.offset || layoutOptions.spacing,
                            wrap = new WrapperLayoutElement(item.element, item.bbox),
                            itemBBox = {
                                x: position.x,
                                y: position.y,
                                width: item.width,
                                height: item.height
                            },
                            itemLegend = that._items[item.itemIndex];
                        wrap.position({
                            of: itemBBox,
                            my: item.pos,
                            at: item.pos
                        });
                        itemLegend.bboxs.push(itemBBox);
                        position[layoutOptions.direction] += item[layoutOptions.measure] + offset;
                        itemIndex++
                    });
                    position[layoutOptions.ortDirection] += firstItem[layoutOptions.ortMeasure] + ortOffset
                });
                $.each(this._items, function(_, item) {
                    var itemBBox = calculateBboxLabelAndMarker(item.bboxs[0], item.bboxs[1]),
                        horizontal = that._options.columnItemSpacing / 2,
                        vertical = that._options.rowItemSpacing / 2;
                    item.tracker.left = itemBBox.left - horizontal;
                    item.tracker.right = itemBBox.right + horizontal;
                    item.tracker.top = itemBBox.top - vertical;
                    item.tracker.bottom = itemBBox.bottom + vertical
                })
            },
            _getItemsLayoutOptions: function() {
                var that = this,
                    options = that._options,
                    border = options.border.visible,
                    orientation = options.orientation,
                    layoutOptions = {
                        itemsAlignment: options.itemsAlignment,
                        orientation: options.orientation
                    },
                    width = that._size.width - (border ? 2 * options.paddingLeftRight : 0),
                    height = that._size.height - (border ? 2 * options.paddingTopBottom : 0);
                if (orientation === HORIZONTAL) {
                    layoutOptions.length = width;
                    layoutOptions.ortLength = height;
                    layoutOptions.spacing = options.columnItemSpacing;
                    layoutOptions.direction = "x";
                    layoutOptions.measure = WIDTH;
                    layoutOptions.ortMeasure = HEIGHT;
                    layoutOptions.ortDirection = "y";
                    layoutOptions.ortSpacing = options.rowItemSpacing;
                    layoutOptions.countItem = options.columnCount;
                    layoutOptions.ortCountItem = options.rowCount;
                    layoutOptions.marginTextLabel = 4;
                    layoutOptions.labelOffset = 7;
                    if (options.itemTextPosition === BOTTOM || options.itemTextPosition === TOP) {
                        layoutOptions.labelOffset = 4;
                        layoutOptions.markerOffset = true
                    }
                }
                else {
                    layoutOptions.length = height;
                    layoutOptions.ortLength = width;
                    layoutOptions.spacing = options.rowItemSpacing;
                    layoutOptions.direction = "y";
                    layoutOptions.measure = HEIGHT;
                    layoutOptions.ortMeasure = WIDTH;
                    layoutOptions.ortDirection = "x";
                    layoutOptions.ortSpacing = options.columnItemSpacing;
                    layoutOptions.countItem = options.rowCount;
                    layoutOptions.ortCountItem = options.columnCount;
                    layoutOptions.marginTextLabel = 7;
                    layoutOptions.labelOffset = 4;
                    if (options.itemTextPosition === RIGHT || options.itemTextPosition === LEFT) {
                        layoutOptions.labelOffset = 7;
                        layoutOptions.markerOffset = true
                    }
                }
                if (!layoutOptions.countItem)
                    if (layoutOptions.ortCountItem)
                        layoutOptions.countItem = _ceil(that._items.length / layoutOptions.ortCountItem);
                    else
                        layoutOptions.countItem = that._items.length;
                if (options.itemTextPosition === TOP || options.itemTextPosition === LEFT)
                    layoutOptions.inverseLabelPosition = true;
                layoutOptions.itemTextPosition = options.itemTextPosition;
                layoutOptions.ortCountItem = layoutOptions.ortCountItem || _ceil(that._items.length / layoutOptions.countItem);
                return layoutOptions
            },
            _adjustBackgroundSettings: function(locationOptions) {
                if (!this._background)
                    return;
                var border = locationOptions.border,
                    legendBox = this._insideLegendGroup.getBBox(),
                    backgroundSettings = {
                        x: _round(legendBox.x - locationOptions.paddingLeftRight),
                        y: _round(legendBox.y - locationOptions.paddingTopBottom),
                        width: _round(legendBox.width) + 2 * locationOptions.paddingLeftRight,
                        height: _round(legendBox.height) + 2 * locationOptions.paddingTopBottom,
                        opacity: locationOptions.backgroundOpacity
                    };
                if (border.visible && border.width && border.color && border.color !== NONE) {
                    backgroundSettings["stroke-width"] = border.width;
                    backgroundSettings.stroke = border.color;
                    backgroundSettings["stroke-opacity"] = border.opacity;
                    backgroundSettings.dashStyle = border.dashStyle;
                    backgroundSettings.rx = border.cornerRadius || 0;
                    backgroundSettings.ry = border.cornerRadius || 0
                }
                this._background.attr(backgroundSettings)
            },
            _setBoundingRect: function(margin) {
                if (!this._insideLegendGroup)
                    return;
                var box = this._insideLegendGroup.getBBox();
                box.height += margin.top + margin.bottom;
                box.width += margin.left + margin.right;
                box.x -= margin.left;
                box.y -= margin.top;
                this._boundingRect = box
            },
            changeSize: function() {
                this.fit.apply(this, arguments)
            },
            fit: function(sizeForDecrease) {
                var that = this,
                    beforeFit = that.getLayoutOptions(),
                    afterFit;
                function fitLegendToDirection(direction) {
                    var size = $.extend({}, that._size);
                    size[direction] = beforeFit[direction] - sizeForDecrease[direction];
                    that.draw(size);
                    afterFit = that.getLayoutOptions();
                    if (that._insideLegendGroup)
                        if (beforeFit[direction] - sizeForDecrease[direction] < afterFit[direction]) {
                            that._options._incidentOccured("W2104");
                            that.erase()
                        }
                }
                if (sizeForDecrease.width > 0)
                    fitLegendToDirection(WIDTH);
                if (sizeForDecrease.height > 0)
                    fitLegendToDirection(HEIGHT);
                return this
            },
            getActionCallback: function(point) {
                var that = this;
                if (that._options.visible)
                    return function(act) {
                            var pointType = point.type,
                                seriesType = pointType || point.series.type;
                            if (pointType || 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,
                    box = {};
                if (that._insideLegendGroup) {
                    that._insideLegendGroup.attr({
                        translateX: x - that._boundingRect.x,
                        translateY: y - that._boundingRect.y
                    });
                    box = that._legendGroup.getBBox()
                }
                that._x1 = box.x;
                that._y1 = box.y;
                that._x2 = box.x + box.width;
                that._y2 = box.y + box.height;
                return that
            },
            getPosition: function() {
                return this._options.position
            },
            coordsIn: function(x, y) {
                return x >= this._x1 && x <= this._x2 && y >= this._y1 && y <= this._y2
            },
            getItemByCoord: function(x, y) {
                var items = this._items,
                    legendGroup = this._insideLegendGroup;
                x = x - legendGroup.attr("translateX");
                y = y - legendGroup.attr("translateY");
                for (var i = 0; i < items.length; i++)
                    if (inRect(items[i].tracker, x, y))
                        return items[i].tracker;
                return null
            },
            dispose: function() {
                var that = this;
                that._legendGroup = that._insideLegendGroup = that._renderer = that._options = that._data = that._items = null;
                return that
            }
        };
        var __getMarkerCreator = getMarkerCreator;
        DX.viz.core._DEBUG_stubMarkerCreator = function(callback) {
            getMarkerCreator = function() {
                return callback
            }
        };
        DX.viz.core._DEBUG_restoreMarkerCreator = function() {
            getMarkerCreator = __getMarkerCreator
        }
    })(DevExpress, jQuery);
    /*! Module viz-core, file range.js */
    (function($, DX, undefined) {
        var core = DX.viz.core,
            utils = DX.utils,
            _isDefined = utils.isDefined,
            _isDate = utils.isDate,
            NUMBER_EQUALITY_CORRECTION = 1,
            DATETIME_EQUALITY_CORRECTION = 60000,
            minSelector = "min",
            maxSelector = "max",
            minVisibleSelector = "minVisible",
            maxVisibleSelector = "maxVisible",
            categoriesSelector = "categories",
            baseSelector = "base",
            axisTypeSelector = "axisType",
            _Range;
        function otherLessThan(thisValue, otherValue) {
            return otherValue < thisValue
        }
        function otherGreaterThan(thisValue, otherValue) {
            return otherValue > thisValue
        }
        function compareAndReplace(thisValue, otherValue, setValue, compare) {
            var otherValueDefined = _isDefined(otherValue);
            if (_isDefined(thisValue)) {
                if (otherValueDefined && compare(thisValue, otherValue))
                    setValue(otherValue)
            }
            else if (otherValueDefined)
                setValue(otherValue)
        }
        function returnValue(value) {
            return value
        }
        function returnValueOf(value) {
            return value.valueOf()
        }
        function getUniqueCategories(categories, otherCategories, dataType) {
            var length = categories.length,
                found,
                i,
                j,
                valueOf = dataType === "datetime" ? returnValueOf : returnValue;
            if (otherCategories && otherCategories.length)
                for (i = 0; i < otherCategories.length; i++) {
                    for (j = 0, found = false; j < length; j++)
                        if (valueOf(categories[j]) === valueOf(otherCategories[i])) {
                            found = true;
                            break
                        }
                    !found && categories.push(otherCategories[i])
                }
            return categories
        }
        DX.viz.core.__NUMBER_EQUALITY_CORRECTION = NUMBER_EQUALITY_CORRECTION;
        DX.viz.core.__DATETIME_EQUALITY_CORRECTION = DATETIME_EQUALITY_CORRECTION;
        _Range = core.Range = function(range) {
            range && $.extend(this, range)
        };
        _Range.prototype = {
            constructor: _Range,
            dispose: function() {
                this[categoriesSelector] = null
            },
            addRange: function(otherRange) {
                var that = this,
                    categories = that[categoriesSelector],
                    otherCategories = otherRange[categoriesSelector];
                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) {
                            _isDefined(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("addSpiderCategory");
                checkField("percentStick");
                checkField("minSpaceCorrection");
                checkField("maxSpaceCorrection");
                checkField("invert");
                checkField(axisTypeSelector);
                checkField("dataType");
                if (that[axisTypeSelector] === "logarithmic")
                    checkField(baseSelector);
                else
                    that[baseSelector] = undefined;
                compareAndReplaceByField(minSelector, otherLessThan);
                compareAndReplaceByField(maxSelector, otherGreaterThan);
                if (that[axisTypeSelector] === "discrete") {
                    checkField(minVisibleSelector);
                    checkField(maxVisibleSelector)
                }
                else {
                    compareAndReplaceByField(minVisibleSelector, otherLessThan);
                    compareAndReplaceByField(maxVisibleSelector, otherGreaterThan)
                }
                compareAndReplaceByField("interval", otherLessThan);
                controlValuesByVisibleBounds(minSelector, minVisibleSelector, otherLessThan);
                controlValuesByVisibleBounds(minSelector, maxVisibleSelector, otherLessThan);
                controlValuesByVisibleBounds(maxSelector, maxVisibleSelector, otherGreaterThan);
                controlValuesByVisibleBounds(maxSelector, minVisibleSelector, otherGreaterThan);
                if (categories === undefined)
                    that[categoriesSelector] = otherCategories;
                else
                    that[categoriesSelector] = getUniqueCategories(categories, otherCategories, that.dataType);
                return this
            },
            isDefined: function() {
                return _isDefined(this[minSelector]) && _isDefined(this[maxSelector]) || _isDefined(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
            },
            correctValueZeroLevel: function() {
                var that = this;
                if (_isDate(that[maxSelector]) || _isDate(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
            },
            checkZeroStick: function() {
                var that = this;
                if (that.min >= 0 && that.max >= 0)
                    that.minStickValue = 0;
                else if (that.min <= 0 && that.max <= 0)
                    that.maxStickValue = 0;
                return that
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file svgRenderer.js */
    (function($, DX, doc, undefined) {
        var rendererNS = DX.viz.renderers = {},
            math = Math,
            mathMin = math.min,
            mathMax = math.max,
            mathCeil = math.ceil,
            mathFloor = math.floor,
            mathRound = math.round,
            mathSin = math.sin,
            mathCos = math.cos,
            mathAbs = math.abs,
            mathPI = math.PI,
            PI_DIV_180 = mathPI / 180,
            _parseInt = parseInt,
            MAX_PIXEL_COUNT = 1E10,
            SHARPING_CORRECTION = 0.5,
            ARC_COORD_PREC = 5;
        var pxAddingExceptions = {
                "column-count": true,
                "fill-opacity": true,
                "flex-grow": true,
                "flex-shrink": true,
                "font-weight": true,
                "line-height": true,
                opacity: true,
                order: true,
                orphans: true,
                widows: true,
                "z-index": true,
                zoom: true
            };
        var KEY_TEXT = "text",
            KEY_STROKE = "stroke",
            KEY_STROKE_WIDTH = "stroke-width",
            KEY_STROKE_OPACITY = "stroke-opacity",
            KEY_FONT_SIZE = "font-size",
            KEY_FONT_STYLE = "font-style",
            KEY_FONT_WEIGHT = "font-weight",
            KEY_TEXT_DECORATION = "text-decoration",
            NONE = "none";
        var DEFAULTS = {
                scaleX: 1,
                scaleY: 1
            };
        var getNextDefsSvgId = function() {
                var numDefsSvgElements = 1;
                return function() {
                        return "DevExpress_" + numDefsSvgElements++
                    }
            }();
        function isObjectArgument(value) {
            return typeof value !== "string"
        }
        function isDefined(value) {
            return value !== null && value !== undefined
        }
        function isArray(value) {
            return Object.prototype.toString.call(value) === "[object Array]"
        }
        function isObject(value) {
            return Object.prototype.toString.call(value) === "[object Object]"
        }
        function createElement(tagName) {
            return doc.createElementNS("http://www.w3.org/2000/svg", tagName)
        }
        function getPatternUrl(id, pathModified) {
            return id !== null ? "url(" + (pathModified ? window.location.href : "") + "#" + id + ")" : ""
        }
        function extend(a, b, skipNonDefined) {
            var value;
            for (var key in b) {
                value = b[key];
                if (!skipNonDefined || skipNonDefined && value !== undefined && value !== null)
                    a[key] = value
            }
            return a
        }
        function rotateBBox(bbox, center, angle) {
            var cos = Number(mathCos(angle * PI_DIV_180).toFixed(3)),
                sin = Number(mathSin(angle * PI_DIV_180).toFixed(3)),
                w2 = bbox.width / 2,
                h2 = bbox.height / 2,
                xc = bbox.x + w2,
                yc = bbox.y + h2,
                w2_ = mathAbs(w2 * cos) + mathAbs(h2 * sin),
                h2_ = mathAbs(w2 * sin) + mathAbs(h2 * cos),
                xc_ = center[0] + (xc - center[0]) * cos + (yc - center[1]) * sin,
                yc_ = center[1] - (xc - center[0]) * sin + (yc - center[1]) * cos;
            return normalizeBBox({
                    x: xc_ - w2_,
                    y: yc_ - h2_,
                    width: 2 * w2_,
                    height: 2 * h2_
                })
        }
        function normalizeBBoxField(value) {
            return -MAX_PIXEL_COUNT < value && value < +MAX_PIXEL_COUNT ? value : 0
        }
        function normalizeBBox(bbox) {
            var rxl = normalizeBBoxField(mathFloor(bbox.x)),
                ryt = normalizeBBoxField(mathFloor(bbox.y)),
                rxr = normalizeBBoxField(mathCeil(bbox.width + bbox.x)),
                ryb = normalizeBBoxField(mathCeil(bbox.height + bbox.y)),
                result = {
                    x: rxl,
                    y: ryt,
                    width: rxr - rxl,
                    height: ryb - ryt
                };
            result.isEmpty = !result.x && !result.y && !result.width && !result.height;
            return result
        }
        function getPreserveAspectRatio(location) {
            return {
                    full: NONE,
                    lefttop: "xMinYMin",
                    leftcenter: "xMinYMid",
                    leftbottom: "xMinYMax",
                    centertop: "xMidYMin",
                    center: "xMidYMid",
                    centerbottom: "xMidYMax",
                    righttop: "xMaxYMin",
                    rightcenter: "xMaxYMid",
                    rightbottom: "xMaxYMax"
                }[(location || "").toLowerCase()] || NONE
        }
        rendererNS._normalizeArcParams = function(x, y, innerR, outerR, startAngle, endAngle) {
            var isCircle,
                noArc = true;
            if (mathRound(startAngle) !== mathRound(endAngle)) {
                if (mathAbs(endAngle - startAngle) % 360 === 0) {
                    startAngle = 0;
                    endAngle = 360;
                    isCircle = true;
                    endAngle -= 0.01
                }
                if (startAngle > 360)
                    startAngle = startAngle % 360;
                if (endAngle > 360)
                    endAngle = endAngle % 360;
                if (startAngle > endAngle)
                    startAngle -= 360;
                noArc = false
            }
            startAngle = startAngle * PI_DIV_180;
            endAngle = endAngle * PI_DIV_180;
            return [x, y, mathMin(outerR, innerR), mathMax(outerR, innerR), mathCos(startAngle), mathSin(startAngle), mathCos(endAngle), mathSin(endAngle), isCircle, mathFloor(mathAbs(endAngle - startAngle) / mathPI) % 2 ? "1" : "0", noArc]
        };
        var buildArcPath = function(x, y, innerR, outerR, startAngleCos, startAngleSin, endAngleCos, endAngleSin, isCircle, longFlag) {
                return ["M", (x + outerR * startAngleCos).toFixed(ARC_COORD_PREC), (y - outerR * startAngleSin).toFixed(ARC_COORD_PREC), "A", outerR.toFixed(ARC_COORD_PREC), outerR.toFixed(ARC_COORD_PREC), 0, longFlag, 0, (x + outerR * endAngleCos).toFixed(ARC_COORD_PREC), (y - outerR * endAngleSin).toFixed(ARC_COORD_PREC), isCircle ? "M" : "L", (x + innerR * endAngleCos).toFixed(5), (y - innerR * endAngleSin).toFixed(ARC_COORD_PREC), "A", innerR.toFixed(ARC_COORD_PREC), innerR.toFixed(ARC_COORD_PREC), 0, longFlag, 1, (x + innerR * startAngleCos).toFixed(ARC_COORD_PREC), (y - innerR * startAngleSin).toFixed(ARC_COORD_PREC), "Z"].join(" ")
            };
        function buildPathSegments(points, type) {
            var list = [["M", 0, 0]];
            switch (type) {
                case"line":
                    list = buildLineSegments(points);
                    break;
                case"area":
                    list = buildLineSegments(points, true);
                    break;
                case"bezier":
                    list = buildCurveSegments(points);
                    break;
                case"bezierarea":
                    list = buildCurveSegments(points, true);
                    break
            }
            return list
        }
        function buildLineSegments(points, close) {
            return buildSegments(points, buildSimpleLineSegment, close)
        }
        function buildCurveSegments(points, close) {
            return buildSegments(points, buildSimpleCurveSegment, close)
        }
        function buildSegments(points, buildSimpleSegment, close) {
            var i = 0,
                ii = (points || []).length,
                list = [];
            if (isArray(points[0]))
                for (; i < ii; )
                    buildSimpleSegment(points[i++], close, list);
            else
                buildSimpleSegment(points, close, list);
            return list
        }
        function buildSimpleLineSegment(points, close, list) {
            var i = 0,
                ii = (points || []).length;
            if (ii)
                if (isObject(points[0]))
                    for (; i < ii; )
                        list.push([!i ? "M" : "L", points[i].x, points[i++].y]);
                else
                    for (; i < ii; )
                        list.push([!i ? "M" : "L", points[i++], points[i++]]);
            else
                list.push(["M", 0, 0]);
            close && list.push(["Z"]);
            return list
        }
        function buildSimpleCurveSegment(points, close, list) {
            var i = 2,
                ii = (points || []).length;
            if (ii)
                if (isObject(points[0])) {
                    i = 1;
                    list.push(["M", points[0].x, points[0].y]);
                    for (; i < ii; )
                        list.push(["C", points[i].x, points[i++].y, points[i].x, points[i++].y, points[i].x, points[i++].y])
                }
                else {
                    list.push(["M", points[0], points[1]]);
                    for (; i < ii; )
                        list.push(["C", points[i++], points[i++], points[i++], points[i++], points[i++], points[i++]])
                }
            else
                list.push(["M", 0, 0]);
            close && list.push(["Z"]);
            return list
        }
        function combinePathParam(segments) {
            var d = [],
                i = 0,
                length = segments.length;
            for (; i < length; i++)
                d.push(segments[i].join(" "));
            return d.join(" ")
        }
        function compensateSegments(oldSegments, newSegments, type) {
            var oldLength = oldSegments.length,
                newLength = newSegments.length,
                i,
                originalNewSegments,
                makeEqualSegments = type.indexOf("area") !== -1 ? makeEqualAreaSegments : makeEqualLineSegments;
            if (oldLength === 0)
                for (i = 0; i < newLength; i++)
                    oldSegments.push(newSegments[i].slice(0));
            else if (oldLength < newLength)
                makeEqualSegments(oldSegments, newSegments, type);
            else if (oldLength > newLength) {
                originalNewSegments = newSegments.slice(0);
                makeEqualSegments(newSegments, oldSegments, type)
            }
            return originalNewSegments
        }
        function prepareConstSegment(constSeg, type) {
            var x = constSeg[constSeg.length - 2],
                y = constSeg[constSeg.length - 1];
            switch (type) {
                case"line":
                case"area":
                    constSeg[0] = "L";
                    break;
                case"bezier":
                case"bezierarea":
                    constSeg[0] = "C";
                    constSeg[1] = constSeg[3] = constSeg[5] = x;
                    constSeg[2] = constSeg[4] = constSeg[6] = y;
                    break
            }
        }
        function makeEqualLineSegments(short, long, type) {
            var constSeg = short[short.length - 1].slice(),
                i = short.length;
            prepareConstSegment(constSeg, type);
            for (; i < long.length; i++)
                short[i] = constSeg.slice(0)
        }
        function makeEqualAreaSegments(short, long, type) {
            var i,
                head,
                shortLength = short.length,
                longLength = long.length,
                constsSeg1,
                constsSeg2;
            if ((shortLength - 1) % 2 === 0 && (longLength - 1) % 2 === 0) {
                i = (shortLength - 1) / 2 - 1;
                head = short.slice(0, i + 1);
                constsSeg1 = head[head.length - 1].slice(0);
                constsSeg2 = short.slice(i + 1)[0].slice(0);
                prepareConstSegment(constsSeg1, type);
                prepareConstSegment(constsSeg2, type);
                for (var j = i; j < (longLength - 1) / 2 - 1; j++) {
                    short.splice(j + 1, 0, constsSeg1);
                    short.splice(j + 3, 0, constsSeg2)
                }
            }
        }
        function baseCss(styles) {
            var elemStyles = this._styles,
                str = "",
                key,
                value;
            extend(elemStyles, styles || {}, true);
            for (key in elemStyles) {
                value = elemStyles[key];
                if (value === "")
                    continue;
                if (typeof value === "number" && !pxAddingExceptions[key])
                    value += "px";
                str += key + ":" + value + ";"
            }
            str && this.element.setAttribute("style", str);
            return this
        }
        function baseAttr(attrs) {
            attrs = attrs || {};
            var that = this,
                settings = that._settings,
                attributes = {},
                key,
                value,
                elem = that.element,
                renderer = that.renderer,
                rtl = renderer.rtl,
                hasTransformations,
                recalculateDashStyle,
                sw,
                i;
            if (!isObjectArgument(attrs)) {
                if (attrs in settings)
                    return settings[attrs];
                if (attrs in DEFAULTS)
                    return DEFAULTS[attrs];
                return 0
            }
            extend(attributes, attrs);
            for (key in attributes) {
                value = attributes[key];
                if (value === undefined)
                    continue;
                settings[key] = value;
                if (key === "align") {
                    key = "text-anchor";
                    value = {
                        left: rtl ? "end" : "start",
                        center: "middle",
                        right: rtl ? "start" : "end"
                    }[value] || ""
                }
                else if (key === "dashStyle") {
                    recalculateDashStyle = true;
                    continue
                }
                else if (key === KEY_STROKE_WIDTH)
                    recalculateDashStyle = true;
                else if (key === "clipId") {
                    key = "clip-path";
                    value = getPatternUrl(value, renderer.pathModified)
                }
                else if (/^(translate(X|Y)|rotate[XY]?|scale(X|Y)|sharp)$/i.test(key)) {
                    hasTransformations = true;
                    continue
                }
                else if (/^(x|y|d)$/i.test(key))
                    hasTransformations = true;
                if (value === null)
                    elem.removeAttribute(key);
                else
                    elem.setAttribute(key, value)
            }
            if (recalculateDashStyle && "dashStyle" in settings) {
                value = settings.dashStyle;
                sw = ("_originalSW" in that ? that._originalSW : settings[KEY_STROKE_WIDTH]) || 1;
                key = "stroke-dasharray";
                value = value === null ? "" : value.toLowerCase();
                if (value === "" || value === "solid" || value === NONE)
                    that.element.removeAttribute(key);
                else {
                    value = value.replace(/longdash/g, "8,3,").replace(/dash/g, "4,3,").replace(/dot/g, "1,3,").replace(/,$/, "").split(",");
                    i = value.length;
                    while (i--)
                        value[i] = _parseInt(value[i]) * sw;
                    that.element.setAttribute(key, value.join(","))
                }
            }
            if (hasTransformations)
                that._applyTransformation();
            return that
        }
        function createPathAttr(baseAttr) {
            return function(attrs, inh) {
                    var that = this,
                        segments;
                    if (isObjectArgument(attrs)) {
                        attrs = extend({}, attrs);
                        segments = attrs.segments;
                        if ("points" in attrs) {
                            segments = buildPathSegments(attrs.points, that.type);
                            delete attrs.points
                        }
                        if (segments) {
                            attrs.d = combinePathParam(segments);
                            that.segments = segments;
                            delete attrs.segments
                        }
                    }
                    return baseAttr.call(that, attrs, inh)
                }
        }
        function createArcAttr(baseAttr, buildArcPath) {
            return function(attrs, inh) {
                    var settings = this._settings,
                        x,
                        y,
                        innerRadius,
                        outerRadius,
                        startAngle,
                        endAngle;
                    if (isObjectArgument(attrs)) {
                        attrs = extend({}, attrs);
                        if ("x" in attrs || "y" in attrs || "innerRadius" in attrs || "outerRadius" in attrs || "startAngle" in attrs || "endAngle" in attrs) {
                            settings.x = x = "x" in attrs ? attrs.x : settings.x;
                            delete attrs.x;
                            settings.y = y = "y" in attrs ? attrs.y : settings.y;
                            delete attrs.y;
                            settings.innerRadius = innerRadius = "innerRadius" in attrs ? attrs.innerRadius : settings.innerRadius;
                            delete attrs.innerRadius;
                            settings.outerRadius = outerRadius = "outerRadius" in attrs ? attrs.outerRadius : settings.outerRadius;
                            delete attrs.outerRadius;
                            settings.startAngle = startAngle = "startAngle" in attrs ? attrs.startAngle : settings.startAngle;
                            delete attrs.startAngle;
                            settings.endAngle = endAngle = "endAngle" in attrs ? attrs.endAngle : settings.endAngle;
                            delete attrs.endAngle;
                            attrs.d = buildArcPath.apply(this, rendererNS._normalizeArcParams(x, y, innerRadius, outerRadius, startAngle, endAngle))
                        }
                    }
                    return baseAttr.call(this, attrs, inh)
                }
        }
        function createRectAttr(baseAttr) {
            return function(attrs, inh) {
                    var that = this,
                        x,
                        y,
                        width,
                        height,
                        sw,
                        maxSW,
                        newSW;
                    if (isObjectArgument(attrs)) {
                        attrs = extend({}, attrs);
                        if (!inh && (attrs.x !== undefined || attrs.y !== undefined || attrs.width !== undefined || attrs.height !== undefined || attrs[KEY_STROKE_WIDTH] !== undefined)) {
                            attrs.x !== undefined ? x = that._originalX = attrs.x : x = that._originalX || 0;
                            attrs.y !== undefined ? y = that._originalY = attrs.y : y = that._originalY || 0;
                            attrs.width !== undefined ? width = that._originalWidth = attrs.width : width = that._originalWidth || 0;
                            attrs.height !== undefined ? height = that._originalHeight = attrs.height : height = that._originalHeight || 0;
                            attrs[KEY_STROKE_WIDTH] !== undefined ? sw = that._originalSW = attrs[KEY_STROKE_WIDTH] : sw = that._originalSW;
                            maxSW = ~~((width < height ? width : height) / 2);
                            newSW = (sw || 0) < maxSW ? sw || 0 : maxSW;
                            attrs.x = x + newSW / 2;
                            attrs.y = y + newSW / 2;
                            attrs.width = width - newSW;
                            attrs.height = height - newSW;
                            ((sw || 0) !== newSW || !(newSW === 0 && sw === undefined)) && (attrs[KEY_STROKE_WIDTH] = newSW)
                        }
                        if ("sharp" in attrs)
                            delete attrs.sharp
                    }
                    return baseAttr.call(that, attrs, inh)
                }
        }
        var pathAttr = createPathAttr(baseAttr),
            arcAttr = createArcAttr(baseAttr, buildArcPath),
            rectAttr = createRectAttr(baseAttr);
        function textAttr(attrs) {
            var that = this,
                settings,
                isResetRequired,
                wasStroked,
                isStroked;
            if (!isObjectArgument(attrs))
                return baseAttr.call(that, attrs);
            attrs = extend({}, attrs);
            settings = that._settings;
            wasStroked = isDefined(settings[KEY_STROKE]) && isDefined(settings[KEY_STROKE_WIDTH]);
            if (attrs[KEY_TEXT] !== undefined) {
                settings[KEY_TEXT] = attrs[KEY_TEXT];
                delete attrs[KEY_TEXT];
                isResetRequired = true
            }
            if (attrs[KEY_STROKE] !== undefined) {
                settings[KEY_STROKE] = attrs[KEY_STROKE];
                delete attrs[KEY_STROKE]
            }
            if (attrs[KEY_STROKE_WIDTH] !== undefined) {
                settings[KEY_STROKE_WIDTH] = attrs[KEY_STROKE_WIDTH];
                delete attrs[KEY_STROKE_WIDTH]
            }
            if (attrs[KEY_STROKE_OPACITY] !== undefined) {
                settings[KEY_STROKE_OPACITY] = attrs[KEY_STROKE_OPACITY];
                delete attrs[KEY_STROKE_OPACITY]
            }
            isStroked = isDefined(settings[KEY_STROKE]) && isDefined(settings[KEY_STROKE_WIDTH]);
            baseAttr.call(that, attrs);
            isResetRequired = isResetRequired || isStroked !== wasStroked && settings[KEY_TEXT];
            if (isResetRequired)
                createTextNodes(that, settings.text, isStroked);
            if (isResetRequired || attrs["x"] !== undefined || attrs["y"] !== undefined)
                locateTextNodes(that);
            if (isStroked)
                strokeTextNodes(that);
            return that
        }
        function textCss(styles) {
            styles = styles || {};
            baseCss.call(this, styles);
            if (KEY_FONT_SIZE in styles)
                locateTextNodes(this);
            return this
        }
        function orderHtmlTree(strCount, node, textArray) {
            var nodeParams = node.params = node.params || {style: {}},
                nodeStyle = nodeParams.style,
                parentStyle = node.parentNode && node.parentNode.params && node.parentNode.params.style || {},
                nativeElementStyle = node.style,
                childCount = node.childNodes.length,
                count = 0;
            if (node.nodeName !== '#text')
                extend(nodeStyle, parentStyle);
            switch (node.tagName) {
                case'B':
                case'STRONG':
                    nodeStyle[KEY_FONT_WEIGHT] = 'bold';
                    break;
                case'I':
                case'EM':
                    nodeStyle[KEY_FONT_STYLE] = 'italic';
                    break;
                case'U':
                    nodeStyle[KEY_TEXT_DECORATION] = 'underline';
                    break;
                case'BR':
                    strCount++;
                    break
            }
            if (nativeElementStyle) {
                if (nativeElementStyle.fontSize)
                    nodeStyle[KEY_FONT_SIZE] = (_parseInt(nativeElementStyle.fontSize, 10) || nodeStyle[KEY_FONT_SIZE]) + 'px';
                nodeStyle.fill = nativeElementStyle.color || nodeStyle.fill;
                nodeStyle[KEY_FONT_STYLE] = nativeElementStyle.fontStyle || nodeStyle[KEY_FONT_STYLE];
                nodeStyle[KEY_FONT_WEIGHT] = nativeElementStyle.fontWeight || nodeStyle[KEY_FONT_WEIGHT];
                nodeStyle[KEY_TEXT_DECORATION] = nativeElementStyle.textDecoration || nodeStyle[KEY_TEXT_DECORATION]
            }
            while (count !== childCount)
                strCount = orderHtmlTree(strCount, node.childNodes[count++], textArray);
            if (node.wholeText !== undefined) {
                extend(nodeStyle, parentStyle);
                textArray.push({
                    value: node.wholeText,
                    style: nodeStyle,
                    line: strCount,
                    height: _parseInt(nodeStyle[KEY_FONT_SIZE], 10) || 0
                })
            }
            return strCount
        }
        function adjustLineHeights(items) {
            var i,
                ii,
                currentItem = items[0],
                item;
            for (i = 1, ii = items.length; i < ii; ++i) {
                item = items[i];
                if (item.line === currentItem.line) {
                    currentItem.height = mathMax(currentItem.height, item.height);
                    currentItem.inherits = currentItem.inherits || item.height === 0;
                    item.height = NaN
                }
                else
                    currentItem = item
            }
        }
        function parseHTML(text) {
            var items = [],
                div = doc.createElement("div");
            div.innerHTML = text.replace(/\r/g, "").replace(/\n/g, "
");
            orderHtmlTree(0, div, items);
            adjustLineHeights(items);
            return items
        }
        function parseMultiline(text) {
            var texts = text.replace(/\r/g, "").split("\n"),
                i = 0,
                items = [];
            for (; i < texts.length; i++)
                items.push({
                    value: texts[i],
                    height: 0
                });
            return items
        }
        function createTspans(items, element, fieldName) {
            var i,
                ii,
                item;
            for (i = 0, ii = items.length; i < ii; ++i) {
                item = items[i];
                item[fieldName] = createElement("tspan");
                item[fieldName].appendChild(doc.createTextNode(item.value));
                item.style && baseCss.call({
                    element: item[fieldName],
                    _styles: {}
                }, item.style);
                element.appendChild(item[fieldName])
            }
        }
        function createTextNodes(wrapper, text, isStroked) {
            var items;
            wrapper._texts = null;
            wrapper.clear();
            if (text === null)
                return;
            text = "" + text;
            if (!wrapper.renderer.encodeHtml && (text.indexOf("<") !== -1 || text.indexOf("&") !== -1))
                items = parseHTML(text);
            else if (text.indexOf("\n") !== -1)
                items = parseMultiline(text);
            else if (isStroked)
                items = [{
                        value: text,
                        height: 0
                    }];
            if (items) {
                if (items.length) {
                    wrapper._texts = items;
                    if (isStroked)
                        createTspans(items, wrapper.element, KEY_STROKE);
                    createTspans(items, wrapper.element, "tspan")
                }
            }
            else
                wrapper.element.appendChild(doc.createTextNode(text))
        }
        function setTextNodeAttribute(item, name, value) {
            item.tspan.setAttribute(name, value);
            item.stroke && item.stroke.setAttribute(name, value)
        }
        function locateTextNodes(wrapper) {
            if (!wrapper._texts)
                return;
            var items = wrapper._texts,
                x = wrapper._settings.x,
                lineHeight = wrapper._styles[KEY_FONT_SIZE] || 12,
                i,
                ii,
                item = items[0];
            setTextNodeAttribute(item, "x", x);
            setTextNodeAttribute(item, "y", wrapper._settings.y);
            for (i = 1, ii = items.length; i < ii; ++i) {
                item = items[i];
                if (item.height >= 0) {
                    setTextNodeAttribute(item, "x", x);
                    setTextNodeAttribute(item, "dy", item.inherits ? mathMax(item.height, lineHeight) : item.height || lineHeight)
                }
            }
        }
        function strokeTextNodes(wrapper) {
            if (!wrapper._texts)
                return;
            var items = wrapper._texts,
                stroke = wrapper._settings[KEY_STROKE],
                strokeWidth = wrapper._settings[KEY_STROKE_WIDTH],
                strokeOpacity = wrapper._settings[KEY_STROKE_OPACITY] || 1,
                tspan,
                i,
                ii;
            for (i = 0, ii = items.length; i < ii; ++i) {
                tspan = items[i].stroke;
                tspan.setAttribute(KEY_STROKE, stroke);
                tspan.setAttribute(KEY_STROKE_WIDTH, strokeWidth);
                tspan.setAttribute(KEY_STROKE_OPACITY, strokeOpacity);
                tspan.setAttribute("stroke-linejoin", "round")
            }
        }
        function baseAnimate(params, options, complete) {
            options = options || {};
            var that = this,
                key,
                value,
                renderer = that.renderer,
                settings = that._settings,
                animationParams = {};
            var defaults = {
                    translateX: 0,
                    translateY: 0,
                    scaleX: 1,
                    scaleY: 1,
                    rotate: 0,
                    rotateX: 0,
                    rotateY: 0
                };
            if (complete)
                options.complete = complete;
            if (renderer.animationEnabled()) {
                for (key in params) {
                    value = params[key];
                    if (/^(translate(X|Y)|rotate[XY]?|scale(X|Y))$/i.test(key)) {
                        animationParams.transform = animationParams.transform || {
                            from: {},
                            to: {}
                        };
                        animationParams.transform.from[key] = key in settings ? settings[key] : defaults[key];
                        animationParams.transform.to[key] = value
                    }
                    else if (key === "arc" || key === "segments")
                        animationParams[key] = value;
                    else
                        animationParams[key] = {
                            from: key in settings ? settings[key] : parseFloat(that.element.getAttribute(key) || 0),
                            to: value
                        }
                }
                renderer.animateElement(that, animationParams, extend(extend({}, renderer._animation), options))
            }
            else {
                options.step && options.step.call(that, 1, 1);
                options.complete && options.complete.call(that);
                that.attr(params)
            }
            return that
        }
        function pathAnimate(params, options, complete) {
            var that = this,
                curSegments = that.segments || [],
                newSegments,
                endSegments;
            if (that.renderer.animationEnabled() && "points" in params) {
                newSegments = buildPathSegments(params.points, that.type);
                endSegments = compensateSegments(curSegments, newSegments, that.type);
                params.segments = {
                    from: curSegments,
                    to: newSegments,
                    end: endSegments
                };
                delete params.points
            }
            return baseAnimate.call(that, params, options, complete)
        }
        function arcAnimate(params, options, complete) {
            var that = this,
                settings = that._settings,
                arcParams = {
                    from: {},
                    to: {}
                };
            if (that.renderer.animationEnabled() && ("x" in params || "y" in params || "innerRadius" in params || "outerRadius" in params || "startAngle" in params || "endAngle" in params)) {
                arcParams.from.x = settings.x || 0;
                arcParams.from.y = settings.y || 0;
                arcParams.from.innerRadius = settings.innerRadius || 0;
                arcParams.from.outerRadius = settings.outerRadius || 0;
                arcParams.from.startAngle = settings.startAngle || 0;
                arcParams.from.endAngle = settings.endAngle || 0;
                arcParams.to.x = "x" in params ? params.x : settings.x;
                delete params.x;
                arcParams.to.y = "y" in params ? params.y : settings.y;
                delete params.y;
                arcParams.to.innerRadius = "innerRadius" in params ? params.innerRadius : settings.innerRadius;
                delete params.innerRadius;
                arcParams.to.outerRadius = "outerRadius" in params ? params.outerRadius : settings.outerRadius;
                delete params.outerRadius;
                arcParams.to.startAngle = "startAngle" in params ? params.startAngle : settings.startAngle;
                delete params.startAngle;
                arcParams.to.endAngle = "endAngle" in params ? params.endAngle : settings.endAngle;
                delete params.endAngle;
                params.arc = arcParams
            }
            return baseAnimate.call(that, params, options, complete)
        }
        rendererNS.__mockPrivateFunctions = function(fs) {
            fs = fs || {};
            function mockFunction(mock, orig) {
                if (!mock)
                    return orig;
                var originalFunction = orig;
                orig = mock;
                orig._originalFunction = originalFunction;
                return orig
            }
            createElement = mockFunction(fs.createElement, createElement);
            baseAttr = mockFunction(fs.baseAttr, baseAttr);
            baseAnimate = mockFunction(fs.baseAnimate, baseAnimate);
            getNextDefsSvgId = mockFunction(fs.getNextDefsSvgId, getNextDefsSvgId);
            compensateSegments = mockFunction(fs.compensateSegments, compensateSegments);
            buildPathSegments = mockFunction(fs.buildPathSegments, buildPathSegments);
            buildArcPath = mockFunction(fs.buildArcPath, buildArcPath);
            pathAttr = createPathAttr(baseAttr);
            arcAttr = createArcAttr(baseAttr, buildArcPath);
            rectAttr = createRectAttr(baseAttr);
            return {
                    createElement: createElement,
                    baseAttr: baseAttr,
                    baseAnimate: baseAnimate,
                    getNextDefsSvgId: getNextDefsSvgId,
                    compensateSegments: compensateSegments,
                    buildPathSegments: buildPathSegments,
                    buildArcPath: buildArcPath
                }
        };
        rendererNS.__restoreMockPrivateFunctions = function() {
            function restoreFunction(func) {
                return func._originalFunction || func
            }
            createElement = restoreFunction(createElement);
            baseAttr = restoreFunction(baseAttr);
            baseAnimate = restoreFunction(baseAnimate);
            getNextDefsSvgId = restoreFunction(getNextDefsSvgId);
            compensateSegments = restoreFunction(compensateSegments);
            buildPathSegments = restoreFunction(buildPathSegments);
            buildArcPath = restoreFunction(buildArcPath);
            pathAttr = createPathAttr(baseAttr);
            arcAttr = createArcAttr(baseAttr, buildArcPath);
            rectAttr = createRectAttr(baseAttr)
        };
        function SvgElement() {
            this.ctor.apply(this, arguments)
        }
        rendererNS.SvgElement = SvgElement;
        SvgElement.prototype = {
            ctor: function(renderer, tagName, type) {
                var that = this;
                that.renderer = renderer;
                that.element = createElement(tagName);
                that._settings = {};
                that._styles = {};
                if (tagName === "path")
                    that.type = type || "line";
                if (tagName === "text") {
                    that.attr = textAttr;
                    that.css = textCss
                }
                else if (tagName === "path")
                    if (that.type === "arc") {
                        that.attr = arcAttr;
                        that.animate = arcAnimate
                    }
                    else {
                        that.attr = pathAttr;
                        that.animate = pathAnimate
                    }
                else if (tagName === "rect") {
                    that.attr = rectAttr;
                    that.sharp = function() {
                        return this
                    }
                }
                that._$element = $(that.element)
            },
            dispose: function() {
                this._$element.remove();
                return this
            },
            append: function(parent) {
                parent = parent || this.renderer.root;
                (parent.element || parent).appendChild(this.element);
                return this
            },
            remove: function() {
                var elem = this.element,
                    parent = elem.parentNode;
                parent && parent.removeChild(elem);
                return this
            },
            clear: function() {
                this._$element.empty();
                return this
            },
            toBackground: function() {
                var elem = this.element,
                    parent = elem.parentNode;
                parent && parent.insertBefore(elem, parent.firstChild);
                return this
            },
            toForeground: function() {
                var elem = this.element,
                    parent = elem.parentNode;
                parent && parent.appendChild(elem);
                return this
            },
            css: baseCss,
            attr: baseAttr,
            sharp: function(pos) {
                return this.attr({sharp: pos || true})
            },
            _applyTransformation: function() {
                var tr = this._settings,
                    scaleXDefined,
                    scaleYDefined,
                    transformations = [],
                    rotateX,
                    rotateY,
                    sharpMode = tr.sharp,
                    strokeOdd = tr[KEY_STROKE_WIDTH] % 2,
                    correctionX = strokeOdd && (sharpMode === "h" || sharpMode === true) ? SHARPING_CORRECTION : 0,
                    correctionY = strokeOdd && (sharpMode === "v" || sharpMode === true) ? SHARPING_CORRECTION : 0;
                if (!("rotateX" in tr))
                    rotateX = tr.x;
                else
                    rotateX = tr.rotateX;
                if (!("rotateY" in tr))
                    rotateY = tr.y;
                else
                    rotateY = tr.rotateY;
                transformations.push("translate(" + ((tr.translateX || 0) + correctionX) + "," + ((tr.translateY || 0) + correctionY) + ")");
                if (tr.rotate)
                    transformations.push("rotate(" + tr.rotate + "," + (rotateX || 0) + "," + (rotateY || 0) + ")");
                scaleXDefined = isDefined(tr.scaleX);
                scaleYDefined = isDefined(tr.scaleY);
                if (scaleXDefined || scaleYDefined)
                    transformations.push("scale(" + (scaleXDefined ? tr.scaleX : 1) + "," + (scaleYDefined ? tr.scaleY : 1) + ")");
                if (transformations.length)
                    this.element.setAttribute("transform", transformations.join(" "))
            },
            move: function(x, y, animate, animOptions) {
                var obj = {};
                isDefined(x) && (obj.translateX = x);
                isDefined(y) && (obj.translateY = y);
                if (!animate)
                    this.attr(obj);
                else
                    this.animate(obj, animOptions);
                return this
            },
            rotate: function(angle, x, y, animate, animOptions) {
                var obj = {rotate: angle || 0};
                isDefined(x) && (obj.rotateX = x);
                isDefined(y) && (obj.rotateY = y);
                if (!animate)
                    this.attr(obj);
                else
                    this.animate(obj, animOptions);
                return this
            },
            getBBox: function() {
                var elem = this.element,
                    transformation = this._settings,
                    bBox;
                try {
                    bBox = elem.getBBox && elem.getBBox()
                }
                catch(e) {}
                bBox = bBox || {
                    x: 0,
                    y: 0,
                    width: elem.offsetWidth || 0,
                    height: elem.offsetHeight || 0
                };
                if (transformation.rotate)
                    bBox = rotateBBox(bBox, [("rotateX" in transformation ? transformation.rotateX : transformation.x) || 0, ("rotateY" in transformation ? transformation.rotateY : transformation.y) || 0], -transformation.rotate);
                else
                    bBox = normalizeBBox(bBox);
                return bBox
            },
            markup: function() {
                var temp = doc.createElement('div'),
                    node = this.element.cloneNode(true);
                temp.appendChild(node);
                return temp.innerHTML
            },
            getOffset: function() {
                return this._$element.offset()
            },
            animate: baseAnimate,
            stopAnimation: function(disableComplete) {
                var animation = this.animation;
                animation && animation.stop(true, disableComplete);
                return this
            },
            setTitle: function(text) {
                var titleElem = createElement('title');
                titleElem.textContent = text || '';
                this.element.appendChild(titleElem)
            },
            on: function() {
                $.fn.on.apply(this._$element, arguments);
                return this
            },
            off: function() {
                $.fn.off.apply(this._$element, arguments);
                return this
            },
            trigger: function() {
                $.fn.trigger.apply(this._$element, arguments);
                return this
            },
            data: function() {
                $.fn.data.apply(this._$element, arguments);
                return this
            }
        };
        function SvgRenderer(options) {
            var that = this;
            that.root = that._createElement("svg", {
                xmlns: "http://www.w3.org/2000/svg",
                "xmlns:xlink": "http://www.w3.org/1999/xlink",
                version: "1.1",
                fill: NONE,
                stroke: NONE,
                "stroke-width": 0,
                "class": options.cssClass
            }).css({
                "line-height": "normal",
                "-ms-user-select": NONE,
                "-moz-user-select": NONE,
                "-webkit-user-select": NONE,
                "-webkit-tap-highlight-color": "rgba(0, 0, 0, 0)",
                display: "block",
                overflow: "hidden"
            });
            that._defs = that._createElement("defs");
            that._animationController = new rendererNS.AnimationController(that.root.element);
            that._animation = {
                enabled: true,
                duration: 1000,
                easing: "easeOutCubic"
            }
        }
        rendererNS.SvgRenderer = SvgRenderer;
        SvgRenderer.prototype = {
            constructor: SvgRenderer,
            setOptions: function(options) {
                var that = this;
                that.pathModified = !!options.pathModified;
                that.rtl = !!options.rtl;
                that.encodeHtml = !!options.encodeHtml,
                that.updateAnimationOptions(options.animation || {});
                that.root.attr({direction: that.rtl ? "rtl" : "ltr"})
            },
            _createElement: function(tagName, attr, type) {
                var elem = new rendererNS.SvgElement(this, tagName, type);
                attr && elem.attr(attr);
                return elem
            },
            draw: function(container) {
                var that = this;
                if (!container || that.drawn)
                    return that;
                that.root.append(container);
                that._defs.append(that.root);
                that.drawn = true;
                return that
            },
            resize: function(width, height) {
                if (width >= 0 && height >= 0)
                    this.root.attr({
                        width: width,
                        height: height
                    });
                return this
            },
            clear: function() {
                var that = this;
                that.root.remove();
                that._defs.remove();
                that.drawn = null;
                return this
            },
            dispose: function() {
                var that = this,
                    key;
                that.root.dispose();
                that._defs.dispose();
                that._animationController.dispose();
                for (key in that)
                    that[key] = null;
                return null
            },
            animationEnabled: function() {
                return !!this._animation.enabled
            },
            updateAnimationOptions: function(newOptions) {
                extend(this._animation, newOptions);
                return this
            },
            stopAllAnimations: function(lock) {
                this._animationController[lock ? "lock" : "stop"]();
                return this
            },
            animateElement: function(element, params, options) {
                this._animationController.animateElement(element, params, options);
                return this
            },
            svg: function() {
                return this.root.markup()
            },
            getRootOffset: function() {
                return this.root.getOffset()
            },
            onEndAnimation: function(endAnimation) {
                this._animationController.onEndAnimation(endAnimation)
            },
            rect: function(x, y, width, height) {
                return this._createElement("rect", {
                        x: x || 0,
                        y: y || 0,
                        width: width || 0,
                        height: height || 0
                    })
            },
            circle: function(x, y, r) {
                return this._createElement("circle", {
                        cx: x || 0,
                        cy: y || 0,
                        r: r || 0
                    })
            },
            g: function() {
                return this._createElement("g")
            },
            image: function(x, y, w, h, href, location) {
                var image = this._createElement("image", {
                        x: x || 0,
                        y: y || 0,
                        width: w || 0,
                        height: h || 0,
                        preserveAspectRatio: getPreserveAspectRatio(location)
                    });
                image.element.setAttributeNS("http://www.w3.org/1999/xlink", "href", href || "");
                return image
            },
            path: function(points, type) {
                return this._createElement("path", {points: points || []}, type)
            },
            arc: function(x, y, innerRadius, outerRadius, startAngle, endAngle) {
                return this._createElement("path", {
                        x: x || 0,
                        y: y || 0,
                        innerRadius: innerRadius || 0,
                        outerRadius: outerRadius || 0,
                        startAngle: startAngle || 0,
                        endAngle: endAngle || 0
                    }, "arc")
            },
            text: function(text, x, y) {
                return this._createElement("text", {
                        text: text,
                        x: x || 0,
                        y: y || 0
                    })
            },
            pattern: function(color, hatching) {
                hatching = hatching || {};
                var that = this,
                    id,
                    d,
                    pattern,
                    rect,
                    path,
                    step = hatching.step || 6,
                    stepTo2 = step / 2,
                    stepBy15 = step * 1.5,
                    direction = (hatching.direction || "").toLowerCase();
                if (direction !== "right" && direction !== "left")
                    return {
                            id: color,
                            append: function() {
                                return this
                            },
                            clear: function(){},
                            dispose: function(){},
                            remove: function(){}
                        };
                id = getNextDefsSvgId();
                d = direction === "right" ? "M " + stepTo2 + " " + -stepTo2 + " L " + -stepTo2 + " " + stepTo2 + " M 0 " + step + " L " + step + " 0 M " + stepBy15 + " " + stepTo2 + " L " + stepTo2 + " " + stepBy15 : "M 0 0 L " + step + " " + step + " M " + -stepTo2 + " " + stepTo2 + " L " + stepTo2 + " " + stepBy15 + " M " + stepTo2 + " " + -stepTo2 + " L " + stepBy15 + " " + stepTo2;
                pattern = that._createElement("pattern", {
                    id: id,
                    width: step,
                    height: step,
                    patternUnits: "userSpaceOnUse"
                }).append(that._defs);
                pattern.id = getPatternUrl(id, that.pathModified);
                rect = that.rect(0, 0, step, step).attr({
                    fill: color,
                    opacity: hatching.opacity
                }).append(pattern);
                path = that._createElement("path", {
                    d: d,
                    "stroke-width": hatching.width || 1,
                    stroke: color
                }).append(pattern);
                pattern.rect = rect;
                pattern.path = path;
                return pattern
            },
            clipRect: function(x, y, width, height) {
                var that = this,
                    id = getNextDefsSvgId(),
                    clipPath = that._createElement("clipPath", {id: id}).append(that._defs),
                    rect = that.rect(x, y, width, height).append(clipPath);
                rect.id = id;
                rect.clipPath = clipPath;
                rect.remove = function() {
                    throw"Not implemented";
                };
                rect.dispose = function() {
                    clipPath.dispose();
                    clipPath = null;
                    return this
                };
                return rect
            },
            shadowFilter: function(x, y, width, height, offsetX, offsetY, blur, color, opacity) {
                var that = this,
                    id = getNextDefsSvgId(),
                    filter = that._createElement("filter", {
                        id: id,
                        x: x || 0,
                        y: y || 0,
                        width: width || 0,
                        height: height || 0
                    }).append(that._defs),
                    gaussianBlur = that._createElement("feGaussianBlur", {
                        "in": "SourceGraphic",
                        result: "gaussianBlurResult",
                        stdDeviation: blur || 0
                    }).append(filter),
                    offset = that._createElement("feOffset", {
                        "in": "gaussianBlurResult",
                        result: "offsetResult",
                        dx: offsetX || 0,
                        dy: offsetY || 0
                    }).append(filter),
                    flood = that._createElement("feFlood", {
                        result: "floodResult",
                        "flood-color": color || "",
                        "flood-opacity": opacity
                    }).append(filter),
                    composite = that._createElement("feComposite", {
                        "in": "floodResult",
                        in2: "offsetResult",
                        operator: "in",
                        result: "compositeResult"
                    }).append(filter),
                    finalComposite = that._createElement("feComposite", {
                        "in": "SourceGraphic",
                        in2: "compositeResult",
                        operator: "over"
                    }).append(filter);
                filter.ref = getPatternUrl(id, that.pathModified);
                filter.gaussianBlur = gaussianBlur;
                filter.offset = offset;
                filter.flood = flood;
                filter.composite = composite;
                filter.finalComposite = finalComposite;
                filter.attr = function(attrs) {
                    var that = this,
                        filterAttrs = {},
                        offsetAttrs = {},
                        floodAttrs = {};
                    "x" in attrs && (filterAttrs.x = attrs.x);
                    "y" in attrs && (filterAttrs.y = attrs.y);
                    "width" in attrs && (filterAttrs.width = attrs.width);
                    "height" in attrs && (filterAttrs.height = attrs.height);
                    baseAttr.call(that, filterAttrs);
                    "blur" in attrs && that.gaussianBlur.attr({stdDeviation: attrs.blur});
                    "offsetX" in attrs && (offsetAttrs.dx = attrs.offsetX);
                    "offsetY" in attrs && (offsetAttrs.dy = attrs.offsetY);
                    that.offset.attr(offsetAttrs);
                    "color" in attrs && (floodAttrs["flood-color"] = attrs.color);
                    "opacity" in attrs && (floodAttrs["flood-opacity"] = attrs.opacity);
                    that.flood.attr(floodAttrs);
                    return that
                };
                return filter
            }
        };
        rendererNS.rotateBBox = rotateBBox;
        rendererNS._createArcAttr = createArcAttr;
        rendererNS._createPathAttr = createPathAttr;
        rendererNS._createRectAttr = createRectAttr
    })(jQuery, DevExpress, document);
    /*! Module viz-core, file vmlRenderer.js */
    (function($, DX, doc) {
        DX.viz.renderers = DX.viz.renderers || {};
        var rendererNS = DX.viz.renderers,
            math = Math,
            mathMin = math.min,
            mathMax = math.max,
            mathFloor = math.floor,
            mathSin = math.sin,
            mathCos = math.cos,
            baseElementPrototype = rendererNS.SvgElement.prototype,
            documentFragment = doc.createDocumentFragment(),
            DEFAULT_STYLE = {
                behavior: "url(#default#VML)",
                display: "inline-block",
                position: "absolute"
            },
            DEFAULT_ATTRS = {xmlns: 'urn:schemas-microsoft-com:vml'},
            INHERITABLE_PROPERTIES = {
                stroke: true,
                fill: true,
                opacity: true,
                'stroke-width': true,
                align: true,
                dashStyle: true,
                "stroke-opacity": true,
                'fill-opacity': true,
                rotate: true,
                rotateX: true,
                rotateY: true
            },
            stub = function(){},
            stubReturnedThis = function() {
                return this
            },
            svgToVmlConv = {
                circle: "oval",
                g: "div",
                path: "shape",
                text: "span"
            },
            FONT_HEIGHT_OFFSET_K = 0.55 + 0.45 / 2,
            DEFAULTS = {
                scaleX: 1,
                scaleY: 1
            },
            pathAttr = rendererNS._createPathAttr(vmlAttr),
            arcAttr = rendererNS._createArcAttr(vmlAttr, buildArcPath),
            rectAttr = rendererNS._createRectAttr(vmlAttr);
        function isDefined(value) {
            return value !== null && value !== undefined
        }
        function extend(a, b) {
            for (var key in b)
                a[key] = b[key];
            return a
        }
        function inArray(array, elem) {
            var i = 0;
            for (; i < array.length; i++)
                if (elem === array[i])
                    return i;
            return -1
        }
        function buildArcPath(x, y, innerR, outerR, startAngleCos, startAngleSin, endAngleCos, endAngleSin, isCircle, longFlag, noArc) {
            var xOuterStart = x + outerR * startAngleCos,
                yOuterStart = y - outerR * startAngleSin,
                xOuterEnd = x + outerR * endAngleCos,
                yOuterEnd = y - outerR * endAngleSin,
                xInnerStart = x + innerR * endAngleCos,
                yInnerStart = y - innerR * endAngleSin,
                xInnerEnd = x + innerR * startAngleCos,
                yInnerEnd = y - innerR * startAngleSin;
            return !noArc ? ['wr', mathFloor(x - innerR), mathFloor(y - innerR), mathFloor(x + innerR), mathFloor(y + innerR), mathFloor(xInnerStart), mathFloor(yInnerStart), mathFloor(xInnerEnd), mathFloor(yInnerEnd), isCircle ? 'wr ' : 'at ', mathFloor(x - outerR), mathFloor(y - outerR), mathFloor(x + outerR), mathFloor(y + outerR), mathFloor(xOuterStart), mathFloor(yOuterStart), mathFloor(xOuterEnd), mathFloor(yOuterEnd), 'x e'].join(" ") : "m 0 0 x e"
        }
        function getInheritSettings(settings) {
            var result = {},
                prop,
                value;
            for (prop in INHERITABLE_PROPERTIES) {
                value = settings[prop];
                value !== undefined && (result[prop] = value)
            }
            return result
        }
        function correctBoundingRectWithStrokeWidth(rect, strokeWidth) {
            strokeWidth = Math.ceil(parseInt(strokeWidth) / 2);
            if (strokeWidth && strokeWidth > 1) {
                rect.left -= strokeWidth;
                rect.top -= strokeWidth;
                rect.right += strokeWidth;
                rect.bottom += strokeWidth
            }
            return rect
        }
        function shapeBBox() {
            var points = (this._settings.d || "").match(/[-0-9]+/g),
                i,
                value,
                resultRect = {};
            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;
            return correctBoundingRectWithStrokeWidth(resultRect, this._fullSettings["stroke-width"])
        }
        function baseAttr(attrs, inh) {
            var element = this.element,
                settings = this._settings,
                fullSettings = this._fullSettings,
                value,
                key,
                params = {style: {}},
                appliedAttr,
                elem;
            if (typeof attrs === "string") {
                if (attrs in settings)
                    return settings[attrs];
                if (attrs in DEFAULTS)
                    return DEFAULTS[attrs];
                return 0
            }
            for (key in attrs) {
                value = attrs[key];
                if (value === undefined)
                    continue;
                appliedAttr = fullSettings[key];
                !inh && (settings[key] = value);
                fullSettings[key] = value;
                if (INHERITABLE_PROPERTIES[key])
                    value = value === null ? this._parent && this._parent._fullSettings[key] || value : value;
                appliedAttr !== value && this.processAttr(element, key, value, params)
            }
            this._applyTransformation(params);
            this.css(params.style);
            for (var i = 0; i < this._children.length; i++) {
                elem = this._children[i];
                elem !== this._clipRect && elem.attr(extend(getInheritSettings(this._fullSettings), elem._settings), true);
                elem._applyStyleSheet()
            }
            !inh && this._applyStyleSheet();
            return this
        }
        function vmlAttr() {
            var elem = this.element,
                result = baseAttr.apply(this, arguments);
            for (var i = 0; i < elem.childNodes.length; i++) {
                elem.childNodes[i].xmlns = 'urn:schemas-microsoft-com:vml';
                elem.childNodes[i].style.behavior = "url(#default#VML)";
                elem.childNodes[i].style.display = "inline-block"
            }
            return result
        }
        function processVmlAttr(element, attr, value, params) {
            switch (attr) {
                case"stroke":
                    value = value || "none";
                    element.stroked = value === 'none' ? 'f' : 't';
                    attr += "color";
                    break;
                case"fill":
                    value = value || "none";
                    element.filled = value === 'none' ? 'f' : 't';
                    attr += "color";
                    break;
                case"stroke-width":
                    attr = "strokeweight";
                    value = value + 'px';
                    break;
                case"stroke-linejoin":
                    element.stroke.joinstyle = value;
                    return;
                case"stroke-linecap":
                    element.stroke.endcap = value === "butt" ? "flat" : value;
                    return;
                case"opacity":
                    value = adjustOpacityValue(value);
                    element.fill.opacity = value;
                    element.stroke.opacity = value;
                    return;
                case"fill-opacity":
                    element.fill.opacity = adjustOpacityValue(value);
                    return;
                case"stroke-opacity":
                    element.stroke.opacity = adjustOpacityValue(value);
                    return;
                case"dashStyle":
                    if (value === null)
                        element.stroke[attr] = "";
                    else {
                        value = value.toLowerCase();
                        if (value === "solid" || value === "none")
                            value = "";
                        else
                            value = value.replace(/longdash/g, "8,3,").replace(/dash/g, "4,3,").replace(/dot/g, "1,3,").replace(/,$/, "");
                        element.stroke[attr] = value
                    }
                    return;
                case"d":
                    attr = "path";
                    value = (value + '').toLowerCase().replace("z", "x e").replace(/([.]\d+)/g, "");
                    break;
                case"href":
                    attr = "src";
                    break;
                case"width":
                case"height":
                case"visibility":
                    params.style[attr] = value || "";
                    return;
                case"class":
                    attr += "Name";
                    break;
                case"translateX":
                case"translateY":
                case"rotate":
                case"rotateX":
                case"rotateY":
                case"scale":
                case"scaleX":
                case"scaleY":
                case"x":
                case"y":
                    return
            }
            element[attr] = value
        }
        function adjustOpacityValue(value) {
            return value >= 0.002 ? value : value === null ? 1 : 0.002
        }
        function createElement(tagName) {
            var element = document.createElement(tagName);
            return documentFragment.appendChild(element)
        }
        var VmlElement = function() {
                this.ctor.apply(this, arguments)
            };
        function processAttr(element, attr, value, params) {
            if (!INHERITABLE_PROPERTIES[attr])
                if (attr === "visibility")
                    params.style[attr] = value || "";
                else if (attr === "width" || attr === "height")
                    params.style[attr] = value;
                else if (attr === "clipId")
                    this.applyClipID(value);
                else if (attr === "translateX" || attr === "translateY" || attr === "x" || attr === "y")
                    return;
                else if (attr === "class")
                    element.className = value;
                else
                    element[attr] = value
        }
        var elementMixin = {
                div: {
                    processAttr: processAttr,
                    attr: baseAttr,
                    _applyTransformation: function(params) {
                        var style = params.style,
                            settings = this._settings,
                            fullSettings = this._fullSettings;
                        if (fullSettings.rotate) {
                            fullSettings.rotateX = fullSettings.rotateX || 0;
                            fullSettings.rotateY = fullSettings.rotateY || 0
                        }
                        style.left = (settings.x || 0) + (settings.translateX || 0);
                        style.top = (settings.y || 0) + (settings.translateY || 0)
                    },
                    _getBBox: function() {
                        var left = Infinity,
                            top = Infinity,
                            right = -Infinity,
                            bottom = -Infinity,
                            i = 0,
                            child,
                            children = this._children,
                            translateX,
                            translateY,
                            childBBox,
                            childSettings;
                        if (!children.length)
                            left = top = bottom = right = 0;
                        else
                            for (; i < children.length; i++) {
                                child = children[i];
                                if (child === this._clipRect)
                                    continue;
                                translateX = child._fullSettings.translateX || 0;
                                translateY = child._fullSettings.translateY || 0;
                                childSettings = child._fullSettings;
                                childBBox = child._getBBox();
                                left = mathMin(left, childBBox.left + translateX);
                                right = mathMax(right, childBBox.right + translateX);
                                top = mathMin(top, childBBox.top + translateY);
                                bottom = mathMax(bottom, childBBox.bottom + translateY)
                            }
                        return {
                                left: left,
                                right: right,
                                top: top,
                                bottom: bottom
                            }
                    },
                    defaultAttrs: {},
                    defaultStyle: {position: "absolute"}
                },
                shape: {
                    defaultAttrs: extend({
                        coordsize: "1,1",
                        "stroke-linejoin": "miter"
                    }, DEFAULT_ATTRS),
                    defaultStyle: extend({
                        width: 1,
                        height: 1
                    }, DEFAULT_STYLE),
                    _getBBox: shapeBBox
                },
                image: {processAttr: function(element, attr, value, params) {
                        if (attr === "fill" || attr === "stroke")
                            return;
                        processVmlAttr(element, attr, value, params)
                    }},
                oval: {
                    processAttr: function(element, attr, value, params) {
                        if (attr === "cx" || attr === "cy")
                            attr = attr[1];
                        else if (attr === "r") {
                            value *= 2;
                            processVmlAttr(element, "width", value, params);
                            attr = "height"
                        }
                        else if (attr === "x" || attr === "y")
                            return;
                        processVmlAttr(element, attr, value, params)
                    },
                    _getBBox: function() {
                        var settings = this._fullSettings,
                            x = settings.cx || 0,
                            y = settings.cy || 0,
                            r = settings.r || 0;
                        return correctBoundingRectWithStrokeWidth({
                                left: x - r,
                                top: y - r,
                                right: x + r,
                                bottom: y + r
                            }, settings["stroke-width"] || 1)
                    }
                },
                span: {
                    defaultAttrs: {},
                    defaultStyle: {
                        position: 'absolute',
                        whiteSpace: 'nowrap'
                    },
                    processAttr: function(element, attr, value, params) {
                        if (attr === "text") {
                            value = isDefined(value) ? value.toString().replace(/\r/g, "") : "";
                            if (this.renderer.encodeHtml)
                                value = value.replace(//g, ">");
                            element.innerHTML = value.replace(/\n/g, "
");
                            this.css({filter: ""});
                            this._bbox = null
                        }
                        else
                            processAttr(element, attr, value, params)
                    },
                    attr: baseAttr,
                    _applyTransformation: function(params) {
                        this.element.offsetHeight;
                        var that = this,
                            style = params.style,
                            settings = that._fullSettings,
                            x = isDefined(settings.x) ? settings.x : 0,
                            y = isDefined(settings.y) ? settings.y : 0,
                            bbox = that._bbox || that.element.getBoundingClientRect(),
                            textHeight = bbox.bottom - bbox.top,
                            textWidth = bbox.right - bbox.left,
                            rotateAngle = settings.rotate,
                            cos = 1,
                            sin = 0,
                            rotateX = isDefined(settings.rotateX) ? settings.rotateX : x,
                            rotateY = isDefined(settings.rotateY) ? settings.rotateY : y,
                            radianAngle,
                            marginLeft = 0,
                            marginTop = 0,
                            fontHeightOffset = textHeight * FONT_HEIGHT_OFFSET_K,
                            filter = "",
                            alignMultiplier = {
                                center: 0.5,
                                right: 1
                            }[settings.align],
                            opacity = this._styles.opacity || settings.opacity || settings["fill-opacity"];
                        if (textHeight && textWidth) {
                            if (rotateAngle) {
                                radianAngle = rotateAngle * Math.PI / 180.0;
                                cos = mathCos(radianAngle);
                                sin = mathSin(radianAngle);
                                marginLeft = (x - rotateX) * cos - (y - rotateY) * sin + rotateX - x;
                                marginTop = (x - rotateX) * sin + (y - rotateY) * cos + rotateY - y;
                                filter = 'progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand", M11 = ' + cos.toFixed(5) + ', M12 = ' + (-sin).toFixed(5) + ', M21 = ' + sin.toFixed(5) + ', M22 = ' + cos.toFixed(5) + ')'
                            }
                            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));
                            if (alignMultiplier) {
                                marginLeft -= textWidth * alignMultiplier * cos;
                                marginTop -= textWidth * alignMultiplier * sin
                            }
                            if (isDefined(opacity))
                                filter += " progid:DXImageTransform.Microsoft.Alpha(Opacity=" + opacity * 100 + ")";
                            x += marginLeft;
                            y += marginTop;
                            this._bbox = bbox;
                            style.filter = (style.filter || "") + filter;
                            style.left = x + (settings.translateX || 0);
                            style.top = y + (settings.translateY || 0)
                        }
                    },
                    _getBBox: function textBBox() {
                        var element = this.element,
                            settings = this._fullSettings,
                            parentRect = (element.parentNode && element.parentNode.getBoundingClientRect ? element.parentNode : this.renderer.root.element).getBoundingClientRect(),
                            boundingRect = element.getBoundingClientRect(),
                            left = boundingRect.left - (settings.translateX || 0) - parentRect.left,
                            top = boundingRect.top - (settings.translateY || 0) - parentRect.top;
                        return {
                                left: left,
                                top: top,
                                right: left + element.offsetWidth,
                                bottom: top + element.offsetHeight
                            }
                    }
                }
            };
        extend(VmlElement.prototype, baseElementPrototype);
        extend(VmlElement.prototype, {
            defaultStyle: DEFAULT_STYLE,
            defaultAttrs: DEFAULT_ATTRS,
            ctor: function(renderer, tagName, type) {
                var that = this,
                    tagPrefix = '<';
                that.renderer = renderer;
                that.type = type;
                that._children = [];
                that._settings = {};
                that._fullSettings = {};
                that._styles = {};
                if (tagName !== "div" && tagName !== "span")
                    tagPrefix = "
");
                that.css(that.defaultStyle).attr(that.defaultAttrs);
                that._$element = $(that.element)
            },
            dispose: function() {
                this.remove();
                this._$element.remove();
                return this
            },
            attr: vmlAttr,
            processAttr: processVmlAttr,
            css: function(css) {
                var elem = this.element,
                    value,
                    appliedValue,
                    key;
                for (key in css) {
                    appliedValue = this._styles[key];
                    value = css[key];
                    if (!isDefined(value))
                        continue;
                    this._styles[key] = value;
                    if (appliedValue === value)
                        continue;
                    switch (key) {
                        case"fill":
                            key = "color";
                            break;
                        case"font-size":
                            key = "fontSize";
                            if (typeof value === "number")
                                value += "px";
                            break;
                        case"font-weight":
                            key = "fontWeight";
                            break;
                        case"z-index":
                            key = "zIndex";
                            break;
                        case"opacity":
                            continue
                    }
                    try {
                        elem.style[key] = value
                    }
                    catch(_) {
                        continue
                    }
                }
                return this
            },
            applyClipID: function(id) {
                var clipRect,
                    cssValue,
                    renderer = this.renderer;
                clipRect = renderer.getClipRect(id);
                if (clipRect) {
                    cssValue = clipRect.getValue();
                    clipRect.addElement(this)
                }
                else
                    cssValue = "rect(-9999px 9999px 9999px -9999px)";
                this._clipRect = this._clipRect || renderer.rect(0, 0, 0, 0).attr({
                    "class": "dxc-vml-clip",
                    fill: "none",
                    opacity: 0.001
                });
                this._clipRect.attr({
                    width: renderer.root.attr("width"),
                    height: renderer.root.attr("height")
                });
                this.css({
                    clip: cssValue,
                    width: renderer.root.attr("width"),
                    height: renderer.root.attr("height")
                })
            },
            append: function(parent) {
                parent = parent || this.renderer.root;
                (parent.element || parent).appendChild(this.element);
                if (parent._children) {
                    this._parent = parent;
                    if (inArray(parent._children, this) === -1)
                        parent._children.push(this);
                    this.attr(extend(getInheritSettings(parent._fullSettings), this._settings), true)
                }
                this._applyStyleSheet();
                if (parent._clipRect && this !== parent._clipRect)
                    parent._clipRect.append(parent);
                return this
            },
            _applyTransformation: function(params) {
                var that = this,
                    style = params.style,
                    element = that.element,
                    settings = that._fullSettings,
                    x = that.type !== "arc" ? settings.x || settings.cx - settings.r || 0 : 0,
                    y = that.type !== "arc" ? settings.y || settings.cy - settings.r || 0 : 0;
                if (settings.rotate) {
                    var radianAngle = settings.rotate * Math.PI / 180.0,
                        rotateX = isDefined(settings.rotateX) ? settings.rotateX : x,
                        rotateY = isDefined(settings.rotateY) ? settings.rotateY : y,
                        rx = x + (settings.width || 0 || parseInt(element.style.width || 0)) / 2,
                        ry = y + (settings.height || 0 || parseInt(element.style.height || 0)) / 2,
                        cos = mathCos(radianAngle),
                        sin = mathSin(radianAngle),
                        marginLeft = (rx - rotateX) * cos - (ry - rotateY) * sin + rotateX - rx,
                        marginTop = (rx - rotateX) * sin + (ry - rotateY) * cos + rotateY - ry;
                    x += marginLeft;
                    y += marginTop;
                    style.rotation = settings.rotate
                }
                style.left = x + (settings.translateX || 0);
                style.top = y + (settings.translateY || 0)
            },
            remove: function() {
                var that = this,
                    parent = that._parent;
                if (parent)
                    parent._children.splice(inArray(parent._children, that), 1);
                that._parent = null;
                return baseElementPrototype.remove.call(that)
            },
            clear: function() {
                this._children = [];
                return baseElementPrototype.clear.call(this)
            },
            getBBox: function() {
                var clientRect = this._getBBox(),
                    x = clientRect.left,
                    y = clientRect.top,
                    width = clientRect.right - x,
                    height = clientRect.bottom - y;
                return {
                        x: x,
                        y: y,
                        width: width,
                        height: height,
                        isEmpty: !x && !y && !width && !height
                    }
            },
            _getBBox: function() {
                var element = this.element,
                    settings = this._fullSettings,
                    x = settings.x || 0,
                    y = settings.y || 0,
                    width = parseInt(element.style.width || 0),
                    height = parseInt(element.style.height || 0);
                return correctBoundingRectWithStrokeWidth({
                        left: x,
                        top: y,
                        right: x + width,
                        bottom: y + height
                    }, settings["stroke-width"] || 1)
            },
            _applyStyleSheet: function() {
                if (this._useCSSTheme)
                    this.attr(getInheritSettings(this.element.currentStyle), true)
            },
            setTitle: function(text) {
                this.element.setAttribute('title', text)
            }
        });
        var ClipRect = function() {
                this.ctor.apply(this, arguments)
            };
        extend(ClipRect.prototype, VmlElement.prototype);
        extend(ClipRect.prototype, {
            ctor: function(renderer, id) {
                this._settings = this._fullSettings = {};
                this.renderer = renderer;
                this._children = [];
                this._elements = [];
                this.id = id
            },
            attr: function() {
                var result = baseAttr.apply(this, arguments),
                    elements = this._elements.slice(),
                    element,
                    i;
                if (result === this)
                    for (i = 0; i < elements.length; i++) {
                        element = elements[i];
                        if (element._fullSettings.clipId === this.id)
                            elements[i].applyClipID(this.id);
                        else
                            this.removeElement(element)
                    }
                return result
            },
            processAttr: stub,
            _applyTransformation: stub,
            append: stubReturnedThis,
            dispose: function() {
                this._elements = null;
                this.renderer.removeClipRect(this.id);
                return this
            },
            addElement: function(element) {
                var elements = this._elements;
                if (inArray(elements, element) === -1)
                    elements.push(element)
            },
            removeElement: function(element) {
                var index = inArray(this._elements, element);
                index > -1 && this._elements.splice(index, 1)
            },
            getValue: function() {
                var settings = this._settings,
                    left = (settings.x || 0) + (settings.translateX || 0),
                    top = (settings.y || 0) + (settings.translateY || 0);
                return "rect(" + top + "px, " + (left + (settings.width || 0)) + "px, " + (top + (settings.height || 0)) + "px, " + left + "px)"
            },
            css: stubReturnedThis,
            remove: stubReturnedThis
        });
        var VmlRenderer = function(options) {
                var that = this;
                that.root = that._createElement("div", {
                    fill: "none",
                    stroke: "none",
                    "stroke-width": 0
                }).css({
                    position: "relative",
                    display: "inline-block",
                    overflow: "hidden"
                });
                that._clipRects = [];
                that._animation = {enabled: false};
                that._defs = {
                    clear: stubReturnedThis,
                    remove: stubReturnedThis,
                    append: stubReturnedThis,
                    dispose: stubReturnedThis
                };
                that.setOptions(options)
            };
        extend(VmlRenderer.prototype, rendererNS.SvgRenderer.prototype);
        extend(VmlRenderer.prototype, {
            constructor: VmlRenderer,
            setOptions: function() {
                rendererNS.SvgRenderer.prototype.setOptions.apply(this, arguments);
                this.root.css({direction: this.rtl ? "rtl" : "ltr"})
            },
            _createElement: function(tagName, attr, type) {
                tagName = svgToVmlConv[tagName] || tagName;
                var elem = new rendererNS.VmlElement(this, tagName, type);
                attr && elem.attr(attr);
                return elem
            },
            dispose: function() {
                this.root.dispose();
                return null
            },
            shadowFilter: function() {
                return {
                        ref: null,
                        append: stubReturnedThis,
                        dispose: stubReturnedThis,
                        attr: stubReturnedThis,
                        css: stubReturnedThis
                    }
            },
            clipRect: function(x, y, width, height) {
                var clipRects = this._clipRects,
                    id = clipRects.length,
                    clipRect = new ClipRect(this, id).attr({
                        x: x || 0,
                        y: y || 0,
                        width: width || 0,
                        height: height || 0
                    });
                clipRects.push(clipRect);
                return clipRect
            },
            getClipRect: function(id) {
                return this._clipRects[id]
            },
            removeClipRect: function(id) {
                delete this._clipRects[id]
            },
            pattern: function(color) {
                return {
                        id: color,
                        append: stubReturnedThis,
                        remove: stubReturnedThis,
                        dispose: stubReturnedThis
                    }
            },
            image: function(x, y, w, h, href, location) {
                var image = this._createElement("image", {
                        x: x || 0,
                        y: y || 0,
                        width: w || 0,
                        height: h || 0,
                        location: location,
                        href: href
                    });
                return image
            },
            updateAnimationOptions: stubReturnedThis,
            stopAllAnimations: stubReturnedThis,
            svg: function() {
                return ""
            },
            onEndAnimation: function(callback) {
                callback()
            }
        });
        rendererNS.VmlRenderer = VmlRenderer;
        rendererNS.VmlElement = VmlElement;
        rendererNS._VmlClipRect = ClipRect
    })(jQuery, DevExpress, document);
    /*! Module viz-core, file animation.js */
    (function(DX) {
        var rendererNS = DX.viz.renderers,
            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
                }
            };
        rendererNS.easingFunctions = easingFunctions;
        rendererNS.animationSvgStep = {
            segments: function(elem, params, progress, easing, currentParams) {
                var from = params.from,
                    to = params.to,
                    curSeg,
                    seg,
                    i,
                    j,
                    segments = [];
                for (i = 0; i < from.length; i++) {
                    curSeg = from[i];
                    seg = [curSeg[0]];
                    if (curSeg.length > 1)
                        for (j = 1; j < curSeg.length; j++)
                            seg.push(easing(progress, curSeg[j], to[i][j]));
                    segments.push(seg)
                }
                currentParams.segments = params.end && progress === 1 ? params.end : segments;
                elem.attr({segments: segments})
            },
            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.attr(current)
            },
            transform: function(elem, params, progress, easing, currentParams) {
                var from = params.from,
                    to = params.to,
                    current = {};
                for (var i in from)
                    current[i] = currentParams[i] = easing(progress, from[i], to[i]);
                elem.attr(current)
            },
            base: function(elem, params, progress, easing, currentParams, attributeName) {
                var obj = {};
                obj[attributeName] = currentParams[attributeName] = easing(progress, params.from, params.to);
                elem.attr(obj)
            },
            _: noop,
            complete: function(element, currentSettings) {
                element.attr(currentSettings)
            }
        };
        function Animation(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 || rendererNS.animationSvgStep;
            that._easing = easingFunctions[options.easing] || easingFunctions["easeOutCubic"];
            that._currentParams = {};
            that.tick = that._start
        }
        Animation.prototype = {
            _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) {
                    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() {
                return true
            },
            stop: function(breakAnimation, disableComplete) {
                var that = this,
                    options = that.options;
                if (!breakAnimation && options.repeatCount && --options.repeatCount > 0) {
                    that.tick = that._start;
                    return true
                }
                else
                    that._end(disableComplete)
            }
        };
        function AnimationController(element) {
            var that = this;
            that._animationCount = 0;
            that._timerId = null;
            that._animations = {};
            that.element = element
        }
        rendererNS.AnimationController = AnimationController;
        AnimationController.prototype = {
            _loop: function() {
                var that = this,
                    animations = that._animations,
                    activeAnimation = 0,
                    now = (new Date).getTime(),
                    an,
                    endAnimation = that._endAnimation;
                for (an in animations) {
                    if (!animations[an].tick(now))
                        delete animations[an];
                    activeAnimation++
                }
                if (activeAnimation === 0) {
                    that.stop();
                    that._endAnimationTimer = endAnimation && setTimeout(function() {
                        if (that._animationCount === 0) {
                            endAnimation();
                            that._endAnimation = null
                        }
                    });
                    return
                }
                that._timerId = DX.requestAnimationFrame.call(null, function() {
                    that._loop()
                }, that.element)
            },
            addAnimation: function(animation) {
                var that = this;
                that._animations[that._animationCount++] = animation;
                clearTimeout(that._endAnimationTimer);
                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))
                }
            },
            onEndAnimation: function(endAnimation) {
                this._animationCount ? this._endAnimation = endAnimation : endAnimation()
            },
            dispose: function() {
                this.stop();
                this.element = null
            },
            stop: function() {
                var that = this;
                that._animations = {};
                that._animationCount = 0;
                DX.cancelAnimationFrame(that._timerId);
                clearTimeout(that._startDelay);
                clearTimeout(that._endAnimationTimer);
                that._timerId = null
            },
            lock: function() {
                var an,
                    animations = this._animations;
                for (an in animations)
                    animations[an].stop(true, true);
                this.stop()
            }
        };
        rendererNS.Animation = Animation;
        rendererNS.noop = noop
    })(DevExpress);
    /*! Module viz-core, file renderer.js */
    (function($, DX, document) {
        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()) {
            if (document.namespaces && !document.namespaces.vml) {
                document.namespaces.add('vml', 'urn:schemas-microsoft-com:vml');
                document.createStyleSheet().cssText = 'vml\\:* { behavior:url(#default#VML); display: inline-block; } '
            }
            renderers.Renderer = renderers.VmlRenderer
        }
        else
            renderers.Renderer = renderers.SvgRenderer;
        renderers.isSvg = isSvg
    })(jQuery, DevExpress, document);
    /*! 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}
            },
            pieLabelIndent: 30
        }
    })(DevExpress);
    /*! Module viz-core, file seriesFamily.js */
    (function($, DX, undefined) {
        var utils = DX.utils,
            _math = Math,
            _round = _math.round,
            _abs = _math.abs,
            _pow = _math.pow,
            _each = $.each;
        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;
                    that.type = options.type.toLowerCase();
                    that.pane = options.pane;
                    that.series = [];
                    that.updateOptions(options);
                    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":
                        case"fullstackedspline":
                        case"fullstackedsplinearea":
                            that.fullStacked = true;
                            that.adjustSeriesDimensions = stubFunction;
                            that.adjustSeriesValues = adjustStackedSeriesValues;
                            that.updateSeriesValues = stubFunction;
                            break;
                        case"stackedarea":
                        case"stackedsplinearea":
                        case"stackedline":
                        case"stackedspline":
                            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 updateOptions = function(options) {
                    this.equalBarWidth = options.equalBarWidth;
                    this.minBubbleSize = options.minBubbleSize;
                    this.maxBubbleSize = options.maxBubbleSize
                };
            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)
                    }
                };
            function correctPointCoordinates(points, width, offset) {
                _each(points, function(_, point) {
                    point.correctCoordinates({
                        width: width,
                        offset: offset
                    })
                })
            }
            function getStacksWithArgument(stackKeepers, argument) {
                var stacksWithArgument = [];
                _each(stackKeepers, function(stackName, seriesInStack) {
                    _each(seriesInStack, function(_, singleSeries) {
                        var points = singleSeries.getPointsByArg(argument),
                            pointsLength = points.length,
                            i;
                        for (i = 0; i < pointsLength; ++i)
                            if (points[i] && points[i].value) {
                                stacksWithArgument.push(stackName);
                                return false
                            }
                    })
                });
                return stacksWithArgument
            }
            function correctPointCoordinatesForStacks(stackKeepers, stacksWithArgument, argument, middleIndex, width, spacing) {
                _each(stackKeepers, function(stackName, seriesInStack) {
                    var stackIndex = $.inArray(stackName, stacksWithArgument),
                        offset;
                    if (stackIndex === -1)
                        return;
                    offset = (stackIndex - middleIndex + 0.5) * width - (middleIndex - stackIndex - 0.5) * spacing;
                    _each(seriesInStack, function(_, singleSeries) {
                        _each(singleSeries.getPointsByArg(argument) || [], function(_, point) {
                            if (point && point.value)
                                point.correctCoordinates({
                                    width: width,
                                    offset: offset
                                })
                        })
                    })
                })
            }
            var adjustBarSeriesDimensionsCore = function(series, interval, stackCount, equalBarWidth, seriesStackIndexCallback) {
                    var spacing,
                        width,
                        maxWidth,
                        middleIndex,
                        stackIndex,
                        i,
                        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 (!spacing)
                            if (stackCount > 1) {
                                spacing = width ? _round((interval * 0.7 - width * stackCount) / (stackCount - 1)) : _round(interval * 0.7 / stackCount * 0.2);
                                if (spacing < 1)
                                    spacing = 1
                            }
                            else
                                spacing = 0;
                        if (!width) {
                            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;
                            correctPointCoordinates(points, width, 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 = getStacksWithArgument(stackKeepers, argument);
                            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;
                            correctPointCoordinatesForStacks(stackKeepers, stacksWithArgument, argument, middleIndex, width, spacing)
                        }
                    }
                };
            function checkMinBarSize(value, minShownValue) {
                return _abs(value) < minShownValue ? value >= 0 ? minShownValue : -minShownValue : value
            }
            function getValueType(value) {
                return value >= 0 ? "positive" : "negative"
            }
            function getVisibleSeries(that) {
                return $.map(that.series, function(s) {
                        return s.isVisible() ? s : null
                    })
            }
            function getAbsStackSumByArg(stackKeepers, stackName, argument) {
                var positiveStackValue = (stackKeepers.positive[stackName] || {})[argument] || 0,
                    negativeStackValue = -(stackKeepers.negative[stackName] || {})[argument] || 0;
                return positiveStackValue + negativeStackValue
            }
            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,
                        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: {}
                        },
                        holesStack = {
                            left: {},
                            right: {}
                        };
                    _each(series, function(seriesIndex, singleSeries) {
                        var points = singleSeries.getPoints(),
                            hole = false;
                        singleSeries._prevSeries = series[seriesIndex - 1],
                        singleSeries.holes = $.extend(true, {}, holesStack);
                        _each(points, function(index, point) {
                            var value = point.initialValue,
                                argument = point.argument.valueOf(),
                                stackName = singleSeries.getStackName(),
                                stacks = value >= 0 ? stackKeepers.positive : stackKeepers.negative,
                                currentStack;
                            stacks[stackName] = stacks[stackName] || {};
                            currentStack = stacks[stackName];
                            if (currentStack[argument]) {
                                point.correctValue(currentStack[argument]);
                                currentStack[argument] += value
                            }
                            else {
                                currentStack[argument] = value;
                                point.resetCorrection()
                            }
                            if (!point.hasValue()) {
                                var prevPoint = points[index - 1];
                                if (!hole && prevPoint && prevPoint.hasValue()) {
                                    argument = prevPoint.argument.valueOf();
                                    prevPoint._skipSetRightHole = true;
                                    holesStack.right[argument] = (holesStack.right[argument] || 0) + (prevPoint.value - (isFinite(prevPoint.minValue) ? prevPoint.minValue : 0))
                                }
                                hole = true
                            }
                            else if (hole) {
                                hole = false;
                                holesStack.left[argument] = (holesStack.left[argument] || 0) + (point.value - (isFinite(point.minValue) ? point.minValue : 0));
                                point._skipSetLeftHole = true
                            }
                        })
                    });
                    _each(series, function(seriesIndex, singleSeries) {
                        var points = singleSeries.getPoints(),
                            holes = singleSeries.holes;
                        _each(points, function(index, point) {
                            var argument = point.argument.valueOf();
                            point.resetHoles();
                            !point._skipSetLeftHole && point.setHole(holes.left[argument] || holesStack.left[argument] && 0, "left");
                            !point._skipSetRightHole && point.setHole(holes.right[argument] || holesStack.right[argument] && 0, "right");
                            point._skipSetLeftHole = null;
                            point._skipSetRightHole = null
                        })
                    });
                    that._stackKeepers = stackKeepers;
                    setPercentStackedValues(series, stackKeepers, that.fullStacked, holesStack)
                };
            var setPercentStackedValues = function(series, stackKeepers, fullStacked, holeStack) {
                    _each(series, function(_, singleSeries) {
                        _each(singleSeries.getPoints(), function(_, point) {
                            var argument = point.argument.valueOf();
                            point.setPercentValue(getAbsStackSumByArg(stackKeepers, singleSeries.getStackName(), argument), fullStacked, holeStack.left[argument], holeStack.right[argument])
                        })
                    })
                };
            var updateStackedSeriesValues = function(translators) {
                    var that = this,
                        series = getVisibleSeries(that),
                        stack = that._stackKeepers,
                        stackKeepers = {
                            positive: {},
                            negative: {}
                        };
                    _each(series, function(_, singleSeries) {
                        var minBarSize = singleSeries.getOptions().minBarSize,
                            minShownBusinessValue = minBarSize && translators.val.getMinBarSize(minBarSize),
                            stackName = singleSeries.getStackName();
                        _each(singleSeries.getPoints(), function(index, point) {
                            if (!point.hasValue())
                                return;
                            var value = point.initialValue,
                                argument = point.argument.valueOf(),
                                updateValue,
                                valueType,
                                currentStack;
                            if (that.fullStacked)
                                value = _abs(value) / getAbsStackSumByArg(stack, stackName, argument) || 0;
                            updateValue = checkMinBarSize(value, minShownBusinessValue);
                            valueType = getValueType(updateValue);
                            currentStack = stackKeepers[valueType][stackName] = stackKeepers[valueType][stackName] || {};
                            if (currentStack[argument]) {
                                point.minValue = currentStack[argument];
                                currentStack[argument] += updateValue
                            }
                            else
                                currentStack[argument] = updateValue;
                            point.value = currentStack[argument]
                        })
                    });
                    if (that.fullStacked)
                        updateFullStackedSeriesValues(series, stackKeepers)
                };
            var updateFullStackedSeriesValues = function(series, stackKeepers) {
                    _each(series, function(_, singleSeries) {
                        var stackName = singleSeries.getStackName ? singleSeries.getStackName() : "default";
                        _each(singleSeries.getPoints(), function(index, point) {
                            var value = _abs(point.value),
                                argument = point.argument.valueOf(),
                                valueType = getValueType(value),
                                currentStack;
                            stackKeepers[valueType][stackName] = stackKeepers[valueType][stackName] || {};
                            currentStack = stackKeepers[valueType][stackName];
                            point.value = point.value / currentStack[argument] || 0;
                            if (utils.isNumber(point.minValue))
                                point.minValue = point.minValue / currentStack[argument] || 0
                        })
                    })
                };
            var updateBarSeriesValues = function(translators) {
                    _each(this.series, function(_, singleSeries) {
                        var minBarSize = singleSeries.getOptions().minBarSize,
                            minShownBusinessValue = minBarSize && translators.val.getMinBarSize(minBarSize);
                        if (minShownBusinessValue)
                            _each(singleSeries.getPoints(), function(index, point) {
                                if (point.hasValue())
                                    point.value = checkMinBarSize(point.initialValue, minShownBusinessValue)
                            })
                    })
                };
            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 = translators.arg;
                    that.interval = argTranslator.getInterval();
                    return that.interval
                };
            var adjustBubbleSeriesDimensions = function(translators) {
                    var debug = DX.utils.debug;
                    debug.assert(translators, "translator was not passed or empty");
                    var that = this,
                        series = getVisibleSeries(that),
                        visibleAreaX = translators.arg.getCanvasVisibleArea(),
                        visibleAreaY = translators.val.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;
                    _each(series, function(_, seriesItem) {
                        _each(seriesItem.getPoints(), 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;
                    _each(series, function(_, seriesItem) {
                        _each(seriesItem.getPoints(), 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,
                    updateOptions: updateOptions
                }
        }())
    })(jQuery, DevExpress);
    /*! Module viz-core, file baseSeries.js */
    (function($, DX) {
        var viz = DX.viz,
            core = viz.core,
            seriesNS = core.series,
            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",
            NEAREST_POINT = "nearestpoint",
            APPLY_SELECTED = "applySelected",
            APPLY_HOVER = "applyHover",
            SYMBOL_POINT = "symbolPoint",
            POLAR_SYMBOL_POINT = "polarSymbolPoint",
            BAR_POINT = "barPoint",
            POLAR_BAR_POINT = "polarBarPoint",
            PIE_POINT = "piePoint",
            HOVER = "hover",
            NORMAL = "normal",
            SELECTION = "selection",
            getEmptyBusinessRange = function() {
                return {
                        arg: {},
                        val: {}
                    }
            };
        function triggerEvent(element, event, point) {
            element && element.trigger(event, point)
        }
        seriesNS.mixins = {
            chart: {pointTypes: {
                    scatter: SYMBOL_POINT,
                    line: SYMBOL_POINT,
                    spline: SYMBOL_POINT,
                    stepline: SYMBOL_POINT,
                    stackedline: SYMBOL_POINT,
                    fullstackedline: SYMBOL_POINT,
                    stackedspline: SYMBOL_POINT,
                    fullstackedspline: SYMBOL_POINT,
                    stackedsplinearea: SYMBOL_POINT,
                    fullstackedsplinearea: SYMBOL_POINT,
                    area: SYMBOL_POINT,
                    splinearea: SYMBOL_POINT,
                    steparea: SYMBOL_POINT,
                    stackedarea: SYMBOL_POINT,
                    fullstackedarea: SYMBOL_POINT,
                    rangearea: "rangeSymbolPoint",
                    bar: BAR_POINT,
                    stackedbar: BAR_POINT,
                    fullstackedbar: BAR_POINT,
                    rangebar: "rangeBarPoint",
                    bubble: "bubblePoint",
                    stock: "stockPoint",
                    candlestick: "candlestickPoint"
                }},
            pie: {pointTypes: {
                    pie: PIE_POINT,
                    doughnut: PIE_POINT,
                    donut: PIE_POINT
                }},
            polar: {pointTypes: {
                    scatter: POLAR_SYMBOL_POINT,
                    line: POLAR_SYMBOL_POINT,
                    area: POLAR_SYMBOL_POINT,
                    bar: POLAR_BAR_POINT,
                    stackedbar: POLAR_BAR_POINT
                }}
        };
        function includePointsMode(mode) {
            return mode === INCLUDE_POINTS || mode === "allseriespoints"
        }
        function Series() {
            this.ctor.apply(this, arguments)
        }
        function applyPointStyle(point, styleName) {
            !point.isSelected() && point.applyStyle(styleName)
        }
        seriesNS.Series = Series;
        Series.prototype = {
            ctor: function(renderSettings, options) {
                var that = this;
                that.fullState = 0;
                that._extGroups = renderSettings;
                that._renderer = renderSettings.renderer;
                that._group = renderSettings.renderer.g().attr({"class": "dxc-series"});
                that.updateOptions(options)
            },
            update: function(data, options) {
                this.updateOptions(options);
                this.updateData(data)
            },
            _createLegendState: _noop,
            getLegendStyles: function() {
                return this._styles.legendStyles
            },
            _createStyles: function(options) {
                var that = this,
                    mainSeriesColor = options.mainSeriesColor,
                    specialMainColor = that._getSpecialColor(mainSeriesColor);
                that._styles = {
                    normal: that._parseStyle(options, mainSeriesColor, mainSeriesColor),
                    hover: that._parseStyle(options.hoverStyle || {}, specialMainColor, mainSeriesColor),
                    selection: that._parseStyle(options.selectionStyle || {}, specialMainColor, mainSeriesColor),
                    legendStyles: {
                        normal: that._createLegendState(options, mainSeriesColor),
                        hover: that._createLegendState(options.hoverStyle || {}, specialMainColor),
                        selection: that._createLegendState(options.selectionStyle || {}, specialMainColor)
                    }
                }
            },
            setAdjustSeriesLabels: function(adjustSeriesLabels) {
                _each(this._points || [], function(_, point) {
                    point.setAdjustSeriesLabels(adjustSeriesLabels)
                })
            },
            setClippingParams: function(baseId, wideId, forceClipping) {
                this._paneClipRectID = baseId;
                this._widePaneClipRectID = wideId;
                this._forceClipping = forceClipping
            },
            applyClip: function() {
                this._group.attr({clipId: this._paneClipRectID})
            },
            resetClip: function() {
                this._group.attr({clipId: null})
            },
            getTagField: function() {
                return this._options.tagField || "tag"
            },
            getValueFields: _noop,
            getArgumentField: _noop,
            getPoints: function() {
                return this._points
            },
            _createPoint: function(data, pointsArray, index) {
                data.index = index;
                var that = this,
                    point = pointsArray[index],
                    pointsByArgument = that.pointsByArgument,
                    options;
                if (that._checkData(data)) {
                    options = that._customizePoint(data) || that._getCreatingPointOptions();
                    if (point)
                        point.update(data, options);
                    else {
                        point = core.CoreFactory.createPoint(that, data, options);
                        pointsArray.push(point)
                    }
                    pointsByArgument[point.argument.valueOf()] = pointsByArgument[point.argument.valueOf()] || [];
                    pointsByArgument[point.argument.valueOf()].push(point);
                    return true
                }
            },
            getRangeData: function(zoomArgs, calcIntervalFunction) {
                return this._visible ? _extend(true, {}, this._getRangeData(zoomArgs, calcIntervalFunction)) : getEmptyBusinessRange()
            },
            _deleteGroup: function(groupName) {
                var group = this[groupName];
                if (group) {
                    group.dispose();
                    this[groupName] = null
                }
            },
            _saveOldAnimationMethods: function() {
                var that = this;
                that._oldClearingAnimation = that._clearingAnimation;
                that._oldUpdateElement = that._updateElement;
                that._oldgetAffineCoordOptions = that._getAffineCoordOptions
            },
            _deleteOldAnimationMethods: function() {
                this._oldClearingAnimation = null;
                this._oldUpdateElement = null;
                this._oldgetAffineCoordOptions = 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._checkPolarBarType(widgetType, newOptions)) {
                    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) {
                var types = {
                        axisType: "continuous",
                        dataType: utils.isDate(min) ? "datetime" : "numeric"
                    },
                    data = {
                        min: min,
                        max: max,
                        screenDelta: screenDelta
                    },
                    options = {
                        gridSpacingFactor: pointSize,
                        labelOptions: {},
                        stick: true
                    },
                    tickManager = new viz.core.tickManager.TickManager(types, data, options);
                return {
                        ticks: tickManager.getTicks(true),
                        tickInterval: tickManager.getTickInterval()
                    }
            },
            _getRangeCorrector: _noop,
            updateDataType: function(settings) {
                var that = this;
                that.argumentType = settings.argumentType;
                that.valueType = settings.valueType;
                that.argumentAxisType = settings.argumentAxisType;
                that.valueAxisType = settings.valueAxisType;
                that.showZero = settings.showZero;
                return that
            },
            getOptions: function() {
                return this._options
            },
            _resetRangeData: function() {
                this._rangeData = getEmptyBusinessRange()
            },
            updateData: function(data) {
                var that = this,
                    points = that._originalPoints || [],
                    lastPointIndex = 0,
                    options = that._options,
                    pointData,
                    rangeCorrector;
                that._rangeErrorBarCorrector = rangeCorrector = that._getRangeCorrector();
                that.pointsByArgument = {};
                that._resetRangeData();
                if (data && data.length)
                    that._canRenderCompleteHandle = true;
                that._beginUpdateData(data);
                _each(data, function(_, dataItem) {
                    pointData = that._getPointData(dataItem, options);
                    if (that._createPoint(pointData, points, lastPointIndex)) {
                        that._processRange(points[lastPointIndex], lastPointIndex > 0 ? points[lastPointIndex - 1] : null, rangeCorrector);
                        lastPointIndex++
                    }
                });
                that._disposePoints(that._aggregatedPoints);
                that._aggregatedPoints = null;
                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(argTranslator, min, max) {
                var that = this,
                    originalPoints = that.getAllPoints(),
                    minI,
                    maxI,
                    sizePoint,
                    tickObject,
                    ticks,
                    tickInterval;
                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 = _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") {
                        tickObject = that._getTicksForAggregation(min, max, argTranslator.canvasLength, sizePoint);
                        ticks = tickObject.ticks;
                        tickInterval = tickObject.tickInterval;
                        if (ticks.length === 1) {
                            that._points = originalPoints;
                            return
                        }
                    }
                    else
                        ticks = argTranslator.canvasLength / sizePoint;
                    that._points = that._resample(ticks, tickInterval, argTranslator)
                }
            },
            _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,
                    drawComplete;
                if (that._oldClearingAnimation && animationEnabled && that._firstDrawing) {
                    drawComplete = function() {
                        that._draw(translators, true, hideLayoutLabels)
                    };
                    that._oldClearingAnimation(translators, drawComplete)
                }
                else
                    that._draw(translators, animationEnabled, hideLayoutLabels, legendCallback)
            },
            _clearSeries: function() {
                var that = this;
                that._deleteGroup("_elementsGroup");
                that._deleteGroup("_bordersGroup");
                that._deleteTrackers();
                that._graphics = [];
                that._trackers = []
            },
            _draw: function(translators, animationEnabled, hideLayoutLabels, legendCallback) {
                var that = this,
                    points = that._points || [],
                    segment = [],
                    segmentCount = 0,
                    firstDrawing = that._firstDrawing,
                    closeSegment = points[0] && points[0].hasValue() && that._options.closed,
                    groupForPoint;
                that._graphics = that._graphics || [];
                that._prepareSeriesToDrawing();
                if (!that._visible) {
                    animationEnabled = false;
                    that._group.remove();
                    return
                }
                that._group.append(that._extGroups.seriesGroup);
                that.translators = translators;
                that._createGroups(animationEnabled, undefined, firstDrawing);
                that._segments = [];
                that._drawedPoints = [];
                that._firstDrawing = points.length ? false : true;
                groupForPoint = {
                    markers: that._markersGroup,
                    labels: that._labelsGroup,
                    errorBars: that._errorBarGroup
                };
                _each(points, function(i, p) {
                    p.translate(translators);
                    if (p.hasValue()) {
                        that._drawPoint({
                            point: p,
                            groups: groupForPoint,
                            hasAnimation: animationEnabled,
                            firstDrawing: firstDrawing,
                            legendCallback: legendCallback
                        });
                        segment.push(p)
                    }
                    else if (segment.length) {
                        that._drawSegment(segment, animationEnabled, segmentCount++);
                        segment = []
                    }
                });
                segment.length && that._drawSegment(segment, animationEnabled, segmentCount++, closeSegment);
                that._removeOldSegments(segmentCount);
                that._defaultSegments = that._generateDefaultSegments();
                hideLayoutLabels && that.hideLabels();
                animationEnabled && that._animate(firstDrawing);
                if (that.isSelected())
                    that._changeStyle(legendCallback, APPLY_SELECTED);
                else if (that.isHovered())
                    that._changeStyle(legendCallback, APPLY_HOVER)
            },
            _checkType: function(widgetType) {
                return !!seriesNS.mixins[widgetType][this.type]
            },
            _checkPolarBarType: function(widgetType, options) {
                return widgetType === "polar" && options.spiderWidget && this.type.indexOf("bar") !== -1
            },
            _resetType: function(seriesType, widgetType) {
                var that = this;
                if (seriesType)
                    _each(seriesNS.mixins[widgetType][seriesType], function(methodName) {
                        delete that[methodName]
                    })
            },
            _setType: function(seriesType, widgetType) {
                var that = this;
                _each(seriesNS.mixins[widgetType][seriesType], function(methodName, method) {
                    that[methodName] = method
                })
            },
            setSelectedState: function(state, mode, legendCallback) {
                var that = this;
                that.lastSelectionMode = (mode || that._options.selectionMode).toLowerCase();
                if (state && !that.isSelected()) {
                    that.fullState = that.fullState | SELECTED_STATE;
                    that._nearestPoint && applyPointStyle(that._nearestPoint, "normal");
                    that._nearestPoint = null;
                    that._changeStyle(legendCallback, APPLY_SELECTED)
                }
                else if (!state && that.isSelected()) {
                    that.fullState = that.fullState & ~SELECTED_STATE;
                    if (that.isHovered())
                        that._changeStyle(legendCallback, APPLY_HOVER, SELECTION);
                    else
                        that._changeStyle(legendCallback, "resetItem")
                }
            },
            setHoverState: function(state, mode, legendCallback) {
                var that = this;
                that.lastHoverMode = (mode || that._options.hoverMode).toLowerCase();
                if (state && !that.isHovered()) {
                    that.fullState = that.fullState | HOVER_STATE;
                    !that.isSelected() && that._changeStyle(legendCallback, APPLY_HOVER)
                }
                else if (!state && that.isHovered()) {
                    that._nearestPoint = null;
                    that.fullState = that.fullState & ~HOVER_STATE;
                    !that.isSelected() && that._changeStyle(legendCallback, "resetItem")
                }
            },
            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, prevStyle) {
                var that = this,
                    style = that._calcStyle(prevStyle),
                    pointStyle;
                if (style.mode === NONE_MODE)
                    return;
                legendCallBack && legendCallBack(legendAction);
                if (includePointsMode(style.mode)) {
                    pointStyle = style.pointStyle;
                    _each(that._points || [], function(_, p) {
                        applyPointStyle(p, pointStyle)
                    })
                }
                that._applyStyle(style.series)
            },
            _calcStyle: function(prevStyle) {
                var that = this,
                    styles = that._styles,
                    pointNormalState = false,
                    result;
                switch (that.fullState & 3) {
                    case 0:
                        result = {
                            pointStyle: NORMAL,
                            mode: INCLUDE_POINTS,
                            series: styles.normal
                        };
                        break;
                    case 1:
                        pointNormalState = prevStyle === SELECTION && that.lastHoverMode === EXLUDE_POINTS || that.lastHoverMode === NEAREST_POINT && includePointsMode(that.lastSelectionMode);
                        result = {
                            pointStyle: pointNormalState ? NORMAL : HOVER,
                            mode: pointNormalState ? INCLUDE_POINTS : that.lastHoverMode,
                            series: styles.hover
                        };
                        break;
                    case 2:
                        result = {
                            pointStyle: SELECTION,
                            mode: that.lastSelectionMode,
                            series: styles.selection
                        };
                        break;
                    case 3:
                        pointNormalState = that.lastSelectionMode === EXLUDE_POINTS && includePointsMode(that.lastHoverMode);
                        result = {
                            pointStyle: pointNormalState ? NORMAL : SELECTION,
                            mode: pointNormalState ? INCLUDE_POINTS : that.lastSelectionMode,
                            series: styles.selection
                        }
                }
                return result
            },
            updateHover: function(x, y) {
                var that = this,
                    currentNearestPoint = that._nearestPoint,
                    point = that.isHovered() && that.lastHoverMode === NEAREST_POINT && that.getNeighborPoint(x, y);
                if (point !== currentNearestPoint && !that.isSelected()) {
                    currentNearestPoint && applyPointStyle(currentNearestPoint, "normal");
                    if (point) {
                        applyPointStyle(point, "hover");
                        that._nearestPoint = point
                    }
                }
            },
            _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 = options.customizePoint,
                    customizeObject,
                    pointOptions,
                    customLabelOptions,
                    customOptions,
                    customizeLabel = options.customizeLabel,
                    useLabelCustomOptions,
                    usePointCustomOptions;
                if (customizeLabel && customizeLabel.call) {
                    customizeObject = _extend({seriesName: that.name}, pointData);
                    customizeObject.series = that;
                    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}, pointData);
                    customizeObject.series = that;
                    customOptions = customizePoint.call(customizeObject, customizeObject);
                    usePointCustomOptions = customOptions && !_isEmptyObject(customOptions)
                }
                if (useLabelCustomOptions || usePointCustomOptions) {
                    pointOptions = that._parsePointOptions(that._preparePointOptions(customOptions), customLabelOptions || options.label, true);
                    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 = {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
                        }},
                    backgroundAttr = {
                        fill: opt.backgroundColor || defaultColor,
                        "stroke-width": 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",
                        "stroke-width": labelConnector.visible ? labelConnector.width || 0 : 0
                    };
                return {
                        alignment: opt.alignment,
                        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
                    }
            },
            show: function() {
                if (!this._visible)
                    this._changeVisibility(true)
            },
            hide: function() {
                if (this._visible)
                    this._changeVisibility(false)
            },
            _changeVisibility: function(visibility) {
                var that = this;
                that._visible = that._options.visible = visibility;
                that._updatePointsVisibility();
                that.hidePointTooltip();
                that._options.visibilityChanged()
            },
            _updatePointsVisibility: $.noop,
            hideLabels: function() {
                _each(this._points, function(_, point) {
                    point._label.hide()
                })
            },
            _parsePointOptions: function(pointOptions, labelOptions, isCustomPointOptions) {
                var that = this,
                    options = that._options,
                    styles = that._createPointStyles(pointOptions, isCustomPointOptions),
                    parsedOptions = _extend(true, {}, pointOptions, {
                        type: options.type,
                        tag: that.tag,
                        rotated: options.rotated,
                        styles: styles,
                        widgetType: options.widgetType,
                        visibilityChanged: options.visibilityChanged
                    });
                parsedOptions.label = that._getLabelOptions(labelOptions, styles.normal.fill);
                parsedOptions.errorBars = options.valueErrorBar;
                return parsedOptions
            },
            _resample: function(ticks, ticksInterval, argTranslator) {
                var that = this,
                    fusPoints = [],
                    arrayFusPoints,
                    nowIndexTicks = 0,
                    lastPointIndex = 0,
                    originalPoints = that.getAllPoints(),
                    visibleArea;
                if (that.argumentAxisType === "discrete" || that.valueAxisType === "discrete") {
                    visibleArea = argTranslator.getCanvasVisibleArea();
                    originalPoints = $.map(originalPoints, function(p) {
                        var pos = argTranslator.translate(p.argument),
                            result;
                        if (pos >= visibleArea.min && pos <= visibleArea.max)
                            result = p;
                        else {
                            p.setInvisibility();
                            result = null
                        }
                        return result
                    });
                    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) {
                    point.setInvisibility();
                    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.dateToMilliseconds(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() && includePointsMode(this.lastSelectionMode)) && !point.isSelected()) {
                    point.applyStyle(HOVER);
                    legendCallback && legendCallback("applyHover")
                }
            },
            releasePointHoverState: function(point, legendCallback) {
                var that = this;
                point.fullState = point.fullState & ~HOVER_STATE;
                if (!(that.isSelected() && includePointsMode(that.lastSelectionMode)) && !point.isSelected())
                    if (!(that.isHovered() && includePointsMode(that.lastHoverMode)) || that.isSelected() && that.lastSelectionMode === EXLUDE_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) {
                var that = this;
                point.fullState = point.fullState & ~SELECTED_STATE;
                if (that.isHovered() && includePointsMode(that.lastHoverMode) || point.isHovered()) {
                    point.applyStyle(HOVER);
                    legendCallback && legendCallback("applyHover")
                }
                else if (that.isSelected() && includePointsMode(that.lastSelectionMode)) {
                    point.applyStyle(SELECTION);
                    legendCallback && legendCallback("applySelected")
                }
                else {
                    point.applyStyle(NORMAL);
                    legendCallback && legendCallback("resetItem")
                }
            },
            selectPoint: function(point) {
                triggerEvent(this._extGroups.seriesGroup, new _Event("selectpoint"), point)
            },
            deselectPoint: function(point) {
                triggerEvent(this._extGroups.seriesGroup, new _Event("deselectpoint"), point)
            },
            showPointTooltip: function(point) {
                triggerEvent(this._extGroups.seriesGroup, new _Event("showpointtooltip"), point)
            },
            hidePointTooltip: function(point) {
                triggerEvent(this._extGroups.seriesGroup, new _Event("hidepointtooltip"), point)
            },
            select: function() {
                var that = this;
                triggerEvent(that._extGroups.seriesGroup, new _Event("selectseries", {target: that}), that._options.selectionMode);
                that._group.toForeground()
            },
            clearSelection: function clearSelection() {
                var that = this;
                triggerEvent(that._extGroups.seriesGroup, new _Event("deselectseries", {target: that}), that._options.selectionMode)
            },
            getPointByArg: function(arg) {
                return this.getPointsByArg(arg)[0] || null
            },
            getPointsByArg: function(arg) {
                return this.pointsByArgument[arg.valueOf()] || []
            },
            _deletePoints: function() {
                var that = this;
                that._disposePoints(that._originalPoints);
                that._disposePoints(that._aggregatedPoints);
                that._disposePoints(that._oldPoints);
                that._points = null;
                that._oldPoints = null;
                that._aggregatedPoints = null;
                that._originalPoints = null;
                that._drawedPoints = 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.dispose();
                that._trackers = that._trackersGroup = null
            },
            dispose: function() {
                var that = this;
                that._deletePoints();
                that._group.dispose();
                that._labelsGroup && that._labelsGroup.dispose();
                that._errorBarGroup && that._errorBarGroup.dispose();
                that._deletePatterns();
                that._deleteTrackers();
                that._group = that._extGroups = that._markersGroup = that._elementsGroup = that._bordersGroup = that._labelsGroup = that._errorBarGroup = that._graphics = that._rangeData = that._renderer = that.translators = that._styles = that._options = that._pointOptions = that._drawedPoints = that._aggregatedPoints = that.pointsByArgument = that._segments = that._prevSeries = null
            },
            correctPosition: _noop,
            drawTrackers: _noop,
            getNeighborPoint: _noop,
            areErrorBarsVisible: _noop,
            getColor: function() {
                return this.getLegendStyles().normal.fill
            },
            getOpacity: function() {
                return this._options.opacity
            },
            getStackName: function() {
                return this.type === "stackedbar" || this.type === "fullstackedbar" ? this._stackName : null
            },
            getPointByCoord: function(x, y) {
                var point = this.getNeighborPoint(x, y);
                return point && point.coordsIn(x, y) ? point : null
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file rangeDataCalculator.js */
    (function($, DX, undefined) {
        var _math = Math,
            _abs = _math.abs,
            _min = _math.min,
            _max = _math.max,
            _each = $.each,
            _isEmptyObject = $.isEmptyObject,
            _isDefined = DX.utils.isDefined,
            _isFinite = isFinite,
            MIN_VISIBLE = "minVisible",
            MAX_VISIBLE = "maxVisible",
            DISCRETE = "discrete";
        function _truncateValue(data, value) {
            var min = data.min,
                max = data.max;
            data.min = value < min || !_isDefined(min) ? value : min;
            data.max = value > max || !_isDefined(max) ? value : max
        }
        function _processValue(series, type, value, prevValue, calcInterval) {
            var axis = type === "arg" ? "argument" : "value",
                data = series._rangeData[type],
                minInterval = data.interval,
                interval;
            if (series[axis + "AxisType"] === DISCRETE) {
                data.categories = data.categories || [];
                data.categories.push(value)
            }
            else {
                _truncateValue(data, value);
                if (type === "arg") {
                    interval = (_isDefined(prevValue) ? _abs(calcInterval ? calcInterval(value, prevValue) : value - prevValue) : interval) || minInterval;
                    data.interval = _isDefined(interval) && (interval < minInterval || !_isDefined(minInterval)) ? interval : minInterval
                }
            }
        }
        function _addToVisibleRange(series, value) {
            var data = series._rangeData.val,
                isDiscrete = series.valueAxisType === DISCRETE;
            if (!isDiscrete) {
                if (value < data.minVisible || !_isDefined(data.minVisible))
                    data.minVisible = value;
                if (value > data.maxVisible || !_isDefined(data.maxVisible))
                    data.maxVisible = value
            }
        }
        function _processRangeValue(series, val, minVal) {
            var data = series._rangeData.val;
            if (series.valueAxisType === DISCRETE) {
                data.categories = data.categories || [];
                data.categories.push(val, minVal)
            }
            else {
                _truncateValue(data, val);
                _truncateValue(data, minVal)
            }
        }
        function _unique(array) {
            var values = {};
            return $.map(array, function(item) {
                    var result = !values[item] ? item : null;
                    values[item] = true;
                    return result
                })
        }
        function _processZoomArgument(series, zoomArgs, isDiscrete) {
            var data = series._rangeData.arg,
                minArg,
                maxArg;
            if (isDiscrete) {
                data.minVisible = zoomArgs.minArg;
                data.maxVisible = zoomArgs.maxArg;
                return
            }
            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
        }
        function _correctZoomValue(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
            }
        }
        function _processZoomValue(series, zoomArgs) {
            var adjustOnZoom = zoomArgs.adjustOnZoom,
                points = series._points || [],
                lastVisibleIndex,
                prevPointAdded = false,
                rangeData = series._rangeData,
                errorBarCorrector = series._rangeErrorBarCorrector;
            _each(points, function(index, point) {
                var arg = point.argument,
                    prevPoint = index > 0 ? points[index - 1] : null;
                if (adjustOnZoom && series.argumentAxisType !== DISCRETE && arg >= rangeData.arg.minVisible && arg <= rangeData.arg.maxVisible) {
                    if (!prevPointAdded) {
                        if (prevPoint && prevPoint.hasValue()) {
                            _addToVisibleRange(series, prevPoint.value);
                            _correctMinMaxByErrorBar(rangeData.val, prevPoint, errorBarCorrector, MIN_VISIBLE, MAX_VISIBLE)
                        }
                        prevPointAdded = true
                    }
                    if (point.hasValue()) {
                        _addToVisibleRange(series, point.value);
                        _correctMinMaxByErrorBar(rangeData.val, point, errorBarCorrector, MIN_VISIBLE, MAX_VISIBLE)
                    }
                    lastVisibleIndex = index
                }
            });
            if (_isDefined(lastVisibleIndex) && lastVisibleIndex < points.length - 1 && points[lastVisibleIndex + 1].hasValue())
                _addToVisibleRange(series, points[lastVisibleIndex + 1].value);
            _correctZoomValue(series, zoomArgs)
        }
        function _processZoomRangeValue(series, zoomArgs, maxValueName, minValueName) {
            var adjustOnZoom = zoomArgs.adjustOnZoom,
                points = series._points || [],
                argRangeData = series._rangeData.arg,
                lastVisibleIndex,
                prevPointAdded = false;
            _each(points, function(index, point) {
                var arg = point.argument,
                    prevPoint = index > 0 ? points[index - 1] : null;
                if (adjustOnZoom && series.argumentAxisType !== DISCRETE && arg >= argRangeData.minVisible && arg <= argRangeData.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)
        }
        function _processNewInterval(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)
            })
        }
        function _fillRangeData(series) {
            var data = series._rangeData;
            data.arg.categories && (data.arg.categories = _unique(data.arg.categories));
            data.val.categories && (data.val.categories = _unique(data.val.categories));
            data.arg.axisType = series.argumentAxisType;
            data.arg.dataType = series.argumentType;
            data.val.axisType = series.valueAxisType;
            data.val.dataType = series.valueType;
            data.val.isValueRange = true
        }
        function processTwoValues(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)
        }
        function calculateRangeMinValue(series, zoomArgs) {
            var data = series._rangeData.val,
                minVisible = data[MIN_VISIBLE],
                maxVisible = data[MAX_VISIBLE];
            zoomArgs = zoomArgs || {};
            if (data)
                if (series.valueAxisType !== "logarithmic" && series.valueType !== "datetime" && series.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;
                    data.max = data.max < 0 ? 0 : data.max
                }
        }
        function processFullStackedRange(series) {
            var data = series._rangeData.val,
                isRangeEmpty = _isEmptyObject(data);
            data.percentStick = true;
            !isRangeEmpty && (data.min = 0)
        }
        function _correctMinMaxByErrorBar(data, point, getMinMaxCorrector, minSelector, maxSelector) {
            if (!getMinMaxCorrector)
                return;
            var correctionData = getMinMaxCorrector(point),
                minError = _min.apply(undefined, correctionData),
                maxError = _max.apply(undefined, correctionData);
            if (_isFinite(minError) && data[minSelector] > minError)
                data[minSelector] = minError;
            if (_isFinite(maxError) && data[maxSelector] < maxError)
                data[maxSelector] = maxError
        }
        function processRange(series, point, prevPoint, getMinMaxCorrector) {
            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);
            _correctMinMaxByErrorBar(series._rangeData.val, point, getMinMaxCorrector, "min", "max")
        }
        function addLabelPaddings(series) {
            var labelOptions = series.getOptions().label,
                valueData;
            if (series.areLabelsVisible() && labelOptions && labelOptions.visible && labelOptions.position !== "inside") {
                valueData = series._rangeData.val;
                if (valueData.min < 0)
                    valueData.minSpaceCorrection = true;
                if (valueData.max > 0)
                    valueData.maxSpaceCorrection = true
            }
        }
        function addRangeSeriesLabelPaddings(series) {
            var data = series._rangeData.val;
            if (series.areLabelsVisible() && series._options.label.visible && series._options.label.position !== "inside")
                data.minSpaceCorrection = data.maxSpaceCorrection = true
        }
        function calculateRangeData(series, zoomArgs, calcIntervalFunction, maxValueName, minValueName) {
            var valueData = series._rangeData.val,
                isRangeSeries = !!maxValueName && !!minValueName,
                isDiscrete = series.argumentAxisType === DISCRETE;
            if (zoomArgs && _isDefined(zoomArgs.minArg) && _isDefined(zoomArgs.maxArg)) {
                if (!isDiscrete) {
                    valueData[MIN_VISIBLE] = zoomArgs.minVal;
                    valueData[MAX_VISIBLE] = zoomArgs.maxVal
                }
                _processZoomArgument(series, zoomArgs, isDiscrete);
                if (isRangeSeries)
                    _processZoomRangeValue(series, zoomArgs, maxValueName, minValueName);
                else
                    _processZoomValue(series, zoomArgs)
            }
            else if (!zoomArgs && calcIntervalFunction)
                _processNewInterval(series, calcIntervalFunction);
            _fillRangeData(series)
        }
        DX.viz.core.series.helpers.rangeDataCalculator = {
            processRange: processRange,
            calculateRangeData: calculateRangeData,
            addLabelPaddings: addLabelPaddings,
            addRangeSeriesLabelPaddings: addRangeSeriesLabelPaddings,
            processFullStackedRange: processFullStackedRange,
            calculateRangeMinValue: calculateRangeMinValue,
            processTwoValues: processTwoValues
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file scatterSeries.js */
    (function($, DX) {
        var series = DX.viz.core.series,
            rangeCalculator = series.helpers.rangeDataCalculator,
            chartSeries = series.mixins.chart,
            _each = $.each,
            _extend = $.extend,
            _map = $.map,
            _noop = $.noop,
            _utils = DX.utils,
            _isDefined = _utils.isDefined,
            _isString = _utils.isString,
            math = Math,
            _floor = math.floor,
            _abs = math.abs,
            _sqrt = math.sqrt,
            _min = math.min,
            _max = math.max,
            DEFAULT_SYMBOL_POINT_SIZE = 2,
            DEFAULT_TRACKER_WIDTH = 20,
            DEFAULT_DURATION = 400,
            HIGH_ERROR = "highError",
            LOW_ERROR = "lowError",
            ORIGINAL = "original",
            VARIANCE = "variance",
            STANDARD_DEVIATION = "stddeviation",
            STANDARD_ERROR = "stderror",
            PERCENT = "percent",
            FIXED = "fixed",
            UNDEFINED = "undefined",
            DISCRETE = "discrete",
            LOGARITHMIC = "logarithmic",
            DATETIME = "datetime";
        function sum(array) {
            var summa = 0;
            _each(array, function(_, value) {
                summa += value
            });
            return summa
        }
        function toLowerCase(value) {
            return value.toLowerCase()
        }
        function isErrorBarTypeCorrect(type) {
            return $.inArray(type, [FIXED, PERCENT, VARIANCE, STANDARD_DEVIATION, STANDARD_ERROR, UNDEFINED]) !== -1
        }
        function variance(array, expectedValue) {
            return sum($.map(array, function(value) {
                    return (value - expectedValue) * (value - expectedValue)
                })) / array.length
        }
        var baseScatterMethods = {
                _defaultDuration: DEFAULT_DURATION,
                _defaultTrackerWidth: DEFAULT_TRACKER_WIDTH,
                _applyStyle: _noop,
                _updateOptions: _noop,
                _parseStyle: _noop,
                _prepareSegment: _noop,
                _drawSegment: _noop,
                _generateDefaultSegments: _noop,
                _prepareSeriesToDrawing: function() {
                    var that = this;
                    that._deleteOldAnimationMethods();
                    that._firstDrawing && that._clearSeries();
                    that._disposePoints(that._oldPoints);
                    that._oldPoints = null
                },
                _createLegendState: function(styleOptions, defaultColor) {
                    return {
                            fill: styleOptions.color || defaultColor,
                            hatching: styleOptions.hatching
                        }
                },
                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] = parent[groupName] || this._renderer.g();
                    group.attr(settings).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 that = this,
                        settings = that._getPointOptions().styles.normal;
                    settings["class"] = "dxc-markers";
                    settings.opacity = 1;
                    that._applyMarkerClipRect(settings);
                    that._createGroup("_markersGroup", that, that._group, settings)
                },
                _createLabelGroup: function() {
                    var that = this,
                        settings = {
                            "class": "dxc-labels",
                            visibility: that.getLabelVisibility() ? "visible" : "hidden"
                        };
                    that._applyElementsClipRect(settings);
                    that._applyClearingSettings(settings);
                    that._createGroup("_labelsGroup", that, that._extGroups.labelsGroup, settings)
                },
                areErrorBarsVisible: function() {
                    var errorBarOptions = this._options.valueErrorBar || {};
                    return this._errorBarsEnabled() && errorBarOptions.displayMode !== "none" && (isErrorBarTypeCorrect(toLowerCase(errorBarOptions.type + "")) || _isDefined(errorBarOptions.lowValueField) || _isDefined(errorBarOptions.highValueField))
                },
                _createErrorBarGroup: function(animationEnabled) {
                    var that = this,
                        errorBarOptions = that._options.valueErrorBar || {},
                        settings;
                    if (that.areErrorBarsVisible()) {
                        settings = {
                            "class": "dxc-error-bars",
                            stroke: errorBarOptions.color,
                            'stroke-width': errorBarOptions.lineWidth,
                            opacity: animationEnabled ? 0.001 : errorBarOptions.opacity || 1,
                            "stroke-linecap": "square",
                            sharp: true,
                            clipId: that._forceClipping ? that._paneClipRectID : that._widePaneClipRectID
                        };
                        that._createGroup("_errorBarGroup", that, that._group, settings)
                    }
                },
                _createGroups: function(animationEnabled) {
                    var that = this;
                    that._createMarkerGroup();
                    that._createLabelGroup();
                    that._createErrorBarGroup(animationEnabled);
                    animationEnabled && that._labelsGroup && that._labelsGroup.attr({opacity: 0.001})
                },
                _getCreatingPointOptions: function() {
                    var that = this,
                        defaultPointOptions,
                        creatingPointOptions = that._predefinedPointOptions,
                        normalStyle;
                    if (!creatingPointOptions) {
                        defaultPointOptions = that._getPointOptions();
                        that._predefinedPointOptions = creatingPointOptions = _extend(true, {styles: {}}, defaultPointOptions);
                        normalStyle = defaultPointOptions.styles && defaultPointOptions.styles.normal || {};
                        creatingPointOptions.styles = creatingPointOptions.styles || {};
                        creatingPointOptions.styles.normal = {
                            "stroke-width": normalStyle["stroke-width"],
                            r: normalStyle.r,
                            opacity: normalStyle.opacity
                        }
                    }
                    return creatingPointOptions
                },
                _getSpecialColor: function(mainSeriesColor) {
                    return mainSeriesColor
                },
                _getPointOptions: function() {
                    return this._parsePointOptions(this._preparePointOptions(), this._options.label)
                },
                _preparePointOptions: function(customOptions) {
                    var point = this._options.point;
                    return customOptions ? _extend(true, {}, point, customOptions) : point
                },
                _parsePointStyle: function(style, defaultColor, defaultBorderColor) {
                    var border = style.border || {};
                    return {
                            fill: style.color || defaultColor,
                            stroke: border.color || defaultBorderColor,
                            "stroke-width": border.visible ? border.width : 0,
                            r: style.size / 2 + (border.visible && style.size !== 0 ? ~~(border.width / 2) || 0 : 0)
                        }
                },
                _createPointStyles: function(pointOptions) {
                    var that = this,
                        mainPointColor = pointOptions.color || that._options.mainSeriesColor,
                        containerColor = that._options.containerBackgroundColor,
                        normalStyle = that._parsePointStyle(pointOptions, mainPointColor, mainPointColor);
                    normalStyle.visibility = pointOptions.visible ? "visible" : "hidden";
                    return {
                            normal: normalStyle,
                            hover: that._parsePointStyle(pointOptions.hoverStyle, containerColor, mainPointColor),
                            selection: that._parsePointStyle(pointOptions.selectionStyle, containerColor, mainPointColor)
                        }
                },
                _checkData: function(data) {
                    return _isDefined(data.argument) && data.value !== undefined
                },
                _getRangeCorrector: function() {
                    var errorBars = this.getOptions().valueErrorBar || {},
                        mode = toLowerCase(errorBars.displayMode + "");
                    return errorBars ? function(point) {
                            var lowError = point.lowError,
                                highError = point.highError;
                            switch (mode) {
                                case"low":
                                    return [lowError];
                                case"high":
                                    return [highError];
                                case"none":
                                    return [];
                                default:
                                    return [lowError, highError]
                            }
                        } : undefined
                },
                _processRange: function(point, prevPoint, errorBarCorrector) {
                    rangeCalculator.processRange(this, point, prevPoint, errorBarCorrector)
                },
                _getRangeData: function(zoomArgs, calcIntervalFunction) {
                    rangeCalculator.calculateRangeData(this, zoomArgs, calcIntervalFunction);
                    rangeCalculator.addLabelPaddings(this);
                    return this._rangeData
                },
                _getPointData: function(data, options) {
                    var pointData = {
                            value: data[options.valueField || "val"],
                            argument: data[options.argumentField || "arg"],
                            tag: data[options.tagField || "tag"]
                        };
                    this._fillErrorBars(data, pointData, options);
                    return pointData
                },
                _errorBarsEnabled: function() {
                    return this.valueAxisType !== DISCRETE && this.valueAxisType !== LOGARITHMIC && this.valueType !== DATETIME
                },
                _fillErrorBars: function(data, pointData, options) {
                    var errorBars = options.valueErrorBar || {};
                    if (this._errorBarsEnabled()) {
                        pointData.lowError = data[errorBars.lowValueField || LOW_ERROR];
                        pointData.highError = data[errorBars.highValueField || HIGH_ERROR]
                    }
                },
                _drawPoint: function(options) {
                    var point = options.point;
                    if (point.isInVisibleArea()) {
                        point.clearVisibility();
                        point.draw(this._renderer, options.groups, options.hasAnimation, options.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)
                    })
                },
                _animateComplete: function() {
                    var that = this,
                        animationSettings = {duration: that._defaultDuration};
                    that._labelsGroup && that._labelsGroup.animate({opacity: 1}, animationSettings);
                    that._errorBarGroup && that._errorBarGroup.animate({opacity: (that._options.valueErrorBar || {}).opacity || 1}, animationSettings)
                },
                _animate: function() {
                    var that = this,
                        lastPointIndex = that._drawedPoints.length - 1;
                    _each(that._drawedPoints || [], function(i, p) {
                        p.animate(i === lastPointIndex ? function() {
                            that._animateComplete()
                        } : undefined, {
                            translateX: p.x,
                            translateY: p.y
                        })
                    })
                },
                _getPointSize: function() {
                    return this._options.point.visible ? this._options.point.size : DEFAULT_SYMBOL_POINT_SIZE
                },
                _calcMedianValue: function(fusionPoints, valueField) {
                    var result,
                        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
                },
                _calcErrorBarValues: function(fusionPoints) {
                    if (!fusionPoints.length)
                        return {};
                    var lowValue = fusionPoints[0].lowError,
                        highValue = fusionPoints[0].highError,
                        i = 1,
                        length = fusionPoints.length,
                        lowError,
                        highError;
                    for (i; i < length; i++) {
                        lowError = fusionPoints[i].lowError;
                        highError = fusionPoints[i].highError;
                        if (_isDefined(lowError) && _isDefined(highError)) {
                            lowValue = _min(lowError, lowValue);
                            highValue = _max(highError, highValue)
                        }
                    }
                    return {
                            low: lowValue,
                            high: highValue
                        }
                },
                _fusionPoints: function(fusionPoints, tick, index) {
                    var errorBarValues = this._calcErrorBarValues(fusionPoints);
                    return {
                            value: this._calcMedianValue(fusionPoints, "value"),
                            argument: tick,
                            tag: null,
                            index: index,
                            seriesName: this.name,
                            lowError: errorBarValues.low,
                            highError: errorBarValues.high
                        }
                },
                _endUpdateData: function() {
                    delete this._predefinedPointOptions
                },
                getArgumentField: function() {
                    return this._options.argumentField || "arg"
                },
                getValueFields: function() {
                    var options = this._options,
                        errorBarsOptions = options.valueErrorBar || {},
                        valueFields = [options.valueField || "val"],
                        lowValueField = errorBarsOptions.lowValueField,
                        highValueField = errorBarsOptions.highValueField;
                    _isString(lowValueField) && valueFields.push(lowValueField);
                    _isString(highValueField) && valueFields.push(highValueField);
                    return valueFields
                },
                _calculateErrorBars: function(data) {
                    var that = this,
                        options = that._options,
                        errorBarsOptions = options.valueErrorBar || {},
                        errorBarType = toLowerCase(errorBarsOptions.type + ""),
                        floatErrorValue = parseFloat(errorBarsOptions.value),
                        valueField = that.getValueFields()[0],
                        value,
                        lowValueField = errorBarsOptions.lowValueField || LOW_ERROR,
                        highValueField = errorBarsOptions.highValueField || HIGH_ERROR,
                        valueArray,
                        valueArrayLength,
                        meanValue,
                        processDataItem,
                        addSubError = function(_i, item) {
                            value = item[valueField];
                            item[lowValueField] = value - floatErrorValue;
                            item[highValueField] = value + floatErrorValue
                        };
                    if (!that._errorBarsEnabled() || !isErrorBarTypeCorrect(errorBarType))
                        return;
                    switch (errorBarType) {
                        case FIXED:
                            processDataItem = addSubError;
                            break;
                        case PERCENT:
                            processDataItem = function(_, item) {
                                value = item[valueField];
                                var error = value * floatErrorValue / 100;
                                item[lowValueField] = value - error;
                                item[highValueField] = value + error
                            };
                            break;
                        case UNDEFINED:
                            processDataItem = function(_, item) {
                                item[lowValueField] = item[ORIGINAL + lowValueField];
                                item[highValueField] = item[ORIGINAL + highValueField]
                            };
                            break;
                        default:
                            valueArray = $.map(data, function(item) {
                                return item[valueField]
                            });
                            valueArrayLength = valueArray.length;
                            floatErrorValue = floatErrorValue || 1;
                            switch (errorBarType) {
                                case VARIANCE:
                                    floatErrorValue = variance(valueArray, sum(valueArray) / valueArrayLength) * floatErrorValue;
                                    processDataItem = addSubError;
                                    break;
                                case STANDARD_DEVIATION:
                                    meanValue = sum(valueArray) / valueArrayLength;
                                    floatErrorValue = _sqrt(variance(valueArray, meanValue)) * floatErrorValue;
                                    processDataItem = function(_, item) {
                                        item[lowValueField] = meanValue - floatErrorValue;
                                        item[highValueField] = meanValue + floatErrorValue
                                    };
                                    break;
                                case STANDARD_ERROR:
                                    floatErrorValue = _sqrt(variance(valueArray, sum(valueArray) / valueArrayLength) / valueArrayLength) * floatErrorValue;
                                    processDataItem = addSubError;
                                    break
                            }
                    }
                    processDataItem && _each(data, processDataItem)
                },
                _beginUpdateData: function(data) {
                    this._calculateErrorBars(data)
                }
            };
        chartSeries.scatter = _extend({}, baseScatterMethods, {
            drawTrackers: function() {
                var that = this,
                    trackers,
                    trackersGroup,
                    segments = that._segments || [],
                    rotated = that._options.rotated,
                    cat = [];
                if (!that.isVisible())
                    return;
                if (segments.length) {
                    trackers = that._trackers = that._trackers || [];
                    trackersGroup = that._trackersGroup = (that._trackersGroup || that._renderer.g().attr({
                        fill: "gray",
                        opacity: 0.001,
                        stroke: "gray",
                        "class": "dxc-trackers"
                    })).attr({clipId: this._paneClipRectID || null}).append(that._group);
                    _each(segments, function(i, segment) {
                        if (!trackers[i])
                            trackers[i] = that._drawTrackerElement(segment).data({series: that}).append(trackersGroup);
                        else
                            that._updateTrackerElement(segment, trackers[i])
                    })
                }
                that._trackersTranslator = cat;
                _each(that.getVisiblePoints(), function(_, p) {
                    var pointCoord = parseInt(rotated ? p.vy : p.vx);
                    if (!cat[pointCoord])
                        cat[pointCoord] = p;
                    else
                        $.isArray(cat[pointCoord]) ? cat[pointCoord].push(p) : cat[pointCoord] = [cat[pointCoord], p]
                })
            },
            getNeighborPoint: function(x, y) {
                var pCoord = this._options.rotated ? y : x,
                    nCoord = pCoord,
                    cat = this._trackersTranslator,
                    point = null,
                    minDistance,
                    oppositeCoord = this._options.rotated ? x : y,
                    opositeCoordName = this._options.rotated ? "vx" : "vy";
                if (this.isVisible() && cat) {
                    point = cat[pCoord];
                    do {
                        point = cat[nCoord] || cat[pCoord];
                        pCoord--;
                        nCoord++
                    } while ((pCoord >= 0 || nCoord < cat.length) && !point);
                    if ($.isArray(point)) {
                        minDistance = _abs(point[0][opositeCoordName] - oppositeCoord);
                        _each(point, function(i, p) {
                            var distance = _abs(p[opositeCoordName] - oppositeCoord);
                            if (minDistance >= distance) {
                                minDistance = distance;
                                point = p
                            }
                        })
                    }
                }
                return point
            }
        });
        series.mixins.polar.scatter = _extend({}, baseScatterMethods, {
            drawTrackers: function() {
                chartSeries.scatter.drawTrackers.call(this);
                var cat = this._trackersTranslator,
                    index;
                if (!this.isVisible())
                    return;
                _each(cat, function(i, category) {
                    if (category) {
                        index = i;
                        return false
                    }
                });
                cat[index + 360] = cat[index]
            },
            getNeighborPoint: function(x, y) {
                var pos = this.translators.untranslate(x, y);
                return chartSeries.scatter.getNeighborPoint.call(this, pos.phi, pos.r)
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file lineSeries.js */
    (function($, DX) {
        var core = DX.viz.core,
            series = core.series,
            chartSeries = series.mixins.chart,
            polarSeries = series.mixins.polar,
            utils = DX.utils,
            scatterSeries = chartSeries.scatter,
            rangeCalculator = core.series.helpers.rangeDataCalculator,
            CANVAS_POSITION_START = "canvas_position_start",
            CANVAS_POSITION_TOP = "canvas_position_top",
            DISCRETE = "discrete",
            _extend = $.extend,
            _map = $.map,
            _each = $.each;
        function clonePoint(point, newX, newY, newAngle) {
            var p = utils.clone(point);
            p.x = newX;
            p.y = newY;
            p.angle = newAngle;
            return p
        }
        function getTangentPoint(point, prevPoint, centerPoint, tan, nextStepAngle) {
            var currectAngle = point.angle + nextStepAngle,
                cossin = utils.getCosAndSin(currectAngle),
                x = centerPoint.x + (point.radius + tan * nextStepAngle) * cossin.cos,
                y = centerPoint.y - (point.radius + tan * nextStepAngle) * cossin.sin;
            return clonePoint(prevPoint, x, y, currectAngle)
        }
        var lineMethods = {
                _createElementsGroup: function(elementsStyle) {
                    var that = this,
                        settings = _extend({"class": "dxc-elements"}, elementsStyle);
                    that._applyElementsClipRect(settings);
                    that._createGroup("_elementsGroup", that, that._group, settings)
                },
                _createBordersGroup: function(borderStyle) {
                    var that = this,
                        settings = _extend({"class": "dxc-borders"}, borderStyle);
                    that._applyElementsClipRect(settings);
                    that._createGroup("_bordersGroup", that, that._group, settings)
                },
                _createGroups: function(animationEnabled, style) {
                    var that = this;
                    style = style || that._styles.normal;
                    that._createElementsGroup(style.elements);
                    that._areBordersVisible() && that._createBordersGroup(style.border);
                    scatterSeries._createGroups.call(that, animationEnabled, {});
                    animationEnabled && that._markersGroup && that._markersGroup.attr({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,
                            "stroke-width": options.width,
                            dashStyle: options.dashStyle || 'solid'
                        }
                },
                _parseStyle: function(options, defaultColor) {
                    return {elements: this._parseLineOptions(options, defaultColor)}
                },
                _applyStyle: function(style) {
                    var that = this;
                    that._elementsGroup && that._elementsGroup.attr(style.elements);
                    _each(that._graphics || [], function(_, graphic) {
                        graphic.line && graphic.line.attr({'stroke-width': style.elements["stroke-width"]}).sharp()
                    })
                },
                _drawElement: function(segment, group) {
                    return {line: this._createMainElement(segment.line, {"stroke-width": this._styles.normal.elements["stroke-width"]}).append(group)}
                },
                _removeElement: function(element) {
                    element.line.remove()
                },
                _generateDefaultSegments: function() {
                    var that = this;
                    return _map(that._segments || [], function(segment) {
                            return that._getDefaultSegment(segment)
                        })
                },
                _updateElement: function(element, segment, animate, animateParams, complete) {
                    var params = {points: segment.line},
                        lineElement = element.line;
                    animate ? lineElement.animate(params, animateParams, complete) : lineElement.attr(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)
                            })
                        })
                    })
                },
                _animateComplete: function() {
                    var that = this;
                    scatterSeries._animateComplete.call(this);
                    that._markersGroup && that._markersGroup.animate({opacity: 1}, {duration: that._defaultDuration})
                },
                _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._animateComplete()
                            } : undefined})
                    })
                },
                _drawPoint: function(options) {
                    scatterSeries._drawPoint.call(this, {
                        point: options.point,
                        groups: options.groups
                    })
                },
                _createMainElement: function(points, settings) {
                    return this._renderer.path(points, "line").attr(settings).sharp()
                },
                _drawSegment: function(points, animationEnabled, segmentCount, lastSegment) {
                    var that = this,
                        segment = that._prepareSegment(points, that._options.rotated, lastSegment);
                    that._segments.push(segment);
                    if (!that._graphics[segmentCount])
                        that._graphics[segmentCount] = that._drawElement(animationEnabled ? that._getDefaultSegment(segment) : segment, that._elementsGroup);
                    else if (!animationEnabled)
                        that._updateElement(that._graphics[segmentCount], segment)
                },
                _getTrackerSettings: function() {
                    var that = this,
                        elements = that._styles.normal.elements;
                    return {
                            "stroke-width": elements["stroke-width"] > that._defaultTrackerWidth ? elements["stroke-width"] : that._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.attr(settings)
                }
            };
        chartSeries.line = _extend({}, scatterSeries, lineMethods);
        chartSeries.stepline = _extend({}, chartSeries.line, {
            _calculateStepLinePoints: function(points) {
                var segment = [];
                _each(points, function(i, pt) {
                    var stepY,
                        point;
                    if (!i) {
                        segment.push(pt);
                        return
                    }
                    stepY = segment[segment.length - 1].y;
                    if (stepY !== pt.y) {
                        point = utils.clone(pt);
                        point.y = stepY;
                        segment.push(point)
                    }
                    segment.push(pt)
                });
                return segment
            },
            _prepareSegment: function(points) {
                return chartSeries.line._prepareSegment(this._calculateStepLinePoints(points))
            }
        });
        chartSeries.stackedline = _extend({}, chartSeries.line, {});
        chartSeries.fullstackedline = _extend({}, chartSeries.line, {_getRangeData: function(zoomArgs, calcIntervalFunction) {
                var that = this;
                rangeCalculator.calculateRangeData(that, zoomArgs, calcIntervalFunction);
                rangeCalculator.addLabelPaddings(that);
                rangeCalculator.processFullStackedRange(that);
                return that._rangeData
            }});
        chartSeries.spline = _extend({}, chartSeries.line, {
            _calculateBezierPoints: function(src, rotated) {
                var bezierPoints = [],
                    pointsCopy = src,
                    checkExtr = function(otherPointCoord, pointCoord, controlCoord) {
                        return otherPointCoord > pointCoord && controlCoord > otherPointCoord || otherPointCoord < pointCoord && controlCoord < otherPointCoord ? otherPointCoord : controlCoord
                    };
                if (pointsCopy.length !== 1)
                    _each(pointsCopy, function(i, curPoint) {
                        var leftControlX,
                            leftControlY,
                            rightControlX,
                            rightControlY,
                            prevPoint,
                            nextPoint,
                            xCur,
                            yCur,
                            x1,
                            x2,
                            y1,
                            y2,
                            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 chartSeries.line._prepareSegment(this._calculateBezierPoints(points, rotated))
            },
            _createMainElement: function(points, settings) {
                return this._renderer.path(points, "bezier").attr(settings).sharp()
            }
        });
        polarSeries.line = _extend({}, polarSeries.scatter, lineMethods, {
            _prepareSegment: function(points, rotated, lastSegment) {
                var preparedPoints = [],
                    centerPoint = this.translators.translate(CANVAS_POSITION_START, CANVAS_POSITION_TOP),
                    i;
                lastSegment && this._closeSegment(points);
                if (this.argumentAxisType !== DISCRETE && this.valueAxisType !== DISCRETE) {
                    for (i = 1; i < points.length; i++)
                        preparedPoints = preparedPoints.concat(this._getTangentPoints(points[i], points[i - 1], centerPoint));
                    if (!preparedPoints.length)
                        preparedPoints = points
                }
                else
                    return chartSeries.line._prepareSegment.apply(this, arguments);
                return {line: preparedPoints}
            },
            _getRemainingAngle: function(angle) {
                var normAngle = utils.normalizeAngle(angle);
                return angle >= 0 ? 360 - normAngle : -normAngle
            },
            _closeSegment: function(points) {
                var point,
                    differenceAngle;
                if (this._segments.length)
                    point = this._segments[0].line[0];
                else
                    point = clonePoint(points[0], points[0].x, points[0].y, points[0].angle);
                if (points[points.length - 1].angle !== point.angle) {
                    if (utils.normalizeAngle(Math.round(points[points.length - 1].angle)) === utils.normalizeAngle(Math.round(point.angle)))
                        point.angle = points[points.length - 1].angle;
                    else {
                        differenceAngle = points[points.length - 1].angle - point.angle;
                        point.angle = points[points.length - 1].angle + this._getRemainingAngle(differenceAngle)
                    }
                    points.push(point)
                }
            },
            _getTangentPoints: function(point, prevPoint, centerPoint) {
                var tangentPoints = [],
                    betweenAngle = Math.round(prevPoint.angle - point.angle),
                    tan = (prevPoint.radius - point.radius) / betweenAngle,
                    i;
                if (betweenAngle === 0)
                    tangentPoints = [prevPoint, point];
                else if (betweenAngle > 0)
                    for (i = betweenAngle; i >= 0; i--)
                        tangentPoints.push(getTangentPoint(point, prevPoint, centerPoint, tan, i));
                else
                    for (i = 0; i >= betweenAngle; i--)
                        tangentPoints.push(getTangentPoint(point, prevPoint, centerPoint, tan, betweenAngle - i));
                return tangentPoints
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file areaSeries.js */
    (function($, DX) {
        var core = DX.viz.core,
            utils = DX.utils,
            series = core.series,
            chartSeries = series.mixins.chart,
            polarSeries = series.mixins.polar,
            lineSeries = chartSeries.line,
            rangeCalculator = core.series.helpers.rangeDataCalculator,
            _map = $.map,
            _extend = $.extend,
            HOVER_COLOR_HIGHLIGHTING = 20;
        var baseAreaMethods = {
                _createBorderElement: lineSeries._createMainElement,
                _createLegendState: function(styleOptions, defaultColor) {
                    var legendState = chartSeries.scatter._createLegendState.call(this, styleOptions, defaultColor);
                    legendState.opacity = styleOptions.opacity;
                    return legendState
                },
                _getSpecialColor: function(color) {
                    return this._options._IE8 ? new DX.Color(color).highlight(HOVER_COLOR_HIGHLIGHTING) : color
                },
                _getRangeData: function(zoomArgs, calcIntervalFunction) {
                    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.attr(lineParams);
                        element.area.attr(areaParams)
                    }
                },
                _removeElement: function(element) {
                    element.line && element.line.remove();
                    element.area.remove()
                },
                _drawElement: function(segment) {
                    return {
                            line: this._bordersGroup && this._createBorderElement(segment.line, {"stroke-width": this._styles.normal.border["stroke-width"]}).append(this._bordersGroup),
                            area: this._createMainElement(segment.area).append(this._elementsGroup)
                        }
                },
                _applyStyle: function(style) {
                    var that = this;
                    that._elementsGroup && that._elementsGroup.attr(style.elements);
                    that._bordersGroup && that._bordersGroup.attr(style.border);
                    $.each(that._graphics || [], function(_, graphic) {
                        graphic.line && graphic.line.attr({'stroke-width': style.border["stroke-width"]}).sharp()
                    })
                },
                _createPattern: function(color, hatching, custom) {
                    if (hatching && utils.isObject(hatching)) {
                        var pattern = this._renderer.pattern(color, hatching);
                        pattern._custom = custom;
                        this._patterns.push(pattern);
                        return pattern.id
                    }
                    return color
                },
                _parseStyle: function(options, defaultColor, defaultBorderColor) {
                    var borderOptions = options.border || {},
                        borderStyle = lineSeries._parseLineOptions(borderOptions, defaultBorderColor);
                    borderStyle["stroke-width"] = borderOptions.visible ? borderStyle["stroke-width"] : 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.path(points, "area").attr(settings)
                },
                _getTrackerSettings: function(segment) {
                    return {"stroke-width": segment.singlePointSegment ? this._defaultTrackerWidth : 0}
                },
                _getMainPointsFromSegment: function(segment) {
                    return segment.area
                }
            };
        chartSeries.area = _extend({}, lineSeries, baseAreaMethods, {
            _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
                    }
            },
            _processSinglePointsAreaSegment: function(points, rotated) {
                if (points.length === 1) {
                    var p = points[0],
                        p1 = utils.clone(p);
                    p1[rotated ? "y" : "x"] += 1;
                    p1.argument = null;
                    return [p, p1]
                }
                return points
            }
        });
        polarSeries.area = _extend({}, polarSeries.line, baseAreaMethods, {
            _prepareSegment: function(points, rotated, lastSegment) {
                lastSegment && polarSeries.line._closeSegment.call(this, points);
                var preparedPoints = chartSeries.area._prepareSegment.call(this, points);
                return preparedPoints
            },
            _processSinglePointsAreaSegment: function(points) {
                return polarSeries.line._prepareSegment.call(this, points).line
            }
        });
        chartSeries.steparea = _extend({}, chartSeries.area, {_prepareSegment: function(points, rotated) {
                points = chartSeries.area._processSinglePointsAreaSegment(points, rotated);
                return chartSeries.area._prepareSegment.call(this, chartSeries.stepline._calculateStepLinePoints(points))
            }});
        chartSeries.splinearea = _extend({}, chartSeries.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 = chartSeries.area,
                    processedPoints = areaSeries._processSinglePointsAreaSegment(points, rotated),
                    areaSegment = areaSeries._prepareSegment.call(this, chartSeries.spline._calculateBezierPoints(processedPoints, rotated));
                this._areaPointsToSplineAreaPoints(areaSegment.area);
                areaSegment.singlePointSegment = processedPoints !== points;
                return areaSegment
            },
            _getDefaultSegment: function(segment) {
                var areaDefaultSegment = chartSeries.area._getDefaultSegment(segment);
                this._areaPointsToSplineAreaPoints(areaDefaultSegment.area);
                return areaDefaultSegment
            },
            _createMainElement: function(points, settings) {
                return this._renderer.path(points, "bezierarea").attr(settings)
            },
            _createBorderElement: chartSeries.spline._createMainElement
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file barSeries.js */
    (function($, DX) {
        var viz = DX.viz,
            series = viz.core.series,
            chartSeries = series.mixins.chart,
            polarSeries = series.mixins.polar,
            scatterSeries = chartSeries.scatter,
            areaSeries = chartSeries.area,
            _extend = $.extend,
            _each = $.each,
            DEFAULT_BAR_POINT_SIZE = 3;
        var baseBarSeriesMethods = {
                _getSpecialColor: areaSeries._getSpecialColor,
                _createPattern: areaSeries._createPattern,
                _updateOptions: function(options) {
                    this._stackName = "axis_" + (options.axis || "default") + "_stack_" + (options.stack || "default")
                },
                _parsePointStyle: function(style, defaultColor, defaultBorderColor, isCustomPointOptions) {
                    var color = this._createPattern(style.color || defaultColor, style.hatching, isCustomPointOptions),
                        base = scatterSeries._parsePointStyle.call(this, style, color, defaultBorderColor);
                    base.fill = color;
                    base.dashStyle = style.border && style.border.dashStyle || "solid";
                    delete base.r;
                    return base
                },
                _applyMarkerClipRect: function(settings) {
                    settings.clipId = null
                },
                _clearingAnimation: function(translators, drawComplete) {
                    var that = this,
                        settings = that._oldgetAffineCoordOptions(translators) || that._getAffineCoordOptions(translators);
                    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.attr({
                                scaleX: null,
                                scaleY: null,
                                translateX: 0,
                                translateY: 0
                            });
                            drawComplete()
                        })
                    })
                },
                _createGroups: function(animationEnabled, style, firstDrawing) {
                    var that = this,
                        settings = {};
                    scatterSeries._createGroups.apply(that, arguments);
                    if (animationEnabled && firstDrawing)
                        settings = this._getAffineCoordOptions(that.translators, true);
                    else if (!animationEnabled)
                        settings = {
                            scaleX: 1,
                            scaleY: 1,
                            translateX: 0,
                            translateY: 0
                        };
                    that._markersGroup.attr(settings)
                },
                _drawPoint: function(options) {
                    options.hasAnimation = options.hasAnimation && !options.firstDrawing;
                    options.firstDrawing = false;
                    scatterSeries._drawPoint.call(this, options)
                },
                _getMainColor: function() {
                    return this._options.mainSeriesColor
                },
                _createPointStyles: function(pointOptions, isCustomPointOptions) {
                    var that = this,
                        mainColor = pointOptions.color || that._getMainColor(),
                        specialMainColor = that._getSpecialColor(mainColor);
                    return {
                            normal: that._parsePointStyle(pointOptions, mainColor, mainColor, isCustomPointOptions),
                            hover: that._parsePointStyle(pointOptions.hoverStyle || {}, specialMainColor, mainColor, isCustomPointOptions),
                            selection: that._parsePointStyle(pointOptions.selectionStyle || {}, specialMainColor, mainColor, isCustomPointOptions)
                        }
                },
                _updatePointsVisibility: function() {
                    var visibility = this._options.visible;
                    $.each(this._points, function(_, point) {
                        point._options.visible = visibility
                    })
                },
                _preparePointOptions: function(customOptions) {
                    var options = this._options;
                    return customOptions ? _extend(true, {}, options, customOptions) : options
                },
                _animate: function(firstDrawing) {
                    var that = this,
                        complete = function() {
                            that._animateComplete()
                        },
                        animateFunc = function(drawedPoints, complete) {
                            var lastPointIndex = drawedPoints.length - 1;
                            _each(drawedPoints || [], function(i, point) {
                                point.animate(i === lastPointIndex ? complete : undefined, point.getMarkerCoords())
                            })
                        };
                    that._animatePoints(firstDrawing, complete, animateFunc)
                },
                _getPointSize: function() {
                    return DEFAULT_BAR_POINT_SIZE
                },
                _beginUpdateData: function(data) {
                    scatterSeries._beginUpdateData.call(this, data);
                    this._patterns = $.map(this._patterns, function(pattern) {
                        if (pattern._custom) {
                            pattern.remove();
                            return null
                        }
                        else
                            return pattern
                    })
                }
            };
        chartSeries.bar = _extend({}, scatterSeries, baseBarSeriesMethods, {
            _getAffineCoordOptions: function(translators) {
                var rotated = this._options.rotated,
                    direction = rotated ? "x" : "y",
                    settings = {
                        scaleX: rotated ? 0.001 : 1,
                        scaleY: rotated ? 1 : 0.001
                    };
                settings["translate" + direction.toUpperCase()] = translators[direction].translate("canvas_position_default");
                return settings
            },
            _getRangeData: function() {
                var rangeData = areaSeries._getRangeData.apply(this, arguments);
                rangeData.arg.stick = false;
                return rangeData
            },
            _animatePoints: function(firstDrawing, complete, animateFunc) {
                var that = this;
                that._markersGroup.animate({
                    scaleX: 1,
                    scaleY: 1,
                    translateY: 0,
                    translateX: 0
                }, undefined, complete);
                if (!firstDrawing)
                    animateFunc(that._drawedPoints, complete)
            }
        });
        polarSeries.bar = _extend({}, polarSeries.scatter, baseBarSeriesMethods, {
            _animatePoints: function(firstDrawing, complete, animateFunc) {
                animateFunc(this._drawedPoints, complete)
            },
            _createGroups: function() {
                scatterSeries._createGroups.apply(this, arguments)
            },
            _drawPoint: function(point, groups, animationEnabled) {
                scatterSeries._drawPoint.call(this, point, groups, animationEnabled)
            },
            _parsePointStyle: function(style) {
                var base = baseBarSeriesMethods._parsePointStyle.apply(this, arguments);
                base.opacity = style.opacity;
                return base
            },
            _createMarkerGroup: function() {
                var that = this,
                    markersSettings = that._getPointOptions().styles.normal,
                    groupSettings;
                markersSettings["class"] = "dxc-markers";
                that._applyMarkerClipRect(markersSettings);
                groupSettings = _extend({}, markersSettings);
                delete groupSettings.opacity;
                that._createGroup("_markersGroup", that, that._group, groupSettings)
            },
            _createLegendState: areaSeries._createLegendState,
            _getRangeData: areaSeries._getRangeData
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file rangeSeries.js */
    (function($, DX) {
        var core = DX.viz.core,
            series = core.series.mixins.chart,
            _extend = $.extend,
            _isDefined = DX.utils.isDefined,
            _noop = $.noop,
            rangeCalculator = core.series.helpers.rangeDataCalculator,
            areaSeries = series.area;
        var baseRangeSeries = {
                _beginUpdateData: _noop,
                areErrorBarsVisible: _noop,
                _createErrorBarGroup: _noop,
                _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.calculateRangeData(this, zoomArgs, calcIntervalFunction, "value", "minValue");
                    rangeCalculator.addRangeSeriesLabelPaddings(this);
                    return this._rangeData
                },
                _getPointData: function(data, options) {
                    return {
                            tag: data[options.tagField || "tag"],
                            minValue: data[options.rangeValue1Field || "val1"],
                            value: data[options.rangeValue2Field || "val2"],
                            argument: data[options.argumentField || "arg"]
                        }
                },
                _fusionPoints: function(fusionPoints, tick) {
                    var calcMedianValue = series.scatter._calcMedianValue,
                        value = calcMedianValue.call(this, fusionPoints, "value"),
                        minValue = calcMedianValue.call(this, fusionPoints, "minValue");
                    if (value === null || minValue === null)
                        value = minValue = null;
                    return {
                            minValue: minValue,
                            value: value,
                            argument: tick,
                            tag: null
                        }
                },
                getValueFields: function() {
                    return [this._options.rangeValue1Field || "val1", this._options.rangeValue2Field || "val2"]
                }
            };
        series.rangebar = _extend({}, series.bar, baseRangeSeries);
        series.rangearea = _extend({}, areaSeries, {
            _drawPoint: function(options) {
                var point = options.point;
                if (point.isInVisibleArea()) {
                    point.clearVisibility();
                    point.draw(this._renderer, options.groups);
                    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 that = this,
                    drawnElement = areaSeries._drawElement.call(that, segment, group);
                drawnElement.bottomLine = that._bordersGroup && that._createBorderElement(segment.bottomLine, {"stroke-width": that._styles.normal.border["stroke-width"]}).append(that._bordersGroup);
                return drawnElement
            },
            _applyStyle: function(style) {
                var that = this,
                    elementsGroup = that._elementsGroup,
                    bordersGroup = that._bordersGroup;
                elementsGroup && elementsGroup.attr(style.elements);
                bordersGroup && bordersGroup.attr(style.border);
                $.each(that._graphics || [], function(_, graphic) {
                    graphic.line && graphic.line.attr({"stroke-width": style.border["stroke-width"]});
                    graphic.bottomLine && graphic.bottomLine.attr({"stroke-width": style.border["stroke-width"]})
                })
            },
            _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.attr(bottomLineParams)
            }
        }, baseRangeSeries)
    })(jQuery, DevExpress);
    /*! Module viz-core, file bubbleSeries.js */
    (function($, DX) {
        var mixins = DX.viz.core.series.mixins,
            series = mixins.chart,
            scatterSeries = series.scatter,
            barSeries = series.bar,
            _isDefined = DX.utils.isDefined,
            _extend = $.extend,
            _each = $.each,
            _noop = $.noop;
        series.bubble = _extend({}, scatterSeries, {
            _fillErrorBars: _noop,
            _getRangeCorrector: _noop,
            _calculateErrorBars: _noop,
            _getMainColor: barSeries._getMainColor,
            _createPointStyles: barSeries._createPointStyles,
            _createPattern: barSeries._createPattern,
            _updatePointsVisibility: barSeries._updatePointsVisibility,
            _preparePointOptions: barSeries._preparePointOptions,
            _getSpecialColor: barSeries._getSpecialColor,
            _applyMarkerClipRect: series.line._applyElementsClipRect,
            _parsePointStyle: mixins.polar.bar._parsePointStyle,
            _createLegendState: series.area._createLegendState,
            _createMarkerGroup: mixins.polar.bar._createMarkerGroup,
            areErrorBarsVisible: _noop,
            _createErrorBarGroup: _noop,
            _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);
                pointData.size = data[options.sizeField || "size"];
                return pointData
            },
            _fusionPoints: function(fusionPoints, tick) {
                var calcMedianValue = scatterSeries._calcMedianValue;
                return {
                        size: calcMedianValue.call(this, fusionPoints, "size"),
                        value: calcMedianValue.call(this, fusionPoints, "value"),
                        argument: tick,
                        tag: null
                    }
            },
            getValueFields: function() {
                var options = this._options;
                return [options.valueField || "val", 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,
                    partitionDuration = 0.5,
                    lastPointIndex = that._drawedPoints.length - 1,
                    labelsGroup = that._labelsGroup;
                labelsGroup && labelsGroup.animate({opacity: 0.001}, {
                    duration: that._defaultDuration,
                    partitionDuration: partitionDuration
                }, function() {
                    _each(that._drawedPoints || [], function(i, p) {
                        p.animate(i === lastPointIndex ? drawComplete : undefined, {r: 0}, partitionDuration)
                    })
                })
            },
            _animate: function() {
                var that = this,
                    lastPointIndex = that._drawedPoints.length - 1,
                    labelsGroup = that._labelsGroup,
                    labelAnimFunc = function() {
                        labelsGroup && labelsGroup.animate({opacity: 1}, {duration: that._defaultDuration})
                    };
                _each(that._drawedPoints || [], function(i, p) {
                    p.animate(i === lastPointIndex ? labelAnimFunc : undefined, {
                        r: p.bubbleSize,
                        translateX: p.x,
                        translateY: p.y
                    })
                })
            },
            _beginUpdateData: barSeries._beginUpdateData
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file pieSeries.js */
    (function($, DX) {
        var mixins = DX.viz.core.series.mixins,
            pieSeries = mixins.pie,
            _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,
            _createErrorBarGroup: _noop,
            _drawPoint: function(options) {
                var point = options.point,
                    legendCallback = options.legendCallback;
                scatterSeries._drawPoint.call(this, options);
                !point.isVisible() && point.setInvisibility();
                legendCallback && point.isSelected() && legendCallback(point)("applySelected")
            },
            adjustLabels: function() {
                var that = this,
                    points = that._points || [],
                    maxLabelLength,
                    labelsBBoxes = [];
                _each(points, function(_, point) {
                    if (point._label.isVisible() && point._label.getLayoutOptions().position !== "inside") {
                        point.setLabelEllipsis();
                        labelsBBoxes.push(point._label.getBoundingRect().width)
                    }
                });
                if (labelsBBoxes.length)
                    maxLabelLength = _max.apply(null, labelsBBoxes);
                _each(points, function(_, point) {
                    if (point._label.isVisible() && point._label.getLayoutOptions().position !== "inside") {
                        point._maxLabelLength = maxLabelLength;
                        point.updateLabelCoord()
                    }
                })
            },
            _processRange: _noop,
            _applyElementsClipRect: _noop,
            getColor: _noop,
            areErrorBarsVisible: _noop,
            _prepareSeriesToDrawing: _noop,
            _endUpdateData: scatterSeries._prepareSeriesToDrawing,
            resetLabelSetups: function() {
                _each(this._points || [], function(_, point) {
                    point._label.clearVisibility()
                })
            },
            drawLabelsWOPoints: function(translators) {
                var that = this,
                    options = that._options,
                    points = that._points || [],
                    labelsGroup;
                if (options.label.position === "inside")
                    return false;
                that._createGroups();
                labelsGroup = that._labelsGroup;
                _each(points, function(_, point) {
                    point.drawLabel(translators, that._renderer, labelsGroup)
                });
                return true
            },
            _getCreatingPointOptions: function() {
                return this._getPointOptions()
            },
            _updateOptions: function(options) {
                this.labelSpace = 0;
                this.innerRadius = this.type === "pie" ? 0 : options.innerRadius
            },
            _checkData: function(data) {
                var base = barSeries._checkData(data);
                return this._options.paintNullPoints ? base : base && data.value !== null
            },
            _createMarkerGroup: function() {
                var that = this;
                if (!that._markersGroup)
                    that._markersGroup = that._renderer.g().attr({"class": "dxc-markers"}).append(that._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 that = this,
                    mainColor = pointOptions.color || that._getMainColor(),
                    specialMainColor = that._getSpecialColor(mainColor);
                return {
                        normal: that._parsePointStyle(pointOptions, mainColor, mainColor),
                        hover: that._parsePointStyle(pointOptions.hoverStyle, specialMainColor, mainColor),
                        selection: that._parsePointStyle(pointOptions.selectionStyle, specialMainColor, mainColor),
                        legendStyles: {
                            normal: that._createLegendState(pointOptions, mainColor),
                            hover: that._createLegendState(pointOptions.hoverStyle, specialMainColor),
                            selection: that._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,
                    originalPoints = that._originalPoints || [],
                    minSegmentSize = that._options.minSegmentSize,
                    minShownValue,
                    pointIndex = 0,
                    total,
                    isAllPointsNegative = _max.apply(null, _map(originalPoints, function(p) {
                        return p.value
                    })) <= 0,
                    points = that._originalPoints = that._points = _map(originalPoints, function(point) {
                        if (point.value === null || !isAllPointsNegative && 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)
                });
                this._centerX = correction.centerX;
                this._centerY = correction.centerY;
                this._radiusOuter = correction.radiusOuter
            },
            _animate: function(firstDrawing) {
                var that = this,
                    index = 0,
                    timeThreshold = 0.2,
                    points = that._points,
                    pointsCount = points && points.length,
                    duration = 1 / (timeThreshold * (pointsCount - 1) + 1),
                    completeFunc = function() {
                        that._animateComplete()
                    },
                    animateP = function() {
                        points[index] && points[index].animate(index === pointsCount - 1 ? completeFunc : undefined, duration, stepFunc);
                        index++
                    },
                    stepFunc = function(_, progress) {
                        if (progress >= timeThreshold) {
                            this.step = null;
                            animateP()
                        }
                    };
                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
                    })
            },
            getPointByCoord: function(x, y) {
                var points = this._points;
                for (var i = 0; i < points.length; i++)
                    if (points[i].coordsIn(x, y))
                        return points[i]
            },
            _beginUpdateData: function() {
                this._deletePatterns();
                this._patterns = []
            },
            getCenter: function() {
                return {
                        x: this._centerX,
                        y: this._centerY
                    }
            }
        });
        pieSeries.doughnut = pieSeries.donut = pieSeries.pie
    })(jQuery, DevExpress);
    /*! Module viz-core, file financialSeries.js */
    (function($, DX) {
        var viz = DX.viz,
            seriesNS = viz.core.series,
            series = seriesNS.mixins.chart,
            scatterSeries = series.scatter,
            barSeries = series.bar,
            rangeCalculator = seriesNS.helpers.rangeDataCalculator,
            _isDefined = DX.utils.isDefined,
            _extend = $.extend,
            _each = $.each,
            _noop = $.noop,
            DEFAULT_FINANCIAL_POINT_SIZE = 10;
        series.stock = _extend({}, scatterSeries, {
            _animate: _noop,
            _applyMarkerClipRect: function(settings) {
                settings.clipId = this._forceClipping ? this._paneClipRectID : this._widePaneClipRectID
            },
            _updatePointsVisibility: barSeries._updatePointsVisibility,
            _preparePointOptions: barSeries._preparePointOptions,
            _getRangeCorrector: _noop,
            _createErrorBarGroup: _noop,
            areErrorBarsVisible: _noop,
            _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() {
                var that = this,
                    defaultPointOptions,
                    creatingPointOptions = that._predefinedPointOptions;
                if (!creatingPointOptions) {
                    defaultPointOptions = this._getPointOptions();
                    that._predefinedPointOptions = creatingPointOptions = _extend(true, {styles: {}}, defaultPointOptions);
                    creatingPointOptions.styles.normal = creatingPointOptions.styles.positive.normal = creatingPointOptions.styles.reduction.normal = creatingPointOptions.styles.reductionPositive.normal = {"stroke-width": defaultPointOptions.styles && defaultPointOptions.styles.normal && defaultPointOptions.styles.normal["stroke-width"]}
                }
                return creatingPointOptions
            },
            _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.calculateRangeData(this, zoomArgs, calcIntervalFunction, "highValue", "lowValue");
                rangeCalculator.addRangeSeriesLabelPaddings(this);
                return this._rangeData
            },
            _getPointData: function(data, options) {
                var that = this,
                    level,
                    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[options.argumentField || "date"],
                        highValue: data[highValueField],
                        lowValue: data[lowValueField],
                        closeValue: data[closeValueField],
                        openValue: data[openValueField],
                        reductionValue: reductionValue,
                        tag: data[options.tagField || "tag"],
                        isReduction: that._checkReduction(reductionValue)
                    }
            },
            _parsePointStyle: function(style, defaultColor, innerColor) {
                return {
                        stroke: style.color || defaultColor,
                        "stroke-width": 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, isCustomPointOptions) {
                var that = this,
                    mainPointColor = options.color || that._options.mainSeriesColor;
                return {
                        normal: that._parsePointStyle(options, mainPointColor, mainPointColor, isCustomPointOptions),
                        hover: that._parsePointStyle(options.hoverStyle, mainPointColor, mainPointColor, isCustomPointOptions),
                        selection: that._parsePointStyle(options.selectionStyle, mainPointColor, mainPointColor, isCustomPointOptions)
                    }
            },
            _getReductionStyle: function(options, isCustomPointOptions) {
                var that = this,
                    reductionColor = options.reduction.color;
                return {
                        normal: that._parsePointStyle({
                            color: reductionColor,
                            width: options.width,
                            hatching: options.hatching
                        }, reductionColor, reductionColor, isCustomPointOptions),
                        hover: that._parsePointStyle(options.hoverStyle, reductionColor, reductionColor, isCustomPointOptions),
                        selection: that._parsePointStyle(options.selectionStyle, reductionColor, reductionColor, isCustomPointOptions)
                    }
            },
            _createPointStyles: function(pointOptions, isCustomPointOptions) {
                var that = this,
                    innerColor = that._options.innerColor,
                    styles = that._getDefaultStyle(pointOptions, isCustomPointOptions),
                    positiveStyle,
                    reductionStyle,
                    reductionPositiveStyle;
                positiveStyle = _extend(true, {}, styles);
                reductionStyle = that._getReductionStyle(pointOptions, isCustomPointOptions);
                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 that = this,
                    result = false;
                if (value !== null) {
                    if (_isDefined(that.prevLevelValue))
                        result = value < that.prevLevelValue;
                    that.prevLevelValue = value
                }
                return result
            },
            _fusionPoints: function(fusionPoints, tick) {
                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"
            },
            _beginUpdateData: _noop
        });
        series.candlestick = _extend({}, series.stock, {
            _createPattern: barSeries._createPattern,
            _beginUpdateData: barSeries._beginUpdateData,
            _parsePointStyle: function(style, defaultColor, innerColor, isCustomPointOptions) {
                var color = this._createPattern(style.color || innerColor, style.hatching, isCustomPointOptions),
                    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 core = DX.viz.core,
            series = core.series,
            chartSeries = series.mixins.chart,
            polarSeries = series.mixins.polar,
            areaSeries = chartSeries.area,
            barSeries = chartSeries.bar,
            lineSeries = chartSeries.line,
            rangeCalculator = core.series.helpers.rangeDataCalculator,
            _extend = $.extend,
            utils = DX.utils,
            _noop = $.noop,
            baseStackedSeries = {
                _processRange: _noop,
                _getRangeCorrector: _noop,
                _fillErrorBars: _noop,
                _calculateErrorBars: _noop,
                _processStackedRange: function() {
                    var that = this,
                        prevPoint;
                    that._resetRangeData();
                    $.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) {
                    var that = this;
                    that._processStackedRange();
                    rangeCalculator.calculateRangeData(that, zoomArgs, calcIntervalFunction);
                    rangeCalculator.addLabelPaddings(that);
                    rangeCalculator.processFullStackedRange(that);
                    rangeCalculator.calculateRangeMinValue(that, zoomArgs);
                    return that._rangeData
                },
                isFullStackedSeries: function() {
                    return true
                }
            });
        chartSeries.stackedline = _extend({}, lineSeries, baseStackedSeries, {_getRangeData: function() {
                this._processStackedRange();
                return lineSeries._getRangeData.apply(this, arguments)
            }});
        chartSeries.stackedspline = _extend({}, chartSeries.spline, baseStackedSeries, {_getRangeData: chartSeries.stackedline._getRangeData});
        chartSeries.fullstackedline = _extend({}, lineSeries, baseFullStackedSeries, {_getRangeData: function(zoomArgs, calcIntervalFunction) {
                var that = this;
                that._processStackedRange();
                rangeCalculator.calculateRangeData(that, zoomArgs, calcIntervalFunction);
                rangeCalculator.addLabelPaddings(that);
                rangeCalculator.processFullStackedRange(that);
                return that._rangeData
            }});
        chartSeries.fullstackedspline = _extend({}, chartSeries.spline, baseFullStackedSeries, {_getRangeData: chartSeries.fullstackedline._getRangeData});
        chartSeries.stackedbar = _extend({}, barSeries, baseStackedSeries, {_getRangeData: function() {
                this._processStackedRange();
                return barSeries._getRangeData.apply(this, arguments)
            }});
        chartSeries.fullstackedbar = _extend({}, barSeries, baseFullStackedSeries, {_getRangeData: function() {
                var rangeData = baseFullStackedSeries._getRangeData.apply(this, arguments);
                rangeData.arg.stick = false;
                return rangeData
            }});
        function clonePoint(point, value, minValue, position) {
            point = utils.clone(point);
            point.value = value;
            point.minValue = minValue;
            point.translate();
            point.argument = point.argument + position;
            return point
        }
        function preparePointsForStackedAreaSegment(points) {
            points = $.map(points, function(p) {
                var result = [p];
                if (p.leftHole)
                    result = [clonePoint(p, p.leftHole, p.minLeftHole, "left"), p];
                if (p.rightHole)
                    result.push(clonePoint(p, p.rightHole, p.minRightHole, "right"));
                return result
            });
            return points
        }
        chartSeries.stackedarea = _extend({}, areaSeries, baseStackedSeries, {_prepareSegment: function(points, rotated) {
                return areaSeries._prepareSegment.call(this, preparePointsForStackedAreaSegment(points, this._prevSeries), rotated)
            }});
        function getPointsByArgFromPrevSeries(prevSeries, argument) {
            var result;
            while (prevSeries) {
                result = prevSeries._segmentByArg[argument];
                if (result)
                    break;
                prevSeries = prevSeries._prevSeries
            }
            return result
        }
        chartSeries.stackedsplinearea = _extend({}, chartSeries.splinearea, baseStackedSeries, {_prepareSegment: function(points, rotated) {
                var that = this,
                    areaSegment;
                points = preparePointsForStackedAreaSegment(points, that._prevSeries);
                if (!this._prevSeries || points.length === 1)
                    areaSegment = chartSeries.splinearea._prepareSegment.call(this, points, rotated);
                else {
                    var fwPoints = chartSeries.spline._calculateBezierPoints(points, rotated),
                        bwPoints = $.map(points, function(p) {
                            var point = p.getCoords(true);
                            point.argument = p.argument;
                            return point
                        }),
                        prevSeriesFwPoints = $.map(that._prevSeries._segments, function(seg) {
                            return seg.line
                        }),
                        pointByArg = {};
                    $.each(prevSeriesFwPoints, function(_, p) {
                        if (p.argument !== null) {
                            var argument = p.argument.valueOf();
                            if (!pointByArg[argument])
                                pointByArg[argument] = [p];
                            else
                                pointByArg[argument].push(p)
                        }
                    });
                    that._prevSeries._segmentByArg = pointByArg;
                    bwPoints = chartSeries.spline._calculateBezierPoints(bwPoints, rotated);
                    $.each(bwPoints, function(i, p) {
                        var argument = p.argument.valueOf(),
                            prevSeriesPoints;
                        if (i % 3 === 0) {
                            prevSeriesPoints = pointByArg[argument] || getPointsByArgFromPrevSeries(that._prevSeries, argument);
                            if (prevSeriesPoints) {
                                bwPoints[i - 1] && prevSeriesPoints[0] && (bwPoints[i - 1] = prevSeriesPoints[0]);
                                bwPoints[i + 1] && (bwPoints[i + 1] = prevSeriesPoints[2] || p)
                            }
                        }
                    });
                    areaSegment = {
                        line: fwPoints,
                        area: fwPoints.concat(bwPoints.reverse())
                    };
                    that._areaPointsToSplineAreaPoints(areaSegment.area)
                }
                return areaSegment
            }});
        chartSeries.fullstackedarea = _extend({}, areaSeries, baseFullStackedSeries, {_prepareSegment: chartSeries.stackedarea._prepareSegment});
        chartSeries.fullstackedsplinearea = _extend({}, chartSeries.splinearea, baseFullStackedSeries, {_prepareSegment: chartSeries.stackedsplinearea._prepareSegment});
        polarSeries.stackedbar = _extend({}, polarSeries.bar, baseStackedSeries, {_getRangeData: function() {
                this._processStackedRange();
                return polarSeries.bar._getRangeData.apply(this, arguments)
            }})
    })(jQuery, DevExpress);
    /*! Module viz-core, file basePoint.js */
    (function($, DX) {
        var seriesNS = DX.viz.core.series,
            statesConsts = seriesNS.helpers.consts.states,
            _each = $.each,
            _extend = $.extend,
            _isDefined = DX.utils.isDefined,
            seiresMixins = seriesNS.mixins,
            _noop = $.noop;
        function Point() {
            this.ctor.apply(this, arguments)
        }
        seriesNS.points = {Point: Point};
        Point.prototype = {
            ctor: function(series, dataItem, options) {
                this.series = series;
                this.update(dataItem, options);
                this._emptySettings = {
                    fill: null,
                    stroke: null,
                    dashStyle: null
                }
            },
            getColor: function() {
                return this._styles.normal.fill || this.series.getColor()
            },
            _getStyle: function() {
                var that = this,
                    styles = that._styles,
                    style;
                if (that.isSelected())
                    style = styles.selection;
                else if (that.isHovered())
                    style = styles.hover;
                else {
                    that.fullState = statesConsts.normalMark;
                    style = styles.normal
                }
                that._currentStyle = style;
                return style
            },
            update: function(dataItem, options) {
                this.updateOptions(options);
                this.updateData(dataItem)
            },
            updateData: function(dataItem) {
                var that = this;
                that.argument = that.initialArgument = that.originalArgument = dataItem.argument;
                that.tag = dataItem.tag;
                that.index = dataItem.index;
                that.lowError = dataItem.lowError;
                that.highError = dataItem.highError;
                that._updateData(dataItem);
                !that.hasValue() && that.setInvisibility();
                that._fillStyle();
                that._updateLabelData()
            },
            deleteMarker: function() {
                var that = this;
                if (that.graphic)
                    that.graphic.dispose();
                that.graphic = null
            },
            _drawErrorBar: _noop,
            draw: function(renderer, groups, animationEnabled, firstDrawing) {
                var that = this;
                if (that._needDeletingOnDraw) {
                    that.deleteMarker();
                    that._needDeletingOnDraw = false
                }
                if (that._needClearingOnDraw) {
                    that.clearMarker();
                    that._needClearingOnDraw = false
                }
                if (!that._hasGraphic())
                    that._getMarkerVisibility() && that._drawMarker(renderer, groups.markers, animationEnabled, firstDrawing);
                else
                    that._updateMarker(animationEnabled, undefined, groups.markers);
                that._drawLabel(renderer, groups.labels);
                that._drawErrorBar(renderer, groups.errorBars, animationEnabled)
            },
            applyStyle: function(style) {
                var that = this;
                if (that.graphic) {
                    if (style === "normal") {
                        if (that.isHovered()) {
                            that.applyStyle("hover");
                            return
                        }
                        that.clearMarker()
                    }
                    else
                        that.graphic.toForeground();
                    that._currentStyle = that._styles[style];
                    that._updateMarker(true, that._currentStyle)
                }
            },
            setHoverState: function() {
                this.series.setPointHoverState(this)
            },
            releaseHoverState: function(callback) {
                var that = this;
                that.series.releasePointHoverState(that, callback);
                if (that.graphic)
                    !that.isSelected() && that.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,
                    widgetType = newOptions.widgetType,
                    oldType = oldOptions && oldOptions.type,
                    newType = newOptions.type;
                if (seiresMixins[widgetType].pointTypes[oldType] !== seiresMixins[widgetType].pointTypes[newType]) {
                    that._needDeletingOnDraw = true;
                    that._needClearingOnDraw = false;
                    that._checkLabelsChanging(oldType, newType) && that.deleteLabel();
                    that._resetType(oldType, widgetType);
                    that._setType(newType, widgetType)
                }
                else {
                    that._needDeletingOnDraw = that._checkSymbol(oldOptions, newOptions);
                    that._needClearingOnDraw = that._checkCustomize(oldOptions, newOptions)
                }
                that._options = newOptions;
                that._fillStyle();
                that._updateLabelOptions(seiresMixins[widgetType].pointTypes[newType])
            },
            translate: function(translators) {
                var that = this;
                that.translators = translators || that.translators;
                that.translators && that.hasValue() && that._translate(that.translators)
            },
            _checkCustomize: function(oldOptions, newOptions) {
                return oldOptions.styles.usePointCustomOptions && !newOptions.styles.usePointCustomOptions
            },
            _getCustomLabelVisibility: function() {
                return this._styles.useLabelCustomOptions ? !!this._options.label.visible : null
            },
            getBoundingRect: function() {
                return this._getGraphicBbox()
            },
            _resetType: function(type, widgetType) {
                var that = this;
                if (type)
                    _each(seriesNS.points.mixins[seiresMixins[widgetType].pointTypes[type]], function(methodName) {
                        delete that[methodName]
                    })
            },
            _setType: function(type, widgetType) {
                var that = this;
                _each(seriesNS.points.mixins[seiresMixins[widgetType].pointTypes[type]], function(methodName, method) {
                    that[methodName] = method
                })
            },
            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) {
                var that = this;
                if (!min)
                    return {
                            x: that.x,
                            y: that.y
                        };
                if (!that._options.rotated)
                    return {
                            x: that.x,
                            y: that.minY
                        };
                return {
                        x: that.minX,
                        y: that.y
                    }
            },
            getDefaultCoords: function() {
                var that = this;
                return !that._options.rotated ? {
                        x: that.x,
                        y: that.defaultY
                    } : {
                        x: that.defaultX,
                        y: that.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
            },
            getBoundaryCoords: function() {
                return this.getBoundingRect()
            },
            getCrosshairCoords: _noop,
            getPointRadius: _noop,
            _populatePointShape: _noop,
            _checkSymbol: _noop,
            getMarkerCoords: _noop,
            hide: _noop,
            show: _noop,
            hideMarker: _noop,
            setInvisibility: _noop,
            clearVisibility: _noop,
            isVisible: _noop,
            resetCorrection: _noop,
            correctValue: _noop,
            setPercentValue: _noop,
            correctCoordinates: _noop,
            coordsIn: _noop,
            getTooltipParams: _noop,
            setLabelEllipsis: _noop,
            updateLabelCoord: _noop,
            drawLabel: _noop,
            dispose: function() {
                var that = this;
                that.deleteMarker();
                that.deleteLabel();
                that._errorBar && this._errorBar.dispose();
                that._options = that._styles = that.series = that.translators = that._errorBar = 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(formatObject);
                        sharedTooltipValuesArray.push(formatObject.seriesName + ": " + formatObject.valueText)
                    });
                    _extend(tooltipFormatObject, {
                        points: tooltipStackPointsFormatObject,
                        valueText: sharedTooltipValuesArray.join("\n"),
                        stackName: that.stackPoints.stackName
                    })
                }
                return tooltipFormatObject
            },
            setHole: function(holeValue, position) {
                var that = this,
                    minValue = isFinite(that.minValue) ? that.minValue : 0;
                if (_isDefined(holeValue))
                    if (position === "left") {
                        that.leftHole = that.value - holeValue;
                        that.minLeftHole = minValue - holeValue
                    }
                    else {
                        that.rightHole = that.value - holeValue;
                        that.minRightHole = minValue - holeValue
                    }
            },
            resetHoles: function() {
                this.leftHole = null;
                this.minLeftHole = null;
                this.rightHole = null;
                this.minRightHole = null
            },
            getLabel: function() {
                return this._label
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file label.js */
    (function(DX, $, undefined) {
        var _degreesToRadians = DX.utils.degreesToRadians,
            _patchFontOptions = DX.viz.core.utils.patchFontOptions,
            _round = Math.round,
            _abs = Math.abs,
            _min = Math.min,
            _max = Math.max,
            _ceil = Math.ceil,
            _getCosAndSin = DX.utils.getCosAndSin,
            _rotateBBox = DX.viz.renderers.rotateBBox,
            LABEL_BACKGROUND_PADDING_X = 8,
            LABEL_BACKGROUND_PADDING_Y = 4;
        function getClosestCoord(point, coords) {
            var closestDistase = Infinity,
                closestCoord;
            $.each(coords, function(_, coord) {
                var x = point[0] - coord[0],
                    y = point[1] - coord[1],
                    distance = x * x + y * y;
                if (distance < closestDistase) {
                    closestDistase = distance;
                    closestCoord = coord
                }
            });
            return closestCoord
        }
        var barPointStrategy = {
                isLabelInside: function(labelPoint, figure) {
                    return labelPoint.x >= figure.x && labelPoint.x <= figure.x + figure.width && labelPoint.y >= figure.y && labelPoint.y <= figure.y + figure.height
                },
                prepareLabelPoints: function(points, center, angle, hasBackground) {
                    return !hasBackground ? points : [center]
                },
                getFigureCenter: function(figure) {
                    return [figure.x + figure.width / 2, figure.y + figure.height / 2]
                },
                findFigurePoint: function(figure, labelPoint) {
                    var figureCenter = barPointStrategy.getFigureCenter(figure),
                        point = getClosestCoord(labelPoint, [[figure.x, figureCenter[1]], [figureCenter[0], figure.y + figure.height], [figure.x + figure.width, figureCenter[1]], [figureCenter[0], figure.y]]);
                    return [_round(point[0]), _round(point[1])]
                }
            };
        var symbolPointStrategy = {
                isLabelInside: function() {
                    return false
                },
                prepareLabelPoints: barPointStrategy.prepareLabelPoints,
                getFigureCenter: function(figure) {
                    return [figure.x, figure.y]
                },
                findFigurePoint: function(figure, labelPoint) {
                    var angle = Math.atan2(figure.y - labelPoint[1], labelPoint[0] - figure.x);
                    return [_round(figure.x + figure.r * Math.cos(angle)), _round(figure.y - figure.r * Math.sin(angle))]
                }
            };
        var piePointStrategy = {
                isLabelInside: function(_0, _1, isOutside) {
                    return !isOutside
                },
                prepareLabelPoints: function(points, center, angle) {
                    var rotatedPoints = [],
                        x0 = center[0],
                        y0 = center[1],
                        cossin = _getCosAndSin(angle || 0);
                    $.each(points, function(_, point) {
                        rotatedPoints.push([_round((point[0] - x0) * cossin.cos + (point[1] - y0) * cossin.sin + x0), _round(-(point[0] - x0) * cossin.sin + (point[1] - y0) * cossin.cos + y0)])
                    });
                    return rotatedPoints
                },
                getFigureCenter: symbolPointStrategy.getFigureCenter,
                findFigurePoint: function(figure, labelPoint) {
                    var x = figure.x + (figure.y - labelPoint[1]) / Math.tan(_degreesToRadians(figure.angle)),
                        point = [figure.x, figure.y];
                    if (figure.x <= x && x <= labelPoint[0] || figure.x >= x && x >= labelPoint[0])
                        point.push(_round(x), labelPoint[1]);
                    return point
                }
            };
        function selectStrategy(figure) {
            return figure.angle !== undefined && piePointStrategy || figure.r !== undefined && symbolPointStrategy || barPointStrategy
        }
        function disposeItem(obj, field) {
            obj[field] && obj[field].dispose();
            obj[field] = null
        }
        function checkBackground(background) {
            return background && (background.fill && background.fill !== "none" || background["stroke-width"] > 0 && background.stroke && background.stroke !== "none")
        }
        function checkConnector(connector) {
            return connector && connector["stroke-width"] > 0 && connector.stroke && connector.stroke !== "none"
        }
        function formatValue(value, format, precision) {
            return DX.formatHelper.format(value, format, precision)
        }
        function formatText(data, options) {
            var format = options.format,
                precision = options.precision;
            data.valueText = formatValue(data.value, format, precision);
            data.argumentText = formatValue(data.argument, options.argumentFormat, options.argumentPrecision);
            if (data.percent !== undefined)
                data.percentText = formatValue(data.percent, "percent", options.percentPrecision);
            if (data.total !== undefined)
                data.totalText = formatValue(data.total, format, precision);
            if (data.openValue !== undefined)
                data.openValueText = formatValue(data.openValue, format, precision);
            if (data.closeValue !== undefined)
                data.closeValueText = formatValue(data.closeValue, format, precision);
            if (data.lowValue !== undefined)
                data.lowValueText = formatValue(data.lowValue, format, precision);
            if (data.highValue !== undefined)
                data.highValueText = formatValue(data.highValue, format, precision);
            if (data.reductionValue !== undefined)
                data.reductionValueText = formatValue(data.reductionValue, format, precision);
            return options.customizeText ? options.customizeText.call(data, data) : data.valueText
        }
        function Label(){}
        Label.prototype = {
            constructor: Label,
            _setVisibility: function(value, state) {
                this._group && this._group.attr({visibility: value});
                this._visible = state
            },
            clearVisibility: function() {
                this._setVisibility(null, true)
            },
            hide: function() {
                this._setVisibility("hidden", false)
            },
            show: function() {
                this._setVisibility("visible", true)
            },
            isVisible: function() {
                return this._visible
            },
            setColor: function(color) {
                this._color = color
            },
            setOptions: function(options) {
                this._options = options
            },
            setData: function(data) {
                this._data = data
            },
            setDataField: function(fieldName, fieldValue) {
                this._data = this._data || {};
                this._data[fieldName] = fieldValue
            },
            getData: function() {
                return this._data
            },
            setFigureToDrawConnector: function(figure) {
                this._figure = figure
            },
            dispose: function() {
                var that = this;
                disposeItem(that, "_group");
                that._data = that._options = that._textContent = that._visible = that._insideGroup = that._text = that._background = that._connector = that._figure = null
            },
            draw: function(renderer, container, customVisibility) {
                var that = this,
                    options = that._options || {},
                    text = that._textContent = formatText(that._data, that._options) || null;
                that.clearVisibility();
                if (text) {
                    if (!that._group) {
                        that._group = renderer.g().append(container);
                        that._insideGroup = renderer.g().append(that._group);
                        that._text = renderer.text("", 0, 0).append(that._insideGroup)
                    }
                    that._text.css(options.attributes ? _patchFontOptions(options.attributes.font) : {});
                    if (checkBackground(options.background)) {
                        that._background = that._background || renderer.rect().append(that._insideGroup).toBackground();
                        that._background.attr(options.background);
                        that._color && that._background.attr({fill: that._color})
                    }
                    else
                        disposeItem(that, "_background");
                    if (checkConnector(options.connector)) {
                        that._connector = that._connector || renderer.path([], "line").sharp().append(that._group).toBackground();
                        that._connector.attr(options.connector);
                        that._color && that._connector.attr({stroke: that._color})
                    }
                    else
                        disposeItem(that, "_connector");
                    that._updateText(text);
                    if (customVisibility !== null)
                        customVisibility ? that.show() : that.hide()
                }
                else
                    that.hide();
                return that
            },
            _updateText: function(text) {
                var that = this,
                    bbox = that._text.attr({text: text}).getBBox();
                that._textSize = [bbox.width, bbox.height];
                if (that._background) {
                    bbox.x -= LABEL_BACKGROUND_PADDING_X;
                    bbox.y -= LABEL_BACKGROUND_PADDING_Y;
                    bbox.width += 2 * LABEL_BACKGROUND_PADDING_X;
                    bbox.height += 2 * LABEL_BACKGROUND_PADDING_Y;
                    that._background.attr(bbox)
                }
                that._labelSize = [bbox.width / 2, bbox.height / 2];
                if (that._options.rotationAngle) {
                    that._insideGroup.rotate(that._options.rotationAngle, bbox.x + bbox.width / 2, bbox.y + bbox.height / 2);
                    bbox = _rotateBBox(bbox, [bbox.x + bbox.width / 2, bbox.y + bbox.height / 2], -that._options.rotationAngle)
                }
                that._bbox = bbox
            },
            _getConnectorPoints: function() {
                var that = this,
                    figure = that._figure,
                    strategy = selectStrategy(figure),
                    bbox = that.getBoundingRect(),
                    labelPoint,
                    figurePoint,
                    xc,
                    yc,
                    points = [];
                if (!strategy.isLabelInside(bbox, figure, that._options.position !== "inside")) {
                    xc = bbox.x + bbox.width / 2;
                    yc = bbox.y + bbox.height / 2;
                    points = strategy.prepareLabelPoints([[xc, yc - that._labelSize[1]], [xc + that._labelSize[0], yc], [xc, yc + that._labelSize[1]], [xc - that._labelSize[0], yc]], [xc, yc], -that._options.rotationAngle || 0, !!that._background);
                    labelPoint = getClosestCoord(strategy.getFigureCenter(figure), points);
                    labelPoint = [_round(labelPoint[0]), _round(labelPoint[1])];
                    figurePoint = strategy.findFigurePoint(figure, labelPoint);
                    points = figurePoint.concat(labelPoint)
                }
                return points
            },
            fit: function(size) {
                var that = this;
                if (!that._textContent)
                    return that;
                var cossin = _getCosAndSin(-that._options.rotationAngle || 0),
                    textSize = _min(_abs(that._textSize[0] / cossin.cos), _abs(that._textSize[1] / cossin.sin)),
                    requiredTextSize = _min(_abs(size.width / cossin.cos), _abs(size.height / cossin.sin)),
                    text = that._textContent,
                    i,
                    ii,
                    line,
                    lines,
                    lineLength,
                    requiredLineLength;
                if (textSize > requiredTextSize) {
                    lines = text.split("
");
                    for (i = 0, ii = lines.length, lineLength = 0; i < ii; ++i) {
                        line = lines[i] = lines[i].replace(/<[^>]+>/g, '');
                        lineLength = _max(lineLength, line.length)
                    }
                    requiredLineLength = _ceil(lineLength * requiredTextSize / textSize);
                    for (i = 0; i < ii; ++i)
                        lines[i] = (line = lines[i]).length > requiredLineLength ? line.substr(0, requiredLineLength - 4) + "..." : line;
                    text = lines.join("
")
                }
                that._updateText(text);
                return that
            },
            shift: function(x, y) {
                var that = this;
                if (that._textContent) {
                    that._insideGroup.attr({
                        translateX: that._x = _round(x - that._bbox.x),
                        translateY: that._y = _round(y - that._bbox.y)
                    });
                    if (that._connector)
                        that._connector.attr({points: that._getConnectorPoints()})
                }
                return that
            },
            getBoundingRect: function() {
                var bbox = this._bbox;
                return this._textContent ? {
                        x: bbox.x + this._x,
                        y: bbox.y + this._y,
                        width: bbox.width,
                        height: bbox.height
                    } : {}
            },
            getLayoutOptions: function() {
                var options = this._options;
                return {
                        alignment: options.alignment,
                        background: checkBackground(options.background),
                        horizontalOffset: options.horizontalOffset,
                        verticalOffset: options.verticalOffset,
                        radialOffset: options.radialOffset,
                        position: options.position
                    }
            }
        };
        DX.viz.core.series.points.Label = Label;
        Label._DEBUG_formatText = formatText
    })(DevExpress, jQuery);
    /*! Module viz-core, file symbolPoint.js */
    (function($, DX) {
        var core = DX.viz.core,
            seriesNS = core.series,
            _extend = $.extend,
            _isDefined = DX.utils.isDefined,
            _math = Math,
            _round = _math.round,
            _floor = _math.floor,
            _ceil = _math.ceil,
            _abs = _math.abs,
            DEFAULT_IMAGE_WIDTH = 20,
            DEFAULT_IMAGE_HEIGHT = 20,
            LABEL_OFFSET = 10,
            CANVAS_POSITION_DEFAULT = "canvas_position_default";
        function getSquareMarkerCoords(radius) {
            return [-radius, -radius, radius, -radius, radius, radius, -radius, radius, -radius, -radius]
        }
        function getPolygonMarkerCoords(radius) {
            var r = _ceil(radius);
            return [-r, 0, 0, -r, r, 0, 0, r, -r, 0]
        }
        function getCrossMarkerCoords(radius) {
            var r = _ceil(radius),
                floorHalfRadius = _floor(r / 2),
                ceilHalfRadius = _ceil(r / 2);
            return [-r, -floorHalfRadius, -floorHalfRadius, -r, 0, -ceilHalfRadius, floorHalfRadius, -r, r, -floorHalfRadius, ceilHalfRadius, 0, r, floorHalfRadius, floorHalfRadius, r, 0, ceilHalfRadius, -floorHalfRadius, r, -r, floorHalfRadius, -ceilHalfRadius, 0]
        }
        function getTriangleDownMarkerCoords(radius) {
            return [-radius, -radius, radius, -radius, 0, radius, -radius, -radius]
        }
        function getTriangleUpMarkerCoords(radius) {
            return [-radius, radius, radius, radius, 0, -radius, -radius, radius]
        }
        seriesNS.points.mixins = seriesNS.points.mixins || {};
        seriesNS.points.mixins.symbolPoint = {
            deleteLabel: function() {
                this._label.dispose();
                this._label = null
            },
            _hasGraphic: function() {
                return this.graphic
            },
            clearVisibility: function() {
                var that = this,
                    graphic = that.graphic;
                if (graphic && graphic.attr("visibility"))
                    graphic.attr({visibility: null});
                that._label.clearVisibility()
            },
            isVisible: function() {
                return this.inVisibleArea && this.series.isVisible()
            },
            setInvisibility: function() {
                var that = this,
                    graphic = that.graphic;
                if (graphic && graphic.attr("visibility") !== "hidden")
                    graphic.attr({visibility: "hidden"});
                that._errorBar && that._errorBar.attr({visibility: "hidden"});
                that._label.hide()
            },
            clearMarker: function() {
                var graphic = this.graphic;
                graphic && graphic.attr(this._emptySettings)
            },
            setAdjustSeriesLabels: function(adjustSeriesLabels) {
                this.adjustSeriesLabels = adjustSeriesLabels
            },
            _createLabel: function() {
                this._label = core.CoreFactory.createLabel()
            },
            _updateLabelData: function() {
                this._label.setData(this._getLabelFormatObject())
            },
            _updateLabelOptions: function() {
                !this._label && this._createLabel();
                this._label.setOptions(this._options.label)
            },
            _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);
                return !!(symbolChanged || imageChanged)
            },
            _populatePointShape: function(symbol, radius) {
                switch (symbol) {
                    case"square":
                        return getSquareMarkerCoords(radius);
                    case"polygon":
                        return getPolygonMarkerCoords(radius);
                    case"triangle":
                    case"triangleDown":
                        return getTriangleDownMarkerCoords(radius);
                    case"triangleUp":
                        return getTriangleUpMarkerCoords(radius);
                    case"cross":
                        return getCrossMarkerCoords(radius)
                }
            },
            correctValue: function(correction) {
                var that = this;
                if (that.hasValue()) {
                    that.value = that.initialValue + correction;
                    that.minValue = correction;
                    that.translate()
                }
            },
            resetCorrection: function() {
                this.value = this.initialValue;
                this.minValue = CANVAS_POSITION_DEFAULT
            },
            _getTranslates: function(animationEnabled) {
                var 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 width = options.width || DEFAULT_IMAGE_WIDTH,
                    height = options.height || DEFAULT_IMAGE_HEIGHT;
                return renderer.image(-_round(width * 0.5), -_round(height * 0.5), width, height, options.url ? options.url.toString() : options.toString(), "center").attr({
                        translateX: settings.translateX,
                        translateY: settings.translateY,
                        visibility: settings.visibility
                    })
            },
            _createSymbolMarker: function(renderer, pointSettings) {
                var marker,
                    options = this._options;
                switch (options.symbol) {
                    case"circle":
                        delete pointSettings.points;
                        marker = renderer.circle().attr(pointSettings);
                        break;
                    case"square":
                    case"polygon":
                    case"triangle":
                    case"triangleDown":
                    case"triangleUp":
                    case"cross":
                        marker = renderer.path([], "area").attr(pointSettings).sharp();
                        break
                }
                return marker
            },
            _createMarker: function(renderer, group, image, settings, animationEnabled) {
                var that = this,
                    marker = that._checkImage(image) ? that._createImageMarker(renderer, settings, image) : that._createSymbolMarker(renderer, settings, animationEnabled);
                if (marker)
                    marker.data({point: that}).append(group);
                return marker
            },
            _getSymbolBbox: function(x, y, r) {
                return {
                        x: x - r,
                        y: y - r,
                        width: r * 2,
                        height: r * 2
                    }
            },
            _getImageBbox: function(x, y) {
                var image = this._options.image,
                    width = image.width || DEFAULT_IMAGE_WIDTH,
                    height = image.height || DEFAULT_IMAGE_HEIGHT;
                return {
                        x: x - _round(width / 2),
                        y: y - _round(height / 2),
                        width: width,
                        height: height
                    }
            },
            _getGraphicBbox: function() {
                var that = this,
                    options = that._options,
                    x = that.x,
                    y = that.y,
                    bbox;
                if (options.visible)
                    bbox = that._checkImage(options.image) ? that._getImageBbox(x, y) : that._getSymbolBbox(x, y, options.styles.normal.r);
                else
                    bbox = {
                        x: x,
                        y: y,
                        width: 0,
                        height: 0
                    };
                return bbox
            },
            _getVisibleArea: function() {
                var translators = this.translators,
                    visibleX,
                    visibleY;
                if (translators) {
                    visibleX = translators.x.getCanvasVisibleArea();
                    visibleY = translators.y.getCanvasVisibleArea();
                    return {
                            minX: visibleX.min,
                            maxX: visibleX.max,
                            minY: visibleY.min,
                            maxY: visibleY.max
                        }
                }
            },
            _isLabelInsidePoint: $.noop,
            _getShiftLabelCoords: function(label) {
                var coord = this._addLabelAlignmentAndOffset(label, this._getLabelCoords(label));
                return this._checkLabelPosition(label, coord)
            },
            _drawLabel: function(renderer, group) {
                var that = this,
                    customVisibility = that._getCustomLabelVisibility(),
                    coord,
                    label = that._label;
                if ((that.series.getLabelVisibility() || customVisibility !== null) && that.hasValue() && that._showForZeroValues()) {
                    label.draw(renderer, group, customVisibility);
                    if (!that._isLabelInsidePoint(label)) {
                        coord = that._getShiftLabelCoords(label);
                        label.setFigureToDrawConnector(that._getLabelConnector());
                        label.shift(_round(coord.x), _round(coord.y))
                    }
                }
                else
                    label.hide()
            },
            _showForZeroValues: function() {
                return true
            },
            _getLabelConnector: function() {
                var bbox = this._getGraphicBbox(),
                    w2 = bbox.width / 2,
                    h2 = bbox.height / 2;
                return {
                        x: bbox.x + w2,
                        y: bbox.y + h2,
                        r: this._options.visible ? Math.max(w2, h2) : 0
                    }
            },
            _getPositionFromLocation: function() {
                return {
                        x: this.x,
                        y: this.y
                    }
            },
            _isPointInVisibleArea: function(visibleArea, graphicBbox) {
                return visibleArea.minX <= graphicBbox.x + graphicBbox.width && visibleArea.maxX >= graphicBbox.x && visibleArea.minY <= graphicBbox.y + graphicBbox.height && visibleArea.maxY >= graphicBbox.y
            },
            _checkLabelPosition: function(label, coord, pointPosition) {
                var that = this,
                    visibleArea = that._getVisibleArea(),
                    labelBbox = label.getBoundingRect(),
                    graphicBbox = that._getGraphicBbox(pointPosition),
                    offset = LABEL_OFFSET;
                if (that._isPointInVisibleArea(visibleArea, graphicBbox))
                    if (!that._options.rotated) {
                        if (visibleArea.minX > coord.x && that.adjustSeriesLabels)
                            coord.x = visibleArea.minX;
                        if (visibleArea.maxX < coord.x + labelBbox.width && that.adjustSeriesLabels)
                            coord.x = visibleArea.maxX - labelBbox.width;
                        if (visibleArea.minY > coord.y)
                            coord.y = graphicBbox.y + graphicBbox.height + offset;
                        if (visibleArea.maxY < coord.y + labelBbox.height)
                            coord.y = graphicBbox.y - labelBbox.height - offset
                    }
                    else {
                        if (visibleArea.minX > coord.x)
                            coord.x = graphicBbox.x + graphicBbox.width + offset;
                        if (visibleArea.maxX < coord.x + labelBbox.width)
                            coord.x = graphicBbox.x - offset - labelBbox.width;
                        if (visibleArea.minY > coord.y && that.adjustSeriesLabels)
                            coord.y = visibleArea.minY;
                        if (visibleArea.maxY < coord.y + labelBbox.height && that.adjustSeriesLabels)
                            coord.y = visibleArea.maxY - labelBbox.height
                    }
                return coord
            },
            _addLabelAlignmentAndOffset: function(label, coord) {
                var labelBBox = label.getBoundingRect(),
                    labelOptions = label.getLayoutOptions();
                if (!this._options.rotated)
                    if (labelOptions.alignment === "left")
                        coord.x += labelBBox.width / 2;
                    else if (labelOptions.alignment === "right")
                        coord.x -= labelBBox.width / 2;
                coord.x += labelOptions.horizontalOffset;
                coord.y += labelOptions.verticalOffset;
                return coord
            },
            _getLabelCoords: function(label, pointPosition) {
                return this._getLabelCoordOfPosition(label, this._getLabelPosition(pointPosition), pointPosition)
            },
            _getLabelCoordOfPosition: function(label, position, pointPosition) {
                var that = this,
                    labelBBox = label.getBoundingRect(),
                    graphicBbox = that._getGraphicBbox(pointPosition),
                    offset = LABEL_OFFSET,
                    centerY = graphicBbox.height / 2 - labelBBox.height / 2,
                    centerX = graphicBbox.width / 2 - labelBBox.width / 2,
                    x = graphicBbox.x,
                    y = graphicBbox.y;
                switch (position) {
                    case"left":
                        x -= labelBBox.width + offset;
                        y += centerY;
                        break;
                    case"right":
                        x += graphicBbox.width + offset;
                        y += centerY;
                        break;
                    case"top":
                        x += centerX;
                        y -= labelBBox.height + offset;
                        break;
                    case"bottom":
                        x += centerX;
                        y += graphicBbox.height + offset;
                        break;
                    case"inside":
                        x += centerX;
                        y += centerY;
                        break
                }
                return {
                        x: x,
                        y: y
                    }
            },
            _drawMarker: function(renderer, group, animationEnabled) {
                var that = this,
                    options = that._options,
                    translates = that._getTranslates(animationEnabled),
                    style = that._getStyle();
                that.graphic = that._createMarker(renderer, group, options.image, _extend({
                    translateX: translates.x,
                    translateY: translates.y,
                    points: that._populatePointShape(options.symbol, style.r)
                }, style), animationEnabled)
            },
            _getErrorBarSettings: function() {
                return {visibility: "visible"}
            },
            _drawErrorBar: function(renderer, group) {
                var that = this,
                    errorBarOptions = that._options.errorBars || {},
                    points = [],
                    settings,
                    pos = that._errorBarPos,
                    high = that._highErrorCoord,
                    low = that._lowErrorCoord,
                    displayMode = (errorBarOptions.displayMode + "").toLowerCase(),
                    isHighDisplayMode = displayMode === "high",
                    isLowDisplayMode = displayMode === "low",
                    edgeLength = _floor(parseInt(errorBarOptions.edgeLength) / 2),
                    highErrorOnly = (isHighDisplayMode || !_isDefined(low)) && _isDefined(high) && !isLowDisplayMode,
                    lowErrorOnly = (isLowDisplayMode || !_isDefined(high)) && _isDefined(low) && !isHighDisplayMode;
                highErrorOnly && (low = that._baseErrorBarPos);
                lowErrorOnly && (high = that._baseErrorBarPos);
                if (displayMode !== "none" && _isDefined(high) && _isDefined(low) && _isDefined(pos)) {
                    !lowErrorOnly && points.push([pos - edgeLength, high, pos + edgeLength, high]);
                    points.push([pos, high, pos, low]);
                    !highErrorOnly && points.push([pos + edgeLength, low, pos - edgeLength, low]);
                    that._options.rotated && $.each(points, function(_, p) {
                        p.reverse()
                    });
                    settings = that._getErrorBarSettings(errorBarOptions);
                    if (!that._errorBar)
                        that._errorBar = renderer.path(points, "line").attr(settings).append(group);
                    else {
                        settings.points = points;
                        that._errorBar.attr(settings)
                    }
                }
                else
                    that._errorBar && that._errorBar.attr({visibility: "hidden"})
            },
            getTooltipParams: function() {
                var that = this,
                    graphic = that.graphic;
                return {
                        x: that.x,
                        y: that.y,
                        offset: graphic ? graphic.getBBox().height / 2 : 0
                    }
            },
            hasValue: function() {
                return this.value !== null && this.minValue !== null
            },
            setPercentValue: function(total, fullStacked, leftHoleTotal, rightHoleTotal) {
                var that = this,
                    valuePercent = _abs(that.value / total || 0),
                    minValuePercent = _abs(that.minValue / total || 0),
                    percent = valuePercent - minValuePercent;
                that._label.setDataField("percent", percent);
                that._label.setDataField("total", total);
                if (that.series.isFullStackedSeries() && that.hasValue()) {
                    if (that.leftHole) {
                        that.leftHole /= total - leftHoleTotal;
                        that.minLeftHole /= total - leftHoleTotal
                    }
                    if (that.rightHole) {
                        that.rightHole /= total - rightHoleTotal;
                        that.minRightHole /= total - rightHoleTotal
                    }
                    that.value = valuePercent;
                    that.minValue = !minValuePercent ? that.minValue : minValuePercent;
                    that.translate()
                }
            },
            _storeTrackerR: function() {
                var that = this,
                    navigator = window.navigator,
                    r = that._options.styles.normal.r,
                    minTrackerSize;
                navigator = that.__debug_navigator || navigator;
                that.__debug_browserNavigator = navigator;
                minTrackerSize = "ontouchstart" in window || navigator.msPointerEnabled && navigator.msMaxTouchPoints || navigator.pointerEnabled && navigator.maxTouchPoints ? 20 : 6;
                that._options.trackerR = r < minTrackerSize ? minTrackerSize : r;
                return that._options.trackerR
            },
            _translateErrorBars: function(valueTranslator) {
                var that = this,
                    options = that._options,
                    errorBars = options.errorBars || {};
                _isDefined(that.lowError) && (that._lowErrorCoord = valueTranslator.translate(that.lowError));
                _isDefined(that.highError) && (that._highErrorCoord = valueTranslator.translate(that.highError));
                that._errorBarPos = _floor(that._options.rotated ? that.vy : that.vx);
                that._baseErrorBarPos = errorBars.type === "stdDeviation" ? that._lowErrorCoord + (that._highErrorCoord - that._lowErrorCoord) / 2 : that._options.rotated ? that.vx : that.vy
            },
            _translate: function(translators) {
                var that = this,
                    valueAxis = that._options.rotated ? "x" : "y",
                    upperValueAxis = valueAxis.toUpperCase(),
                    valueTranslator = translators[valueAxis],
                    argumentAxis = that._options.rotated ? "y" : "x";
                that["v" + valueAxis] = that[valueAxis] = valueTranslator.translate(that.value);
                that["v" + argumentAxis] = that[argumentAxis] = translators[argumentAxis].translate(that.argument);
                that["min" + upperValueAxis] = valueTranslator.translate(that.minValue);
                that["default" + upperValueAxis] = valueTranslator.translate(CANVAS_POSITION_DEFAULT);
                that._translateErrorBars(valueTranslator);
                that._calculateVisibility(that.x, that.y)
            },
            _updateData: function(data) {
                var that = this;
                that.value = that.initialValue = that.originalValue = data.value;
                that.minValue = that.initialMinValue = that.originalMinValue = _isDefined(data.minValue) ? data.minValue : CANVAS_POSITION_DEFAULT
            },
            _getImageSettings: function(image) {
                return {
                        href: image.url || image.toString(),
                        width: image.width || DEFAULT_IMAGE_WIDTH,
                        height: image.height || DEFAULT_IMAGE_HEIGHT
                    }
            },
            getCrosshairCoords: function() {
                return {
                        x: this.vx,
                        y: this.vy
                    }
            },
            getPointRadius: function() {
                var style = this._currentStyle || this._getStyle(),
                    options = this._options,
                    r = style.r,
                    extraSpace,
                    symbol = options.symbol,
                    isSquare = symbol === "square",
                    isTriangle = symbol === "triangle" || symbol === "triangleDown" || symbol === "triangleUp";
                if (options.visible && !options.image && r) {
                    extraSpace = style["stroke-width"] / 2;
                    return (isSquare || isTriangle ? 1.4 * r : r) + extraSpace
                }
                return 0
            },
            _updateMarker: function(animationEnabled, style) {
                var that = this,
                    options = that._options,
                    settings,
                    image = options.image,
                    visibility = !that.isVisible() ? {visibility: "hidden"} : {};
                style = style || that._getStyle();
                if (that._checkImage(image))
                    settings = _extend({}, {visibility: style.visibility}, visibility, that._getImageSettings(image));
                else
                    settings = _extend({}, style, visibility, {points: that._populatePointShape(options.symbol, style.r)});
                if (!animationEnabled) {
                    settings.translateX = that.x;
                    settings.translateY = that.y
                }
                that.graphic.attr(settings).sharp()
            },
            _getLabelFormatObject: function() {
                var that = this;
                return {
                        argument: that.initialArgument,
                        value: that.initialValue,
                        originalArgument: that.originalArgument,
                        originalValue: that.originalValue,
                        seriesName: that.series.name,
                        lowErrorValue: that.lowError,
                        highErrorValue: that.highError,
                        point: that
                    }
            },
            _getLabelPosition: function() {
                var rotated = this._options.rotated;
                if (this.series.isFullStackedSeries() || this.initialValue > 0)
                    return rotated ? "right" : "top";
                else
                    return rotated ? "left" : "bottom"
            },
            _getFormatObject: function(tooltip) {
                var that = this,
                    labelFormatObject = that._label.getData();
                return _extend({}, labelFormatObject, {
                        argumentText: tooltip.formatValue(that.initialArgument, "argument"),
                        valueText: tooltip.formatValue(that.initialValue)
                    }, _isDefined(labelFormatObject.percent) ? {percentText: tooltip.formatValue(labelFormatObject.percent, "percent")} : {}, _isDefined(labelFormatObject.total) ? {totalText: tooltip.formatValue(labelFormatObject.total)} : {})
            },
            _getMarkerVisibility: function() {
                return this._options.visible
            },
            coordsIn: function(x, y) {
                var trackerRadius = this._storeTrackerR();
                return x >= this.x - trackerRadius && x <= this.x + trackerRadius && y >= this.y - trackerRadius && y <= this.y + trackerRadius
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file barPoint.js */
    (function($, DX) {
        var points = DX.viz.core.series.points.mixins,
            _extend = $.extend,
            _math = Math,
            _floor = _math.floor,
            _abs = _math.abs,
            _min = _math.min,
            CANVAS_POSITION_DEFAULT = "canvas_position_default",
            DEFAULT_BAR_TRACKER_SIZE = 9,
            CORRECTING_BAR_TRACKER_VALUE = 4,
            RIGHT = "right",
            LEFT = "left",
            TOP = "top",
            BOTTOM = "bottom";
        points.barPoint = _extend({}, points.symbolPoint, {
            correctCoordinates: function(correctOptions) {
                var correction = _floor(correctOptions.offset - 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 that = this,
                    bbox = {};
                bbox.x = that.x;
                bbox.y = that.y;
                bbox.width = that.width;
                bbox.height = that.height;
                return bbox
            },
            _getLabelConnector: function() {
                return this._getGraphicBbox()
            },
            _getLabelPosition: function() {
                var that = this,
                    position,
                    translators = that.translators,
                    initialValue = that.initialValue,
                    invertX = translators.x.getBusinessRange().invert,
                    invertY = translators.y.getBusinessRange().invert,
                    isDiscreteValue = that.series.valueAxisType === "discrete",
                    isFullStacked = that.series.isFullStackedSeries(),
                    notVerticalInverted = !isDiscreteValue && (initialValue >= 0 && !invertY || initialValue < 0 && invertY) || isDiscreteValue && !invertY || isFullStacked,
                    notHorizontalInverted = !isDiscreteValue && (initialValue >= 0 && !invertX || initialValue < 0 && invertX) || isDiscreteValue && !invertX || isFullStacked;
                if (!that._options.rotated)
                    position = notVerticalInverted ? TOP : BOTTOM;
                else
                    position = notHorizontalInverted ? RIGHT : LEFT;
                return position
            },
            _getLabelCoords: function(label) {
                var that = this,
                    coords;
                if (that.initialValue === 0 && that.series.isFullStackedSeries())
                    if (!this._options.rotated)
                        coords = that._getLabelCoordOfPosition(label, TOP);
                    else
                        coords = that._getLabelCoordOfPosition(label, RIGHT);
                else if (label.getLayoutOptions().position === "inside")
                    coords = that._getLabelCoordOfPosition(label, "inside");
                else
                    coords = points.symbolPoint._getLabelCoords.call(this, label);
                return coords
            },
            _checkLabelPosition: function(label, coord) {
                var that = this,
                    visibleArea = that._getVisibleArea(),
                    rotated = that._options.rotated,
                    graphicBbox = that._getGraphicBbox(),
                    labelBbox = label.getBoundingRect();
                if (that._isPointInVisibleArea(visibleArea, graphicBbox))
                    return that._moveLabelOnCanvas(coord, visibleArea, labelBbox, that.adjustSeriesLabels || rotated, that.adjustSeriesLabels || !rotated);
                return coord
            },
            _isLabelInsidePoint: function(label) {
                var that = this,
                    graphicBbox = that._getGraphicBbox(),
                    labelBbox = label.getBoundingRect();
                if (that._options.resolveLabelsOverlapping && label.getLayoutOptions().position === "inside")
                    if (labelBbox.width > graphicBbox.width || labelBbox.height > graphicBbox.height) {
                        label.hide();
                        return true
                    }
                return false
            },
            _moveLabelOnCanvas: function(coord, visibleArea, labelBbox, horizontalAdjust, verticalAdjust) {
                var x = coord.x,
                    y = coord.y;
                if (visibleArea.minX > x && horizontalAdjust)
                    x = visibleArea.minX;
                if (visibleArea.maxX < x + labelBbox.width && horizontalAdjust)
                    x = visibleArea.maxX - labelBbox.width;
                if (visibleArea.minY > y && verticalAdjust)
                    y = visibleArea.minY;
                if (visibleArea.maxY < y + labelBbox.height && verticalAdjust)
                    y = visibleArea.maxY - labelBbox.height;
                return {
                        x: x,
                        y: y
                    }
            },
            _showForZeroValues: function() {
                return this._options.label.showForZeroValues || this.initialValue
            },
            _drawMarker: function(renderer, group, animationEnabled) {
                var that = this,
                    style = that._getStyle(),
                    x = that.x,
                    y = that.y,
                    width = that.width,
                    height = that.height,
                    r = that._options.cornerRadius;
                if (animationEnabled)
                    if (that._options.rotated) {
                        width = 0;
                        x = that.defaultX
                    }
                    else {
                        height = 0;
                        y = that.defaultY
                    }
                that.graphic = renderer.rect(x, y, width, height).attr({
                    rx: r,
                    ry: r
                }).attr(style).data({point: that}).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
                    }
            },
            getGraphicSettings: function() {
                var graphic = this.graphic;
                return {
                        x: graphic.attr("x"),
                        y: graphic.attr("y"),
                        height: graphic.attr("height"),
                        width: graphic.attr("width")
                    }
            },
            _getEdgeTooltipParams: function(x, y, width, height) {
                var isPositive = this.value >= 0,
                    invertedY = this.translators.y.getBusinessRange().invert,
                    invertedX = this.translators.x.getBusinessRange().invert,
                    xCoord,
                    yCoord;
                if (this._options.rotated) {
                    yCoord = y + height / 2;
                    if (invertedX)
                        xCoord = isPositive ? x : x + width;
                    else
                        xCoord = isPositive ? x + width : x
                }
                else {
                    xCoord = x + width / 2;
                    if (invertedY)
                        yCoord = isPositive ? y + height : y;
                    else
                        yCoord = isPositive ? y : y + height
                }
                return {
                        x: xCoord,
                        y: yCoord,
                        offset: 0
                    }
            },
            getTooltipParams: function(location) {
                var x = this.x,
                    y = this.y,
                    width = this.width,
                    height = this.height;
                return location === 'edge' ? this._getEdgeTooltipParams(x, y, width, height) : {
                        x: x + width / 2,
                        y: y + height / 2,
                        offset: 0
                    }
            },
            _truncateCoord: function(coord, minBounce, maxBounce) {
                if (coord < minBounce)
                    return minBounce;
                if (coord > maxBounce)
                    return maxBounce;
                return coord
            },
            _translateErrorBars: function(valueTranslator, argVisibleArea) {
                points.symbolPoint._translateErrorBars.call(this, valueTranslator);
                if (this._errorBarPos < argVisibleArea.min || this._errorBarPos > argVisibleArea.max)
                    this._errorBarPos = undefined
            },
            _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["v" + valAxis] = val;
                that["v" + argAxis] = arg + that[argIntervalName] / 2;
                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);
                that._translateErrorBars(valTranslator, argVisibleArea);
                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) {
                this.graphic.attr(_extend({}, style || this._getStyle(), !animationEnabled ? this.getMarkerCoords() : {}))
            },
            getMarkerCoords: function() {
                return {
                        x: this.x,
                        y: this.y,
                        width: this.width,
                        height: this.height
                    }
            },
            coordsIn: function(x, y) {
                var that = this;
                return x >= that.x && x <= that.x + that.width && y >= that.y && y <= that.y + that.height
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file bubblePoint.js */
    (function($, DX) {
        var points = DX.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 that = this,
                    attr = _extend({
                        translateX: that.x,
                        translateY: that.y
                    }, that._getStyle());
                that.graphic = renderer.circle(0, 0, animationEnabled ? 0 : that.bubbleSize).attr(attr).data({point: that}).append(group)
            },
            getTooltipParams: function(location) {
                var that = this,
                    graphic = that.graphic,
                    height;
                if (!graphic)
                    return;
                height = graphic.getBBox().height;
                return {
                        x: that.x,
                        y: height < MIN_BUBBLE_HEIGHT || location === 'edge' ? this.y - height / 2 : this.y,
                        offset: 0
                    }
            },
            _getLabelFormatObject: function() {
                var formatObject = points.symbolPoint._getLabelFormatObject.call(this);
                formatObject.size = this.initialSize;
                return formatObject
            },
            _updateData: function(data) {
                points.symbolPoint._updateData.call(this, data);
                this.size = this.initialSize = data.size
            },
            _getGraphicBbox: function() {
                var that = this;
                return that._getSymbolBbox(that.x, that.y, that.bubbleSize)
            },
            _updateMarker: function(animationEnabled, style) {
                var that = this;
                style = style || that._getStyle();
                if (!animationEnabled)
                    style = $.extend({
                        r: that.bubbleSize,
                        translateX: that.x,
                        translateY: that.y
                    }, style);
                that.graphic.attr(style)
            },
            _getFormatObject: function(tooltip) {
                var formatObject = points.symbolPoint._getFormatObject.call(this, tooltip);
                formatObject.sizeText = tooltip.formatValue(this.initialSize);
                return formatObject
            },
            _storeTrackerR: function() {
                return this.bubbleSize
            },
            _getLabelCoords: function(label) {
                var coords;
                if (label.getLayoutOptions().position === "inside")
                    coords = this._getLabelCoordOfPosition(label, "inside");
                else
                    coords = points.symbolPoint._getLabelCoords.call(this, label);
                return coords
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file piePoint.js */
    (function($, DX) {
        var CONNECTOR_LENGTH = 20,
            series = DX.viz.core.series,
            points = series.points.mixins,
            _extend = $.extend,
            _round = Math.round,
            _sqrt = Math.sqrt,
            _acos = Math.acos,
            DEG = 180 / Math.PI,
            _abs = Math.abs,
            _normalizeAngle = DX.utils.normalizeAngle,
            _getCosAndSin = DX.utils.getCosAndSin,
            _isDefined = DX.utils.isDefined,
            INDENT_FROM_PIE = series.helpers.consts.pieLabelIndent;
        function getVerticallyShiftedAngularCoords(bbox, dy, center) {
            var isPositive = bbox.x + bbox.width / 2 >= center.x,
                dx1 = (isPositive ? bbox.x : bbox.x + bbox.width) - center.x,
                dy1 = bbox.y - center.y,
                dy2 = dy1 + dy,
                dx2 = _round(_sqrt(dx1 * dx1 + dy1 * dy1 - dy2 * dy2)),
                dx = (isPositive ? +dx2 : -dx2) || dx1;
            return {
                    x: center.x + (isPositive ? dx : dx - bbox.width),
                    y: bbox.y + dy
                }
        }
        DX.viz.core.utils.getVerticallyShiftedAngularCoords = getVerticallyShiftedAngularCoords;
        points.piePoint = _extend({}, points.symbolPoint, {
            _updateData: function(data) {
                var that = this;
                points.symbolPoint._updateData.call(this, data);
                that._visible = true;
                that.minValue = that.initialMinValue = that.originalMinValue = _isDefined(data.minValue) ? data.minValue : 0
            },
            animate: function(complete, duration, step) {
                var that = this;
                that.graphic.animate({
                    x: that.centerX,
                    y: that.centerY,
                    outerRadius: that.radiusOuter,
                    innerRadius: that.radiusInner,
                    startAngle: that.toAngle,
                    endAngle: that.fromAngle
                }, {
                    partitionDuration: duration,
                    step: step
                }, complete)
            },
            correctPosition: function(correction) {
                var that = this;
                that.radiusInner = correction.radiusInner;
                that.radiusOuter = correction.radiusOuter;
                that.centerX = correction.centerX;
                that.centerY = correction.centerY
            },
            correctValue: function(correction, percent, base) {
                var that = this;
                that.value = (base || that.initialValue) + correction;
                that.minValue = correction;
                that.percent = percent;
                that._label.setDataField("percent", percent)
            },
            _updateLabelData: function() {
                this._label.setData(this._getLabelFormatObject())
            },
            _updateLabelOptions: function() {
                var that = this;
                !that._label && that._createLabel();
                that._label.setOptions(that._options.label)
            },
            _getShiftLabelCoords: function() {
                var that = this,
                    bbox = that._label.getBoundingRect(),
                    coord = that._getLabelCoords(that._label),
                    visibleArea = that._getVisibleArea();
                if (that._isLabelDrawingWithoutPoints)
                    return that._checkLabelPosition(coord, bbox, visibleArea);
                else
                    return that._getLabelExtraCoord(coord, that._checkVerticalLabelPosition(coord, bbox, visibleArea), bbox)
            },
            _getLabelPosition: function(options) {
                return options.position
            },
            _getLabelCoords: function(label) {
                var that = this,
                    bbox = label.getBoundingRect(),
                    options = label.getLayoutOptions(),
                    angleFunctions = _getCosAndSin(that.middleAngle),
                    position = that._getLabelPosition(options),
                    radiusInner = that.radiusInner,
                    radiusOuter = that.radiusOuter,
                    rad,
                    x;
                if (position === 'inside') {
                    rad = radiusInner + (radiusOuter - radiusInner) / 2 + options.radialOffset;
                    x = that.centerX + rad * angleFunctions.cos - bbox.width / 2
                }
                else {
                    rad = radiusOuter + options.radialOffset + INDENT_FROM_PIE;
                    if (angleFunctions.cos > 0.1)
                        x = that.centerX + rad * angleFunctions.cos;
                    else if (angleFunctions.cos < -0.1)
                        x = that.centerX + rad * angleFunctions.cos - bbox.width;
                    else
                        x = that.centerX + rad * angleFunctions.cos - bbox.width / 2
                }
                return {
                        x: x,
                        y: _round(that.centerY - rad * angleFunctions.sin - bbox.height / 2)
                    }
            },
            _getColumnsCoord: function(coord) {
                var that = this,
                    label = that._label,
                    bbox = label.getBoundingRect(),
                    options = label.getLayoutOptions(),
                    rad = that.radiusOuter + options.radialOffset,
                    canvas = that.series.canvas,
                    rightBorderX = canvas.width - canvas.right - bbox.width,
                    leftBorderX = canvas.left,
                    angleOfPoint = _normalizeAngle(that.middleAngle),
                    x;
                if (options.position !== 'columns')
                    return coord;
                rad += CONNECTOR_LENGTH;
                if (angleOfPoint < 90 || angleOfPoint >= 270) {
                    x = that._maxLabelLength ? that.centerX + rad + that._maxLabelLength - bbox.width : rightBorderX;
                    x = x > rightBorderX ? rightBorderX : x
                }
                else {
                    x = that._maxLabelLength ? that.centerX - rad - that._maxLabelLength : leftBorderX;
                    x = x < leftBorderX ? leftBorderX : x
                }
                coord.x = x;
                return coord
            },
            drawLabel: function(translators, renderer, group) {
                this.translate(translators);
                this._isLabelDrawingWithoutPoints = true;
                this._drawLabel(renderer, group);
                this._isLabelDrawingWithoutPoints = false
            },
            updateLabelCoord: function() {
                var that = this,
                    bbox = that._label.getBoundingRect(),
                    coord = that._getColumnsCoord(bbox);
                coord = that._checkHorizontalLabelPosition(coord, bbox, that._getVisibleArea());
                that._label.shift(_round(coord.x), _round(bbox.y))
            },
            _checkVerticalLabelPosition: function(coord, box, visibleArea) {
                var x = coord.x,
                    y = coord.y;
                if (coord.y + box.height > visibleArea.maxY)
                    y = visibleArea.maxY - box.height;
                else if (coord.y < visibleArea.minY)
                    y = visibleArea.minY;
                return {
                        x: x,
                        y: y
                    }
            },
            _getLabelExtraCoord: function(coord, shiftCoord, box) {
                return coord.y !== shiftCoord.y ? getVerticallyShiftedAngularCoords({
                        x: coord.x,
                        y: coord.y,
                        width: box.width,
                        height: box.height
                    }, shiftCoord.y - coord.y, {
                        x: this.centerX,
                        y: this.centerY
                    }) : coord
            },
            _checkHorizontalLabelPosition: function(coord, box, visibleArea) {
                var x = coord.x,
                    y = coord.y;
                if (coord.x + box.width > visibleArea.maxX)
                    x = visibleArea.maxX - box.width;
                else if (coord.x < visibleArea.minX)
                    x = visibleArea.minX;
                return {
                        x: x,
                        y: y
                    }
            },
            setLabelEllipsis: function() {
                var that = this,
                    bbox = that._label.getBoundingRect(),
                    coord = that._checkHorizontalLabelPosition(bbox, bbox, that._getVisibleArea());
                that._label.fit({
                    width: bbox.width - _abs(coord.x - bbox.x),
                    height: bbox.height - _abs(coord.y - bbox.y)
                })
            },
            _getVisibleArea: function() {
                var canvas = this.series.canvas;
                return {
                        minX: canvas.left,
                        maxX: canvas.width - canvas.right,
                        minY: canvas.top,
                        maxY: canvas.height - canvas.bottom
                    }
            },
            _checkLabelPosition: function(coord, bbox, visibleArea) {
                coord = this._checkHorizontalLabelPosition(coord, bbox, visibleArea);
                return this._checkVerticalLabelPosition(coord, bbox, visibleArea)
            },
            getBoundaryCoords: function() {
                var that = this,
                    rad = that.radiusOuter,
                    seriesStyle = that._options.styles.normal,
                    strokeWidthBy2 = seriesStyle["stroke-width"] / 2,
                    borderWidth = that.series.getOptions().containerBackgroundColor === seriesStyle.stroke ? _round(strokeWidthBy2) : _round(-strokeWidthBy2),
                    angleFunctions = _getCosAndSin(_round(that.middleAngle));
                return {
                        x: _round(that.centerX + (rad - borderWidth) * angleFunctions.cos),
                        y: _round(that.centerY - (rad - borderWidth) * angleFunctions.sin)
                    }
            },
            _getLabelConnector: function() {
                var coords = this.getBoundaryCoords();
                coords.angle = this.middleAngle;
                return coords
            },
            _drawMarker: function(renderer, group, animationEnabled, firstDrawing) {
                var that = this,
                    radiusOuter = that.radiusOuter,
                    radiusInner = that.radiusInner,
                    fromAngle = that.fromAngle,
                    toAngle = that.toAngle;
                if (animationEnabled) {
                    radiusInner = radiusOuter = 0;
                    if (!firstDrawing)
                        fromAngle = toAngle = that.shiftedAngle
                }
                that.graphic = renderer.arc(that.centerX, that.centerY, radiusInner, radiusOuter, toAngle, fromAngle).attr({"stroke-linejoin": "round"}).attr(that._getStyle()).data({point: that}).sharp().append(group)
            },
            getTooltipParams: function() {
                var that = this,
                    angleFunctions = _getCosAndSin(that.middleAngle),
                    radiusInner = that.radiusInner,
                    radiusOuter = that.radiusOuter;
                return {
                        x: that.centerX + (radiusInner + (radiusOuter - radiusInner) / 2) * angleFunctions.cos,
                        y: that.centerY - (radiusInner + (radiusOuter - radiusInner) / 2) * angleFunctions.sin,
                        offset: 0
                    }
            },
            _translate: function(translator) {
                var that = this,
                    angle = that.shiftedAngle || 0,
                    value = that.value,
                    minValue = that.minValue;
                that.fromAngle = translator.translate(minValue) + angle;
                that.toAngle = translator.translate(value) + angle;
                that.middleAngle = translator.translate((value - minValue) / 2 + minValue) + angle;
                if (!that.isVisible())
                    that.middleAngle = that.toAngle = that.fromAngle = that.fromAngle || angle
            },
            _getMarkerVisibility: function() {
                return true
            },
            _updateMarker: function(animationEnabled, style) {
                var that = this;
                style = style || that._getStyle();
                if (!animationEnabled)
                    style = _extend({
                        x: that.centerX,
                        y: that.centerY,
                        outerRadius: that.radiusOuter,
                        innerRadius: that.radiusInner,
                        startAngle: that.toAngle,
                        endAngle: that.fromAngle
                    }, style);
                that.graphic.attr(style).sharp()
            },
            getLegendStyles: function() {
                return this._styles.legendStyles
            },
            isInVisibleArea: function() {
                return true
            },
            hide: function() {
                var that = this;
                if (that._visible) {
                    that._visible = false;
                    that.hideTooltip();
                    that._options.visibilityChanged(that)
                }
            },
            show: function() {
                var that = this;
                if (!that._visible) {
                    that._visible = true;
                    that._options.visibilityChanged(that)
                }
            },
            setInvisibility: function() {
                this._label.hide()
            },
            isVisible: function() {
                return this._visible
            },
            _getFormatObject: function(tooltip) {
                var formatObject = points.symbolPoint._getFormatObject.call(this, tooltip),
                    percent = this.percent;
                formatObject.percent = percent;
                formatObject.percentText = tooltip.formatValue(percent, "percent");
                return formatObject
            },
            getColor: function() {
                return this._styles.normal.fill
            },
            coordsIn: function(x, y) {
                var that = this,
                    lx = x - that.centerX,
                    ly = y - that.centerY,
                    r = _sqrt(lx * lx + ly * ly),
                    fromAngle = that.fromAngle % 360,
                    toAngle = that.toAngle % 360,
                    angle;
                if (r < that.radiusInner || r > that.radiusOuter || r === 0)
                    return false;
                angle = _acos(lx / r) * DEG * (ly > 0 ? -1 : 1);
                if (angle < 0)
                    angle += 360;
                if (fromAngle === toAngle && _abs(that.toAngle - that.fromAngle) > 1E-4)
                    return true;
                else
                    return fromAngle >= toAngle ? angle <= fromAngle && angle >= toAngle : !(angle >= fromAngle && angle <= toAngle)
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file rangeSymbolPoint.js */
    (function($, DX) {
        var core = DX.viz.core,
            points = 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() {
                var that = this;
                that._topLabel.dispose();
                that._topLabel = null;
                that._bottomLabel.dispose();
                that._bottomLabel = null
            },
            hideMarker: function(type) {
                var graphic = this.graphic,
                    marker = graphic && graphic[type + "Marker"],
                    label = this["_" + type + "Label"];
                if (marker && marker.attr("visibility") !== "hidden")
                    marker.attr({visibility: "hidden"});
                label.hide()
            },
            setInvisibility: function() {
                this.hideMarker("top");
                this.hideMarker("bottom")
            },
            clearVisibility: function() {
                var that = this,
                    graphic = that.graphic,
                    topMarker = graphic && graphic.topMarker,
                    bottomMarker = graphic && graphic.bottomMarker;
                if (topMarker && topMarker.attr("visibility"))
                    topMarker.attr({visibility: null});
                if (bottomMarker && bottomMarker.attr("visibility"))
                    bottomMarker.attr({visibility: null});
                that._topLabel.clearVisibility();
                that._bottomLabel.clearVisibility()
            },
            clearMarker: function() {
                var that = this,
                    graphic = that.graphic,
                    topMarker = graphic && graphic.topMarker,
                    bottomMarker = graphic && graphic.bottomMarker,
                    emptySettings = that._emptySettings;
                topMarker && topMarker.attr(emptySettings);
                bottomMarker && bottomMarker.attr(emptySettings)
            },
            _getLabelPosition: function(markerType) {
                var position,
                    labelsInside = this._options.label.position === "inside";
                if (!this._options.rotated)
                    position = markerType === "top" ^ labelsInside ? "top" : "bottom";
                else
                    position = markerType === "top" ^ labelsInside ? "right" : "left";
                return position
            },
            _getLabelMinFormatObject: function() {
                var that = this;
                return {
                        index: 0,
                        argument: that.initialArgument,
                        value: that.initialMinValue,
                        seriesName: that.series.name,
                        originalValue: that.originalMinValue,
                        originalArgument: that.originalArgument,
                        point: that
                    }
            },
            _updateLabelData: function() {
                var maxFormatObject = this._getLabelFormatObject();
                maxFormatObject.index = 1;
                this._topLabel.setData(maxFormatObject);
                this._bottomLabel.setData(this._getLabelMinFormatObject())
            },
            _updateLabelOptions: function() {
                var that = this,
                    options = this._options.label;
                (!that._topLabel || !that._bottomLabel) && that._createLabel();
                that._topLabel.setOptions(options);
                that._bottomLabel.setOptions(options)
            },
            _createLabel: function() {
                this._topLabel = core.CoreFactory.createLabel();
                this._bottomLabel = core.CoreFactory.createLabel()
            },
            _getGraphicBbox: function(location) {
                location = location || this._labelLocation;
                var options = this._options,
                    images = this._getImage(options.image),
                    image = location === "top" ? this._checkImage(images.top) : this._checkImage(images.bottom),
                    bbox,
                    coord = this._getPositionFromLocation(location);
                if (options.visible)
                    bbox = image ? this._getImageBbox(coord.x, coord.y) : this._getSymbolBbox(coord.x, coord.y, options.styles.normal.r);
                else
                    bbox = {
                        x: coord.x,
                        y: coord.y,
                        width: 0,
                        height: 0
                    };
                return bbox
            },
            _getPositionFromLocation: function(location) {
                var x,
                    y,
                    isTop = location === "top";
                if (!this._options.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
                }
                return {
                        x: x,
                        y: y
                    }
            },
            _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.getBoundingRect(),
                    bottomCoords = that._bottomLabel.getBoundingRect(),
                    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.shift(topCoords.x, corrections.coord1);
                            that._bottomLabel.shift(bottomCoords.x, corrections.coord2)
                        }
                    }
                    else if (this._checkOverlay(topCoords.y, bottomCoords.y, bottomCoords.height)) {
                        corrections = this._getOverlayCorrections("vertical", bottomCoords, topCoords);
                        that._topLabel.shift(topCoords.x, corrections.coord2);
                        that._bottomLabel.shift(bottomCoords.x, corrections.coord1)
                    }
                }
                else if (topLocation === "top") {
                    if (this._checkOverlay(topCoords.x, bottomCoords.x, bottomCoords.width)) {
                        corrections = this._getOverlayCorrections("horizontal", bottomCoords, topCoords);
                        that._topLabel.shift(corrections.coord2, topCoords.y);
                        that._bottomLabel.shift(corrections.coord1, bottomCoords.y)
                    }
                }
                else if (this._checkOverlay(bottomCoords.x, topCoords.x, topCoords.width)) {
                    corrections = this._getOverlayCorrections("horizontal", topCoords, bottomCoords);
                    that._topLabel.shift(corrections.coord1, topCoords.y);
                    that._bottomLabel.shift(corrections.coord2, bottomCoords.y)
                }
            },
            _drawLabel: function(renderer, group) {
                var that = this,
                    coord,
                    labels = [],
                    notInverted = that._options.rotated ? that.x >= that.minX : that.y < that.minY,
                    customVisibility = that._getCustomLabelVisibility();
                that._topLabel.pointPosition = notInverted ? "top" : "bottom";
                that._bottomLabel.pointPosition = notInverted ? "bottom" : "top";
                if ((that.series.getLabelVisibility() || customVisibility !== null) && that.hasValue()) {
                    that.visibleTopMarker !== false && labels.push(that._topLabel);
                    that.visibleBottomMarker !== false && labels.push(that._bottomLabel);
                    $.each(labels, function(_, label) {
                        var pointPosition = label.pointPosition;
                        label.draw(renderer, group, customVisibility);
                        coord = that._addLabelAlignmentAndOffset(label, that._getLabelCoords(label, pointPosition));
                        coord = that._checkLabelPosition(label, coord, pointPosition);
                        that._labelLocation = label.pointPosition;
                        label.setFigureToDrawConnector(that._getLabelConnector());
                        that._labelLocation = null;
                        label.shift(_round(coord.x), _round(coord.y))
                    });
                    that._checkLabelsOverlay(that._topLabel.pointPosition)
                }
                else {
                    that._topLabel.hide();
                    that._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 that = this,
                    oldSymbol = oldOptions.symbol,
                    newSymbol = newOptions.symbol,
                    symbolChanged = oldSymbol === "circle" && newSymbol !== "circle" || oldSymbol !== "circle" && newSymbol === "circle",
                    oldImages = that._getImage(oldOptions.image),
                    newImages = that._getImage(newOptions.image),
                    topImageChanged = that._checkImage(oldImages.top) !== that._checkImage(newImages.top),
                    bottomImageChanged = that._checkImage(oldImages.bottom) !== that._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 = _extend({
                    translateX: x + that.width,
                    translateY: y,
                    r: radius
                }, style);
                settings.bottom = _extend({
                    translateX: x,
                    translateY: y + that.height,
                    r: radius
                }, style);
                if (points)
                    settings.top.points = settings.bottom.points = points;
                return settings
            },
            _hasGraphic: function() {
                return this.graphic && this.graphic.topMarker && this.graphic.bottomMarker
            },
            _drawOneMarker: function(renderer, markerType, imageSettings, settings) {
                var that = this,
                    graphic = that.graphic;
                if (graphic[markerType])
                    that._updateOneMarker(markerType, settings);
                else
                    graphic[markerType] = that._createMarker(renderer, graphic, imageSettings, settings)
            },
            _drawMarker: function(renderer, group, animationEnabled, firstDrawing, style) {
                var that = this,
                    settings = that._getSettingsForTwoMarkers(style || that._getStyle()),
                    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.g().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,
                    rotated = that._options.rotated;
                return {
                        translateX: rotated ? _min(that.x, that.minX) - radius : that.x - radius,
                        translateY: rotated ? that.y - radius : _min(that.y, that.minY) - radius,
                        width: that.width + 2 * radius,
                        height: that.height + 2 * radius
                    }
            },
            isInVisibleArea: function() {
                var that = this,
                    rotated = that._options.rotated,
                    argument = !rotated ? that.x : that.y,
                    maxValue = !rotated ? _max(that.minY, that.y) : _max(that.minX, that.x),
                    minValue = !rotated ? _min(that.minY, that.y) : _min(that.minX, that.x),
                    translators = that.translators,
                    notVisibleByArg,
                    notVisibleByVal,
                    tmp,
                    visibleTopMarker = true,
                    visibleBottomMarker = true,
                    visibleRangeArea = true,
                    visibleArgArea,
                    visibleValArea;
                if (translators) {
                    visibleArgArea = translators[!rotated ? "x" : "y"].getCanvasVisibleArea();
                    visibleValArea = translators[!rotated ? "y" : "x"].getCanvasVisibleArea();
                    notVisibleByArg = visibleArgArea.max < argument || visibleArgArea.min > argument;
                    notVisibleByVal = visibleValArea.min > minValue && visibleValArea.min > maxValue || visibleValArea.max < minValue && visibleValArea.max < maxValue;
                    if (notVisibleByArg || notVisibleByVal)
                        visibleTopMarker = visibleBottomMarker = visibleRangeArea = false;
                    else {
                        visibleTopMarker = visibleValArea.min <= minValue && visibleValArea.max > minValue;
                        visibleBottomMarker = visibleValArea.min < maxValue && visibleValArea.max >= maxValue;
                        if (rotated) {
                            tmp = visibleTopMarker;
                            visibleTopMarker = visibleBottomMarker;
                            visibleBottomMarker = tmp
                        }
                    }
                }
                that.visibleTopMarker = visibleTopMarker;
                that.visibleBottomMarker = visibleBottomMarker;
                return visibleRangeArea
            },
            getTooltipParams: function() {
                var that = this,
                    x,
                    y,
                    min,
                    max,
                    minValue,
                    translators = that.translators,
                    visibleAreaX = translators.x.getCanvasVisibleArea(),
                    visibleAreaY = 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 that = this,
                    rotated = that._options.rotated;
                that.minX = that.minY = translators.y.translate(that.minValue);
                points.symbolPoint._translate.call(that, translators);
                that.height = rotated ? 0 : _abs(that.minY - that.y);
                that.width = rotated ? _abs(that.x - that.minX) : 0
            },
            _updateData: function(data) {
                var that = this;
                points.symbolPoint._updateData.call(that, data);
                that.minValue = that.initialMinValue = that.originalMinValue = data.minValue
            },
            _getImageSettings: function(settings, image) {
                return {
                        href: image.url || image.toString(),
                        width: image.width || DEFAULT_IMAGE_WIDTH,
                        height: image.height || DEFAULT_IMAGE_HEIGHT,
                        translateX: settings.translateX,
                        translateY: settings.translateY
                    }
            },
            getCrosshairCoords: function(x, y) {
                var coords;
                if (this._options.rotated)
                    coords = {
                        y: this.vy,
                        x: Math.abs(this.vx - x) < Math.abs(this.minX - x) ? this.vx : this.minX
                    };
                else
                    coords = {
                        x: this.vx,
                        y: Math.abs(this.vy - y) < Math.abs(this.minY - y) ? this.vy : this.minY
                    };
                return coords
            },
            _updateOneMarker: function(markerType, settings) {
                this.graphic && this.graphic[markerType] && this.graphic[markerType].attr(settings)
            },
            _updateMarker: function(animationEnabled, style) {
                this._drawMarker(undefined, undefined, false, false, style)
            },
            _getFormatObject: function(tooltip) {
                var that = this,
                    initialMinValue = that.initialMinValue,
                    initialValue = that.initialValue,
                    initialArgument = that.initialArgument,
                    minValue = tooltip.formatValue(initialMinValue),
                    value = tooltip.formatValue(initialValue);
                return {
                        argument: initialArgument,
                        argumentText: tooltip.formatValue(initialArgument, "argument"),
                        valueText: minValue + " - " + value,
                        rangeValue1Text: minValue,
                        rangeValue2Text: value,
                        rangeValue1: initialMinValue,
                        rangeValue2: initialValue,
                        seriesName: that.series.name,
                        point: that,
                        originalMinValue: that.originalMinValue,
                        originalValue: that.originalValue,
                        originalArgument: that.originalArgument
                    }
            },
            getLabel: function() {
                return [this._topLabel, this._bottomLabel]
            },
            getBoundingRect: $.noop,
            coordsIn: function(x, y) {
                var trackerRadius = this._storeTrackerR(),
                    xCond = x >= this.x - trackerRadius && x <= this.x + trackerRadius,
                    yCond = y >= this.y - trackerRadius && y <= this.y + trackerRadius;
                if (this._options.rotated)
                    return yCond && (xCond || x >= this.minX - trackerRadius && x <= this.minX + trackerRadius);
                else
                    return xCond && (yCond || y >= this.minY - trackerRadius && y <= this.minY + trackerRadius)
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file rangeBarPoint.js */
    (function($, DX) {
        var points = DX.viz.core.series.points.mixins,
            rangeSymbolPointMethods = points.rangeSymbolPoint,
            _extend = $.extend;
        points.rangeBarPoint = _extend({}, points.barPoint, {
            deleteLabel: rangeSymbolPointMethods.deleteLabel,
            _getFormatObject: rangeSymbolPointMethods._getFormatObject,
            clearVisibility: function() {
                var graphic = this.graphic;
                if (graphic && graphic.attr("visibility"))
                    graphic.attr({visibility: null});
                this._topLabel.clearVisibility();
                this._bottomLabel.clearVisibility()
            },
            setInvisibility: function() {
                var graphic = this.graphic;
                if (graphic && graphic.attr("visibility") !== "hidden")
                    graphic.attr({visibility: "hidden"});
                this._topLabel.hide();
                this._bottomLabel.hide()
            },
            getTooltipParams: function(location) {
                var edgeLocation = location === 'edge',
                    x,
                    y;
                if (this._options.rotated) {
                    x = edgeLocation ? this.x + this.width : this.x + this.width / 2;
                    y = this.y + this.height / 2
                }
                else {
                    x = this.x + this.width / 2;
                    y = edgeLocation ? this.y : this.y + this.height / 2
                }
                return {
                        x: x,
                        y: y,
                        offset: 0
                    }
            },
            _translate: function(translator) {
                var that = this,
                    barMethods = points.barPoint;
                barMethods._translate.call(that, translator);
                if (that._options.rotated)
                    that.width = that.width || 1;
                else
                    that.height = that.height || 1
            },
            _updateData: rangeSymbolPointMethods._updateData,
            _getLabelPosition: rangeSymbolPointMethods._getLabelPosition,
            _getLabelMinFormatObject: rangeSymbolPointMethods._getLabelMinFormatObject,
            _updateLabelData: rangeSymbolPointMethods._updateLabelData,
            _updateLabelOptions: rangeSymbolPointMethods._updateLabelOptions,
            getCrosshairCoords: rangeSymbolPointMethods.getCrosshairCoords,
            _createLabel: rangeSymbolPointMethods._createLabel,
            _checkOverlay: rangeSymbolPointMethods._checkOverlay,
            _checkLabelsOverlay: rangeSymbolPointMethods._checkLabelsOverlay,
            _getOverlayCorrections: rangeSymbolPointMethods._getOverlayCorrections,
            _drawLabel: rangeSymbolPointMethods._drawLabel,
            _getLabelCoords: rangeSymbolPointMethods._getLabelCoords,
            _getGraphicBbox: function(location) {
                location = location || this._labelLocation;
                var isTop = location === "top",
                    bbox = points.barPoint._getGraphicBbox.call(this);
                if (!this._options.rotated) {
                    bbox.y = isTop ? bbox.y : bbox.y + bbox.height;
                    bbox.height = 0
                }
                else {
                    bbox.x = isTop ? bbox.x + bbox.width : bbox.x;
                    bbox.width = 0
                }
                return bbox
            },
            getLabel: rangeSymbolPointMethods.getLabel,
            getBoundingRect: $.noop
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file candlestickPoint.js */
    (function($, DX) {
        var viz = DX.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 [y, x]
                    } : function(x, y) {
                        return [x, y]
                    },
                    width = that.width,
                    min = that[minValueName],
                    max = that[maxValueName],
                    points;
                if (min === max)
                    points = [].concat(createPoint(x, that.highY)).concat(createPoint(x, that.lowY)).concat(createPoint(x, that.closeY)).concat(createPoint(x - width / 2, that.closeY)).concat(createPoint(x + width / 2, that.closeY)).concat(createPoint(x, that.closeY));
                else
                    points = [].concat(createPoint(x, that.highY)).concat(createPoint(x, max)).concat(createPoint(x + width / 2, max)).concat(createPoint(x + width / 2, min)).concat(createPoint(x, min)).concat(createPoint(x, that.lowY)).concat(createPoint(x, min)).concat(createPoint(x - width / 2, min)).concat(createPoint(x - width / 2, max)).concat(createPoint(x, max));
                return points
            },
            _getCategoryPoints: function(y) {
                var that = this,
                    x = that.x,
                    createPoint = that._options.rotated ? function(x, y) {
                        return [y, x]
                    } : function(x, y) {
                        return [x, y]
                    };
                return [].concat(createPoint(x, that.highY)).concat(createPoint(x, that.lowY)).concat(createPoint(x, y)).concat(createPoint(x - that.width / 2, y)).concat(createPoint(x + that.width / 2, y)).concat(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 = [that.x, that.highY, that.x, that.lowY];
                else
                    points = that._getCategoryPoints(_isNumeric(openValue) ? that.openY : that.closeY);
                return points
            },
            getColor: function() {
                var that = this;
                return that._isReduction ? that._options.reduction.color : that._styles.normal.stroke || that.series.getColor()
            },
            _drawMarkerInGroup: function(group, attributes, renderer) {
                var that = this;
                that.graphic = renderer.path(that._getPoints(), "area").attr({"stroke-linecap": "square"}).attr(attributes).data({point: that}).sharp().append(group)
            },
            _fillStyle: function() {
                var that = this,
                    styles = that._options.styles;
                if (that._isReduction && that._isPositive)
                    that._styles = styles.reductionPositive;
                else if (that._isReduction)
                    that._styles = styles.reduction;
                else if (that._isPositive)
                    that._styles = styles.positive;
                else
                    that._styles = styles
            },
            _getMinTrackerWidth: function() {
                return 2 + 2 * this._styles.normal['stroke-width']
            },
            correctCoordinates: function(correctOptions) {
                var minWidth = this._getMinTrackerWidth(),
                    maxWidth = 10,
                    width = correctOptions.width;
                width = width < minWidth ? minWidth : width > maxWidth ? maxWidth : width;
                this.width = width + width % 2;
                this.xCorrection = correctOptions.offset
            },
            _getMarkerGroup: function(group) {
                var that = this,
                    markerGroup;
                if (that._isReduction && that._isPositive)
                    markerGroup = group.reductionPositiveMarkersGroup;
                else if (that._isReduction)
                    markerGroup = group.reductionMarkersGroup;
                else if (that._isPositive)
                    markerGroup = group.defaultPositiveMarkersGroup;
                else
                    markerGroup = group.defaultMarkersGroup;
                return markerGroup
            },
            _drawMarker: function(renderer, group) {
                this._drawMarkerInGroup(this._getMarkerGroup(group), this._getStyle(), 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
                    }
            },
            _getGraphicBbox: function() {
                var that = this,
                    rotated = that._options.rotated,
                    x = that.x,
                    width = that.width,
                    lowY = that.lowY,
                    highY = that.highY;
                return {
                        x: !rotated ? x - _round(width / 2) : lowY,
                        y: !rotated ? highY : x - _round(width / 2),
                        width: !rotated ? width : highY - lowY,
                        height: !rotated ? lowY - highY : width
                    }
            },
            getTooltipParams: function(location) {
                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(),
                        edgeLocation = location === 'edge';
                    if (!that._options.rotated) {
                        min = _max(visibleAreaY.min, minValue);
                        max = _min(visibleAreaY.max, maxValue);
                        x = that.x;
                        y = edgeLocation ? min : min + (max - min) / 2
                    }
                    else {
                        min = _max(visibleAreaX.min, minValue);
                        max = _min(visibleAreaX.max, maxValue);
                        y = that.x;
                        x = edgeLocation ? max : min + (max - min) / 2
                    }
                    return {
                            x: x,
                            y: y,
                            offset: 0
                        }
                }
            },
            hasValue: function() {
                return this.highValue !== null && this.lowValue !== null
            },
            _translate: function() {
                var that = this,
                    rotated = that._options.rotated,
                    translators = that.translators,
                    argTranslator = rotated ? translators.y : translators.x,
                    valTranslator = rotated ? translators.x : translators.y,
                    centerValue,
                    height;
                that.vx = that.vy = 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)
            },
            getCrosshairCoords: function(x, y) {
                var coords,
                    valueCoord = this._options.rotated ? x : y,
                    value = Math.abs(this.lowY - valueCoord) < Math.abs(this.closeY - valueCoord) ? this.lowY : this.closeY;
                value = Math.abs(value - valueCoord) < Math.abs(this.openY - valueCoord) ? value : this.openY;
                value = Math.abs(value - valueCoord) < Math.abs(this.highY - valueCoord) ? value : this.highY;
                if (this._options.rotated)
                    coords = {
                        y: this.vy,
                        x: value
                    };
                else
                    coords = {
                        x: this.vx,
                        y: value
                    };
                return coords
            },
            _updateData: function(data) {
                var that = this,
                    label = that._label,
                    reductionColor = this._options.reduction.color;
                that.value = that.initialValue = data.reductionValue;
                that.originalValue = data.value;
                that.lowValue = that.originalLowValue = data.lowValue;
                that.highValue = that.originalHighValue = data.highValue;
                that.openValue = that.originalOpenValue = data.openValue;
                that.closeValue = that.originalCloseValue = data.closeValue;
                that._isPositive = data.openValue < data.closeValue;
                that._isReduction = data.isReduction;
                if (that._isReduction)
                    label.setColor(reductionColor)
            },
            _updateMarker: function(animationEnabled, style, group) {
                var that = this,
                    graphic = that.graphic;
                graphic.attr({points: that._getPoints()}).attr(style || that._getStyle()).sharp();
                group && graphic.append(that._getMarkerGroup(group))
            },
            _getLabelFormatObject: function() {
                var that = this;
                return {
                        openValue: that.openValue,
                        highValue: that.highValue,
                        lowValue: that.lowValue,
                        closeValue: that.closeValue,
                        reductionValue: that.initialValue,
                        argument: that.initialArgument,
                        value: that.initialValue,
                        seriesName: that.series.name,
                        originalOpenValue: that.originalOpenValue,
                        originalCloseValue: that.originalCloseValue,
                        originalLowValue: that.originalLowValue,
                        originalHighValue: that.originalHighValue,
                        originalArgument: that.originalArgument,
                        point: that
                    }
            },
            _getFormatObject: function(tooltip) {
                var that = this,
                    highValue = tooltip.formatValue(that.highValue),
                    openValue = tooltip.formatValue(that.openValue),
                    closeValue = tooltip.formatValue(that.closeValue),
                    lowValue = tooltip.formatValue(that.lowValue),
                    symbolMethods = points.symbolPoint,
                    formatObject = symbolMethods._getFormatObject.call(that, 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 points = DX.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 [y, x]
                    } : function(x, y) {
                        return [x, y]
                    },
                    openYExist = _isNumeric(that.openY),
                    closeYExist = _isNumeric(that.closeY),
                    x = that.x,
                    width = that.width,
                    points;
                points = [].concat(createPoint(x, that.highY));
                openYExist && (points = points.concat(createPoint(x, that.openY)));
                openYExist && (points = points.concat(createPoint(x - width / 2, that.openY)));
                openYExist && (points = points.concat(createPoint(x, that.openY)));
                closeYExist && (points = points.concat(createPoint(x, that.closeY)));
                closeYExist && (points = points.concat(createPoint(x + width / 2, that.closeY)));
                closeYExist && (points = points.concat(createPoint(x, that.closeY)));
                points = points.concat(createPoint(x, that.lowY));
                return points
            },
            _drawMarkerInGroup: function(group, attributes, renderer) {
                this.graphic = renderer.path(this._getPoints(), "line").attr({"stroke-linecap": "square"}).attr(attributes).data({point: this}).sharp().append(group)
            },
            _getMinTrackerWidth: function() {
                var width = 2 + this._styles.normal['stroke-width'];
                return width + width % 2
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file polarPoint.js */
    (function($, DX, undefined) {
        var _extend = $.extend,
            viz = DX.viz,
            points = viz.core.series.points.mixins,
            utils = DX.utils,
            isDefined = utils.isDefined,
            normalizeAngle = utils.normalizeAngle,
            _math = Math,
            _max = _math.max,
            ERROR_BARS_ANGLE_OFFSET = 90,
            CANVAS_POSITION_START = "canvas_position_start",
            CANVAS_POSITION_TOP = "canvas_position_top",
            CANVAS_POSITION_END = "canvas_position_end",
            CANVAS_POSITION_DEFAULT = "canvas_position_default";
        points.polarSymbolPoint = _extend({}, points.symbolPoint, {
            _getLabelCoords: points.piePoint._getLabelCoords,
            _moveLabelOnCanvas: points.barPoint._moveLabelOnCanvas,
            _getLabelPosition: function() {
                return "outside"
            },
            _translate: function(translator) {
                var that = this,
                    coord = translator.translate(that.argument, that.value),
                    center = translator.translate(CANVAS_POSITION_START, CANVAS_POSITION_TOP);
                that.vx = normalizeAngle(coord.angle);
                that.vy = that.radiusOuter = coord.radius;
                that.radius = coord.radius;
                that.middleAngle = -coord.angle;
                that.angle = -coord.angle;
                that.x = coord.x;
                that.y = coord.y;
                that.defaultX = that.centerX = center.x;
                that.defaultY = that.centerY = center.y;
                that._translateErrorBars(translator);
                that.inVisibleArea = true
            },
            _translateErrorBars: function(translator) {
                var that = this;
                isDefined(that.lowError) && (that._lowErrorCoord = that.centerY - translator.translate(that.argument, that.lowError).radius);
                isDefined(that.highError) && (that._highErrorCoord = that.centerY - translator.translate(that.argument, that.highError).radius);
                that._errorBarPos = that.centerX;
                that._baseErrorBarPos = (that._options.errorBars || {}).type === "stdDeviation" ? that._lowErrorCoord + (that._highErrorCoord - that._lowErrorCoord) / 2 : that.centerY - that.radius
            },
            _getTranslates: function(animationEnabled) {
                return animationEnabled ? this.getDefaultCoords() : {
                        x: this.x,
                        y: this.y
                    }
            },
            getDefaultCoords: function() {
                var cossin = utils.getCosAndSin(-this.angle),
                    radius = this.translators.translate(CANVAS_POSITION_START, CANVAS_POSITION_DEFAULT).radius,
                    x = this.defaultX + radius * cossin.cos,
                    y = this.defaultY + radius * cossin.sin;
                return {
                        x: x,
                        y: y
                    }
            },
            _addLabelAlignmentAndOffset: function(label, coord) {
                return coord
            },
            _getVisibleArea: function() {
                var canvas = this.translators.canvas;
                return {
                        minX: canvas.left,
                        maxX: canvas.width - canvas.right,
                        minY: canvas.top,
                        maxY: canvas.height - canvas.bottom
                    }
            },
            _checkLabelPosition: function(label, coord) {
                var that = this,
                    visibleArea = that._getVisibleArea(),
                    graphicBbox = that._getGraphicBbox();
                if (that._isPointInVisibleArea(visibleArea, graphicBbox))
                    coord = that._moveLabelOnCanvas(coord, visibleArea, label.getBoundingRect(), true, true);
                return coord
            },
            _getErrorBarSettings: function(errorBarOptions, animationEnabled) {
                var settings = points.symbolPoint._getErrorBarSettings.call(this, errorBarOptions, animationEnabled);
                settings.rotate = ERROR_BARS_ANGLE_OFFSET - this.angle;
                settings.rotateX = this.centerX;
                settings.rotateY = this.centerY;
                return settings
            },
            getCoords: function(min) {
                return min ? this.getDefaultCoords() : {
                        x: this.x,
                        y: this.y
                    }
            }
        });
        points.polarBarPoint = _extend({}, points.barPoint, {
            _translateErrorBars: points.polarSymbolPoint._translateErrorBars,
            _getErrorBarSettings: points.polarSymbolPoint._getErrorBarSettings,
            _getVisibleArea: points.polarSymbolPoint._getVisibleArea,
            _moveLabelOnCanvas: points.barPoint._moveLabelOnCanvas,
            _getLabelCoords: points.piePoint._getLabelCoords,
            _getLabelConnector: points.piePoint._getLabelConnector,
            getBoundaryCoords: points.piePoint.getBoundaryCoords,
            getTooltipParams: points.piePoint.getTooltipParams,
            _getLabelPosition: points.piePoint._getLabelPosition,
            _translate: function(translator) {
                var that = this,
                    maxRadius = translator.translate(CANVAS_POSITION_TOP, CANVAS_POSITION_END).radius;
                that.radiusInner = translator.translate(that.argument, that.minValue).radius;
                points.polarSymbolPoint._translate.call(that, translator);
                if (that.radiusInner === null)
                    that.radiusInner = that.radius = maxRadius;
                else if (that.radius === null)
                    this.radius = this.value >= 0 ? maxRadius : 0;
                that.radiusOuter = _max(that.radiusInner, that.radius);
                that.radiusInner = that.defaultRadius = _math.min(that.radiusInner, that.radius);
                that.middleAngle = that.angle = -utils.normalizeAngle(that.middleAngleCorrection - that.angle)
            },
            _checkVisibility: function(translator) {
                return translator.checkVisibility(this.radius, this.radiusInner)
            },
            getMarkerCoords: function() {
                return {
                        x: this.centerX,
                        y: this.centerY,
                        outerRadius: this.radiusOuter,
                        innerRadius: this.defaultRadius,
                        startAngle: this.middleAngle - this.interval / 2,
                        endAngle: this.middleAngle + this.interval / 2
                    }
            },
            _drawMarker: function(renderer, group, animationEnabled) {
                var that = this,
                    styles = that._getStyle(),
                    coords = that.getMarkerCoords(),
                    innerRadius = coords.innerRadius,
                    outerRadius = coords.outerRadius,
                    start = that.translators.translate(that.argument, CANVAS_POSITION_DEFAULT),
                    x = coords.x,
                    y = coords.y;
                if (animationEnabled) {
                    innerRadius = 0;
                    outerRadius = 0;
                    x = start.x;
                    y = start.y
                }
                that.graphic = renderer.arc(x, y, innerRadius, outerRadius, coords.startAngle, coords.endAngle).attr(styles).data({point: that}).append(group)
            },
            _checkLabelPosition: function(label, coord) {
                var that = this,
                    visibleArea = that._getVisibleArea(),
                    angleFunctions = utils.getCosAndSin(that.middleAngle),
                    x = that.centerX + that.defaultRadius * angleFunctions.cos,
                    y = that.centerY - that.defaultRadius * angleFunctions.sin;
                if (x > visibleArea.minX && x < visibleArea.maxX && y > visibleArea.minY && y < visibleArea.maxY)
                    coord = that._moveLabelOnCanvas(coord, visibleArea, label.getBoundingRect(), true, true);
                return coord
            },
            _addLabelAlignmentAndOffset: function(label, coord) {
                return coord
            },
            correctCoordinates: function(correctOptions) {
                this.middleAngleCorrection = correctOptions.offset;
                this.interval = correctOptions.width
            },
            coordsIn: function(x, y) {
                var val = this.translators.untranslate(x, y),
                    coords = this.getMarkerCoords(),
                    isBetweenAngles = coords.startAngle < coords.endAngle ? -val.phi >= coords.startAngle && -val.phi <= coords.endAngle : -val.phi <= coords.startAngle && -val.phi >= coords.endAngle;
                return val.r >= coords.innerRadius && val.r <= coords.outerRadius && isBetweenAngles
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file dataValidator.js */
    (function($, DX, undefined) {
        var viz = DX.viz,
            parseUtils = new viz.core.ParseUtils,
            STRING = "string",
            NUMERIC = "numeric",
            DATETIME = "datetime",
            DISCRETE = "discrete",
            CONTINUOUS = "continuous",
            LOGARITHMIC = "logarithmic",
            VALUE_TYPE = "valueType",
            ARGUMENT_TYPE = "argumentType",
            axisTypeParser = viz.core.utils.enumParser([STRING, NUMERIC, DATETIME]),
            utils = DX.utils,
            _each = $.each,
            _isDefined = utils.isDefined;
        function groupingValues(data, others, valueField, 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
            })
        }
        function mergeSort(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
        }
        function merge(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
        }
        function DataValidator(data, groups, incidentOccured, dataPrepareOptions) {
            var that = this;
            groups = groups || [[]];
            that._nullData = !data;
            that.groups = groups;
            that.data = data || [];
            that._parsers = {};
            that._errorShowList = {};
            that._skipFields = {};
            that.options = dataPrepareOptions || {};
            that.incidentOccured = incidentOccured;
            that.userArgumentCategories = that.groups.argumentOptions && that.groups.argumentOptions.categories || [];
            if (!incidentOccured)
                that.incidentOccured = $.noop
        }
        viz.core.DataValidator = DataValidator;
        DataValidator.prototype = {
            ctor: DataValidator,
            validate: function validate() {
                var that = this,
                    dataLength;
                that._data = that.data;
                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({})
                    });
                    group.valueAxis && group.valueAxis.resetTypes(VALUE_TYPE)
                });
                if (that.groups.argumentAxes)
                    _each(that.groups.argumentAxes, function(_, axis) {
                        axis.resetTypes(ARGUMENT_TYPE)
                    });
                that._checkType();
                that._checkAxisType();
                if (!utils.isArray(that.data) || that._nullData)
                    that._incorrectDataMessage();
                if (that.options.convertToAxisDataType) {
                    that._createParser();
                    that._parse()
                }
                that._groupData();
                that._sort();
                dataLength = that._data.length;
                _each(that._skipFields, function(field, fieldValue) {
                    if (fieldValue === dataLength)
                        that.incidentOccured("W2002", [field])
                });
                return that._data
            },
            _checkValueTypeOfGroup: function(group, cell) {
                var that = this;
                _each(group, function(_, series) {
                    _each(series.getValueFields(), function(_, field) {
                        group.valueType = that._getType(cell[field], group.valueType)
                    })
                });
                return group.valueType
            },
            _checkArgumentTypeOfGroup: function(group, cell) {
                var that = this;
                _each(group, function(_, series) {
                    that.groups.argumentType = that._getType(cell[series.getArgumentField()], that.groups.argumentType)
                });
                return that.groups.argumentType
            },
            _checkType: function _checkType() {
                var that = this,
                    groupsWithUndefinedValueType = [],
                    groupsWithUndefinedArgumentType = [],
                    groups = that.groups,
                    argumentTypeGroup = groups.argumentOptions && axisTypeParser(groups.argumentOptions.argumentType);
                _each(groups, function(_, group) {
                    if (!group.length)
                        return null;
                    var valueTypeGroup = group.valueOptions && axisTypeParser(group.valueOptions.valueType);
                    group.valueType = valueTypeGroup;
                    groups.argumentType = argumentTypeGroup;
                    !valueTypeGroup && groupsWithUndefinedValueType.push(group);
                    !argumentTypeGroup && groupsWithUndefinedArgumentType.push(group)
                });
                if (groupsWithUndefinedValueType.length || groupsWithUndefinedArgumentType.length)
                    _each(that.data, function(_, cell) {
                        var defineVal,
                            defineArg;
                        if (!utils.isObject(cell))
                            return;
                        _each(groupsWithUndefinedValueType, function(_, group) {
                            defineVal = that._checkValueTypeOfGroup(group, cell)
                        });
                        _each(groupsWithUndefinedArgumentType, function(_, group) {
                            defineArg = that._checkArgumentTypeOfGroup(group, cell)
                        });
                        if (!that.options.checkTypeForAllData && defineVal && defineArg)
                            return false
                    })
            },
            _checkAxisType: function _checkAxisType() {
                var that = this,
                    groups = that.groups,
                    argumentOptions = groups.argumentOptions || {};
                _each(groups, function(_, group) {
                    _each(group, function(_, series) {
                        var optionsSeries = {},
                            valueOptions = group.valueOptions || {},
                            valueCategories = valueOptions.categories || [];
                        optionsSeries.argumentAxisType = that._correctAxisType(groups.argumentType, argumentOptions.type, !!that.userArgumentCategories.length);
                        optionsSeries.valueAxisType = that._correctAxisType(group.valueType, valueOptions.type, !!valueCategories.length);
                        groups.argumentAxisType = groups.argumentAxisType || optionsSeries.argumentAxisType;
                        group.valueAxisType = group.valueAxisType || optionsSeries.valueAxisType;
                        optionsSeries.argumentType = groups.argumentType;
                        optionsSeries.valueType = group.valueType;
                        optionsSeries.showZero = valueOptions.showZero;
                        series.updateDataType(optionsSeries)
                    });
                    if (group.valueAxis) {
                        group.valueAxis.setTypes(group.valueAxisType, group.valueType, VALUE_TYPE);
                        group.valueAxis.validate(false)
                    }
                });
                if (that.groups.argumentAxes)
                    _each(that.groups.argumentAxes, function(_, axis) {
                        axis.setTypes(that.groups.argumentAxisType, that.groups.argumentType, ARGUMENT_TYPE);
                        axis.validate(true)
                    })
            },
            _createParser: function _createParser() {
                var that = this,
                    groups = that.groups;
                _each(groups, function(_, group) {
                    _each(group, function(_, series) {
                        that._parsers[series.getArgumentField()] = that._createParserUnit(groups.argumentType, groups.argumentAxisType === LOGARITHMIC ? that._filterForLogAxis : null);
                        _each(series.getValueFields(), function(_, field) {
                            that._parsers[field] = that._createParserUnit(group.valueType, group.valueAxisType === 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) {
                smallValuesGrouping = smallValuesGrouping || {};
                var that = this,
                    mode = smallValuesGrouping.mode,
                    count = smallValuesGrouping.topCount,
                    threshold = smallValuesGrouping.threshold,
                    name = smallValuesGrouping.groupName || "others",
                    others = {},
                    data = that._data.slice(),
                    index;
                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(data, others, valueField, index)
                }
                else if (mode === "topN")
                    groupingValues(data, others, valueField, 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 === 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 === STRING || utils.isString(unit))
                    return STRING;
                if (type === DATETIME || utils.isDate(unit))
                    return DATETIME;
                if (utils.isNumber(unit))
                    return NUMERIC;
                return type
            },
            _correctAxisType: function _correctAxisType(type, axisType, hasCategories) {
                if (type === STRING && (axisType === CONTINUOUS || axisType === LOGARITHMIC))
                    this.incidentOccured("E2002");
                if (axisType === LOGARITHMIC)
                    return LOGARITHMIC;
                axisType = (hasCategories || axisType === DISCRETE || type === STRING) && DISCRETE;
                return axisType || 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) {
                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,
                    sortingMethod = that.options.sortingMethod,
                    data = that._data,
                    groups = that.groups,
                    hash = {},
                    argumentField = groups.length && groups[0].length && groups[0][0].getArgumentField();
                if (utils.isFunction(sortingMethod))
                    data.sort(sortingMethod);
                else if (that.userArgumentCategories.length) {
                    _each(that.userArgumentCategories, function(index, value) {
                        hash[value] = index
                    });
                    data.sort(function sortCat(a, b) {
                        a = a[argumentField];
                        b = b[argumentField];
                        return hash[a] - hash[b]
                    })
                }
                else if (sortingMethod === true && groups.argumentType !== STRING)
                    mergeSort(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 default.js */
    (function(DX, undefined) {
        var WHITE = "#ffffff",
            BLACK = "#000000",
            LIGHT_GREY = "#d3d3d3",
            GREY_GREEN = "#303030",
            RED = "#ff0000";
        DX.viz.core.registerTheme({
            name: "generic.light",
            font: {
                color: '#767676',
                family: "'Segoe UI', 'Helvetica Neue', 'Trebuchet MS', Verdana",
                weight: 400,
                size: 12,
                cursor: 'default'
            },
            redrawOnResize: true,
            backgroundColor: WHITE,
            primaryTitleColor: "#232323",
            secondaryTitleColor: "#767676",
            axisColor: LIGHT_GREY,
            axisLabelColor: "#a8a8a8",
            title: {font: {
                    family: "'Segoe UI Light', 'Helvetica Neue Light', 'Segoe UI', 'Helvetica Neue', 'Trebuchet MS', Verdana",
                    weight: 200
                }},
            loadingIndicator: {text: "Loading..."},
            tooltip: {
                enabled: false,
                border: {
                    width: 1,
                    color: LIGHT_GREY,
                    dashStyle: 'solid',
                    visible: true
                },
                font: {color: '#232323'},
                color: WHITE,
                arrowLength: 10,
                paddingLeftRight: 18,
                paddingTopBottom: 15,
                shared: false,
                location: 'center',
                format: '',
                argumentFormat: '',
                precision: 0,
                argumentPrecision: 0,
                percentPrecision: 0,
                shadow: {
                    opacity: 0.4,
                    offsetX: 0,
                    offsetY: 4,
                    blur: 2,
                    color: BLACK
                }
            },
            legend: {
                hoverMode: 'includePoints',
                verticalAlignment: 'top',
                horizontalAlignment: 'right',
                position: 'outside',
                visible: true,
                margin: 10,
                markerSize: 12,
                border: {
                    visible: false,
                    width: 1,
                    cornerRadius: 0,
                    dashStyle: 'solid'
                },
                paddingLeftRight: 20,
                paddingTopBottom: 15,
                columnCount: 0,
                rowCount: 0,
                columnItemSpacing: 20,
                rowItemSpacing: 8
            },
            "chart:common": {
                animation: {
                    enabled: true,
                    duration: 1000,
                    easing: 'easeOutCubic',
                    maxPointCountSupported: 300
                },
                commonSeriesSettings: {
                    border: {
                        visible: false,
                        width: 2
                    },
                    showInLegend: true,
                    visible: true,
                    hoverMode: 'nearestPoint',
                    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
                        }
                    },
                    valueErrorBar: {
                        displayMode: "auto",
                        value: 1,
                        color: BLACK,
                        lineWidth: 2,
                        edgeLength: 8
                    },
                    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: WHITE},
                        border: {
                            visible: false,
                            width: 1,
                            color: LIGHT_GREY,
                            dashStyle: 'solid'
                        },
                        connector: {
                            visible: false,
                            width: 1
                        }
                    }
                },
                seriesSelectionMode: 'single',
                pointSelectionMode: 'single',
                equalRowHeight: true,
                dataPrepareSettings: {
                    checkTypeForAllData: false,
                    convertToAxisDataType: true,
                    sortingMethod: true
                },
                title: {
                    font: {size: 28},
                    margin: 10
                },
                adaptiveLayout: {
                    width: 80,
                    height: 80,
                    keepLabels: true
                },
                _rtl: {legend: {itemTextPosition: 'left'}},
                resolveLabelOverlapping: "none"
            },
            "chart:common:axis": {
                visible: false,
                setTicksAtUnitBeginning: true,
                valueMarginsEnabled: true,
                placeholderSize: null,
                logarithmBase: 10,
                discreteAxisDivisionMode: 'betweenLabels',
                width: 1,
                label: {
                    visible: true,
                    precision: 0,
                    format: ""
                },
                grid: {
                    visible: false,
                    width: 1
                },
                minorGrid: {
                    visible: false,
                    width: 1,
                    opacity: 0.3
                },
                tick: {visible: false},
                minorTick: {
                    visible: false,
                    opacity: 0.3
                },
                stripStyle: {
                    paddingLeftRight: 10,
                    paddingTopBottom: 5
                },
                constantLineStyle: {
                    width: 1,
                    color: BLACK,
                    dashStyle: "solid",
                    label: {
                        visible: true,
                        position: "inside"
                    }
                }
            },
            chart: {
                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}
                    },
                    stackedspline: {
                        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}
                    },
                    fullstackedspline: {
                        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
                    },
                    fullstackedsplinearea: {
                        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
                    },
                    stackedsplinearea: {
                        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,
                        reduction: {color: RED},
                        hoverStyle: {
                            width: 3,
                            hatching: {direction: 'none'}
                        },
                        selectionStyle: {width: 3},
                        point: {border: {visible: true}}
                    },
                    stock: {
                        width: 1,
                        reduction: {color: RED},
                        hoverStyle: {
                            width: 3,
                            hatching: {direction: 'none'}
                        },
                        selectionStyle: {width: 3},
                        point: {border: {visible: true}}
                    }
                },
                crosshair: {
                    enabled: false,
                    color: '#f78119',
                    width: 1,
                    dashStyle: 'solid',
                    label: {
                        visible: false,
                        font: {
                            color: WHITE,
                            size: 12
                        }
                    },
                    verticalLine: {visible: true},
                    horizontalLine: {visible: true}
                },
                commonAxisSettings: {
                    multipleAxesSpacing: 5,
                    label: {
                        overlappingBehavior: {
                            mode: 'auto',
                            rotationAngle: 90,
                            staggeringSpacing: 5
                        },
                        indentFromAxis: 10
                    },
                    title: {
                        font: {size: 16},
                        margin: 6
                    },
                    constantLineStyle: {
                        paddingLeftRight: 10,
                        paddingTopBottom: 10
                    }
                },
                horizontalAxis: {
                    position: 'bottom',
                    axisDivisionFactor: 50,
                    label: {alignment: "center"},
                    stripStyle: {label: {
                            horizontalAlignment: 'center',
                            verticalAlignment: 'top'
                        }},
                    constantLineStyle: {label: {
                            horizontalAlignment: 'right',
                            verticalAlignment: 'top'
                        }},
                    constantLines: {}
                },
                verticalAxis: {
                    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: LIGHT_GREY,
                        width: 1,
                        visible: false,
                        top: true,
                        bottom: true,
                        left: true,
                        right: true,
                        dashStyle: 'solid'
                    }
                },
                scrollBar: {
                    visible: false,
                    offset: 5,
                    color: "gray",
                    width: 10
                },
                useAggregation: false,
                adjustOnZoom: true,
                rotated: false,
                zoomingMode: 'none',
                scrollingMode: 'none',
                synchronizeMultiAxes: true,
                equalBarWidth: true,
                minBubbleSize: 12,
                maxBubbleSize: 0.2
            },
            pie: {
                commonSeriesSettings: {
                    type: 'pie',
                    pie: {
                        border: {
                            visible: false,
                            width: 2,
                            color: WHITE
                        },
                        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: WHITE
                        },
                        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: WHITE
                        },
                        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',
                    backgroundColor: "none"
                },
                adaptiveLayout: {keepLabels: false}
            },
            pieIE8: {commonSeriesSettings: {
                    pie: {
                        hoverStyle: {border: {
                                visible: true,
                                color: WHITE
                            }},
                        selectionStyle: {border: {
                                visible: true,
                                color: WHITE
                            }}
                    },
                    donut: {
                        hoverStyle: {border: {
                                visible: true,
                                color: WHITE
                            }},
                        selectionStyle: {border: {
                                visible: true,
                                color: WHITE
                            }}
                    },
                    doughnut: {
                        hoverStyle: {border: {
                                visible: true,
                                color: WHITE
                            }},
                        selectionStyle: {border: {
                                visible: true,
                                color: WHITE
                            }}
                    }
                }},
            gauge: {
                scale: {
                    majorTick: {
                        visible: true,
                        length: 5,
                        width: 2,
                        showCalculatedTicks: true,
                        useTicksAutoArrangement: true
                    },
                    minorTick: {
                        visible: false,
                        length: 3,
                        width: 1,
                        showCalculatedTicks: true
                    },
                    label: {visible: true}
                },
                rangeContainer: {
                    offset: 0,
                    width: 5,
                    backgroundColor: '#808080'
                },
                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: WHITE,
                                size: 18
                            }}
                    }
                },
                title: {
                    layout: {
                        horizontalAlignment: 'center',
                        verticalAlignment: 'top',
                        overlay: 0
                    },
                    font: {size: 16}
                },
                subtitle: {font: {size: 14}},
                indicator: {
                    hasPositiveMeaning: true,
                    layout: {
                        horizontalAlignment: 'center',
                        verticalAlignment: 'bottom',
                        overlay: 0
                    },
                    text: {font: {size: 18}}
                },
                _circular: {
                    scale: {
                        orientation: 'outside',
                        label: {indentFromTick: 10}
                    },
                    rangeContainer: {orientation: 'outside'},
                    valueIndicatorType: 'rectangleneedle',
                    subvalueIndicatorType: 'trianglemarker',
                    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'
                    },
                    valueIndicatorType: 'rangebar',
                    subvalueIndicatorType: 'trianglemarker',
                    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}
                },
                subtitle: {font: {size: 14}},
                indicator: {
                    hasPositiveMeaning: true,
                    layout: {
                        horizontalAlignment: 'center',
                        verticalAlignment: 'bottom',
                        overlay: 0
                    },
                    text: {font: {size: 18}}
                }
            },
            rangeSelector: {
                scale: {
                    showCustomBoundaryTicks: true,
                    showMinorTicks: true,
                    useTicksAutoArrangement: true,
                    setTicksAtUnitBeginning: true,
                    label: {
                        visible: true,
                        topIndent: 7,
                        font: {size: 11}
                    },
                    tick: {
                        width: 1,
                        color: BLACK,
                        opacity: 0.1
                    },
                    marker: {
                        visible: true,
                        separatorHeight: 33,
                        topIndent: 10,
                        textLeftIndent: 7,
                        textTopIndent: 11,
                        label: {}
                    },
                    logarithmBase: 10
                },
                selectedRangeColor: "#606060",
                sliderMarker: {
                    visible: true,
                    paddingTopBottom: 2,
                    paddingLeftRight: 4,
                    color: '#606060',
                    invalidRangeColor: RED,
                    font: {
                        color: WHITE,
                        size: 11
                    }
                },
                sliderHandle: {
                    width: 1,
                    color: BLACK,
                    opacity: 0.2
                },
                shutter: {opacity: 0.75},
                background: {
                    color: "#c0bae1",
                    visible: true,
                    image: {location: 'full'}
                },
                behavior: {
                    snapToTicks: true,
                    animationEnabled: true,
                    moveSelectedRangeByClick: true,
                    manualRangeSelectionEnabled: true,
                    allowSlidersSwap: true,
                    callSelectedRangeChanged: "onMovingComplete"
                },
                redrawOnResize: true,
                chart: {
                    useAggregation: false,
                    equalBarWidth: true,
                    minBubbleSize: 12,
                    maxBubbleSize: 0.2,
                    topIndent: 0.1,
                    bottomIndent: 0,
                    valueAxis: {
                        inverted: false,
                        logarithmBase: 10
                    },
                    commonSeriesSettings: {
                        type: "area",
                        point: {visible: false}
                    }
                }
            },
            map: {
                background: {
                    borderWidth: 1,
                    borderColor: '#cacaca'
                },
                areaSettings: {
                    borderWidth: 1,
                    borderColor: WHITE,
                    color: '#d2d2d2',
                    hoveredBorderColor: GREY_GREEN,
                    selectedBorderWidth: 2,
                    selectedBorderColor: GREY_GREEN,
                    label: {
                        enabled: false,
                        stroke: WHITE,
                        'stroke-width': 2,
                        'stroke-opacity': 0.5,
                        font: {
                            color: '#2b2b2b',
                            size: 16,
                            opacity: 0.5
                        }
                    }
                },
                markerSettings: {
                    label: {
                        enabled: true,
                        stroke: WHITE,
                        'stroke-width': 1,
                        'stroke-opacity': 0.5,
                        font: {
                            color: '#2b2b2b',
                            size: 12
                        }
                    },
                    _dot: {
                        borderWidth: 2,
                        borderColor: WHITE,
                        color: '#ba4d51',
                        size: 8,
                        selectedStep: 2,
                        backStep: 18,
                        backColor: WHITE,
                        backOpacity: 0.32,
                        shadow: true
                    },
                    _bubble: {
                        minSize: 20,
                        maxSize: 50,
                        color: '#ba4d51',
                        hoveredBorderWidth: 1,
                        hoveredBorderColor: GREY_GREEN,
                        selectedBorderWidth: 2,
                        selectedBorderColor: GREY_GREEN
                    },
                    _pie: {
                        size: 50,
                        hoveredBorderWidth: 1,
                        hoveredBorderColor: GREY_GREEN,
                        selectedBorderWidth: 2,
                        selectedBorderColor: GREY_GREEN
                    },
                    _image: {size: 20}
                },
                legend: {
                    verticalAlignment: 'bottom',
                    horizontalAlignment: 'right',
                    position: 'inside',
                    backgroundOpacity: 0.65,
                    border: {
                        visible: true,
                        color: '#cacaca'
                    },
                    paddingLeftRight: 16,
                    paddingTopBottom: 12,
                    markerColor: '#ba4d51'
                },
                controlBar: {
                    borderColor: '#5d5d5d',
                    borderWidth: 3,
                    color: WHITE,
                    margin: 20,
                    opacity: 0.3
                },
                _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: WHITE,
                pointSize: 4,
                type: "line",
                argumentField: "arg",
                valueField: "val",
                winlossThreshold: 0,
                showFirstLast: true,
                showMinMax: false,
                tooltip: {enabled: true}
            },
            bullet: {
                color: '#e8c267',
                targetColor: '#666666',
                targetWidth: 4,
                showTarget: true,
                showZeroLevel: true,
                tooltip: {enabled: true}
            },
            polar: {
                commonSeriesSettings: {
                    type: 'scatter',
                    closed: true,
                    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}
                    },
                    area: {
                        point: {visible: false},
                        opacity: 0.5
                    },
                    stackedline: {width: 2},
                    bar: {opacity: 0.8},
                    stackedbar: {opacity: 0.8}
                },
                adaptiveLayout: {
                    width: 170,
                    height: 170,
                    keepLabels: true
                },
                equalBarWidth: true,
                commonAxisSettings: {
                    visible: true,
                    label: {
                        overlappingBehavior: {mode: 'enlargeTickInterval'},
                        indentFromAxis: 5
                    },
                    grid: {visible: true},
                    minorGrid: {visible: true},
                    tick: {visible: true},
                    title: {
                        font: {size: 16},
                        margin: 10
                    }
                },
                argumentAxis: {
                    startAngle: 0,
                    firstPointOnStartAngle: false,
                    period: undefined
                },
                valueAxis: {tick: {visible: false}},
                horizontalAxis: {
                    position: 'top',
                    axisDivisionFactor: 50,
                    label: {alignment: "center"}
                },
                verticalAxis: {
                    position: 'top',
                    axisDivisionFactor: 30,
                    label: {alignment: "right"}
                }
            }
        });
        DX.viz.core.registerTheme({
            name: "generic.dark",
            font: {color: '#808080'},
            backgroundColor: GREY_GREEN,
            primaryTitleColor: "#dbdbdb",
            secondaryTitleColor: "#a3a3a3",
            axisColor: "#555555",
            axisLabelColor: "#707070",
            tooltip: {
                color: '#2b2b2b',
                border: {color: '#494949'},
                font: {color: '#929292'}
            },
            "chart:common": {commonSeriesSettings: {
                    label: {border: {color: '#494949'}},
                    valueErrorBar: {color: WHITE}
                }},
            "chart:common:axis": {constantLineStyle: {color: WHITE}},
            chart: {
                crosshair: {color: '#515151'},
                commonPaneSettings: {border: {color: '#494949'}}
            },
            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: {
                rangeContainer: {backgroundColor: '#b5b5b5'},
                valueIndicators: {
                    _default: {color: '#b5b5b5'},
                    rangebar: {color: '#84788b'},
                    twocolorneedle: {secondColor: '#ba544d'},
                    trianglemarker: {color: '#b7918f'},
                    textcloud: {color: '#ba544d'}
                }
            },
            barGauge: {backgroundColor: "#3c3c3c"},
            rangeSelector: {
                selectedRangeColor: '#b5b5b5',
                scale: {tick: {
                        color: WHITE,
                        opacity: 0.05
                    }},
                sliderMarker: {
                    color: '#b5b5b5',
                    font: {color: GREY_GREEN}
                },
                sliderHandle: {
                    color: WHITE,
                    opacity: 0.2
                },
                shutter: {
                    color: '#2b2b2b',
                    opacity: 0.9
                }
            },
            map: {
                background: {borderColor: '#3f3f3f'},
                areaSettings: {
                    borderColor: GREY_GREEN,
                    color: '#686868',
                    hoveredBorderColor: WHITE,
                    selectedBorderColor: WHITE,
                    label: {
                        stroke: BLACK,
                        font: {color: WHITE}
                    }
                },
                markerSettings: {
                    label: {
                        stroke: BLACK,
                        font: {color: WHITE}
                    },
                    _bubble: {
                        hoveredBorderColor: WHITE,
                        selectedBorderColor: WHITE
                    },
                    _pie: {
                        hoveredBorderColor: WHITE,
                        selectedBorderColor: WHITE
                    }
                },
                legend: {
                    border: {color: '#3f3f3f'},
                    font: {color: WHITE}
                },
                controlBar: {
                    borderColor: '#c7c7c7',
                    color: GREY_GREEN
                }
            },
            sparkline: {
                lineColor: '#c7c7c7',
                firstLastColor: '#c7c7c7',
                barPositiveColor: '#b8b8b8',
                barNegativeColor: '#8e8e8e',
                winColor: '#b8b8b8',
                lossColor: '#8e8e8e',
                pointColor: GREY_GREEN
            },
            bullet: {targetColor: '#8e8e8e'}
        }, "generic.light");
        DX.viz.core.currentTheme("generic.light");
        DX.viz.core.registerThemeAlias("desktop.light", "generic.light");
        DX.viz.core.registerThemeAlias("desktop.dark", "generic.dark")
    })(DevExpress);
    /*! Module viz-core, file android.js */
    (function(DX) {
        var ANDROID5_LIGHT = "android5.light",
            registerThemeAlias = DX.viz.core.registerThemeAlias;
        DX.viz.core.registerTheme({
            name: ANDROID5_LIGHT,
            backgroundColor: "#ffffff",
            primaryTitleColor: "#232323",
            secondaryTitleColor: "#767676",
            axisColor: "#d3d3d3",
            axisLabelColor: "#a8a8a8",
            tooltip: {
                color: "#e8e8e8",
                font: {color: "#808080"}
            },
            legend: {font: {color: "#000000"}},
            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'}}
                    }
                }}
        }, "generic.light");
        registerThemeAlias("android", ANDROID5_LIGHT);
        registerThemeAlias("android.holo-dark", ANDROID5_LIGHT);
        registerThemeAlias("android.holo-light", ANDROID5_LIGHT);
        registerThemeAlias("android.dark", ANDROID5_LIGHT);
        registerThemeAlias("android.light", ANDROID5_LIGHT)
    })(DevExpress);
    /*! Module viz-core, file ios.js */
    (function(DX) {
        var IOS7_DEFAULT = "ios7.default",
            core = DX.viz.core;
        core.registerTheme({
            name: IOS7_DEFAULT,
            backgroundColor: "#ffffff",
            primaryTitleColor: "#000000",
            secondaryTitleColor: "#767676",
            axisColor: "#ececec",
            axisLabelColor: "#b8b8b8",
            legend: {font: {color: '#000000'}},
            tooltip: {font: {color: '#808080'}},
            "chart:common": {commonSeriesSettings: {label: {border: {color: '#d3d3d3'}}}},
            chart: {commonPaneSettings: {border: {color: '#d3d3d3'}}}
        }, "generic.light");
        core.registerThemeAlias("ios", IOS7_DEFAULT)
    })(DevExpress);
    /*! Module viz-core, file win8.js */
    (function(DX) {
        var core = DX.viz.core,
            registerTheme = core.registerTheme,
            registerThemeSchemeAlias = core.registerThemeSchemeAlias,
            BLACK = "#000000",
            WHITE = "#ffffff";
        registerTheme({
            name: "win8.black",
            backgroundColor: BLACK,
            primaryTitleColor: WHITE,
            secondaryTitleColor: "#d8d8d8",
            axisColor: "#4c4c4c",
            axisLabelColor: "#a0a0a0",
            title: {font: {color: WHITE}},
            legend: {font: {color: WHITE}},
            tooltip: {
                color: BLACK,
                font: {color: WHITE}
            },
            "chart:common": {commonSeriesSettings: {label: {border: {color: '#454545'}}}},
            chart: {commonPaneSettings: {border: {color: '#454545'}}},
            pieIE8: {commonSeriesSettings: {
                    pie: {
                        hoverStyle: {border: {color: BLACK}},
                        selectionStyle: {border: {color: BLACK}}
                    },
                    donut: {
                        hoverStyle: {border: {color: BLACK}},
                        selectionStyle: {border: {color: BLACK}}
                    },
                    doughnut: {
                        hoverStyle: {border: {color: BLACK}},
                        selectionStyle: {border: {color: BLACK}}
                    }
                }},
            barGauge: {backgroundColor: "#2b3036"},
            rangeSelector: {scale: {tick: {opacity: 0.15}}}
        }, "generic.dark");
        registerTheme({
            name: "win8.white",
            backgroundColor: WHITE,
            primaryTitleColor: BLACK,
            secondaryTitleColor: "#767676",
            axisColor: "#ececec",
            axisLabelColor: "#b8b8b8",
            title: {font: {color: '#808080'}},
            legend: {font: {color: BLACK}},
            tooltip: {font: {color: '#808080'}}
        }, "generic.light");
        registerThemeSchemeAlias("win8.dark", "win8.black");
        registerThemeSchemeAlias("win8.light", "win8.white")
    })(DevExpress);
    /*! Module viz-core, file themeManager.js */
    (function($, DX, undefined) {
        var viz = DX.viz,
            Palette = viz.core.Palette,
            utils = DX.utils,
            _findTheme = DX.viz.core.findTheme,
            _isString = utils.isString,
            _isDefined = utils.isDefined,
            HOVER_COLOR_HIGHLIGHTING = 20,
            HIGHLIGHTING_STEP = 50,
            FONT = "font",
            COMMON_AXIS_SETTINGS = "commonAxisSettings",
            PIE_FONT_FIELDS = ["legend." + FONT, "title." + FONT, "tooltip." + FONT, "loadingIndicator." + FONT, "commonSeriesSettings.label." + FONT],
            POLAR_FONT_FIELDS = PIE_FONT_FIELDS.concat([COMMON_AXIS_SETTINGS + ".label." + FONT, COMMON_AXIS_SETTINGS + ".title." + FONT]),
            CHART_FONT_FIELDS = POLAR_FONT_FIELDS.concat(["crosshair.label." + FONT]),
            chartToFontFieldsMap = {
                pie: PIE_FONT_FIELDS,
                chart: CHART_FONT_FIELDS,
                polar: POLAR_FONT_FIELDS
            };
        viz.charts = viz.charts || {};
        viz.charts.ThemeManager = viz.core.BaseThemeManager.inherit(function() {
            var ctor = function(options, themeGroupName) {
                    var that = this,
                        themeObj;
                    that.callBase.apply(that, arguments);
                    options = options || {};
                    that._userOptions = options;
                    that._mergeAxisTitleOptions = [];
                    that._themeSection = themeGroupName;
                    that._fontFields = chartToFontFieldsMap[themeGroupName];
                    that._IE8 = DX.browser.msie && DX.browser.version < 9;
                    themeObj = options.theme && _findTheme(_isString(options.theme) ? options.theme : options.theme.name) || {};
                    that.palette = new Palette(options.palette, {
                        stepHighlight: HIGHLIGHTING_STEP,
                        theme: themeObj.name
                    });
                    that._callback = $.noop
                };
            var dispose = function() {
                    var that = this;
                    that.palette.dispose();
                    that.palette = that._userOptions = that._mergedSettings = null;
                    return that.callBase.apply(that, arguments)
                };
            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 _isString(options) ? {text: options} : options
                };
            var processAxisOptions = function(axisOptions) {
                    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 (_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 = _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) {
                        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"),
                            isLine = ~type.indexOf("line"),
                            isArea = ~type.indexOf("area"),
                            isBubble = type === "bubble",
                            mainSeriesColor,
                            resolveLabelsOverlapping = this.getOptions("resolveLabelsOverlapping"),
                            resolveLabelOverlapping = this.getOptions("resolveLabelOverlapping"),
                            containerBackgroundColor = this.getOptions("containerBackgroundColor"),
                            seriesVisibility;
                        if (isBar || isBubble) {
                            userOptions = $.extend(true, {}, userCommonSettings, userCommonSettings[type], userOptions);
                            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.widgetType = this._themeSection.split(".").slice(-1)[0];
                        settings.containerBackgroundColor = containerBackgroundColor;
                        if (settings.widgetType !== "pie")
                            mainSeriesColor = settings.color || palette.getNextColor();
                        else
                            mainSeriesColor = function() {
                                return palette.getNextColor()
                            };
                        settings.mainSeriesColor = mainSeriesColor;
                        settings._IE8 = this._IE8;
                        settings.resolveLabelOverlapping = resolveLabelOverlapping;
                        settings.resolveLabelsOverlapping = resolveLabelsOverlapping;
                        if (settings.label && (isLine || isArea && type !== "rangearea" || type === "scatter"))
                            settings.label.position = "outside";
                        return settings
                    },
                    pieSegment: function(name, seriesSettings, segmentSettings) {
                        var settings = $.extend(true, {}, seriesSettings, segmentSettings),
                            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 : _isDefined(userOptions) ? {enabled: !!userOptions} : {};
                        return mergeOptions.call(this, name, userOptions)
                    }
                };
            return {
                    _themeSection: "chart",
                    ctor: ctor,
                    dispose: dispose,
                    resetPalette: resetPalette,
                    getOptions: function(name) {
                        return (applyParticularTheme[name] || applyParticularTheme.base).apply(this, arguments)
                    },
                    refresh: function() {
                        this._mergedSettings = {};
                        return this.callBase.apply(this, arguments)
                    },
                    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 createThemeManager = function(options, groupName) {
                    return new charts.ThemeManager(options, groupName)
                };
            var createTracker = function(options, name) {
                    return name === "dxPieChart" ? new charts.PieTracker(options) : new charts.ChartTracker(options)
                };
            var createTitle = function(renderer, options, group) {
                    return new charts.ChartTitle(renderer, options, group)
                };
            var createChartLayoutManager = function(options) {
                    return new charts.LayoutManager(options)
                };
            var createCrosshair = function(renderer, options, params, group) {
                    return new charts.Crosshair(renderer, options, params, group)
                };
            return {
                    createSeriesFamily: createSeriesFamily,
                    createThemeManager: createThemeManager,
                    createTracker: createTracker,
                    createChartLayoutManager: createChartLayoutManager,
                    createTitle: createTitle,
                    createCrosshair: createCrosshair,
                    createScrollBar: function(renderer, group) {
                        return new DevExpress.viz.charts.ScrollBar(renderer, group)
                    }
                }
        }()
    })(jQuery, DevExpress);
    /*! Module viz-core, file baseWidget.js */
    (function(DX, $, undefined) {
        var core = DX.viz.core,
            _windowResizeCallbacks = DX.utils.windowResizeCallbacks,
            _Number = Number,
            _stringFormat = DX.utils.stringFormat,
            _isFunction = DX.utils.isFunction,
            _parseScalar = core.utils.parseScalar,
            OPTION_RTL_ENABLED = "rtlEnabled",
            OPTION_LOADING_INDICATOR = "loadingIndicator";
        function defaultIncidentOccured(options) {
            var args = [options.id];
            args.push.apply(args, options.args || []);
            DX.log.apply(null, args)
        }
        function getTrue() {
            return true
        }
        function getFalse() {
            return false
        }
        function areCanvasesDifferent(canvas1, canvas2) {
            return !(canvas1.width === canvas2.width && canvas1.height === canvas2.height && canvas1.left === canvas2.left && canvas1.top === canvas2.top && canvas1.right === canvas2.right && canvas1.bottom === canvas2.bottom)
        }
        function createResizeHandler(callback) {
            var $window = $(window),
                width,
                height,
                timeout;
            handler.dispose = function() {
                clearTimeout(timeout);
                return this
            };
            return handler;
            function handler() {
                width = $window.width();
                height = $window.height();
                clearTimeout(timeout);
                timeout = setTimeout(trigger, 100)
            }
            function trigger() {
                $window.width() === width && $window.height() === height && callback()
            }
        }
        core.DEBUG_createResizeHandler = createResizeHandler;
        core.BaseWidget = DX.DOMComponent.inherit({
            _eventsMap: {
                onIncidentOccurred: {
                    name: 'incidentOccured',
                    deprecated: 'incidentOccured',
                    deprecatedContext: $.noop,
                    deprecatedArgs: function(arg) {
                        return [arg.target]
                    }
                },
                onDrawn: {
                    name: 'drawn',
                    deprecated: 'drawn',
                    deprecatedContext: $.noop,
                    deprecatedArgs: function(arg) {
                        return [arg.component]
                    }
                },
                incidentOccured: {newName: 'onIncidentOccurred'},
                drawn: {newName: 'onDrawn'},
                onTooltipShown: {name: 'tooltipShown'},
                onTooltipHidden: {name: 'tooltipHidden'},
                onLoadingIndicatorReady: {name: "loadingIndicatorReady"}
            },
            _setDeprecatedOptions: function() {
                this.callBase.apply(this, arguments);
                $.extend(this._deprecatedOptions, {
                    incidentOccured: {
                        since: '14.2',
                        message: "Use the 'onIncidentOccurred' option instead"
                    },
                    drawn: {
                        since: '14.2',
                        message: "Use the 'onDrawn' option instead"
                    }
                })
            },
            _setDefaultOptions: function() {
                this.callBase.apply(this, arguments);
                this.option({incidentOccured: defaultIncidentOccured})
            },
            _init: function() {
                var that = this;
                that.callBase.apply(that, arguments);
                that._themeManager = that._createThemeManager();
                that._themeManager.setCallback(function() {
                    that._handleThemeOptions()
                });
                that._renderer = new DX.viz.renderers.Renderer({cssClass: that._rootClassPrefix + " " + that._rootClass});
                that._initIncidentOccured();
                that._renderVisibilityChange();
                that._initEventTrigger();
                that._initTooltip();
                that._initCore();
                that._setThemeAndRtl();
                that._initSize();
                that._setupResizeHandler();
                that._initLoadingIndicator()
            },
            _initTooltip: function() {
                this._tooltip = new core.Tooltip({
                    cssClass: this._rootClassPrefix + "-tooltip",
                    eventTrigger: this._eventTrigger
                })
            },
            _getAnimationOptions: $.noop,
            _initSize: function() {
                var canvas = null;
                if (this._isContainerVisible()) {
                    canvas = this._calculateCanvas();
                    if (canvas)
                        this._updateSize(canvas, true)
                }
                if (!canvas)
                    this._setHiddenState()
            },
            _setHiddenState: function() {
                var that = this;
                that._clean = that._render = $.noop;
                that._canvas = null;
                that._incidentOccured('W2001', [that.NAME])
            },
            _setVisibleState: function() {
                delete this._clean;
                delete this._render
            },
            _updateSize: function(canvas, isDrawRequired) {
                var that = this;
                that._renderer.resize(canvas.width, canvas.height);
                isDrawRequired && that._renderer.draw(that._$element[0]);
                that._canvas = canvas;
                that._applySize();
                that._updateLoadingIndicatorCanvas()
            },
            _updateCanvasAndResize: function() {
                var that = this,
                    canvas = that._calculateCanvas();
                if (canvas)
                    if (areCanvasesDifferent(canvas, that._canvas) || that.__forceRender) {
                        that._updateSize(canvas);
                        that._resize()
                    }
                return canvas
            },
            render: function() {
                var that = this,
                    canvas,
                    visible = that._isContainerVisible();
                if (that._canvas) {
                    if (visible)
                        canvas = that._updateCanvasAndResize();
                    if (!canvas) {
                        that._clean();
                        that._renderer.clear();
                        that._setHiddenState()
                    }
                }
                else {
                    if (visible) {
                        canvas = that._calculateCanvas();
                        if (canvas) {
                            that._setVisibleState();
                            that._updateSize(canvas, true);
                            that._render()
                        }
                    }
                    if (!canvas)
                        that._setHiddenState()
                }
            },
            _handleResize: function() {
                if (this._canvas)
                    this._updateCanvasAndResize()
            },
            _dispose: function() {
                var that = this;
                that.callBase.apply(that, arguments);
                that._removeResizeHandler();
                that._eventTrigger.dispose();
                that._disposeCore();
                that._disposeLoadingIndicator();
                that._renderer.dispose();
                that._tooltip && that._tooltip.dispose();
                that._themeManager.dispose();
                that._themeManager = that._renderer = that._eventTrigger = that._tooltip = null
            },
            _initEventTrigger: function() {
                var that = this;
                that._eventTrigger = createEventTrigger(that._eventsMap, function(name, deprecatedName) {
                    var data = {callback: that._createActionByOption(name)};
                    that._suppressDeprecatedWarnings();
                    if (that.option(name) === undefined)
                        data.deprecatedCallback = that.option(deprecatedName);
                    that._resumeDeprecatedWarnings();
                    return data
                })
            },
            _isContainerVisible: function() {
                return this._$element.is(':visible')
            },
            _calculateCanvas: function() {
                var that = this,
                    size = that.option('size') || {},
                    margin = that.option('margin') || {},
                    defaultCanvas = that._getDefaultSize() || {},
                    canvas = {};
                if (size.width <= 0 || size.height <= 0)
                    canvas = null;
                else {
                    canvas.width = size.width > 0 ? _Number(size.width) : that._$element.width() || defaultCanvas.width;
                    canvas.height = size.height > 0 ? _Number(size.height) : that._$element.height() || defaultCanvas.height;
                    canvas.left = margin.left > 0 ? _Number(margin.left) : defaultCanvas.left || 0;
                    canvas.top = margin.top > 0 ? _Number(margin.top) : defaultCanvas.top || 0;
                    canvas.right = margin.right > 0 ? _Number(margin.right) : defaultCanvas.right || 0;
                    canvas.bottom = margin.bottom > 0 ? _Number(margin.bottom) : defaultCanvas.bottom || 0;
                    canvas = canvas.width - canvas.left - canvas.right > 0 && canvas.height - canvas.top - canvas.bottom > 0 ? canvas : null
                }
                return canvas
            },
            DEBUG_getCanvas: function() {
                return this._canvas
            },
            DEBUG_getEventTrigger: function() {
                return this._eventTrigger
            },
            _getOption: function(name, isScalar) {
                var theme = this._themeManager.theme(name),
                    option = this.option(name);
                return isScalar ? option !== undefined ? option : theme : $.extend(true, {}, theme, option)
            },
            _setupResizeHandler: function() {
                if (_parseScalar(this._getOption('redrawOnResize', true), true))
                    this._addResizeHandler();
                else
                    this._removeResizeHandler()
            },
            _addResizeHandler: function() {
                var that = this;
                if (!that._resizeHandler) {
                    that._resizeHandler = createResizeHandler(function() {
                        that._handleResize()
                    });
                    _windowResizeCallbacks.add(that._resizeHandler)
                }
            },
            _removeResizeHandler: function() {
                if (this._resizeHandler) {
                    _windowResizeCallbacks.remove(this._resizeHandler);
                    this._resizeHandler.dispose();
                    this._resizeHandler = null
                }
            },
            _optionChanged: function(args) {
                var that = this;
                if (!that._eventTrigger.update(args.name))
                    switch (args.name) {
                        case'size':
                        case'margin':
                            that.render();
                            break;
                        case'redrawOnResize':
                            that._setupResizeHandler();
                            break;
                        case OPTION_LOADING_INDICATOR:
                            that._handleLoadingIndicatorOptionChanged();
                            break;
                        case"theme":
                        case OPTION_RTL_ENABLED:
                            that._setThemeAndRtl();
                            break;
                        case"encodeHtml":
                        case"pathModified":
                            that._handleThemeOptions();
                            break;
                        case"tooltip":
                            that._setTooltipOptions();
                            break;
                        default:
                            that._invalidate();
                            that.callBase.apply(that, arguments)
                    }
            },
            _handleThemeOptions: function() {
                var that = this,
                    options = {
                        rtl: that.option(OPTION_RTL_ENABLED),
                        encodeHtml: that.option("encodeHtml"),
                        pathModified: that.option("pathModified"),
                        animation: that._getAnimationOptions()
                    };
                that._renderer.setOptions(options);
                that._setTooltipRendererOptions(options);
                that._setTooltipOptions();
                that._updateLoadingIndicatorOptions();
                that._handleThemeOptionsCore()
            },
            _handleThemeOptionsCore: function() {
                this._initialized && this._refresh()
            },
            _visibilityChanged: function() {
                this.render()
            },
            _initIncidentOccured: function() {
                var that = this;
                that._incidentOccured = function(errorOrWarningId, options) {
                    that._eventTrigger('incidentOccured', {target: {
                            id: errorOrWarningId,
                            type: errorOrWarningId[0] === 'E' ? 'error' : 'warning',
                            args: options,
                            text: _stringFormat.apply(null, [DX.ERROR_MESSAGES[errorOrWarningId]].concat(options ? options.slice(0) : [])),
                            widget: that.NAME,
                            version: DX.VERSION
                        }})
                }
            },
            _setThemeAndRtl: function() {
                this._themeManager.setTheme(this.option("theme"), this.option(OPTION_RTL_ENABLED))
            },
            _setTooltipRendererOptions: function(options) {
                this._tooltip.setRendererOptions(options)
            },
            _setTooltipOptions: function() {
                this._tooltip.update(this._getOption("tooltip"))
            },
            _initLoadingIndicator: function() {
                if (this._getOption(OPTION_LOADING_INDICATOR).show) {
                    this.showLoadingIndicator();
                    this._loadIndicator.forceShow()
                }
            },
            _handleLoadingIndicatorOptionChanged: function() {
                var that = this;
                if (!that._skipOptionChanged) {
                    that._updateLoadingIndicatorOptions();
                    if (that._getOption(OPTION_LOADING_INDICATOR).show)
                        that.showLoadingIndicator();
                    else
                        that.hideLoadingIndicator()
                }
            },
            _updateLoadingIndicatorCanvas: function() {
                this._loadIndicator && this._canvas && this._loadIndicator.applyCanvas(this._canvas)
            },
            _updateLoadingIndicatorOptions: function() {
                this._loadIndicator && this._loadIndicator.applyOptions(this._getOption(OPTION_LOADING_INDICATOR))
            },
            _endLoading: function(complete) {
                if (this._loadIndicator) {
                    this._resetIsReady();
                    this._loadIndicator.endLoading(complete)
                }
                else
                    complete && complete()
            },
            _reappendLoadingIndicator: function() {
                this._loadIndicator && this._loadIndicator.toForeground()
            },
            _disposeLoadingIndicator: function() {
                if (this._loadIndicator) {
                    this._loadIndicator.dispose();
                    this._loadIndicator = null
                }
            },
            _scheduleLoadingIndicatorHiding: function() {
                this._loadIndicator && this._loadIndicator.scheduleHiding()
            },
            _fulfillLoadingIndicatorHiding: function() {
                this._loadIndicator && this._loadIndicator.fulfillHiding() && this._toggleLoadingIndicatorState(false)
            },
            _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"')
            },
            _dataIsReady: getTrue,
            _resetIsReady: function() {
                this.isReady = getFalse
            },
            _drawn: function() {
                var that = this;
                that.isReady = getFalse;
                that._dataIsReady() && that._renderer.onEndAnimation(function() {
                    that.isReady = getTrue
                });
                that._eventTrigger('drawn', {})
            },
            _toggleLoadingIndicatorState: function(state) {
                if (Boolean(this._getOption(OPTION_LOADING_INDICATOR).show) !== state) {
                    this._skipOptionChanged = true;
                    this.option(OPTION_LOADING_INDICATOR, {show: state});
                    this._skipOptionChanged = false
                }
            },
            _handleLoadingIndicatorShown: function() {
                this._tooltip.hide()
            },
            showLoadingIndicator: function() {
                var that = this;
                if (!that._loadIndicator) {
                    that._loadIndicator = new core.LoadIndicator({
                        container: that._$element,
                        eventTrigger: that._eventTrigger
                    });
                    that._updateLoadingIndicatorCanvas();
                    that._updateLoadingIndicatorOptions()
                }
                that._toggleLoadingIndicatorState(true);
                that._loadIndicator.show();
                that._handleLoadingIndicatorShown()
            },
            hideLoadingIndicator: function() {
                var that = this;
                if (that._loadIndicator) {
                    that._toggleLoadingIndicatorState(false);
                    that._loadIndicator.hide()
                }
            },
            svg: function() {
                return this._normalizeHtml(this._renderer.svg())
            },
            isReady: getFalse
        });
        function createEventTrigger(eventsMap, callbackGetter) {
            var triggers = {},
                timers = {};
            $.each(eventsMap, function(name, info) {
                if (info.name)
                    createItem(name)
            });
            trigger.update = function(name) {
                var eventInfo = eventsMap[name];
                if (eventInfo)
                    createItem(eventInfo.newName || name);
                return !!eventInfo
            };
            trigger.dispose = function() {
                $.each(timers, function(timer) {
                    clearTimeout(timer)
                });
                eventsMap = callbackGetter = triggers = timers = null
            };
            return trigger;
            function trigger(eventName, arg, complete) {
                triggers[eventName](arg, complete)
            }
            function createItem(name) {
                var eventInfo = eventsMap[name],
                    data = callbackGetter(name, eventInfo.deprecated);
                triggers[eventInfo.name] = createCallback(data.callback, _isFunction(data.deprecatedCallback) && data.deprecatedCallback, eventInfo.deprecatedContext, eventInfo.deprecatedArgs)
            }
            function createCallback(callback, deprectatedCallback, deprecatedContext, deprecatedArgs) {
                return function(arg, complete) {
                        var timer = setTimeout(function() {
                                callback(arg);
                                deprectatedCallback && deprectatedCallback.apply(deprecatedContext(arg), deprecatedArgs(arg));
                                complete && complete();
                                delete timers[timer]
                            });
                        timers[timer] = 1
                    }
            }
        }
        core.DEBUG_createEventTrigger = createEventTrigger
    })(DevExpress, jQuery);
    /*! Module viz-core, file CoreFactory.js */
    (function(DX, undefined) {
        var viz = DX.viz,
            core = viz.core,
            seriesNS = core.series;
        core.CoreFactory = {
            createSeries: function(renderSettings, options) {
                return new seriesNS.Series(renderSettings, options)
            },
            createPoint: function(series, data, options) {
                return new seriesNS.points.Point(series, data, options)
            },
            createLabel: function() {
                return new core.series.points.Label
            },
            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)
            },
            createTickManager: function(types, data, options) {
                return new core.tickManager.TickManager(types, data, options)
            },
            createLegend: function(settings) {
                return new core.Legend(settings)
            },
            createSeriesFamily: function(options) {
                return new seriesNS.helpers.SeriesFamily(options)
            },
            createDataValidator: function(data, groups, incidentOccured, dataPrepareOptions) {
                return new core.DataValidator(data, groups, incidentOccured, dataPrepareOptions)
            }
        }
    })(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 viz = DX.viz,
            vizUtils = viz.core.utils,
            isDefined = DX.utils.isDefined,
            DEFAULT_MARGIN = 10;
        function parseMargins(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
            }
        }
        function parseAlignments(options) {
            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'
        }
        function ChartTitle(renderer, options, group) {
            var that = this;
            that.update(options);
            that.renderer = renderer;
            that.titleGroup = group
        }
        viz.charts.ChartTitle = ChartTitle;
        ChartTitle.prototype = {
            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) {
                var that = this;
                if (options) {
                    parseAlignments(options);
                    that.horizontalAlignment = options.horizontalAlignment;
                    that.verticalAlignment = options.verticalAlignment;
                    parseMargins(options);
                    that.margin = options.margin;
                    that.options = options
                }
            },
            _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(size) {
                var that = this,
                    titleOptions = that.options,
                    renderer = that.renderer;
                if (!titleOptions.text)
                    return that;
                size && that.setSize(size);
                that.changedMargin = null;
                if (!that.innerTitleGroup) {
                    that.innerTitleGroup = renderer.g();
                    that.clipRect = that.createClipRect();
                    that.titleGroup && that.clipRect && that.titleGroup.attr({clipId: that.clipRect.id})
                }
                else
                    that.innerTitleGroup.clear();
                that.innerTitleGroup.append(that.titleGroup);
                that.title = renderer.text(titleOptions.text, 0, 0).css(vizUtils.patchFontOptions(titleOptions.font)).attr({align: that.horizontalAlignment}).append(that.innerTitleGroup);
                that.title.text = titleOptions.text;
                that._correctTitleLength();
                that._setClipRectSettings();
                return that
            },
            _correctTitleLength: function() {
                var that = this,
                    text = that.title.text,
                    lineLength,
                    box;
                that.title.attr({text: text});
                that._setBoundingRect();
                box = that.getLayoutOptions();
                if (that._width > box.width || text.indexOf("
") !== -1)
                    return;
                lineLength = text.length * that._width / box.width;
                that.title.attr({text: text.substr(0, ~~lineLength - 1 - 3) + "..."});
                that.title.setTitle(text);
                that._setBoundingRect()
            },
            changeSize: function(size) {
                var that = this,
                    margin = $.extend(true, {}, that.margin);
                if (margin.top + margin.bottom < size.height) {
                    if (that.innerTitleGroup) {
                        that.options._incidentOccured("W2103");
                        that.innerTitleGroup.dispose();
                        that.innerTitleGroup = null
                    }
                    if (that.clipRect) {
                        that.clipRect.dispose();
                        that.clipRect = null
                    }
                }
                else if (size.height > 0) {
                    vizUtils.decreaseGaps(margin, ["top", "bottom"], size.height);
                    size.height && (that.changedMargin = margin)
                }
                that._correctTitleLength();
                that._setBoundingRect();
                that._setClipRectSettings();
                return that
            },
            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
            },
            getBBox: function() {
                var bbox = $.extend({}, this.getLayoutOptions());
                bbox.x = this._x;
                bbox.y = this._y;
                return bbox
            },
            setSize: function(size) {
                this._width = size.width || this._width;
                return this
            },
            shift: function(x, y) {
                var that = this,
                    box = that.getLayoutOptions();
                that._x = x;
                that._y = y;
                x -= box.x;
                y -= box.y;
                that.innerTitleGroup && that.innerTitleGroup.move(x, y);
                that.clipRect && that.clipRect.attr({
                    translateX: x,
                    translateY: y
                });
                return that
            },
            createClipRect: function() {
                if (isDefined(this.options.placeholderSize))
                    return this.renderer.clipRect(0, 0, 0, 0)
            },
            _setClipRectSettings: function() {
                var bbox = this.getLayoutOptions(),
                    clipRect = this.clipRect;
                if (clipRect)
                    clipRect.attr({
                        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 axesConstants.js */
    (function($, DX, undefined) {
        var _map = $.map;
        function getFormatObject(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 formatObject
        }
        DX.viz.charts.axes = {};
        DX.viz.charts.axes.constants = {
            logarithmic: "logarithmic",
            discrete: "discrete",
            numeric: "numeric",
            left: "left",
            right: "right",
            top: "top",
            bottom: "bottom",
            center: "center",
            canvasPositionPrefix: "canvas_position_",
            canvasPositionTop: "canvas_position_top",
            canvasPositionBottom: "canvas_position_bottom",
            canvasPositionLeft: "canvas_position_left",
            canvasPositionRight: "canvas_position_right",
            canvasPositionStart: "canvas_position_start",
            canvasPositionEnd: "canvas_position_end",
            horizontal: "horizontal",
            vertical: "vertical",
            halfTickLength: 4,
            convertTicksToValues: function(ticks) {
                return _map(ticks || [], function(item) {
                        return item.value
                    })
            },
            convertValuesToTicks: function(values) {
                return _map(values || [], function(item) {
                        return {value: item}
                    })
            },
            validateOverlappingMode: function(mode) {
                return mode !== "ignore" ? "enlargeTickInterval" : "ignore"
            },
            formatLabel: function(value, options, axisMinMax) {
                var formatObject = getFormatObject(value, options, axisMinMax);
                return $.isFunction(options.customizeText) ? options.customizeText.call(formatObject, formatObject) : formatObject.valueText
            },
            formatHint: function(value, options, axisMinMax) {
                var formatObject = getFormatObject(value, options, axisMinMax);
                return $.isFunction(options.customizeHint) ? options.customizeHint.call(formatObject, formatObject) : undefined
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-charts, file xyAxes.js */
    (function($, DX, undefined) {
        var viz = DX.viz,
            core = viz.core,
            axes = viz.charts.axes,
            constants = axes.constants,
            _abs = Math.abs,
            _extend = $.extend,
            CANVAS_POSITION_PREFIX = constants.canvasPositionPrefix,
            TOP = constants.top,
            BOTTOM = constants.bottom,
            LEFT = constants.left,
            RIGHT = constants.right,
            CENTER = constants.center;
        axes.xyAxes = {};
        axes.xyAxes.linear = {
            _getSharpParam: function(oposite) {
                return this._isHorizontal ^ oposite ? "h" : "v"
            },
            _createAxisElement: function() {
                var axisCoord = this._axisPosition,
                    canvas = this._getCanvasStartEnd(),
                    points = this._isHorizontal ? [canvas.start, axisCoord, canvas.end, axisCoord] : [axisCoord, canvas.start, axisCoord, canvas.end];
                return this._renderer.path(points, "line")
            },
            _getTranslatedCoord: function(value, offset) {
                return this._translator.translate(value, offset)
            },
            _getCanvasStartEnd: function() {
                return {
                        start: this._translator.translateSpecialCase(constants.canvasPositionStart),
                        end: this._translator.translateSpecialCase(constants.canvasPositionEnd)
                    }
            },
            _getScreenDelta: function() {
                return _abs(this._translator.translateSpecialCase(constants.canvasPositionStart) - this._translator.translateSpecialCase(constants.canvasPositionEnd))
            },
            _initAxisPositions: function() {
                var that = this,
                    position = that._options.position,
                    delta = 0;
                if (that.delta)
                    delta = that.delta[position] || 0;
                that._axisPosition = that._additionalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + position) + delta
            },
            _drawTitle: function() {
                var that = this,
                    options = that._options,
                    titleOptions = options.title,
                    attr = {
                        opacity: titleOptions.opacity,
                        align: CENTER
                    };
                if (!titleOptions.text || !that._axisTitleGroup)
                    return;
                that._title = that._renderer.text(titleOptions.text, 0, 0).css(core.utils.patchFontOptions(titleOptions.font)).attr(attr).append(that._axisTitleGroup)
            },
            _adjustConstantLineLabels: function() {
                var that = this,
                    options = that._options,
                    isHorizontal = that._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
                    },
                    paddingTopBottom,
                    paddingLeftRight,
                    labelVerticalAlignment,
                    labelHorizontalAlignment,
                    labelIsInside,
                    labelHeight,
                    labelWidth,
                    delta = 0;
                if (labels === undefined && lines === undefined)
                    return;
                for (i = 0; i < labels.length; i++) {
                    x = y = 0;
                    linesOptions = options.constantLines[i];
                    paddingTopBottom = linesOptions.paddingTopBottom;
                    paddingLeftRight = linesOptions.paddingLeftRight;
                    labelOptions = linesOptions.label;
                    labelVerticalAlignment = labelOptions.verticalAlignment;
                    labelHorizontalAlignment = labelOptions.horizontalAlignment;
                    labelIsInside = labelOptions.position === "inside";
                    label = labels[i];
                    if (label !== null) {
                        line = lines[i];
                        box = label.getBBox();
                        lineBox = line.getBBox();
                        labelHeight = box.height;
                        labelWidth = box.width;
                        if (isHorizontal)
                            if (labelIsInside) {
                                if (labelHorizontalAlignment === LEFT)
                                    x -= paddingLeftRight;
                                else
                                    x += paddingLeftRight;
                                switch (labelVerticalAlignment) {
                                    case CENTER:
                                        y += lineBox.y + lineBox.height / 2 - box.y - labelHeight / 2;
                                        break;
                                    case BOTTOM:
                                        y += lineBox.y + lineBox.height - box.y - labelHeight - paddingTopBottom;
                                        break;
                                    default:
                                        y += lineBox.y - box.y + paddingTopBottom;
                                        break
                                }
                            }
                            else if (labelVerticalAlignment === BOTTOM) {
                                delta = that.delta && that.delta[BOTTOM] || 0;
                                y += paddingTopBottom - box.y + that._additionalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + BOTTOM) + delta;
                                if (padding[BOTTOM] < labelHeight + paddingTopBottom)
                                    padding[BOTTOM] = labelHeight + paddingTopBottom
                            }
                            else {
                                delta = that.delta && that.delta[TOP] || 0;
                                y -= paddingTopBottom + box.y + labelHeight - that._additionalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + TOP) - delta;
                                if (padding[TOP] < paddingTopBottom + labelHeight)
                                    padding[TOP] = paddingTopBottom + labelHeight
                            }
                        else if (labelIsInside) {
                            switch (labelHorizontalAlignment) {
                                case CENTER:
                                    x += lineBox.x + labelWidth / 2 - box.x - labelWidth / 2;
                                    break;
                                case RIGHT:
                                    x -= paddingLeftRight;
                                    break;
                                default:
                                    x += paddingLeftRight;
                                    break
                            }
                            if (labelVerticalAlignment === BOTTOM)
                                y += lineBox.y - box.y + paddingTopBottom;
                            else
                                y += lineBox.y - box.y - labelHeight - paddingTopBottom
                        }
                        else {
                            y += lineBox.y + lineBox.height / 2 - box.y - labelHeight / 2;
                            if (labelHorizontalAlignment === RIGHT) {
                                x += paddingLeftRight;
                                if (padding[RIGHT] < paddingLeftRight + labelWidth)
                                    padding[RIGHT] = paddingLeftRight + labelWidth
                            }
                            else {
                                x -= paddingLeftRight;
                                if (padding[LEFT] < paddingLeftRight + labelWidth)
                                    padding[LEFT] = paddingLeftRight + labelWidth
                            }
                        }
                        label.move(x, y)
                    }
                }
                that.padding = padding
            },
            _checkAlignmentConstantLineLabels: function(labelOptions) {
                var position = labelOptions.position,
                    verticalAlignment = (labelOptions.verticalAlignment || "").toLowerCase(),
                    horizontalAlignment = (labelOptions.horizontalAlignment || "").toLowerCase();
                if (this._isHorizontal)
                    if (position === "outside") {
                        verticalAlignment = verticalAlignment === BOTTOM ? BOTTOM : TOP;
                        horizontalAlignment = CENTER
                    }
                    else {
                        verticalAlignment = verticalAlignment === CENTER ? CENTER : verticalAlignment === BOTTOM ? BOTTOM : TOP;
                        horizontalAlignment = horizontalAlignment === LEFT ? LEFT : RIGHT
                    }
                else if (position === "outside") {
                    verticalAlignment = CENTER;
                    horizontalAlignment = horizontalAlignment === LEFT ? LEFT : RIGHT
                }
                else {
                    verticalAlignment = verticalAlignment === BOTTOM ? BOTTOM : TOP;
                    horizontalAlignment = horizontalAlignment === RIGHT ? RIGHT : horizontalAlignment === CENTER ? CENTER : LEFT
                }
                labelOptions.verticalAlignment = verticalAlignment;
                labelOptions.horizontalAlignment = horizontalAlignment
            },
            _getConstantLineLabelsCoords: function(value, lineLabelOptions) {
                var that = this,
                    additionalTranslator = that._additionalTranslator,
                    align = CENTER,
                    x = value,
                    y = value;
                if (that._isHorizontal)
                    y = additionalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + lineLabelOptions.verticalAlignment);
                else
                    x = additionalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + lineLabelOptions.horizontalAlignment);
                switch (lineLabelOptions.horizontalAlignment) {
                    case LEFT:
                        align = !that._isHorizontal && lineLabelOptions.position === "inside" ? LEFT : RIGHT;
                        break;
                    case CENTER:
                        align = CENTER;
                        break;
                    case RIGHT:
                        align = !that._isHorizontal && lineLabelOptions.position === "inside" ? RIGHT : LEFT;
                        break
                }
                return {
                        x: x,
                        y: y,
                        align: align
                    }
            },
            _getAdjustedStripLabelCoords: function(stripOptions, label, rect) {
                var x = 0,
                    y = 0,
                    horizontalAlignment = stripOptions.label.horizontalAlignment,
                    verticalAlignment = stripOptions.label.verticalAlignment,
                    box = label.getBBox(),
                    rectBox = rect.getBBox();
                if (horizontalAlignment === LEFT)
                    x += stripOptions.paddingLeftRight;
                else if (horizontalAlignment === RIGHT)
                    x -= stripOptions.paddingLeftRight;
                if (verticalAlignment === TOP)
                    y += rectBox.y - box.y + stripOptions.paddingTopBottom;
                else if (verticalAlignment === CENTER)
                    y += rectBox.y + rectBox.height / 2 - box.y - box.height / 2;
                else if (verticalAlignment === BOTTOM)
                    y -= stripOptions.paddingTopBottom;
                return {
                        x: x,
                        y: y
                    }
            },
            _adjustTitle: function() {
                var that = this,
                    options = that._options,
                    position = options.position,
                    title = that._title,
                    margin = options.title.margin,
                    boxGroup,
                    boxTitle,
                    params,
                    centerPosition = that._translator.translateSpecialCase(CANVAS_POSITION_PREFIX + CENTER),
                    axisElementsGroup = that._axisElementsGroup,
                    heightTitle,
                    axisPosition = that._axisPosition,
                    noLabels;
                if (!title || !axisElementsGroup)
                    return;
                boxTitle = title.getBBox();
                boxGroup = axisElementsGroup.getBBox();
                noLabels = boxGroup.isEmpty;
                heightTitle = boxTitle.height;
                if (that._isHorizontal)
                    if (position === BOTTOM)
                        params = {
                            y: (noLabels ? axisPosition : boxGroup.y + boxGroup.height) - boxTitle.y + margin,
                            x: centerPosition
                        };
                    else
                        params = {
                            y: (noLabels ? axisPosition : boxGroup.y) - heightTitle - boxTitle.y - margin,
                            x: centerPosition
                        };
                else {
                    if (position === LEFT)
                        params = {
                            x: (noLabels ? axisPosition : boxGroup.x) - heightTitle - boxTitle.y - margin,
                            y: centerPosition
                        };
                    else
                        params = {
                            x: (noLabels ? axisPosition : boxGroup.x + boxGroup.width) + heightTitle + boxTitle.y + margin,
                            y: centerPosition
                        };
                    params.rotate = options.position === LEFT ? 270 : 90
                }
                title.attr(params)
            },
            coordsIn: function(x, y) {
                var rect = this.getBoundingRect();
                return x >= rect.x && x <= rect.x + rect.width && y >= rect.y && y <= rect.y + rect.height
            },
            _getTicksOptions: function() {
                var options = this._options;
                return {
                        base: options.type === constants.logarithmic ? options.logarithmBase : undefined,
                        tickInterval: this._translator.getBusinessRange().stubData ? null : options.tickInterval,
                        gridSpacingFactor: options.axisDivisionFactor,
                        incidentOccured: options.incidentOccured,
                        setTicksAtUnitBeginning: options.setTicksAtUnitBeginning,
                        showMinorTicks: options.minorTick.visible || options.minorGrid.visible,
                        minorTickInterval: options.minorTickInterval,
                        minorTickCount: options.minorTickCount
                    }
            },
            _getOverlappingBehaviorOptions: function() {
                var that = this,
                    options = that._options,
                    getText = function() {
                        return ""
                    },
                    overlappingBehavior = options.label.overlappingBehavior ? _extend({}, options.label.overlappingBehavior) : null;
                if (overlappingBehavior) {
                    if (!that._isHorizontal)
                        overlappingBehavior.mode = constants.validateOverlappingMode(overlappingBehavior.mode);
                    if (overlappingBehavior.mode !== "rotate")
                        overlappingBehavior.rotationAngle = 0
                }
                if (!that._translator.getBusinessRange().stubData)
                    getText = function(value, labelOptions) {
                        return constants.formatLabel(value, labelOptions, {
                                min: options.min,
                                max: options.max
                            })
                    };
                return {
                        hasLabelFormat: that._hasLabelFormat,
                        labelOptions: options.label,
                        overlappingBehavior: overlappingBehavior,
                        isHorizontal: that._isHorizontal,
                        textOptions: that._textOptions,
                        textFontStyles: that._textFontStyles,
                        textSpacing: options.label.minSpacing,
                        getText: getText,
                        renderText: function(text, x, y, options) {
                            return that._renderer.text(text, x, y, options).append(that._renderer.root)
                        },
                        translate: function(value, useAdditionalTranslator) {
                            return useAdditionalTranslator ? that._additionalTranslator.translate(value) : that._translator.translate(value)
                        },
                        isInverted: that._translator.getBusinessRange().invert
                    }
            },
            _getSpiderCategoryOption: $.noop,
            _getMinMax: function() {
                return {
                        min: this._options.min,
                        max: this._options.max
                    }
            },
            _getStick: function() {
                return !this._options.valueMarginsEnabled
            },
            _getStripLabelCoords: function(stripLabelOptions, stripFrom, stripTo) {
                var that = this,
                    additionalTranslator = that._additionalTranslator,
                    isHorizontal = that._isHorizontal,
                    align = isHorizontal ? CENTER : LEFT,
                    x,
                    y;
                if (isHorizontal) {
                    if (stripLabelOptions.horizontalAlignment === CENTER) {
                        x = stripFrom + (stripTo - stripFrom) / 2;
                        align = CENTER
                    }
                    else if (stripLabelOptions.horizontalAlignment === LEFT) {
                        x = stripFrom;
                        align = LEFT
                    }
                    else if (stripLabelOptions.horizontalAlignment === RIGHT) {
                        x = stripTo;
                        align = RIGHT
                    }
                    y = additionalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + stripLabelOptions.verticalAlignment)
                }
                else {
                    x = additionalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + stripLabelOptions.horizontalAlignment);
                    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 {
                        x: x,
                        y: y,
                        align: align
                    }
            },
            _getTranslatedValue: function(value, y, offset) {
                return {
                        x: this._translator.translate(value, offset),
                        y: y
                    }
            },
            _getSkippedCategory: function() {
                var that = this,
                    options = that._options,
                    categories = that._translator.getVisibleCategories() || that._translator.getBusinessRange().categories,
                    categoryToSkip;
                if (categories && !!that._tickOffset && !options.valueMarginsEnabled)
                    categoryToSkip = options.inverted ? categories[0] : categories[categories.length - 1];
                return categoryToSkip
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-charts, file polarAxes.js */
    (function($, DX, undefined) {
        var viz = DX.viz,
            core = viz.core,
            utils = DX.utils,
            constants = viz.charts.axes.constants,
            _math = Math,
            _abs = _math.abs,
            _round = _math.round,
            _extend = $.extend,
            _noop = $.noop,
            _map = $.map,
            HALF_PI_ANGLE = 90;
        viz.charts.axes.polarAxes = {};
        function getPolarQuarter(angle) {
            var quarter;
            angle = utils.normalizeAngle(angle);
            if (angle >= 315 && angle <= 360 || angle < 45 && angle >= 0)
                quarter = 1;
            else if (angle >= 45 && angle < 135)
                quarter = 2;
            else if (angle >= 135 && angle < 225)
                quarter = 3;
            else if (angle >= 225 && angle < 315)
                quarter = 4;
            return quarter
        }
        viz.charts.axes.polarAxes.circular = {
            _overlappingBehaviorType: "circular",
            _createAxisElement: function() {
                var additionalTranslator = this._additionalTranslator;
                return this._renderer.circle(additionalTranslator.getCenter().x, additionalTranslator.getCenter().y, additionalTranslator.getRadius())
            },
            _setBoundingRect: function() {
                this.boundingRect = {
                    width: 0,
                    height: 0
                }
            },
            _getTicksOptions: viz.charts.axes.xyAxes.linear._getTicksOptions,
            _getOverlappingBehaviorOptions: function() {
                var that = this,
                    additionalTranslator = that._additionalTranslator,
                    startAngle = additionalTranslator.getStartAngle(),
                    options = viz.charts.axes.xyAxes.linear._getOverlappingBehaviorOptions.call(that),
                    translator = that._translator,
                    indentFromAxis = that._options.label.indentFromAxis || 0;
                if (options.overlappingBehavior)
                    options.overlappingBehavior = {mode: constants.validateOverlappingMode(options.overlappingBehavior.mode)};
                options.translate = function(value) {
                    return core.utils.convertPolarToXY(additionalTranslator.getCenter(), startAngle, translator.translate(value), additionalTranslator.translate(constants.canvasPositionBottom))
                };
                options.addMinMax = {min: true};
                options.isInverted = translator.getBusinessRange().invert;
                options.circularRadius = additionalTranslator.getRadius() + indentFromAxis;
                options.circularStartAngle = options.circularEndAngle = startAngle;
                options.isHorizontal = false;
                return options
            },
            _getSpiderCategoryOption: function() {
                return this._options.firstPointOnStartAngle
            },
            _getMinMax: function() {
                var options = this._options;
                return {
                        min: undefined,
                        max: utils.isNumber(options.period) && options.argumentType === constants.numeric ? options.period : undefined
                    }
            },
            _getStick: function() {
                return this._options.firstPointOnStartAngle || this._options.type !== constants.discrete
            },
            measureLabels: function() {
                var that = this,
                    options = that._options,
                    indentFromAxis = options.label.indentFromAxis || 0,
                    widthAxis = options.visible ? options.width : 0,
                    maxLabelParams;
                if (!that._axisElementsGroup || !that._options.label.visible)
                    return {
                            height: widthAxis,
                            width: widthAxis
                        };
                that._updateTickManager();
                maxLabelParams = that._tickManager.getMaxLabelParams();
                return {
                        height: maxLabelParams.height + indentFromAxis + constants.halfTickLength,
                        width: maxLabelParams.width + indentFromAxis + constants.halfTickLength
                    }
            },
            _getTranslatedCoord: function(value, offset) {
                return this._translator.translate(value, offset) - HALF_PI_ANGLE
            },
            _getCanvasStartEnd: function() {
                return {
                        start: 0 - HALF_PI_ANGLE,
                        end: 360 - HALF_PI_ANGLE
                    }
            },
            _createStrip: function(fromAngle, toAngle, attr) {
                var center = this._additionalTranslator.getCenter(),
                    r = this._additionalTranslator.getRadius();
                return this._renderer.arc(center.x, center.y, 0, r, -toAngle, -fromAngle).attr(attr)
            },
            _getStripLabelCoords: function(_, stripFrom, stripTo) {
                var that = this,
                    angle = stripFrom + (stripTo - stripFrom) / 2,
                    cossin = utils.getCosAndSin(-angle),
                    halfRad = that._additionalTranslator.getRadius() / 2,
                    center = that._additionalTranslator.getCenter(),
                    x = _round(center.x + halfRad * cossin.cos),
                    y = _round(center.y - halfRad * cossin.sin);
                return {
                        x: x,
                        y: y,
                        align: constants.center
                    }
            },
            _createConstantLine: function(value, attr) {
                var center = this._additionalTranslator.getCenter(),
                    r = this._additionalTranslator.getRadius();
                return this._createPathElement([center.x, center.y, center.x + r, center.y], attr).rotate(value, center.x, center.y)
            },
            _getConstantLineLabelsCoords: function(value) {
                var that = this,
                    cossin = utils.getCosAndSin(-value),
                    halfRad = that._additionalTranslator.getRadius() / 2,
                    center = that._additionalTranslator.getCenter(),
                    x = _round(center.x + halfRad * cossin.cos),
                    y = _round(center.y - halfRad * cossin.sin);
                return {
                        x: x,
                        y: y,
                        align: constants.center
                    }
            },
            _checkAlignmentConstantLineLabels: _noop,
            _getScreenDelta: function() {
                return 2 * Math.PI * this._additionalTranslator.getRadius()
            },
            _getTickCoord: function(tick) {
                var center = this._additionalTranslator.getCenter(),
                    r = this._additionalTranslator.getRadius();
                return {
                        x1: center.x + r - constants.halfTickLength,
                        y1: center.y,
                        x2: center.x + r + constants.halfTickLength,
                        y2: center.y,
                        angle: tick.angle
                    }
            },
            _getLabelAdjustedCoord: function(tick) {
                var that = this,
                    pos = tick.labelPos,
                    cossin = utils.getCosAndSin(pos.angle),
                    cos = cossin.cos,
                    sin = cossin.sin,
                    box = tick.label.getBBox(),
                    halfWidth = box.width / 2,
                    halfHeight = box.height / 2,
                    indentFromAxis = that._options.label.indentFromAxis || 0,
                    x = pos.x + indentFromAxis * cos,
                    y = pos.y + (pos.y - box.y - halfHeight) + indentFromAxis * sin;
                switch (getPolarQuarter(pos.angle)) {
                    case 1:
                        x += halfWidth;
                        y += halfHeight * sin;
                        break;
                    case 2:
                        x += halfWidth * cos;
                        y += halfHeight;
                        break;
                    case 3:
                        x += -halfWidth;
                        y += halfHeight * sin;
                        break;
                    case 4:
                        x += halfWidth * cos;
                        y += -halfHeight;
                        break
                }
                return {
                        x: x,
                        y: y
                    }
            },
            _getGridLineDrawer: function() {
                var that = this,
                    r = that._additionalTranslator.getRadius(),
                    center = that._additionalTranslator.getCenter();
                return function(tick) {
                        return that._createPathElement([center.x, center.y, center.x + r, center.y], tick.gridStyle).rotate(tick.angle, center.x, center.y)
                    }
            },
            _getTranslatedValue: function(value, _, offset) {
                var additionalTranslator = this._additionalTranslator,
                    startAngle = additionalTranslator.getStartAngle(),
                    angle = this._translator.translate(value, -offset),
                    coords = core.utils.convertPolarToXY(additionalTranslator.getCenter(), startAngle, angle, additionalTranslator.translate(constants.canvasPositionBottom));
                return {
                        x: coords.x,
                        y: coords.y,
                        angle: angle + startAngle - HALF_PI_ANGLE
                    }
            },
            _getAdjustedStripLabelCoords: function(_, label) {
                var y,
                    box = label.getBBox();
                y = label.attr("y") - box.y - box.height / 2;
                return {
                        x: 0,
                        y: y
                    }
            },
            coordsIn: function(x, y) {
                return core.utils.convertXYToPolar(this._additionalTranslator.getCenter(), x, y).r > this._additionalTranslator.getRadius()
            },
            _rotateTick: function(tick, angle) {
                var center = this._additionalTranslator.getCenter();
                tick.graphic.rotate(angle, center.x, center.y)
            }
        };
        viz.charts.axes.polarAxes.circularSpider = _extend({}, viz.charts.axes.polarAxes.circular, {
            _createAxisElement: function() {
                var points = _map(this.getSpiderTicks(), function(tick) {
                        return {
                                x: tick.posX,
                                y: tick.posY
                            }
                    });
                return this._renderer.path(points, "area")
            },
            _getStick: function() {
                return true
            },
            _getSpiderCategoryOption: function() {
                return true
            },
            getSpiderTicks: function() {
                var that = this;
                that._spiderTicks = constants.convertValuesToTicks(that._tickManager.getFullTicks());
                that._initTicks(that._spiderTicks, {}, {});
                return that._spiderTicks
            },
            _createStrip: function(fromAngle, toAngle, attr) {
                var center = this._additionalTranslator.getCenter(),
                    spiderTicks = this.getSpiderTicks(),
                    firstTick,
                    lastTick,
                    points = _map(spiderTicks, function(tick, i) {
                        var result = [],
                            nextTick;
                        if (tick.angle >= fromAngle && tick.angle <= toAngle) {
                            if (!firstTick) {
                                firstTick = spiderTicks[i - 1] || spiderTicks[spiderTicks.length - 1];
                                result.push((tick.posX + firstTick.posX) / 2, (tick.posY + firstTick.posY) / 2)
                            }
                            result.push(tick.posX, tick.posY);
                            nextTick = spiderTicks[i + 1] || spiderTicks[0];
                            lastTick = {
                                x: (tick.posX + nextTick.posX) / 2,
                                y: (tick.posY + nextTick.posY) / 2
                            }
                        }
                        else
                            result = null;
                        return result
                    });
                points.push(lastTick.x, lastTick.y);
                points.push(center.x, center.y);
                return this._renderer.path(points, "area").attr(attr)
            },
            _getTranslatedCoord: function(value, offset) {
                return this._translator.translate(value, offset) - HALF_PI_ANGLE
            },
            _setTickOffset: function() {
                this._tickOffset = false
            }
        });
        viz.charts.axes.polarAxes.linear = {
            _overlappingBehaviorType: "linear",
            _getMinMax: viz.charts.axes.polarAxes.circular._getMinMax,
            _getStick: viz.charts.axes.xyAxes.linear._getStick,
            _getTicksOptions: viz.charts.axes.xyAxes.linear._getTicksOptions,
            _getSpiderCategoryOption: $.noop,
            _createAxisElement: function() {
                var additionalTranslator = this._additionalTranslator,
                    centerCoord = additionalTranslator.getCenter(),
                    points = [centerCoord.x, centerCoord.y, centerCoord.x + additionalTranslator.getRadius(), centerCoord.y];
                return this._renderer.path(points, "line").rotate(additionalTranslator.getStartAngle() - HALF_PI_ANGLE, centerCoord.x, centerCoord.y)
            },
            _setBoundingRect: viz.charts.axes.polarAxes.circular._setBoundingRect,
            _getScreenDelta: function() {
                return this._additionalTranslator.getRadius()
            },
            _getTickCoord: function(tick) {
                return {
                        x1: tick.posX - constants.halfTickLength,
                        y1: tick.posY,
                        x2: tick.posX + constants.halfTickLength,
                        y2: tick.posY,
                        angle: tick.angle + HALF_PI_ANGLE
                    }
            },
            _getOverlappingBehaviorOptions: function() {
                var that = this,
                    translator = that._translator,
                    orthTranslator = that._additionalTranslator,
                    options = viz.charts.axes.xyAxes.linear._getOverlappingBehaviorOptions.call(this),
                    startAngle = utils.normalizeAngle(that._additionalTranslator.getStartAngle());
                if (options.overlappingBehavior)
                    options.overlappingBehavior = {mode: constants.validateOverlappingMode(options.overlappingBehavior.mode)};
                options.isHorizontal = startAngle > 45 && startAngle < 135 || startAngle > 225 && startAngle < 315 ? true : false;
                options.isInverted = translator.getBusinessRange().invert;
                options.translate = function(value) {
                    return core.utils.convertPolarToXY(orthTranslator.getCenter(), that._options.startAngle, orthTranslator.translate(constants.canvasPositionTop), translator.translate(value)).x
                };
                return options
            },
            _getLabelAdjustedCoord: function(tick) {
                var that = this,
                    pos = tick.labelPos,
                    cossin = utils.getCosAndSin(pos.angle),
                    indentFromAxis = that._options.label.indentFromAxis || 0,
                    box = tick.label.getBBox(),
                    x,
                    y;
                x = pos.x - _abs(indentFromAxis * cossin.sin) + _abs(box.width / 2 * cossin.cos);
                y = pos.y + (pos.y - box.y) - _abs(box.height / 2 * cossin.sin) + _abs(indentFromAxis * cossin.cos);
                return {
                        x: x,
                        y: y
                    }
            },
            _getGridLineDrawer: function() {
                var that = this,
                    pos = that._additionalTranslator.getCenter();
                return function(tick) {
                        return that._renderer.circle(pos.x, pos.y, utils.getDistance(pos.x, pos.y, tick.posX, tick.posY)).attr(tick.gridStyle).sharp()
                    }
            },
            _getTranslatedValue: function(value, _, offset) {
                var additionalTranslator = this._additionalTranslator,
                    startAngle = additionalTranslator.getStartAngle(),
                    angle = additionalTranslator.translate(constants.canvasPositionStart),
                    xy = core.utils.convertPolarToXY(additionalTranslator.getCenter(), startAngle, angle, this._translator.translate(value, offset));
                return {
                        x: xy.x,
                        y: xy.y,
                        angle: angle + startAngle - HALF_PI_ANGLE
                    }
            },
            _getTranslatedCoord: function(value, offset) {
                return this._translator.translate(value, offset)
            },
            _getCanvasStartEnd: function() {
                return {
                        start: 0,
                        end: this._additionalTranslator.getRadius()
                    }
            },
            _createStrip: function(fromPoint, toPoint, attr) {
                var center = this._additionalTranslator.getCenter();
                return this._renderer.arc(center.x, center.y, fromPoint, toPoint, 0, 360).attr(attr)
            },
            _getAdjustedStripLabelCoords: viz.charts.axes.polarAxes.circular._getAdjustedStripLabelCoords,
            _getStripLabelCoords: function(_, stripFrom, stripTo) {
                var that = this,
                    labelPos = stripFrom + (stripTo - stripFrom) / 2,
                    center = that._additionalTranslator.getCenter(),
                    y = _round(center.y - labelPos);
                return {
                        x: center.x,
                        y: y,
                        align: constants.center
                    }
            },
            _createConstantLine: function(value, attr) {
                var center = this._additionalTranslator.getCenter();
                return this._renderer.circle(center.x, center.y, value).attr(attr).sharp()
            },
            _getConstantLineLabelsCoords: function(value) {
                var that = this,
                    center = that._additionalTranslator.getCenter(),
                    y = _round(center.y - value);
                return {
                        x: center.x,
                        y: y,
                        align: constants.center
                    }
            },
            _checkAlignmentConstantLineLabels: _noop,
            _rotateTick: function(tick, angle) {
                tick.graphic.rotate(angle, tick.posX, tick.posY)
            }
        };
        viz.charts.axes.polarAxes.linearSpider = _extend({}, viz.charts.axes.polarAxes.linear, {
            _createPathElement: function(points, attr) {
                return this._renderer.path(points, "area").attr(attr).sharp()
            },
            setSpiderTicks: function(ticks) {
                this._spiderTicks = ticks
            },
            _getGridLineDrawer: function() {
                var that = this,
                    pos = that._additionalTranslator.getCenter();
                return function(tick) {
                        var radius = utils.getDistance(pos.x, pos.y, tick.posX, tick.posY);
                        return that._createPathElement(that._getGridPoints(pos, radius), tick.gridStyle)
                    }
            },
            _getGridPoints: function(pos, radius) {
                return _map(this._spiderTicks, function(tick) {
                        var cossin = utils.getCosAndSin(tick.angle);
                        return {
                                x: _round(pos.x + radius * cossin.cos),
                                y: _round(pos.y + radius * cossin.sin)
                            }
                    })
            },
            _createStrip: function(fromPoint, toPoint, attr) {
                var center = this._additionalTranslator.getCenter(),
                    innerPoints = this._getGridPoints(center, toPoint),
                    outerPoints = this._getGridPoints(center, fromPoint);
                return this._renderer.path([outerPoints, innerPoints.reverse()], "area").attr(attr)
            },
            _createConstantLine: function(value, attr) {
                var center = this._additionalTranslator.getCenter(),
                    points = this._getGridPoints(center, value);
                return this._createPathElement(points, attr)
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-charts, file baseAxis.js */
    (function($, DX, undefined) {
        var viz = DX.viz,
            core = viz.core,
            utils = DX.utils,
            constants = viz.charts.axes.constants,
            _isDefined = utils.isDefined,
            _isNumber = utils.isNumber,
            _getSignificantDigitPosition = utils.getSignificantDigitPosition,
            _roundValue = utils.roundValue,
            _math = Math,
            _abs = _math.abs,
            _round = _math.round,
            _extend = $.extend,
            _each = $.each,
            _noop = $.noop,
            WIDGET_CLASS = "dxc",
            DEFAULT_AXIS_LABEL_SPACING = 5,
            MAX_GRID_BORDER_ADHENSION = 4,
            LABEL_BACKGROUND_PADDING_X = 8,
            LABEL_BACKGROUND_PADDING_Y = 4,
            Axis;
        function validateAxisOptions(options, isHorizontal) {
            var labelOptions = options.label,
                position = options.position,
                defaultPosition = isHorizontal ? constants.bottom : constants.left,
                secondaryPosition = isHorizontal ? constants.top : constants.right;
            if (position !== defaultPosition && position !== secondaryPosition)
                position = defaultPosition;
            if (position === constants.right && !labelOptions.userAlignment)
                labelOptions.alignment = constants.left;
            options.position = position;
            options.hoverMode = options.hoverMode ? options.hoverMode.toLowerCase() : "none";
            labelOptions.minSpacing = _isDefined(labelOptions.minSpacing) ? labelOptions.minSpacing : DEFAULT_AXIS_LABEL_SPACING
        }
        Axis = DX.viz.charts.axes.Axis = function(renderSettings) {
            var that = this;
            that._renderer = renderSettings.renderer;
            that._isHorizontal = renderSettings.isHorizontal;
            that._incidentOccured = renderSettings.incidentOccured;
            that._stripsGroup = renderSettings.stripsGroup;
            that._labelAxesGroup = renderSettings.labelAxesGroup;
            that._constantLinesGroup = renderSettings.constantLinesGroup;
            that._axesContainerGroup = renderSettings.axesContainerGroup;
            that._gridContainerGroup = renderSettings.gridGroup;
            that._axisClass = renderSettings.axisClass;
            that._setType(renderSettings.axesType, renderSettings.drawingType);
            that._createAxisGroups();
            that._tickManager = that._createTickManager()
        };
        Axis.prototype = {
            constructor: Axis,
            dispose: function() {
                var that = this;
                that._axisElementsGroup && that._axisElementsGroup.dispose();
                that._stripLabels = that._strips = null;
                that._title = null;
                that._axisStripGroup = that._axisConstantLineGroup = that._axisLabelGroup = null;
                that._axisLineGroup = that._axisElementsGroup = that._axisGridGroup = null;
                that._axisGroup = that._axisTitleGroup = null;
                that._axesContainerGroup = that._stripsGroup = that._constantLinesGroup = null;
                that._renderer = that._options = that._textOptions = that._textFontStyles = null;
                that._translator = that._additionalTranslator = null;
                that._majorTicks = that._minorTicks = null;
                that._tickManager = null
            },
            getOptions: function() {
                return this._options
            },
            setPane: function(pane) {
                this.pane = pane;
                this._options.pane = pane
            },
            setTypes: function(type, axisType, typeSelector) {
                this._options.type = type || this._options.type;
                this._options[typeSelector] = axisType || this._options[typeSelector]
            },
            resetTypes: function(typeSelector) {
                this._options.type = this._initTypes.type;
                this._options[typeSelector] = this._initTypes[typeSelector]
            },
            getTranslator: function() {
                return this._translator
            },
            updateOptions: function(options) {
                var that = this,
                    labelOpt = options.label;
                that._options = options;
                that._initTypes = {
                    type: options.type,
                    argumentType: options.argumentType,
                    valueType: options.valueType
                };
                validateAxisOptions(options, that._isHorizontal);
                that._setTickOffset();
                that.pane = options.pane;
                that.name = options.name;
                that.priority = options.priority;
                that._virtual = options.virtual;
                that._hasLabelFormat = labelOpt.format !== "" && _isDefined(labelOpt.format);
                that._textOptions = {
                    align: labelOpt.alignment,
                    opacity: labelOpt.opacity
                };
                that._textFontStyles = core.utils.patchFontOptions(labelOpt.font);
                if (options.type === constants.logarithmic) {
                    if (options.logarithmBaseError) {
                        that._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 = that._isHorizontal ? "horizontal" : "vertical";
                if (options.title.text && that._axisTitleGroup) {
                    that._incidentOccured("W2105", [direction]);
                    that._axisTitleGroup.dispose();
                    that._axisTitleGroup = null
                }
                if (clearAxis && that._axisElementsGroup && options.label.visible && !that._translator.getBusinessRange().stubData) {
                    that._incidentOccured("W2106", [direction]);
                    that._axisElementsGroup.dispose();
                    that._axisElementsGroup = null
                }
                that._setBoundingRect()
            },
            _updateTranslatorInterval: function() {
                var that = this,
                    i,
                    majorTicks,
                    majorTicksLength,
                    translator = that._translator,
                    businessRange = translator.getBusinessRange();
                if (!businessRange.categories && !businessRange.isSynchronized) {
                    that.getMajorTicks(true);
                    businessRange.addRange(that._tickManager.getTickBounds());
                    translator.reinit()
                }
                that._majorTicks = majorTicks = that.getMajorTicks();
                if (!businessRange.categories) {
                    majorTicksLength = majorTicks.length;
                    for (i = 0; i < majorTicksLength - 1; i++)
                        businessRange.addRange({interval: _abs(majorTicks[i].value - majorTicks[i + 1].value)})
                }
                that._decimatedTicks = businessRange.categories ? that.getDecimatedTicks() : [];
                that._minorTicks = that.getMinorTicks()
            },
            setTranslator: function(translator, additionalTranslator) {
                var that = this,
                    range = translator.getBusinessRange();
                this._minBound = range.minVisible;
                this._maxBound = range.maxVisible;
                that._translator = translator;
                that._additionalTranslator = additionalTranslator;
                that.resetTicks();
                that._updateTranslatorInterval()
            },
            resetTicks: function() {
                this._deleteLabels();
                this._majorTicks = this._minorTicks = null
            },
            getCurrentLabelPos: function() {
                var that = this,
                    options = that._options,
                    position = options.position,
                    labelOffset = options.label.indentFromAxis,
                    axisPosition = that._axisPosition;
                return position === constants.top || position === constants.left ? axisPosition - labelOffset : axisPosition + labelOffset
            },
            getUntranslatedValue: function(pos) {
                var that = this,
                    translator = that._translator,
                    value = translator.untranslate(pos);
                if (_isDefined(value))
                    return constants.formatLabel(_isNumber(value) ? _roundValue(value, _getSignificantDigitPosition(translator.getBusinessRange().interval)) : value, that._options.label);
                return null
            },
            _drawAxis: function() {
                var that = this,
                    options = that._options,
                    axis = that._createAxis({
                        "stroke-width": options.width,
                        stroke: options.color,
                        "stroke-opacity": options.opacity
                    });
                axis.append(that._axisLineGroup)
            },
            _correctMinForTicks: function(min, max, screenDelta) {
                var digitPosition = _getSignificantDigitPosition(_abs(max - min) / screenDelta),
                    newMin = _roundValue(Number(min), digitPosition),
                    correctingValue;
                if (newMin < min) {
                    correctingValue = _math.pow(10, -digitPosition);
                    newMin = utils.applyPrecisionByMinDelta(newMin, correctingValue, newMin + correctingValue)
                }
                if (newMin > max)
                    newMin = min;
                return newMin
            },
            _getTickManagerData: function() {
                var that = this,
                    options = that._options,
                    screenDelta = that._getScreenDelta(),
                    min = that._minBound,
                    max = that._maxBound,
                    categories = that._translator.getVisibleCategories() || that._translator.getBusinessRange().categories,
                    customTicks = $.isArray(categories) ? categories : that._majorTicks && constants.convertTicksToValues(that._majorTicks),
                    customMinorTicks = that._minorTicks && constants.convertTicksToValues(that._minorTicks);
                if (_isNumber(min) && options.type !== constants.logarithmic)
                    min = that._correctMinForTicks(min, max, screenDelta);
                return {
                        min: min,
                        max: max,
                        customTicks: customTicks,
                        customMinorTicks: customMinorTicks,
                        screenDelta: screenDelta
                    }
            },
            _getTickManagerTypes: function() {
                return {
                        axisType: this._options.type,
                        dataType: this._options.dataType
                    }
            },
            _createTickManager: function() {
                return DX.viz.core.CoreFactory.createTickManager({}, {}, {overlappingBehaviorType: this._overlappingBehaviorType})
            },
            _getMarginsOptions: function() {
                var range = this._translator.getBusinessRange();
                return {
                        stick: range.stick,
                        minStickValue: range.minStickValue,
                        maxStickValue: range.maxStickValue,
                        percentStick: range.percentStick,
                        minValueMargin: this._options.minValueMargin,
                        maxValueMargin: this._options.maxValueMargin,
                        minSpaceCorrection: range.minSpaceCorrection,
                        maxSpaceCorrection: range.maxSpaceCorrection
                    }
            },
            _updateTickManager: function() {
                var overlappingOptions = this._getOverlappingBehaviorOptions(),
                    options;
                options = _extend(true, {}, this._getMarginsOptions(), overlappingOptions, this._getTicksOptions());
                this._tickManager.update(this._getTickManagerTypes(), this._getTickManagerData(), options)
            },
            _correctLabelAlignment: function() {
                var that = this,
                    labelOptions = that._options.label,
                    overlappingBehavior = that._tickManager.getOverlappingBehavior();
                if (overlappingBehavior && overlappingBehavior.mode === "rotate") {
                    that._textOptions.rotate = overlappingBehavior.rotationAngle;
                    if (!labelOptions.userAlignment)
                        that._textOptions.align = constants.left
                }
                else if (!labelOptions.userAlignment)
                    that._textOptions.align = labelOptions.alignment
            },
            _correctLabelFormat: function() {
                this._options.label = this._tickManager.getOptions().labelOptions
            },
            getTicksValues: function() {
                return {
                        majorTicksValues: constants.convertTicksToValues(this._majorTicks || this.getMajorTicks()),
                        minorTicksValues: constants.convertTicksToValues(this._minorTicks || this.getMinorTicks())
                    }
            },
            getMajorTicks: function(withoutOverlappingBehavior) {
                var that = this,
                    majorTicks;
                that._updateTickManager();
                that._textOptions.rotate = 0;
                majorTicks = constants.convertValuesToTicks(that._tickManager.getTicks(withoutOverlappingBehavior));
                that._correctLabelAlignment();
                that._correctLabelFormat();
                return majorTicks
            },
            getMinorTicks: function() {
                return constants.convertValuesToTicks(this._tickManager.getMinorTicks())
            },
            getDecimatedTicks: function() {
                return constants.convertValuesToTicks(this._tickManager.getDecimatedTicks())
            },
            setTicks: function(ticks) {
                this.resetTicks();
                this._majorTicks = constants.convertValuesToTicks(ticks.majorTicks);
                this._minorTicks = constants.convertValuesToTicks(ticks.minorTicks)
            },
            _deleteLabels: function() {
                this._axisElementsGroup && this._axisElementsGroup.clear()
            },
            _drawTicks: function(ticks) {
                var that = this,
                    group = that._axisLineGroup;
                _each(ticks || [], function(_, tick) {
                    var coord = that._getTickCoord(tick),
                        points;
                    if (coord) {
                        points = that._isHorizontal ? [coord.x1, coord.y1, coord.x2, coord.y2] : [coord.y1, coord.x1, coord.y2, coord.x2];
                        tick.graphic = that._createPathElement(points, tick.tickStyle).append(group);
                        coord.angle && that._rotateTick(tick, coord.angle)
                    }
                })
            },
            _createPathElement: function(points, attr, oposite) {
                return this._renderer.path(points, "line").attr(attr).sharp(this._getSharpParam(oposite))
            },
            _createAxis: function(options) {
                return this._createAxisElement().attr(options).sharp(this._getSharpParam(true))
            },
            _getTickCoord: function(tick) {
                var coords;
                if (_isDefined(tick.posX) && _isDefined(tick.posY))
                    coords = {
                        x1: tick.posX,
                        y1: tick.posY - constants.halfTickLength,
                        x2: tick.posX,
                        y2: tick.posY + constants.halfTickLength
                    };
                else
                    coords = null;
                return coords
            },
            setPercentLabelFormat: function() {
                if (!this._hasLabelFormat)
                    this._options.label.format = "percent"
            },
            resetAutoLabelFormat: function() {
                if (!this._hasLabelFormat)
                    delete this._options.label.format
            },
            _drawLabels: function() {
                var that = this,
                    renderer = that._renderer,
                    group = that._axisElementsGroup,
                    emptyStrRegExp = /^\s+$/;
                _each(that._majorTicks, function(_, tick) {
                    var text = tick.labelText,
                        xCoord,
                        yCoord;
                    if (_isDefined(text) && text !== "" && !emptyStrRegExp.test(text)) {
                        xCoord = that._isHorizontal ? tick.labelPos.x : tick.labelPos.y;
                        yCoord = that._isHorizontal ? tick.labelPos.y : tick.labelPos.x;
                        if (!tick.label)
                            tick.label = renderer.text(text, xCoord, yCoord).css(tick.labelFontStyle).attr(tick.labelStyle).append(group);
                        else
                            tick.label.css(tick.labelFontStyle).attr(tick.labelStyle).attr({
                                text: text,
                                x: xCoord,
                                y: yCoord
                            });
                        tick.label.data({argument: tick.value})
                    }
                })
            },
            getMultipleAxesSpacing: function() {
                return this._options.multipleAxesSpacing || 0
            },
            _drawTitle: _noop,
            _getGridLineDrawer: function(borderOptions) {
                var that = this,
                    translator = that._translator,
                    additionalTranslator = that._additionalTranslator,
                    isHorizontal = that._isHorizontal,
                    canvasStart = isHorizontal ? constants.left : constants.top,
                    canvasEnd = isHorizontal ? constants.right : constants.bottom,
                    positionFrom = additionalTranslator.translateSpecialCase(constants.canvasPositionStart),
                    positionTo = additionalTranslator.translateSpecialCase(constants.canvasPositionEnd),
                    firstBorderLinePosition = borderOptions.visible && borderOptions[canvasStart] ? translator.translateSpecialCase(constants.canvasPositionPrefix + canvasStart) : undefined,
                    lastBorderLinePosition = borderOptions.visible && borderOptions[canvasEnd] ? translator.translateSpecialCase(constants.canvasPositionPrefix + canvasEnd) : undefined,
                    getPoints = isHorizontal ? function(tick) {
                        return tick.posX !== null ? [tick.posX, positionFrom, tick.posX, positionTo] : null
                    } : function(tick) {
                        return tick.posX !== null ? [positionFrom, tick.posX, positionTo, tick.posX] : null
                    };
                return function(tick) {
                        var points;
                        if (_abs(tick.posX - firstBorderLinePosition) < MAX_GRID_BORDER_ADHENSION || _abs(tick.posX - lastBorderLinePosition) < MAX_GRID_BORDER_ADHENSION)
                            return;
                        points = getPoints(tick);
                        return points && that._createPathElement(points, tick.gridStyle)
                    }
            },
            _drawGrids: function(ticks, borderOptions) {
                var that = this,
                    group = that._axisGridGroup,
                    drawLine = that._getGridLineDrawer(borderOptions || {visible: false});
                _each(ticks || [], function(_, tick) {
                    tick.grid = drawLine(tick);
                    tick.grid && tick.grid.append(group)
                })
            },
            _getConstantLinePos: function(lineValue, canvasStart, canvasEnd) {
                var parsedValue = this._validateUnit(lineValue, "E2105", "constantLine"),
                    value = this._getTranslatedCoord(parsedValue);
                if (!_isDefined(value) || value < _math.min(canvasStart, canvasEnd) || value > _math.max(canvasStart, canvasEnd))
                    return {};
                return {
                        value: value,
                        parsedValue: parsedValue
                    }
            },
            _createConstantLine: function(value, attr) {
                var that = this,
                    additionalTranslator = this._additionalTranslator,
                    positionFrom = additionalTranslator.translateSpecialCase(constants.canvasPositionStart),
                    positionTo = additionalTranslator.translateSpecialCase(constants.canvasPositionEnd),
                    points = this._isHorizontal ? [value, positionTo, value, positionFrom] : [positionFrom, value, positionTo, value];
                return that._createPathElement(points, attr)
            },
            _drawConstantLinesAndLabels: function(lineOptions, canvasStart, canvasEnd) {
                if (!_isDefined(lineOptions.value))
                    return;
                var that = this,
                    pos = that._getConstantLinePos(lineOptions.value, canvasStart, canvasEnd),
                    labelOptions = lineOptions.label || {},
                    value = pos.value,
                    attr = {
                        stroke: lineOptions.color,
                        "stroke-width": lineOptions.width,
                        dashStyle: lineOptions.dashStyle
                    };
                if (!_isDefined(value)) {
                    that._constantLines.push(null);
                    if (labelOptions.visible)
                        that._constantLineLabels.push(null);
                    return
                }
                that._constantLines.push(that._createConstantLine(value, attr).append(that._axisConstantLineGroup));
                that._constantLineLabels.push(labelOptions.visible ? that._drawConstantLineLabels(pos.parsedValue, labelOptions, value) : null)
            },
            _drawConstantLine: function() {
                var that = this,
                    options = that._options,
                    data = options.constantLines,
                    canvas = that._getCanvasStartEnd();
                if (that._translator.getBusinessRange().stubData)
                    return;
                that._constantLines = [];
                that._constantLineLabels = [];
                _each(data, function(_, dataItem) {
                    that._drawConstantLinesAndLabels(dataItem, canvas.start, canvas.end)
                })
            },
            _drawConstantLineLabels: function(parsedValue, lineLabelOptions, value) {
                var that = this,
                    text = lineLabelOptions.text,
                    options = that._options,
                    labelOptions = options.label,
                    coords;
                that._checkAlignmentConstantLineLabels(lineLabelOptions);
                text = _isDefined(text) ? text : constants.formatLabel(parsedValue, labelOptions);
                coords = that._getConstantLineLabelsCoords(value, lineLabelOptions);
                return that._renderer.text(text, coords.x, coords.y).css(core.utils.patchFontOptions(_extend({}, labelOptions.font, lineLabelOptions.font))).attr({align: coords.align}).append(that._axisConstantLineGroup)
            },
            _adjustConstantLineLabels: _noop,
            _getStripPos: function(startValue, endValue, canvasStart, canvasEnd, range) {
                var isContinous = !!(range.minVisible || range.maxVisible),
                    categories = range.categories || [],
                    start,
                    end,
                    firstValue = startValue,
                    lastValue = endValue,
                    startCategoryIndex,
                    endCategoryIndex,
                    min = range.minVisible;
                if (!isContinous) {
                    startCategoryIndex = $.inArray(startValue, categories);
                    endCategoryIndex = $.inArray(endValue, categories);
                    if (startCategoryIndex === -1 || endCategoryIndex === -1)
                        return {
                                stripFrom: 0,
                                stripTo: 0
                            };
                    if (startCategoryIndex > endCategoryIndex) {
                        firstValue = endValue;
                        lastValue = startValue
                    }
                }
                start = this._getTranslatedCoord(this._validateUnit(firstValue, "E2105", "strip"), -1);
                end = this._getTranslatedCoord(this._validateUnit(lastValue, "E2105", "strip"), 1);
                if (!_isDefined(start) && isContinous)
                    start = startValue < min ? canvasStart : canvasEnd;
                if (!_isDefined(end) && isContinous)
                    end = endValue < min ? canvasStart : canvasEnd;
                return start < end ? {
                        stripFrom: start,
                        stripTo: end
                    } : {
                        stripFrom: end,
                        stripTo: start
                    }
            },
            _createStrip: function(fromPoint, toPoint, attr) {
                var x,
                    y,
                    width,
                    height,
                    additionalTranslator = this._additionalTranslator,
                    positionFrom = additionalTranslator.translateSpecialCase(constants.canvasPositionStart),
                    positionTo = additionalTranslator.translateSpecialCase(constants.canvasPositionEnd);
                if (this._isHorizontal) {
                    x = fromPoint;
                    y = _math.min(positionFrom, positionTo);
                    width = toPoint - fromPoint;
                    height = _abs(positionFrom - positionTo)
                }
                else {
                    x = _math.min(positionFrom, positionTo);
                    y = fromPoint;
                    width = _abs(positionFrom - positionTo);
                    height = _abs(fromPoint - toPoint)
                }
                return this._renderer.rect(x, y, width, height).attr(attr)
            },
            _drawStrip: function() {
                var that = this,
                    options = that._options,
                    stripData = options.strips,
                    canvas = this._getCanvasStartEnd(),
                    i,
                    stripOptions,
                    stripPos,
                    stripLabelOptions,
                    attr,
                    range = that._translator.getBusinessRange();
                if (range.stubData)
                    return;
                that._strips = [];
                that._stripLabels = [];
                for (i = 0; i < stripData.length; i++) {
                    stripOptions = stripData[i];
                    stripLabelOptions = stripOptions.label || {};
                    attr = {fill: stripOptions.color};
                    if (_isDefined(stripOptions.startValue) && _isDefined(stripOptions.endValue) && _isDefined(stripOptions.color)) {
                        stripPos = that._getStripPos(stripOptions.startValue, stripOptions.endValue, canvas.start, canvas.end, range);
                        if (stripPos.stripTo - stripPos.stripFrom === 0 || !_isDefined(stripPos.stripTo) || !_isDefined(stripPos.stripFrom)) {
                            that._strips.push(null);
                            if (stripLabelOptions.text)
                                that._stripLabels.push(null);
                            continue
                        }
                        that._strips.push(that._createStrip(stripPos.stripFrom, stripPos.stripTo, attr).append(that._axisStripGroup));
                        that._stripLabels.push(stripLabelOptions.text ? that._drawStripLabel(stripLabelOptions, stripPos.stripFrom, stripPos.stripTo) : null)
                    }
                }
            },
            _drawStripLabel: function(stripLabelOptions, stripFrom, stripTo) {
                var that = this,
                    options = that._options,
                    coords = that._getStripLabelCoords(stripLabelOptions, stripFrom, stripTo);
                return that._renderer.text(stripLabelOptions.text, coords.x, coords.y).css(core.utils.patchFontOptions(_extend({}, options.label.font, stripLabelOptions.font))).attr({align: coords.align}).append(that._axisLabelGroup)
            },
            _adjustStripLabels: function() {
                var that = this,
                    labels = that._stripLabels,
                    rects = that._strips,
                    i,
                    coords;
                if (labels === undefined && rects === undefined)
                    return;
                for (i = 0; i < labels.length; i++)
                    if (labels[i] !== null) {
                        coords = that._getAdjustedStripLabelCoords(that._options.strips[i], labels[i], rects[i]);
                        labels[i].move(coords.x, coords.y)
                    }
            },
            _initAxisPositions: _noop,
            _adjustLabels: function() {
                var that = this,
                    options = that._options,
                    majorTicks = that._majorTicks,
                    majorTicksLength = majorTicks.length,
                    isHorizontal = that._isHorizontal,
                    overlappingBehavior = that._tickManager ? that._tickManager.getOverlappingBehavior() : options.label.overlappingBehavior,
                    position = options.position,
                    label,
                    labelHeight,
                    isNeedLabelAdjustment,
                    staggeringSpacing,
                    i,
                    box,
                    hasLabels = false,
                    boxAxis = that._axisElementsGroup && that._axisElementsGroup.getBBox() || {};
                _each(majorTicks, function(_, tick) {
                    if (tick.label) {
                        tick.label.attr(that._getLabelAdjustedCoord(tick, boxAxis));
                        hasLabels = true
                    }
                });
                isNeedLabelAdjustment = hasLabels && isHorizontal && overlappingBehavior && overlappingBehavior.mode === "stagger";
                if (isNeedLabelAdjustment) {
                    labelHeight = 0;
                    for (i = 0; i < majorTicksLength; i = i + 2) {
                        label = majorTicks[i].label;
                        box = label && label.getBBox() || {};
                        if (box.height > labelHeight)
                            labelHeight = box.height
                    }
                    staggeringSpacing = overlappingBehavior.staggeringSpacing;
                    labelHeight = _round(labelHeight) + staggeringSpacing;
                    for (i = 1; i < majorTicksLength; i = i + 2) {
                        label = majorTicks[i].label;
                        if (label)
                            if (position === constants.bottom)
                                label.move(0, labelHeight);
                            else if (position === constants.top)
                                label.move(0, -labelHeight)
                    }
                    for (i = 0; i < majorTicksLength; i++)
                        majorTicks[i].label && majorTicks[i].label.rotate(0)
                }
            },
            _getLabelAdjustedCoord: function(tick, boxAxis) {
                var that = this,
                    options = that._options,
                    box = tick.label.getBBox(),
                    x,
                    y,
                    isHorizontal = that._isHorizontal,
                    position = options.position,
                    shift = that.padding && that.padding[position] || 0,
                    textOptions = that._textOptions,
                    labelSettingsY = tick.label.attr("y");
                if (isHorizontal && position === constants.bottom)
                    y = 2 * labelSettingsY - box.y + shift;
                else if (!isHorizontal) {
                    if (position === constants.left)
                        if (textOptions.align === constants.right)
                            x = box.x + box.width - shift;
                        else if (textOptions.align === constants.center)
                            x = box.x + box.width / 2 - shift - (boxAxis.width / 2 || 0);
                        else
                            x = box.x - shift - (boxAxis.width || 0);
                    else if (textOptions.align === constants.center)
                        x = box.x + box.width / 2 + (boxAxis.width / 2 || 0) + shift;
                    else if (textOptions.align === constants.right)
                        x = box.x + box.width + (boxAxis.width || 0) + shift;
                    else
                        x = box.x + shift;
                    y = labelSettingsY + ~~(labelSettingsY - box.y - box.height / 2)
                }
                else if (isHorizontal && position === constants.top)
                    y = 2 * labelSettingsY - box.y - box.height - shift;
                return {
                        x: x,
                        y: y
                    }
            },
            _adjustTitle: _noop,
            _createAxisGroups: function() {
                var that = this,
                    renderer = that._renderer,
                    classSelector = WIDGET_CLASS + "-" + that._axisClass + "-";
                that._axisGroup = renderer.g().attr({"class": classSelector + "axis"});
                that._axisStripGroup = renderer.g().attr({"class": classSelector + "strips"});
                that._axisGridGroup = renderer.g().attr({"class": classSelector + "grid"});
                that._axisElementsGroup = renderer.g().attr({"class": classSelector + "elements"}).append(that._axisGroup);
                that._axisLineGroup = renderer.g().attr({"class": classSelector + "line"}).append(that._axisGroup);
                that._axisTitleGroup = renderer.g().attr({"class": classSelector + "title"}).append(that._axisGroup);
                that._axisConstantLineGroup = renderer.g().attr({"class": classSelector + "constant-lines"});
                that._axisLabelGroup = renderer.g().attr({"class": classSelector + "axis-labels"})
            },
            _clearAxisGroups: function(adjustAxis) {
                var that = this,
                    classSelector = WIDGET_CLASS + "-" + that._axisClass + "-";
                that._axisGroup.remove();
                that._axisStripGroup.remove();
                that._axisLabelGroup.remove();
                that._axisConstantLineGroup.remove();
                that._axisGridGroup.remove();
                if (that._axisTitleGroup)
                    that._axisTitleGroup.clear();
                else if (!adjustAxis)
                    that._axisTitleGroup = that._renderer.g().attr({"class": classSelector + "title"}).append(that._axisGroup);
                if (that._axisElementsGroup)
                    that._axisElementsGroup.clear();
                else if (!adjustAxis)
                    that._axisElementsGroup = that._renderer.g().attr({"class": classSelector + "elements"}).append(that._axisGroup);
                that._axisLineGroup.clear();
                that._axisStripGroup.clear();
                that._axisGridGroup.clear();
                that._axisConstantLineGroup.clear();
                that._axisLabelGroup.clear()
            },
            _initTicks: function(ticks, tickOptions, gridOptions, withLabels) {
                var that = this,
                    options = that._options,
                    tickStyle = {
                        stroke: tickOptions.color,
                        "stroke-width": 1,
                        "stroke-opacity": tickOptions.opacity
                    },
                    gridStyle = {
                        stroke: gridOptions.color,
                        "stroke-width": gridOptions.width,
                        "stroke-opacity": gridOptions.opacity
                    },
                    currentLabelConst = that.getCurrentLabelPos(),
                    categoryToSkip = that._getSkippedCategory();
                _each(ticks || [], function(_, tick) {
                    var coord;
                    if (!(categoryToSkip && categoryToSkip === tick.value)) {
                        coord = that._getTranslatedValue(tick.value, that._axisPosition, that._tickOffset);
                        tick.posX = coord.x;
                        tick.posY = coord.y;
                        tick.angle = coord.angle
                    }
                    tick.tickStyle = tickStyle;
                    tick.gridStyle = gridStyle;
                    if (withLabels) {
                        tick.labelText = constants.formatLabel(tick.value, options.label, {
                            min: that._minBound,
                            max: that._maxBound
                        });
                        tick.labelPos = that._getTranslatedValue(tick.value, currentLabelConst);
                        tick.labelStyle = that._textOptions;
                        tick.labelFontStyle = that._textFontStyles;
                        tick.labelHint = constants.formatHint(tick.value, options.label, {
                            min: that._minBound,
                            max: that._maxBound
                        })
                    }
                })
            },
            _setTickOffset: function() {
                var options = this._options,
                    discreteAxisDivisionMode = options.discreteAxisDivisionMode;
                this._tickOffset = +(discreteAxisDivisionMode !== "crossLabels" || !discreteAxisDivisionMode)
            },
            drawGrids: function(borderOptions) {
                var that = this,
                    options = that._options;
                borderOptions = borderOptions || {};
                that._axisGridGroup.append(that._gridContainerGroup);
                if (options.grid.visible)
                    that._drawGrids(that._majorTicks.concat(that._decimatedTicks), borderOptions);
                options.minorGrid.visible && that._drawGrids(that._minorTicks, borderOptions)
            },
            draw: function(adjustAxis) {
                var that = this,
                    options = that._options,
                    areLabelsVisible;
                if (that._axisGroup)
                    that._clearAxisGroups(adjustAxis);
                areLabelsVisible = options.label.visible && that._axisElementsGroup && !that._translator.getBusinessRange().stubData;
                that._updateTranslatorInterval();
                that._initAxisPositions();
                that._initTicks(that._majorTicks, options.tick, options.grid, areLabelsVisible);
                that._initTicks(that._decimatedTicks, options.tick, options.grid, false);
                that._initTicks(that._minorTicks, options.minorTick, options.minorGrid);
                if (!that._virtual) {
                    options.visible && that._drawAxis();
                    if (options.tick.visible) {
                        that._drawTicks(that._majorTicks);
                        that._drawTicks(that._decimatedTicks)
                    }
                    options.minorTick.visible && that._drawTicks(that._minorTicks);
                    areLabelsVisible && that._drawLabels();
                    that._drawTitle()
                }
                options.strips && that._drawStrip();
                options.constantLines && that._drawConstantLine();
                that._axisStripGroup.append(that._stripsGroup);
                that._axisConstantLineGroup.append(that._constantLinesGroup);
                that._axisGroup.append(that._axesContainerGroup);
                that._axisLabelGroup.append(that._labelAxesGroup);
                that._adjustConstantLineLabels();
                areLabelsVisible && that._adjustLabels();
                that._createHints();
                that._adjustStripLabels();
                that._adjustTitle();
                that._setBoundingRect()
            },
            _createHints: function() {
                var that = this;
                _each(that._majorTicks || [], function(_, tick) {
                    var labelHint = tick.labelHint;
                    if (_isDefined(labelHint) && labelHint !== "")
                        tick.label.setTitle(labelHint)
                })
            },
            _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 = that._isHorizontal,
                    coord = isHorizontal ? "y" : "x",
                    side = isHorizontal ? "height" : "width",
                    shiftCoords = options.crosshairEnabled ? isHorizontal ? LABEL_BACKGROUND_PADDING_Y : LABEL_BACKGROUND_PADDING_X : 0,
                    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 && constants.bottom || constants.right)) {
                    axisBox[side] = placeholderSize || axisTitleBox[coord] + axisTitleBox[side] - start + shiftCoords;
                    axisBox[coord] = start
                }
                else {
                    axisBox[side] = placeholderSize || lineBox[side] + start - axisTitleBox[coord] + shiftCoords;
                    axisBox[coord] = axisTitleBox.isEmpty ? start : axisTitleBox[coord] - shiftCoords
                }
                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.attr(settings)
            },
            applyClipRects: function(elementsClipID, canvasClipID) {
                this._axisGroup.attr({clipId: canvasClipID});
                this._axisStripGroup.attr({clipId: elementsClipID})
            },
            validate: function(isArgumentAxis) {
                var that = this,
                    options = that._options,
                    parseUtils = new core.ParseUtils,
                    dataType = isArgumentAxis ? options.argumentType : options.valueType,
                    parser = dataType ? parseUtils.getParser(dataType, "axis") : function(unit) {
                        return unit
                    };
                that.parser = parser;
                options.dataType = dataType;
                if (options.min !== undefined)
                    options.min = that._validateUnit(options.min, "E2106");
                if (options.max !== undefined)
                    options.max = that._validateUnit(options.max, "E2106");
                if (that._minBound !== undefined)
                    that._minBound = that._validateUnit(that._minBound);
                if (that._maxBound !== undefined)
                    that._maxBound = that._validateUnit(that._maxBound)
            },
            _validateUnit: function(unit, idError, parameters) {
                var that = this;
                unit = that.parser(unit);
                if (unit === undefined && idError)
                    that._incidentOccured(idError, [parameters]);
                return unit
            },
            zoom: function(min, max, skipAdjusting) {
                var that = this,
                    minOpt = that._options.min,
                    maxOpt = that._options.max;
                skipAdjusting = skipAdjusting || that._options.type === constants.discrete;
                min = that._validateUnit(min);
                max = that._validateUnit(max);
                if (!skipAdjusting) {
                    if (minOpt !== undefined) {
                        min = minOpt > min ? minOpt : min;
                        max = minOpt > max ? minOpt : max
                    }
                    if (maxOpt !== undefined) {
                        max = maxOpt < max ? maxOpt : max;
                        min = maxOpt < min ? maxOpt : min
                    }
                }
                that._zoomArgs = {
                    min: min,
                    max: max
                };
                return that._zoomArgs
            },
            resetZoom: function() {
                this._zoomArgs = null
            },
            getRangeData: function() {
                var that = this,
                    options = that._options,
                    minMax = that._getMinMax(),
                    min = minMax.min,
                    max = minMax.max,
                    zoomArgs = that._zoomArgs || {},
                    type = options.type,
                    rangeMin,
                    rangeMax,
                    rangeMinVisible,
                    rangeMaxVisible;
                if (type === constants.logarithmic) {
                    min = min <= 0 ? undefined : min;
                    max = max <= 0 ? undefined : max
                }
                if (type !== constants.discrete) {
                    rangeMin = min;
                    rangeMax = max;
                    if (_isDefined(min) && _isDefined(max)) {
                        rangeMin = min < max ? min : max;
                        rangeMax = max > min ? max : min
                    }
                    rangeMinVisible = _isDefined(zoomArgs.min) ? zoomArgs.min : rangeMin;
                    rangeMaxVisible = _isDefined(zoomArgs.max) ? zoomArgs.max : rangeMax
                }
                else {
                    rangeMinVisible = _isDefined(zoomArgs.min) ? zoomArgs.min : min;
                    rangeMaxVisible = _isDefined(zoomArgs.max) ? zoomArgs.max : max
                }
                return {
                        min: rangeMin,
                        max: rangeMax,
                        stick: that._getStick(),
                        categories: options.categories,
                        dataType: options.dataType,
                        axisType: type,
                        base: options.logarithmBase,
                        invert: options.inverted,
                        addSpiderCategory: that._getSpiderCategoryOption(),
                        minVisible: rangeMinVisible,
                        maxVisible: rangeMaxVisible
                    }
            },
            _setType: function(axesType, drawingType) {
                var that = this;
                _each(DX.viz.charts.axes[axesType][drawingType], function(methodName, method) {
                    that[methodName] = method
                })
            },
            _getSharpParam: function() {
                return true
            },
            getSpiderTicks: _noop,
            setSpiderTicks: _noop,
            measureLabels: _noop,
            coordsIn: _noop,
            _getSkippedCategory: _noop
        }
    })(jQuery, DevExpress);
    /*! Module viz-charts, file scrollBar.js */
    (function($, DX, math) {
        var MIN_SCROLL_BAR_SIZE = 2,
            isDefined = DX.utils.isDefined,
            _min = math.min,
            _max = math.max;
        DX.viz.charts.ScrollBar = function(renderer, group) {
            this._translator = DX.viz.core.CoreFactory.createTranslator2D({}, {}, {});
            this._scroll = renderer.rect().append(group);
            this._addEvents()
        };
        function _getXCoord(canvas, pos, offset, width) {
            var x = 0;
            if (pos === "right")
                x = canvas.width - canvas.right + offset;
            else if (pos === "left")
                x = canvas.left - offset - width;
            return x
        }
        function _getYCoord(canvas, pos, offset, width) {
            var y = 0;
            if (pos === "top")
                y = canvas.top - offset;
            else if (pos === "bottom")
                y = canvas.height - canvas.bottom + width + offset;
            return y
        }
        DX.viz.charts.ScrollBar.prototype = {
            _addEvents: function() {
                var that = this,
                    $scroll = $(that._scroll.element),
                    startPosX = 0,
                    startPosY = 0,
                    scrollChangeHandler = function(e) {
                        var dX = (startPosX - e.pageX) * that._scale,
                            dY = (startPosY - e.pageY) * that._scale;
                        $scroll.trigger(new $.Event("dxc-scroll-move", $.extend(e, {
                            type: "dxc-scroll-move",
                            pointers: [{
                                    pageX: startPosX + dX,
                                    pageY: startPosY + dY
                                }]
                        })))
                    };
                $scroll.on("dxpointerdown", function(e) {
                    startPosX = e.pageX;
                    startPosY = e.pageY;
                    $scroll.trigger(new $.Event("dxc-scroll-start", {pointers: [{
                                pageX: startPosX,
                                pageY: startPosY
                            }]}));
                    $(document).on("dxpointermove", scrollChangeHandler)
                });
                $(document).on("dxpointerup", function() {
                    $(document).off("dxpointermove", scrollChangeHandler)
                })
            },
            update: function(options) {
                var that = this,
                    position = options.position,
                    isVertical = options.rotated,
                    defaultPosition = isVertical ? "right" : "top",
                    secondaryPosition = isVertical ? "left" : "bottom";
                if (position !== defaultPosition && position !== secondaryPosition)
                    position = defaultPosition;
                that._scroll.attr({
                    rotate: !options.rotated ? -90 : 0,
                    rotateX: 0,
                    rotateY: 0,
                    fill: options.color,
                    width: options.width,
                    opacity: options.opacity
                });
                that._layoutOptions = {
                    width: options.width,
                    offset: options.offset,
                    vertical: isVertical,
                    position: position
                };
                return that
            },
            init: function(range, canvas) {
                var that = this;
                that._translateWithOffset = range.axisType === "discrete" && !range.stick && 1 || 0;
                that._translator.update($.extend({}, range, {
                    minVisible: null,
                    maxVisible: null,
                    visibleCategories: null
                }), $.extend({}, canvas), {direction: that._layoutOptions.vertical ? "vertical" : "horizontal"});
                return that
            },
            getOptions: function() {
                return this._layoutOptions
            },
            shift: function(x, y) {
                this._scroll.attr({
                    translateX: x,
                    translateY: y
                })
            },
            setPane: function(panes) {
                var position = this._layoutOptions.position,
                    pane;
                if (position === "left" || position === "top")
                    pane = panes[0];
                else
                    pane = panes[panes.length - 1];
                this.pane = pane.name;
                this._canvas = pane.canvas;
                return this
            },
            getMultipleAxesSpacing: function() {
                return 0
            },
            getBoundingRect: function() {
                var options = this._layoutOptions,
                    isVertical = options.vertical,
                    offset = options.offset,
                    width = options.width,
                    pos = options.position,
                    size = width + offset,
                    canvas = this._canvas;
                return isVertical ? {
                        x: _getXCoord(canvas, pos, offset, width),
                        y: canvas.top,
                        width: size,
                        height: canvas.height - canvas.top - canvas.bottom
                    } : {
                        x: canvas.left,
                        y: _getYCoord(canvas, pos, offset, width),
                        width: canvas.width - canvas.left - canvas.right,
                        height: size
                    }
            },
            applyLayout: function() {
                var canvas = this._canvas,
                    options = this._layoutOptions,
                    pos = options.position,
                    offset = options.offset,
                    width = options.width;
                this.shift(_getXCoord(canvas, pos, offset, width), _getYCoord(canvas, pos, offset, width))
            },
            setPosition: function(min, max) {
                var that = this,
                    translator = that._translator,
                    minPoint = isDefined(min) ? translator.translate(min, -that._translateWithOffset) : translator.translate("canvas_position_start"),
                    maxPoint = isDefined(max) ? translator.translate(max, that._translateWithOffset) : translator.translate("canvas_position_end");
                that._offset = _min(minPoint, maxPoint);
                that._scale = translator.getScale(min, max);
                that._applyPosition(_min(minPoint, maxPoint), _max(minPoint, maxPoint))
            },
            transform: function(translate, scale) {
                var x = this._translator.getCanvasVisibleArea().min,
                    dx = x - (x * scale - translate),
                    lx = this._offset + dx / (this._scale * scale);
                this._applyPosition(lx, lx + this._translator.canvasLength / (this._scale * scale))
            },
            dispose: function() {
                this._scroll.dispose();
                this._scroll = this._translator = null
            },
            _applyPosition: function(x1, x2) {
                var that = this,
                    visibleArea = that._translator.getCanvasVisibleArea(),
                    height;
                x1 = _max(x1, visibleArea.min);
                x1 = _min(x1, visibleArea.max);
                x2 = _min(x2, visibleArea.max);
                x2 = _max(x2, visibleArea.min);
                height = math.abs(x2 - x1);
                that._scroll.attr({
                    y: x1,
                    height: height < MIN_SCROLL_BAR_SIZE ? MIN_SCROLL_BAR_SIZE : height
                })
            }
        }
    })(jQuery, DevExpress, Math);
    /*! Module viz-charts, file baseChart.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            charts = DX.viz.charts,
            utils = DX.utils,
            ACTIONS_BY_PRIORITY = ['reinit', '_reinitDataSource', '_dataInit', 'force_render', "_resize"],
            core = DX.viz.core,
            _each = $.each,
            _map = $.map,
            _extend = $.extend,
            DEFAULT_ANIMATION_OPTIONS = {asyncSeriesRendering: true},
            _isDefined = utils.isDefined,
            DEFAULT_OPACITY = 0.3;
        function createEventMapObject(name, deprecatedArgs) {
            return {
                    name: name,
                    deprecated: name,
                    deprecatedContext: function(arg) {
                        return arg.target
                    },
                    deprecatedArgs: deprecatedArgs || function(arg) {
                        return [arg.target, arg.jQueryEvent]
                    }
                }
        }
        function checkHeightLabelsInCanvas(points, canvas, isRotated) {
            var commonLabelSize = 0,
                canvasSize = canvas.end - canvas.start,
                label,
                bbox;
            for (var i = 0; i < points.length; i++) {
                label = points[i].getLabel();
                if (label.isVisible()) {
                    bbox = label.getBoundingRect();
                    commonLabelSize += isRotated ? bbox.width : bbox.height
                }
                else
                    points[i] = null
            }
            if (canvasSize > 0)
                while (commonLabelSize > canvasSize)
                    commonLabelSize -= killSmallValues(points, isRotated)
        }
        function killSmallValues(points, isRotated) {
            var smallestValuePoint = {originalValue: Infinity},
                label,
                bbox,
                indexOfPoint;
            _each(points, function(index, point) {
                if (point && smallestValuePoint.originalValue >= point.originalValue) {
                    smallestValuePoint = point;
                    indexOfPoint = index
                }
            });
            if (indexOfPoint !== null) {
                label = points[indexOfPoint].getLabel();
                bbox = label.getBoundingRect();
                label.hide();
                points[indexOfPoint] = null;
                return isRotated ? bbox.width : bbox.height
            }
            return 0
        }
        function resolveLabelOverlappingInOneDirection(points, canvas, isRotated, shiftFunction) {
            var stubCanvas = {
                    start: isRotated ? canvas.left : canvas.top,
                    end: isRotated ? canvas.width - canvas.right : canvas.height - canvas.bottom
                };
            checkHeightLabelsInCanvas(points, stubCanvas, isRotated);
            var rollingStocks = $.map(points, function(point) {
                    return point && new RollingStock(point, isRotated, shiftFunction)
                });
            rollingStocks.sort(function(a, b) {
                return a.getPointPosition() - b.getPointPosition()
            });
            if (!checkStackOverlap(rollingStocks))
                return;
            rollingStocks.reverse();
            moveRollingStock(rollingStocks, stubCanvas)
        }
        function overlapRollingStock(firstRolling, secondRolling) {
            if (!firstRolling || !secondRolling)
                return;
            return firstRolling.getBoundingRect().end > secondRolling.getBoundingRect().start
        }
        function checkStackOverlap(rollingStocks) {
            var i,
                j,
                currentRollingStock,
                nextRollingStock,
                overlap;
            for (i = 0; i < rollingStocks.length; i++) {
                currentRollingStock = rollingStocks[i];
                for (j = i + 1; j < rollingStocks.length; j++) {
                    nextRollingStock = rollingStocks[j];
                    if (overlapRollingStock(currentRollingStock, nextRollingStock)) {
                        currentRollingStock.toChain(nextRollingStock);
                        overlap = true;
                        rollingStocks[j] = null
                    }
                }
            }
            return overlap
        }
        function moveRollingStock(rollingStocks, canvas) {
            var i,
                j,
                currentRollingStock,
                nextRollingStock,
                currentBBox,
                nextBBox;
            for (i = 0; i < rollingStocks.length; i++) {
                currentRollingStock = rollingStocks[i];
                if (rollingStocksIsOut(currentRollingStock, canvas)) {
                    currentBBox = currentRollingStock.getBoundingRect();
                    for (j = i + 1; j < rollingStocks.length; j++) {
                        nextRollingStock = rollingStocks[j];
                        if (!nextRollingStock)
                            continue;
                        nextBBox = nextRollingStock.getBoundingRect();
                        if (nextBBox.end > currentBBox.start - (currentBBox.end - canvas.end)) {
                            nextRollingStock.toChain(currentRollingStock);
                            rollingStocks[i] = currentRollingStock = null;
                            break
                        }
                    }
                }
                currentRollingStock && currentRollingStock.setRollingStockInCanvas(canvas)
            }
        }
        function rollingStocksIsOut(rollingStock, canvas) {
            return rollingStock && rollingStock.getBoundingRect().end > canvas.end
        }
        function RollingStock(point, isRotated, shiftFunction) {
            var label = point.getLabel(),
                bbox = label.getBoundingRect();
            this.labels = [label];
            this.points = [point];
            this.shiftFunction = shiftFunction;
            this._bbox = {
                start: isRotated ? bbox.x : bbox.y,
                width: isRotated ? bbox.width : bbox.height,
                end: isRotated ? bbox.x + bbox.width : bbox.y + bbox.height
            };
            this._pointPositionInitialize = isRotated ? point.getBoundaryCoords().x : point.getBoundaryCoords().y;
            return this
        }
        RollingStock.prototype = {
            toChain: function(nextRollingStock) {
                var nextRollingStockBBox = nextRollingStock.getBoundingRect();
                nextRollingStock.shift(nextRollingStockBBox.start - this._bbox.end);
                this._changeBoxWidth(nextRollingStockBBox.width);
                this.labels = this.labels.concat(nextRollingStock.labels);
                this.points = this.points.concat(nextRollingStock.points)
            },
            getBoundingRect: function() {
                return this._bbox
            },
            shift: function(shiftLength) {
                var shiftFunction = this.shiftFunction;
                _each(this.labels, function(index, label) {
                    var bbox = label.getBoundingRect(),
                        coords = shiftFunction(bbox, shiftLength, label);
                    label.shift(coords.x, coords.y)
                });
                this._bbox.end -= shiftLength;
                this._bbox.start -= shiftLength
            },
            setRollingStockInCanvas: function(canvas) {
                if (this._bbox.end > canvas.end)
                    this.shift(this._bbox.end - canvas.end)
            },
            getPointPosition: function() {
                return this._pointPositionInitialize
            },
            _changeBoxWidth: function(width) {
                this._bbox.end += width;
                this._bbox.width += width
            }
        };
        function getLegendFields(name) {
            return {
                    nameField: name + 'Name',
                    colorField: name + 'Color',
                    indexField: name + 'Index'
                }
        }
        function getLegendSettings(legendDataField) {
            var formatObjectFields = getLegendFields(legendDataField);
            return {
                    getFormatObject: function(data) {
                        var res = {};
                        res[formatObjectFields.indexField] = data.id;
                        res[formatObjectFields.colorField] = data.states.normal.fill;
                        res[formatObjectFields.nameField] = data.text;
                        return res
                    },
                    textField: formatObjectFields.nameField
                }
        }
        function checkOverlapping(firstRect, secondRect) {
            return (firstRect.x <= secondRect.x && secondRect.x <= firstRect.x + firstRect.width || firstRect.x >= secondRect.x && firstRect.x <= secondRect.x + secondRect.width) && (firstRect.y <= secondRect.y && secondRect.y <= firstRect.y + firstRect.height || firstRect.y >= secondRect.y && firstRect.y <= secondRect.y + secondRect.height)
        }
        charts.overlapping = {resolveLabelOverlappingInOneDirection: resolveLabelOverlappingInOneDirection};
        charts.BaseChart = core.BaseWidget.inherit({
            _eventsMap: $.extend({}, core.BaseWidget.prototype._eventsMap, {
                onSeriesClick: createEventMapObject("seriesClick"),
                onPointClick: createEventMapObject("pointClick"),
                onArgumentAxisClick: createEventMapObject("argumentAxisClick", function(arg) {
                    return [arg.target, arg.argument, arg.jQueryEvent]
                }),
                onLegendClick: createEventMapObject("legendClick"),
                onSeriesSelectionChanged: createEventMapObject('seriesSelectionChanged'),
                onPointSelectionChanged: createEventMapObject('pointSelectionChanged'),
                onSeriesHoverChanged: createEventMapObject('seriesHoverChanged'),
                onPointHoverChanged: createEventMapObject('pointHoverChanged'),
                onTooltipShown: createEventMapObject('tooltipShown'),
                onTooltipHidden: createEventMapObject('tooltipHidden'),
                onDone: createEventMapObject("done"),
                seriesClick: {newName: 'onSeriesClick'},
                pointClick: {newName: 'onPointClick'},
                argumentAxisClick: {newName: 'onArgumentAxisClick'},
                legendClick: {newName: 'onLegendClick'},
                pointHoverChanged: {newName: 'onPointHoverChanged'},
                seriesSelectionChanged: {newName: 'onSeriesSelectionChanged'},
                pointSelectionChanged: {newName: 'onPointSelectionChanged'},
                seriesHoverChanged: {newName: 'onSeriesHoverChanged'},
                tooltipShown: {newName: 'onTooltipShown'},
                tooltipHidden: {newName: 'onTooltipHidden'},
                done: {newName: 'onDone'}
            }),
            _setDeprecatedOptions: function() {
                this.callBase();
                $.extend(this._deprecatedOptions, {
                    seriesClick: {
                        since: '14.2',
                        message: "Use the 'onSeriesClick' option instead"
                    },
                    pointClick: {
                        since: '14.2',
                        message: "Use the 'onPointClick' option instead"
                    },
                    argumentAxisClick: {
                        since: '14.2',
                        message: "Use the 'onArgumentAxisClick' option instead"
                    },
                    legendClick: {
                        since: '14.2',
                        message: "Use the 'onLegendClick' option instead"
                    },
                    seriesSelectionChanged: {
                        since: '14.2',
                        message: "Use the 'onSeriesSelectionChanged' option instead"
                    },
                    pointSelectionChanged: {
                        since: '14.2',
                        message: "Use the 'onPointSelectionChanged' option instead"
                    },
                    seriesHoverChanged: {
                        since: '14.2',
                        message: "Use the 'onSeriesHoverChanged' option instead"
                    },
                    pointHoverChanged: {
                        since: '14.2',
                        message: "Use the 'onPointHoverChanged' option instead"
                    },
                    tooltipShown: {
                        since: '14.2',
                        message: "Use the 'onTooltipShown' option instead"
                    },
                    tooltipHidden: {
                        since: '14.2',
                        message: "Use the 'onTooltipHidden' option instead"
                    },
                    done: {
                        since: '14.2',
                        message: "Use the 'onDone' option instead"
                    }
                })
            },
            _rootClassPrefix: "dxc",
            _rootClass: "dxc-chart",
            _init: function() {
                var that = this;
                that.callBase.apply(that, arguments);
                that._reinit()
            },
            _createThemeManager: function() {
                var option = this.option(),
                    themeManager = charts.factory.createThemeManager(option, this._chartType);
                themeManager.setTheme(option.theme, option.rtlEnabled);
                return themeManager
            },
            _initCore: function() {
                var that = this;
                that._canvasClipRect = that._renderer.clipRect();
                that._createHtmlStructure();
                that._createLegend();
                that._needHandleRenderComplete = true;
                that.layoutManager = charts.factory.createChartLayoutManager(that._layoutManagerOptions());
                that._createScrollBar();
                that._$element.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()
                })
            },
            _layoutManagerOptions: function() {
                return this._themeManager.getOptions("adaptiveLayout")
            },
            _reinit: function(needRedraw) {
                var that = this;
                charts._setCanvasValues(that._canvas);
                that._createTracker();
                that._reinitAxes();
                that._reinitDataSource();
                if (!that.series)
                    that._dataSpecificInit();
                that._correctAxes();
                needRedraw && that._endLoading(function() {
                    that._render({force: true})
                })
            },
            _createHtmlStructure: function() {
                var that = this,
                    renderer = that._renderer;
                that._backgroundRect = renderer.rect(0, 0, 0, 0).attr({
                    fill: "gray",
                    opacity: 0.0001
                });
                that._panesBackgroundGroup = renderer.g().attr({'class': 'dxc-background'});
                that._titleGroup = renderer.g().attr({'class': 'dxc-title'});
                that._legendGroup = renderer.g().attr({
                    'class': 'dxc-legend',
                    clipId: that._getCanvasClipRectID()
                });
                that._stripsGroup = renderer.g().attr({'class': 'dxc-strips-group'});
                that._constantLinesGroup = renderer.g().attr({'class': 'dxc-constant-lines-group'});
                that._axesGroup = renderer.g().attr({'class': 'dxc-axes-group'});
                that._gridGroup = renderer.g().attr({'class': 'dxc-grids-group'});
                that._panesBorderGroup = renderer.g().attr({'class': 'dxc-border'});
                that._labelAxesGroup = renderer.g().attr({'class': 'dxc-strips-labels-group'});
                that._scrollBarGroup = renderer.g().attr({'class': 'dxc-scroll-bar'});
                that._seriesGroup = renderer.g().attr({'class': 'dxc-series-group'});
                that._labelsGroup = renderer.g().attr({'class': 'dxc-labels-group'});
                that._crosshairCursorGroup = renderer.g().attr({'class': 'dxc-crosshair-cursor'})
            },
            _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
            },
            _disposeCore: function() {
                var that = this,
                    disposeObject = function(propName) {
                        if (that[propName]) {
                            that[propName].dispose();
                            that[propName] = null
                        }
                    },
                    disposeObjectsInArray = this._disposeObjectsInArray;
                clearTimeout(that._delayedRedraw);
                that._renderer.stopAllAnimations();
                disposeObjectsInArray.call(that, "businessRanges", ["arg", "val"]);
                that.translators = null;
                disposeObjectsInArray.call(that, "series");
                disposeObject("layoutManager");
                disposeObject("tracker");
                disposeObject("chartTitle");
                disposeObject("_crosshair");
                that.paneAxis = null;
                that._userOptions = null;
                that._canvas = null;
                disposeObject("_canvasClipRect");
                disposeObject("_panesBackgroundGroup");
                disposeObject("_titleGroup");
                disposeObject("_scrollBarGroup");
                disposeObject("_legendGroup");
                disposeObject("_stripsGroup");
                disposeObject("_constantLinesGroup");
                disposeObject("_axesGroup");
                disposeObject("_gridGroup");
                disposeObject("_labelAxesGroup");
                disposeObject("_panesBorderGroup");
                disposeObject("_seriesGroup");
                disposeObject("_labelsGroup");
                disposeObject("_crosshairCursorGroup")
            },
            _getAnimationOptions: function() {
                return $.extend({}, DEFAULT_ANIMATION_OPTIONS, this._themeManager.getOptions("animation"))
            },
            _getDefaultSize: function() {
                return {
                        width: 400,
                        height: 400
                    }
            },
            _getOption: function(name) {
                return this._themeManager.getOptions(name)
            },
            _reinitDataSource: function() {
                this._refreshDataSource()
            },
            _applySize: $.noop,
            _resize: function() {
                if (this._updateLockCount)
                    this._processRefreshData("_resize");
                else
                    this._render(this.__renderOptions || {
                        animate: false,
                        isResize: true,
                        updateTracker: false
                    })
            },
            _createTracker: function() {
                var that = this,
                    themeManager = that._themeManager;
                if (that.tracker)
                    that.tracker.dispose();
                that.tracker = charts.factory.createTracker({
                    seriesSelectionMode: themeManager.getOptions('seriesSelectionMode'),
                    pointSelectionMode: themeManager.getOptions('pointSelectionMode'),
                    seriesGroup: that._seriesGroup,
                    renderer: that._renderer,
                    tooltip: that._tooltip,
                    eventTrigger: that._eventTrigger
                }, that.NAME)
            },
            _getTrackerSettings: function() {
                var that = this;
                return {
                        series: that.series,
                        legend: that.legend,
                        legendCallback: $.proxy(that.legend.getActionCallback, that.legend)
                    }
            },
            _updateTracker: function() {
                this.tracker.update(this._getTrackerSettings())
            },
            _render: function(_options) {
                var that = this,
                    drawOptions,
                    originalCanvas;
                if (!that._initialized)
                    return;
                if (!that._canvas)
                    return;
                that._resetIsReady();
                drawOptions = that._prepareDrawOptions(_options);
                clearTimeout(that._delayedRedraw);
                originalCanvas = that._canvas;
                that._canvas = $.extend({}, that._canvas);
                if (drawOptions.recreateCanvas)
                    that.__currentCanvas = that._canvas;
                else
                    that._canvas = that.__currentCanvas;
                that.DEBUG_canvas = that._canvas;
                if (drawOptions.recreateCanvas) {
                    that._reappendLoadingIndicator();
                    that._updateCanvasClipRect()
                }
                that._renderer.stopAllAnimations(true);
                charts._setCanvasValues(that._canvas);
                that._cleanGroups(drawOptions);
                that._renderElements(drawOptions);
                that._canvas = originalCanvas
            },
            _renderElements: function(drawOptions) {
                var that = this,
                    preparedOptions = that._prepareToRender(drawOptions),
                    isRotated = that._isRotated(),
                    isLegendInside = that._isLegendInside(),
                    trackerCanvases = [],
                    layoutTargets = that._getLayoutTargets(),
                    dirtyCanvas = $.extend({}, that._canvas),
                    argBusinessRange,
                    zoomMinArg,
                    zoomMaxArg;
                !drawOptions.isResize && that._scheduleLoadingIndicatorHiding();
                that.DEBUG_dirtyCanvas = dirtyCanvas;
                that._renderTitleAndLegend(drawOptions, isLegendInside);
                that._renderAxes(drawOptions, preparedOptions, isRotated);
                if (drawOptions.drawTitle && drawOptions.drawLegend && drawOptions.adjustAxes && that.layoutManager.needMoreSpaceForPanesCanvas(that._getLayoutTargets(), isRotated)) {
                    that.layoutManager.updateDrawnElements(that._getAxesForTransform(isRotated), that._canvas, dirtyCanvas, that._getLayoutTargets(), isRotated);
                    if (that.chartTitle)
                        that.layoutManager.correctSizeElement(that.chartTitle, that._canvas);
                    that._updateCanvasClipRect(dirtyCanvas);
                    that._updateAxesLayout(drawOptions, preparedOptions, isRotated)
                }
                drawOptions.drawTitle && drawOptions.drawLegend && drawOptions.adjustAxes && that.layoutManager.placeDrawnElements(that._canvas);
                that._applyClipRects(preparedOptions);
                that._appendSeriesGroups();
                that._createCrosshairCursor();
                $.each(layoutTargets, function() {
                    var canvas = this.canvas;
                    trackerCanvases.push({
                        left: canvas.left,
                        right: canvas.width - canvas.right,
                        top: canvas.top,
                        bottom: canvas.height - canvas.bottom
                    })
                });
                if (that._scrollBar) {
                    argBusinessRange = that.businessRanges[0].arg;
                    if (argBusinessRange.categories && argBusinessRange.categories.length <= 1)
                        zoomMinArg = zoomMaxArg = undefined;
                    else {
                        zoomMinArg = argBusinessRange.minVisible;
                        zoomMaxArg = argBusinessRange.maxVisible
                    }
                    that._scrollBar.init(argBusinessRange, layoutTargets[0].canvas).setPosition(zoomMinArg, zoomMaxArg)
                }
                drawOptions.updateTracker && that._updateTracker();
                that.tracker.setCanvases({
                    left: 0,
                    right: that._canvas.width,
                    top: 0,
                    bottom: that._canvas.height
                }, trackerCanvases);
                that._updateLegendPosition(drawOptions, isLegendInside);
                var timeout = that._getSeriesRenderTimeout(drawOptions);
                if (timeout >= 0)
                    that._delayedRedraw = setTimeout(renderSeries, timeout);
                else
                    renderSeries();
                function renderSeries() {
                    that._renderSeries(drawOptions, isRotated, isLegendInside)
                }
            },
            _createCrosshairCursor: $.noop,
            _appendSeriesGroups: function() {
                var that = this,
                    root = that._renderer.root;
                that._seriesGroup.append(root);
                that._labelsGroup.append(root);
                that._appendAdditionalSeriesGroups()
            },
            _renderSeries: function(drawOptions, isRotated, isLegendInside) {
                var that = this,
                    themeManager = that._themeManager,
                    resolveLabelOverlapping = themeManager.getOptions("resolveLabelOverlapping");
                drawOptions.hideLayoutLabels = that.layoutManager.needMoreSpaceForPanesCanvas(that._getLayoutTargets(), that._isRotated()) && !themeManager.getOptions("adaptiveLayout").keepLabels;
                that._drawSeries(drawOptions, isRotated);
                resolveLabelOverlapping !== "none" && that._resolveLabelOverlapping(resolveLabelOverlapping);
                that._adjustSeries();
                that._renderTrackers(isLegendInside);
                if (that._dataSource && that._dataSource.isLoaded())
                    that._fulfillLoadingIndicatorHiding();
                that.tracker.repairTooltip();
                that._drawn();
                that._renderCompleteHandler()
            },
            _getAnimateOption: function(series, drawOptions) {
                return drawOptions.animate && series.getPoints().length <= drawOptions.animationPointsLimit && this._renderer.animationEnabled()
            },
            _resolveLabelOverlapping: function(resolveLabelOverlapping) {
                var func;
                switch (resolveLabelOverlapping) {
                    case"stack":
                        func = this._resolveLabelOverlappingStack;
                        break;
                    case"hide":
                        func = this._resolveLabelOverlappingHide;
                        break;
                    case"shift":
                        func = this._resolveLabelOverlappingShift;
                        break
                }
                $.isFunction(func) && func.call(this)
            },
            _getVisibleSeries: function() {
                return $.grep(this.getAllSeries(), function(series) {
                        return series.isVisible()
                    })
            },
            _resolveLabelOverlappingHide: function() {
                var labels = $.map(this._getVisibleSeries(), function(series) {
                        return $.map(series.getVisiblePoints(), function(point) {
                                return point.getLabel()
                            })
                    }),
                    currenctLabel,
                    nextLabel,
                    currenctLabelRect,
                    nextLabelRect,
                    i,
                    j;
                for (i = 0; i < labels.length; i++) {
                    currenctLabel = labels[i];
                    currenctLabelRect = currenctLabel.getBoundingRect();
                    if (!currenctLabel.isVisible())
                        continue;
                    for (j = i + 1; j < labels.length; j++) {
                        nextLabel = labels[j];
                        nextLabelRect = nextLabel.getBoundingRect();
                        if (checkOverlapping(currenctLabelRect, nextLabelRect))
                            nextLabel.hide()
                    }
                }
            },
            _cleanGroups: function(drawOptions) {
                var that = this;
                that._stripsGroup.remove();
                that._constantLinesGroup.remove();
                that._axesGroup.remove();
                that._gridGroup.remove();
                that._labelAxesGroup.remove();
                that._labelsGroup.remove();
                that._crosshairCursorGroup.remove();
                if (!drawOptions || drawOptions.drawLegend)
                    that._legendGroup.remove().clear();
                if (!drawOptions || drawOptions.drawTitle)
                    that._titleGroup.remove().clear();
                that._stripsGroup.clear();
                that._constantLinesGroup.clear();
                that._axesGroup.clear();
                that._gridGroup.clear();
                that._labelAxesGroup.clear();
                that._labelsGroup.clear();
                that._crosshairCursorGroup.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, that._titleGroup)
            },
            _createLegend: function() {
                var legendSettings = getLegendSettings(this._legendDataField);
                this.legend = core.CoreFactory.createLegend({
                    renderer: this._renderer,
                    group: this._legendGroup,
                    backgroundClass: 'dxc-border',
                    itemGroupClass: 'dxc-item',
                    textField: legendSettings.textField,
                    getFormatObject: legendSettings.getFormatObject
                })
            },
            _updateLegend: function() {
                var that = this,
                    themeManager = that._themeManager,
                    legendOptions = themeManager.getOptions('legend'),
                    legendData = that._getLegendData();
                legendOptions.containerBackgroundColor = themeManager.getOptions("containerBackgroundColor");
                legendOptions._incidentOccured = that._incidentOccured;
                that.legend.update(legendData, legendOptions)
            },
            _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,
                    updateTracker: true
                }, drawOptions, this.__renderOptions);
                if (!_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
            },
            _getLegendData: function() {
                var that = this;
                return _map(this._getLegendTargets(), function(item) {
                        var style = item.getLegendStyles(),
                            textOpacity,
                            opacity = style.normal.opacity;
                        if (!item.isVisible()) {
                            if (!_isDefined(opacity) || opacity > DEFAULT_OPACITY)
                                opacity = DEFAULT_OPACITY;
                            textOpacity = DEFAULT_OPACITY
                        }
                        return {
                                text: item[that._legendItemTextField],
                                id: item.index,
                                textOpacity: textOpacity,
                                states: {
                                    hover: style.hover,
                                    selection: style.selection,
                                    normal: _extend({}, style.normal, {opacity: opacity})
                                }
                            }
                    })
            },
            _seriesVisibilityChanged: function() {
                this._specialProcessSeries();
                this._populateBusinessRange();
                this._renderer.stopAllAnimations(true);
                this._updateLegend();
                this._render({
                    force: true,
                    asyncSeriesRendering: false,
                    updateTracker: false
                })
            },
            _disposeSeries: function() {
                var that = this;
                $.each(that.series || [], function(_, series) {
                    series.dispose()
                });
                that.series = null;
                $.each(that.seriesFamilies || [], function(_, family) {
                    family.dispose()
                });
                that.seriesFamilies = null;
                that._needHandleRenderComplete = true
            },
            _optionChanged: function(args) {
                var that = this,
                    themeManager = that._themeManager,
                    name = args.name;
                themeManager.resetOptions(name);
                themeManager.update(that._options);
                that._scheduleLoadingIndicatorHiding();
                if (name === 'animation') {
                    that._renderer.updateAnimationOptions(that._getAnimationOptions());
                    return
                }
                switch (name) {
                    case'size':
                    case'margin':
                        that._invalidate();
                        break;
                    case'dataSource':
                        that._needHandleRenderComplete = true;
                        that._processRefreshData('_reinitDataSource');
                        break;
                    case'palette':
                        themeManager.updatePalette(that.option(name));
                        that._refreshSeries('_dataInit');
                        break;
                    case'series':
                    case'commonSeriesSettings':
                    case'containerBackgroundColor':
                    case'dataPrepareSettings':
                        that._refreshSeries('_dataInit');
                        break;
                    case'legend':
                    case'seriesTemplate':
                        that._processRefreshData('_dataInit');
                        break;
                    case'title':
                        that._processRefreshData('force_render');
                        break;
                    case'valueAxis':
                    case'argumentAxis':
                    case'commonAxisSettings':
                    case'panes':
                    case'defaultPane':
                        that._refreshSeries('reinit');
                        that.paneAxis = {};
                        break;
                    case'rotated':
                        that._createScrollBar();
                        that._refreshSeries('reinit');
                        break;
                    case'customizePoint':
                    case'customizeLabel':
                        that._refreshSeries('reinit');
                        break;
                    case'scrollBar':
                        that._createScrollBar();
                        that._processRefreshData('force_render');
                        break;
                    case'tooltip':
                        that._organizeStackPoints();
                        break;
                    default:
                        that._processRefreshData('reinit')
                }
                that.callBase.apply(that, arguments)
            },
            _handleThemeOptionsCore: function() {
                var that = this;
                if (that._initialized) {
                    that._scheduleLoadingIndicatorHiding();
                    that._refreshSeries('reinit');
                    that.beginUpdate();
                    that._invalidate();
                    that.endUpdate()
                }
            },
            _refreshSeries: function(actionName) {
                this._disposeSeries();
                this._processRefreshData(actionName)
            },
            _refresh: function() {
                var that = this;
                that._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}
            },
            _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.attr({
                    x: canvas.left,
                    y: canvas.top,
                    width: width,
                    height: height
                });
                that._backgroundRect.attr({
                    x: canvas.left,
                    y: canvas.top,
                    width: width,
                    height: height
                }).append(that._renderer.root).toBackground()
            },
            _getCanvasClipRectID: function() {
                return this._canvasClipRect.id
            },
            _dataSourceChangedHandler: function() {
                this._resetZoom();
                this._scheduleLoadingIndicatorHiding();
                this._dataInit()
            },
            _dataInit: function() {
                clearTimeout(this._delayedRedraw);
                this._dataSpecificInit(true)
            },
            _dataSpecificInit: function(needRedraw) {
                this.series = this.series || this._populateSeries();
                this._repopulateSeries();
                this._seriesPopulatedHandler(needRedraw)
            },
            _seriesPopulatedHandler: function(needRedraw) {
                var that = this;
                that._seriesPopulatedHandlerCore();
                that._populateBusinessRange();
                that._updateLegend();
                needRedraw && that._endLoading(function() {
                    that._render({force: true})
                })
            },
            _repopulateSeries: function() {
                var that = this,
                    parsedData,
                    themeManager = that._themeManager,
                    data = that._dataSource && that._dataSource.items(),
                    dataValidatorOptions = themeManager.getOptions('dataPrepareSettings'),
                    seriesTemplate = 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 = DX.viz.core.CoreFactory.createDataValidator(data, that._groupedSeries, that._incidentOccured, dataValidatorOptions);
                parsedData = that._dataValidator.validate();
                themeManager.resetPalette();
                $.each(that.series, function(_, singleSeries) {
                    singleSeries.updateData(parsedData);
                    that._processSingleSeries(singleSeries)
                });
                that._organizeStackPoints()
            },
            _organizeStackPoints: function() {
                var that = this,
                    themeManager = that._themeManager,
                    sharedTooltip = themeManager.getOptions("tooltip").shared,
                    stackPoints = {};
                $.each(that.series || [], function(_, singleSeries) {
                    that._resetStackPoints(singleSeries);
                    sharedTooltip && that._prepareStackPoints(singleSeries, stackPoints, true)
                })
            },
            _renderCompleteHandler: function() {
                var that = this,
                    allSeriesInited = true;
                if (that._needHandleRenderComplete) {
                    $.each(that.series, function(_, s) {
                        allSeriesInited = allSeriesInited && s.canRenderCompleteHandle()
                    });
                    if (allSeriesInited) {
                        that._needHandleRenderComplete = false;
                        that._eventTrigger("done", {target: 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._renderer.root);
                    that._drawTitle();
                    drawElements.push(that.chartTitle)
                }
                if (drawLegend) {
                    that._legendGroup.append(that._renderer.root);
                    drawElements.push(that.legend)
                }
                drawElements.length && that.layoutManager.drawElements(drawElements, that._canvas);
                if (drawTitle)
                    that.layoutManager.correctSizeElement(that.chartTitle, that._canvas)
            },
            _prepareStackPoints: $.noop,
            _resetStackPoints: $.noop,
            _resetZoom: $.noop,
            _dataIsReady: function() {
                return this._isDataSourceReady()
            },
            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]
            },
            clearSelection: function clearSelection() {
                this.tracker.clearSelection()
            },
            hideTooltip: function() {
                this.tracker._hideTooltip()
            },
            render: function(renderOptions) {
                var that = this;
                that.__renderOptions = renderOptions;
                that.__forceRender = renderOptions && renderOptions.force;
                that.callBase.apply(that, arguments);
                that.__renderOptions = that.__forceRender = null;
                return that
            },
            getSize: function() {
                var canvas = this._canvas || {};
                return {
                        width: canvas.width,
                        height: canvas.height
                    }
            }
        }).include(ui.DataHelperMixin)
    })(jQuery, DevExpress);
    /*! Module viz-charts, file advancedChart.js */
    (function($, DX, undefined) {
        var charts = DX.viz.charts,
            utils = DX.utils,
            core = DX.viz.core,
            DEFAULT_AXIS_NAME = "defaultAxisName",
            _isArray = utils.isArray,
            _isDefined = utils.isDefined,
            _each = $.each,
            _extend = $.extend,
            _map = $.map,
            MIN = 'min',
            MAX = 'max';
        function prepareAxis(axisOptions) {
            return _isArray(axisOptions) ? axisOptions.length === 0 ? [{}] : axisOptions : [axisOptions]
        }
        function unique(array) {
            var values = {},
                i,
                len = array.length;
            for (i = 0; i < len; i++)
                values[array[i]] = true;
            return _map(values, function(_, key) {
                    return key
                })
        }
        function prepareVisibleArea(visibleArea, axisRange, useAggregation, aggregationRange) {
            visibleArea.minVal = axisRange.min;
            visibleArea.maxVal = axisRange.max;
            if (useAggregation && !visibleArea.adjustOnZoom) {
                visibleArea.minVal = _isDefined(visibleArea.minVal) ? visibleArea.minVal : aggregationRange.val.min;
                visibleArea.maxVal = _isDefined(visibleArea.maxVal) ? visibleArea.maxVal : aggregationRange.val.max
            }
        }
        function setTemplateFields(data, templateData, series) {
            _each(data, function(_, data) {
                _each(series.getTeamplatedFields(), function(_, field) {
                    data[field.teamplateField] = data[field.originalField]
                });
                templateData.push(data)
            });
            series.updateTeamplateFieldNames()
        }
        charts.AdvancedChart = charts.BaseChart.inherit({
            _dispose: function() {
                var that = this,
                    disposeObjectsInArray = this._disposeObjectsInArray;
                that.callBase();
                that.panes = null;
                if (that.legend) {
                    that.legend.dispose();
                    that.legend = null
                }
                disposeObjectsInArray.call(that, "panesBackground");
                disposeObjectsInArray.call(that, "seriesFamilies");
                that._disposeAxes()
            },
            _reinitAxes: function() {
                this.translators = {};
                this.panes = this._createPanes();
                this._populateAxes()
            },
            _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] : [],
                    data,
                    extraOptions = that._getExtraOptions(),
                    particularSeriesOptions,
                    particularSeries,
                    rotated = that._isRotated(),
                    i;
                that.teamplateData = [];
                that._disposeSeries();
                that.series = [];
                themeManager.resetPalette();
                for (i = 0; i < allSeriesOptions.length; i++) {
                    particularSeriesOptions = _extend(true, {}, allSeriesOptions[i], extraOptions);
                    data = particularSeriesOptions.data;
                    particularSeriesOptions.data = null;
                    particularSeriesOptions.rotated = rotated;
                    particularSeriesOptions.customizePoint = themeManager.getOptions("customizePoint");
                    particularSeriesOptions.customizeLabel = themeManager.getOptions("customizeLabel");
                    particularSeriesOptions.visibilityChanged = $.proxy(that._seriesVisibilityChanged, that);
                    particularSeriesOptions.resolveLabelsOverlapping = themeManager.getOptions("resolveLabelsOverlapping");
                    particularSeriesOptions.incidentOccured = that._incidentOccured;
                    if (!particularSeriesOptions.name)
                        particularSeriesOptions.name = "Series " + (i + 1).toString();
                    var seriesTheme = themeManager.getOptions("series", particularSeriesOptions);
                    if (!that._checkPaneName(seriesTheme))
                        continue;
                    particularSeries = core.CoreFactory.createSeries({
                        renderer: that._renderer,
                        seriesGroup: that._seriesGroup,
                        labelsGroup: that._labelsGroup
                    }, seriesTheme);
                    if (!particularSeries.isUpdated)
                        that._incidentOccured("E2101", [seriesTheme.type]);
                    else {
                        particularSeries.index = that.series.length;
                        that.series.push(particularSeries);
                        if (hasSeriesTemplate)
                            setTemplateFields(data, that.teamplateData, particularSeries)
                    }
                }
                return that.series
            },
            _populateAxes: function() {
                var that = this,
                    valueAxes = [],
                    argumentAxes,
                    panes = that.panes,
                    rotated = that._isRotated(),
                    valueAxisOptions = that.option("valueAxis") || {},
                    argumentOption = that.option("argumentAxis") || {},
                    argumentAxesOptions = prepareAxis(argumentOption)[0],
                    valueAxesOptions = prepareAxis(valueAxisOptions),
                    axisNames = [],
                    valueAxesCounter = 0,
                    paneWithNonVirtualAxis,
                    crosshairOptions = that._getOption("crosshair") || {},
                    crosshairEnabled = crosshairOptions.enabled,
                    horCrosshairEnabled = crosshairEnabled && crosshairOptions.horizontalLine.visible,
                    verCrosshairEnabled = crosshairEnabled && crosshairOptions.verticalLine.visible;
                function getNextAxisName() {
                    return DEFAULT_AXIS_NAME + valueAxesCounter++
                }
                that._disposeAxes();
                if (rotated)
                    paneWithNonVirtualAxis = argumentAxesOptions.position === "right" ? panes[panes.length - 1].name : panes[0].name;
                else
                    paneWithNonVirtualAxis = argumentAxesOptions.position === "top" ? panes[0].name : panes[panes.length - 1].name;
                argumentAxes = _map(panes, function(pane) {
                    return that._createAxis("argumentAxis", argumentAxesOptions, {
                            virtual: pane.name !== paneWithNonVirtualAxis,
                            pane: pane.name,
                            crosshairEnabled: rotated ? horCrosshairEnabled : verCrosshairEnabled
                        }, rotated)
                });
                _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._createAxis("valueAxis", axisOptions, {
                            name: name || getNextAxisName(),
                            pane: pane,
                            priority: priority,
                            crosshairEnabled: rotated ? verCrosshairEnabled : horCrosshairEnabled
                        }, rotated))
                    })
                });
                that._valueAxes = valueAxes;
                that._argumentAxes = argumentAxes
            },
            _prepareStackPoints: function(singleSeries, stackPoints, isSharedTooltip) {
                var points = singleSeries.getPoints(),
                    stackName = singleSeries.getStackName();
                _each(points, function(_, point) {
                    var argument = point.argument;
                    if (!stackPoints[argument]) {
                        stackPoints[argument] = {};
                        stackPoints[argument][null] = []
                    }
                    if (stackName && !_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)
                        });
                    if (isSharedTooltip) {
                        point.stackPoints = stackPoints[argument][stackName];
                        point.stackName = stackName
                    }
                })
            },
            _resetStackPoints: function(singleSeries) {
                _each(singleSeries.getPoints(), function(_, point) {
                    point.stackPoints = null;
                    point.stackName = null
                })
            },
            _disposeAxes: function() {
                var disposeObjectsInArray = this._disposeObjectsInArray;
                disposeObjectsInArray.call(this, "_argumentAxes");
                disposeObjectsInArray.call(this, "_valueAxes")
            },
            _drawAxes: function(panesBorderOptions, drawOptions, adjustUnits) {
                var that = this,
                    drawAxes = function(axes) {
                        _each(axes, function(_, axis) {
                            axis.draw(adjustUnits)
                        })
                    },
                    drawStaticAxisElements = function(axes) {
                        _each(axes, function(_i, axis) {
                            axis.drawGrids(panesBorderOptions[axis.pane])
                        })
                    };
                that._reinitTranslators();
                that._prepareAxesAndDraw(drawAxes, drawStaticAxisElements, drawOptions)
            },
            _appendAdditionalSeriesGroups: function() {
                var that = this,
                    root = that._renderer.root;
                that._crosshairCursorGroup.append(root);
                that._legendGroup.append(root);
                that._scrollBar && that._scrollBarGroup.append(root)
            },
            _getLegendTargets: function() {
                return _map(this.series, function(item) {
                        if (item.getOptions().showInLegend)
                            return item
                    })
            },
            _legendItemTextField: "name",
            _seriesPopulatedHandlerCore: function() {
                this._processSeriesFamilies();
                this._processValueAxisFormat()
            },
            _renderTrackers: function() {
                var that = this,
                    i;
                for (i = 0; i < that.series.length; ++i)
                    that.series[i].drawTrackers()
            },
            _specialProcessSeries: function() {
                this._processSeriesFamilies()
            },
            _processSeriesFamilies: function() {
                var that = this,
                    types = [],
                    families = [],
                    paneSeries,
                    themeManager = that._themeManager,
                    familyOptions = {
                        equalBarWidth: that._getEqualBarWidth(),
                        minBubbleSize: themeManager.getOptions("minBubbleSize"),
                        maxBubbleSize: themeManager.getOptions("maxBubbleSize")
                    };
                if (that.seriesFamilies && that.seriesFamilies.length) {
                    _each(that.seriesFamilies, function(_, family) {
                        family.updateOptions(familyOptions);
                        family.adjustSeriesValues()
                    });
                    return
                }
                _each(that.series, function(_, item) {
                    if ($.inArray(item.type, types) === -1)
                        types.push(item.type)
                });
                _each(that._getLayoutTargets(), function(_, pane) {
                    paneSeries = that._getSeriesForPane(pane.name);
                    _each(types, function(_, type) {
                        var family = core.CoreFactory.createSeriesFamily({
                                type: type,
                                pane: pane.name,
                                equalBarWidth: familyOptions.equalBarWidth,
                                minBubbleSize: familyOptions.minBubbleSize,
                                maxBubbleSize: familyOptions.maxBubbleSize
                            });
                        family.add(paneSeries);
                        family.adjustSeriesValues();
                        families.push(family)
                    })
                });
                that.seriesFamilies = families
            },
            _appendAxesGroups: function() {
                var that = this,
                    root = that._renderer.root;
                that._stripsGroup.append(root);
                that._gridGroup.append(root);
                that._axesGroup.append(root);
                that._constantLinesGroup.append(root);
                that._labelAxesGroup.append(root)
            },
            _updateAxesLayout: function(drawOptions, panesBorderOptions, rotated) {
                this.layoutManager.updatePanesCanvases(this._getLayoutTargets(), this._canvas, rotated);
                this._drawAxes(panesBorderOptions, drawOptions, true)
            },
            _populateBusinessRange: function(visibleArea) {
                var that = this,
                    businessRanges = [],
                    themeManager = that._themeManager,
                    rotated = that._isRotated(),
                    useAggregation = themeManager.getOptions('useAggregation'),
                    argAxes = that._argumentAxes,
                    lastArgAxis = argAxes[argAxes.length - 1],
                    calcInterval = lastArgAxis.calcInterval,
                    argRange = new core.Range({rotated: !!rotated}),
                    argBusinessRange;
                that._disposeObjectsInArray("businessRanges", ["arg", "val"]);
                _each(argAxes, function(_, axis) {
                    argRange.addRange(axis.getRangeData())
                });
                _each(that._groupedSeries, function(_, group) {
                    var groupRange = new core.Range({
                            rotated: !!rotated,
                            isValueRange: true,
                            pane: group.valueAxis.pane,
                            axis: group.valueAxis.name
                        }),
                        groupAxisRange = group.valueAxis.getRangeData();
                    groupRange.addRange(groupAxisRange);
                    _each(group, function(_, series) {
                        visibleArea && prepareVisibleArea(visibleArea, groupAxisRange, useAggregation, series._originalBusinessRange);
                        var seriesRange = series.getRangeData(visibleArea, calcInterval);
                        groupRange.addRange(seriesRange.val);
                        argRange.addRange(seriesRange.arg)
                    });
                    if (!groupRange.isDefined())
                        groupRange.setStubData(group.valueAxis.getOptions().valueType === 'datetime' ? 'datetime' : undefined);
                    if (group.valueAxis.getOptions().showZero)
                        groupRange.correctValueZeroLevel();
                    groupRange.checkZeroStick();
                    businessRanges.push({
                        val: groupRange,
                        arg: argRange
                    })
                });
                if (!argRange.isDefined())
                    argRange.setStubData(argAxes[0].getOptions().argumentType);
                if (visibleArea && visibleArea.notApplyMargins && argRange.axisType !== "discrete") {
                    argBusinessRange = argAxes[0].getTranslator().getBusinessRange();
                    argRange.addRange({
                        min: argBusinessRange.min,
                        max: argBusinessRange.max,
                        stick: true
                    })
                }
                that._correctBusinessRange(argRange, lastArgAxis);
                that.businessRanges = businessRanges
            },
            _correctBusinessRange: function(range, lastArgAxis) {
                var setTicksAtUnitBeginning = lastArgAxis.getOptions().setTicksAtUnitBeginning,
                    tickIntervalRange = {},
                    tickInterval = lastArgAxis.getOptions().tickInterval,
                    originInterval = tickInterval;
                tickInterval = $.isNumeric(tickInterval) ? tickInterval : utils.dateToMilliseconds(tickInterval);
                if (tickInterval && _isDefined(range[MIN]) && _isDefined(range[MAX]) && 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)
                }
            },
            _getArgumentAxes: function() {
                return this._argumentAxes
            },
            _getValueAxes: function() {
                return this._valueAxes
            },
            _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()
                })
            },
            _createAxis: function(typeSelector, userOptions, axisOptions, rotated) {
                var that = this,
                    renderingSettings = _extend({
                        renderer: that._renderer,
                        incidentOccured: that._incidentOccured,
                        axisClass: typeSelector === "argumentAxis" ? "arg" : "val",
                        stripsGroup: that._stripsGroup,
                        labelAxesGroup: that._labelAxesGroup,
                        constantLinesGroup: that._constantLinesGroup,
                        axesContainerGroup: that._axesGroup,
                        gridGroup: that._gridGroup
                    }, that._getAxisRenderingOptions(typeSelector, userOptions, rotated)),
                    axis;
                userOptions = that._prepareStripsAndConstantLines(typeSelector, userOptions, rotated);
                axis = new charts.axes.Axis(renderingSettings);
                axis.updateOptions(_extend(true, {}, userOptions, axisOptions, that._prepareAxisOptions(typeSelector, userOptions)));
                return axis
            },
            _getTrackerSettings: function() {
                return _extend(this.callBase(), {argumentAxis: this._argumentAxes})
            },
            _prepareStripsAndConstantLines: function(typeSelector, userOptions, rotated) {
                userOptions = this._themeManager.getOptions(typeSelector, userOptions, rotated);
                if (userOptions.strips)
                    _each(userOptions.strips, function(i) {
                        userOptions.strips[i] = _extend(true, {}, userOptions.stripStyle, userOptions.strips[i])
                    });
                if (userOptions.constantLines)
                    _each(userOptions.constantLines, function(i, line) {
                        userOptions.constantLines[i] = _extend(true, {}, userOptions.constantLineStyle, line)
                    });
                return userOptions
            },
            _legendDataField: 'series',
            _adjustSeries: $.noop
        })
    })(jQuery, DevExpress);
    /*! Module viz-charts, file chart.js */
    (function($, DX, undefined) {
        var viz = DX.viz,
            core = viz.core,
            charts = viz.charts,
            utils = DX.utils,
            MAX_ADJUSTMENT_ATTEMPTS = 5,
            DEFAULT_PANE_NAME = "default",
            ASYNC_SERIES_RENDERING_DELAY = 25,
            DEFAULT_PANES = [{
                    name: DEFAULT_PANE_NAME,
                    border: {}
                }],
            _map = $.map,
            _each = $.each,
            _extend = $.extend,
            _isArray = utils.isArray,
            _isDefined = utils.isDefined;
        function getFirstAxisNameForPane(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 = axes[0].name;
            return result
        }
        function hideGridsOnNonFirstValueAxisForPane(valAxes, paneName, synchronizeMultiAxes) {
            var axesForPane = [],
                firstShownAxis;
            _each(valAxes, function(_, axis) {
                if (axis.pane === paneName)
                    axesForPane.push(axis)
            });
            if (axesForPane.length > 1 && synchronizeMultiAxes)
                _each(axesForPane, function(_, axis) {
                    var gridOpt = axis.getOptions().grid,
                        minorGridOpt = axis.getOptions().minorGrid;
                    if (firstShownAxis && gridOpt && gridOpt.visible) {
                        gridOpt.visible = false;
                        minorGridOpt && (minorGridOpt.visible = false)
                    }
                    else
                        firstShownAxis = firstShownAxis ? firstShownAxis : gridOpt && gridOpt.visible
                })
        }
        function getPaneForAxis(paneAxis, axisNameWithoutPane) {
            var result;
            _each(paneAxis, function(paneName, pane) {
                _each(pane, function(axisName) {
                    if (axisNameWithoutPane === axisName) {
                        result = paneName;
                        return false
                    }
                })
            });
            return result
        }
        function findAxisOptions(valueAxes, valueAxesOptions, 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].getOptions();
                        result.priority = valueAxes[axInd].priority;
                        break
                    }
            return result
        }
        function findAxis(paneName, axisName, axes) {
            var axis,
                i;
            for (i = 0; i < axes.length; i++) {
                axis = axes[i];
                if (axis.name === axisName && axis.pane === paneName)
                    return axis
            }
        }
        function prepareSegmentRectPoints(left, top, width, height, borderOptions) {
            var maxSW = ~~((width < height ? width : height) / 2),
                sw = borderOptions.width || 0,
                newSW = sw < maxSW ? sw : maxSW;
            left = left + newSW / 2;
            top = top + newSW / 2;
            width = width - newSW;
            height = height - newSW;
            var right = left + width,
                bottom = top + height,
                points = [],
                segments = [],
                segmentSequence,
                visiblyOpt = 0,
                prevSegmentVisibility = 0;
            var allSegment = {
                    top: [[left, top], [right, top]],
                    right: [[right, top], [right, bottom]],
                    bottom: [[right, bottom], [left, bottom]],
                    left: [[left, bottom], [left, top]]
                };
            _each(allSegment, function(seg) {
                var visibility = !!borderOptions[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 = !!borderOptions[seg];
                if (!prevSegmentVisibility && segments.length) {
                    points.push(segments);
                    segments = []
                }
                if (segmentVisibility)
                    _each(allSegment[seg].slice(prevSegmentVisibility), function(_, segment) {
                        segments = segments.concat(segment)
                    });
                prevSegmentVisibility = ~~segmentVisibility
            });
            segments.length && points.push(segments);
            points.length === 1 && (points = points[0]);
            return {
                    points: points,
                    pathType: visiblyOpt === 15 ? "area" : "line"
                }
        }
        function applyClipSettings(clipRects, settings) {
            _each(clipRects || [], function(_, c) {
                c && c.attr(settings)
            })
        }
        function reinitTranslators(translators) {
            _each(translators, function(_, axisTrans) {
                _each(axisTrans, function(_, translator) {
                    translator.arg.reinit();
                    translator.val.reinit()
                })
            })
        }
        charts._test_prepareSegmentRectPoints = function() {
            var original = prepareSegmentRectPoints.original || prepareSegmentRectPoints;
            if (arguments[0])
                prepareSegmentRectPoints = arguments[0];
            prepareSegmentRectPoints.original = original;
            prepareSegmentRectPoints.restore = function() {
                prepareSegmentRectPoints = original
            };
            return prepareSegmentRectPoints
        };
        DX.registerComponent("dxChart", viz.charts, charts.AdvancedChart.inherit({
            _chartType: "chart",
            _setDefaultOptions: function() {
                this.callBase();
                this.option({defaultPane: DEFAULT_PANE_NAME})
            },
            _initCore: function() {
                this.__ASYNC_SERIES_RENDERING_DELAY = ASYNC_SERIES_RENDERING_DELAY;
                this.paneAxis = {};
                this._panesClipRects = {};
                this.callBase()
            },
            _disposeCore: function() {
                var that = this,
                    disposeObjectsInArray = this._disposeObjectsInArray,
                    panesClipRects = that._panesClipRects;
                that.callBase();
                disposeObjectsInArray.call(panesClipRects, "fixed");
                disposeObjectsInArray.call(panesClipRects, "base");
                disposeObjectsInArray.call(panesClipRects, "wide");
                that._panesClipRects = null
            },
            _correctAxes: function() {
                this.series && this._correctValueAxes()
            },
            _getExtraOptions: $.noop,
            _processSingleSeries: $.noop,
            _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,
                    synchronizeMultiAxes = that._themeManager.getOptions("synchronizeMultiAxes"),
                    groupedSeries = that._groupedSeries = [];
                _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();
                _each(paneAxis, function(paneName, pane) {
                    hideGridsOnNonFirstValueAxisForPane(valAxes, paneName, synchronizeMultiAxes);
                    _each(pane, function(axisName) {
                        var group = [];
                        _each(series, function(_, particularSeries) {
                            if (particularSeries.pane === paneName && particularSeries.axis === axisName)
                                group.push(particularSeries)
                        });
                        groupedSeries.push(group);
                        group.valueAxis = findAxis(paneName, axisName, valAxes);
                        group.valueOptions = group.valueAxis.getOptions()
                    })
                });
                groupedSeries.argumentAxes = that._argumentAxes;
                groupedSeries.argumentOptions = groupedSeries.argumentAxes[0].getOptions()
            },
            _cleanPanesClipRects: function(clipArrayName) {
                var that = this,
                    clipArray = that._panesClipRects[clipArrayName];
                _each(clipArray || [], function(_, clipRect) {
                    clipRect && clipRect.dispose()
                });
                that._panesClipRects[clipArrayName] = []
            },
            _createPanes: function() {
                var that = this,
                    panes = that.option("panes"),
                    panesNameCounter = 0,
                    bottomPaneName;
                if (panes && _isArray(panes) && !panes.length || $.isEmptyObject(panes))
                    panes = DEFAULT_PANES;
                that._cleanPanesClipRects("fixed");
                that._cleanPanesClipRects("base");
                that._cleanPanesClipRects("wide");
                that.defaultPane = that.option("defaultPane");
                panes = _extend(true, [], _isArray(panes) ? panes : panes ? [panes] : []);
                _each(panes, function(_, pane) {
                    pane.name = !_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._isRotated() ? 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
            },
            _getAxisRenderingOptions: function(typeSelector, axisOptions, rotated) {
                return {
                        axesType: "xyAxes",
                        drawingType: "linear",
                        isHorizontal: typeSelector === "argumentAxis" ? !rotated : rotated
                    }
            },
            _prepareAxisOptions: $.noop,
            _checkPaneName: function(seriesTheme) {
                var paneList = _map(this.panes, function(pane) {
                        return pane.name
                    });
                seriesTheme.pane = seriesTheme.pane || this.defaultPane;
                return $.inArray(seriesTheme.pane, paneList) !== -1
            },
            _correctValueAxes: function() {
                var that = this,
                    rotated = that._isRotated(),
                    valueAxisOptions = that.option("valueAxis") || {},
                    valueAxesOptions = _isArray(valueAxisOptions) ? valueAxisOptions : [valueAxisOptions],
                    valueAxes = that._valueAxes || [],
                    defaultAxisName = valueAxes[0].name,
                    paneAxis = that.paneAxis || {},
                    panes = that.panes,
                    i,
                    neededAxis = {};
                _each(valueAxes, function(_, axis) {
                    if (axis.pane)
                        return;
                    var pane = getPaneForAxis(that.paneAxis, axis.name);
                    if (!pane) {
                        pane = that.defaultPane;
                        paneAxis[pane] = paneAxis[pane] || {};
                        paneAxis[pane][axis.name] = true
                    }
                    axis.setPane(pane)
                });
                for (i = 0; i < panes.length; i++)
                    if (!paneAxis[panes[i].name]) {
                        paneAxis[panes[i].name] = {};
                        paneAxis[panes[i].name][defaultAxisName] = true
                    }
                _each(that.paneAxis, function(paneName, axisNames) {
                    _each(axisNames, function(axisName) {
                        neededAxis[axisName + "-" + paneName] = true;
                        if (!findAxis(paneName, axisName, valueAxes)) {
                            var axisOptions = findAxisOptions(valueAxes, valueAxesOptions, axisName);
                            if (!axisOptions) {
                                that._incidentOccured("W2102", [axisName]);
                                axisOptions = {
                                    name: axisName,
                                    priority: valueAxes.length
                                }
                            }
                            valueAxes.push(that._createAxis("valueAxis", axisOptions, {
                                pane: paneName,
                                name: axisName
                            }, rotated))
                        }
                    })
                });
                valueAxes = $.grep(valueAxes, function(elem) {
                    return !!neededAxis[elem.name + "-" + elem.pane]
                });
                valueAxes.sort(function(a, b) {
                    return a.priority - b.priority
                });
                that._valueAxes = valueAxes
            },
            _getSeriesForPane: function(paneName) {
                var paneSeries = [];
                _each(this.series, function(_, oneSeries) {
                    if (oneSeries.pane === paneName)
                        paneSeries.push(oneSeries)
                });
                return paneSeries
            },
            _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) {
                    panesBorderOptions[pane.name] = _extend(true, {}, commonBorderOptions, pane.border)
                });
                return panesBorderOptions
            },
            _createScrollBar: function() {
                var that = this,
                    scrollBarOptions = that._themeManager.getOptions("scrollBar") || {},
                    scrollBarGroup = that._scrollBarGroup;
                if (scrollBarOptions.visible) {
                    scrollBarOptions.rotated = that._isRotated();
                    that._scrollBar = (that._scrollBar || charts.factory.createScrollBar(that._renderer, scrollBarGroup)).update(scrollBarOptions)
                }
                else {
                    scrollBarGroup.remove();
                    that._scrollBar && that._scrollBar.dispose();
                    that._scrollBar = null
                }
            },
            _prepareToRender: function(drawOptions) {
                var that = this,
                    panesBorderOptions = that._createPanesBorderOptions();
                that._createPanesBackground();
                that._appendAxesGroups();
                that._transformed && that._resetTransform();
                that._createTranslators(drawOptions);
                that._options.useAggregation && _each(that.series, function(_, series) {
                    series._originalBusinessRange = series._originalBusinessRange || series.getRangeData();
                    series.resamplePoints(that._getTranslator(series.pane, series.axis).arg, that._zoomMinArg, that._zoomMaxArg)
                });
                if (_isDefined(that._zoomMinArg) || _isDefined(that._zoomMaxArg))
                    that._populateBusinessRange({
                        adjustOnZoom: that._themeManager.getOptions("adjustOnZoom"),
                        minArg: that._zoomMinArg,
                        maxArg: that._zoomMaxArg,
                        notApplyMargins: that._notApplyMargins
                    });
                if (that._options.useAggregation || _isDefined(that._zoomMinArg) || _isDefined(that._zoomMaxArg))
                    that._updateTranslators();
                return panesBorderOptions
            },
            _isLegendInside: function() {
                return this.legend && this.legend.getPosition() === "inside"
            },
            _renderAxes: function(drawOptions, panesBorderOptions, rotated) {
                if (drawOptions && drawOptions.recreateCanvas)
                    this.layoutManager.updatePanesCanvases(this.panes, this._canvas, rotated);
                this._drawAxes(panesBorderOptions, drawOptions)
            },
            _isRotated: function() {
                return this._themeManager.getOptions("rotated")
            },
            _getLayoutTargets: function() {
                return this.panes
            },
            _applyClipRects: function(panesBorderOptions) {
                var that = this,
                    canvasClipRectID = that._getCanvasClipRectID(),
                    i;
                that._drawPanesBorders(panesBorderOptions);
                that._createClipRectsForPanes();
                for (i = 0; i < that._argumentAxes.length; i++)
                    that._argumentAxes[i].applyClipRects(that._getElementsClipRectID(that._argumentAxes[i].pane), canvasClipRectID);
                for (i = 0; i < that._valueAxes.length; i++)
                    that._valueAxes[i].applyClipRects(that._getElementsClipRectID(that._valueAxes[i].pane), canvasClipRectID);
                that._fillPanesBackground()
            },
            _getSeriesRenderTimeout: function(drawOptions) {
                return drawOptions.asyncSeriesRendering ? ASYNC_SERIES_RENDERING_DELAY : undefined
            },
            _updateLegendPosition: function(drawOptions, legendHasInsidePosition) {
                var that = this;
                if (drawOptions.drawLegend && that.legend && legendHasInsidePosition) {
                    var panes = that.panes,
                        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._renderer.root);
                    layoutManager.drawElements([that.legend], newCanvas);
                    layoutManager.placeDrawnElements(newCanvas)
                }
            },
            _drawSeries: function(drawOptions, rotated) {
                var that = this;
                _each(that.seriesFamilies || [], function(_, seriesFamily) {
                    var translators = that._getTranslator(seriesFamily.pane) || {};
                    seriesFamily.updateSeriesValues(translators);
                    seriesFamily.adjustSeriesDimensions(translators)
                });
                _each(that.series, function(_, particularSeries) {
                    that._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, that._getAnimateOption(particularSeries, drawOptions), drawOptions.hideLayoutLabels, that.legend && that.legend.getActionCallback(particularSeries))
                })
            },
            _applyPaneClipRect: function(seriesOptions) {
                var that = this,
                    paneIndex = that._getPaneIndex(seriesOptions.pane),
                    panesClipRects = that._panesClipRects,
                    wideClipRect = panesClipRects.wide[paneIndex];
                seriesOptions.setClippingParams(panesClipRects.base[paneIndex].id, wideClipRect && wideClipRect.id, that._getPaneBorderVisibility(paneIndex))
            },
            _createTranslators: function(drawOptions) {
                var that = this,
                    rotated = that._isRotated(),
                    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, paneAxisTran) {
                        paneAxisTran.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
                    })
                })
            },
            _getAxesForTransform: function(rotated) {
                return {
                        verticalAxes: !rotated ? this._getValueAxes() : this._getArgumentAxes(),
                        horizontalAxes: !rotated ? this._getArgumentAxes() : this._getValueAxes()
                    }
            },
            _reinitTranslators: function() {
                var that = this;
                _each(that._argumentAxes, function(_, axis) {
                    var translator = that._getTranslator(axis.pane);
                    if (translator) {
                        translator.arg.reinit();
                        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.setTranslator(translator.val, translator.arg)
                    }
                })
            },
            _prepareAxesAndDraw: function(drawAxes, drawStaticAxisElements, drawOptions) {
                var that = this,
                    i = 0,
                    layoutManager = that.layoutManager,
                    rotated = that._isRotated(),
                    adjustmentCounter = 0,
                    synchronizeMultiAxes = that._themeManager.getOptions('synchronizeMultiAxes'),
                    layoutTargets = that._getLayoutTargets(),
                    verticalAxes = rotated ? that._argumentAxes : that._valueAxes,
                    horizontalAxes = rotated ? that._valueAxes : that._argumentAxes,
                    hElements = horizontalAxes,
                    vElements = verticalAxes;
                if (that._scrollBar) {
                    that._scrollBar.setPane(layoutTargets);
                    if (rotated)
                        vElements = [that._scrollBar].concat(vElements);
                    else
                        hElements = hElements.concat([that._scrollBar])
                }
                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(horizontalAxes);
                    layoutManager.requireAxesRedraw = false;
                    if (drawOptions.adjustAxes) {
                        layoutManager.applyHorizontalAxesLayout(hElements, layoutTargets, rotated);
                        !layoutManager.stopDrawAxes && reinitTranslators(that.translators)
                    }
                    drawAxes(verticalAxes);
                    if (drawOptions.adjustAxes && !layoutManager.stopDrawAxes) {
                        layoutManager.applyVerticalAxesLayout(vElements, layoutTargets, rotated);
                        !layoutManager.stopDrawAxes && reinitTranslators(that.translators)
                    }
                    adjustmentCounter = adjustmentCounter + 1
                } while (!layoutManager.stopDrawAxes && layoutManager.requireAxesRedraw && adjustmentCounter < MAX_ADJUSTMENT_ATTEMPTS);
                drawStaticAxisElements(verticalAxes);
                drawStaticAxisElements(horizontalAxes);
                that._scrollBar && that._scrollBar.applyLayout();
                that.__axisAdjustmentsCount = adjustmentCounter
            },
            _getPanesParameters: function() {
                var that = this,
                    panes = that.panes,
                    i,
                    params = [];
                for (i = 0; i < panes.length; i++)
                    if (that._getPaneBorderVisibility(i))
                        params.push({
                            coords: panes[i].borderCoords,
                            clipRect: that._panesClipRects.fixed[i]
                        });
                return params
            },
            _createCrosshairCursor: function() {
                var that = this,
                    options = that._themeManager.getOptions("crosshair") || {},
                    axes = !that._isRotated() ? [that._argumentAxes, that._valueAxes] : [that._valueAxes, that._argumentAxes],
                    parameters = {
                        canvas: that._getCommonCanvas(),
                        panes: that._getPanesParameters(),
                        axes: axes
                    };
                if (!options || !options.enabled)
                    return;
                if (!that._crosshair)
                    that._crosshair = charts.factory.createCrosshair(that._renderer, options, parameters, that._crosshairCursorGroup);
                else
                    that._crosshair.update(options, parameters);
                that._crosshair.render()
            },
            _getCommonCanvas: function() {
                var i,
                    canvas,
                    commonCanvas,
                    panes = this.panes;
                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
                    }
                }
                return 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.rect(0, 0, 0, 0).attr({
                        fill: backgroundColor,
                        "stroke-width": 0
                    }).append(that._panesBackgroundGroup);
                    rects.push(rect)
                }
                that.panesBackground = rects;
                that._panesBackgroundGroup.append(renderer.root)
            },
            _fillPanesBackground: function() {
                var that = this,
                    bc;
                _each(that.panes, function(i, pane) {
                    bc = pane.borderCoords;
                    if (that.panesBackground[i] !== null)
                        that.panesBackground[i].attr({
                            x: bc.left,
                            y: bc.top,
                            width: bc.width,
                            height: bc.height
                        })
                })
            },
            _calcPaneBorderCoords: function(pane) {
                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._isRotated();
                that._panesBorderGroup && that._panesBorderGroup.remove().clear();
                _each(that.panes, function(i, pane) {
                    var bc,
                        borderOptions = panesBorderOptions[pane.name],
                        segmentRectParams,
                        attr = {
                            fill: "none",
                            stroke: borderOptions.color,
                            "stroke-opacity": borderOptions.opacity,
                            "stroke-width": borderOptions.width,
                            dashStyle: borderOptions.dashStyle,
                            "stroke-linecap": "square"
                        };
                    that._calcPaneBorderCoords(pane, rotated);
                    if (!borderOptions.visible)
                        return;
                    bc = pane.borderCoords;
                    segmentRectParams = prepareSegmentRectPoints(bc.left, bc.top, bc.width, bc.height, borderOptions);
                    that._renderer.path(segmentRectParams.points, segmentRectParams.pathType).attr(attr).append(that._panesBorderGroup)
                });
                that._panesBorderGroup.append(that._renderer.root)
            },
            _createClipRect: function(clipArray, index, left, top, width, height) {
                var that = this,
                    clipRect = clipArray[index];
                if (!clipRect) {
                    clipRect = that._renderer.clipRect(left, top, width, height);
                    clipArray[index] = clipRect
                }
                else
                    clipRect.attr({
                        x: left,
                        y: top,
                        width: width,
                        height: height
                    })
            },
            _createClipRectsForPanes: function() {
                var that = this,
                    canvas = that._canvas;
                _each(that.panes, function(i, pane) {
                    var needWideClipRect = false,
                        bc = pane.borderCoords,
                        left = bc.left,
                        top = bc.top,
                        width = bc.width,
                        height = bc.height,
                        panesClipRects = that._panesClipRects;
                    that._createClipRect(panesClipRects.fixed, i, left, top, width, height);
                    that._createClipRect(panesClipRects.base, i, left, top, width, height);
                    _each(that.series, function(_, series) {
                        if (series.pane === pane.name && (series.isFinancialSeries() || series.areErrorBarsVisible()))
                            needWideClipRect = true
                    });
                    if (needWideClipRect) {
                        if (that._isRotated()) {
                            top = 0;
                            height = canvas.height
                        }
                        else {
                            left = 0;
                            width = canvas.width
                        }
                        that._createClipRect(panesClipRects.wide, i, left, top, width, height)
                    }
                    else
                        panesClipRects.wide.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.fixed[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
            },
            _transformArgument: function(translate, scale) {
                var that = this,
                    rotated = that._isRotated(),
                    settings,
                    clipSettings,
                    panesClipRects = that._panesClipRects;
                if (!that._transformed) {
                    that._transformed = true;
                    that._labelsGroup.remove();
                    that._resetIsReady();
                    _each(that.series || [], function(i, s) {
                        s.applyClip()
                    })
                }
                if (rotated) {
                    settings = {
                        translateY: translate,
                        scaleY: scale
                    };
                    clipSettings = {
                        translateY: -translate / scale,
                        scaleY: 1 / scale
                    }
                }
                else {
                    settings = {
                        translateX: translate,
                        scaleX: scale
                    };
                    clipSettings = {
                        translateX: -translate / scale,
                        scaleX: 1 / scale
                    }
                }
                applyClipSettings(panesClipRects.base, clipSettings);
                applyClipSettings(panesClipRects.wide, clipSettings);
                that._seriesGroup.attr(settings);
                that._scrollBar && that._scrollBar.transform(-translate, scale)
            },
            _resetTransform: function() {
                var that = this,
                    settings = {
                        translateX: 0,
                        translateY: 0,
                        scaleX: null,
                        scaleY: null
                    },
                    panesClipRects = that._panesClipRects;
                applyClipSettings(panesClipRects.base, settings);
                applyClipSettings(panesClipRects.wide, settings);
                that._seriesGroup.attr(settings);
                _each(that.series || [], function(i, s) {
                    s.resetClip()
                });
                that._transformed = false
            },
            _getTrackerSettings: function() {
                var that = this,
                    themeManager = that._themeManager;
                return _extend(this.callBase(), {
                        chart: that,
                        zoomingMode: themeManager.getOptions("zoomingMode"),
                        scrollingMode: themeManager.getOptions("scrollingMode"),
                        rotated: that._isRotated(),
                        crosshair: that._crosshair
                    })
            },
            _resolveLabelOverlappingStack: function() {
                var that = this,
                    stackPoints = {},
                    isRotated = that._isRotated(),
                    shiftDirection = isRotated ? function(box, length) {
                        return {
                                x: box.x - length,
                                y: box.y
                            }
                    } : function(box, length) {
                        return {
                                x: box.x,
                                y: box.y - length
                            }
                    };
                _each(this._getVisibleSeries(), function(_, particularSeries) {
                    that._prepareStackPoints(particularSeries, stackPoints)
                });
                _each(stackPoints, function(_, stacks) {
                    _each(stacks, function(_, points) {
                        charts.overlapping.resolveLabelOverlappingInOneDirection(points, that._getCommonCanvas(), isRotated, shiftDirection)
                    })
                })
            },
            _getEqualBarWidth: function() {
                return this._themeManager.getOptions("equalBarWidth")
            },
            zoomArgument: function(min, max, gesturesUsed) {
                var that = this,
                    zoomArg;
                if (!_isDefined(min) && !_isDefined(max))
                    return;
                zoomArg = that._argumentAxes[0].zoom(min, max, gesturesUsed);
                that._zoomMinArg = zoomArg.min;
                that._zoomMaxArg = zoomArg.max;
                that._notApplyMargins = gesturesUsed;
                that._render({
                    force: true,
                    drawTitle: false,
                    drawLegend: false,
                    adjustAxes: false,
                    animate: false,
                    adjustSeriesLabels: false,
                    asyncSeriesRendering: false,
                    updateTracker: false
                })
            },
            _resetZoom: function() {
                var that = this;
                that._zoomMinArg = that._zoomMaxArg = undefined;
                that._argumentAxes[0] && that._argumentAxes[0].resetZoom()
            },
            getVisibleArgumentBounds: function() {
                var range = this._argumentAxes[0].getTranslator().getBusinessRange(),
                    isDiscrete = range.axisType === "discrete",
                    categories = range.categories;
                return {
                        minVisible: isDiscrete ? range.minVisible || categories[0] : range.minVisible,
                        maxVisible: isDiscrete ? range.maxVisible || categories[categories.length - 1] : range.maxVisible
                    }
            }
        }))
    })(jQuery, DevExpress);
    /*! Module viz-charts, file pieChart.js */
    (function($, DX, undefined) {
        var viz = DX.viz,
            core = viz.core,
            charts = viz.charts,
            utils = DX.utils,
            _extend = $.extend,
            _noop = $.noop,
            _getVerticallyShiftedAngularCoords = DX.viz.core.utils.getVerticallyShiftedAngularCoords;
        DX.registerComponent("dxPieChart", viz.charts, charts.BaseChart.inherit({
            _chartType: 'pie',
            _reinitAxes: _noop,
            _correctAxes: _noop,
            _layoutManagerOptions: function() {
                var diameter = this._themeManager.getOptions('diameter');
                if (utils.isNumber(diameter)) {
                    if (diameter > 1)
                        diameter = 1;
                    else if (diameter < 0)
                        diameter = 0
                }
                else
                    diameter = undefined;
                return _extend(true, {}, this.callBase(), {piePercentage: diameter})
            },
            _groupSeries: function() {
                this.series.valueOptions = {valueType: "numeric"};
                this._groupedSeries = [this.series];
                this._groupedSeries.argumentOptions = this.series[0] && this.series[0].getOptions()
            },
            _populateBusinessRange: function() {
                var businessRanges = [],
                    series = this.series,
                    singleSeries = series[0],
                    range = new core.Range,
                    singleSeriesRange;
                this._disposeObjectsInArray("businessRanges");
                if (singleSeries) {
                    singleSeriesRange = singleSeries.getRangeData();
                    range.addRange(singleSeriesRange.val);
                    if (!range.isDefined())
                        range.setStubData();
                    businessRanges.push(range)
                }
                this.businessRanges = businessRanges
            },
            _specialProcessSeries: function() {
                this.series[0].arrangePoints()
            },
            _createTranslator: function(range) {
                return core.CoreFactory.createTranslator1D(range.min, range.max, 360, 0)
            },
            _populateSeries: function() {
                var that = this,
                    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.visibilityChanged = $.proxy(that._seriesVisibilityChanged, that);
                    seriesTheme.customizePoint = themeManager.getOptions("customizePoint");
                    seriesTheme.customizeLabel = themeManager.getOptions("customizeLabel");
                    particularSeries = core.CoreFactory.createSeries({
                        renderer: that._renderer,
                        seriesGroup: that._seriesGroup,
                        labelsGroup: that._labelsGroup
                    }, 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()
            },
            _seriesPopulatedHandlerCore: _noop,
            _getLegendTargets: function() {
                return this.series[0] ? this.series[0].getPoints() : []
            },
            _legendItemTextField: "argument",
            _prepareToRender: _noop,
            _isLegendInside: _noop,
            _renderAxes: _noop,
            _isRotated: _noop,
            _getLayoutTargets: function() {
                return [{canvas: this._canvas}]
            },
            _getAxesForTransform: function() {
                return {
                        verticalAxes: [],
                        horizontalAxes: []
                    }
            },
            _updateAxesLayout: _noop,
            _applyClipRects: _noop,
            _appendAdditionalSeriesGroups: _noop,
            _getSeriesRenderTimeout: _noop,
            _drawSeries: function(drawOptions) {
                var that = this,
                    singleSeries = that.getSeries(),
                    legend = that.legend,
                    getActionCallbackProxy = $.proxy(legend.getActionCallback, legend);
                if (singleSeries) {
                    that.layoutManager.applyPieChartSeriesLayout(that._canvas, singleSeries, true);
                    singleSeries.canvas = that._canvas;
                    singleSeries.resetLabelSetups();
                    if (singleSeries.drawLabelsWOPoints(that._createTranslator(that.businessRanges[0], that._canvas)))
                        that.layoutManager.applyPieChartSeriesLayout(that._canvas, singleSeries, drawOptions.hideLayoutLabels);
                    singleSeries.draw(that._createTranslator(that.businessRanges[0], that._canvas), that._getAnimateOption(singleSeries, drawOptions), drawOptions.hideLayoutLabels, getActionCallbackProxy)
                }
            },
            _adjustSeries: function() {
                var singleSeries = this.getSeries();
                singleSeries && singleSeries.adjustLabels()
            },
            _updateLegendPosition: _noop,
            _renderTrackers: _noop,
            _createScrollBar: _noop,
            _resolveLabelOverlappingShift: function() {
                var series = this.series[0],
                    center = series.getCenter(),
                    lPoints = [],
                    rPoints = [];
                $.each(series.getVisiblePoints(), function(_, point) {
                    var angle = utils.normalizeAngle(point.middleAngle);
                    (angle <= 90 || angle >= 270 ? rPoints : lPoints).push(point)
                });
                charts.overlapping.resolveLabelOverlappingInOneDirection(lPoints, this._canvas, false, shiftFunction);
                charts.overlapping.resolveLabelOverlappingInOneDirection(rPoints, this._canvas, false, shiftFunction);
                function shiftFunction(box, length) {
                    return _getVerticallyShiftedAngularCoords(box, -length, center)
                }
            },
            getSeries: function getSeries() {
                return this.series && this.series[0]
            },
            _legendDataField: 'point'
        }))
    })(jQuery, DevExpress);
    /*! Module viz-charts, file polarChart.js */
    (function($, DX, undefined) {
        var charts = DX.viz.charts,
            core = DX.viz.core,
            DEFAULT_PANE_NAME = 'default';
        var PolarChart = charts.AdvancedChart.inherit({
                _chartType: 'polar',
                _createPanes: function() {
                    return [{name: DEFAULT_PANE_NAME}]
                },
                _checkPaneName: function() {
                    return true
                },
                _getAxisRenderingOptions: function(typeSelector) {
                    var isArgumentAxis = typeSelector === "argumentAxis",
                        type = isArgumentAxis ? "circular" : "linear",
                        useSpiderWeb = this.option("useSpiderWeb");
                    if (useSpiderWeb)
                        type += "Spider";
                    return {
                            axesType: "polarAxes",
                            drawingType: type,
                            isHorizontal: true
                        }
                },
                _prepareAxisOptions: function(typeSelector, axisOptions) {
                    return {type: this.option("useSpiderWeb") && typeSelector === "argumentAxis" ? "discrete" : axisOptions.type}
                },
                _getExtraOptions: function() {
                    return {spiderWidget: this.option("useSpiderWeb")}
                },
                _correctAxes: $.noop,
                _groupSeries: function() {
                    this._groupedSeries = [this.series];
                    this._groupedSeries[0].valueAxis = this._valueAxes[0];
                    this._groupedSeries[0].valueOptions = this._valueAxes[0].getOptions();
                    this._groupedSeries.argumentAxes = this._argumentAxes;
                    this._groupedSeries.argumentOptions = this._argumentAxes[0].getOptions()
                },
                _processSingleSeries: $.noop,
                _prepareToRender: function() {
                    this._appendAxesGroups();
                    return {}
                },
                _isLegendInside: $.noop,
                _renderAxes: function(drawOptions) {
                    this._drawAxes({}, drawOptions)
                },
                _reinitTranslators: function() {
                    var that = this,
                        valueAxes = that._valueAxes,
                        argumentAxes = that._argumentAxes,
                        translator = that._createTranslator({
                            arg: new core.Range(that.businessRanges[0].arg),
                            val: new core.Range(that.businessRanges[0].val)
                        }),
                        argTranslator = translator.getComponent("arg"),
                        valTranslator = translator.getComponent("val"),
                        i = 0;
                    that.translator = translator;
                    argumentAxes[0].setTranslator(argTranslator, valTranslator);
                    for (i; i < valueAxes.length; i++)
                        valueAxes[i].setTranslator(valTranslator, argTranslator)
                },
                _prepareAxesAndDraw: function(drawAxes, drawStaticAxisElements) {
                    var that = this,
                        valueAxes = that._valueAxes,
                        argAxes = that._argumentAxes,
                        argumentAxis = argAxes[0];
                    that._calcCanvas(argumentAxis.measureLabels());
                    that.translator.reinit();
                    drawAxes(argAxes);
                    $.each(valueAxes, function(_, valAxis) {
                        valAxis.setSpiderTicks(argumentAxis.getSpiderTicks())
                    });
                    drawAxes(valueAxes);
                    drawStaticAxisElements(argAxes);
                    drawStaticAxisElements(valueAxes)
                },
                _calcCanvas: function(measure) {
                    var canvas = this.translator.canvas;
                    canvas.left += measure.width;
                    canvas.right += measure.width;
                    canvas.top += measure.height;
                    canvas.bottom += measure.height
                },
                _isRotated: $.noop,
                _getLayoutTargets: function() {
                    return [{canvas: this._canvas}]
                },
                _getAxesForTransform: function() {
                    var argAxes = this._getArgumentAxes();
                    return {
                            verticalAxes: argAxes,
                            horizontalAxes: argAxes
                        }
                },
                _applyClipRects: $.noop,
                _getSeriesRenderTimeout: $.noop,
                _drawSeries: function(drawOptions) {
                    var that = this,
                        i,
                        seriesFamilies = that.seriesFamilies || [],
                        series = that.series;
                    if (!series.length)
                        return;
                    for (i = 0; i < seriesFamilies.length; i++) {
                        var translators = {};
                        translators.val = that.translator;
                        translators.arg = that.translator;
                        seriesFamilies[i].updateSeriesValues(translators);
                        seriesFamilies[i].adjustSeriesDimensions(translators)
                    }
                    for (i = 0; i < series.length; i++)
                        series[i].draw(that.translator, that._getAnimateOption(series[i], drawOptions), drawOptions.hideLayoutLabels, that.legend && that.legend.getActionCallback(series[i]))
                },
                _updateLegendPosition: $.noop,
                _createScrollBar: $.noop,
                _createTranslator: function(br) {
                    var themeManager = this._themeManager,
                        axisUserOptions = this.option("argumentAxis"),
                        axisOptions = themeManager.getOptions("argumentAxis", axisUserOptions) || {};
                    return new core.PolarTranslator(br, $.extend(true, {}, this._canvas), {startAngle: axisOptions.startAngle})
                },
                _getSeriesForPane: function() {
                    return this.series
                },
                _getEqualBarWidth: function() {
                    return !!this._themeManager.getOptions("equalBarWidth")
                }
            });
        DX.registerComponent('dxPolarChart', charts, PolarChart)
    })(jQuery, DevExpress);
    /*! Module viz-charts, file layoutManager.js */
    (function($, DX, undefined) {
        var _isNumber = DX.utils.isNumber,
            _decreaseGaps = DX.viz.core.utils.decreaseGaps,
            _round = Math.round,
            _min = Math.min,
            _max = Math.max,
            _floor = Math.floor,
            _sqrt = Math.sqrt,
            _each = $.each,
            _extend = $.extend;
        function correctElementsPosition(elements, direction, canvas) {
            _each(elements, function(_, element) {
                var options = element.getLayoutOptions(),
                    side = options.cutLayoutSide;
                canvas[side] -= options[direction]
            })
        }
        function placeElementAndCutCanvas(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)
            })
        }
        function getLength(side) {
            return side === 'left' || side === 'right' ? 'width' : 'height'
        }
        function setCanvasValues(canvas) {
            if (canvas) {
                canvas.originalTop = canvas.top;
                canvas.originalBottom = canvas.bottom;
                canvas.originalLeft = canvas.left;
                canvas.originalRight = canvas.right
            }
        }
        function updateElements(elements, length, otherLength, dirtyCanvas, canvas, needRemoveSpace) {
            _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]
            })
        }
        function updateAxis(axes, side, needRemoveSpace) {
            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 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, paneCenterX, paneCenterY) {
            return _sqrt((x - paneCenterX) * (x - paneCenterX) + (y - paneCenterY) * (y - paneCenterY))
        }
        function getInnerRadius(series) {
            var innerRadius;
            if (series.type === "pie")
                innerRadius = 0;
            else {
                innerRadius = _isNumber(series.innerRadius) ? Number(series.innerRadius) : 0.5;
                innerRadius = innerRadius < 0.2 ? 0.2 : innerRadius;
                innerRadius = innerRadius > 0.8 ? 0.8 : innerRadius
            }
            return innerRadius
        }
        function isValidBox(box) {
            return !!(box.x || box.y || box.width || box.height)
        }
        function correctDeltaMarginValue(panes, marginSides) {
            var canvas,
                deltaSide,
                requireAxesRedraw = false;
            _each(panes, function(_, pane) {
                canvas = pane.canvas;
                _each(marginSides, function(_, side) {
                    deltaSide = "delta" + side;
                    canvas[deltaSide] = _max(canvas[deltaSide] - (canvas[side.toLowerCase()] - canvas["original" + side]), 0);
                    if (canvas[deltaSide] > 0)
                        requireAxesRedraw = true
                })
            });
            return requireAxesRedraw
        }
        function getPane(name, panes) {
            var findPane = panes[0];
            _each(panes, function(_, pane) {
                if (name === pane.name)
                    findPane = pane
            });
            return findPane
        }
        function applyFoundExceedings(panes, rotated) {
            var stopDrawAxes = false,
                maxLeft = 0,
                maxRight = 0,
                maxTop = 0,
                maxBottom = 0;
            _each(panes, function(_, pane) {
                maxLeft = _max(maxLeft, pane.canvas.deltaLeft);
                maxRight = _max(maxRight, pane.canvas.deltaRight);
                maxTop = _max(maxTop, pane.canvas.deltaTop);
                maxBottom = _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
        }
        function LayoutManager(options) {
            this._verticalElements = [];
            this._horizontalElements = [];
            this._options = options
        }
        LayoutManager.prototype = {
            constructor: LayoutManager,
            dispose: function() {
                this._verticalElements = this._horizontalElements = this._options = null
            },
            drawElements: function(elements, canvas) {
                var horizontalElements = [],
                    verticalElements = [];
                _each(elements, function(_, element) {
                    var options,
                        length;
                    element.setSize({
                        width: canvas.width - canvas.left - canvas.right,
                        height: canvas.height - canvas.top - canvas.bottom
                    });
                    element.draw();
                    options = element.getLayoutOptions();
                    if (options) {
                        length = getLength(options.cutLayoutSide);
                        (length === 'width' ? horizontalElements : verticalElements).push(element);
                        canvas[options.cutLayoutSide] += options[length];
                        setCanvasValues(canvas)
                    }
                });
                this._horizontalElements = horizontalElements;
                this._verticalElements = verticalElements;
                return this
            },
            placeDrawnElements: function(canvas) {
                correctElementsPosition(this._horizontalElements, 'width', canvas);
                placeElementAndCutCanvas(this._horizontalElements, canvas);
                correctElementsPosition(this._verticalElements, 'height', canvas);
                placeElementAndCutCanvas(this._verticalElements, canvas);
                return this
            },
            updatePanesCanvases: function(panes, canvas, rotated) {
                var weightSum = 0;
                _each(panes, function(_, pane) {
                    pane.weight = pane.weight || 1;
                    weightSum += pane.weight
                });
                var distributedSpace = 0,
                    padding = panes.padding || 10,
                    paneSpace = rotated ? canvas.width - canvas.left - canvas.right : canvas.height - canvas.top - canvas.bottom,
                    oneWeight = (paneSpace - padding * (panes.length - 1)) / weightSum,
                    startName = rotated ? "left" : "top",
                    endName = rotated ? "right" : "bottom";
                _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)
                })
            },
            applyVerticalAxesLayout: function(axes, panes, rotated) {
                this._applyAxesLayout(axes, panes, rotated)
            },
            applyHorizontalAxesLayout: function(axes, panes, rotated) {
                axes.reverse();
                this._applyAxesLayout(axes, panes, rotated);
                axes.reverse()
            },
            _applyAxesLayout: function(axes, panes, rotated) {
                var that = this,
                    canvas,
                    axisPosition,
                    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.getOptions().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;
                that.stopDrawAxes = applyFoundExceedings(panes, rotated)
            },
            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,
                    piePercentage = this._options.piePercentage,
                    accessibleRadius = _isNumber(piePercentage) ? piePercentage * _min(canvas.height, canvas.width) / 2 : _min(paneSpaceWidth, paneSpaceHeight) / 2,
                    minR = 0.7 * accessibleRadius,
                    innerRadius = getInnerRadius(singleSeries);
                if (!hideLayoutLabels && !_isNumber(piePercentage))
                    _each(singleSeries.getPoints(), function(_, point) {
                        if (point._label.isVisible() && point.isVisible()) {
                            var labelBBox = point._label.getBoundingRect(),
                                nearestX = getNearestCoord(labelBBox.x, labelBBox.x + labelBBox.width, paneCenterX),
                                nearestY = getNearestCoord(labelBBox.y, labelBBox.y + labelBBox.height, paneCenterY),
                                minRadiusWithLabels = _max(getLengthFromCenter(nearestX, nearestY, paneCenterX, paneCenterY) - DX.viz.core.series.helpers.consts.pieLabelIndent, minR);
                            accessibleRadius = _min(accessibleRadius, minRadiusWithLabels)
                        }
                    });
                singleSeries.correctPosition({
                    centerX: _floor(paneCenterX),
                    centerY: _floor(paneCenterY),
                    radiusInner: _floor(accessibleRadius * innerRadius),
                    radiusOuter: _floor(accessibleRadius)
                })
            },
            updateDrawnElements: function(axes, canvas, dirtyCanvas, panes, rotated) {
                var needRemoveSpace,
                    saveDirtyCanvas = _extend({}, dirtyCanvas);
                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(this._horizontalElements, "width", "height", dirtyCanvas, canvas, needRemoveSpace);
                updateElements(this._verticalElements, "height", "width", dirtyCanvas, canvas, needRemoveSpace);
                updateAxis(axes.verticalAxes, "width", needRemoveSpace);
                updateAxis(axes.horizontalAxes, "height", needRemoveSpace)
            },
            needMoreSpaceForPanesCanvas: function(panes, rotated) {
                var options = this._options,
                    width = options.width,
                    height = options.height,
                    piePercentage = options.piePercentage,
                    percentageIsValid = _isNumber(piePercentage),
                    needHorizontalSpace = 0,
                    needVerticalSpace = 0;
                _each(panes, function(_, pane) {
                    var paneCanvas = pane.canvas,
                        minSize = percentageIsValid ? _min(paneCanvas.width, paneCanvas.height) * piePercentage : undefined,
                        needPaneHorizonralSpace = (percentageIsValid ? minSize : width) - (paneCanvas.width - paneCanvas.left - paneCanvas.right),
                        needPaneVerticalSpace = (percentageIsValid ? minSize : height) - (paneCanvas.height - paneCanvas.top - paneCanvas.bottom);
                    if (rotated) {
                        needHorizontalSpace += needPaneHorizonralSpace > 0 ? needPaneHorizonralSpace : 0;
                        needVerticalSpace = _max(needPaneVerticalSpace > 0 ? needPaneVerticalSpace : 0, needVerticalSpace)
                    }
                    else {
                        needHorizontalSpace = _max(needPaneHorizonralSpace > 0 ? needPaneHorizonralSpace : 0, needHorizontalSpace);
                        needVerticalSpace += needPaneVerticalSpace > 0 ? needPaneVerticalSpace : 0
                    }
                });
                return needHorizontalSpace > 0 || needVerticalSpace > 0 ? {
                        width: needHorizontalSpace,
                        height: needVerticalSpace
                    } : false
            },
            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
                })
            }
        };
        DX.viz.charts._setCanvasValues = setCanvasValues;
        DX.viz.charts.LayoutManager = LayoutManager
    })(jQuery, DevExpress);
    /*! Module viz-charts, file multiAxesSynchronizer.js */
    (function($, DX, undefined) {
        var Range = DX.viz.core.Range,
            utils = DX.utils,
            _adjustValue = utils.adjustValue,
            _applyPrecisionByMinDelta = utils.applyPrecisionByMinDelta,
            _isDefined = utils.isDefined,
            _math = Math,
            _floor = _math.floor,
            _max = _math.max,
            _each = $.each,
            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,
                    translator = axis.getTranslator();
                if (!translator._originalBusinessRange)
                    translator._originalBusinessRange = new Range(translator.getBusinessRange());
                else {
                    businessRange = new Range(translator._originalBusinessRange);
                    translator.updateBusinessRange(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: _floor
            };
        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: _adjustValue
            };
        var convertAxisInfo = function(axisInfo, convertor) {
                if (!axisInfo.isLogarithmic)
                    return;
                var base = axisInfo.logarithmicBase,
                    tickValues = axisInfo.tickValues,
                    tick,
                    ticks = [],
                    interval,
                    i;
                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);
                tick = convertor.transform(tickValues[0], base);
                for (i = 0; i < tickValues.length; i++) {
                    ticks.push(convertor.adjustValue(tick));
                    tick = convertor.addInterval(tick, interval)
                }
                ticks.tickInterval = axisInfo.tickInterval;
                axisInfo.tickValues = ticks
            };
        var populateAxesInfo = function(axes) {
                return $.map(axes, function(axis) {
                        restoreOriginalBusinessRange(axis);
                        var ticksValues = axis.getTicksValues(),
                            majorTicks = ticksValues.majorTicksValues,
                            options = axis.getOptions(),
                            minValue,
                            maxValue,
                            axisInfo = null,
                            businessRange,
                            tickInterval,
                            synchronizedValue;
                        if (majorTicks && majorTicks.length > 0 && utils.isNumber(majorTicks[0]) && options.type !== "discrete") {
                            businessRange = axis.getTranslator().getBusinessRange();
                            tickInterval = axis._tickManager.getTickInterval();
                            minValue = businessRange.minVisible;
                            maxValue = businessRange.maxVisible;
                            synchronizedValue = options.synchronizedValue;
                            if (minValue === maxValue && _isDefined(synchronizedValue)) {
                                minValue = majorTicks[0] - 1;
                                maxValue = majorTicks[0] + 1;
                                tickInterval = 1
                            }
                            axisInfo = {
                                axis: axis,
                                isLogarithmic: options.type === "logarithmic",
                                logarithmicBase: businessRange.base,
                                tickValues: majorTicks,
                                minorValues: ticksValues.minorTicksValues,
                                minValue: minValue,
                                oldMinValue: minValue,
                                maxValue: maxValue,
                                oldMaxValue: maxValue,
                                inverted: businessRange.invert,
                                tickInterval: tickInterval,
                                synchronizedValue: 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 = _max(maxTicksCount, axisInfo.tickValues.length)
                });
                _each(axesInfo, function(_, axisInfo) {
                    var ticksMultiplier,
                        ticksCount,
                        additionalStartTicksCount = 0,
                        synchronizedValue = axisInfo.synchronizedValue,
                        tickValues = axisInfo.tickValues,
                        tickInterval = axisInfo.tickInterval;
                    if (_isDefined(synchronizedValue)) {
                        axisInfo.baseTickValue = axisInfo.invertedBaseTickValue = synchronizedValue;
                        axisInfo.tickValues = [axisInfo.baseTickValue]
                    }
                    else {
                        if (tickValues.length > 1 && tickInterval) {
                            ticksMultiplier = _floor((maxTicksCount + 1) / tickValues.length);
                            ticksCount = ticksMultiplier > 1 ? _floor((maxTicksCount + 1) / ticksMultiplier) : maxTicksCount;
                            additionalStartTicksCount = _floor((ticksCount - tickValues.length) / 2);
                            while (additionalStartTicksCount > 0 && tickValues[0] !== 0) {
                                tickValues.unshift(_applyPrecisionByMinDelta(tickValues[0], tickInterval, tickValues[0] - tickInterval));
                                additionalStartTicksCount--
                            }
                            while (tickValues.length < ticksCount)
                                tickValues.push(_applyPrecisionByMinDelta(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 || 1
            };
        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),
                    mainAxisInfoTickInterval = mainAxisInfo.tickInterval;
                _each(axesInfo, function(_, axisInfo) {
                    var scale,
                        move,
                        mainAxisBaseValueOffset,
                        valueFromAxisInfo;
                    if (axisInfo !== mainAxisInfo) {
                        if (mainAxisInfoTickInterval && axisInfo.tickInterval) {
                            if (axisInfo.stubData && _isDefined(axisInfo.synchronizedValue)) {
                                axisInfo.oldMinValue = axisInfo.minValue = axisInfo.baseTickValue - (mainAxisInfo.baseTickValue - mainAxisInfo.minValue) / mainAxisInfoTickInterval * axisInfo.tickInterval;
                                axisInfo.oldMaxValue = axisInfo.maxValue = axisInfo.baseTickValue - (mainAxisInfo.baseTickValue - mainAxisInfo.maxValue) / mainAxisInfoTickInterval * axisInfo.tickInterval
                            }
                            scale = mainAxisInfoTickInterval / 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;
                        valueFromAxisInfo = getAxisRange(axisInfo);
                        move = (mainAxisBaseValueOffset / getAxisRange(mainAxisInfo) - (axisInfo.baseTickValue - axisInfo.minValue) / valueFromAxisInfo) * valueFromAxisInfo;
                        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 = _max(startPadding, inverted ? maxPadding : minPadding);
                    endPadding = _max(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, _adjustValue(info.minValue));
                        info.maxValue = _max(info.maxValue, _adjustValue(info.maxValue))
                    }
                })
            };
        var updateTickValuesIfSyncronizedValueUsed = function(axesInfo) {
                var hasSyncronizedValue = false;
                _each(axesInfo, function(_, info) {
                    hasSyncronizedValue = hasSyncronizedValue || _isDefined(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(_adjustValue(tickValues[0] - tickInterval));
                        lastTickValue = tickValues[tickValues.length - 1];
                        while ((lastTickValue = lastTickValue + tickInterval) <= maxValue)
                            tickValues.push(utils.isExponential(lastTickValue) ? _adjustValue(lastTickValue) : _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.getTranslator().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 (_isDefined(info.stubData))
                        range.stubData = info.stubData;
                    if (range.min > range.minVisible)
                        range.min = range.minVisible;
                    if (range.max < range.maxVisible)
                        range.max = range.maxVisible;
                    range.isSynchronized = true;
                    axis.getTranslator().updateBusinessRange(range);
                    axis.setTicks({
                        majorTicks: info.tickValues,
                        minorTicks: info.minorValues
                    })
                })
            };
        var correctAfterSynchronize = function(axesInfo) {
                var invalidAxisInfo = [],
                    correctValue,
                    validAxisInfo;
                _each(axesInfo, function(i, info) {
                    if (info.oldMaxValue - info.oldMinValue === 0)
                        invalidAxisInfo.push(info);
                    else if (!_isDefined(correctValue) && !_isDefined(info.synchronizedValue)) {
                        correctValue = _math.abs((info.maxValue - info.minValue) / (info.tickValues[_floor(info.tickValues.length / 2)] || info.maxValue));
                        validAxisInfo = info
                    }
                });
                if (!_isDefined(correctValue))
                    return;
                _each(invalidAxisInfo, function(i, info) {
                    var firstTick = info.tickValues[0],
                        correctedTick = firstTick * correctValue,
                        tickValues = validAxisInfo.tickValues,
                        centralTick = tickValues[_floor(tickValues.length / 2)];
                    if (firstTick > 0) {
                        info.maxValue = correctedTick;
                        info.minValue = 0
                    }
                    else if (firstTick < 0) {
                        info.minValue = correctedTick;
                        info.maxValue = 0
                    }
                    else if (firstTick === 0) {
                        info.maxValue = validAxisInfo.maxValue - centralTick;
                        info.minValue = validAxisInfo.minValue - centralTick
                    }
                })
            };
        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);
                        correctAfterSynchronize(axesInfo);
                        updateTickValuesIfSyncronizedValueUsed(axesInfo);
                        _each(axesInfo, function() {
                            convertAxisInfo(this, logConvertor)
                        });
                        applyMinMaxValues(axesInfo)
                    }
                })
            }}
    })(jQuery, DevExpress);
    /*! Module viz-charts, file tracker.js */
    (function($, DX, math) {
        var charts = DX.viz.charts,
            eventsConsts = DX.viz.core.series.helpers.consts.events,
            utils = DX.utils,
            isDefined = utils.isDefined,
            _floor = math.floor,
            _each = $.each,
            MULTIPLE_MODE = 'multiple',
            ALL_ARGUMENTS_POINTS_MODE = 'allargumentpoints',
            ALL_SERIES_POINTS_MODE = 'allseriespoints',
            NONE_MODE = 'none',
            POINTER_ACTION = "dxpointerdown dxpointermove",
            POINT_SELECTION_CHANGED = "pointSelectionChanged",
            LEGEND_CLICK = "legendClick",
            SERIES_CLICK = "seriesClick",
            POINT_CLICK = "pointClick",
            RELEASE_POINT_SELECTED_STATE = "releasePointSelectedState",
            SET_POINT_SELECTED_STATE = "setPointSelectedState",
            DELAY = 100;
        function processMode(mode) {
            return (mode + "").toLowerCase()
        }
        function getNonVirtualAxis(axisArray) {
            var axis;
            _each(axisArray, function(_, a) {
                if (!a._virtual) {
                    axis = a;
                    return false
                }
            });
            return axis
        }
        function eventCanceled(event, target) {
            return event.cancel || !target.getOptions()
        }
        var baseTrackerPrototype = {
                ctor: function(options) {
                    var that = this,
                        data = {tracker: that};
                    if (processMode(options.pointSelectionMode) === MULTIPLE_MODE) {
                        that._setSelectedPoint = that._selectPointMultipleMode;
                        that._releaseSelectedPoint = that._releaseSelectedPointMultipleMode
                    }
                    else {
                        that._setSelectedPoint = that._selectPointSingleMode;
                        that._releaseSelectedPoint = that._releaseSelectedPointSingleMode
                    }
                    if (processMode(options.seriesSelectionMode) === MULTIPLE_MODE) {
                        that._releaseSelectedSeries = that._releaseSelectedSeriesMultipleMode;
                        that._setSelectedSeries = that._setSelectedSeriesMultipleMode
                    }
                    else {
                        that._releaseSelectedSeries = that._releaseSelectedSeriesSingleMode;
                        that._setSelectedSeries = that._setSelectedSeriesSingleMode
                    }
                    that._renderer = options.renderer;
                    that._tooltip = options.tooltip;
                    that._eventTrigger = options.eventTrigger;
                    options.seriesGroup.off().on(eventsConsts.selectSeries, data, that._selectSeries).on(eventsConsts.deselectSeries, data, that._deselectSeries).on(eventsConsts.selectPoint, data, that._selectPoint).on(eventsConsts.deselectPoint, data, that._deselectPoint).on(eventsConsts.showPointTooltip, data, that._showPointTooltip).on(eventsConsts.hidePointTooltip, data, that._hidePointTooltip);
                    that._renderer.root.off(POINTER_ACTION).off("dxclick dxhold").on(POINTER_ACTION, data, that._pointerHandler).on("dxclick", data, that._clickHandler).on("dxhold", {timeout: 300}, $.noop)
                },
                update: function(options) {
                    var that = this;
                    if (that._storedSeries !== options.series) {
                        that._storedSeries = options.series || [];
                        that._clean()
                    }
                    else {
                        that._hideTooltip(that.pointAtShownTooltip);
                        that._clearHover();
                        that.clearSelection()
                    }
                    that._legend = options.legend;
                    that.legendCallback = options.legendCallback;
                    that._prepare(that._renderer.root)
                },
                setCanvases: function(mainCanvas, paneCanvases) {
                    this._mainCanvas = mainCanvas;
                    this._canvases = paneCanvases
                },
                repairTooltip: function() {
                    var point = this.pointAtShownTooltip;
                    if (point && !point.isVisible())
                        this._hideTooltip(point, true);
                    else
                        this._showTooltip(point)
                },
                _prepare: function(root) {
                    root.off("dxmousewheel").on("dxmousewheel", {tracker: this}, function(e) {
                        e.data.tracker._pointerOut()
                    })
                },
                _selectPointMultipleMode: function(point) {
                    var that = this;
                    that._selectedPoint = that._selectedPoint || [];
                    if ($.inArray(point, that._selectedPoint) < 0) {
                        that._selectedPoint.push(point);
                        that._setPointState(point, SET_POINT_SELECTED_STATE, processMode(point.getOptions().selectionMode), POINT_SELECTION_CHANGED, that.legendCallback(point))
                    }
                },
                _releaseSelectedPointMultipleMode: function(point) {
                    var that = this,
                        points = that._selectedPoint || [],
                        pointIndex = $.inArray(point, points);
                    if (pointIndex >= 0) {
                        that._setPointState(point, RELEASE_POINT_SELECTED_STATE, processMode(point.getOptions().selectionMode), POINT_SELECTION_CHANGED, that.legendCallback(point));
                        points.splice(pointIndex, 1)
                    }
                    else if (!point)
                        _each(points, function(_, point) {
                            that._releaseSelectedPoint(point)
                        })
                },
                _selectPointSingleMode: function(point) {
                    var that = this;
                    if (that._selectedPoint !== point) {
                        that._releaseSelectedPoint();
                        that._selectedPoint = point;
                        that._setPointState(point, SET_POINT_SELECTED_STATE, processMode(point.getOptions().selectionMode), POINT_SELECTION_CHANGED, that.legendCallback(point))
                    }
                },
                _releaseSelectedPointSingleMode: function() {
                    var that = this,
                        point = that._selectedPoint;
                    if (point) {
                        that._setPointState(point, RELEASE_POINT_SELECTED_STATE, processMode(point.getOptions().selectionMode), POINT_SELECTION_CHANGED, that.legendCallback(point));
                        that._selectedPoint = null
                    }
                },
                _setPointState: function(point, action, mode, eventName, legendCallback) {
                    var that = this;
                    switch (mode) {
                        case ALL_ARGUMENTS_POINTS_MODE:
                            that._toAllArgumentPoints(point.argument, action, eventName);
                            break;
                        case ALL_SERIES_POINTS_MODE:
                            _each(point.series.getPoints(), function(_, point) {
                                point.series[action](point);
                                that._eventTrigger(eventName, {target: point})
                            });
                            break;
                        case NONE_MODE:
                            break;
                        default:
                            point.series[action](point, legendCallback);
                            that._eventTrigger(eventName, {target: point})
                    }
                },
                _toAllArgumentPoints: function(argument, func, eventName) {
                    var that = this;
                    _each(that._storedSeries, function(_, series) {
                        var neighborPoints = series.getPointsByArg(argument);
                        _each(neighborPoints || [], function(_, point) {
                            series[func](point);
                            eventName && that._eventTrigger(eventName, {target: point})
                        })
                    })
                },
                _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._releaseHoveredPoint();
                    if (point && point.getOptions() && mode !== NONE_MODE) {
                        that.hoveredPoint = point;
                        that._setPointState(point, 'setPointHoverState', mode || processMode(point.getOptions().hoverMode), "pointHoverChanged", that.legendCallback(point))
                    }
                },
                _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._eventTrigger("pointHoverChanged", {target: point})
                        });
                    else if (mode === ALL_ARGUMENTS_POINTS_MODE)
                        that._toAllArgumentPoints(point.argument, 'releasePointHoverState', "pointHoverChanged");
                    else {
                        point.releaseHoverState(that.legendCallback(point));
                        that._eventTrigger("pointHoverChanged", {target: point})
                    }
                    if (that._tooltip.isEnabled())
                        that._hideTooltip(point);
                    that.hoveredPoint = null
                },
                _setSelectedSeriesMultipleMode: function(series, mode) {
                    var that = this;
                    that._selectedSeries = that._selectedSeries || [];
                    if ($.inArray(series, that._selectedSeries) < 0) {
                        that._selectedSeries.push(series);
                        series.setSelectedState(true, mode, that.legendCallback(series));
                        that._eventTrigger("seriesSelectionChanged", {target: series})
                    }
                },
                _setSelectedSeriesSingleMode: function(series, mode) {
                    var that = this;
                    if (series !== that._selectedSeries || series.lastSelectionMode !== mode) {
                        this._releaseSelectedSeries();
                        that._selectedSeries = series;
                        series.setSelectedState(true, mode, that.legendCallback(series));
                        that._eventTrigger("seriesSelectionChanged", {target: series})
                    }
                },
                _releaseSelectedSeriesMultipleMode: function(series) {
                    var that = this,
                        selectedSeries = that._selectedSeries || [],
                        seriesIndex = $.inArray(series, selectedSeries);
                    if (seriesIndex >= 0) {
                        series.setSelectedState(false, undefined, that.legendCallback(series));
                        that._eventTrigger("seriesSelectionChanged", {target: series});
                        selectedSeries.splice(seriesIndex, 1)
                    }
                    else if (!series)
                        _each(selectedSeries, function(_, series) {
                            that._releaseSelectedSeries(series)
                        })
                },
                _releaseSelectedSeriesSingleMode: function() {
                    var that = this,
                        series = that._selectedSeries;
                    if (series) {
                        series.setSelectedState(false, undefined, that.legendCallback(series));
                        that._eventTrigger("seriesSelectionChanged", {target: series});
                        that._selectedSeries = null
                    }
                },
                _setHoveredSeries: function(series, mode) {
                    var that = this;
                    if (mode !== NONE_MODE && that.hoveredSeries !== series || series.lastHoverMode !== mode) {
                        that._clearHover();
                        series.setHoverState(true, mode, that.legendCallback(series));
                        that._eventTrigger("seriesHoverChanged", {target: series})
                    }
                    that.hoveredSeries = series;
                    if (mode === NONE_MODE)
                        $(series).trigger('NoneMode')
                },
                _releaseHoveredSeries: function() {
                    var that = this;
                    if (that.hoveredSeries) {
                        that.hoveredSeries.setHoverState(false, undefined, that.legendCallback(that.hoveredSeries));
                        that._eventTrigger("seriesHoverChanged", {target: that.hoveredSeries});
                        that.hoveredSeries = null
                    }
                },
                _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)
                },
                clearSelection: function() {
                    this._releaseSelectedPoint();
                    this._releaseSelectedSeries()
                },
                _clean: function() {
                    var that = this;
                    that._selectedPoint = that._selectedSeries = that.hoveredPoint = that.hoveredSeries = null;
                    that._hideTooltip(that.pointAtShownTooltip)
                },
                _clearHover: function() {
                    this._releaseHoveredSeries();
                    this._releaseHoveredPoint()
                },
                _hideTooltip: function(point, silent) {
                    var that = this;
                    if (!that._tooltip || point && that.pointAtShownTooltip !== point)
                        return;
                    if (!silent && that.pointAtShownTooltip)
                        that.pointAtShownTooltip = null;
                    that._tooltip.hide()
                },
                _showTooltip: function(point) {
                    var that = this,
                        tooltipFormatObject,
                        eventData;
                    if (point && point.getOptions()) {
                        tooltipFormatObject = point.getTooltipFormatObject(that._tooltip);
                        if (!isDefined(tooltipFormatObject.valueText) && !tooltipFormatObject.points || !point.isVisible())
                            return;
                        if (!that.pointAtShownTooltip || that.pointAtShownTooltip !== point)
                            eventData = {target: point};
                        var coords = point.getTooltipParams(that._tooltip.getLocation()),
                            rootOffset = that._renderer.getRootOffset();
                        coords.x += rootOffset.left;
                        coords.y += rootOffset.top;
                        if (!that._tooltip.show(tooltipFormatObject, coords, eventData))
                            return;
                        that.pointAtShownTooltip = point
                    }
                },
                _showPointTooltip: function(event, point) {
                    var that = event.data.tracker,
                        pointWithTooltip = that.pointAtShownTooltip;
                    if (pointWithTooltip && pointWithTooltip !== point)
                        that._hideTooltip(pointWithTooltip);
                    that._showTooltip(point)
                },
                _hidePointTooltip: function(event, point) {
                    event.data.tracker._hideTooltip(point)
                },
                _enableOutHandler: function() {
                    if (this._outHandler)
                        return;
                    var that = this,
                        handler = function(e) {
                            var rootOffset = that._renderer.getRootOffset(),
                                x = _floor(e.pageX - rootOffset.left),
                                y = _floor(e.pageY - rootOffset.top);
                            if (!that._inCanvas(that._mainCanvas, x, y)) {
                                that._pointerOut();
                                that._disableOutHandler()
                            }
                        };
                    $(document).on(POINTER_ACTION, handler);
                    this._outHandler = handler
                },
                _disableOutHandler: function() {
                    this._outHandler && $(document).off(POINTER_ACTION, this._outHandler);
                    this._outHandler = null
                },
                _pointerOut: function() {
                    this._clearHover();
                    this._tooltip.isEnabled() && this._hideTooltip(this.pointAtShownTooltip)
                },
                _inCanvas: function(canvas, x, y) {
                    return x >= canvas.left && x <= canvas.right && y >= canvas.top && y <= canvas.bottom
                },
                dispose: function() {
                    var that = this;
                    that._disableOutHandler();
                    _each(that, function(k) {
                        that[k] = null
                    })
                }
            };
        charts.ChartTracker = function(options) {
            this.ctor(options)
        };
        $.extend(charts.ChartTracker.prototype, baseTrackerPrototype, {
            ctor: function(options) {
                var that = this;
                baseTrackerPrototype.ctor.call(that, options)
            },
            _pointClick: function(point, event) {
                var that = this,
                    eventTrigger = that._eventTrigger,
                    series = point.series;
                eventTrigger(POINT_CLICK, {
                    target: point,
                    jQueryEvent: event
                }, function() {
                    !eventCanceled(event, series) && eventTrigger(SERIES_CLICK, {
                        target: series,
                        jQueryEvent: event
                    })
                })
            },
            __trackerDelay: DELAY,
            _legendClick: function(series, event) {
                var that = this,
                    evetArgs = {
                        target: series,
                        jQueryEvent: event
                    },
                    eventTrigger = that._eventTrigger;
                eventTrigger(LEGEND_CLICK, evetArgs, function() {
                    !eventCanceled(event, series) && eventTrigger(SERIES_CLICK, evetArgs)
                })
            },
            update: function(options) {
                var that = this;
                that._zoomingMode = (options.zoomingMode + '').toLowerCase();
                that._scrollingMode = (options.scrollingMode + '').toLowerCase();
                baseTrackerPrototype.update.call(this, options);
                that._argumentAxis = getNonVirtualAxis(options.argumentAxis || []);
                that._axisHoverEnabled = that._argumentAxis && processMode(that._argumentAxis.getOptions().hoverMode) === ALL_ARGUMENTS_POINTS_MODE;
                that._chart = options.chart;
                that._rotated = options.rotated;
                that._crosshair = options.crosshair
            },
            _getAxisArgument: function(event) {
                var $target = $(event.target);
                return event.target.tagName === "tspan" ? $target.parent().data('argument') : $target.data('argument')
            },
            _getCanvas: function(x, y) {
                var that = this,
                    canvases = that._canvases || [];
                for (var i = 0; i < canvases.length; i++) {
                    var c = canvases[i];
                    if (that._inCanvas(c, x, y))
                        return c
                }
                return null
            },
            _focusOnCanvas: function(canvas) {
                if (!canvas && this._stickedSeries)
                    this._pointerOut()
            },
            _resetHoveredArgument: function() {
                if (isDefined(this.hoveredArgument)) {
                    this._toAllArgumentPoints(this.hoveredArgument, 'releasePointHoverState');
                    this.hoveredArgument = null
                }
            },
            _hideCrosshair: function() {
                this._crosshair && this._crosshair.hide()
            },
            _moveCrosshair: function(point, x, y) {
                if (point && this._crosshair && point.isVisible()) {
                    var coords = point.getCrosshairCoords(x, y),
                        r = point.getPointRadius();
                    this._crosshair.shift(coords.x, coords.y, r)
                }
            },
            _prepare: function(root) {
                var that = this,
                    touchScrollingEnabled = that._scrollingMode === 'all' || that._scrollingMode === 'touch',
                    touchZoomingEnabled = that._zoomingMode === 'all' || that._zoomingMode === 'touch',
                    cssValue = (!touchScrollingEnabled ? "pan-x pan-y " : '') + (!touchZoomingEnabled ? "pinch-zoom" : '') || "none",
                    rootStyles = {
                        'touch-action': cssValue,
                        '-ms-touch-action': cssValue
                    },
                    wheelzoomingEnabled = that._zoomingMode === "all" || that._zoomingMode === "mouse";
                root.off("dxmousewheel dxc-scroll-start dxc-scroll-move");
                baseTrackerPrototype._prepare.call(that, root);
                if (!that._gestureEndHandler) {
                    that._gestureEndHandler = function() {
                        that._gestureEnd && that._gestureEnd()
                    };
                    $(document).on("dxpointerup", that._gestureEndHandler)
                }
                wheelzoomingEnabled && root.on("dxmousewheel", function(e) {
                    var rootOffset = that._renderer.getRootOffset(),
                        x = that._rotated ? e.pageY - rootOffset.top : e.pageX - rootOffset.left,
                        scale = that._argumentAxis.getTranslator().getMinScale(e.delta > 0),
                        translate = x - x * scale,
                        zoom = that._argumentAxis.getTranslator().zoom(-translate, scale);
                    that._pointerOut();
                    that._chart.zoomArgument(zoom.min, zoom.max, true);
                    e.preventDefault();
                    e.stopPropagation()
                });
                root.on("dxc-scroll-start", function(e) {
                    that._gestureStart(that._getGestureParams(e, {
                        left: 0,
                        top: 0
                    }))
                }).on("dxc-scroll-move", function(e) {
                    that._gestureChange(that._getGestureParams(e, {
                        left: 0,
                        top: 0
                    })) && e.preventDefault()
                });
                root.css(rootStyles)
            },
            _getGestureParams: function(e, offset) {
                var that = this,
                    x1,
                    x2,
                    touches = e.pointers.length,
                    left,
                    right,
                    eventCoordField = that._rotated ? "pageY" : "pageX";
                offset = that._rotated ? offset.top : offset.left;
                if (touches === 2)
                    x1 = e.pointers[0][eventCoordField] - offset,
                    x2 = e.pointers[1][eventCoordField] - offset;
                else if (touches === 1)
                    x1 = x2 = e.pointers[0][eventCoordField] - offset;
                left = math.min(x1, x2);
                right = math.max(x1, x2);
                return {
                        center: left + (right - left) / 2,
                        distance: right - left,
                        touches: touches,
                        scale: 1,
                        pointerType: e.pointerType
                    }
            },
            _gestureStart: function(gestureParams) {
                var that = this;
                that._startGesture = that._startGesture || gestureParams;
                if (that._startGesture.touches !== gestureParams.touches)
                    that._startGesture = gestureParams
            },
            _gestureChange: function(gestureParams) {
                var that = this,
                    startGesture = that._startGesture,
                    gestureChanged = false,
                    scrollingEnabled = that._scrollingMode === 'all' || that._scrollingMode !== 'none' && that._scrollingMode === gestureParams.pointerType,
                    zoommingEnabled = that._zoomingMode === 'all' || that._zoomingMode === 'touch';
                if (!startGesture)
                    return gestureChanged;
                if (startGesture.touches === 1 && math.abs(startGesture.center - gestureParams.center) < 3) {
                    that._gestureStart(gestureParams);
                    return gestureChanged
                }
                if (startGesture.touches === 2 && zoommingEnabled) {
                    gestureChanged = true;
                    startGesture.scale = gestureParams.distance / startGesture.distance;
                    startGesture.scroll = gestureParams.center - startGesture.center + (startGesture.center - startGesture.center * startGesture.scale)
                }
                else if (startGesture.touches === 1 && scrollingEnabled) {
                    gestureChanged = true;
                    startGesture.scroll = gestureParams.center - startGesture.center
                }
                if (gestureChanged) {
                    startGesture.changed = gestureChanged;
                    that._chart._transformArgument(startGesture.scroll, startGesture.scale)
                }
                return gestureChanged
            },
            _gestureEnd: function() {
                var that = this,
                    startGesture = that._startGesture,
                    zoom,
                    renderer = that._renderer;
                that._startGesture = null;
                function complete() {
                    that._chart.zoomArgument(zoom.min, zoom.max, true)
                }
                if (startGesture && startGesture.changed) {
                    zoom = that._argumentAxis._translator.zoom(-startGesture.scroll, startGesture.scale);
                    if (renderer.animationEnabled() && (-startGesture.scroll !== zoom.translate || startGesture.scale !== zoom.scale)) {
                        var translateDelta = -(startGesture.scroll + zoom.translate),
                            scaleDelta = startGesture.scale - zoom.scale;
                        renderer.root.animate({_: 0}, {
                            step: function(pos) {
                                var translateValue = -startGesture.scroll - translateDelta * pos;
                                var scaleValue = startGesture.scale - scaleDelta * pos;
                                that._chart._transformArgument(-translateValue, scaleValue)
                            },
                            complete: complete,
                            duration: 250
                        })
                    }
                    else
                        complete()
                }
            },
            _clean: function() {
                var that = this;
                baseTrackerPrototype._clean.call(that);
                that._resetTimer();
                that._stickedSeries = null
            },
            _getSeriesForShared: function(x, y) {
                var that = this,
                    points = [],
                    point = null,
                    distance = Infinity;
                if (that._tooltip.isShared() && !that.hoveredSeries) {
                    _each(that._storedSeries, function(_, series) {
                        var point = series.getNeighborPoint(x, y);
                        point && points.push(point)
                    });
                    _each(points, function(_, p) {
                        var coords = p.getCrosshairCoords(x, y),
                            d = math.sqrt((x - coords.x) * (x - coords.x) + (y - coords.y) * (y - coords.y));
                        if (d < distance) {
                            point = p;
                            distance = d
                        }
                    })
                }
                return point && point.series
            },
            _setTimeout: function(callback, keeper) {
                var that = this;
                if (that._timeoutKeeper !== keeper) {
                    that._resetTimer();
                    that._hoverTimeout = setTimeout(function() {
                        callback();
                        that._timeoutKeeper = null
                    }, DELAY);
                    that._timeoutKeeper = keeper
                }
            },
            _resetTimer: function() {
                clearTimeout(this._hoverTimeout);
                this._timeoutKeeper = this._hoverTimeout = null
            },
            _pointerHandler: function(e) {
                var that = e.data.tracker,
                    rootOffset = that._renderer.getRootOffset(),
                    x = _floor(e.pageX - rootOffset.left),
                    y = _floor(e.pageY - rootOffset.top),
                    canvas = that._getCanvas(x, y),
                    series = $(e.target).data("series"),
                    point = $(e.target).data("point") || series && series.getPointByCoord(x, y);
                that._enableOutHandler();
                that._x = x;
                that._y = y;
                if (e.type === "dxpointerdown")
                    canvas && that._gestureStart(that._getGestureParams(e, rootOffset));
                else if (that._startGesture && canvas)
                    if (that._gestureChange(that._getGestureParams(e, rootOffset))) {
                        that._pointerOut();
                        e.preventDefault();
                        return
                    }
                if (that._legend.coordsIn(x, y)) {
                    var item = that._legend.getItemByCoord(x, y);
                    if (item) {
                        series = that._storedSeries[item.id];
                        that._setHoveredSeries(series, that._legend._options.hoverMode);
                        that._stickedSeries = series
                    }
                    else
                        that._clearHover();
                    that._hideCrosshair();
                    return
                }
                if (that._axisHoverEnabled && that._argumentAxis.coordsIn(x, y)) {
                    var argument = that._getAxisArgument(e),
                        argumentDefined = isDefined(argument);
                    if (argumentDefined && that.hoveredArgument !== argument) {
                        that._clearHover();
                        that._resetHoveredArgument();
                        that._toAllArgumentPoints(argument, "setPointHoverState");
                        that.hoveredArgument = argument
                    }
                    else if (!argumentDefined)
                        that._resetHoveredArgument();
                    return
                }
                that._resetHoveredArgument();
                that._focusOnCanvas(canvas);
                if (!canvas && !point)
                    return;
                if (!series && !point)
                    that._stickedSeries = that._stickedSeries || that._getSeriesForShared(x, y);
                if (series && !point) {
                    point = series.getNeighborPoint(x, y);
                    if (series !== that.hoveredSeries) {
                        that._setTimeout(function() {
                            that._setHoveredSeries(series, series.getOptions().hoverMode);
                            that._stickedSeries = series;
                            that._pointerComplete(point)
                        }, series);
                        return
                    }
                }
                else if (point) {
                    if (that.hoveredSeries)
                        that._setTimeout(function() {
                            that._pointerOnPoint(point)
                        }, point);
                    else
                        that._pointerOnPoint(point);
                    return
                }
                else if (that._stickedSeries) {
                    series = that._stickedSeries;
                    point = series.getNeighborPoint(x, y);
                    that.hoveredSeries && that._releaseHoveredSeries();
                    point && that._setHoveredPoint(point)
                }
                that._pointerComplete(point)
            },
            _pointerOnPoint: function(point) {
                var that = this;
                that._stickedSeries = point.series;
                that._setHoveredPoint(point);
                that.hoveredSeries && that._releaseHoveredSeries();
                that._pointerComplete(point)
            },
            _pointerComplete: function(point) {
                var that = this;
                that.hoveredSeries && that.hoveredSeries.updateHover(that._x, that._y);
                that._resetTimer();
                that._moveCrosshair(point, that._x, that._y);
                that.pointAtShownTooltip !== point && that._tooltip.isEnabled() && that._showTooltip(point)
            },
            _pointerOut: function() {
                var that = this;
                that._stickedSeries = null;
                that._hideCrosshair();
                that._resetHoveredArgument();
                that._resetTimer();
                baseTrackerPrototype._pointerOut.call(that)
            },
            _clickHandler: function(e) {
                var that = e.data.tracker,
                    rootOffset = that._renderer.getRootOffset(),
                    x = _floor(e.pageX - rootOffset.left),
                    y = _floor(e.pageY - rootOffset.top),
                    point = $(e.target).data("point"),
                    series = that._stickedSeries || $(e.target).data("series") || point && point.series,
                    axis = that._argumentAxis;
                if (that._legend.coordsIn(x, y)) {
                    var item = that._legend.getItemByCoord(x, y);
                    if (item) {
                        series = that._storedSeries[item.id];
                        that._legendClick(series, e)
                    }
                    return
                }
                if (axis && axis.coordsIn(x, y)) {
                    var argument = that._getAxisArgument(e);
                    if (isDefined(argument)) {
                        that._eventTrigger("argumentAxisClick", {
                            argument: argument,
                            jQueryEvent: e
                        });
                        return
                    }
                }
                if (series) {
                    point = point || series.getPointByCoord(x, y);
                    if (point)
                        that._pointClick(point, e);
                    else
                        $(e.target).data("series") && that._eventTrigger(SERIES_CLICK, {
                            target: series,
                            jQueryEvent: e
                        })
                }
            },
            dispose: function() {
                this._gestureEndHandler && $(document).off("dxpointerup", this._gestureEndHandler);
                this._resetTimer();
                baseTrackerPrototype.dispose.call(this)
            }
        });
        charts.PieTracker = function(options) {
            this.ctor(options)
        };
        $.extend(charts.PieTracker.prototype, baseTrackerPrototype, {
            _legendClick: function(point, event) {
                var that = this,
                    eventArg = {
                        target: point,
                        jQueryEvent: event
                    },
                    eventTrigger = that._eventTrigger;
                eventTrigger(LEGEND_CLICK, eventArg, function() {
                    !eventCanceled(event, point) && eventTrigger(POINT_CLICK, eventArg)
                })
            },
            _pointerHandler: function(e) {
                var that = e.data.tracker,
                    rootOffset = that._renderer.getRootOffset(),
                    x = _floor(e.pageX - rootOffset.left),
                    y = _floor(e.pageY - rootOffset.top),
                    series = that._storedSeries[0],
                    point = $(e.target).data("point") || series && series.getPointByCoord(x, y),
                    item,
                    mode;
                that._enableOutHandler();
                if (that._legend.coordsIn(x, y)) {
                    item = that._legend.getItemByCoord(x, y);
                    if (item) {
                        point = series.getPoints()[item.id];
                        mode = that._legend._options.hoverMode
                    }
                }
                if (point && point !== that.hoveredPoint) {
                    that._tooltip.isEnabled() && that._showTooltip(point);
                    that._setHoveredPoint(point, mode)
                }
                else if (!point)
                    that._pointerOut()
            },
            _clickHandler: function(e) {
                var that = e.data.tracker,
                    rootOffset = that._renderer.getRootOffset(),
                    x = _floor(e.pageX - rootOffset.left),
                    y = _floor(e.pageY - rootOffset.top),
                    storedSeries = that._storedSeries[0],
                    point;
                if (that._legend.coordsIn(x, y)) {
                    var item = that._legend.getItemByCoord(x, y);
                    if (item) {
                        point = storedSeries.getPoints()[item.id];
                        that._legendClick(point, e)
                    }
                }
                else {
                    point = $(e.target).data("point") || storedSeries && storedSeries.getPointByCoord(x, y);
                    point && that._eventTrigger(POINT_CLICK, {
                        target: point,
                        jQueryEvent: e
                    })
                }
            }
        })
    })(jQuery, DevExpress, Math);
    /*! Module viz-charts, file crosshair.js */
    (function($, DX, undefined) {
        var _math = Math,
            mathAbs = _math.abs,
            mathMin = _math.min,
            mathMax = _math.max,
            _round = _math.round,
            HORIZONTAL = "horizontal",
            VERTICAL = "vertical",
            LABEL_BACKGROUND_PADDING_X = 8,
            LABEL_BACKGROUND_PADDING_Y = 4,
            CENTER = "center",
            RIGHT = "right",
            LEFT = "left",
            TOP = "top",
            BOTTOM = "bottom",
            _isDefined = DX.utils.isDefined;
        function Crosshair() {
            this.ctor.apply(this, arguments)
        }
        DX.viz.charts.Crosshair = Crosshair;
        Crosshair.prototype = {
            ctor: function(renderer, options, params, group) {
                var that = this;
                that._renderer = renderer;
                that._crosshairGroup = group;
                that._options = {};
                that._init(options, params)
            },
            update: function(options, params) {
                this._init(options, params)
            },
            dispose: function() {
                var that = this;
                that._renderer = null;
                that._crosshairGroup = null;
                that._options = null;
                that._axes = null;
                that._canvas = null;
                that._horizontalGroup = null;
                that._verticalGroup = null;
                that._horizontal = null;
                that._vertical = null;
                that._circle = null;
                that._panes = null
            },
            _init: function(options, params) {
                var that = this,
                    canvas = params.canvas;
                that._canvas = {
                    top: canvas.top,
                    bottom: canvas.height - canvas.bottom,
                    left: canvas.left,
                    right: canvas.width - canvas.right,
                    width: canvas.width,
                    height: canvas.height
                };
                that._axes = params.axes;
                that._panes = params.panes;
                that._prepareOptions(options, HORIZONTAL);
                that._prepareOptions(options, VERTICAL)
            },
            _prepareOptions: function(options, direction) {
                this._options[direction] = {
                    visible: options[direction + "Line"].visible,
                    line: {
                        stroke: options[direction + "Line"].color || options.color,
                        "stroke-width": options[direction + "Line"].width || options.width,
                        dashStyle: options[direction + "Line"].dashStyle || options.dashStyle,
                        opacity: options[direction + "Line"].opacity || options.opacity,
                        "stroke-linecap": "butt"
                    },
                    label: $.extend(true, {}, options.label, options[direction + "Line"].label)
                }
            },
            _createLines: function(options, sharpParam, group) {
                var lines = [],
                    canvas = this._canvas,
                    points = [canvas.left, canvas.top, canvas.left, canvas.top];
                for (var i = 0; i < 2; i++)
                    lines.push(this._renderer.path(points, "line").attr(options).sharp(sharpParam).append(group));
                return lines
            },
            render: function() {
                var that = this,
                    renderer = that._renderer,
                    options = that._options,
                    verticalOptions = options.vertical,
                    horizontalOptions = options.horizontal,
                    extraOptions = horizontalOptions.visible ? horizontalOptions.line : verticalOptions.line,
                    circleOptions = {
                        stroke: extraOptions.stroke,
                        "stroke-width": extraOptions["stroke-width"],
                        dashStyle: extraOptions.dashStyle,
                        opacity: extraOptions.opacity
                    },
                    canvas = that._canvas;
                that._horizontal = {};
                that._vertical = {};
                that._horizontalGroup = renderer.g().append(that._crosshairGroup);
                that._verticalGroup = renderer.g().append(that._crosshairGroup);
                if (verticalOptions.visible) {
                    that._vertical.lines = that._createLines(verticalOptions.line, "h", that._verticalGroup);
                    that._vertical.labels = that._createLabels(that._axes[0], verticalOptions, false, that._verticalGroup)
                }
                if (horizontalOptions.visible) {
                    that._horizontal.lines = that._createLines(horizontalOptions.line, "v", that._horizontalGroup);
                    that._horizontal.labels = that._createLabels(that._axes[1], horizontalOptions, true, that._horizontalGroup)
                }
                that._circle = renderer.circle(canvas.left, canvas.top, 0).attr(circleOptions).append(that._crosshairGroup)
            },
            _createLabels: function(axes, options, isHorizontal, group) {
                var that = this,
                    canvas = that._canvas,
                    renderer = that._renderer,
                    x,
                    y,
                    text,
                    labels = [],
                    background,
                    curentLabelPos,
                    bbox;
                if (!options.label || !options.label.visible)
                    return;
                $.each(axes, function(_, axis) {
                    var axisOptions = axis.getOptions(),
                        position = axisOptions.position;
                    if (axis._virtual || axisOptions.stubData)
                        return;
                    curentLabelPos = axis.getCurrentLabelPos();
                    if (isHorizontal) {
                        y = canvas.top;
                        x = curentLabelPos
                    }
                    else {
                        x = canvas.left;
                        y = curentLabelPos
                    }
                    text = renderer.text("0", x, y).css(DX.viz.core.utils.patchFontOptions(options.label.font)).attr({align: position === TOP || position === BOTTOM ? CENTER : position === RIGHT ? LEFT : RIGHT}).append(group);
                    bbox = text.getBBox();
                    text.attr({y: isHorizontal ? 2 * y - bbox.y - bbox.height / 2 : position === BOTTOM ? 2 * y - bbox.y : 2 * y - (bbox.y + bbox.height)});
                    background = renderer.rect(0, 0, 0, 0).attr({fill: options.label.backgroundColor || options.line.stroke}).append(group).toBackground();
                    labels.push({
                        text: text,
                        background: background,
                        axis: axis,
                        pos: {
                            coord: curentLabelPos,
                            side: position
                        }
                    })
                });
                return labels
            },
            _updateText: function(coord, labels) {
                var that = this,
                    bbox,
                    text,
                    textElement,
                    backgroundElement;
                if (!labels)
                    return;
                $.each(labels, function(i, label) {
                    textElement = label.text;
                    backgroundElement = label.background;
                    if (!textElement)
                        return;
                    text = label.axis.getUntranslatedValue(coord);
                    if (_isDefined(text)) {
                        textElement.attr({text: text});
                        bbox = textElement.getBBox();
                        that._updateLinesCanvas(label.pos.side, label.pos.coord);
                        backgroundElement.attr({
                            x: bbox.x - LABEL_BACKGROUND_PADDING_X,
                            y: bbox.y - LABEL_BACKGROUND_PADDING_Y,
                            width: bbox.width + LABEL_BACKGROUND_PADDING_X * 2,
                            height: bbox.height + LABEL_BACKGROUND_PADDING_Y * 2
                        })
                    }
                    else {
                        textElement.attr({text: ""});
                        backgroundElement.attr({
                            x: 0,
                            y: 0,
                            width: 0,
                            height: 0
                        })
                    }
                })
            },
            show: function() {
                this._crosshairGroup.attr({visibility: "visible"})
            },
            hide: function() {
                this._crosshairGroup.attr({visibility: "hidden"})
            },
            _updateLinesCanvas: function(position, labelPosition) {
                var coords = this._linesCanvas,
                    canvas = this._canvas;
                coords[position] = coords[position] !== canvas[position] && mathAbs(coords[position] - canvas[position]) < mathAbs(labelPosition - canvas[position]) ? coords[position] : labelPosition
            },
            _updateLines: function(lines, x, y, r, isHorizontal) {
                var coords = this._linesCanvas,
                    canvas = this._canvas,
                    points = isHorizontal ? [[mathMin(x - r, coords.left), canvas.top, x - r, canvas.top], [x + r, canvas.top, mathMax(coords.right, x + r), canvas.top]] : [[canvas.left, mathMin(coords.top, y - r), canvas.left, y - r], [canvas.left, y + r, canvas.left, mathMax(coords.bottom, y + r)]];
                for (var i = 0; i < 2; i++)
                    lines[i].attr({points: points[i]})
            },
            _resetLinesCanvas: function() {
                var canvas = this._canvas;
                this._linesCanvas = {
                    left: canvas.left,
                    right: canvas.right,
                    top: canvas.top,
                    bottom: canvas.bottom
                }
            },
            _getClipRectForPane: function(x, y) {
                var panes = this._panes,
                    i,
                    coords;
                for (i = 0; i < panes.length; i++) {
                    coords = panes[i].coords;
                    if (coords.left <= x && coords.right >= x && coords.top <= y && coords.bottom >= y)
                        return panes[i].clipRect
                }
                return {id: null}
            },
            shift: function(x, y, r) {
                var that = this,
                    horizontal = that._horizontal,
                    vertical = that._vertical,
                    clipRect,
                    rad = !r ? 0 : r + 3,
                    canvas = that._canvas;
                x = _round(x);
                y = _round(y);
                if (x >= canvas.left && x <= canvas.right && y >= canvas.top && y <= canvas.bottom) {
                    that.show();
                    that._resetLinesCanvas();
                    clipRect = that._getClipRectForPane(x, y);
                    that._circle.attr({
                        cx: x,
                        cy: y,
                        r: rad,
                        clipId: clipRect.id
                    });
                    if (horizontal.lines) {
                        that._updateText(y, horizontal.labels);
                        that._updateLines(horizontal.lines, x, y, rad, true);
                        that._horizontalGroup.attr({translateY: y - canvas.top})
                    }
                    if (vertical.lines) {
                        that._updateText(x, vertical.labels);
                        that._updateLines(vertical.lines, x, y, rad, false);
                        that._verticalGroup.attr({translateX: x - canvas.left})
                    }
                }
                else
                    that.hide()
            }
        }
    })(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,
            _String = String;
        DX.viz.gauges.__factory = {
            createCircularIndicator: function(parameters, type, _strict) {
                var indicatorType;
                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;
                    default:
                        indicatorType = _strict ? null : circularNeedles.RectangleNeedle;
                        break
                }
                return indicatorType ? new indicatorType(parameters) : null
            },
            createLinearIndicator: function(parameters, type, _strict) {
                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;
                    case'trianglemarker':
                        indicatorType = linearMarkers.TriangleMarker;
                        break;
                    case'textcloud':
                        indicatorType = linearMarkers.TextCloudMarker;
                        break;
                    default:
                        indicatorType = _strict ? null : internals.LinearRangeBar;
                        break
                }
                return indicatorType ? new indicatorType(parameters) : null
            },
            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,
            _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)) {
                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 baseIndicator.js */
    (function(DX, $, undefined) {
        var _isFinite = isFinite,
            _Number = Number;
        DX.viz.gauges.__internals.BaseElement = DX.Class.inherit({
            ctor: function(parameters) {
                var that = this;
                $.each(parameters, function(name, value) {
                    that["_" + name] = value
                });
                that._init()
            },
            dispose: function() {
                var that = this;
                $.each(that, function(name) {
                    that[name] = null
                });
                return that
            },
            getOffset: function() {
                return _Number(this._options.offset) || 0
            }
        });
        DX.viz.gauges.__internals.BaseIndicator = DX.viz.gauges.__internals.BaseElement.inherit({
            _init: function() {
                this._rootElement = this._createRoot();
                this._trackerElement = this._createTracker()
            },
            _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, notifyReady) {
                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,
                    complete: notifyReady
                })
            },
            _createRoot: function() {
                return this._renderer.g().attr({'class': this._className})
            },
            _createTracker: function() {
                return this._renderer.path([], "area")
            },
            _getTrackerSettings: $.noop,
            clean: function() {
                var that = this;
                that._animation && that._rootElement.stopAnimation();
                that._rootElement.remove();
                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.attr({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.attr(that._getTrackerSettings());
                    that._move()
                }
                return that
            },
            value: function(arg, _noAnimation) {
                var that = this,
                    immediateReady = true,
                    val;
                if (arg !== undefined) {
                    val = that._translator.adjust(arg);
                    that._notifiers.dirty();
                    if (that._currentValue !== val && _isFinite(val)) {
                        that._currentValue = val;
                        if (that.visible)
                            if (that._animation && !_noAnimation) {
                                immediateReady = false;
                                that._runAnimation(val, that._notifiers.ready)
                            }
                            else {
                                that._actualValue = val;
                                that._actualPosition = that._translator.translate(val);
                                that._move()
                            }
                    }
                    immediateReady && that._notifiers.ready();
                    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 viz = DX.viz,
            core = viz.core,
            _min = Math.min,
            _round = Math.round,
            _formatValue = viz.gauges.__internals.formatValue,
            _getSampleText = viz.gauges.__internals.getSampleText,
            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];
        function getTextCloudInfo(options) {
            var x = options.x,
                y = options.y,
                type = COEFFICIENTS_MAP[options.type],
                cloudWidth = options.textWidth + 2 * options.horMargin,
                cloudHeight = options.textHeight + 2 * options.verMargin,
                tailWidth,
                tailHeight,
                cx = x,
                cy = y;
            tailWidth = tailHeight = options.tailLength;
            if (type[0] & 1)
                tailHeight = _min(tailHeight, cloudHeight / 3);
            else
                tailWidth = _min(tailWidth, cloudWidth / 3);
            return {
                    cx: _round(cx + type[0] * tailWidth + (type[0] + type[2]) * cloudWidth / 2),
                    cy: _round(cy + type[1] * tailHeight + (type[1] + type[3]) * cloudHeight / 2),
                    points: [_round(x), _round(y), _round(x += type[0] * (cloudWidth + tailWidth)), _round(y += type[1] * (cloudHeight + tailHeight)), _round(x += type[2] * cloudWidth), _round(y += type[3] * cloudHeight), _round(x += type[4] * cloudWidth), _round(y += type[5] * cloudHeight), _round(x += type[6] * (cloudWidth - tailWidth)), _round(y += type[7] * (cloudHeight - tailHeight))]
                }
        }
        viz.gauges.__tests.getTextCloudInfo = getTextCloudInfo;
        viz.gauges.__internals.BaseTextCloudMarker = viz.gauges.__internals.BaseIndicator.inherit({
            _move: function() {
                var that = this,
                    bbox,
                    info,
                    textCloudOptions = that._getTextCloudOptions();
                that._text.attr({text: _formatValue(that._actualValue, that._options.text)});
                bbox = that._text.getBBox();
                info = getTextCloudInfo({
                    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.attr({
                    x: info.cx,
                    y: info.cy + that._textVerticalOffset
                });
                that._cloud.attr({points: info.points});
                that._trackerElement && that._trackerElement.attr({points: info.points})
            },
            _measureText: function() {
                var that = this,
                    root,
                    text,
                    bbox;
                if (!that._textVerticalOffset) {
                    root = that._createRoot().append(that._owner);
                    text = that._renderer.text(_getSampleText(that._translator, that._options.text), 0, 0).attr({align: "center"}).css(core.utils.patchFontOptions(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.path([], "area").append(that._rootElement);
                that._text = that._text || that._renderer.text().append(that._rootElement);
                that._text.attr({align: "center"}).css(core.utils.patchFontOptions(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 viz = DX.viz,
            core = viz.core,
            $extend = $.extend,
            formatValue = viz.gauges.__internals.formatValue,
            getSampleText = viz.gauges.__internals.getSampleText;
        viz.gauges.__internals.BaseRangeBar = 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.text(getSampleText(that._translator, that._options.text), 0, 0).attr({
                        'class': 'dxg-text',
                        align: 'center'
                    }).css(core.utils.patchFontOptions(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.attr({text: formatValue(that._actualValue, that._options.text)});
                    that._updateTextPosition();
                    that._updateLinePosition()
                }
            },
            _updateBarItems: function() {
                var that = this,
                    options = that._options,
                    backgroundColor,
                    spaceColor,
                    translator = that._translator;
                that._setBarSides();
                that._startPosition = translator.translate(translator.getDomainStart());
                that._endPosition = translator.translate(translator.getDomainEnd());
                that._basePosition = 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.attr({fill: backgroundColor});
                that._backItem2.attr({fill: backgroundColor});
                that._spaceItem1.attr({fill: spaceColor});
                that._spaceItem2.attr({fill: spaceColor})
            },
            _getSpace: function() {
                return 0
            },
            _updateTextItems: function() {
                var that = this;
                if (that._hasText) {
                    that._line = that._line || that._renderer.path([], "line").attr({
                        'class': 'dxg-main-bar',
                        "stroke-linecap": "square"
                    }).append(that._rootElement);
                    that._text = that._text || that._renderer.text('', 0, 0).attr({'class': 'dxg-text'}).append(that._rootElement);
                    that._text.attr({align: that._getTextAlign()}).css(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 core.utils.patchFontOptions(font)
            },
            _updateBarItemsPositions: function() {
                var that = this,
                    positions = that._getPositions();
                that._backItem1.attr(that._buildItemSettings(positions.start, positions.back1));
                that._backItem2.attr(that._buildItemSettings(positions.back2, positions.end));
                that._spaceItem1.attr(that._buildItemSettings(positions.back1, positions.main1));
                that._spaceItem2.attr(that._buildItemSettings(positions.main2, positions.back2));
                that._mainItem.attr(that._buildItemSettings(positions.main1, positions.main2));
                that._trackerElement && that._trackerElement.attr(that._buildItemSettings(positions.main1, positions.main2))
            },
            _render: function() {
                var that = this;
                that._measureText();
                if (!that._backItem1) {
                    that._backItem1 = that._createBarItem();
                    that._backItem1.attr({'class': 'dxg-back-bar'})
                }
                if (!that._backItem2) {
                    that._backItem2 = that._createBarItem();
                    that._backItem2.attr({'class': 'dxg-back-bar'})
                }
                if (!that._spaceItem1) {
                    that._spaceItem1 = that._createBarItem();
                    that._spaceItem1.attr({'class': 'dxg-space-bar'})
                }
                if (!that._spaceItem2) {
                    that._spaceItem2 = that._createBarItem();
                    that._spaceItem2.attr({'class': 'dxg-space-bar'})
                }
                if (!that._mainItem) {
                    that._mainItem = that._createBarItem();
                    that._mainItem.attr({'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,
            _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.circle().append(that._rootElement);
                    that._spindleInner = that._spindleInner || that._renderer.circle().append(that._rootElement);
                    that._spindleOuter.attr({
                        'class': 'dxg-spindle-border',
                        cx: options.x,
                        cy: options.y,
                        r: options.spindleSize / 2
                    });
                    that._spindleInner.attr({
                        '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.path([], "area").append(that._rootElement);
                that._element.attr({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.path([], "area").append(that._rootElement);
                that._element.attr({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 = y4;
                else {
                    y3 = y4 + (y1 - y4) * fraction;
                    y2 = y3 + _Number(options.space)
                }
                that._firstElement = that._firstElement || that._renderer.path([], "area").append(that._rootElement);
                that._spaceElement = that._spaceElement || that._renderer.path([], "area").append(that._rootElement);
                that._secondElement = that._secondElement || that._renderer.path([], "area").append(that._rootElement);
                that._firstElement.attr({points: [x1, y1, x1, y2, x2, y2, x2, y1]});
                that._spaceElement.attr({
                    points: [x1, y2, x1, y3, x2, y3, x2, y2],
                    'class': 'dxg-hole',
                    fill: options.containerBackgroundColor
                });
                that._secondElement.attr({
                    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;
        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() {
                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.path([], "area").append(that._rootElement);
                that._element.attr({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.path([], "area").append(that._rootElement);
                that._element.attr({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.circle().append(that._rootElement);
                that._element.attr({
                    cx: x,
                    cy: y,
                    r: r
                })
            }})
    })(DevExpress);
    /*! Module viz-gauges, file circularMarker.js */
    (function(DX, undefined) {
        var circularMarkers = DX.viz.gauges.__internals.circularMarkers,
            _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.path([], "area").append(that._rootElement);
                settings = {
                    points: [x, y1, x - dx, y2, x + dx, y2],
                    stroke: "none",
                    "stroke-width": 0,
                    "stroke-linecap": "square"
                };
                if (options.space > 0) {
                    settings["stroke-width"] = Math.min(options.space, options.width / 4) || 0;
                    settings.stroke = settings["stroke-width"] > 0 ? options.containerBackgroundColor || "none" : "none"
                }
                that._element.attr(settings).sharp()
            },
            _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,
                    arrowLength = _Number(that._options.arrowLength) || 0,
                    verticalOffset,
                    horizontalOffset;
                that._measureText();
                verticalOffset = that._textFullHeight + arrowLength;
                horizontalOffset = that._textFullWidth + arrowLength;
                return {
                        min: layout.radius,
                        max: layout.radius,
                        horizontalOffset: horizontalOffset,
                        verticalOffset: verticalOffset,
                        inverseHorizontalOffset: horizontalOffset,
                        inverseVerticalOffset: verticalOffset
                    }
            }
        })
    })(DevExpress);
    /*! Module viz-gauges, file linearMarker.js */
    (function(DX, undefined) {
        var linearMarkers = DX.viz.gauges.__internals.linearMarkers,
            _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() {
                return true
            },
            _render: function() {
                var that = this,
                    options = that._options,
                    x1,
                    x2,
                    y1,
                    y2,
                    settings = {
                        stroke: 'none',
                        "stroke-width": 0,
                        "stroke-linecap": "square"
                    };
                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["stroke-width"] = Math.min(options.space, options.width / 4) || 0;
                    settings.stroke = settings["stroke-width"] > 0 ? options.containerBackgroundColor || 'none' : 'none'
                }
                that._element = that._element || that._renderer.path([], "area").append(that._rootElement);
                that._element.attr(settings).sharp()
            },
            _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() {
                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.arc().attr({"stroke-linejoin": "round"}).append(this._rootElement)
            },
            _createTracker: function() {
                return this._renderer.arc().attr({"stroke-linejoin": "round"})
            },
            _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,
                    indent = _Number(options.text.indent);
                that._lineFrom = options.y - options.radius;
                that._lineTo = that._lineFrom - indent;
                that._textRadius = options.radius + 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.attr({
                    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.attr({points: [x1, that._lineFrom, x1, that._lineTo, x2, that._lineTo, x2, that._lineFrom]}).rotate(convertAngleToRendererSpace(that._actualPosition), x, that._options.y).sharp()
            },
            _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() {
                return true
            },
            _createBarItem: function() {
                return this._renderer.path([], "area").append(this._rootElement)
            },
            _createTracker: function() {
                return this._renderer.path([], "area")
            },
            _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,
                    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,
                    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.attr(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.attr({points: points}).sharp()
            },
            _getTooltipPosition: function() {
                var that = this,
                    crossCenter = (that._minSide + that._maxSide) / 2,
                    alongCenter = (that._basePosition + that._actualPosition) / 2;
                return that.vertical ? {
                        x: crossCenter,
                        y: alongCenter
                    } : {
                        x: alongCenter,
                        y: crossCenter
                    }
            },
            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 scale.js */
    (function(DX, $, undefined) {
        var viz = DX.viz,
            core = viz.core,
            _Number = Number,
            _String = String,
            _isFinite = isFinite,
            _math = Math,
            _min = _math.min,
            _max = _math.max,
            _abs = _math.abs,
            PI_DIV_180 = _math.PI / 180,
            utils = DX.utils,
            _isFunction = utils.isFunction,
            _isArray = utils.isArray,
            _getCosAndSin = utils.getCosAndSin,
            _convertAngleToRendererSpace = utils.convertAngleToRendererSpace,
            _map = $.map,
            _formatHelper = DX.formatHelper,
            _createTickManager = core.CoreFactory.createTickManager;
        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
        }
        viz.gauges.__internals.BaseScale = viz.gauges.__internals.BaseElement.inherit({
            _init: function() {
                var that = this;
                that._root = that._renderer.g().attr({'class': 'dxg-scale'});
                that._majorTicks = that._renderer.g().attr({'class': 'dxg-major-ticks'});
                that._minorTicks = that._renderer.g().attr({'class': 'dxg-minor-ticks'});
                that._labels = that._renderer.g().attr({'class': 'dxg-labels'})
            },
            clean: function() {
                var that = this;
                that._root.remove();
                that._majorTicks.remove().clear();
                that._minorTicks.remove().clear();
                that._labels.remove().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()
            },
            _measureText: function() {
                var that = this,
                    domain = that._translator.getDomain(),
                    options = that._options,
                    tickManager = _createTickManager({}, {
                        min: domain[0],
                        max: domain[1],
                        screenDelta: options.approximateScreenDelta
                    }, {
                        tickInterval: options.majorTick.tickInterval > 0 ? _Number(options.majorTick.tickInterval) : undefined,
                        stick: true,
                        textFontStyles: core.utils.patchFontOptions(options.label.font),
                        gridSpacingFactor: that._getGridSpacingFactor().majorTicks,
                        renderText: function(text, x, y, options) {
                            return that._renderer.text(text, x, y, options).append(that._renderer.root)
                        },
                        getText: function(value) {
                            return that._formatValue(value)
                        },
                        overlappingBehaviorType: that._overlappingBehaviorType
                    }),
                    maxTextParams = tickManager.getMaxLabelParams();
                that._textVerticalOffset = -maxTextParams.y - maxTextParams.height / 2;
                that._textWidth = maxTextParams.width;
                that._textHeight = maxTextParams.height;
                that._textLength = maxTextParams.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
            },
            _getLabelPosition: function(layout) {
                return this._getAxisLabelPosition(_Number(this._options.majorTick.length), _Number(this._options.label.indentFromTick), layout)
            },
            _generateTicks: function(layout) {
                var that = this,
                    scaleOptions = that._options,
                    translatorDomains = that._translator.getDomain(),
                    data = {
                        min: translatorDomains[0],
                        max: translatorDomains[1],
                        screenDelta: that._getScreenDelta(layout)
                    },
                    gridSpacingFactors = that._getGridSpacingFactor(),
                    options = {
                        tickInterval: scaleOptions.majorTick.tickInterval > 0 ? _Number(scaleOptions.majorTick.tickInterval) : undefined,
                        minorTickInterval: scaleOptions.minorTick.tickInterval > 0 ? _Number(scaleOptions.minorTick.tickInterval) : undefined,
                        gridSpacingFactor: gridSpacingFactors.majorTicks,
                        minorGridSpacingFactor: gridSpacingFactors.minorTicks,
                        numberMultipliers: [1, 2, 5],
                        textFontStyles: core.utils.patchFontOptions(scaleOptions.label.font),
                        labelOptions: scaleOptions.label,
                        getText: function(value) {
                            return that._formatValue(value)
                        },
                        isHorizontal: !that.vertical,
                        stick: true,
                        showMinorTicks: true
                    },
                    tickManager;
                if (scaleOptions.majorTick.useTicksAutoArrangement) {
                    options.useTicksAutoArrangement = true;
                    options.renderText = function(text, x, y, options) {
                        return that._renderer.text(text, x, y, options).append(that._renderer.root)
                    };
                    options.translate = that._getTranslateFunction(layout);
                    that._applyOverlappingOptions(options, layout)
                }
                tickManager = _createTickManager({}, data, options);
                return {
                        majorTicks: tickManager.getTicks(true),
                        minorTicks: tickManager.getMinorTicks()
                    }
            },
            _getTicks: function(layout) {
                var that = this,
                    options = that._options,
                    info = that._generateTicks(layout),
                    majorValues = options.majorTick.showCalculatedTicks ? info.majorTicks : [],
                    customMajorValues = _map(that._getCustomValues(options.majorTick.customTickValues, sortAsc), function(value) {
                        return binarySearch(value, majorValues) === -1 ? value : null
                    }),
                    minorValues = _map(options.minorTick.showCalculatedTicks ? info.minorTicks : [], function(value) {
                        return binarySearch(value, customMajorValues) === -1 ? value : null
                    }),
                    customMinorValues = that._getCustomValues(options.minorTick.customTickValues, sortAsc),
                    list = majorValues.concat(minorValues, customMajorValues).sort(sortAsc);
                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,
                    points,
                    i = 0,
                    ii = ticks.length,
                    element;
                that._majorTicks.clear().attr({fill: that._options.majorTick.color});
                points = that._getTickPoints(_Number(that._options.majorTick.length), _Number(that._options.majorTick.width), layout);
                if (points) {
                    that._options.hideFirstTick && ++i;
                    that._options.hideLastTick && --ii;
                    for (; i < ii; ++i) {
                        element = that._renderer.path(points, "area");
                        that._moveTick(element, ticks[i], layout);
                        element.append(that._majorTicks)
                    }
                }
            },
            _createMinorTicks: function(ticks, layout) {
                var that = this,
                    points,
                    i = 0,
                    ii = ticks.length,
                    element;
                that._minorTicks.clear().attr({fill: that._options.minorTick.color});
                points = that._getTickPoints(_Number(that._options.minorTick.length), _Number(that._options.minorTick.width), layout);
                if (points)
                    for (; i < ii; ++i) {
                        element = that._renderer.path(points, "area");
                        that._moveTick(element, ticks[i], layout);
                        element.append(that._minorTicks)
                    }
            },
            _createLabels: function(ticks, layout) {
                var that = this,
                    indentFromTick = _Number(that._options.label.indentFromTick),
                    textPosition,
                    i = 0,
                    ii = ticks.length,
                    points,
                    text,
                    fontStyles = {},
                    rangeContainer;
                that._labels.clear().attr({align: that._getLabelAlign(indentFromTick)}).css(core.utils.patchFontOptions(that._options.label.font));
                textPosition = that._getLabelPosition(layout);
                if (textPosition) {
                    rangeContainer = that._options.label.useRangeColors ? that._options.rangeContainer : null;
                    that._options.hideFirstLabel && ++i;
                    that._options.hideLastLabel && --ii;
                    for (; i < ii; ++i) {
                        text = that._formatValue(ticks[i].value);
                        fontStyles.fill = rangeContainer ? rangeContainer.getColorForValue(ticks[i].value) : null;
                        points = that._getLabelOptions(text, textPosition, indentFromTick, ticks[i], layout);
                        that._renderer.text(text, points.x, points.y + that._textVerticalOffset).css(fontStyles).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
            }
        });
        viz.gauges.__internals.CircularScale = viz.gauges.__internals.BaseScale.inherit({
            _getGridSpacingFactor: function() {
                return {
                        majorTicks: 17,
                        minorTicks: 5
                    }
            },
            _getTranslateFunction: function(layout) {
                var that = this,
                    indent = _Number(that._options.label.indentFromTick),
                    translator = this._translator;
                layout = layout || {
                    x: 0,
                    y: 0,
                    radius: 0
                };
                return function(value) {
                        var position = that._getLabelPosition(layout),
                            text = that._formatValue(value);
                        return that._getLabelOptions(text, position, indent, {position: translator.translate(value)}, layout)
                    }
            },
            _overlappingBehaviorType: "circular",
            _getScreenDelta: function(layout) {
                return (this._translator.getCodomainStart() - this._translator.getCodomainEnd()) * layout.radius * PI_DIV_180
            },
            _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)
            },
            _getAxisLabelPosition: 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'
            },
            _applyOverlappingOptions: function(options, layout) {
                options.circularRadius = this._getLabelPosition(layout);
                options.circularStartAngle = this._translator.getCodomainStart();
                options.circularEndAngle = this._translator.getCodomainEnd();
                options.overlappingBehaviorType = "circular"
            },
            _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
            }
        });
        viz.gauges.__internals.LinearScale = viz.gauges.__internals.BaseScale.inherit({
            _getGridSpacingFactor: function() {
                return {
                        majorTicks: 25,
                        minorTicks: 5
                    }
            },
            _getTranslateFunction: function() {
                var tr = this._translator;
                return function(value) {
                        return tr.translate(value)
                    }
            },
            _overlappingBehaviorType: "linear",
            _getScreenDelta: function() {
                return _abs(this._translator.getCodomainEnd() - this._translator.getCodomainStart())
            },
            _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) {
                var x = 0,
                    y = 0;
                if (this.vertical)
                    y = tick.position;
                else
                    x = tick.position;
                element.move(x, y)
            },
            _getAxisLabelPosition: 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 || 0);
                return position
            },
            _getLabelAlign: function(textIndent) {
                return this.vertical ? textIndent > 0 ? 'left' : 'right' : 'center'
            },
            _applyOverlappingOptions: function(options) {
                options.overlappingBehaviorType = "linear"
            },
            _getLabelOptions: function(textValue, textPosition, textIndent, tick) {
                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 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,
            _Palette = DX.viz.core.Palette;
        DX.viz.gauges.__internals.BaseRangeContainer = DX.viz.gauges.__internals.BaseElement.inherit({
            _init: function() {
                this._root = this._renderer.g().attr({'class': 'dxg-range-container'})
            },
            clean: function() {
                this._root.remove().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).attr({
                            fill: range.color,
                            'class': range.className
                        }).append(that._root)
                    });
                return that
            },
            _processOptions: null,
            _isVisible: null,
            _createRange: null,
            getColorForValue: function(value) {
                var color = null;
                _each(this._ranges, function(_, range) {
                    if (range.start <= value && value <= range.end || range.start >= value && value >= range.end) {
                        color = range.color;
                        return false
                    }
                });
                return color
            }
        });
        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.arc(layout.x, layout.y, layout.radius - that._inner * width, layout.radius + that._outer * width, that._translator.translate(range.end), that._translator.translate(range.start)).attr({"stroke-linejoin": "round"})
            },
            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() {
                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,
                    x = layout.x,
                    y = layout.y,
                    startWidth = range.startWidth,
                    endWidth = range.endWidth;
                if (that.vertical)
                    points = [x - startWidth * inner, startPosition, x - endWidth * inner, endPosition, x + endWidth * outer, endPosition, x + startWidth * outer, startPosition];
                else
                    points = [startPosition, y + startWidth * outer, startPosition, y - startWidth * inner, endPosition, y - endWidth * inner, endPosition, y + endWidth * outer];
                return that._renderer.path(points, "area")
            },
            measure: function(layout) {
                var result = {},
                    width;
                result.min = result.max = layout[this.vertical ? 'x' : 'y'];
                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 viz = DX.viz,
            core = viz.core,
            _isString = DX.utils.isString,
            _max = Math.max,
            _extend = $.extend;
        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.remove().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,
                    element,
                    bbox,
                    totalWidth = 0,
                    totalHeight = 0,
                    y = 0;
                if (!hasTitle && !hasSubtitle)
                    return that;
                that._root = that._renderer.g().attr({'class': 'dxg-title'}).append(that._container);
                if (hasTitle) {
                    element = that._renderer.text(titleOptions.text, 0, 0).attr({align: 'center'}).css(core.utils.patchFontOptions(titleOptions.font)).append(that._root);
                    bbox = element.getBBox();
                    y += -bbox.y;
                    element.attr({y: y});
                    y += bbox.height + bbox.y;
                    totalWidth = _max(totalWidth, bbox.width);
                    totalHeight += bbox.height
                }
                if (hasSubtitle) {
                    element = that._renderer.text(subtitleOptions.text, 0, 0).attr({align: 'center'}).css(core.utils.patchFontOptions(subtitleOptions.font)).append(that._root);
                    bbox = element.getBBox();
                    y += -bbox.y;
                    element.attr({y: y});
                    totalWidth = _max(totalWidth, bbox.width);
                    totalHeight += bbox.height
                }
                that._layout = _extend({
                    position: titleOptions.position,
                    width: totalWidth,
                    height: totalHeight
                }, titleOptions.layout);
                return that
            },
            getLayoutOptions: function() {
                return this._layout
            },
            locate: function(left, top) {
                this._root.attr({
                    translateX: left + this._layout.width / 2,
                    translateY: top
                });
                return this
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file layoutManager.js */
    (function(DX, $, undefined) {
        var _Number = Number,
            _String = String,
            _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(),
                    currentRect,
                    verticalOverlay;
                if (!options)
                    return this;
                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',
            _fontFields: ['scale.label.font', 'valueIndicators.rangebar.text.font', 'valueIndicators.textcloud.text.font', 'title.font', 'subtitle.font', 'tooltip.font', 'indicator.text.font', 'loadingIndicator.font'],
            _initializeTheme: function() {
                var that = this,
                    subTheme;
                if (that._subTheme) {
                    subTheme = _extend(true, {}, that._theme[that._subTheme], that._theme);
                    _extend(true, that._theme, subTheme)
                }
                that.callBase.apply(that, arguments)
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file baseGauge.js */
    (function(DX, $, undefined) {
        var _Number = Number,
            _isString = DX.utils.isString,
            _getAppropriateFormat = DX.utils.getAppropriateFormat,
            _extend = $.extend,
            _each = $.each;
        DX.viz.gauges.dxBaseGauge = DX.viz.core.BaseWidget.inherit({
            _rootClassPrefix: "dxg",
            _createThemeManager: function() {
                return this._factory.createThemeManager()
            },
            _initCore: function() {
                var that = this;
                that._root = that._renderer.root;
                that._translator = that._factory.createTranslator();
                that._initNotifiers();
                that._tracker = that._factory.createTracker({
                    renderer: that._renderer,
                    container: that._root
                });
                that._layoutManager = that._factory.createLayoutManager();
                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._setTrackerCallbacks()
            },
            _setTrackerCallbacks: function() {
                var that = this,
                    renderer = that._renderer,
                    tooltip = that._tooltip;
                that._tracker.setCallbacks({
                    'tooltip-show': function(target, info) {
                        var tooltipParameters = target.getTooltipParameters(),
                            offset = renderer.getRootOffset(),
                            formatObject = _extend({
                                value: tooltipParameters.value,
                                valueText: tooltip.formatValue(tooltipParameters.value),
                                color: tooltipParameters.color
                            }, info);
                        return tooltip.show(formatObject, {
                                x: tooltipParameters.x + offset.left,
                                y: tooltipParameters.y + offset.top,
                                offset: tooltipParameters.offset
                            }, {target: info})
                    },
                    'tooltip-hide': function() {
                        return tooltip.hide()
                    }
                });
                that._resetTrackerCallbacks = function() {
                    that._resetTrackerCallbacks = that = renderer = tooltip = null
                }
            },
            _initNotifiers: function() {
                var that = this,
                    counter = 0;
                that._notifiers = {
                    dirty: function() {
                        that._resetIsReady();
                        ++counter
                    },
                    ready: function() {
                        if (--counter === 0)
                            that._drawn()
                    }
                }
            },
            _disposeCore: function() {
                var that = this;
                that._themeManager.dispose();
                that._tracker.dispose();
                that._title.dispose();
                that._deltaIndicator && that._deltaIndicator.dispose();
                that._root = that._translator = that._notifiers = that._tracker = that._layoutManager = that._title = 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();
                that._setupDefaultFormat();
                that._renderCore()
            },
            _cleanCore: function() {
                var that = this;
                that._title.clean();
                that._deltaIndicator && that._deltaIndicator.clean();
                that._tracker.deactivate();
                that._cleanContent()
            },
            _renderCore: function() {
                var that = this;
                if (!that._isValidDomain)
                    return;
                var theme = that._themeManager.theme(),
                    titleTheme = _extend(true, {}, theme.title, processTitleOptions(that.option("title"))),
                    subTitleTheme = _extend(true, {}, theme.subtitle, processTitleOptions(that.option("subtitle")));
                that._title.render(titleTheme, subTitleTheme);
                that._deltaIndicator && that._deltaIndicator.render(_extend(true, {}, 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._tracker.setTooltipState(that._tooltip.isEnabled());
                that._tracker.activate();
                that._noAnimation = null;
                that.option("debugMode") === true && that._renderDebugInfo();
                that._debug_rendered && that._debug_rendered()
            },
            _setTooltipOptions: function() {
                var that = this;
                that.callBase();
                that._tracker && that._tracker.setTooltipState(that._tooltip.isEnabled())
            },
            _renderDebugInfo: function() {
                var that = this,
                    group = that._debugGroup || that._renderer.g().attr({"class": "debug-info"}).append(that._renderer.root),
                    rect;
                group.clear();
                rect = that._rootRect;
                that._renderer.rect(rect.left, rect.top, rect.width(), rect.height()).attr({
                    stroke: "#000000",
                    "stroke-width": 1,
                    fill: "none"
                }).append(group);
                rect = that._mainRect;
                that._renderer.rect(rect.left, rect.top, rect.width(), rect.height()).attr({
                    stroke: "#0000FF",
                    "stroke-width": 1,
                    fill: "none"
                }).append(group);
                rect = that._layoutManager.getRect();
                rect && that._renderer.rect(rect.left, rect.top, rect.width(), rect.height()).attr({
                    stroke: "#FF0000",
                    "stroke-width": 1,
                    fill: "none"
                }).append(group);
                rect = that._title.getLayoutOptions() ? that._title._root.getBBox() : null;
                rect && that._renderer.rect(rect.x, rect.y, rect.width, rect.height).attr({
                    stroke: "#00FF00",
                    "stroke-width": 1,
                    fill: "none"
                }).append(group);
                rect = that._deltaIndicator && that._deltaIndicator.getLayoutOptions() ? that._deltaIndicator._root.getBBox() : null;
                rect && that._renderer.rect(rect.x, rect.y, rect.width, rect.height).attr({
                    stroke: "#00FF00",
                    "stroke-width": 1,
                    fill: "none"
                }).append(group)
            },
            _applySize: function() {
                var canvas = this._canvas;
                this._rootRect = new DX.viz.core.Rectangle({
                    left: canvas.left,
                    top: canvas.top,
                    right: canvas.width - canvas.right,
                    bottom: canvas.height - canvas.bottom
                });
                this._width = canvas.width;
                this._height = canvas.height
            },
            _resize: function() {
                var that = this;
                that._resizing = that._noAnimation = true;
                that._cleanCore();
                that._renderCore();
                that._resizing = null
            },
            _optionChanged: function(args) {
                var that = this;
                switch (args.name) {
                    case"startValue":
                    case"endValue":
                        that._setupDomain();
                        that._invalidate();
                        break;
                    default:
                        that.callBase(args);
                        break
                }
            },
            _setupDomain: function() {
                var that = this;
                that._setupDomainCore();
                that._isValidDomain = isFinite(1 / (that._translator.getDomain()[1] - that._translator.getDomain()[0]));
                if (!that._isValidDomain)
                    that._incidentOccured("W2301")
            },
            _setupAnimationSettings: function() {
                var that = this,
                    option = that.option("animation");
                that._animationSettings = null;
                if (option === undefined || option) {
                    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())
            },
            _setupDomainCore: null,
            _calculateSize: null,
            _cleanContent: null,
            _renderContent: null,
            _setupCodomain: null,
            _getApproximateScreenRange: null,
            _factory: {
                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
                }
            }
        });
        function processTitleOptions(options) {
            return _isString(options) ? {text: options} : options || {}
        }
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file gauge.js */
    (function(DX, $, undefined) {
        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,
            _factory = DX.viz.gauges.__factory,
            OPTION_VALUE = 'value',
            OPTION_SUBVALUES = 'subvalues';
        function processValue(value, fallbackValue) {
            return _isFinite(value) ? _Number(value) : fallbackValue
        }
        function parseArrayOfNumbers(arg) {
            return _isArray(arg) ? arg : _isNumber(arg) ? [arg] : null
        }
        DX.viz.gauges.dxGauge = DX.viz.gauges.dxBaseGauge.inherit({
            _initCore: function() {
                var that = this;
                that._setupValue(that.option(OPTION_VALUE));
                that.__subvalues = parseArrayOfNumbers(that.option(OPTION_SUBVALUES));
                that._setupSubvalues(that.__subvalues);
                selectMode(that);
                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
                })
            },
            _disposeCore: 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
            },
            _setupDomainCore: 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)
            },
            _cleanContent: function() {
                var that = this;
                that._rangeContainer.clean();
                that._scale.clean();
                that._cleanValueIndicators()
            },
            _renderContent: function() {
                var that = this,
                    elements;
                that._rangeContainer.render(_extend(that._getOption("rangeContainer"), {
                    themeName: that._themeManager.themeName(),
                    vertical: that._area.vertical
                }));
                that._scale.render(_extend(that._getOption("scale"), {
                    rangeContainer: that._rangeContainer.enabled ? that._rangeContainer : null,
                    approximateScreenDelta: that._getApproximateScreenRange(),
                    offset: 0,
                    vertical: that._area.vertical
                }));
                elements = _map([that._scale, that._rangeContainer].concat(that._prepareValueIndicators()), function(element) {
                    return element && element.enabled ? element : null
                });
                that._applyMainLayout(elements);
                _each(elements, function(_, element) {
                    element.resize(that._getElementLayout(element.getOffset()))
                });
                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
                }
            },
            _prepareIndicatorSettings: function(options, defaultTypeField) {
                var that = this,
                    theme = that._themeManager.theme("valueIndicators"),
                    type = _String(options.type || that._themeManager.theme(defaultTypeField)).toLowerCase(),
                    settings = _extend(true, {}, theme._default, theme[type], options);
                settings.type = type;
                settings.animation = that._animationSettings;
                settings.containerBackgroundColor = that._containerBackgroundColor;
                that._updateIndicatorSettings(settings);
                return settings
            },
            _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,
                    target = that._valueIndicator,
                    settings = that._prepareIndicatorSettings(that.option("valueIndicator") || {}, 'valueIndicatorType');
                if (target && target.type !== settings.type) {
                    target.dispose();
                    target = null
                }
                if (!target)
                    target = that._valueIndicator = that._createIndicator(settings.type, that._root, 'dxg-value-indicator', 'value-indicator');
                target.render(settings)
            },
            _createSubvalueIndicatorsSet: function() {
                var that = this,
                    owner = that._renderer.g().attr({'class': 'dxg-subvalue-indicators'});
                return new ValueIndicatorsSet({
                        root: owner,
                        container: that._root,
                        createIndicator: function(type, i) {
                            return that._createIndicator(type, owner, 'dxg-subvalue-indicator', 'subvalue-indicator', i)
                        }
                    })
            },
            _prepareSubvalueIndicators: function() {
                var that = this,
                    target = that._subvalueIndicatorsSet,
                    settings = that._prepareIndicatorSettings(that.option("subvalueIndicator") || {}, 'subvalueIndicatorType'),
                    isRecreate;
                if (!target)
                    target = that._subvalueIndicatorsSet = that._createSubvalueIndicatorsSet();
                isRecreate = settings.type !== target.type;
                target.type = settings.type;
                if (that._createIndicator(settings.type))
                    target.render(settings, isRecreate)
            },
            _setupValue: function(value) {
                this.__value = processValue(value, this.__value)
            },
            _setupSubvalues: function(subvalues) {
                var vals = subvalues === undefined ? this.__subvalues : parseArrayOfNumbers(subvalues),
                    i,
                    ii,
                    list;
                if (vals === null)
                    return;
                for (i = 0, ii = vals.length, list = []; i < ii; ++i)
                    list.push(processValue(vals[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
            },
            _valueChangedHandler: function(name, val) {
                var that = this;
                switch (name) {
                    case OPTION_VALUE:
                        that._setupValue(val);
                        that._updateValueIndicator();
                        that.option(OPTION_VALUE, that.__value);
                        return true;
                    case OPTION_SUBVALUES:
                        if (that.__subvalues !== null) {
                            that._setupSubvalues(val);
                            that._updateSubvalueIndicators();
                            that.option(OPTION_SUBVALUES, that.__subvalues);
                            return true
                        }
                        return false;
                    default:
                        return false
                }
            },
            _optionChanged: function(args) {
                var that = this;
                if (that._valueChangedHandler(args.name, args.value, args.previousValue))
                    return;
                if (args.name === "scale") {
                    that._setupDomain();
                    that._invalidate()
                }
                else
                    that.callBase.apply(that, arguments)
            },
            _optionValuesEqual: function(name, oldValue, newValue) {
                var result;
                switch (name) {
                    case OPTION_VALUE:
                        result = oldValue === newValue;
                        break;
                    case OPTION_SUBVALUES:
                        result = compareArrays(oldValue, newValue);
                        break;
                    default:
                        result = this.callBase.apply(this, arguments);
                        break
                }
                return result
            },
            _applyMainLayout: null,
            _getElementLayout: null,
            _createScale: function(parameters) {
                return _factory[this._factoryMethods.scale](parameters)
            },
            _createRangeContainer: function(parameters) {
                return _factory[this._factoryMethods.rangeContainer](parameters)
            },
            _createIndicator: function(type, owner, className, trackerType, trackerIndex, _strict) {
                var that = this,
                    indicator = _factory[that._factoryMethods.indicator]({
                        renderer: that._renderer,
                        translator: that._translator,
                        notifiers: that._notifiers,
                        owner: owner,
                        tracker: that._tracker,
                        className: className
                    }, type, _strict);
                if (indicator) {
                    indicator.type = type;
                    indicator._trackerInfo = {
                        type: trackerType,
                        index: trackerIndex
                    }
                }
                return indicator
            },
            _getApproximateScreenRange: null
        });
        DX.viz.gauges.dxGauge.prototype._factory = DX.utils.clone(DX.viz.gauges.dxBaseGauge.prototype._factory);
        DX.viz.gauges.dxGauge.prototype._factory.createThemeManager = function() {
            return new DX.viz.gauges.__internals.ThemeManager
        };
        function valueGetter(arg) {
            return arg ? arg.value : NaN
        }
        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(processValue(newValues[i], currentValues[i]));
            that[fieldName] = list
        }
        function selectMode(gauge) {
            if (gauge.option(OPTION_VALUE) === undefined && gauge.option(OPTION_SUBVALUES) === undefined)
                if (gauge.option('valueIndicators') !== undefined) {
                    disableDefaultMode(gauge);
                    selectHardMode(gauge)
                }
        }
        function disableDefaultMode(that) {
            that.value = that.subvalues = _noop;
            that._setupValue = that._setupSubvalues = that._updateValueIndicator = that._updateSubvalueIndicators = null
        }
        function selectHardMode(that) {
            that._indicatorValues = [];
            setupValues(that, '_indicatorValues', that.option('valueIndicators'));
            that._valueIndicators = [];
            that._valueChangedHandler = valueChangedHandler_hardMode;
            that._updateActiveElements = updateActiveElements_hardMode;
            that._prepareValueIndicators = prepareValueIndicators_hardMode;
            that._disposeValueIndicators = disposeValueIndicators_hardMode;
            that._cleanValueIndicators = cleanValueIndicators_hardMode;
            that.indicatorValue = indicatorValue_hardMode
        }
        function valueChangedHandler_hardMode(name, val) {
            if (name === 'valueIndicators') {
                setupValues(this, '_indicatorValues', val);
                this._invalidate();
                return true
            }
            return false
        }
        function updateActiveElements_hardMode() {
            var that = this;
            _each(that._valueIndicators, function(_, valueIndicator) {
                valueIndicator.value(that._indicatorValues[valueIndicator.index], that._noAnimation)
            });
            that._resizing || that.hideLoadingIndicator()
        }
        function prepareValueIndicators_hardMode() {
            var that = this,
                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 newValueIndicators = [];
            _each(optionList, function(i, userSettings) {
                var valueIndicator = valueIndicators[i];
                if (!userSettings) {
                    valueIndicator && valueIndicator.dispose();
                    return
                }
                var settings = that._prepareIndicatorSettings(userSettings, "valueIndicatorType");
                if (valueIndicator && valueIndicator.type !== settings.type) {
                    valueIndicator.dispose();
                    valueIndicator = null
                }
                if (!valueIndicator)
                    valueIndicator = that._createIndicator(settings.type, that._root, 'dxg-value-indicator', 'value-indicator', i, true);
                if (valueIndicator) {
                    valueIndicator.index = i;
                    valueIndicator.render(settings);
                    newValueIndicators.push(valueIndicator)
                }
            });
            that._valueIndicators = newValueIndicators;
            return that._valueIndicators
        }
        function disposeValueIndicators_hardMode() {
            _each(this._valueIndicators, function(_, valueIndicator) {
                valueIndicator.dispose()
            });
            this._valueIndicators = null
        }
        function cleanValueIndicators_hardMode() {
            _each(this._valueIndicators, function(_, valueIndicator) {
                valueIndicator.clean()
            })
        }
        function indicatorValue_hardMode(index, value) {
            return accessPointerValue(this, this._valueIndicators, this._indicatorValues, index, value)
        }
        function accessPointerValue(that, pointers, values, index, value) {
            if (value !== undefined) {
                if (values[index] !== undefined) {
                    values[index] = 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) {
            var i,
                ii;
            if (array1 === array2)
                return true;
            if (_isArray(array1) && _isArray(array2) && array1.length === array2.length) {
                for (i = 0, ii = array1.length; i < ii; ++i)
                    if (_abs(array1[i] - array2[i]) > 1E-8)
                        return false;
                return true
            }
            return false
        }
        function ValueIndicatorsSet(parameters) {
            this._parameters = parameters;
            this._indicators = []
        }
        ValueIndicatorsSet.prototype = {
            costructor: ValueIndicatorsSet,
            dispose: function() {
                var that = this;
                _each(that._indicators, function(_, indicator) {
                    indicator.dispose()
                });
                that._parameters = that._options = that._indicators = that._colorPalette = that._palette = null;
                return that
            },
            clean: function() {
                var that = this;
                that._parameters.root.remove();
                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._parameters.createIndicator(that.type);
                that._sample.render(options);
                that.enabled = that._sample.enabled;
                that._palette = _isDefined(options.palette) ? new DX.viz.core.Palette(options.palette) : null;
                if (that.enabled) {
                    that._parameters.root.append(that._parameters.container);
                    that._generatePalette(that._indicators.length);
                    that._indicators = _map(that._indicators, function(indicator, i) {
                        if (isRecreate) {
                            indicator.dispose();
                            indicator = that._parameters.createIndicator(that.type, i)
                        }
                        indicator.render(that._getIndicatorOptions(i));
                        return indicator
                    })
                }
                return that
            },
            getOffset: function() {
                return _Number(this._options.offset) || 0
            },
            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,
                    indicator,
                    indicatorsLen = indicators.length;
                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._parameters.createIndicator(that.type, 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 _isFinite = isFinite,
            _Number = Number,
            _normalizeAngle = DX.utils.normalizeAngle,
            _getCosAndSin = DX.utils.getCosAndSin,
            _abs = Math.abs,
            _max = Math.max,
            _min = Math.min,
            _round = Math.round,
            _each = $.each,
            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.registerComponent("dxCircularGauge", DX.viz.gauges, DX.viz.gauges.dxGauge.inherit({
            _rootClass: "dxg-circular-gauge",
            _factoryMethods: {
                scale: 'createCircularScale',
                rangeContainer: 'createCircularRangeContainer',
                indicator: 'createCircularIndicator'
            },
            _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,
                    radius = that._area.radius,
                    maxRadius = 0,
                    minRadius = Infinity,
                    maxHorizontalOffset = 0,
                    maxVerticalOffset = 0,
                    maxInverseHorizontalOffset = 0,
                    maxInverseVerticalOffset = 0;
                _each(elements, function(_, element) {
                    var bounds = element.measure({radius: radius - element.getOffset()});
                    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,
                    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)
            },
            _getElementLayout: function(offset) {
                return {
                        x: this._area.x,
                        y: this._area.y,
                        radius: _round(this._area.radius - offset)
                    }
            },
            _getApproximateScreenRange: function() {
                var that = this,
                    area = that._area,
                    r = _min(that._canvas.width / (area.sides.right - area.sides.left), that._canvas.height / (area.sides.down - area.sides.up));
                r > area.totalRadius && (r = area.totalRadius);
                r = 0.8 * r;
                return -that._translator.getCodomainRange() * r * PI / 180
            },
            _getDefaultSize: function() {
                return {
                        width: 300,
                        height: 300
                    }
            }
        }));
        DX.viz.gauges.dxCircularGauge.prototype._factory = DX.utils.clone(DX.viz.gauges.dxBaseGauge.prototype._factory);
        DX.viz.gauges.dxCircularGauge.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 _String = String,
            _Number = Number,
            _max = Math.max,
            _min = Math.min,
            _round = Math.round,
            _each = $.each;
        DX.registerComponent("dxLinearGauge", DX.viz.gauges, DX.viz.gauges.dxGauge.inherit({
            _rootClass: 'dxg-linear-gauge',
            _factoryMethods: {
                scale: 'createLinearScale',
                rangeContainer: 'createLinearRangeContainer',
                indicator: 'createLinearIndicator'
            },
            _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,
                    x = that._area.x,
                    y = that._area.y,
                    minBound = 1000,
                    maxBound = 0,
                    indent = 0;
                _each(elements, function(_, element) {
                    var bounds = element.measure({
                            x: x + element.getOffset(),
                            y: y + element.getOffset()
                        });
                    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)
            },
            _getElementLayout: function(offset) {
                return {
                        x: _round(this._area.x + offset),
                        y: _round(this._area.y + offset)
                    }
            },
            _getApproximateScreenRange: function() {
                var that = this,
                    area = that._area,
                    s = area.vertical ? that._canvas.height : that._canvas.width;
                s > area.totalSize && (s = area.totalSize);
                s = s * 0.8;
                return s
            },
            _getDefaultSize: function() {
                var geometry = this.option('geometry') || {};
                if (geometry.orientation === 'vertical')
                    return {
                            width: 100,
                            height: 300
                        };
                else
                    return {
                            width: 300,
                            height: 100
                        }
            }
        }));
        DX.viz.gauges.dxLinearGauge.prototype._factory = DX.utils.clone(DX.viz.gauges.dxBaseGauge.prototype._factory);
        DX.viz.gauges.dxLinearGauge.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_DIV_180 = Math.PI / 180,
            _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,
            _patchFontOptions = DX.viz.core.utils.patchFontOptions,
            _Number = Number,
            _isFinite = isFinite,
            _noop = $.noop,
            _extend = $.extend,
            _getSampleText = DX.viz.gauges.__internals.getSampleText,
            _formatValue = DX.viz.gauges.__internals.formatValue,
            _Palette = DX.viz.core.Palette,
            OPTION_VALUES = "values";
        var dxBarGauge = DX.viz.gauges.dxBaseGauge.inherit({
                _rootClass: "dxbg-bar-gauge",
                _initCore: function() {
                    var that = this;
                    that.callBase.apply(that, arguments);
                    that._barsGroup = that._renderer.g().attr({"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,
                            ii;
                        for (i = 0, ii = bars.length; i < ii; ++i)
                            bars[i].animate(pos)
                    };
                    that._animateComplete = function() {
                        var bars = that._bars,
                            i,
                            ii;
                        for (i = 0, ii = bars.length; i < ii; ++i)
                            bars[i].endAnimation();
                        that._notifiers.ready()
                    }
                },
                _disposeCore: function() {
                    var that = this;
                    that._barsGroup = that._values = that._context = that._animateStep = that._animateComplete = null;
                    that.callBase.apply(that, arguments)
                },
                _setupDomainCore: 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)
                },
                _getDefaultSize: function() {
                    return {
                            width: 300,
                            height: 300
                        }
                },
                _setupCodomain: DX.viz.gauges.dxCircularGauge.prototype._setupCodomain,
                _getApproximateScreenRange: function() {
                    var that = this,
                        sides = that._area.sides,
                        width = that._canvas.width / (sides.right - sides.left),
                        height = that._canvas.height / (sides.down - sides.up),
                        r = width < height ? width : height;
                    return -that._translator.getCodomainRange() * r * PI_DIV_180
                },
                _setupAnimationSettings: function() {
                    var that = this;
                    that.callBase.apply(that, arguments);
                    if (that._animationSettings) {
                        that._animationSettings.step = that._animateStep;
                        that._animationSettings.complete = that._animateComplete
                    }
                },
                _cleanContent: function() {
                    var that = this,
                        i,
                        ii;
                    that._barsGroup.remove();
                    that._animationSettings && that._barsGroup.stopAnimation();
                    for (i = 0, ii = that._bars ? that._bars.length : 0; i < ii; ++i)
                        that._bars[i].dispose();
                    that._palette = that._bars = null
                },
                _renderContent: function() {
                    var that = this,
                        labelOptions = that.option("label"),
                        text,
                        bbox,
                        context = that._context;
                    that._barsGroup.append(that._root);
                    context.textEnabled = labelOptions === undefined || labelOptions && (!("visible" in labelOptions) || labelOptions.visible);
                    if (context.textEnabled) {
                        context.textColor = labelOptions && labelOptions.font && labelOptions.font.color || null;
                        labelOptions = _extend(true, {}, that._themeManager.theme().label, labelOptions);
                        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
                        };
                        context.textOptions = {align: "center"};
                        context.fontStyles = _patchFontOptions(_extend({}, that._themeManager.theme().label.font, labelOptions.font, {color: null}));
                        that._textIndent = labelOptions.indent > 0 ? _Number(labelOptions.indent) : 0;
                        context.lineWidth = labelOptions.connectorWidth > 0 ? _Number(labelOptions.connectorWidth) : 0;
                        context.lineColor = labelOptions.connectorColor || null;
                        text = that._renderer.text(_getSampleText(that._translator, context.formatOptions), 0, 0).attr(context.textOptions).css(context.fontStyles).append(that._barsGroup);
                        bbox = text.getBBox();
                        text.remove();
                        context.textVerticalOffset = -bbox.y - bbox.height / 2;
                        context.textWidth = bbox.width;
                        context.textHeight = bbox.height
                    }
                    DX.viz.gauges.dxCircularGauge.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()),
                        relativeInnerRadius,
                        radius,
                        area = that._area;
                    that._palette = new _Palette(options.palette, {
                        stepHighlight: 50,
                        theme: that._themeManager.themeName()
                    });
                    relativeInnerRadius = options.relativeInnerRadius > 0 && options.relativeInnerRadius < 1 ? _Number(options.relativeInnerRadius) : 0.1;
                    radius = area.radius;
                    if (that._context.textEnabled) {
                        that._textIndent = _round(_min(that._textIndent, radius / 2));
                        radius -= that._textIndent
                    }
                    that._outerRadius = _floor(radius);
                    that._innerRadius = _floor(radius * relativeInnerRadius);
                    that._barSpacing = options.barSpacing > 0 ? _Number(options.barSpacing) : 0;
                    _extend(that._context, {
                        backgroundColor: options.backgroundColor,
                        x: area.x,
                        y: area.y,
                        startAngle: area.startCoord,
                        endAngle: area.endCoord,
                        baseAngle: that._translator.translate(that._baseValue)
                    });
                    that._bars = [];
                    that._updateValues(that.option(OPTION_VALUES))
                },
                _arrangeBars: function(count) {
                    var that = this,
                        radius = that._outerRadius - that._innerRadius,
                        context = that._context,
                        spacing,
                        _count,
                        unitOffset,
                        i;
                    context.barSize = count > 0 ? _max((radius - (count - 1) * that._barSpacing) / count, 1) : 0;
                    spacing = count > 1 ? _max(_min((radius - count * context.barSize) / (count - 1), that._barSpacing), 0) : 0;
                    _count = _min(_floor((radius + spacing) / context.barSize), count);
                    that._setBarsCount(_count);
                    radius = that._outerRadius;
                    context.textRadius = radius + that._textIndent;
                    that._palette.reset();
                    unitOffset = context.barSize + spacing;
                    for (i = 0; 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.dispose();
                            that._dummyBackground = null
                        }
                    }
                    else {
                        if (!that._dummyBackground)
                            that._dummyBackground = that._renderer.arc().attr({"stroke-linejoin": "round"}).append(that._barsGroup);
                        that._dummyBackground.attr({
                            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(values) {
                    var that = this,
                        i,
                        ii;
                    for (i = 0, ii = that._bars.length; i < ii; ++i)
                        that._bars[i].setValue(values[i])
                },
                _animateBars: function(values) {
                    var that = this,
                        i,
                        ii = that._bars.length;
                    if (ii > 0) {
                        for (i = 0; i < ii; ++i)
                            that._bars[i].beginAnimation(values[i]);
                        that._barsGroup.animate({_: 0}, that._animationSettings)
                    }
                },
                _updateValues: function(values) {
                    var that = this,
                        list = _isArray(values) && values || _isFinite(values) && [values] || [],
                        i,
                        ii = list.length,
                        value,
                        barValues = [],
                        immediateReady = true;
                    that._values.length = ii;
                    for (i = 0; i < ii; ++i) {
                        value = list[i];
                        that._values[i] = value = _Number(_isFinite(value) ? value : that._values[i]);
                        if (_isFinite(value))
                            barValues.push(value)
                    }
                    that._notifiers.dirty();
                    that._animationSettings && that._barsGroup.stopAnimation();
                    if (that._bars) {
                        that._arrangeBars(barValues.length);
                        if (that._animationSettings && !that._noAnimation) {
                            immediateReady = false;
                            that._animateBars(barValues)
                        }
                        else
                            that._updateBars(barValues)
                    }
                    immediateReady && that._notifiers.ready();
                    if (!that._resizing) {
                        that.option(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(args) {
                    if (args.name === OPTION_VALUES)
                        this._updateValues(args.value);
                    else
                        this.callBase.apply(this, arguments)
                },
                _optionValuesEqual: function(name, oldValue, newValue) {
                    if (name === OPTION_VALUES)
                        return compareArrays(oldValue, newValue);
                    else
                        return this.callBase.apply(this, arguments)
                }
            });
        DX.registerComponent("dxBarGauge", DX.viz.gauges, dxBarGauge);
        var ThemeManager = DX.viz.gauges.__internals.ThemeManager.inherit({
                _themeSection: "barGauge",
                _fontFields: ["label.font", "title.font", "tooltip.font", "loadingIndicator.font"]
            });
        dxBarGauge.prototype._factory = DX.utils.clone(DX.viz.gauges.dxBaseGauge.prototype._factory);
        dxBarGauge.prototype._factory.createThemeManager = function() {
            return new ThemeManager
        };
        var BarWrapper = function(index, context) {
                var that = this;
                that._context = context;
                that._background = context.renderer.arc().attr({
                    "stroke-linejoin": "round",
                    fill: context.backgroundColor
                }).append(context.group);
                that._bar = context.renderer.arc().attr({"stroke-linejoin": "round"}).append(context.group);
                if (context.textEnabled) {
                    that._line = context.renderer.path([], "line").attr({"stroke-width": context.lineWidth}).append(context.group);
                    that._text = context.renderer.text("", 0, 0).css(context.fontStyles).attr(context.textOptions).append(context.group)
                }
                that._tracker = context.renderer.arc().attr({"stroke-linejoin": "round"});
                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.dispose();
                that._bar.dispose();
                if (that._context.textEnabled) {
                    that._line.dispose();
                    that._text.dispose()
                }
                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,
                    context = that._context;
                that._settings.outerRadius = options.radius;
                that._settings.innerRadius = options.radius - context.barSize;
                that._background.attr(_extend({}, that._settings, {
                    startAngle: context.endAngle,
                    endAngle: context.startAngle
                }));
                that._bar.attr(that._settings);
                that._tracker.attr(that._settings);
                that._color = options.color;
                that._bar.attr({fill: options.color});
                if (context.textEnabled) {
                    that._line.attr({
                        points: [context.x, context.y - that._settings.innerRadius, context.x, context.y - context.textRadius],
                        stroke: context.lineColor || options.color
                    }).sharp();
                    that._text.css({fill: 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,
                    cossin;
                that._angle = angle;
                setAngles(that._settings, that._context.baseAngle, that._angle);
                that._bar.attr(that._settings);
                that._tracker.attr(that._settings);
                if (that._context.textEnabled) {
                    that._line.rotate(_convertAngleToRendererSpace(that._angle), that._context.x, that._context.y);
                    cossin = _getCosAndSin(that._angle);
                    that._text.attr({
                        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
            },
            _processValue: function(value) {
                this._value = this._context.translator.adjust(value);
                return this._context.translator.translate(this._value)
            },
            setValue: function(value) {
                return this.setAngle(this._processValue(value))
            },
            beginAnimation: function(value) {
                var that = this,
                    angle = this._processValue(value);
                if (!compareFloats(that._angle, angle)) {
                    that._start = that._angle;
                    that._delta = angle - that._angle;
                    that._tracker.attr({visibility: "hidden"});
                    if (that._context.textEnabled) {
                        that._line.attr({visibility: "hidden"});
                        that._text.attr({visibility: "hidden"})
                    }
                }
                else {
                    that.animate = _noop;
                    that.setAngle(that._angle)
                }
            },
            animate: function(pos) {
                var that = this;
                that._angle = that._start + that._delta * pos;
                setAngles(that._settings, that._context.baseAngle, that._angle);
                that._bar.attr(that._settings)
            },
            endAnimation: function() {
                var that = this;
                if (that._delta !== undefined) {
                    if (compareFloats(that._angle, that._start + that._delta)) {
                        that._tracker.attr({visibility: null});
                        if (that._context.textEnabled) {
                            that._line.attr({visibility: null});
                            that._text.attr({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
        }
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file tracker.js */
    (function(DX, $, undefined) {
        var _abs = Math.abs,
            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.g().attr({
                    'class': 'dxg-tracker',
                    stroke: 'none',
                    "stroke-width": 0,
                    fill: '#000000',
                    opacity: 0.0001
                });
                that._showTooltipCallback = function() {
                    that._showTooltipTimeout = null;
                    var target = that._tooltipEvent.target,
                        data = $(target).data();
                    that._targetEvent = null;
                    if (that._tooltipTarget !== target && that._callbacks['tooltip-show'](data.target, data.info))
                        that._tooltipTarget = target
                };
                that._hideTooltipCallback = function() {
                    that._hideTooltipTimeout = null;
                    that._targetEvent = null;
                    if (that._tooltipTarget) {
                        that._callbacks['tooltip-hide']();
                        that._tooltipTarget = null
                    }
                };
                that._dispose = function() {
                    clearTimeout(that._showTooltipTimeout);
                    clearTimeout(that._hideTooltipTimeout);
                    that._showTooltipCallback = that._hideTooltipCallback = that._dispose = null
                };
                that._DEBUG_showTooltipTimeoutSet = that._DEBUG_showTooltipTimeoutCleared = that._DEBUG_hideTooltipTimeoutSet = that._DEBUG_hideTooltipTimeoutCleared = 0;
                that.TOOLTIP_SHOW_DELAY = TOOLTIP_SHOW_DELAY;
                that.TOOLTIP_HIDE_DELAY = TOOLTIP_HIDE_DELAY;
                that.TOOLTIP_TOUCH_SHOW_DELAY = TOOLTIP_TOUCH_SHOW_DELAY;
                that.TOOLTIP_TOUCH_HIDE_DELAY = TOOLTIP_TOUCH_HIDE_DELAY
            },
            dispose: function() {
                var that = this;
                that._dispose();
                that.deactivate();
                that._element.remove();
                that._container = that._element = that._context = that._callbacks = null;
                return that
            },
            activate: function() {
                this._element.append(this._container);
                return this
            },
            deactivate: function() {
                this._element.remove().clear();
                return this
            },
            attach: function(element, target, info) {
                element.data({
                    target: target,
                    info: info
                }).append(this._element);
                return this
            },
            detach: function(element) {
                element.remove();
                return this
            },
            setTooltipState: function(state) {
                var that = this,
                    data;
                that._element.off(tooltipMouseEvents).off(tooltipTouchEvents).off(tooltipMouseWheelEvents);
                if (state) {
                    data = {tracker: that};
                    that._element.on(tooltipMouseEvents, data).on(tooltipTouchEvents, data).on(tooltipMouseWheelEvents, data)
                }
                return that
            },
            setCallbacks: function(callbacks) {
                this._callbacks = callbacks;
                return this
            },
            _showTooltip: function(event, delay) {
                var that = this;
                that._hideTooltipTimeout && ++that._DEBUG_hideTooltipTimeoutCleared;
                clearTimeout(that._hideTooltipTimeout);
                that._hideTooltipTimeout = null;
                if (that._tooltipTarget === event.target)
                    return;
                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);
                if (delay) {
                    ++that._DEBUG_hideTooltipTimeoutSet;
                    that._hideTooltipTimeout = setTimeout(that._hideTooltipCallback, delay)
                }
                else
                    that._hideTooltipCallback()
            }
        });
        var tooltipMouseEvents = {
                'mouseover.gauge-tooltip': handleTooltipMouseOver,
                'mouseout.gauge-tooltip': handleTooltipMouseOut
            };
        var tooltipMouseMoveEvents = {'mousemove.gauge-tooltip': handleTooltipMouseMove};
        var tooltipMouseWheelEvents = {'dxmousewheel.gauge-tooltip': handleTooltipMouseWheel};
        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)
        }
        function handleTooltipMouseWheel(event) {
            event.data.tracker._hideTooltip()
        }
        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() {
            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() {
            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);
    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 = {}
    })(DevExpress);
    /*! Module viz-rangeselector, file utils.js */
    (function($, DX, undefined) {
        var dxUtils = DX.utils;
        var findLessOrEqualValueIndex = function(values, value) {
                if (!values || values.length === 0)
                    return -1;
                var minIndex = 0,
                    maxIndex = values.length - 1;
                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 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 truncateSelectedRange = function(value, scaleOptions) {
                var isDiscrete = scaleOptions.type === 'discrete',
                    categories = isDiscrete ? scaleOptions._categoriesInfo.categories : undefined,
                    startValue = scaleOptions.startValue,
                    endValue = scaleOptions.endValue,
                    min,
                    max,
                    valueIndex;
                if (isDiscrete) {
                    valueIndex = $.inArray(value, categories);
                    return valueIndex < 0 ? startValue : value
                }
                else
                    min = startValue > endValue ? endValue : startValue,
                    max = startValue > endValue ? startValue : endValue;
                if (value < min)
                    value = min;
                if (value > max)
                    value = max;
                return value
            };
        DX.viz.rangeSelector.utils = {
            findLessOrEqualValue: findLessOrEqualValue,
            findNearValue: findNearValue,
            findGreaterOrEqualValue: findGreaterOrEqualValue,
            getEventPageX: getEventPageX,
            truncateSelectedRange: truncateSelectedRange,
            trackerSettings: {
                fill: 'grey',
                stroke: 'grey',
                opacity: 0.0001
            },
            animationSettings: {duration: 250}
        }
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file baseVisualElementMethods.js */
    (function(DX) {
        DX.viz.rangeSelector.baseVisualElementMethods = {
            init: function(renderer) {
                this._renderer = renderer;
                this._isDrawn = false
            },
            applyOptions: function(options) {
                this._options = options || {};
                this._applyOptions(this._options)
            },
            _applyOptions: function(){},
            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(){},
            _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,
            core = DX.viz.core,
            patchFontOptions = core.utils.patchFontOptions,
            ParseUtils = core.ParseUtils,
            formatHelper = DX.formatHelper,
            SCALE_TEXT_SPACING = 5,
            HEIGHT_COMPACT_MODE = 24,
            POINTER_SIZE = 4,
            EMPTY_SLIDER_MARKER_TEXT = '. . .',
            _isDefined = utils.isDefined,
            _isNumber = utils.isNumber,
            _isDate = utils.isDate,
            _max = Math.max,
            _ceil = Math.ceil,
            START_VALUE = 'startValue',
            END_VALUE = 'endValue',
            DATETIME = 'datetime',
            SELECTED_RANGE = 'selectedRange',
            DISCRETE = 'discrete',
            STRING = 'string',
            SELECTED_RANGE_CHANGED = SELECTED_RANGE + 'Changed',
            CONTAINER_BACKGROUND_COLOR = "containerBackgroundColor",
            SLIDER_MARKER = "sliderMarker",
            BACKGROUND = "background",
            LOGARITHMIC = "logarithmic",
            INVISIBLE_POS = -1000,
            logarithmBase = 10;
        rangeSelector.consts = {
            emptySliderMarkerText: EMPTY_SLIDER_MARKER_TEXT,
            pointerSize: POINTER_SIZE
        };
        rangeSelector.HEIGHT_COMPACT_MODE = HEIGHT_COMPACT_MODE;
        rangeSelector.__getTextBBox = getTextBBox;
        function cloneSelectedRange(arg) {
            return {
                    startValue: arg.startValue,
                    endValue: arg.endValue
                }
        }
        var formatValue = 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)
            };
        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 calculateMarkerHeight = function(renderer, value, sliderMarkerOptions) {
                var formattedText = value === undefined ? EMPTY_SLIDER_MARKER_TEXT : formatValue(value, sliderMarkerOptions),
                    textBBox = getTextBBox(renderer, formattedText, sliderMarkerOptions.font);
                return _ceil(textBBox.height) + 2 * sliderMarkerOptions.paddingTopBottom + POINTER_SIZE
            };
        var calculateScaleLabelHalfWidth = function(renderer, value, scaleOptions) {
                var formattedText = formatValue(value, scaleOptions.label),
                    textBBox = getTextBBox(renderer, formattedText, scaleOptions.label.font);
                return _ceil(textBBox.width / 2)
            };
        var calculateRangeContainerCanvas = function(size, indents, scaleLabelsAreaHeight, isCompactMode) {
                var canvas = {
                        left: size.left + indents.left,
                        top: size.top + indents.top,
                        width: size.width - size.left - size.right - indents.left - indents.right,
                        height: !isCompactMode ? size.height - size.top - size.bottom - indents.top : HEIGHT_COMPACT_MODE + scaleLabelsAreaHeight
                    };
                if (canvas.width <= 0)
                    canvas.width = 1;
                return canvas
            };
        var parseSliderMarkersPlaceholderSize = function(placeholderSize) {
                var placeholderWidthLeft,
                    placeholderWidthRight,
                    placeholderHeight;
                if (_isNumber(placeholderSize))
                    placeholderWidthLeft = placeholderWidthRight = placeholderHeight = placeholderSize;
                else if (placeholderSize) {
                    if (_isNumber(placeholderSize.height))
                        placeholderHeight = placeholderSize.height;
                    if (_isNumber(placeholderSize.width))
                        placeholderWidthLeft = placeholderWidthRight = placeholderSize.width;
                    else if (placeholderSize.width) {
                        if (_isNumber(placeholderSize.width.left))
                            placeholderWidthLeft = placeholderSize.width.left;
                        if (_isNumber(placeholderSize.width.right))
                            placeholderWidthRight = placeholderSize.width.right
                    }
                }
                else
                    return null;
                return {
                        widthLeft: placeholderWidthLeft,
                        widthRight: placeholderWidthRight,
                        height: placeholderHeight
                    }
            };
        var calculateIndents = function(renderer, size, scale, sliderMarkerOptions, indentOptions) {
                var leftMarkerHeight,
                    leftScaleLabelWidth = 0,
                    rightScaleLabelWidth = 0,
                    rightMarkerHeight,
                    placeholderWidthLeft = 0,
                    placeholderWidthRight = 0,
                    placeholderHeight,
                    parsedPlaceholderSize;
                indentOptions = indentOptions || {};
                parsedPlaceholderSize = parseSliderMarkersPlaceholderSize(sliderMarkerOptions.placeholderSize);
                if (parsedPlaceholderSize && indentOptions.left === undefined && indentOptions.right === undefined) {
                    placeholderWidthLeft = parsedPlaceholderSize.widthLeft;
                    placeholderWidthRight = parsedPlaceholderSize.widthRight
                }
                else {
                    placeholderWidthLeft = indentOptions.left;
                    placeholderWidthRight = indentOptions.right
                }
                if (parsedPlaceholderSize && sliderMarkerOptions.placeholderHeight === undefined)
                    placeholderHeight = parsedPlaceholderSize.height;
                else
                    placeholderHeight = sliderMarkerOptions.placeholderHeight;
                if (sliderMarkerOptions.visible) {
                    leftMarkerHeight = calculateMarkerHeight(renderer, scale.startValue, sliderMarkerOptions);
                    rightMarkerHeight = calculateMarkerHeight(renderer, scale.endValue, sliderMarkerOptions);
                    if (placeholderHeight === undefined)
                        placeholderHeight = _max(leftMarkerHeight, rightMarkerHeight)
                }
                if (scale.label.visible) {
                    leftScaleLabelWidth = calculateScaleLabelHalfWidth(renderer, scale.startValue, scale);
                    rightScaleLabelWidth = calculateScaleLabelHalfWidth(renderer, scale.endValue, scale)
                }
                placeholderWidthLeft = placeholderWidthLeft !== undefined ? placeholderWidthLeft : leftScaleLabelWidth;
                placeholderWidthRight = (placeholderWidthRight !== undefined ? placeholderWidthRight : rightScaleLabelWidth) || 1;
                return {
                        left: placeholderWidthLeft,
                        right: placeholderWidthRight,
                        top: placeholderHeight || 0,
                        bottom: 0
                    }
            };
        var calculateValueType = function(firstValue, secondValue) {
                var typeFirstValue = $.type(firstValue),
                    typeSecondValue = $.type(secondValue),
                    validType = function(type) {
                        return typeFirstValue === type || typeSecondValue === type
                    };
                return validType('date') ? DATETIME : validType('number') ? 'numeric' : validType(STRING) ? STRING : ''
            };
        var showScaleMarkers = function(scaleOptions) {
                return scaleOptions.valueType === DATETIME && scaleOptions.marker.visible
            };
        var updateTranslatorRangeInterval = function(translatorRange, scaleOptions) {
                var intervalX = scaleOptions.minorTickInterval || scaleOptions.majorTickInterval;
                if (scaleOptions.valueType === "datetime")
                    intervalX = utils.dateToMilliseconds(intervalX);
                translatorRange = translatorRange.arg.addRange({interval: intervalX})
            };
        var createRange = function(options) {
                return new core.Range(options)
            };
        var checkLogarithmicOptions = function(options, defaultLogarithmBase, incidentOccured) {
                var logarithmBase;
                if (!options)
                    return;
                logarithmBase = options.logarithmBase;
                if (options.type === LOGARITHMIC && logarithmBase <= 0 || logarithmBase && !_isNumber(logarithmBase)) {
                    options.logarithmBase = defaultLogarithmBase;
                    incidentOccured('E2104')
                }
                else if (options.type !== LOGARITHMIC)
                    options.logarithmBase = undefined
            };
        var calculateScaleAreaHeight = function(renderer, scaleOptions, visibleMarkers) {
                var textBBox,
                    value = "0",
                    formatObject = {
                        value: 0,
                        valueText: value
                    },
                    labelScaleOptions = scaleOptions.label,
                    markerScaleOPtions = scaleOptions.marker,
                    customizeText = labelScaleOptions.customizeText,
                    placeholderHeight = scaleOptions.placeholderHeight,
                    text = utils.isFunction(customizeText) ? customizeText.call(formatObject, formatObject) : value,
                    visibleLabels = labelScaleOptions.visible;
                if (placeholderHeight)
                    return placeholderHeight;
                else {
                    textBBox = getTextBBox(renderer, text, labelScaleOptions.font);
                    return (visibleLabels ? labelScaleOptions.topIndent + textBBox.height : 0) + (visibleMarkers ? markerScaleOPtions.topIndent + markerScaleOPtions.separatorHeight : 0)
                }
            };
        var updateTickIntervals = function(scaleOptions, screenDelta, incidentOccured, stick, min, max) {
                var categoriesInfo = scaleOptions._categoriesInfo,
                    tickManager = core.CoreFactory.createTickManager({
                        axisType: scaleOptions.type,
                        dataType: scaleOptions.valueType
                    }, {
                        min: min,
                        max: max,
                        screenDelta: screenDelta,
                        customTicks: categoriesInfo && categoriesInfo.categories
                    }, {
                        labelOptions: {},
                        boundCoef: 1,
                        minorTickInterval: scaleOptions.minorTickInterval,
                        tickInterval: scaleOptions.majorTickInterval,
                        incidentOccured: incidentOccured,
                        base: scaleOptions.logarithmBase,
                        showMinorTicks: true,
                        withMinorCorrection: true,
                        stick: stick !== false
                    });
                tickManager.getTicks(true);
                return {
                        majorTickInterval: tickManager.getTickInterval(),
                        minorTickInterval: tickManager.getMinorTickInterval(),
                        bounds: tickManager.getTickBounds()
                    }
            };
        var calculateTranslatorRange = function(seriesDataSource, scaleOptions) {
                var minValue,
                    maxValue,
                    inverted = false,
                    isEqualDates,
                    startValue = scaleOptions.startValue,
                    endValue = scaleOptions.endValue,
                    categories,
                    categoriesInfo,
                    translatorRange = seriesDataSource ? seriesDataSource.getBoundRange() : {
                        arg: createRange(),
                        val: createRange({isValueRange: true})
                    },
                    rangeForCategories;
                if (scaleOptions.type === DISCRETE) {
                    rangeForCategories = createRange({
                        categories: scaleOptions.categories || (!seriesDataSource && startValue && endValue ? [startValue, endValue] : undefined),
                        minVisible: startValue,
                        maxVisible: endValue
                    });
                    rangeForCategories.addRange(translatorRange.arg);
                    translatorRange.arg = rangeForCategories;
                    categories = rangeForCategories.categories || [];
                    scaleOptions._categoriesInfo = categoriesInfo = utils.getCategoriesInfo(categories, startValue || categories[0], endValue || categories[categories.length - 1])
                }
                if (_isDefined(startValue) && _isDefined(endValue)) {
                    inverted = scaleOptions.inverted = categoriesInfo ? categoriesInfo.inverted : startValue > endValue;
                    minValue = categoriesInfo ? categoriesInfo.start : inverted ? endValue : startValue;
                    maxValue = categoriesInfo ? categoriesInfo.end : inverted ? startValue : endValue
                }
                else if (_isDefined(startValue) || _isDefined(endValue)) {
                    minValue = startValue;
                    maxValue = endValue
                }
                else if (categoriesInfo) {
                    minValue = categoriesInfo.start;
                    maxValue = categoriesInfo.end
                }
                isEqualDates = _isDate(minValue) && _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 startEndNotDefined = function(start, end) {
                return !_isDefined(start) || !_isDefined(end)
            };
        function getTextBBox(renderer, text, fontOptions) {
            var textElement = renderer.text(text, INVISIBLE_POS, INVISIBLE_POS).css(patchFontOptions(fontOptions)).append(renderer.root);
            var textBBox = textElement.getBBox();
            textElement.remove();
            return textBBox
        }
        function processValue(selectedRangeOptions, scaleOptions, entity, incidentOccured) {
            var parsedValue,
                value = selectedRangeOptions[entity],
                parser = scaleOptions.parser || function() {
                    return null
                },
                resultValue = scaleOptions[entity];
            if (_isDefined(value))
                parsedValue = parser(value);
            if (!_isDefined(parsedValue))
                incidentOccured("E2203", [entity]);
            else
                resultValue = parsedValue;
            return rangeSelector.utils.truncateSelectedRange(resultValue, scaleOptions)
        }
        DX.registerComponent("dxRangeSelector", rangeSelector, core.BaseWidget.inherit({
            _eventsMap: $.extend({}, core.BaseWidget.prototype._eventsMap, {
                onSelectedRangeChanged: {
                    name: SELECTED_RANGE_CHANGED,
                    deprecated: SELECTED_RANGE_CHANGED,
                    deprecatedContext: function() {
                        return null
                    },
                    deprecatedArgs: function(arg) {
                        return [cloneSelectedRange(arg)]
                    }
                },
                selectedRangeChanged: {newName: "onSelectedRangeChanged"}
            }),
            _setDeprecatedOptions: function() {
                this.callBase();
                $.extend(this._deprecatedOptions, {
                    selectedRangeChanged: {
                        since: "14.2",
                        message: "Use the 'onSelectedRangeChanged' option instead"
                    },
                    "sliderMarker.padding": {
                        since: "15.1",
                        message: "Use the 'paddingTopBottom' and 'paddingLeftRight' options instead"
                    },
                    "sliderMarker.placeholderSize": {
                        since: "15.1",
                        message: "Use the 'placeholderHeight' and 'indent' options instead"
                    }
                })
            },
            _rootClassPrefix: "dxrs",
            _rootClass: "dxrs-range-selector",
            _dataSourceOptions: function() {
                return {paginate: false}
            },
            _dataIsReady: function() {
                return this._isDataSourceReady()
            },
            _initCore: function() {
                var that = this;
                that.rangeContainer = createRangeContainer(that._renderer);
                that._reinitDataSource();
                that._renderer.root.css({
                    "touch-action": "pan-y",
                    "-ms-touch-action": "pan-y"
                })
            },
            _initTooltip: $.noop,
            _setTooltipRendererOptions: $.noop,
            _setTooltipOptions: $.noop,
            _getDefaultSize: function() {
                return {
                        width: 400,
                        height: 160
                    }
            },
            _handleLoadingIndicatorShown: $.noop,
            _reinitDataSource: function() {
                this._refreshDataSource()
            },
            _disposeCore: function() {
                var that = this,
                    disposeObject = function(propName) {
                        that[propName] && that[propName].dispose(),
                        that[propName] = null
                    };
                that.callBase();
                disposeObject("renderer");
                that.translators = null;
                disposeObject("rangeContainer")
            },
            _createThemeManager: function() {
                return rangeSelector.rangeSelectorFactory.createThemeManager()
            },
            _refresh: function() {
                var that = this,
                    callBase = that.callBase;
                that._endLoading(function() {
                    callBase.call(that)
                })
            },
            _render: function(isResizing) {
                var that = this,
                    currentAnimationEnabled,
                    renderer = that._renderer;
                isResizing = isResizing || that.__isResizing;
                that._applyOptions();
                if (isResizing) {
                    currentAnimationEnabled = renderer.animationEnabled();
                    renderer.updateAnimationOptions({enabled: false});
                    that.rangeContainer.redraw();
                    renderer.updateAnimationOptions({enabled: currentAnimationEnabled})
                }
                else
                    that.rangeContainer.redraw();
                !isResizing && (!that._dataSource || that._dataSource && that._dataSource.isLoaded()) && that.hideLoadingIndicator();
                that._drawn();
                that.__rendered && that.__rendered()
            },
            _optionChanged: function(args) {
                var that = this,
                    name = args.name;
                if (name === "dataSource")
                    that._reinitDataSource();
                else if (name === SELECTED_RANGE)
                    that.setSelectedRange(that.option(SELECTED_RANGE));
                else
                    that.callBase(args)
            },
            _applySize: $.noop,
            _resize: function() {
                this._render(true)
            },
            _dataSourceChangedHandler: function() {
                var that = this;
                that._endLoading(function() {
                    if (that._renderer.drawn)
                        that._render()
                })
            },
            _applyOptions: function() {
                var that = this,
                    rangeContainerCanvas,
                    seriesDataSource,
                    translatorRange,
                    scaleLabelsAreaHeight,
                    sizeOptions = that._canvas,
                    indents,
                    sliderMarkerOptions,
                    selectedRange,
                    chartOptions = that.option('chart'),
                    shutterOptions = that._getOption("shutter"),
                    background = that._getOption(BACKGROUND),
                    isCompactMode,
                    scaleOptions,
                    chartThemeManager;
                that._isUpdating = true;
                seriesDataSource = that._createSeriesDataSource(chartOptions);
                isCompactMode = !(seriesDataSource && seriesDataSource.isShowChart() || background && background.image && background.image.url);
                if (seriesDataSource) {
                    chartThemeManager = seriesDataSource.getThemeManager();
                    checkLogarithmicOptions(chartOptions && chartOptions.valueAxis, chartThemeManager.getOptions("valueAxis").logarithmBase, that._incidentOccured)
                }
                scaleOptions = that._scaleOptions = that._prepareScaleOptions(seriesDataSource);
                translatorRange = calculateTranslatorRange(seriesDataSource, scaleOptions);
                that._updateScaleOptions(seriesDataSource, translatorRange.arg, sizeOptions.width);
                updateTranslatorRangeInterval(translatorRange, scaleOptions);
                sliderMarkerOptions = that._prepareSliderMarkersOptions(sizeOptions.width);
                selectedRange = that._initSelection();
                indents = calculateIndents(that._renderer, sizeOptions, scaleOptions, sliderMarkerOptions, that.option("indent"));
                scaleLabelsAreaHeight = calculateScaleAreaHeight(that._renderer, scaleOptions, showScaleMarkers(scaleOptions));
                rangeContainerCanvas = calculateRangeContainerCanvas(sizeOptions, indents, scaleLabelsAreaHeight, isCompactMode);
                that.translators = createTranslator(translatorRange, createTranslatorCanvas(sizeOptions, rangeContainerCanvas, scaleLabelsAreaHeight));
                scaleOptions.ticksInfo = that._getTicksInfo(rangeContainerCanvas.width);
                that._testTicksInfo = scaleOptions.ticksInfo;
                that._selectedRange = selectedRange;
                if (seriesDataSource)
                    seriesDataSource.adjustSeriesDimensions(that.translators);
                shutterOptions.color = shutterOptions.color || that._getOption(CONTAINER_BACKGROUND_COLOR, true);
                that.rangeContainer.applyOptions({
                    canvas: rangeContainerCanvas,
                    isCompactMode: isCompactMode,
                    scaleLabelsAreaHeight: scaleLabelsAreaHeight,
                    indents: indents,
                    translators: that.translators,
                    selectedRange: selectedRange,
                    scale: scaleOptions,
                    behavior: that._getOption('behavior'),
                    background: background,
                    chart: chartOptions,
                    seriesDataSource: seriesDataSource,
                    sliderMarker: sliderMarkerOptions,
                    sliderHandle: that._getOption('sliderHandle'),
                    shutter: shutterOptions,
                    selectedRangeColor: that._getOption("selectedRangeColor", true),
                    selectedRangeChanged: function(selectedRange, blockSelectedRangeChanged) {
                        that.option(SELECTED_RANGE, selectedRange);
                        if (!blockSelectedRangeChanged)
                            that._eventTrigger(SELECTED_RANGE_CHANGED, cloneSelectedRange(selectedRange))
                    },
                    setSelectedRange: function(selectedRange) {
                        that.setSelectedRange(selectedRange)
                    }
                });
                that._isUpdating = false;
                chartThemeManager && chartThemeManager.dispose()
            },
            _initSelection: function() {
                var that = this,
                    scaleOptions = that._scaleOptions,
                    selectedRangeOptions = that.option(SELECTED_RANGE),
                    incidentOccured = that._incidentOccured;
                if (!selectedRangeOptions)
                    return cloneSelectedRange(scaleOptions);
                else
                    return {
                            startValue: processValue(selectedRangeOptions, scaleOptions, START_VALUE, incidentOccured),
                            endValue: processValue(selectedRangeOptions, scaleOptions, END_VALUE, incidentOccured)
                        }
            },
            _createSeriesDataSource: function(chartOptions) {
                var that = this,
                    seriesDataSource,
                    dataSource = that._dataSource && that._dataSource.items(),
                    scaleOptions = that._getOption('scale'),
                    valueType = scaleOptions.valueType,
                    backgroundOption = that.option(BACKGROUND);
                if (!valueType)
                    valueType = calculateValueType(scaleOptions.startValue, scaleOptions.endValue);
                if (dataSource || chartOptions && chartOptions.series) {
                    chartOptions = $.extend({}, chartOptions, {theme: that.option("theme")});
                    seriesDataSource = new rangeSelector.SeriesDataSource({
                        renderer: that._renderer,
                        dataSource: dataSource,
                        valueType: (valueType || '').toLowerCase(),
                        axisType: scaleOptions.type,
                        chart: chartOptions,
                        dataSourceField: that.option('dataSourceField'),
                        backgroundColor: backgroundOption && backgroundOption.color,
                        incidentOccured: that._incidentOccured,
                        categories: scaleOptions.categories
                    })
                }
                return seriesDataSource
            },
            _prepareScaleOptions: function(seriesDataSource) {
                var that = this,
                    scaleOptions = that._getOption('scale'),
                    parsedValue = 0,
                    parseUtils = new ParseUtils,
                    valueType = parseUtils.correctValueType((scaleOptions.valueType || '').toLowerCase()),
                    parser,
                    validateStartEndValues = function(field, parser) {
                        var messageToIncidentOccured = field === START_VALUE ? 'start' : 'end';
                        if (_isDefined(scaleOptions[field])) {
                            parsedValue = parser(scaleOptions[field]);
                            if (_isDefined(parsedValue))
                                scaleOptions[field] = parsedValue;
                            else {
                                scaleOptions[field] = undefined;
                                that._incidentOccured("E2202", [messageToIncidentOccured])
                            }
                        }
                    };
                if (seriesDataSource)
                    valueType = seriesDataSource.getCalculatedValueType() || valueType;
                if (!valueType)
                    valueType = calculateValueType(scaleOptions.startValue, scaleOptions.endValue) || 'numeric';
                if (valueType === STRING || scaleOptions.categories) {
                    scaleOptions.type = DISCRETE;
                    valueType = STRING
                }
                scaleOptions.valueType = valueType;
                parser = parseUtils.getParser(valueType, 'scale');
                validateStartEndValues(START_VALUE, parser);
                validateStartEndValues(END_VALUE, parser);
                checkLogarithmicOptions(scaleOptions, logarithmBase, that._incidentOccured);
                if (!scaleOptions.type)
                    scaleOptions.type = 'continuous';
                scaleOptions.parser = parser;
                return scaleOptions
            },
            _prepareSliderMarkersOptions: function(screenDelta) {
                var that = this,
                    scaleOptions = that._scaleOptions,
                    minorTickInterval = scaleOptions.minorTickInterval,
                    majorTickInterval = scaleOptions.majorTickInterval,
                    endValue = scaleOptions.endValue,
                    startValue = scaleOptions.startValue,
                    sliderMarkerOptions = that._getOption(SLIDER_MARKER),
                    businessInterval,
                    sliderMarkerUserOption = that.option(SLIDER_MARKER) || {};
                sliderMarkerOptions.borderColor = that._getOption(CONTAINER_BACKGROUND_COLOR, true);
                if (!sliderMarkerOptions.format) {
                    if (!that._getOption('behavior').snapToTicks && _isNumber(scaleOptions.startValue)) {
                        businessInterval = Math.abs(endValue - startValue);
                        sliderMarkerOptions.format = 'fixedPoint';
                        sliderMarkerOptions.precision = utils.getSignificantDigitPosition(businessInterval / screenDelta)
                    }
                    if (scaleOptions.valueType === DATETIME)
                        if (!scaleOptions.marker.visible) {
                            if (_isDefined(startValue) && _isDefined(endValue))
                                sliderMarkerOptions.format = formatHelper.getDateFormatByTickInterval(startValue, endValue, minorTickInterval !== 0 ? minorTickInterval : majorTickInterval)
                        }
                        else
                            sliderMarkerOptions.format = utils.getDateUnitInterval(_isDefined(minorTickInterval) && minorTickInterval !== 0 ? minorTickInterval : majorTickInterval)
                }
                if (sliderMarkerUserOption.padding !== undefined && sliderMarkerUserOption.paddingLeftRight === undefined && sliderMarkerUserOption.paddingTopBottom === undefined)
                    sliderMarkerOptions.paddingLeftRight = sliderMarkerOptions.paddingTopBottom = sliderMarkerUserOption.padding;
                return sliderMarkerOptions
            },
            _updateScaleOptions: function(seriesDataSource, translatorRange, screenDelta) {
                var scaleOptions = this._scaleOptions,
                    min = _isDefined(translatorRange.minVisible) ? translatorRange.minVisible : translatorRange.min,
                    max = _isDefined(translatorRange.maxVisible) ? translatorRange.maxVisible : translatorRange.max,
                    tickIntervalsInfo = updateTickIntervals(scaleOptions, screenDelta, this._incidentOccured, translatorRange.stick, min, max),
                    bounds,
                    isEmptyInterval,
                    categoriesInfo = scaleOptions._categoriesInfo;
                if (seriesDataSource && !seriesDataSource.isEmpty() && !translatorRange.stubData) {
                    bounds = tickIntervalsInfo.bounds;
                    translatorRange.addRange(bounds);
                    scaleOptions.startValue = scaleOptions.inverted ? bounds.maxVisible : bounds.minVisible;
                    scaleOptions.endValue = scaleOptions.inverted ? bounds.minVisible : bounds.maxVisible
                }
                if (categoriesInfo) {
                    scaleOptions.startValue = categoriesInfo.start;
                    scaleOptions.endValue = categoriesInfo.end
                }
                isEmptyInterval = _isDate(scaleOptions.startValue) && _isDate(scaleOptions.endValue) && scaleOptions.startValue.getTime() === scaleOptions.endValue.getTime() || scaleOptions.startValue === scaleOptions.endValue;
                scaleOptions.isEmpty = startEndNotDefined(scaleOptions.startValue, scaleOptions.endValue) || isEmptyInterval;
                if (scaleOptions.isEmpty)
                    scaleOptions.startValue = scaleOptions.endValue = undefined;
                else {
                    scaleOptions.minorTickInterval = tickIntervalsInfo.minorTickInterval;
                    scaleOptions.majorTickInterval = tickIntervalsInfo.majorTickInterval;
                    if (scaleOptions.valueType === DATETIME && !_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)
                }
            },
            _getStubTicks: function(scaleOptions) {
                scaleOptions.isEmpty = true;
                return ["canvas_position_left", "canvas_position_center", "canvas_position_right"]
            },
            _getTickManagerOptions: function(scaleOptions, isEmpty, startValue, endValue) {
                var that = this;
                return {
                        labelOptions: {},
                        minorTickInterval: isEmpty ? 0 : that._getOption('scale').minorTickInterval,
                        tickInterval: scaleOptions.majorTickInterval,
                        addMinMax: scaleOptions.showCustomBoundaryTicks ? {
                            min: true,
                            max: true
                        } : undefined,
                        minorTickCount: scaleOptions.minorTickCount,
                        textOptions: {
                            align: 'center',
                            font: scaleOptions.label.font
                        },
                        textFontStyles: patchFontOptions(scaleOptions.label.font),
                        incidentOccured: that._incidentOccured,
                        isHorizontal: true,
                        renderText: function(text, x, y, options) {
                            return that._renderer.text(text, x, y, options).append(that._renderer.root)
                        },
                        getText: startEndNotDefined(startValue, endValue) ? function(value) {
                            return value
                        } : function(value) {
                            return formatValue(value, scaleOptions.label)
                        },
                        translate: function(value) {
                            return that.translators.x.translate(value)
                        },
                        textSpacing: SCALE_TEXT_SPACING,
                        setTicksAtUnitBeginning: scaleOptions.setTicksAtUnitBeginning,
                        useTicksAutoArrangement: scaleOptions.useTicksAutoArrangement,
                        base: scaleOptions.logarithmBase,
                        stick: true,
                        showMinorTicks: true,
                        withMinorCorrection: true
                    }
            },
            _getTicksInfo: function(screenDelta) {
                var that = this,
                    scaleOptions = that._scaleOptions,
                    translators = that.translators,
                    isEmpty = scaleOptions.isEmpty,
                    businessRange = translators.x.getBusinessRange(),
                    categoriesInfo = scaleOptions._categoriesInfo,
                    tickManagerTypes = {
                        axisType: scaleOptions.type,
                        dataType: scaleOptions.valueType
                    },
                    tickManagerData,
                    startValue = scaleOptions.startValue,
                    endValue = scaleOptions.endValue,
                    tickManagerOptions = that._getTickManagerOptions(scaleOptions, isEmpty, startValue, endValue),
                    majorTicks,
                    customBoundaryTicks,
                    tickManager,
                    fullTicks,
                    noInfoFromMinMax;
                tickManagerData = {
                    min: isEmpty ? businessRange.min : startValue,
                    max: isEmpty ? businessRange.max : endValue,
                    screenDelta: screenDelta,
                    customTicks: categoriesInfo && categoriesInfo.categories
                };
                tickManager = core.CoreFactory.createTickManager(tickManagerTypes, tickManagerData, tickManagerOptions);
                if (scaleOptions.type === DISCRETE)
                    noInfoFromMinMax = !_isDefined(tickManagerData.min) || !_isDefined(tickManagerData.max);
                else
                    noInfoFromMinMax = !_isDefined(tickManagerData.min) && !_isDefined(tickManagerData.max);
                majorTicks = noInfoFromMinMax && !_isDefined(tickManagerData.customTicks) ? that._getStubTicks(scaleOptions) : tickManager.getTicks(true);
                customBoundaryTicks = tickManager.getBoundaryTicks();
                fullTicks = tickManager.getFullTicks();
                if (customBoundaryTicks.length) {
                    if (majorTicks[0].valueOf() === customBoundaryTicks[0].valueOf())
                        majorTicks.splice(0, 1);
                    if (majorTicks[majorTicks.length - 1].valueOf() === customBoundaryTicks[customBoundaryTicks.length - 1].valueOf())
                        majorTicks.pop()
                }
                return {
                        majorTicks: majorTicks,
                        minorTicks: tickManager.getMinorTicks(),
                        majorTickInterval: tickManager.getTickInterval(),
                        fullTicks: fullTicks,
                        customBoundaryTicks: customBoundaryTicks
                    }
            },
            getSelectedRange: function() {
                return cloneSelectedRange(this.rangeContainer.slidersContainer.getSelectedRange())
            },
            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 data = cloneSelectedRange(this._scaleOptions);
                data.blockSelectedRangeChanged = blockSelectedRangeChanged;
                this.setSelectedRange(data)
            },
            render: function(isResizing) {
                var that = this;
                that.__isResizing = isResizing;
                that.callBase.apply(that, arguments);
                that.__isResizing = null;
                return that
            }
        }).include(DX.ui.DataHelperMixin))
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file rangeContainer.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            baseVisualElementMethods = rangeSelector.baseVisualElementMethods,
            RangeContainer;
        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, indents) {
                return {
                        left: canvas.left - indents.left,
                        top: canvas.top - indents.top,
                        width: canvas.width + indents.right + indents.left,
                        height: canvas.height + indents.bottom + indents.top
                    }
            };
        function canvasOptionsToRenderOptions(canvasOptions) {
            return {
                    x: canvasOptions.left,
                    y: canvasOptions.top,
                    width: canvasOptions.width,
                    height: canvasOptions.height
                }
        }
        RangeContainer = function(renderer) {
            baseVisualElementMethods.init.apply(this, arguments);
            this.slidersContainer = createSlidersContainer(renderer);
            this.rangeView = createRangeView(renderer);
            this.scale = createScale(renderer)
        };
        RangeContainer.prototype = $.extend({}, baseVisualElementMethods, {
            constructor: RangeContainer,
            dispose: function() {
                this.slidersContainer.dispose();
                this.slidersContainer = null
            },
            _applyOptions: function(options) {
                var that = this,
                    scaleLabelsAreaHeight = options.scaleLabelsAreaHeight,
                    canvas = options.canvas,
                    isCompactMode = options.isCompactMode,
                    viewCanvas = {
                        left: canvas.left,
                        top: canvas.top,
                        width: canvas.width,
                        height: canvas.height >= scaleLabelsAreaHeight ? canvas.height - scaleLabelsAreaHeight : 0
                    };
                that._viewCanvas = viewCanvas;
                that.slidersContainer.applyOptions({
                    isCompactMode: isCompactMode,
                    canvas: viewCanvas,
                    selectedRangeColor: options.selectedRangeColor,
                    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
                });
                that.rangeView.applyOptions({
                    isCompactMode: isCompactMode,
                    canvas: viewCanvas,
                    translators: options.translators,
                    background: options.background,
                    chart: options.chart,
                    seriesDataSource: options.seriesDataSource,
                    behavior: options.behavior,
                    isEmpty: options.scale.isEmpty
                });
                that.scale.applyOptions({
                    isCompactMode: isCompactMode,
                    canvas: canvas,
                    translator: options.translators.x,
                    scale: options.scale,
                    scaleLabelsAreaHeight: scaleLabelsAreaHeight,
                    setSelectedRange: options.setSelectedRange
                })
            },
            _draw: function() {
                var that = this,
                    containerGroup,
                    rangeViewGroup,
                    slidersContainerGroup,
                    scaleGroup,
                    trackersGroup,
                    options = that._options,
                    clipRectCanvas = _createClipRectCanvas(options.canvas, options.indents),
                    viewCanvas = that._viewCanvas,
                    renderer = that._renderer,
                    slidersContainer = that.slidersContainer;
                that._clipRect = renderer.clipRect(clipRectCanvas.left, clipRectCanvas.top, clipRectCanvas.width, clipRectCanvas.height);
                that._viewClipRect = renderer.clipRect(viewCanvas.left, viewCanvas.top, viewCanvas.width, viewCanvas.height);
                containerGroup = renderer.g().attr({
                    'class': 'rangeContainer',
                    clipId: that._clipRect.id
                }).append(renderer.root);
                rangeViewGroup = renderer.g().attr({
                    'class': 'view',
                    clipId: that._viewClipRect.id
                });
                that._slidersGroup = slidersContainerGroup = renderer.g().attr({'class': 'slidersContainer'});
                scaleGroup = renderer.g().attr({'class': 'scale'});
                trackersGroup = renderer.g().attr({'class': 'trackers'});
                rangeViewGroup.append(containerGroup);
                if (!options.isCompactMode) {
                    slidersContainerGroup.append(containerGroup);
                    scaleGroup.append(containerGroup)
                }
                else {
                    scaleGroup.append(containerGroup);
                    slidersContainerGroup.append(containerGroup)
                }
                trackersGroup.append(containerGroup);
                that.rangeView.redraw(rangeViewGroup);
                slidersContainer.redraw(slidersContainerGroup);
                that.scale.redraw(scaleGroup);
                that._trackersGroup = trackersGroup;
                slidersContainer.appendTrackers(trackersGroup)
            },
            _update: function() {
                var that = this,
                    options = that._options,
                    slidersContainer = that.slidersContainer;
                that._clipRect.attr(canvasOptionsToRenderOptions(_createClipRectCanvas(options.canvas, options.indents)));
                that._viewClipRect.attr(canvasOptionsToRenderOptions(that._viewCanvas));
                that.rangeView.redraw();
                slidersContainer.redraw(that._slidersGroup);
                slidersContainer.appendTrackers(that._trackersGroup);
                that.scale.redraw()
            },
            createSlidersContainer: createSlidersContainer,
            createScale: createScale
        });
        rangeSelector.RangeContainer = RangeContainer
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file scale.js */
    (function($, DX, undefined) {
        var viz = DX.viz,
            rangeSelector = viz.rangeSelector,
            formatHelper = DX.formatHelper,
            rangeSelectorUtils = rangeSelector.utils,
            utils = DX.utils,
            _isDefined = utils.isDefined,
            HALF_TICK_LENGTH = 6,
            MINOR_TICK_OPACITY_COEF = 0.6,
            Scale,
            baseVisualElementMethods = rangeSelector.baseVisualElementMethods,
            _extend = $.extend;
        function calculateRangeByMarkerPosition(posX, markerDatePositions, scaleOptions) {
            var selectedRange = {},
                position,
                i;
            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
        }
        var dateSetters = {};
        dateSetters.millisecond = function(date) {
            date.setMilliseconds(0)
        };
        dateSetters.second = function(date) {
            date.setSeconds(0, 0)
        };
        dateSetters.minute = function(date) {
            date.setMinutes(0, 0, 0)
        };
        dateSetters.hour = function(date) {
            date.setHours(0, 0, 0, 0)
        };
        dateSetters.week = dateSetters.day = function(date) {
            date.setDate(1);
            dateSetters.hour(date)
        };
        dateSetters.month = function(date) {
            date.setMonth(0);
            dateSetters.day(date)
        };
        dateSetters.quarter = function(date) {
            date.setMonth(formatHelper.getFirstQuarterMonth(date.getMonth()));
            dateSetters.day(date)
        };
        function getMarkerDate(date, tickInterval) {
            var markerDate = new Date(date.getTime()),
                setter = dateSetters[tickInterval];
            setter && setter(markerDate);
            return markerDate
        }
        function prepareDatesDifferences(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
                }
        }
        function getLabel(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)
        }
        Scale = function() {
            baseVisualElementMethods.init.apply(this, arguments)
        };
        Scale.prototype = _extend({}, baseVisualElementMethods, {
            constructor: Scale,
            _setupDateUnitInterval: function(scaleOptions) {
                var key,
                    millisecTickInterval,
                    majorTickInterval = scaleOptions.ticksInfo.majorTickInterval,
                    majorTicks = scaleOptions.ticksInfo.majorTicks;
                if (scaleOptions.valueType === 'datetime') {
                    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.dateToMilliseconds(majorTickInterval)
                            }
                        majorTickInterval = utils.convertMillisecondsToDateUnits(millisecTickInterval)
                    }
                    this.dateUnitInterval = utils.getDateUnitInterval(majorTickInterval)
                }
            },
            _getDrawnDateMarker: function(date, options) {
                var that = this,
                    labelPosX,
                    labelPosY,
                    scaleOptions = that._options.scale,
                    textElement,
                    textElementWidth,
                    textIndent,
                    pathElement;
                if (options.x === null)
                    return;
                that.textOptions.align = "left";
                pathElement = that._renderer.path([options.x, options.y, options.x, options.y + scaleOptions.marker.separatorHeight], "line").attr(that._majorTickStyle).append(options.group);
                textElement = that._renderer.text(getLabel(date, options.label), 0, 0).attr(that.textOptions).css(that.fontOptions).append(options.group);
                textElementWidth = textElement.getBBox().width;
                textIndent = scaleOptions.tick.width + scaleOptions.marker.textLeftIndent;
                labelPosX = scaleOptions.inverted ? options.x - textIndent - textElementWidth : options.x + textIndent;
                labelPosY = options.y + scaleOptions.marker.textTopIndent + that.fontOptions["font-size"];
                textElement.move(labelPosX, labelPosY);
                return {
                        x1: labelPosX,
                        x2: labelPosX + textElementWidth,
                        path: pathElement,
                        text: textElement
                    }
            },
            _deleteDrawnDateMarker: function(marker) {
                marker.path.dispose();
                marker.path = null;
                marker.text.dispose();
                marker.text = null
            },
            _drawDateMarkers: function(dates, group) {
                var that = this,
                    i,
                    options = that._options,
                    datesLength = dates.length,
                    datesDifferences,
                    markerDate,
                    posX,
                    markerDatePositions = [],
                    prevDateMarker,
                    dateMarker;
                if (options.scale.valueType !== 'datetime' || !that.visibleMarkers)
                    return;
                if (dates.length > 1) {
                    for (i = 1; i < datesLength; i++) {
                        datesDifferences = utils.getDatesDifferences(dates[i - 1], dates[i]);
                        prepareDatesDifferences(datesDifferences, that.dateUnitInterval);
                        if (datesDifferences.count > 0) {
                            markerDate = getMarkerDate(dates[i], that.dateUnitInterval);
                            that.markerDates = that.markerDates || [];
                            that.markerDates.push(markerDate);
                            posX = that.translator.translate(markerDate);
                            dateMarker = that._getDrawnDateMarker(markerDate, {
                                group: group,
                                y: options.canvas.top + options.canvas.height - that.markersAreaHeight + options.scale.marker.topIndent,
                                x: posX,
                                label: that._getLabelFormatOptions(formatHelper.getDateFormatByDifferences(datesDifferences))
                            });
                            if (prevDateMarker === undefined || dateMarker.x1 > prevDateMarker.x2 || dateMarker.x2 < prevDateMarker.x1) {
                                posX !== null && markerDatePositions.push({
                                    date: markerDate,
                                    posX: posX
                                });
                                prevDateMarker = dateMarker
                            }
                            else
                                that._deleteDrawnDateMarker(dateMarker)
                        }
                    }
                    that._initializeMarkersEvents(markerDatePositions, group)
                }
            },
            _getLabelFormatOptions: function(formatString) {
                if (!_isDefined(this._options.scale.marker.label.format))
                    return _extend({}, this._options.scale.marker.label, {format: formatString});
                return this._options.scale.marker.label
            },
            _initializeMarkersEvents: function(markerDatePositions, group) {
                var that = this,
                    options = that._options,
                    markersAreaTop = options.canvas.top + options.canvas.height - this.markersAreaHeight + options.scale.marker.topIndent,
                    markersTracker,
                    svgOffsetLeft,
                    posX,
                    selectedRange;
                if (markerDatePositions.length > 0) {
                    markersTracker = that._renderer.rect(options.canvas.left, markersAreaTop, options.canvas.width, options.scale.marker.separatorHeight).attr(rangeSelectorUtils.trackerSettings).append(group);
                    markersTracker.on(rangeSelector.events.start, function(e) {
                        svgOffsetLeft = that._renderer.getRootOffset().left;
                        posX = rangeSelectorUtils.getEventPageX(e) - svgOffsetLeft;
                        selectedRange = calculateRangeByMarkerPosition(posX, markerDatePositions, options.scale);
                        options.setSelectedRange(selectedRange)
                    });
                    that._markersTracker = markersTracker
                }
            },
            _drawLabel: function(text, group) {
                var that = this,
                    options = that._options,
                    canvas = options.canvas,
                    textY = canvas.top + canvas.height - that.markersAreaHeight,
                    textElements = that._renderer.text(getLabel(text, options.scale.label), that.translator.translate(text), textY).attr(that.textOptions).css(that.fontOptions).append(group);
                that.textElements = that.textElements || [];
                that.textElements.push(textElements)
            },
            _drawTicks: function(ticks, group, directionOffset, coords, style, labelsGroup) {
                var that = this,
                    i,
                    posX,
                    tickElement;
                for (i = 0; i < ticks.length; i++) {
                    if (labelsGroup)
                        that._drawLabel(ticks[i], labelsGroup);
                    posX = that.translator.translate(ticks[i], directionOffset);
                    tickElement = that._createLine([posX, coords[0], posX, coords[1]], group, style);
                    that.tickElements = that.tickElements || [];
                    that.tickElements.push(tickElement)
                }
            },
            _createLine: function(points, group, options) {
                return this._renderer.path(points, "line").attr(options).append(group)
            },
            _redraw: function(group) {
                var that = this,
                    options = that._options,
                    scaleOptions = options.scale,
                    renderer = that._renderer,
                    labelsGroup = renderer.g().append(group),
                    ticksGroup = renderer.g(),
                    ticksInfo = scaleOptions.ticksInfo,
                    majorTicks = ticksInfo.majorTicks,
                    minorTicks = ticksInfo.minorTicks,
                    customBoundaryTicks = ticksInfo.customBoundaryTicks,
                    hideLabels = scaleOptions.isEmpty || !scaleOptions.label.visible,
                    isDiscrete = scaleOptions.type === "discrete",
                    directionOffset = isDiscrete ? -1 : 0,
                    isCompactMode = options.isCompactMode,
                    canvas = options.canvas,
                    bottom = canvas.top + canvas.height - that.scaleLabelsAreaHeight,
                    center = canvas.top + (bottom - canvas.top) / 2,
                    coords = isCompactMode ? [center - HALF_TICK_LENGTH, center + HALF_TICK_LENGTH] : [canvas.top, bottom],
                    categoriesInfo = scaleOptions._categoriesInfo,
                    majorTickStyle = that._majorTickStyle;
                that._drawTicks(majorTicks, ticksGroup, directionOffset, coords, majorTickStyle, !hideLabels && labelsGroup);
                if (scaleOptions.showMinorTicks || isDiscrete)
                    that._drawTicks(minorTicks, ticksGroup, directionOffset, coords, that._minorTickStyle);
                that._drawTicks(customBoundaryTicks, ticksGroup, 0, coords, majorTickStyle);
                isDiscrete && categoriesInfo && _isDefined(categoriesInfo.end) && that._drawTicks([categoriesInfo.end], ticksGroup, 1, coords, majorTickStyle);
                if (isCompactMode)
                    that._createLine([canvas.left, center, canvas.width + canvas.left, center], group, _extend({}, majorTickStyle, {sharp: "v"}));
                ticksGroup.append(group);
                that._drawDateMarkers(majorTicks, labelsGroup)
            },
            _applyOptions: function(options) {
                var that = this,
                    scaleOptions = options.scale,
                    labelsAreaHeight,
                    tick = scaleOptions.tick;
                that.textOptions = {align: 'center'};
                that.fontOptions = viz.core.utils.patchFontOptions(scaleOptions.label.font);
                that._majorTickStyle = {
                    "stroke-width": tick.width,
                    stroke: tick.color,
                    "stroke-opacity": tick.opacity,
                    sharp: "h"
                };
                that._minorTickStyle = _extend({}, that._majorTickStyle, {"stroke-opacity": tick.opacity * MINOR_TICK_OPACITY_COEF});
                that._setupDateUnitInterval(scaleOptions);
                that.visibleMarkers = scaleOptions.marker.visible === undefined ? true : scaleOptions.marker.visible;
                labelsAreaHeight = scaleOptions.label.visible ? scaleOptions.label.topIndent + that.fontOptions["font-size"] : 0;
                that.scaleLabelsAreaHeight = options.scaleLabelsAreaHeight;
                that.markersAreaHeight = that.scaleLabelsAreaHeight - labelsAreaHeight;
                that.translator = options.translator
            },
            _draw: function(group) {
                this._redraw(group)
            },
            _update: function() {
                if (this._markersTracker)
                    this._markersTracker.off(rangeSelector.events.start, '**');
                baseVisualElementMethods._update.apply(this, arguments)
            }
        });
        Scale.prototype._calculateRangeByMarkerPosition = calculateRangeByMarkerPosition;
        Scale.prototype._prepareDatesDifferences = prepareDatesDifferences;
        rangeSelector.Scale = Scale
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file rangeFactory.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector;
        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,
            msPointerEnabled = DX.support.pointer,
            isNumber = utils.isNumber,
            isDate = utils.isDate,
            isString = utils.isString,
            rangeSelectorUtils = rangeSelector.utils,
            baseVisualElementMethods = rangeSelector.baseVisualElementMethods,
            rangeSelectorFactory = rangeSelector.rangeSelectorFactory,
            trackerAttributes = rangeSelectorUtils.trackerSettings;
        function SlidersContainer() {
            var that = this;
            baseVisualElementMethods.init.apply(that, arguments);
            that._controller = rangeSelectorFactory.createSlidersController(that._renderer);
            that._eventsManager = rangeSelectorFactory.createSlidersEventsManager(that._renderer, that._controller, function(moving) {
                that._processSelectionChanged(moving)
            });
            that._lastSelectedRange = {}
        }
        SlidersContainer.prototype = $.extend({}, baseVisualElementMethods, {
            constructor: SlidersContainer,
            _drawAreaTracker: function(group) {
                var that = this,
                    areaTracker,
                    selectedAreaTracker,
                    canvas = that._options.canvas,
                    renderer = that._renderer;
                areaTracker = renderer.rect(canvas.left, canvas.top, canvas.width, canvas.height).attr(trackerAttributes).append(group);
                selectedAreaTracker = renderer.rect(canvas.left, canvas.top, canvas.width, canvas.height).attr(trackerAttributes).css({cursor: 'pointer'}).append(group);
                that._controller.setAreaTrackers(areaTracker, selectedAreaTracker)
            },
            dispose: function() {
                this._eventsManager.dispose();
                this._controller.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 (utils.isFunction(that._options.selectedRangeChanged))
                        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
                }
            },
            getSelectedRange: function() {
                return this._controller.getSelectedRange()
            },
            setSelectedRange: function(selectedRange) {
                var that = this,
                    scale = that._options.scale,
                    startValue,
                    endValue,
                    currentSelectedRange = that._options.selectedRange,
                    checkTypes = function(valueName, value) {
                        var valueFromScale = scale[valueName];
                        if (isNumber(valueFromScale) && isNumber(value) || isDate(valueFromScale) && isDate(value) || isString(valueFromScale) && isString(value))
                            currentSelectedRange[valueName] = value
                    };
                if (selectedRange) {
                    startValue = selectedRange.startValue;
                    endValue = selectedRange.endValue
                }
                checkTypes('startValue', startValue);
                checkTypes('endValue', endValue);
                currentSelectedRange.startValue = rangeSelectorUtils.truncateSelectedRange(currentSelectedRange.startValue, scale);
                currentSelectedRange.endValue = rangeSelectorUtils.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({
                    isCompactMode: options.isCompactMode,
                    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.root;
                    rootElement && rootElement.css({msTouchAction: "pinch-zoom"})
                }
                that._controller.redraw(group);
                that._drawAreaTracker(group);
                that._eventsManager.initialize();
                that._update(group)
            },
            _updateSelectedView: function(group) {
                var that = this,
                    options = that._options,
                    canvas = options.canvas,
                    lineOptions = {
                        "stroke-width": 3,
                        stroke: options.selectedRangeColor,
                        sharp: "v"
                    },
                    center = canvas.top + canvas.height / 2,
                    selectedView = that._selectedView,
                    selectedViewAppended = that._selectedViewAppended,
                    controller = that._controller;
                if (!options.isCompactMode) {
                    if (selectedView && selectedViewAppended) {
                        selectedView.remove();
                        that._selectedViewAppended = false
                    }
                    controller.createShutters()
                }
                else {
                    if (!selectedView) {
                        that._selectedView = selectedView = that._renderer.path([canvas.left, center, canvas.left, center], "line").attr(lineOptions);
                        controller.setSelectedView(selectedView)
                    }
                    else
                        selectedView.attr(lineOptions);
                    if (!selectedViewAppended) {
                        selectedView.append(group);
                        controller.removeShutters();
                        that._selectedViewAppended = true
                    }
                }
            },
            _update: function(group) {
                var that = this,
                    isEmpty = that._options.scale.isEmpty,
                    controller = that._controller;
                that._eventsManager.setEnabled(!isEmpty);
                !isEmpty && that._updateSelectedView(group);
                controller.applySelectedRange(isEmpty ? {} : that._options.selectedRange);
                controller.applyPosition(that.isDrawn());
                that._updateLastSelectedRange();
                controller.redraw()
            },
            getController: function() {
                return this._controller
            }
        });
        rangeSelector.SlidersContainer = SlidersContainer
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file slidersController.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            createSlider = rangeSelector.rangeSelectorFactory.createSlider,
            utils = DX.utils,
            rangeSelectorUtils = rangeSelector.utils,
            _SliderController,
            START_VALUE_INDEX = 0,
            END_VALUE_INDEX = 1,
            DISCRETE = 'discrete';
        _SliderController = rangeSelector.SlidersController = function(renderer) {
            var sliders = [createSlider(renderer, START_VALUE_INDEX), createSlider(renderer, END_VALUE_INDEX)];
            sliders[START_VALUE_INDEX].setAnotherSlider(sliders[END_VALUE_INDEX]);
            sliders[END_VALUE_INDEX].setAnotherSlider(sliders[START_VALUE_INDEX]);
            this._sliders = sliders
        };
        _SliderController.prototype = {
            constructor: _SliderController,
            setAreaTrackers: function(areaTracker, selectedAreaTracker) {
                this._areaTracker = areaTracker;
                this._selectedAreaTracker = selectedAreaTracker
            },
            applyOptions: function(options) {
                var that = this,
                    values = null,
                    startSlider = that.getSlider(START_VALUE_INDEX),
                    endSlider = that.getSlider(END_VALUE_INDEX),
                    scaleOptions = options.scale;
                that._options = options;
                startSlider.applyOptions(options);
                endSlider.applyOptions(options);
                if (options.behavior.snapToTicks && scaleOptions.type !== DISCRETE) {
                    values = scaleOptions.ticksInfo.fullTicks;
                    if (values.length > 1 && values[0] > values[values.length - 1])
                        values = values.reverse()
                }
                startSlider.setAvailableValues(values);
                endSlider.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();
                that._applySelectedRangePosition()
            },
            _applySelectedRangePosition: function(disableAnimation) {
                var that = this,
                    options = that._options,
                    canvas = options.canvas,
                    center = canvas.top + canvas.height / 2,
                    isAnimation = options.behavior.animationEnabled && !disableAnimation,
                    startSliderPos = that.getSlider(START_VALUE_INDEX).getPosition(),
                    interval = that.getSelectedRangeInterval(),
                    points = [startSliderPos, center, startSliderPos + interval, center],
                    selectedView = that._selectedView;
                if (!selectedView || !options.isCompactMode)
                    return;
                if (isAnimation)
                    selectedView.animate({points: points}, rangeSelectorUtils.animationSettings);
                else
                    selectedView.stopAnimation().attr({points: points})
            },
            setSelectedView: function(selectedView) {
                this._selectedView = selectedView
            },
            getSelectedRangeInterval: function() {
                var that = this;
                return that.getSlider(END_VALUE_INDEX).getPosition() - that.getSlider(START_VALUE_INDEX).getPosition()
            },
            moveSliders: function(postitionDelta, selectedRangeInterval) {
                var startSlider = this.getSlider(START_VALUE_INDEX);
                startSlider.setPosition(startSlider.getPosition() + postitionDelta, false, selectedRangeInterval);
                this.applyPosition(true)
            },
            moveSlider: function(sliderIndex, fastSwap, position, offsetPosition, startOffsetPosition, startOffsetPositionChangedCallback) {
                var that = this,
                    slider = that.getSlider(sliderIndex),
                    anotherSlider = slider.getAnotherSlider(),
                    anotherSliderPosition = anotherSlider.getPosition(),
                    doSwap;
                if (slider.canSwap())
                    if (sliderIndex === START_VALUE_INDEX ? position > anotherSliderPosition : position < anotherSliderPosition) {
                        doSwap = fastSwap;
                        if (!fastSwap)
                            if (Math.abs(offsetPosition) >= Math.abs(startOffsetPosition)) {
                                doSwap = true;
                                if (offsetPosition * startOffsetPosition < 0) {
                                    position += 2 * startOffsetPosition;
                                    startOffsetPositionChangedCallback(-startOffsetPosition)
                                }
                                else {
                                    position -= 2 * startOffsetPosition;
                                    startOffsetPositionChangedCallback(startOffsetPosition)
                                }
                            }
                        if (doSwap) {
                            that.swapSliders();
                            anotherSlider.applyPosition(true)
                        }
                    }
                slider.setPosition(position, true);
                slider.applyPosition(true);
                that.applyAreaTrackersPosition();
                that._applySelectedRangePosition(true);
                that.setTrackersCursorStyle('w-resize')
            },
            applySelectedAreaCenterPosition: function(pos) {
                var that = this,
                    startSlider = that.getSlider(START_VALUE_INDEX),
                    slidersContainerHalfWidth = (that.getSlider(END_VALUE_INDEX).getPosition() - startSlider.getPosition()) / 2,
                    selectedRangeInterval = that.getSelectedRangeInterval();
                startSlider.setPosition(pos - slidersContainerHalfWidth, false, selectedRangeInterval);
                that.applyPosition();
                that.processDocking()
            },
            endSelection: function() {
                var startSlider = this.getSlider(START_VALUE_INDEX),
                    endSlider = this.getSlider(END_VALUE_INDEX),
                    cloudSpacing = startSlider.getCloudBorder() - endSlider.getCloudBorder(),
                    overlappedState;
                if (cloudSpacing > 0)
                    overlappedState = true;
                else
                    overlappedState = false;
                startSlider.setOverlapped(overlappedState);
                endSlider.setOverlapped(overlappedState)
            },
            processManualSelection: function(startPosition, endPosition, eventArgs) {
                var that = this,
                    animateSliderIndex,
                    movingSliderIndex,
                    positionRange = [Math.min(startPosition, endPosition), Math.max(startPosition, endPosition)],
                    movingSlider,
                    animatedSlider;
                animateSliderIndex = startPosition < endPosition ? START_VALUE_INDEX : END_VALUE_INDEX;
                movingSliderIndex = startPosition < endPosition ? END_VALUE_INDEX : START_VALUE_INDEX;
                movingSlider = that.getSlider(movingSliderIndex);
                animatedSlider = that.getSlider(animateSliderIndex);
                movingSlider.setPosition(positionRange[movingSliderIndex]);
                animatedSlider.setPosition(positionRange[animateSliderIndex]);
                movingSlider.setPosition(positionRange[movingSliderIndex], true);
                movingSlider.startEventHandler(eventArgs);
                animatedSlider.processDocking();
                movingSlider.applyPosition(true)
            },
            applySelectedRange: function(selectedRange) {
                utils.debug.assertParam(selectedRange, 'selectedRange not passed');
                var that = this,
                    scaleoptions = that._options.scale,
                    inverted = scaleoptions.inverted,
                    startSlider = that.getSlider(START_VALUE_INDEX),
                    endSlider = that.getSlider(END_VALUE_INDEX),
                    startValue = selectedRange.startValue,
                    endValue = selectedRange.endValue,
                    categoriesInfo,
                    setValues = function(startValue, endValue, isInverted) {
                        (isInverted ? endSlider : startSlider).setValue(startValue);
                        (isInverted ? startSlider : endSlider).setValue(endValue)
                    };
                if (scaleoptions.type !== DISCRETE)
                    if (!inverted && startValue > endValue || inverted && startValue < endValue)
                        setValues(startValue, endValue, true);
                    else
                        setValues(startValue, endValue);
                else {
                    categoriesInfo = utils.getCategoriesInfo(scaleoptions._categoriesInfo.categories, startValue, endValue);
                    setValues(categoriesInfo.start, categoriesInfo.end, categoriesInfo.inverted ^ scaleoptions.inverted)
                }
            },
            getSelectedRange: function() {
                return {
                        startValue: this.getSlider(START_VALUE_INDEX).getValue(),
                        endValue: this.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(),
                    canvas = that._options.canvas,
                    scaleOptions = that._options.scale,
                    startSlider = that.getSlider(START_VALUE_INDEX),
                    width = that.getSlider(END_VALUE_INDEX).getPosition() - startSlider.getPosition(),
                    options = {
                        x: startSlider.getPosition(),
                        width: width < 0 ? 0 : width,
                        y: canvas.top,
                        height: canvas.height
                    },
                    style = {cursor: scaleOptions.endValue - scaleOptions.startValue === selectedRange.endValue - selectedRange.startValue ? 'default' : 'pointer'};
                that._selectedAreaTracker.attr(options).css(style);
                that._areaTracker.attr({
                    x: canvas.left,
                    width: canvas.width,
                    y: canvas.top,
                    height: canvas.height
                })
            },
            applyPosition: function(disableAnimation) {
                var that = this;
                that.getSlider(START_VALUE_INDEX).applyPosition(disableAnimation);
                that.getSlider(END_VALUE_INDEX).applyPosition(disableAnimation);
                that.applyAreaTrackersPosition();
                that._applySelectedRangePosition(disableAnimation)
            },
            redraw: function(group) {
                var that = this;
                that.getSlider(START_VALUE_INDEX).redraw(group);
                that.getSlider(END_VALUE_INDEX).redraw(group);
                that._foregroundSliderIndex = END_VALUE_INDEX
            },
            toForeground: function(slider) {
                var that = this,
                    sliderIndex = slider.getIndex();
                if (that._foregroundSliderIndex !== sliderIndex) {
                    slider.toForeground();
                    that._foregroundSliderIndex = sliderIndex
                }
            },
            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.css({cursor: style});
                that._areaTracker.css({cursor: style})
            },
            createShutters: function() {
                var sliders = this._sliders;
                sliders[0].createShutter();
                sliders[1].createShutter()
            },
            removeShutters: function() {
                var sliders = this._sliders;
                sliders[0].removeShutter();
                sliders[1].removeShutter()
            },
            dispose: function() {
                var sliders = this._sliders;
                sliders[0].dispose();
                sliders[1].dispose()
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file slidersEventsManager.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            MIN_MANUAL_SELECTING_WIDTH = 10,
            START_VALUE_INDEX = 0,
            END_VALUE_INDEX = 1,
            addNamespace = DX.ui.events.addNamespace,
            _SlidersEventManager,
            rangeSelectorUtils = rangeSelector.utils,
            getEventPageX = rangeSelectorUtils.getEventPageX,
            rangeSelectorCount = 0;
        rangeSelector.events = {
            start: "dxpointerdown",
            move: "dxpointermove",
            end: "dxpointerup"
        };
        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,
            _initializeSliderEvents: function(sliderIndex) {
                var that = this,
                    isTouchEvent,
                    slidersController = that._slidersController,
                    processSelectionChanged = that._processSelectionChanged,
                    slider = slidersController.getSlider(sliderIndex),
                    fastSwap,
                    startOffsetPosition,
                    splitterMoving,
                    sliderEndHandler = function() {
                        if (splitterMoving) {
                            splitterMoving = false;
                            slidersController.endSelection();
                            slidersController.processDocking();
                            processSelectionChanged(false)
                        }
                    },
                    sliderMoveHandler = function(e) {
                        var pageX,
                            offsetPosition,
                            svgOffsetLeft = that._renderer.getRootOffset().left,
                            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)
                        }
                        slidersController.endSelection()
                    },
                    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._renderer.getRootOffset().left;
                    if (!isMultiTouches(e)) {
                        this.preventedDefault = true;
                        e.stopPropagation();
                        e.preventDefault()
                    }
                };
                slider.on(eventsNames.move, function() {
                    slidersController.toForeground(slider)
                });
                slider.on(eventsNames.start, slider.startEventHandler);
                $(document).on(eventsNames.end, sliderEndHandler).on(eventsNames.move, sliderMoveHandler);
                slider.__moveEventHandler = sliderMoveHandler
            },
            _initializeAreaEvents: function() {
                var that = this,
                    isTouchEvent,
                    slidersController = that._slidersController,
                    processSelectionChanged = that._processSelectionChanged,
                    areaTracker = slidersController.getAreaTracker(),
                    unselectedAreaProcessing = 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._renderer.getRootOffset().left);
                            unselectedAreaProcessing = false;
                            slidersController.endSelection();
                            processSelectionChanged(false)
                        }
                    },
                    areaMoveHandler = function(e) {
                        var pageX,
                            startPosition,
                            endPosition,
                            svgOffsetLeft = that._renderer.getRootOffset().left;
                        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,
                    isTouchEvent,
                    slidersController = that._slidersController,
                    processSelectionChanged = that._processSelectionChanged,
                    selectedAreaTracker = slidersController.getSelectedAreaTracker(),
                    selectedAreaMoving = false,
                    offsetStartPosition,
                    selectedRangeInterval,
                    selectedAreaEndHandler = function() {
                        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)
                        }
                        slidersController.endSelection()
                    },
                    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;
                that._initializeSelectedAreaEvents(that);
                that._initializeAreaEvents();
                that._initializeSliderEvents(START_VALUE_INDEX);
                that._initializeSliderEvents(END_VALUE_INDEX)
            },
            setEnabled: function(enabled) {
                this._enabled = enabled
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file slider.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            utils = DX.utils,
            rangeSelectorUtils = rangeSelector.utils,
            _inArray = $.inArray,
            dxSupport = DX.support,
            touchSupport = dxSupport.touchEvents,
            msPointerEnabled = dxSupport.pointer,
            SPLITTER_WIDTH = 8,
            TOUCH_SPLITTER_WIDTH = 20,
            START_VALUE_INDEX = 0,
            END_VALUE_INDEX = 1,
            DISCRETE = 'discrete',
            baseVisualElementMethods = rangeSelector.baseVisualElementMethods;
        function checkItemsSpacing(firstSliderPosition, secondSliderPosition, distance) {
            return Math.abs(secondSliderPosition - firstSliderPosition) < distance
        }
        function getValidCategories(categories, curValue, anotherSliderValue, offset) {
            var curValueindex = _inArray(curValue, categories);
            if (curValueindex === 0 || curValueindex === categories.length - 1)
                return anotherSliderValue;
            return categories[curValueindex - offset]
        }
        function Slider(renderer, index) {
            baseVisualElementMethods.init.apply(this, arguments);
            this._index = index
        }
        Slider.prototype = $.extend({}, baseVisualElementMethods, {
            getText: function() {
                if (this._marker)
                    return this._marker.getText()
            },
            getAvailableValues: function() {
                return this._values
            },
            getShutter: function() {
                return this._shutter
            },
            getMarker: function() {
                return this._marker
            },
            constructor: Slider,
            _createSlider: function(group) {
                var that = this,
                    sliderHandle,
                    sliderGroup,
                    sliderHandleOptions = that._options.sliderHandle,
                    canvas = that._options.canvas,
                    renderer = that._renderer;
                sliderGroup = renderer.g().attr({
                    'class': 'slider',
                    translateX: canvas.left,
                    translateY: canvas.top
                }).append(group);
                sliderHandle = renderer.path([0, 0, 0, canvas.height], "line").attr({
                    "stroke-width": sliderHandleOptions.width,
                    stroke: sliderHandleOptions.color,
                    "stroke-opacity": sliderHandleOptions.opacity,
                    sharp: "h"
                }).append(sliderGroup);
                sliderGroup.setValid = function(correct) {
                    sliderHandle.attr({stroke: correct ? that._options.sliderHandle.color : that._options.sliderMarker.invalidRangeColor})
                };
                sliderGroup.updateHeight = function() {
                    sliderHandle.attr({points: [0, 0, 0, that._options.canvas.height]})
                };
                sliderGroup.applyOptions = function(options) {
                    sliderHandle.attr(options)
                };
                sliderGroup.__line = sliderHandle;
                return sliderGroup
            },
            _createSliderTracker: function(group) {
                var that = this,
                    sliderHandleWidth = that._options.sliderHandle.width,
                    splitterWidth = SPLITTER_WIDTH < sliderHandleWidth ? sliderHandleWidth : SPLITTER_WIDTH,
                    sliderWidth = touchSupport || msPointerEnabled ? TOUCH_SPLITTER_WIDTH : splitterWidth,
                    sliderTracker,
                    canvas = that._options.canvas,
                    renderer = that._renderer,
                    sliderTrackerGroup = renderer.g().attr({
                        'class': 'sliderTracker',
                        translateX: 0,
                        translateY: canvas.top
                    }).append(group);
                sliderTracker = renderer.rect(-sliderWidth / 2, 0, sliderWidth, canvas.height).attr(rangeSelectorUtils.trackerSettings).css({cursor: 'w-resize'}).append(sliderTrackerGroup);
                sliderTrackerGroup.updateHeight = function() {
                    sliderTracker.attr({height: that._options.canvas.height})
                };
                sliderTrackerGroup.__rect = sliderTracker;
                return sliderTrackerGroup
            },
            _setPosition: function(position, correctByMinMaxRange) {
                var that = this,
                    correctedPosition = that._correctPosition(position),
                    value = that._options.translator.untranslate(correctedPosition, that._getValueDirection());
                that.setValue(value, correctByMinMaxRange, false);
                that._position = correctedPosition
            },
            _getValueDirection: function() {
                return this._options.scale.type === DISCRETE ? this.getIndex() === START_VALUE_INDEX ? -1 : 1 : 0
            },
            _setPositionForBothSliders: function(startPosition, interval) {
                var that = this,
                    anotherSlider = that.getAnotherSlider(),
                    startValue,
                    endValue,
                    endPosition,
                    options = that._options,
                    scale = options.scale,
                    canvas = options.canvas,
                    rightBorderCoords = canvas.left + canvas.width,
                    translator = options.translator,
                    valueDirection = that._getValueDirection(),
                    valueDirectionAnotherSlider = anotherSlider._getValueDirection(),
                    getNextValue = function(value, isNegative, reverseValueDirection) {
                        var curValueDirection = !reverseValueDirection ? valueDirection : valueDirectionAnotherSlider,
                            curAnotherValueDirection = reverseValueDirection ? valueDirection : valueDirectionAnotherSlider;
                        return translator.untranslate(that._correctBounds(utils.addInterval(translator.translate(value, curValueDirection), interval, isNegative)), curAnotherValueDirection)
                    };
                startPosition = that._correctBounds(startPosition);
                startValue = translator.untranslate(startPosition, valueDirection);
                endValue = getNextValue(startValue);
                endPosition = startPosition + interval;
                if (endPosition > rightBorderCoords) {
                    endValue = scale.endValue;
                    endPosition = rightBorderCoords;
                    startValue = getNextValue(endValue, true, true);
                    startPosition = that._correctBounds(endPosition - interval)
                }
                else
                    endPosition = that._correctBounds(endPosition);
                if (that._values)
                    if (!scale.inverted ? startValue < that._values[0] : startValue > that._values[that._values.length - 1]) {
                        startValue = that._correctByAvailableValues(startValue, false);
                        endValue = getNextValue(startValue)
                    }
                    else {
                        endValue = that._correctByAvailableValues(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) {
                return this._correctBounds(this._correctInversion(position))
            },
            _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
            },
            _correctValue: function(businessValue, correctByMinMaxRange, skipCorrection) {
                var that = this,
                    result = that._correctByAvailableValues(businessValue, skipCorrection);
                if (correctByMinMaxRange)
                    result = that._correctByMinMaxRange(result);
                if (that._options.scale.type !== DISCRETE)
                    result = that.correctByMinRange(result);
                return result
            },
            _correctByAvailableValues: function(businessValue, skipCorrection) {
                var values = this._values;
                if (!skipCorrection && values)
                    return rangeSelectorUtils.findNearValue(values, businessValue);
                return businessValue
            },
            _correctByMinMaxRange: function(businessValue) {
                var that = this,
                    result = businessValue,
                    scale = that._options.scale,
                    values = that._values,
                    sliderIndex = that.getIndex(),
                    anotherSlider = that.getAnotherSlider(),
                    anotherBusinessValue = anotherSlider.getValue(),
                    isValid = true,
                    minValue,
                    maxValue,
                    maxRange = scale.maxRange,
                    minRange = scale.minRange,
                    categoriesInfo;
                if (scale.type === DISCRETE) {
                    categoriesInfo = scale._categoriesInfo;
                    if (checkItemsSpacing(that.getPosition(), anotherSlider.getPosition(), that._options.translator.getInterval() / 2)) {
                        isValid = false;
                        result = getValidCategories(categoriesInfo.categories, businessValue, anotherSlider.getValue(), sliderIndex === START_VALUE_INDEX ? 1 : -1)
                    }
                }
                else {
                    if (!scale.inverted && sliderIndex === START_VALUE_INDEX || scale.inverted && sliderIndex === END_VALUE_INDEX) {
                        if (maxRange)
                            minValue = that._addInterval(anotherBusinessValue, maxRange, true);
                        if (minRange)
                            maxValue = that._addInterval(anotherBusinessValue, minRange, true)
                    }
                    else {
                        if (maxRange)
                            maxValue = that._addInterval(anotherBusinessValue, maxRange);
                        if (minRange)
                            minValue = that._addInterval(anotherBusinessValue, minRange)
                    }
                    if (maxValue !== undefined && result > maxValue) {
                        result = values ? rangeSelectorUtils.findLessOrEqualValue(values, maxValue) : maxValue;
                        isValid = false
                    }
                    else if (minValue !== undefined && result < minValue) {
                        result = values ? rangeSelectorUtils.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,
                    power;
                if (base) {
                    power = utils.addInterval(utils.getLog(value, base), interval, isNegative);
                    result = Math.pow(base, power)
                }
                else
                    result = utils.addInterval(value, interval, isNegative);
                return result
            },
            correctByMinRange: function(businessValue) {
                var that = this,
                    startValue,
                    endValue,
                    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,
                    options = that._options,
                    isAnimation = options.behavior.animationEnabled && !disableAnimation,
                    slider = that._slider,
                    sliderTracker = that._sliderTracker,
                    attrs = {
                        translateX: position,
                        translateY: options.canvas.top
                    },
                    animationSettings = rangeSelectorUtils.animationSettings;
                that._marker && that._marker.setPosition(position);
                if (isAnimation) {
                    slider.animate(attrs, animationSettings);
                    sliderTracker.animate(attrs, animationSettings)
                }
                else {
                    slider.stopAnimation().attr(attrs);
                    sliderTracker.stopAnimation().attr(attrs)
                }
                sliderTracker.updateHeight();
                slider.updateHeight()
            },
            _applyShutterPosition: function(position, disableAnimation) {
                var that = this,
                    shutterSettings,
                    options = that._options,
                    shutter = that._shutter,
                    isAnimation = options.behavior.animationEnabled && !disableAnimation,
                    sliderIndex = that.getIndex(),
                    canvas = options.canvas,
                    halfSliderHandleWidth = options.sliderHandle.width / 2,
                    width;
                if (!shutter)
                    return;
                if (sliderIndex === START_VALUE_INDEX) {
                    width = position - canvas.left - Math.floor(halfSliderHandleWidth);
                    if (width < 0)
                        width = 0;
                    shutterSettings = {
                        x: canvas.left,
                        y: canvas.top,
                        width: width,
                        height: canvas.height
                    }
                }
                else if (sliderIndex === END_VALUE_INDEX)
                    shutterSettings = {
                        x: position + Math.ceil(halfSliderHandleWidth),
                        y: canvas.top,
                        width: canvas.left + canvas.width - position,
                        height: canvas.height
                    };
                if (isAnimation)
                    shutter.animate(shutterSettings, rangeSelectorUtils.animationSettings);
                else
                    shutter.stopAnimation().attr(shutterSettings)
            },
            _setValid: function(isValid) {
                this._marker && this._marker.setValid(isValid);
                this._slider.setValid(isValid)
            },
            _setText: function(text) {
                this._marker && this._marker.setText(text)
            },
            _update: function() {
                var that = this,
                    options = that._options,
                    shutterOptions = options.shutter,
                    sliderHandleOptions = options.sliderHandle,
                    marker = that._marker;
                if (marker) {
                    marker.applyOptions(options.sliderMarker);
                    marker.setCanvas(that._options.canvas)
                }
                that._shutter && that._shutter.attr({
                    fill: shutterOptions.color,
                    "fill-opacity": shutterOptions.opacity
                });
                that._slider && that._slider.applyOptions({
                    "stroke-width": sliderHandleOptions.width,
                    stroke: sliderHandleOptions.color,
                    "stroke-opacity": sliderHandleOptions.opacity
                })
            },
            _draw: function(group) {
                var that = this,
                    slider,
                    marker,
                    sliderAreaGroup,
                    options = that._options,
                    renderer = that._renderer;
                that._container = sliderAreaGroup = renderer.g().attr({'class': 'sliderArea'}).append(group);
                slider = that._createSlider(sliderAreaGroup);
                if (options.sliderMarker.visible) {
                    marker = rangeSelector.rangeSelectorFactory.createSliderMarker({
                        renderer: renderer,
                        isLeftPointer: that.getIndex() === END_VALUE_INDEX,
                        sliderMarkerOptions: options.sliderMarker
                    });
                    marker.setCanvas(options.canvas);
                    marker.draw(slider)
                }
                that._slider = slider;
                that._marker = marker;
                that._sliderTracker = that._createSliderTracker(group)
            },
            toForeground: function() {
                this._container.toForeground()
            },
            _applyOptions: function() {
                this._lastPosition = null
            },
            getIndex: function() {
                return this._index
            },
            setAvailableValues: function(values) {
                this._values = values
            },
            setAnotherSlider: function(slider) {
                this._anotherSlider = slider
            },
            getAnotherSlider: function() {
                return this._anotherSlider
            },
            appendTrackers: function(group) {
                this._sliderTracker && this._sliderTracker.append(group)
            },
            getSliderTracker: function() {
                return this._sliderTracker
            },
            changeLocation: function() {
                var that = this;
                that._marker && that._marker.changeLocation();
                that._index = that._index === START_VALUE_INDEX ? END_VALUE_INDEX : START_VALUE_INDEX;
                if (that._options.scale.type === DISCRETE)
                    that.setPosition(that._position);
                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
            },
            setValue: function(value, correctByMinMaxRange, skipCorrection) {
                var that = this,
                    options = that._options,
                    canvas = options.canvas,
                    position,
                    text;
                if (value === undefined) {
                    that._value = undefined;
                    position = that.getIndex() === START_VALUE_INDEX ? canvas.left : canvas.left + canvas.width;
                    text = rangeSelector.consts.emptySliderMarkerText
                }
                else {
                    that._value = that._correctValue(value, correctByMinMaxRange, utils.isDefined(skipCorrection) ? !!skipCorrection : true);
                    position = options.translator.translate(that._value, that._getValueDirection());
                    text = rangeSelector.formatValue(that._value, options.sliderMarker)
                }
                that._setText(text);
                that._valuePosition = that._position = position
            },
            setOverlapped: function(isOverlapped) {
                this._marker && this._marker.setOverlapped(isOverlapped)
            },
            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 = that._addInterval(scale.endValue, scale.minRange, !scale.inverted);
                            if (!scale.inverted && anotherSliderValue > endValue || scale.inverted && anotherSliderValue < endValue)
                                return false
                        }
                        else {
                            startValue = that._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,
                    marker = that._marker,
                    tracker = marker && marker.getTracker(),
                    sliderTracker = that._sliderTracker;
                sliderTracker && sliderTracker.on(event, handler);
                tracker && tracker.on(event, handler)
            },
            createShutter: function() {
                var that = this,
                    index = that.getIndex(),
                    canvas = that._options.canvas,
                    renderer = that._renderer,
                    shutter = that._shutter;
                if (!shutter) {
                    if (index === START_VALUE_INDEX)
                        shutter = renderer.rect(canvas.left, canvas.top, 0, canvas.height);
                    else if (index === END_VALUE_INDEX)
                        shutter = renderer.rect(canvas.left, canvas.top, canvas.width, canvas.height);
                    that._shutter = shutter
                }
                shutter.append(that._container)
            },
            removeShutter: function() {
                var shutter = this._shutter;
                shutter && shutter.remove()
            },
            getCloudBorder: function() {
                return this._marker ? this._marker.getBorderPosition() : 0
            },
            dispose: function() {
                var marker = this._marker;
                marker && marker.dispose()
            }
        });
        rangeSelector.Slider = Slider
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file sliderMarker.js */
    (function($, DX, undefined) {
        var viz = DX.viz,
            core = viz.core,
            rangeSelector = viz.rangeSelector,
            SliderMarker,
            SLIDER_MARKER_UPDATE_DELAY = 75,
            POINTER_SIZE = rangeSelector.consts.pointerSize;
        var getRectSize = function(that, textSize) {
                var options = that._options;
                return {
                        width: Math.round(2 * options.paddingLeftRight + textSize.width),
                        height: Math.round(2 * options.paddingTopBottom + textSize.height)
                    }
            };
        var getAreaPointsInfo = function(that, textSize) {
                var rectSize = getRectSize(that, textSize),
                    rectWidth = rectSize.width,
                    rectHeight = rectSize.height,
                    rectLeftBorder = -rectWidth,
                    rectRightBorder = 0,
                    pointerRightPoint = POINTER_SIZE,
                    pointerCenterPoint = 0,
                    pointerLeftPoint = -POINTER_SIZE,
                    position = that._position,
                    canvas = that._canvas,
                    isLeft = that._isLeftPointer,
                    correctCloudBorders = function() {
                        rectLeftBorder++;
                        rectRightBorder++;
                        pointerRightPoint++;
                        pointerCenterPoint++;
                        pointerLeftPoint++
                    },
                    checkPointerBorders = function() {
                        if (pointerRightPoint > rectRightBorder)
                            pointerRightPoint = rectRightBorder;
                        else if (pointerLeftPoint < rectLeftBorder)
                            pointerLeftPoint = rectLeftBorder;
                        isLeft && correctCloudBorders()
                    },
                    borderPosition = position;
                if (isLeft)
                    if (position > canvas.left + canvas.width - rectWidth) {
                        rectRightBorder = -position + (canvas.left + canvas.width);
                        rectLeftBorder = rectRightBorder - rectWidth;
                        checkPointerBorders();
                        borderPosition += rectLeftBorder
                    }
                    else {
                        rectLeftBorder = pointerLeftPoint = 0;
                        rectRightBorder = rectWidth
                    }
                else if (position - canvas.left < rectWidth) {
                    rectLeftBorder = -(position - canvas.left);
                    rectRightBorder = rectLeftBorder + rectWidth;
                    checkPointerBorders();
                    borderPosition += rectRightBorder
                }
                else {
                    pointerRightPoint = 0;
                    correctCloudBorders()
                }
                that._borderPosition = borderPosition;
                return {
                        offset: rectLeftBorder,
                        isCutted: (!isLeft || pointerCenterPoint !== pointerLeftPoint) && (isLeft || pointerCenterPoint !== pointerRightPoint),
                        points: [rectLeftBorder, 0, rectRightBorder, 0, rectRightBorder, rectHeight, pointerRightPoint, rectHeight, pointerCenterPoint, rectHeight + POINTER_SIZE, pointerLeftPoint, rectHeight, rectLeftBorder, rectHeight]
                    }
            };
        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,
                        y: textSize.y
                    }
            };
        SliderMarker = rangeSelector.SliderMarker = function(options) {
            var that = this;
            that._renderer = options.renderer;
            that._text = options.text;
            that._isLeftPointer = options.isLeftPointer;
            that._options = $.extend(true, {}, options.sliderMarkerOptions);
            that._options.textFontStyles = core.utils.patchFontOptions(that._options.font);
            that._isValid = true;
            that._isOverlapped = false
        };
        SliderMarker.prototype = {
            constructor: SliderMarker,
            draw: function(group) {
                var that = this,
                    options = that._options,
                    sliderMarkerGroup = that._sliderMarkerGroup = that._renderer.g().attr({'class': 'sliderMarker'}).append(group);
                that._area = that._renderer.path([], "area").attr({fill: options.color}).append(sliderMarkerGroup);
                that._label = that._renderer.text(that._text, 0, 0).attr({align: 'left'}).css(options.textFontStyles).append(sliderMarkerGroup);
                that._tracker = that._renderer.rect(0, 0, 2 * options.paddingLeftRight, 2 * options.paddingTopBottom + POINTER_SIZE).attr(rangeSelector.utils.trackerSettings).css({cursor: 'pointer'}).append(sliderMarkerGroup);
                that._border = that._renderer.rect(0, 0, 1, 0).attr({fill: options.borderColor});
                that._drawn = true;
                that._update()
            },
            _update: function() {
                var that = this,
                    textSize,
                    options = that._options,
                    currentTextSize,
                    rectSize;
                clearTimeout(that._timeout);
                if (!that._drawn)
                    return;
                that._label.attr({text: that._text || ""});
                currentTextSize = getTextSize(that);
                rectSize = getRectSize(that, currentTextSize);
                textSize = that._textSize || currentTextSize;
                textSize = that._textSize = currentTextSize.width > textSize.width || currentTextSize.height > textSize.height ? currentTextSize : textSize;
                that._timeout = setTimeout(function() {
                    updateSliderMarker(currentTextSize, rectSize);
                    that._textSize = currentTextSize
                }, SLIDER_MARKER_UPDATE_DELAY);
                function updateSliderMarker(size, rectSize) {
                    var points,
                        pointsData,
                        offset;
                    rectSize = rectSize || getRectSize(that, size);
                    that._sliderMarkerGroup.attr({translateY: -(rectSize.height + POINTER_SIZE)});
                    pointsData = getAreaPointsInfo(that, size);
                    points = pointsData.points;
                    offset = pointsData.offset;
                    that._area.attr({points: points});
                    that._border.attr({
                        x: that._isLeftPointer ? points[0] - 1 : points[2],
                        height: pointsData.isCutted ? rectSize.height : rectSize.height + POINTER_SIZE
                    });
                    that._tracker.attr({
                        translateX: offset,
                        width: rectSize.width,
                        height: rectSize.height + POINTER_SIZE
                    });
                    that._label.attr({
                        translateX: options.paddingLeftRight + offset,
                        translateY: rectSize.height / 2 - (size.y + size.height / 2)
                    })
                }
                updateSliderMarker(textSize)
            },
            setText: function(value) {
                var that = this;
                if (that._text !== value)
                    that._text = value
            },
            setPosition: function(position) {
                this._position = position;
                this._update()
            },
            changeLocation: function() {
                var that = this;
                that._isLeftPointer = !that._isLeftPointer;
                that._update()
            },
            applyOptions: function(options) {
                var that = this,
                    fontSyles,
                    opt = that._options = $.extend(true, {}, options);
                fontSyles = opt.textFontStyles = core.utils.patchFontOptions(opt.font);
                that._textHeight = null;
                that._area.attr({fill: options.color});
                that._border.attr({fill: options.borderColor});
                that._label.css(fontSyles);
                that._update()
            },
            getTracker: function() {
                return this._tracker
            },
            setValid: function(isValid) {
                var that = this,
                    options = that._options;
                if (that._isValid !== isValid) {
                    that._isValid = isValid;
                    that._area.attr({fill: isValid ? options.color : options.invalidRangeColor})
                }
            },
            dispose: function() {
                clearTimeout(this._timeout)
            },
            setOverlapped: function(isOverlapped) {
                var border = this._border,
                    currentOverlappedState = this._isOverlapped;
                if (currentOverlappedState === isOverlapped)
                    return;
                if (isOverlapped)
                    border.append(this._sliderMarkerGroup);
                else
                    this._isOverlapped && border.remove();
                this._isOverlapped = isOverlapped
            },
            getBorderPosition: function() {
                return this._borderPosition
            },
            setCanvas: function(canvas) {
                this._canvas = canvas
            }
        };
        SliderMarker.prototype.updateDelay = SLIDER_MARKER_UPDATE_DELAY;
        SliderMarker.prototype.getText = function() {
            return this._text
        }
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file rangeView.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            RangeView,
            baseVisualElementMethods = rangeSelector.baseVisualElementMethods;
        RangeView = function() {
            baseVisualElementMethods.init.apply(this, arguments)
        };
        RangeView.prototype = $.extend({}, baseVisualElementMethods, {
            constructor: RangeView,
            _draw: function(group) {
                var that = this,
                    series,
                    i,
                    options = that._options,
                    isCompactMode = options.isCompactMode,
                    canvas = options.canvas,
                    isEmpty = options.isEmpty,
                    renderer = that._renderer,
                    seriesDataSource = options.seriesDataSource,
                    showChart = seriesDataSource && seriesDataSource.isShowChart() && !isEmpty,
                    background = options.background,
                    backgroundColor = showChart ? seriesDataSource.getBackgroundColor() : background.color,
                    backgroundImage = background.image,
                    backgroundIsVisible = background.visible;
                if (isCompactMode)
                    return;
                if (backgroundIsVisible && !isEmpty && backgroundColor)
                    renderer.rect(canvas.left, canvas.top, canvas.width + 1, canvas.height).attr({
                        fill: backgroundColor,
                        'class': 'dx-range-selector-background'
                    }).append(group);
                if (backgroundIsVisible && backgroundImage && backgroundImage.url)
                    renderer.image(canvas.left, canvas.top, canvas.width + 1, canvas.height, backgroundImage.url, backgroundImage.location).append(group);
                if (showChart) {
                    series = seriesDataSource.getSeries();
                    seriesDataSource.adjustSeriesDimensions(options.translators, options.chart.useAggregation);
                    for (i = 0; i < series.length; i++) {
                        series[i]._extGroups.seriesGroup = group;
                        series[i]._extGroups.labelsGroup = group;
                        series[i].draw(options.translators, options.behavior && options.behavior.animationEnabled && renderer.animationEnabled())
                    }
                }
            }
        });
        rangeSelector.RangeView = RangeView
    })(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,
            _SeriesDatasource;
        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 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 isStickType = function(type) {
                var nonStickTypes = ["bar", "candlestick", "stock", "bubble"],
                    stickType = true;
                type = type.toLowerCase();
                $.each(nonStickTypes, function(_, item) {
                    if (type.indexOf(item) !== -1) {
                        stickType = false;
                        return false
                    }
                });
                return stickType
            };
        function setTemplateFields(data, templateData, series) {
            $.each(data, function(_, data) {
                $.each(series.getTeamplatedFields(), function(_, field) {
                    data[field.teamplateField] = data[field.originalField]
                });
                templateData.push(data)
            });
            series.updateTeamplateFieldNames()
        }
        _SeriesDatasource = rangeSelector.SeriesDataSource = function(options) {
            var that = this,
                templatedSeries,
                seriesTemplate,
                themeManager = that._themeManager = createThemeManager(options.chart),
                topIndent,
                bottomIndent;
            themeManager._fontFields = ["commonSeriesSettings.label.font"];
            themeManager.setTheme(options.chart.theme);
            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 = that._calculateSeries(options, templatedSeries);
            that._seriesFamilies = processSeriesFamilies(that._series, themeManager.getOptions('equalBarWidth'), themeManager.getOptions('minBubbleSize'), themeManager.getOptions('maxBubbleSize'))
        };
        _SeriesDatasource.prototype = {
            constructor: _SeriesDatasource,
            _calculateSeries: function(options, templatedSeries) {
                var that = this,
                    series = [],
                    particularSeriesOptions,
                    seriesTheme,
                    data,
                    groupSeries,
                    parsedData,
                    chartThemeManager = that._themeManager,
                    hasSeriesTemplate = !!chartThemeManager.getOptions('seriesTemplate'),
                    allSeriesOptions = hasSeriesTemplate ? templatedSeries : options.chart.series,
                    seriesValueType = options.chart.valueAxis && options.chart.valueAxis.valueType,
                    dataSourceField,
                    i,
                    newSeries,
                    particularSeries;
                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;
                for (i = 0; i < allSeriesOptions.length; i++) {
                    particularSeriesOptions = $.extend(true, {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) {
                        newSeries = coreFactory.createSeries({renderer: options.renderer}, seriesTheme);
                        series.push(newSeries)
                    }
                    if (hasSeriesTemplate)
                        setTemplateFields(data, that.teamplateData, newSeries)
                }
                data = hasSeriesTemplate ? that.teamplateData : data;
                groupSeries = [series];
                groupSeries.argumentOptions = {
                    categories: options.categories,
                    argumentType: options.valueType,
                    type: options.axisType
                };
                groupSeries[0].valueOptions = {valueType: dataSourceField ? options.valueType : seriesValueType};
                that._dataValidator = core.CoreFactory.createDataValidator(data, groupSeries, options.incidentOccured, chartThemeManager.getOptions("dataPrepareSettings"));
                parsedData = that._dataValidator.validate();
                for (i = 0; i < series.length; i++) {
                    particularSeries = series[i];
                    particularSeries.updateData(parsedData)
                }
                return series
            },
            adjustSeriesDimensions: function(translators, useAggregation) {
                var that = this;
                if (useAggregation)
                    $.each(that._series || [], function(_, s) {
                        s.resamplePoints(translators.x)
                    });
                $.each(that._seriesFamilies, function(_, family) {
                    family.adjustSeriesDimensions({
                        arg: translators.x,
                        val: translators.y
                    })
                })
            },
            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,
                    minIndent,
                    maxIndent;
                $.each(that._series, function(_, series) {
                    rangeData = series.getRangeData();
                    valRange.addRange(rangeData.val);
                    argRange.addRange(rangeData.arg);
                    if (!isStickType(series.type))
                        argRange.addRange({stick: false})
                });
                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() {
                return this._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
            },
            getThemeManager: function() {
                return this._themeManager
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file themeManager.js */
    (function($, DX, undefined) {
        DX.viz.rangeSelector.ThemeManager = DX.viz.core.BaseThemeManager.inherit({
            _themeSection: 'rangeSelector',
            _fontFields: ['scale.label.font', 'sliderMarker.font', 'loadingIndicator.font']
        })
    })(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 _parseScalar = DX.viz.core.utils.parseScalar,
            DEFAULT_WIDTH = 800,
            DEFAULT_HEIGHT = 400,
            TOOLTIP_OFFSET = 12,
            _extend = $.extend,
            nextDataKey = 1;
        function generateDataKey() {
            return "vectormap-data-" + nextDataKey++
        }
        var Map = DX.viz.core.BaseWidget.inherit({
                _eventsMap: _extend({}, DX.viz.core.BaseWidget.prototype._eventsMap, {
                    onClick: {
                        name: "click",
                        deprecated: "click",
                        deprecatedContext: function(arg) {
                            return arg.component
                        },
                        deprecatedArgs: function(arg) {
                            return [arg.jQueryEvent]
                        }
                    },
                    click: {newName: "onClick"},
                    onCenterChanged: {
                        name: "centerChanged",
                        deprecated: "centerChanged",
                        deprecatedContext: function(arg) {
                            return arg.component
                        },
                        deprecatedArgs: function(arg) {
                            return [arg.center]
                        }
                    },
                    centerChanged: {newName: "onCenterChanged"},
                    onZoomFactorChanged: {
                        name: "zoomFactorChanged",
                        deprecated: "zoomFactorChanged",
                        deprecatedContext: function(arg) {
                            return arg.component
                        },
                        deprecatedArgs: function(arg) {
                            return [arg.zoomFactor]
                        }
                    },
                    zoomFactorChanged: {newName: "onZoomFactorChanged"},
                    onAreaClick: {
                        name: "areaClick",
                        deprecated: "areaSettings.click",
                        deprecatedContext: function(arg) {
                            return arg.target
                        },
                        deprecatedArgs: function(arg) {
                            return [arg.target, arg.jQueryEvent]
                        }
                    },
                    onAreaHoverChanged: {name: "areaHoverChanged"},
                    onAreaSelectionChanged: {
                        name: "areaSelectionChanged",
                        deprecated: "areaSettings.selectionChanged",
                        deprecatedContext: function(arg) {
                            return arg.target
                        },
                        deprecatedArgs: function(arg) {
                            return [arg.target]
                        }
                    },
                    onMarkerClick: {
                        name: "markerClick",
                        deprecated: "markerSettings.click",
                        deprecatedContext: function(arg) {
                            return arg.target
                        },
                        deprecatedArgs: function(arg) {
                            return [arg.target, arg.jQueryEvent]
                        }
                    },
                    onMarkerHoverChanged: {name: "markerHoverChanged"},
                    onMarkerSelectionChanged: {
                        name: "markerSelectionChanged",
                        deprecated: "markerSettings.selectionChanged",
                        deprecatedContext: function(arg) {
                            return arg.target
                        },
                        deprecatedArgs: function(arg) {
                            return [arg.target]
                        }
                    }
                }),
                _setDeprecatedOptions: function() {
                    this.callBase();
                    $.extend(this._deprecatedOptions, {
                        click: {
                            since: "14.2",
                            message: 'Use the "onClick" option instead'
                        },
                        centerChanged: {
                            since: "14.2",
                            message: 'Use the "onCenterChanged" option instead'
                        },
                        zoomFactorChanged: {
                            since: "14.2",
                            message: 'Use the "onZoomFactorChanged" option instead'
                        },
                        "areaSettings.click": {
                            since: "14.2",
                            message: 'Use the "onAreaClick" option instead'
                        },
                        "areaSettings.selectionChanged": {
                            since: "14.2",
                            message: 'Use the "onAreaSelectionChanged" option instead'
                        },
                        "markerSettings.click": {
                            since: "14.2",
                            message: 'Use the "onMarkerClick" option instead'
                        },
                        "markerSettings.selectionChanged": {
                            since: "14.2",
                            message: 'Use the "onMarkerSelectionChanged" option instead'
                        },
                        "markerSettings.font": {
                            since: "14.2",
                            message: 'Use the "label.font" option instead'
                        }
                    })
                },
                _rootClassPrefix: "dxm",
                _rootClass: "dxm-vector-map",
                _createThemeManager: function() {
                    return this._factory.createThemeManager()
                },
                _initBackground: function(dataKey) {
                    this._background = this._renderer.rect(0, 0, 0, 0).attr({"class": "dxm-background"}).data(dataKey, {type: "background"})
                },
                _initAreasManager: function(dataKey, notifyDirty, notifyReady) {
                    var that = this;
                    that._areasManager = that._factory.createAreasManager({
                        container: that._root,
                        renderer: that._renderer,
                        projection: that._projection,
                        themeManager: that._themeManager,
                        tracker: that._tracker,
                        dataKey: dataKey,
                        eventTrigger: that._eventTrigger,
                        dataExchanger: that._dataExchanger,
                        notifyDirty: notifyDirty,
                        notifyReady: notifyReady
                    })
                },
                _initMarkersManager: function(dataKey, notifyDirty, notifyReady) {
                    var that = this;
                    that._markersManager = that._factory.createMarkersManager({
                        container: that._root,
                        renderer: that._renderer,
                        projection: that._projection,
                        themeManager: that._themeManager,
                        tracker: that._tracker,
                        eventTrigger: that._eventTrigger,
                        dataExchanger: that._dataExchanger,
                        dataKey: dataKey,
                        notifyDirty: notifyDirty,
                        notifyReady: notifyReady
                    })
                },
                _initLegendsControl: function() {
                    var that = this;
                    that._legendsControl = that._factory.createLegendsControl({
                        container: that._root,
                        renderer: that._renderer,
                        layoutControl: that._layoutControl,
                        dataExchanger: that._dataExchanger
                    })
                },
                _initControlBar: function(dataKey) {
                    var that = this;
                    that._controlBar = that._factory.createControlBar({
                        container: that._root,
                        renderer: that._renderer,
                        layoutControl: that._layoutControl,
                        projection: that._projection,
                        dataKey: dataKey
                    })
                },
                _initElements: function() {
                    var that = this,
                        dataKey = generateDataKey(),
                        notifyCounter = 0;
                    that._dataExchanger = new DataExchanger;
                    that._initCenterHandler();
                    that._projection = that._factory.createProjection();
                    that._tracker = that._factory.createTracker({
                        root: that._root,
                        projection: that._projection,
                        dataKey: dataKey
                    });
                    that._layoutControl = that._factory.createLayoutControl();
                    that._initBackground(dataKey);
                    that._initAreasManager(dataKey, notifyDirty, notifyReady);
                    that._initMarkersManager(dataKey, notifyDirty, notifyReady);
                    that._initLegendsControl();
                    that._initControlBar(dataKey);
                    function notifyDirty() {
                        that._resetIsReady();
                        ++notifyCounter
                    }
                    function notifyReady() {
                        if (--notifyCounter === 0) {
                            that._drawn();
                            that.hideLoadingIndicator()
                        }
                    }
                },
                _initCore: function() {
                    var that = this;
                    that._root = that._renderer.root;
                    that._root.attr({
                        align: 'center',
                        cursor: 'default'
                    });
                    that._initElements();
                    that._projection.setBounds(that.option("bounds")).setMaxZoom(that.option("maxZoomFactor")).setZoom(that.option("zoomFactor"), true).setCenter(that.option("center"), true);
                    that._setTrackerCallbacks();
                    that._setControlBarCallbacks();
                    that._setProjectionCallbacks()
                },
                _init: function() {
                    var that = this;
                    that.callBase.apply(that, arguments);
                    that._areasManager.setData(that.option("mapData"));
                    that._markersManager.setData(that.option("markers"))
                },
                _disposeCore: function() {
                    var that = this;
                    that._resetProjectionCallbacks();
                    that._resetTrackerCallbacks();
                    that._resetControlBarCallbacks();
                    that._tracker.dispose();
                    that._legendsControl.dispose();
                    that._areasManager.dispose();
                    that._markersManager.dispose();
                    that._controlBar.dispose();
                    that._layoutControl.dispose();
                    that._disposeCenterHandler();
                    that._dataExchanger.dispose();
                    that._projection.dispose();
                    that._dataExchanger = that._projection = that._tracker = that._layoutControl = that._root = that._background = that._areasManager = that._markersManager = that._controlBar = that._legendsControl = null
                },
                _initCenterHandler: function() {
                    var that = this,
                        xdrag,
                        ydrag,
                        isCursorChanged = false;
                    that._centerHandler = {
                        processStart: function(arg) {
                            if (that._centeringEnabled) {
                                xdrag = arg.x;
                                ydrag = arg.y;
                                that._noCenterChanged = true
                            }
                        },
                        processMove: function(arg) {
                            if (that._centeringEnabled) {
                                if (!isCursorChanged) {
                                    that._root.attr({cursor: "move"});
                                    isCursorChanged = true
                                }
                                that._projection.moveCenter(xdrag - arg.x, ydrag - arg.y);
                                xdrag = arg.x;
                                ydrag = arg.y
                            }
                        },
                        processEnd: function() {
                            if (that._centeringEnabled) {
                                that._root.attr({cursor: "default"});
                                that._noCenterChanged = null;
                                isCursorChanged && that._raiseCenterChanged();
                                isCursorChanged = false
                            }
                        }
                    }
                },
                _disposeCenterHandler: function() {
                    this._centerHandler = null
                },
                _setProjectionCallbacks: function() {
                    var that = this;
                    that._projection.on({
                        center: function() {
                            that._raiseCenterChanged()
                        },
                        zoom: function() {
                            that._raiseZoomFactorChanged()
                        }
                    });
                    that._resetProjectionCallbacks = function() {
                        that._resetProjectionCallbacks = that = null
                    }
                },
                _setTrackerCallbacks: function() {
                    var that = this,
                        centerHandler = that._centerHandler,
                        renderer = that._renderer,
                        managers = {
                            area: that._areasManager,
                            marker: that._markersManager
                        },
                        controlBar = that._controlBar,
                        tooltip = that._tooltip,
                        isControlDrag = false;
                    that._tracker.setCallbacks({
                        click: function(arg) {
                            var offset = renderer.getRootOffset(),
                                manager;
                            arg.$event.x = arg.x - offset.left;
                            arg.$event.y = arg.y - offset.top;
                            manager = managers[arg.data.type];
                            if (manager)
                                manager.raiseClick(arg.data.index, arg.$event);
                            if (manager || arg.data.type === "background")
                                that._eventTrigger("click", {jQueryEvent: arg.$event})
                        },
                        start: function(arg) {
                            isControlDrag = arg.data.type === "control-bar";
                            if (isControlDrag) {
                                arg.data = arg.data.index;
                                controlBar.processStart(arg)
                            }
                            else
                                centerHandler.processStart(arg)
                        },
                        move: function(arg) {
                            if (isControlDrag) {
                                arg.data = arg.data.index;
                                controlBar.processMove(arg)
                            }
                            else
                                centerHandler.processMove(arg)
                        },
                        end: function(arg) {
                            if (isControlDrag) {
                                arg.data = arg.data.index;
                                controlBar.processEnd(arg);
                                isControlDrag = false
                            }
                            else
                                centerHandler.processEnd()
                        },
                        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,
                                proxy;
                            if (tooltip.isEnabled()) {
                                proxy = managers[arg.data.type] ? managers[arg.data.type].getProxyItem(arg.data.index) : null;
                                if (proxy && tooltip.show(proxy, {
                                    x: 0,
                                    y: 0,
                                    offset: 0
                                }, {target: proxy})) {
                                    tooltip.move(arg.x, arg.y, TOOLTIP_OFFSET);
                                    result = true
                                }
                            }
                            done(result)
                        },
                        "focus-move": function(arg) {
                            tooltip.move(arg.x, arg.y, TOOLTIP_OFFSET)
                        },
                        "focus-off": function() {
                            tooltip.hide()
                        }
                    });
                    that._resetTrackerCallbacks = function() {
                        that._resetTrackerCallbacks = that = centerHandler = renderer = managers = controlBar = tooltip = null
                    }
                },
                _setControlBarCallbacks: function() {
                    var that = this,
                        projection = that._projection,
                        isZoomChanged;
                    that._projection.on({zoom: function() {
                            isZoomChanged = true
                        }});
                    that._controlBar.setCallbacks({
                        reset: function(isCenter, isZoom) {
                            if (isCenter)
                                projection.setCenter(null);
                            if (isZoom)
                                projection.setZoom(null)
                        },
                        beginMove: function() {
                            that._noCenterChanged = true
                        },
                        endMove: function() {
                            that._noCenterChanged = null;
                            that._raiseCenterChanged()
                        },
                        move: function(dx, dy) {
                            projection.moveCenter(dx, dy)
                        },
                        zoom: function(zoom, center) {
                            var coords,
                                screenPosition;
                            if (center) {
                                screenPosition = that._renderer.getRootOffset();
                                screenPosition = [center[0] - screenPosition.left, center[1] - screenPosition.top];
                                coords = projection.fromScreenPoint(screenPosition[0], screenPosition[1])
                            }
                            isZoomChanged = false;
                            projection.setScaledZoom(zoom);
                            if (isZoomChanged && center)
                                projection.setCenterByPoint(coords, screenPosition)
                        }
                    });
                    that._resetControlBarCallbacks = function() {
                        that._resetControlBarCallbacks = that = projection = null
                    }
                },
                _setupInteraction: function() {
                    var that = this;
                    that._centerHandler.processEnd();
                    that._centeringEnabled = !!_parseScalar(this._getOption("panningEnabled", true), true);
                    that._zoomingEnabled = !!_parseScalar(this._getOption("zoomingEnabled", true), true);
                    that._controlBar.setInteraction({
                        centeringEnabled: that._centeringEnabled,
                        zoomingEnabled: that._zoomingEnabled
                    })
                },
                _getDefaultSize: function() {
                    return {
                            width: DEFAULT_WIDTH,
                            height: DEFAULT_HEIGHT
                        }
                },
                _applySize: function() {
                    var that = this,
                        width = that._canvas.width,
                        height = that._canvas.height;
                    that._projection.setSize(width, height);
                    that._layoutControl.setSize(width, height);
                    that._background.attr({
                        x: 0,
                        y: 0,
                        width: width,
                        height: height
                    })
                },
                _resize: $.noop,
                _clean: function() {
                    var that = this;
                    that._tracker.reset();
                    that._layoutControl.stop();
                    that._background.remove();
                    that._areasManager.clean();
                    that._markersManager.clean();
                    that._controlBar.clean();
                    that._legendsControl.clean()
                },
                _render: function() {
                    var that = this;
                    that._background.append(that._root);
                    that._areasManager.render();
                    that._markersManager.render();
                    that._controlBar.render();
                    that._legendsControl.render();
                    that._layoutControl.start()
                },
                _optionChanged: function(args) {
                    var that = this,
                        value = args.value;
                    switch (args.name) {
                        case"mapData":
                            that._areasManager.setData(value);
                            break;
                        case"markers":
                            that._markersManager.setData(value);
                            break;
                        case"bounds":
                            that._projection.setBounds(value);
                            break;
                        case"maxZoomFactor":
                            that._projection.setMaxZoom(value);
                            break;
                        case"zoomFactor":
                            that._projection.setZoom(value);
                            break;
                        case"center":
                            that._projection.setCenter(value);
                            break;
                        case"background":
                            that._setBackgroundOptions();
                            break;
                        case"areaSettings":
                            that._setAreasManagerOptions();
                            break;
                        case"markerSettings":
                            that._setMarkersManagerOptions();
                            break;
                        case"controlBar":
                            that._setControlBarOptions();
                            break;
                        case"legends":
                            that._setLegendsOptions();
                            break;
                        case"touchEnabled":
                        case"wheelEnabled":
                            that._setTrackerOptions();
                            break;
                        case"panningEnabled":
                        case"zoomingEnabled":
                            that._setupInteraction();
                            break;
                        default:
                            that.callBase.apply(that, arguments);
                            break
                    }
                },
                _handleThemeOptionsCore: function() {
                    var that = this;
                    that._setBackgroundOptions();
                    that._setAreasManagerOptions();
                    that._setMarkersManagerOptions();
                    that._setControlBarOptions();
                    that._setLegendsOptions();
                    that._setTrackerOptions();
                    that._setupInteraction()
                },
                _setBackgroundOptions: function() {
                    var settings = this._getOption("background");
                    this._background.attr({
                        "stroke-width": settings.borderWidth,
                        stroke: settings.borderColor,
                        fill: settings.color
                    })
                },
                _setAreasManagerOptions: function() {
                    this._areasManager.setOptions(this.option("areaSettings"));
                    this._eventTrigger.update("onAreaClick");
                    this._eventTrigger.update("onAreaSelectionChanged")
                },
                _setMarkersManagerOptions: function() {
                    this._markersManager.setOptions(this.option("markerSettings"));
                    this._eventTrigger.update("onMarkerClick");
                    this._eventTrigger.update("onMarkerSelectionChanged")
                },
                _setControlBarOptions: function() {
                    this._controlBar.setOptions(this._getOption("controlBar"))
                },
                _setLegendsOptions: function() {
                    this._legendsControl.setOptions(this.option("legends"), this._themeManager.theme("legend"))
                },
                _setTrackerOptions: function() {
                    this._tracker.setOptions({
                        touchEnabled: this._getOption("touchEnabled", true),
                        wheelEnabled: this._getOption("wheelEnabled", true)
                    })
                },
                _raiseCenterChanged: function() {
                    !this._noCenterChanged && this._eventTrigger("centerChanged", {center: this._projection.getCenter()})
                },
                _raiseZoomFactorChanged: function() {
                    !this._noZoomFactorChanged && this._eventTrigger("zoomFactorChanged", {zoomFactor: this._projection.getZoom()})
                },
                _refresh: function() {
                    var that = this,
                        callBase = that.callBase;
                    that._endLoading(function() {
                        callBase.call(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) {
                    var that = this;
                    if (value === undefined)
                        return that._projection.getCenter();
                    else {
                        that._noCenterChanged = _noEvent;
                        that._projection.setCenter(value);
                        that._noCenterChanged = null;
                        return that
                    }
                },
                zoomFactor: function(value, _noEvent) {
                    var that = this;
                    if (value === undefined)
                        return that._projection.getZoom();
                    else {
                        that._noZoomFactorChanged = _noEvent;
                        that._projection.setZoom(value);
                        that._noZoomFactorChanged = null;
                        return that
                    }
                },
                viewport: function(value, _noEvent) {
                    var that = this;
                    if (value === undefined)
                        return that._projection.getViewport();
                    else {
                        that._noCenterChanged = that._noZoomFactorChanged = _noEvent;
                        that._projection.setViewport(value);
                        that._noCenterChanged = that._noZoomFactorChanged = null;
                        return that
                    }
                },
                convertCoordinates: function(x, y) {
                    return this._projection.fromScreenPoint(x, y)
                },
                _factory: {}
            });
        var DataExchanger = function() {
                this._store = {}
            };
        DataExchanger.prototype = {
            constructor: DataExchanger,
            dispose: function() {
                this._store = null;
                return this
            },
            _get: function(category, name) {
                var store = this._store[category] || (this._store[category] = {});
                return store[name] || (store[name] = {})
            },
            set: function(category, name, data) {
                var item = this._get(category, name);
                item.data = data;
                item.callback && item.callback(data);
                return this
            },
            bind: function(category, name, callback) {
                var item = this._get(category, name);
                item.callback = callback;
                item.data && callback(item.data);
                return this
            },
            unbind: function(category, name) {
                var item = this._get(category, name);
                item.data = item.callback = null;
                return this
            }
        };
        DX.registerComponent("dxVectorMap", DX.viz.map, Map);
        DX.viz.map._internal = {};
        DX.viz.map.sources = {};
        DX.viz.map._tests = {};
        DX.viz.map._tests.DataExchanger = DataExchanger;
        DX.viz.map._tests.stubDataExchanger = function(stub) {
            DataExchanger = stub
        }
    })(DevExpress, jQuery);
    /*! Module viz-vectormap, file projection.js */
    (function(DX, $, undefined) {
        var _Number = Number,
            _isArray = DX.utils.isArray,
            _math = Math,
            _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,
            PI = _math.PI,
            QUARTER_PI = PI / 4,
            PI_TO_360 = PI / 360,
            TWO_TO_LN2 = 2 / _math.LN2,
            MIN_BOUNDS_RANGE = 1 / 3600 / 180 / 10,
            DEFAULT_MIN_ZOOM = 1,
            DEFAULT_MAX_ZOOM = 1 << 8,
            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 = truncateQuad(quad, min, max);
            return {
                    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._events = {
                project: $.Callbacks(),
                transform: $.Callbacks(),
                center: $.Callbacks(),
                zoom: $.Callbacks(),
                "max-zoom": $.Callbacks()
            };
            this.setBounds(null)
        }
        Projection.prototype = {
            constructor: Projection,
            _minZoom: DEFAULT_MIN_ZOOM,
            _maxZoom: DEFAULT_MAX_ZOOM,
            _zoom: DEFAULT_MIN_ZOOM,
            _center: [NaN, NaN],
            dispose: function() {
                this._events = null;
                return this
            },
            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
                }
                that._events["transform"].fire(that.getTransform());
                return that
            },
            setBounds: function(bounds) {
                var that = this,
                    _bounds = parseBounds(bounds),
                    p1,
                    p2,
                    delta,
                    methods;
                that._minBound = _bounds.min;
                that._maxBound = _bounds.max;
                p1 = mercator.project(_bounds.min);
                p2 = mercator.project(_bounds.max);
                delta = [_abs(p2[0] - p1[0]), _abs(p2[1] - p1[1])];
                delta = _min(delta[0] > MIN_BOUNDS_RANGE ? delta[0] : 2, delta[1] > MIN_BOUNDS_RANGE ? delta[1] : 2);
                methods = delta < 2 ? createProjectUnprojectMethods(p1, p2, delta) : mercator;
                that._project = methods.project;
                that._unproject = methods.unproject;
                that._defaultCenter = that._unproject([0, 0]);
                that.setCenter(that._defaultCenter);
                that._events.project.fire();
                return that
            },
            _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(partialPath)
                }
                return list
            },
            getPointCoordinates: function(data) {
                var point = this._toScreen(this._toTransformedFast(data));
                return {
                        x: _round(point[0]),
                        y: _round(point[1])
                    }
            },
            getSquareSize: function(size) {
                return [size[0] * this._zoom * this._xradius, size[1] * this._zoom * this._yradius]
            },
            getZoom: function() {
                return this._zoom
            },
            setZoom: function(zoom, _forceEvent) {
                var that = this,
                    zoom__ = that._zoom;
                that._zoom = truncate(zoom, that._minZoom, that._maxZoom, that._minZoom);
                that._adjustCenter();
                if (!floatsEqual(zoom__, that._zoom) || _forceEvent)
                    that._events.zoom.fire(that.getZoom(), that.getTransform());
                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)),
                    step,
                    zoom,
                    i = 1;
                k = k > 4 ? k : 4;
                step = _pow(that._maxZoom, 1 / k);
                zoom = that._minZoom;
                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);
                that._events["max-zoom"].fire(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, _forceEvent) {
                var that = this,
                    _center = _isArray(center) ? center : [],
                    center__ = that._center;
                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();
                if (!floatsEqual(center__[0], that._center[0]) || !floatsEqual(center__[1], that._center[1]) || _forceEvent)
                    that._events.center.fire(that.getCenter(), that.getTransform());
                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._minBound, that._maxBound),
                    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])))
            },
            on: function(obj) {
                $.each(this._events, function(name, list) {
                    obj[name] && list.add(obj[name])
                });
                return this
            }
        };
        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.dxVectorMap.prototype._factory.createProjection = function() {
            return new Projection
        }
    })(DevExpress, jQuery);
    /*! Module viz-vectormap, file controlBar.js */
    (function(DX, undefined) {
        var _Number = Number,
            _math = Math,
            _round = _math.round,
            _floor = _math.floor,
            _pow = _math.pow,
            _ln = _math.log,
            _LN2 = _math.LN2,
            utils = DX.viz.core.utils,
            _parseScalar = utils.parseScalar,
            parseHorizontalAlignment = utils.enumParser(["left", "center", "right"]),
            parseVerticalAlignment = utils.enumParser(["top", "bottom"]),
            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_LINE = "command-zoom-drag-line",
            COMMAND_ZOOM_DRAG = "command-zoom-drag",
            EVENT_TARGET_TYPE = "control-bar",
            FLAG_CENTERING = 1,
            FLAG_ZOOMING = 2,
            SIZE_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
            },
            OFFSET_X = 30.5,
            OFFSET_Y = 30.5,
            TOTAL_WIDTH = 61,
            TOTAL_HEIGHT = 274,
            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({
                _flags: 0,
                ctor: function(parameters) {
                    var that = this;
                    that._params = parameters;
                    that._createElements(parameters.renderer, parameters.dataKey);
                    parameters.layoutControl.addItem(that);
                    that._subscribeToProjection(parameters.projection);
                    that._setVisibility(false)
                },
                setCallbacks: function(callbacks) {
                    this._callbacks = callbacks;
                    return this
                },
                _createElements: function(renderer, dataKey) {
                    var that = this,
                        buttonsGroups,
                        trackersGroup;
                    that._root = renderer.g().attr({"class": "dxm-control-bar"});
                    buttonsGroups = that._buttonsGroup = renderer.g().attr({"class": "dxm-control-buttons"}).append(that._root);
                    trackersGroup = renderer.g().attr({
                        stroke: "none",
                        "stroke-width": 0,
                        fill: "#000000",
                        opacity: 0.0001
                    }).css({cursor: "pointer"}).append(that._root);
                    that._createButtons(renderer, dataKey, buttonsGroups);
                    that._createTrackers(renderer, dataKey, trackersGroup)
                },
                _createButtons: function(renderer, dataKey, group) {
                    var that = this,
                        options = SIZE_OPTIONS,
                        size = options.buttonSize / 2,
                        offset1 = options.arrowButtonOffset - size,
                        offset2 = options.arrowButtonOffset,
                        incdecButtonSize = options.incdecButtonSize / 2,
                        directionOptions = {
                            "stroke-linecap": "square",
                            fill: "none"
                        },
                        line = "line";
                    renderer.circle(0, 0, options.bigCircleSize / 2).append(group);
                    renderer.circle(0, 0, size).attr({fill: "none"}).append(group);
                    renderer.path([-size, -offset1, 0, -offset2, size, -offset1], line).attr(directionOptions).append(group);
                    renderer.path([offset1, -size, offset2, 0, offset1, size], line).attr(directionOptions).append(group);
                    renderer.path([size, offset1, 0, offset2, -size, offset1], line).attr(directionOptions).append(group);
                    renderer.path([-offset1, size, -offset2, 0, -offset1, -size], line).attr(directionOptions).append(group);
                    renderer.circle(0, options.incButtonOffset, options.smallCircleSize / 2).append(group);
                    renderer.path([[-incdecButtonSize, options.incButtonOffset, incdecButtonSize, options.incButtonOffset], [0, options.incButtonOffset - incdecButtonSize, 0, options.incButtonOffset + incdecButtonSize]], "area").append(group);
                    renderer.circle(0, options.decButtonOffset, options.smallCircleSize / 2).append(group);
                    renderer.path([-incdecButtonSize, options.decButtonOffset, incdecButtonSize, options.decButtonOffset], "area").append(group);
                    that._progressBar = renderer.path([], "area").append(group);
                    that._zoomDrag = renderer.rect(_floor(-options.sliderLength / 2), _floor(options.sliderLineEndOffset - options.sliderWidth / 2), options.sliderLength, options.sliderWidth).append(group);
                    that._sliderLineLength = options.sliderLineEndOffset - options.sliderLineStartOffset
                },
                _createTrackers: function(renderer, dataKey, group) {
                    var options = SIZE_OPTIONS,
                        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;
                    renderer.rect(-size, -size, size * 2, size * 2).data(dataKey, {
                        index: COMMAND_RESET,
                        type: EVENT_TARGET_TYPE
                    }).append(group);
                    renderer.rect(-size, -offset2, size * 2, size2).data(dataKey, {
                        index: COMMAND_MOVE_UP,
                        type: EVENT_TARGET_TYPE
                    }).append(group);
                    renderer.rect(offset1, -size, size2, size * 2).data(dataKey, {
                        index: COMMAND_MOVE_RIGHT,
                        type: EVENT_TARGET_TYPE
                    }).append(group);
                    renderer.rect(-size, offset1, size * 2, size2).data(dataKey, {
                        index: COMMAND_MOVE_DOWN,
                        type: EVENT_TARGET_TYPE
                    }).append(group);
                    renderer.rect(-offset2, -size, size2, size * 2).data(dataKey, {
                        index: COMMAND_MOVE_LEFT,
                        type: EVENT_TARGET_TYPE
                    }).append(group);
                    renderer.circle(0, options.incButtonOffset, options.smallCircleSize / 2).data(dataKey, {
                        index: COMMAND_ZOOM_IN,
                        type: EVENT_TARGET_TYPE
                    }).append(group);
                    renderer.circle(0, options.decButtonOffset, options.smallCircleSize / 2).data(dataKey, {
                        index: COMMAND_ZOOM_OUT,
                        type: EVENT_TARGET_TYPE
                    }).append(group);
                    renderer.rect(-2, options.sliderLineStartOffset - 2, 4, options.sliderLineEndOffset - options.sliderLineStartOffset + 4).css({cursor: "default"}).data(dataKey, {
                        index: COMMAND_ZOOM_DRAG_LINE,
                        type: EVENT_TARGET_TYPE
                    }).append(group);
                    this._zoomDragCover = renderer.rect(-options.sliderLength / 2, options.sliderLineEndOffset - options.sliderWidth / 2, options.sliderLength, options.sliderWidth).data(dataKey, {
                        index: COMMAND_ZOOM_DRAG,
                        type: EVENT_TARGET_TYPE
                    }).append(group)
                },
                _subscribeToProjection: function(projection) {
                    var that = this;
                    projection.on({
                        zoom: function() {
                            that._adjustZoom(projection.getScaledZoom())
                        },
                        "max-zoom": function() {
                            that._zoomPartition = projection.getZoomScalePartition();
                            that._sliderUnitLength = that._sliderLineLength / that._zoomPartition;
                            that._adjustZoom(projection.getScaledZoom())
                        }
                    })
                },
                dispose: function() {
                    var that = this;
                    that._params.layoutControl.removeItem(that);
                    that._root.clear();
                    that._params = that._callbacks = that._root = that._buttonsGroup = that._zoomDrag = that._zoomDragCover = that._progressBar = null;
                    return that
                },
                resize: function(size) {
                    this._setVisibility(size !== null && this._options.enabled && this._flags);
                    return this
                },
                _setVisibility: function(state) {
                    this._root.attr({visibility: state ? null : "hidden"})
                },
                getLayoutOptions: function() {
                    var options = this._options;
                    return this._rendered && options.enabled && this._flags ? {
                            width: 2 * options.margin + TOTAL_WIDTH,
                            height: 2 * options.margin + TOTAL_HEIGHT,
                            horizontalAlignment: options.horizontalAlignment,
                            verticalAlignment: options.verticalAlignment
                        } : null
                },
                locate: function(x, y) {
                    this._root.attr({
                        translateX: x + this._options.margin + OFFSET_X,
                        translateY: y + this._options.margin + OFFSET_Y
                    });
                    return this
                },
                setInteraction: function(interaction) {
                    var that = this;
                    that.processEnd();
                    if (_parseScalar(interaction.centeringEnabled, true))
                        that._flags |= FLAG_CENTERING;
                    else
                        that._flags &= ~FLAG_CENTERING;
                    if (_parseScalar(interaction.zoomingEnabled, true))
                        that._flags |= FLAG_ZOOMING;
                    else
                        that._flags &= ~FLAG_ZOOMING;
                    if (that._rendered)
                        that._refresh();
                    return that
                },
                setOptions: function(options) {
                    var that = this;
                    that.processEnd();
                    that._buttonsGroup.attr({
                        "stroke-width": options.borderWidth,
                        stroke: options.borderColor,
                        fill: options.color,
                        "fill-opacity": options.opacity
                    });
                    that._options = {
                        enabled: !!_parseScalar(options.enabled, true),
                        margin: options.margin > 0 ? _Number(options.margin) : 0,
                        horizontalAlignment: parseHorizontalAlignment(options.horizontalAlignment, "left"),
                        verticalAlignment: parseVerticalAlignment(options.verticalAlignment, "top")
                    };
                    that._rendered && that._refresh();
                    return that
                },
                _refresh: function() {
                    var isVisible = this._flags && this._options.enabled;
                    this._setVisibility(isVisible);
                    if (isVisible)
                        this.updateLayout()
                },
                clean: function() {
                    var that = this;
                    that._rendered = null;
                    that._root.remove();
                    return that
                },
                render: function() {
                    var that = this;
                    that._rendered = true;
                    that._root.append(that._params.container);
                    that._refresh();
                    return that
                },
                _adjustZoom: function(zoom) {
                    var that = this,
                        transform,
                        y,
                        start = SIZE_OPTIONS.sliderLineStartOffset,
                        end = SIZE_OPTIONS.sliderLineEndOffset,
                        h = SIZE_OPTIONS.sliderWidth;
                    that._zoomFactor = _round(zoom);
                    that._zoomFactor >= 0 || (that._zoomFactor = 0);
                    that._zoomFactor <= that._zoomPartition || (that._zoomFactor = that._zoomPartition);
                    transform = {translateY: -that._zoomFactor * that._sliderUnitLength};
                    y = end - h / 2 + transform.translateY;
                    that._progressBar.attr({points: [[0, start, 0, _math.max(start, y)], [0, _math.min(end, y + h), 0, end]]});
                    that._zoomDrag.attr(transform);
                    that._zoomDragCover.attr(transform)
                },
                _applyZoom: function(center) {
                    this._callbacks.zoom(this._zoomFactor, this._flags & FLAG_CENTERING ? center : undefined)
                },
                processStart: function(arg) {
                    var commandType = COMMAND_TO_TYPE_MAP[arg.data];
                    this._command = commandType && this._options.enabled && commandType.flags & this._flags ? new commandType(this, arg) : null;
                    return this
                },
                processMove: function(arg) {
                    this._command && this._command.update(arg);
                    return this
                },
                processEnd: function() {
                    this._command && this._command.finish();
                    this._command = null;
                    return this
                },
                processZoom: function(arg) {
                    var that = this,
                        zoomFactor;
                    if (that._flags & FLAG_ZOOMING) {
                        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.flags = FLAG_CENTERING | FLAG_ZOOMING;
        ResetCommand.prototype.update = function(arg) {
            arg.data !== this._command && disposeCommand(this)
        };
        ResetCommand.prototype.finish = function() {
            var flags = this._owner._flags;
            this._owner._callbacks.reset(!!(flags & FLAG_CENTERING), !!(flags & FLAG_ZOOMING));
            if (flags & FLAG_ZOOMING)
                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._callbacks.move(dx, dy);
                timeout = setTimeout(callback, interval)
            }
            this._stop = function() {
                clearTimeout(timeout);
                owner._callbacks.endMove();
                this._stop = owner = null;
                return this
            };
            arg = null;
            owner._callbacks.beginMove();
            callback()
        }
        MoveCommand.flags = FLAG_CENTERING;
        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 = null;
                return this
            };
            arg = null;
            callback()
        }
        ZoomCommand.flags = FLAG_ZOOMING;
        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.flags = FLAG_ZOOMING;
        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;
        var COMMAND_TO_TYPE_MAP__ORIGINAL = COMMAND_TO_TYPE_MAP;
        DX.viz.map._tests.stubCommandToTypeMap = function(map) {
            COMMAND_TO_TYPE_MAP = map
        };
        DX.viz.map._tests.restoreCommandToTypeMap = function() {
            COMMAND_TO_TYPE_MAP = COMMAND_TO_TYPE_MAP__ORIGINAL
        };
        DX.viz.map.dxVectorMap.prototype._factory.createControlBar = function(parameters) {
            return new ControlBar(parameters)
        }
    })(DevExpress);
    /*! Module viz-vectormap, file tracker.js */
    (function(DX, $, undefined) {
        var _math = Math,
            _abs = _math.abs,
            _sqrt = _math.sqrt,
            _round = _math.round,
            _addNamespace = DX.ui.events.addNamespace,
            _parseScalar = DX.viz.core.utils.parseScalar,
            _now = $.now,
            _NAME = DX.viz.map.dxVectorMap.prototype.NAME,
            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",
            CLICK_TIME_THRESHOLD = 500,
            CLICK_COORD_THRESHOLD_MOUSE = 5,
            CLICK_COORD_THRESHOLD_TOUCH = 20,
            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,
            WHEEL_COOLDOWN = 50,
            WHEEL_DIRECTION_COOLDOWN = 300;
        function Tracker(parameters) {
            var that = this;
            that._root = parameters.root;
            that._callbacks = {};
            that._createEventHandlers(parameters.dataKey);
            that._createProjectionHandlers(parameters.projection);
            that._focus = new Focus(that._callbacks);
            that._attachHandlers()
        }
        Tracker.prototype = {
            constructor: Tracker,
            dispose: function() {
                var that = this;
                that._detachHandlers();
                that._focus.dispose();
                that._root = that._callbacks = that._focus = that._docHandlers = that._rootHandlers = null;
                return that
            },
            _startClick: function(event, data) {
                if (!data)
                    return;
                var coords = getEventCoords(event);
                this._clickState = {
                    x: coords.x,
                    y: coords.y,
                    threshold: isTouchEvent(event) ? CLICK_COORD_THRESHOLD_TOUCH : CLICK_COORD_THRESHOLD_MOUSE,
                    time: _now()
                }
            },
            _endClick: function(event, data) {
                var state = this._clickState,
                    threshold,
                    coords;
                if (!state)
                    return;
                if (_now() - state.time <= CLICK_TIME_THRESHOLD) {
                    threshold = state.threshold;
                    coords = getEventCoords(event);
                    if (_abs(coords.x - state.x) <= threshold && _abs(coords.y - state.y) <= threshold)
                        this._callbacks[EVENT_CLICK]({
                            data: data,
                            x: coords.x,
                            y: coords.y,
                            $event: event
                        })
                }
                this._clickState = null
            },
            _startDrag: function(event, data) {
                if (!data)
                    return;
                var coords = getEventCoords(event),
                    state = this._dragState = {
                        x: coords.x,
                        y: coords.y,
                        data: data
                    };
                this._callbacks[EVENT_START]({
                    x: state.x,
                    y: state.y,
                    data: state.data
                })
            },
            _moveDrag: function(event, data) {
                var state = this._dragState,
                    coords,
                    threshold;
                if (!state)
                    return;
                coords = getEventCoords(event);
                threshold = isTouchEvent(event) ? 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 = data || {};
                    this._callbacks[EVENT_MOVE]({
                        x: state.x,
                        y: state.y,
                        data: state.data
                    })
                }
            },
            _endDrag: function() {
                var state = this._dragState;
                if (!state)
                    return;
                this._dragState = null;
                this._callbacks[EVENT_END]({
                    x: state.x,
                    y: state.y,
                    data: state.data
                })
            },
            _wheelZoom: function(event, data) {
                if (!data)
                    return;
                var that = this,
                    lock = that._wheelLock,
                    time = _now(),
                    delta,
                    coords;
                if (time - lock.time <= WHEEL_COOLDOWN)
                    return;
                if (time - lock.dirTime > WHEEL_DIRECTION_COOLDOWN)
                    lock.dir = 0;
                delta = adjustWheelDelta(event.originalEvent.wheelDelta / 120 || event.originalEvent.detail / -3 || 0, lock);
                if (delta === 0)
                    return;
                coords = getEventCoords(event);
                that._callbacks[EVENT_ZOOM]({
                    delta: delta,
                    x: coords.x,
                    y: coords.y
                });
                lock.time = lock.dirTime = time
            },
            _startZoom: function(event, data) {
                if (!isTouchEvent(event) || !data)
                    return;
                var state = this._zoomState = this._zoomState || {},
                    coords,
                    pointer2;
                if (state.pointer1 && state.pointer2)
                    return;
                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) {
                    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;
                            this._endDrag()
                        }
                    }
                }
            },
            _moveZoom: function(event) {
                var state = this._zoomState,
                    coords;
                if (!state || !isTouchEvent(event))
                    return;
                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
                    }
                }
            },
            _endZoom: function(event) {
                var state = this._zoomState,
                    startDistance,
                    currentDistance;
                if (!state || !isTouchEvent(event))
                    return;
                if (state.ready) {
                    startDistance = getDistance(state.x1_0, state.y1_0, state.x2_0, state.y2_0);
                    currentDistance = getDistance(state.x1, state.y1, state.x2, state.y2);
                    this._callbacks[EVENT_ZOOM]({
                        ratio: currentDistance / startDistance,
                        x: (state.x1_0 + state.x2_0) / 2,
                        y: (state.y1_0 + state.y2_0) / 2
                    })
                }
                this._zoomState = null
            },
            _startHover: function(event, data) {
                this._doHover(event, data, true)
            },
            _moveHover: function(event, data) {
                this._doHover(event, data, false)
            },
            _doHover: function(event, data, isTouch) {
                var that = this;
                if (that._dragState && that._dragState.active || that._zoomState && that._zoomState.ready) {
                    that._cancelHover();
                    return
                }
                if (isTouchEvent(event) !== isTouch || that._hoverTarget === event.target || that._hoverState && that._hoverState.data === data)
                    return;
                that._cancelHover();
                if (data) {
                    that._hoverState = {data: data};
                    that._callbacks[EVENT_HOVER_ON]({data: data})
                }
                that._hoverTarget = event.target
            },
            _cancelHover: function() {
                var state = this._hoverState;
                this._hoverState = this._hoverTarget = null;
                if (state)
                    this._callbacks[EVENT_HOVER_OFF]({data: state.data})
            },
            _startFocus: function(event, data) {
                this._doFocus(event, data, true)
            },
            _moveFocus: function(event, data) {
                this._doFocus(event, data, false)
            },
            _doFocus: function(event, data, isTouch) {
                var that = this;
                if (that._dragState && that._dragState.active || that._zoomState && that._zoomState.ready) {
                    that._cancelFocus();
                    return
                }
                if (isTouchEvent(event) !== isTouch)
                    return;
                that._focus.turnOff(isTouch ? FOCUS_OFF_DELAY_TOUCH : FOCUS_OFF_DELAY_MOUSE);
                data && that._focus.turnOn(data, getEventCoords(event), isTouch ? FOCUS_ON_DELAY_TOUCH : FOCUS_ON_DELAY_MOUSE, isTouch)
            },
            _endFocus: function(event) {
                if (!isTouchEvent(event))
                    return;
                this._focus.cancelOn()
            },
            _cancelFocus: function() {
                this._focus.cancel()
            },
            _createEventHandlers: function(DATA_KEY) {
                var that = this;
                that._docHandlers = {};
                that._rootHandlers = {};
                that._docHandlers[EVENTS.start] = function(event) {
                    var isTouch = isTouchEvent(event),
                        data = $(event.target).data(DATA_KEY);
                    if (isTouch && !that._isTouchEnabled)
                        return;
                    data && event.preventDefault();
                    that._startClick(event, data);
                    that._startDrag(event, data);
                    that._startZoom(event, data);
                    that._startHover(event, data);
                    that._startFocus(event, data)
                };
                that._docHandlers[EVENTS.move] = function(event) {
                    var isTouch = isTouchEvent(event),
                        data = $(event.target).data(DATA_KEY);
                    if (isTouch && !that._isTouchEnabled)
                        return;
                    that._moveDrag(event, data);
                    that._moveZoom(event, data);
                    that._moveHover(event, data);
                    that._moveFocus(event, data)
                };
                that._docHandlers[EVENTS.end] = function(event) {
                    var isTouch = isTouchEvent(event),
                        data = $(event.target).data(DATA_KEY);
                    if (isTouch && !that._isTouchEnabled)
                        return;
                    that._endClick(event, data);
                    that._endDrag(event, data);
                    that._endZoom(event, data);
                    that._endFocus(event, data)
                };
                that._rootHandlers[EVENTS.wheel] = function(event) {
                    that._cancelFocus();
                    if (!that._isWheelEnabled)
                        return;
                    var data = $(event.target).data(DATA_KEY);
                    if (data) {
                        event.preventDefault();
                        event.stopPropagation();
                        that._wheelZoom(event, data)
                    }
                };
                that._wheelLock = {dir: 0}
            },
            _createProjectionHandlers: function(projection) {
                var that = this;
                projection.on({
                    center: handler,
                    zoom: handler
                });
                function handler() {
                    that._cancelFocus()
                }
            },
            reset: function() {
                var that = this;
                that._clickState = null;
                that._endDrag();
                that._cancelHover();
                that._cancelFocus();
                return that
            },
            setCallbacks: function(callbacks) {
                $.extend(this._callbacks, callbacks);
                return this
            },
            setOptions: function(options) {
                var that = this;
                that.reset();
                that._detachHandlers();
                that._isTouchEnabled = !!_parseScalar(options.touchEnabled, true);
                that._isWheelEnabled = !!_parseScalar(options.wheelEnabled, true);
                that._attachHandlers();
                return that
            },
            _detachHandlers: function() {
                var that = this;
                if (that._isTouchEnabled)
                    that._root.css({
                        "touch-action": "",
                        "-ms-touch-action": "",
                        "-webkit-user-select": ""
                    }).off(_addNamespace("MSHoldVisual", _NAME)).off(_addNamespace("contextmenu", _NAME));
                $(document).off(that._docHandlers);
                that._root.off(that._rootHandlers)
            },
            _attachHandlers: function() {
                var that = this;
                if (that._isTouchEnabled)
                    that._root.css({
                        "touch-action": "none",
                        "-ms-touch-action": "none",
                        "-webkit-user-select": "none"
                    }).on(_addNamespace("MSHoldVisual", _NAME), function(event) {
                        event.preventDefault()
                    }).on(_addNamespace("contextmenu", _NAME), function(event) {
                        isTouchEvent(event) && event.preventDefault()
                    });
                $(document).on(that._docHandlers);
                that._root.on(that._rootHandlers)
            }
        };
        var Focus = function(callbacks) {
                var that = this,
                    _activeData = null,
                    _data = null,
                    _disabled = false,
                    _onTimer = null,
                    _offTimer = null,
                    _x,
                    _y;
                that.dispose = function() {
                    clearTimeout(_onTimer);
                    clearTimeout(_offTimer);
                    that.turnOn = that.turnOff = that.cancel = that.cancelOn = that.dispose = that = callbacks = _activeData = _data = _onTimer = _offTimer = null
                };
                that.turnOn = function(data, coords, timeout, forceTimeout) {
                    if (data === _data && _disabled)
                        return;
                    _disabled = false;
                    _data = data;
                    if (_activeData) {
                        _x = coords.x;
                        _y = coords.y;
                        clearTimeout(_onTimer);
                        _onTimer = setTimeout(function() {
                            _onTimer = null;
                            if (_data === _activeData) {
                                callbacks[EVENT_FOCUS_MOVE]({
                                    data: _data,
                                    x: _x,
                                    y: _y
                                });
                                onCheck(true)
                            }
                            else
                                callbacks[EVENT_FOCUS_ON]({
                                    data: _data,
                                    x: _x,
                                    y: _y
                                }, onCheck)
                        }, forceTimeout ? timeout : 0)
                    }
                    else if (!_onTimer || _abs(coords.x - _x) > FOCUS_COORD_THRESHOLD_MOUSE || _abs(coords.y - _y) > FOCUS_COORD_THRESHOLD_MOUSE || forceTimeout) {
                        _x = coords.x;
                        _y = coords.y;
                        clearTimeout(_onTimer);
                        _onTimer = setTimeout(function() {
                            _onTimer = null;
                            callbacks[EVENT_FOCUS_ON]({
                                data: _data,
                                x: _x,
                                y: _y
                            }, onCheck)
                        }, timeout)
                    }
                    function onCheck(result) {
                        _disabled = !result;
                        if (result) {
                            _activeData = _data;
                            clearTimeout(_offTimer);
                            _offTimer = null
                        }
                    }
                };
                that.turnOff = function(timeout) {
                    clearTimeout(_onTimer);
                    _onTimer = null;
                    _data = null;
                    if (_activeData && !_disabled)
                        _offTimer = _offTimer || setTimeout(function() {
                            _offTimer = null;
                            callbacks[EVENT_FOCUS_OFF]({data: _activeData});
                            _activeData = null
                        }, timeout)
                };
                that.cancel = function() {
                    clearTimeout(_onTimer);
                    clearTimeout(_offTimer);
                    if (_activeData)
                        callbacks[EVENT_FOCUS_OFF]({data: _activeData});
                    _activeData = _data = _onTimer = _offTimer = null
                };
                that.cancelOn = function() {
                    clearTimeout(_onTimer);
                    _onTimer = null
                }
            };
        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.dxVectorMap.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"]),
                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
        }
        function adjustWheelDelta(delta, lock) {
            if (delta === 0)
                return 0;
            var _delta = _abs(delta),
                sign = _round(delta / _delta);
            if (lock.dir && sign !== lock.dir)
                return 0;
            lock.dir = sign;
            if (_delta < 0.1)
                _delta = 0;
            else if (_delta < 1)
                _delta = 1;
            else if (_delta > 4)
                _delta = 4;
            else
                _delta = _round(_delta);
            return sign * _delta
        }
    })(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",
                _fontFields: ["areaSettings.label.font", "markerSettings.label.font", "tooltip.font", "legend.font", "loadingIndicator.font"],
                getCommonAreaSettings: function(options) {
                    var settings = _extend(true, {}, this._theme.areaSettings, options),
                        palette,
                        i,
                        colors;
                    if (settings.paletteSize > 0) {
                        palette = new DX.viz.core.GradientPalette(settings.palette, settings.paletteSize);
                        for (i = 0, colors = []; i < settings.paletteSize; ++i)
                            colors.push(palette.getColor(i));
                        settings._colors = colors
                    }
                    return settings
                },
                getAreaSettings: function(commonSettings, options) {
                    var settings = _extend(true, {}, commonSettings, options);
                    settings.borderWidth = _Number(settings.borderWidth) || 0;
                    settings.borderColor = settings.borderColor || null;
                    if (options.color === undefined && options.paletteIndex >= 0)
                        settings.color = commonSettings._colors[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.label && options.font && (options.label = {font: options.font}) && (options.font = undefined);
                    var theme = _extend({}, this._theme.markerSettings),
                        _options = _extend({}, options),
                        themeParts = {},
                        optionsParts = {},
                        settings;
                    _each(theme, function(name, themePart) {
                        if (name[0] === "_") {
                            themeParts[name] = themePart;
                            optionsParts[name] = _options[name];
                            theme[name] = _options[name] = undefined
                        }
                    });
                    settings = _extend(true, {}, theme, _options);
                    _each(themeParts, function(name, themePart) {
                        settings[name] = _extend(true, {}, theme, themePart, _options, optionsParts[name])
                    });
                    return settings
                },
                getMarkerSettings: function(commonSettings, options, type) {
                    var settings = _extend(true, {}, commonSettings["_" + type], options);
                    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
                },
                getPieColors: function(commonSettings, count) {
                    var colors = commonSettings._pie._colors || [],
                        palette,
                        i,
                        _count = count > 8 ? count : 8;
                    if (colors.length < _count) {
                        palette = new DX.viz.core.Palette(commonSettings._pie.palette, {
                            stepHighlight: 50,
                            theme: this.themeName()
                        });
                        for (i = 0, colors = []; i < _count; ++i)
                            colors.push(palette.getNextColor());
                        commonSettings._pie._colors = colors
                    }
                    return colors
                }
            });
        DX.viz.map._tests.ThemeManager = ThemeManager;
        DX.viz.map.dxVectorMap.prototype._factory.createThemeManager = function() {
            return new ThemeManager
        }
    })(DevExpress, jQuery);
    /*! Module viz-vectormap, file legend.js */
    (function(DX, $, undefined) {
        var _String = String,
            _isArray = DX.utils.isArray,
            _extend = $.extend,
            _each = $.each,
            _BaseLegend = DX.viz.core.Legend;
        function Legend(parameters) {
            var that = this;
            that._params = parameters;
            that._root = parameters.renderer.g().attr({"class": "dxm-legend"});
            parameters.layoutControl.addItem(that);
            _BaseLegend.apply(that, [{
                    renderer: parameters.renderer,
                    group: that._root,
                    backgroundClass: null,
                    itemsGroupClass: null,
                    textField: "text",
                    getFormatObject: function(data) {
                        return data
                    }
                }]);
            that._onDataChanged = function(items) {
                var itemsForUpdate = $.map(items, function(item) {
                        return _extend(true, {states: {normal: {fill: item.color}}}, item)
                    });
                that.update(itemsForUpdate, that._options);
                that._refresh()
            }
        }
        var legendPrototype = Legend.prototype = DX.utils.clone(_BaseLegend.prototype);
        legendPrototype.constructor = Legend;
        legendPrototype.dispose = function() {
            var that = this;
            that._params.layoutControl.removeItem(that);
            that._unbindData();
            that._params = that._root = that._onDataChanged = null;
            return _BaseLegend.prototype.dispose.apply(that, arguments)
        };
        legendPrototype.clean = function() {
            this._rendered = false;
            this._root.remove();
            return this
        };
        legendPrototype.render = function() {
            var that = this;
            that._root.append(that._params.container);
            that._rendered = true;
            that._refresh();
            return that
        };
        legendPrototype.resize = function(size) {
            if (size === null)
                this.erase();
            else
                this.setSize(size).draw();
            return this
        };
        legendPrototype.locate = _BaseLegend.prototype.shift;
        legendPrototype._unbindData = function() {
            if (this._dataCategory)
                this._params.dataExchanger.unbind(this._dataCategory, this._dataName)
        };
        legendPrototype._bindData = function(info) {
            this._params.dataExchanger.bind(this._dataCategory = info.category, this._dataName = info.name, this._onDataChanged)
        };
        var sourceMap = {
                areacolorgroups: {
                    category: "areas",
                    name: "color"
                },
                markercolorgroups: {
                    category: "markers",
                    name: "color"
                },
                markersizegroups: {
                    category: "markers",
                    name: "size"
                }
            };
        var unknownSource = {
                category: "UNKNOWN",
                name: "UNKNOWN"
            };
        legendPrototype.setOptions = function(options) {
            var that = this;
            that.update(that._data, options);
            that._unbindData();
            that._bindData(sourceMap[_String(options.source).toLowerCase()] || unknownSource);
            that._refresh();
            return that
        };
        legendPrototype._refresh = function() {
            if (this._rendered)
                this.updateLayout()
        };
        function LegendsControl(parameters) {
            this._parameters = parameters;
            this._items = []
        }
        LegendsControl.prototype = {
            constructor: LegendsControl,
            dispose: function() {
                _each(this._items, function(_, item) {
                    item.dispose()
                });
                this._parameters = this._items = null;
                return this
            },
            setOptions: function(options, theme) {
                var optionList = _isArray(options) ? options : [],
                    i = 0,
                    ii = optionList.length,
                    item,
                    newItems = [],
                    items = this._items;
                for (; i < ii; ++i) {
                    item = (items[i] || new Legend(this._parameters)).setOptions(_extend(true, {}, theme, optionList[i]));
                    newItems.push(item)
                }
                for (ii = items.length; i < ii; ++i)
                    items[i].clean().dispose();
                this._items = newItems
            },
            clean: function() {
                _each(this._items, function(_, item) {
                    item.clean()
                });
                return this
            },
            render: function() {
                _each(this._items, function(_, item) {
                    item.render()
                });
                return this
            }
        };
        DX.viz.map.dxVectorMap.prototype._factory.createLegendsControl = function(parameters) {
            return new LegendsControl(parameters)
        };
        DX.viz.map._tests.Legend = Legend;
        DX.viz.map._tests.LegendsControl = LegendsControl;
        DX.viz.map._tests.stubLegendType = function(stub) {
            Legend = stub
        };
        DX.viz.map._tests.restoreLegendType = function() {
            Legend = DX.viz.map._tests.Legend
        };
        DX.viz.map._tests.extendLegendSourceMap = function(name, value) {
            sourceMap[name] = value
        }
    })(DevExpress, jQuery);
    /*! Module viz-vectormap, file layout.js */
    (function(DX, $, undefined) {
        var _round = Math.round,
            _min = Math.min,
            _max = Math.max,
            _each = $.each,
            _inArray = $.inArray,
            horizontalAlignmentMap = {
                left: 0,
                center: 1,
                right: 2
            },
            verticalAlignmentMap = {
                top: 0,
                bottom: 1
            };
        function getCellIndex(options) {
            return verticalAlignmentMap[options.verticalAlignment] * 3 + horizontalAlignmentMap[options.horizontalAlignment]
        }
        function createCells(canvas, items) {
            var hstep = (canvas.right - canvas.left) / 3,
                vstep = (canvas.bottom - canvas.top) / 2,
                h1 = canvas.left,
                h2 = _round(h1 + hstep),
                h3 = _round(h1 + hstep + hstep),
                h4 = canvas.right,
                v1 = canvas.top,
                v2 = _round(v1 + vstep),
                v3 = canvas.bottom,
                cells = [{rect: [h1, v1, h2, v2]}, {
                        rect: [h2, v1, h3, v2],
                        center: true
                    }, {
                        rect: [h3, v1, h4, v2],
                        horInv: true
                    }, {
                        rect: [h1, v2, h2, v3],
                        verInv: true
                    }, {
                        rect: [h2, v2, h3, v3],
                        center: true,
                        verInv: true
                    }, {
                        rect: [h3, v2, h4, v3],
                        horInv: true,
                        verInv: true
                    }],
                itemsList = [[], [], [], [], [], []];
            _each(items, function(_, item) {
                var options = item.getLayoutOptions();
                if (options)
                    itemsList[getCellIndex(options)].push({
                        item: item,
                        width: options.width,
                        height: options.height
                    })
            });
            _each(cells, function(i, cell) {
                if (itemsList[i].length)
                    cell.items = itemsList[i];
                else {
                    if (cell.center)
                        cell.rect[0] = cell.rect[2] = (cell.rect[0] + cell.rect[2]) / 2;
                    else
                        cell.rect[cell.horInv ? 0 : 2] = cell.rect[cell.horInv ? 2 : 0];
                    cell.rect[cell.verInv ? 1 : 3] = cell.rect[cell.verInv ? 3 : 1]
                }
            });
            return cells
        }
        function adjustCellSizes(cells) {
            _each([0, 1, 2, 3, 4, 5], function(_, index) {
                var cell = cells[index],
                    otherCell = cells[(index + 3) % 6];
                if (cell.items)
                    if (!otherCell.items) {
                        cell.rect[1] = _min(cell.rect[1], otherCell.rect[3]);
                        cell.rect[3] = _max(cell.rect[3], otherCell.rect[1])
                    }
            });
            _each([1, 4], function(_, index) {
                var cell = cells[index],
                    otherCell1 = cells[index - 1],
                    otherCell2 = cells[index + 1],
                    size1,
                    size2;
                if (cell.items) {
                    if (!otherCell1.items && !otherCell2.items) {
                        size1 = cell.rect[0] - otherCell1.rect[2];
                        size2 = otherCell2.rect[0] - cell.rect[2];
                        if (size1 > size2)
                            if (size1 / size2 >= 2) {
                                cell.rect[0] -= size1;
                                cell.right = true
                            }
                            else {
                                cell.rect[0] -= size2;
                                cell.rect[2] += size2
                            }
                        else if (size2 / size1 >= 2) {
                            cell.rect[2] += size2;
                            cell.center = null
                        }
                        else {
                            cell.rect[0] -= size1;
                            cell.rect[2] += size1
                        }
                    }
                }
                else {
                    if (otherCell1.items)
                        otherCell1.rect[2] = (cell.rect[0] + cell.rect[2]) / 2;
                    if (otherCell2.items)
                        otherCell2.rect[0] = (cell.rect[0] + cell.rect[2]) / 2
                }
            })
        }
        function adjustCellsAndApplyLayout(cells, forceMode) {
            var hasHiddenItems = false;
            adjustCellSizes(cells);
            _each(cells, function(_, cell) {
                if (cell.items)
                    hasHiddenItems = applyCellLayout(cell, forceMode) || hasHiddenItems
            });
            return hasHiddenItems
        }
        function applyCellLayout(cell, forceMode) {
            var cellRect = cell.rect,
                cellWidth = cellRect[2] - cellRect[0],
                cellHeight = cellRect[3] - cellRect[1],
                xoffset = 0,
                yoffset = 0,
                currentHeight = 0,
                totalL = cellRect[2],
                totalT = cellRect[3],
                totalR = cellRect[0],
                totalB = cellRect[1],
                moves = [],
                hasHiddenItems = false;
            _each(cell.items, function(_, item) {
                if (item.width > cellWidth || item.height > cellHeight) {
                    moves.push(null);
                    hasHiddenItems = true;
                    return forceMode || false
                }
                if (xoffset + item.width > cellWidth) {
                    yoffset += currentHeight;
                    xoffset = currentHeight = 0
                }
                if (yoffset + item.height > cellHeight) {
                    moves.push(null);
                    hasHiddenItems = true;
                    return forceMode || false
                }
                currentHeight = _max(currentHeight, item.height);
                var dx = cell.horInv ? cellRect[2] - item.width - xoffset : cellRect[0] + xoffset,
                    dy = cell.verInv ? cellRect[3] - item.height - yoffset : cellRect[1] + yoffset;
                xoffset += item.width;
                totalL = _min(totalL, dx);
                totalT = _min(totalT, dy);
                totalR = _max(totalR, dx + item.width);
                totalB = _max(totalB, dy + item.height);
                moves.push([dx, dy])
            });
            if (forceMode || !hasHiddenItems) {
                xoffset = 0;
                if (cell.right)
                    xoffset = cellRect[2] - cellRect[0] - totalR + totalL;
                else if (cell.center)
                    xoffset = _round((cellRect[2] - cellRect[0] - totalR + totalL) / 2);
                _each(cell.items, function(i, item) {
                    var move = moves[i];
                    if (move)
                        item.item.locate(move[0] + xoffset, move[1]);
                    else
                        item.item.resize(null)
                });
                cell.rect = [totalL, totalT, totalR, totalB];
                cell.items = null
            }
            return hasHiddenItems
        }
        function applyLayout(canvas, items) {
            var cells = createCells(canvas, items);
            if (adjustCellsAndApplyLayout(cells))
                adjustCellsAndApplyLayout(cells, true)
        }
        function LayoutControl() {
            var that = this;
            that._items = [];
            that._suspended = true;
            that._updateLayout = function() {
                that._update()
            }
        }
        LayoutControl.prototype = {
            constructor: LayoutControl,
            dispose: function() {
                this._items = this._updateLayout = null;
                return this
            },
            setSize: function(width, height) {
                this._size = {
                    width: width,
                    height: height
                };
                this._update();
                return this
            },
            stop: function() {
                this._suspended = true;
                return this
            },
            start: function() {
                this._suspended = null;
                this._update();
                return this
            },
            addItem: function(item) {
                this._items.push(item);
                item.updateLayout = this._updateLayout;
                return this
            },
            removeItem: function(item) {
                this._items.splice(_inArray(item, this._items), 1);
                item.updateLayout = null;
                return this
            },
            _update: function() {
                if (this._suspended)
                    return;
                var size = this._size;
                _each(this._items, function(_, item) {
                    item.resize(size)
                });
                applyLayout({
                    left: 0,
                    top: 0,
                    right: size.width,
                    bottom: size.height
                }, this._items)
            }
        };
        DX.viz.map.dxVectorMap.prototype._factory.createLayoutControl = function() {
            return new LayoutControl
        };
        DX.viz.map._tests.LayoutControl = LayoutControl
    })(DevExpress, jQuery);
    /*! Module viz-vectormap, file mapItemsManager.js */
    (function(DX, $, undefined) {
        var _isFinite = isFinite,
            _utils = DX.utils,
            _coreUtils = DX.viz.core.utils,
            _isString = _utils.isString,
            _isArray = _utils.isArray,
            _isFunction = _utils.isFunction,
            _patchFontOptions = _coreUtils.patchFontOptions,
            _parseScalar = _coreUtils.parseScalar,
            _extend = $.extend,
            _each = $.each,
            _map = $.map;
        var SELECTIONS = {
                none: null,
                single: -1,
                multiple: NaN
            };
        function getSelection(selectionMode) {
            var selection = String(selectionMode).toLowerCase();
            selection = selection in SELECTIONS ? SELECTIONS[selection] : SELECTIONS.single;
            if (selection !== null)
                selection = {
                    state: {},
                    single: selection || null
                };
            return selection
        }
        function createEventTriggers(context, trigger, names) {
            context.raiseHoverChanged = function(handle, state) {
                trigger(names.hoverChanged, {
                    target: handle.proxy,
                    state: state
                })
            };
            context.raiseSelectionChanged = function(handle) {
                trigger(names.selectionChanged, {target: handle.proxy})
            }
        }
        var MapItemsManager = DX.Class.inherit({
                _rootClass: null,
                ctor: function(parameters) {
                    var that = this;
                    that._params = parameters;
                    that._init();
                    parameters.projection.on({
                        project: function() {
                            that._reproject()
                        },
                        transform: function(transform) {
                            that._transform(transform);
                            that._relocate()
                        },
                        center: function(_, transform) {
                            that._transform(transform)
                        },
                        zoom: function(_, transform) {
                            that._transform(transform);
                            that._relocate()
                        }
                    })
                },
                _init: function() {
                    var that = this;
                    that._context = {
                        renderer: that._params.renderer,
                        projection: that._params.projection,
                        dataKey: that._params.dataKey,
                        selection: null,
                        getItemSettings: that._createItemSettingsBuilder()
                    };
                    that._initRoot();
                    createEventTriggers(that._context, that._params.eventTrigger, that._eventNames)
                },
                _createItemSettingsBuilder: function() {
                    var that = this;
                    return function(proxy, settings) {
                            var result = {};
                            _each(that._grouping, function(settingField, grouping) {
                                var value,
                                    index;
                                if (_isFinite(value = grouping.callback(proxy)) && (index = findGroupPosition(value, grouping.groups)) >= 0)
                                    result[settingField] = grouping.groups[index][settingField]
                            });
                            return that._getItemSettings(proxy, _extend({}, settings, result))
                        }
                },
                _initRoot: function() {
                    this._context.root = this._root = this._params.renderer.g().attr({"class": this._rootClass})
                },
                dispose: function() {
                    var that = this;
                    that._destroyHandles();
                    that._params = that._context = that._grouping = null;
                    that._disposeRoot();
                    return that
                },
                _disposeRoot: function() {
                    this._root = null
                },
                clean: function() {
                    var that = this;
                    that._destroyItems();
                    that._removeRoot();
                    that._rendered = false;
                    return that
                },
                _removeRoot: function() {
                    this._root.remove()
                },
                setOptions: function(options) {
                    var that = this;
                    that._processOptions(options || {});
                    that._params.notifyDirty();
                    that._destroyItems();
                    that._createItems(that._params.notifyReady);
                    return that
                },
                render: function() {
                    var that = this;
                    that._rendered = true;
                    that._params.notifyDirty();
                    that._appendRoot();
                    that._createItems(that._params.notifyReady, true);
                    return that
                },
                _processOptions: function(options) {
                    var that = this,
                        settings = that._commonSettings = that._getCommonSettings(options),
                        context = that._context;
                    that._customizeCallback = _isFunction(settings.customize) ? settings.customize : $.noop;
                    context.hover = !!_parseScalar(settings.hoverEnabled, true);
                    if (context.selection)
                        _each(context.selection.state, function(_, handle) {
                            handle && handle.resetSelected()
                        });
                    context.selection = getSelection(settings.selectionMode);
                    that._grouping = {};
                    that._updateGrouping()
                },
                _appendRoot: function() {
                    this._root.append(this._params.container)
                },
                _destroyItems: function() {
                    var that = this;
                    that._clearRoot();
                    clearTimeout(that._labelsTimeout);
                    that._rendered && that._handles && _each(that._handles, function(_, handle) {
                        if (handle.item) {
                            handle.item.dispose();
                            handle.item = null
                        }
                    })
                },
                _clearRoot: function() {
                    this._root.clear()
                },
                _destroyHandles: function() {
                    this._handles && _each(this._handles, function(_, handle) {
                        handle.dispose()
                    });
                    this._handles = null
                },
                _createHandles: function(source) {
                    var that = this;
                    if (_isArray(source))
                        that._handles = _map(source, function(dataItem, i) {
                            dataItem = dataItem || {};
                            var handle = new MapItemHandle(that._context, that._getItemCoordinates(dataItem), that._getItemAttributes(dataItem), i, that._itemType),
                                proxy = handle.proxy;
                            that._initProxy(proxy, dataItem);
                            handle.settings = that._customizeCallback.call(proxy, proxy) || {};
                            if (handle.settings.isSelected)
                                proxy.selected(true);
                            return handle
                        })
                },
                _createItems: function(notifyReady) {
                    var that = this,
                        selectedItems = [],
                        immediateReady = true;
                    if (that._rendered && that._handles) {
                        _each(that._handles, function(_, handle) {
                            handle.item = that._createItem(handle.proxy).init(that._context, handle.proxy).project().update(handle.settings).locate();
                            if (handle.proxy.selected())
                                selectedItems.push(handle.item)
                        });
                        _each(selectedItems, function(_, item) {
                            item.setSelectedState()
                        });
                        that._arrangeItems();
                        if (that._commonSettings.label.enabled) {
                            immediateReady = false;
                            clearTimeout(that._labelsTimeout);
                            that._labelsTimeout = setTimeout(function() {
                                _each(that._handles, function(_, handle) {
                                    handle.item.createLabel()
                                });
                                notifyReady()
                            })
                        }
                    }
                    immediateReady && notifyReady()
                },
                _processSource: null,
                setData: function(data) {
                    var that = this;
                    that._params.notifyDirty();
                    if (_isString(data))
                        $.getJSON(data).done(updateSource).fail(function() {
                            updateSource(null)
                        });
                    else
                        updateSource(data);
                    return that;
                    function updateSource(source) {
                        if (that._rendered)
                            that._params.tracker.reset();
                        that._destroyItems();
                        that._destroyHandles();
                        that._createHandles(that._processSource(source));
                        that._createItems(that._params.notifyReady)
                    }
                },
                _transform: function(transform) {
                    this._root.attr(transform)
                },
                _reproject: function() {
                    this._rendered && this._handles && _each(this._handles, function(_, handle) {
                        handle.item.project().locate()
                    })
                },
                _relocate: function() {
                    this._rendered && this._handles && _each(this._handles, function(_, handle) {
                        handle.item.locate()
                    })
                },
                hoverItem: function(index, state) {
                    this._handles[index].setHovered(state);
                    return this
                },
                selectItem: function(index, state, noCallback) {
                    this._handles[index].setSelected(state, noCallback);
                    return this
                },
                clearSelection: function() {
                    var selection = this._context.selection;
                    if (selection)
                        _each(selection.state, function(_, handle) {
                            handle && handle.setSelected(false)
                        });
                    return this
                },
                raiseClick: function(index, $event) {
                    this._params.eventTrigger(this._eventNames.click, {
                        target: this._handles[index].proxy,
                        jQueryEvent: $event
                    });
                    return this
                },
                getProxyItems: function() {
                    return _map(this._handles, function(handle) {
                            return handle.proxy
                        })
                },
                getProxyItem: function(index) {
                    return this._handles[index].proxy
                },
                _performGrouping: function(partition, settingField, valueCallback, valuesCallback) {
                    var groups = createGroups(partition),
                        values;
                    if (groups) {
                        values = valuesCallback(groups.length);
                        _each(groups, function(i, group) {
                            group.index = i;
                            group[settingField] = values[i]
                        });
                        this._grouping[settingField] = {
                            callback: valueCallback,
                            groups: groups
                        }
                    }
                    else {
                        delete this._grouping[settingField];
                        groups = []
                    }
                    this._params.dataExchanger.set(this._dataCategory, settingField, groups)
                },
                _groupByColor: function(colorGroups, palette, valueCallback) {
                    this._performGrouping(colorGroups, "color", valueCallback, function(count) {
                        var _palette = new DX.viz.core.GradientPalette(palette, count),
                            i = 0,
                            list = [];
                        for (; i < count; ++i)
                            list.push(_palette.getColor(i));
                        return list
                    })
                }
            });
        MapItemsManager.prototype.TEST_getContext = function() {
            return this._context
        };
        MapItemsManager.prototype.TEST_performGrouping = MapItemsManager.prototype._performGrouping;
        MapItemsManager.prototype.TEST_groupByColor = MapItemsManager.prototype._groupByColor;
        DX.viz.map._internal.mapItemBehavior = {
            init: function(ctx, proxy) {
                var that = this;
                that._ctx = ctx;
                that._data = {
                    index: proxy.index,
                    type: proxy.type
                };
                that._proxy = proxy;
                that._root = that._createRoot().append(that._ctx.root);
                return that
            },
            dispose: function() {
                disposeItem(this);
                return this
            },
            project: function() {
                var that = this;
                that._coords = that._project(that._ctx.projection, that._proxy.coordinates());
                return this
            },
            locate: function() {
                var that = this;
                that._locate(that._transform(that._ctx.projection, that._coords));
                that._label && that._label.value && that._locateLabel();
                return that
            },
            update: function(settings) {
                var that = this;
                that._settings = that._ctx.getItemSettings(that._proxy, settings);
                that._update(that._settings);
                that._label && that._updateLabel();
                return that
            },
            createLabel: function() {
                var that = this;
                that._label = {
                    root: that._createLabelRoot(),
                    text: that._ctx.renderer.text(),
                    tracker: that._ctx.renderer.rect().attr({
                        stroke: "none",
                        "stroke-width": 0,
                        fill: "#000000",
                        opacity: 0.0001
                    }).data(that._ctx.dataKey, that._data)
                };
                that._updateLabel();
                return that
            },
            _updateLabel: function() {
                var that = this,
                    settings = that._settings.label;
                that._label.value = String(this._proxy.text || this._proxy.attribute(this._settings.label.dataField) || "");
                if (that._label.value) {
                    that._label.text.attr({
                        text: that._label.value,
                        x: 0,
                        y: 0
                    }).css(_patchFontOptions(settings.font)).attr({
                        align: "center",
                        stroke: settings.stroke,
                        "stroke-width": settings["stroke-width"],
                        "stroke-opacity": settings["stroke-opacity"]
                    }).append(that._label.root);
                    that._label.tracker.append(that._label.root);
                    that._adjustLabel();
                    that._locateLabel()
                }
            }
        };
        var MapItemHandle = function(context, coordinates, attributes, index, type) {
                var handle = this;
                handle._ctx = context;
                handle._idx = index;
                handle._hovered = handle._selected = false;
                attributes = _extend({}, attributes);
                handle.proxy = {
                    index: index,
                    type: type,
                    coordinates: function() {
                        return coordinates
                    },
                    attribute: function(name, value) {
                        if (arguments.length > 1) {
                            attributes[name] = value;
                            return this
                        }
                        else
                            return arguments.length > 0 ? attributes[name] : attributes
                    },
                    selected: function(state, _noEvent) {
                        if (arguments.length > 0) {
                            handle.setSelected(!!state, _noEvent);
                            return this
                        }
                        else
                            return handle._selected
                    },
                    applySettings: function(settings) {
                        _extend(true, handle.settings, settings);
                        handle.item && handle.item.update(handle.settings);
                        return this
                    }
                }
            };
        MapItemHandle.prototype = {
            constructor: MapItemHandle,
            dispose: function() {
                disposeItem(this.proxy);
                disposeItem(this);
                return this
            },
            setHovered: function(state) {
                state = !!state;
                var that = this;
                if (that._ctx.hover && that._hovered !== state) {
                    that._hovered = state;
                    if (that.item) {
                        if (that._hovered)
                            that.item.onHover();
                        if (!that._selected) {
                            that.item[that._hovered ? "setHoveredState" : "setDefaultState"]();
                            that._ctx.raiseHoverChanged(that, that._hovered)
                        }
                    }
                }
                return that
            },
            resetSelected: function() {
                this._selected = false;
                return this
            },
            setSelected: function(state, _noEvent) {
                state = !!state;
                var that = this,
                    context = that._ctx,
                    selection = that._ctx.selection,
                    tmp;
                if (selection && that._selected !== state) {
                    that._selected = state;
                    tmp = selection.state[selection.single];
                    selection.state[selection.single] = null;
                    if (tmp)
                        tmp.setSelected(false);
                    selection.state[selection.single || that._idx] = state ? that : null;
                    if (that.item) {
                        that.item[state ? "setSelectedState" : that._hovered ? "setHoveredState" : "setDefaultState"]();
                        if (!_noEvent)
                            context.raiseSelectionChanged(that)
                    }
                }
                return that
            }
        };
        function disposeItem(item) {
            _each(item, function(name) {
                item[name] = null
            })
        }
        function createGroups(partition) {
            var i,
                ii,
                groups = null;
            if (_isArray(partition) && partition.length > 1) {
                groups = [];
                for (i = 0, ii = partition.length - 1; i < ii; ++i)
                    groups.push({
                        start: Number(partition[i]),
                        end: Number(partition[i + 1])
                    })
            }
            return groups
        }
        function findGroupPosition(value, groups) {
            var i = 0,
                ii = groups.length;
            for (; i < ii; ++i)
                if (groups[i].start <= value && value <= groups[i].end)
                    return i;
            return -1
        }
        _extend(DX.viz.map._tests, {
            MapItemsManager: MapItemsManager,
            MapItemHandle: MapItemHandle,
            stubMapItemHandle: function(mapItemHandleType) {
                MapItemHandle = mapItemHandleType
            },
            restoreMapItemHandle: function() {
                MapItemHandle = DX.viz.map._tests.MapItemHandle
            }
        });
        DX.viz.map.dxVectorMap.prototype._factory.MapItemsManager = MapItemsManager
    })(DevExpress, jQuery);
    /*! Module viz-vectormap, file areasManager.js */
    (function(DX, $, undefined) {
        var _abs = Math.abs,
            _sqrt = Math.sqrt,
            _noop = $.noop,
            TOLERANCE = 1;
        var AreasManager = DX.viz.map.dxVectorMap.prototype._factory.MapItemsManager.inherit({
                _rootClass: "dxm-areas",
                _dataCategory: "areas",
                _eventNames: {
                    click: "areaClick",
                    hoverChanged: "areaHoverChanged",
                    selectionChanged: "areaSelectionChanged"
                },
                _initRoot: function() {
                    var that = this;
                    that.callBase.apply(that, arguments);
                    that._context.labelRoot = that._labelRoot = that._params.renderer.g().attr({"class": "dxm-area-labels"})
                },
                _disposeRoot: function() {
                    this.callBase.apply(this, arguments);
                    this._labelRoot = null
                },
                _processSource: function(source) {
                    var isGeoJson = source && source.type === "FeatureCollection";
                    this._getItemCoordinates = isGeoJson ? getCoordinatesGeoJson : getCoordinatesDefault;
                    this._getItemAttributes = isGeoJson ? getAttributesGeoJson : getAttributesDefault;
                    return isGeoJson ? source.features : source
                },
                _getCommonSettings: function(options) {
                    return this._params.themeManager.getCommonAreaSettings(options)
                },
                _initProxy: _noop,
                _itemType: "area",
                _removeRoot: function() {
                    this.callBase.apply(this, arguments);
                    this._labelRoot.remove()
                },
                _appendRoot: function() {
                    var that = this;
                    that.callBase.apply(that, arguments);
                    if (that._commonSettings.label.enabled)
                        that._labelRoot.append(that._params.container)
                },
                _clearRoot: function() {
                    this.callBase.apply(this, arguments);
                    this._labelRoot.clear()
                },
                _getItemSettings: function(_, options) {
                    return this._params.themeManager.getAreaSettings(this._commonSettings, options)
                },
                _transform: function(transform) {
                    this.callBase.apply(this, arguments);
                    this._labelRoot.attr(transform)
                },
                _createItem: function() {
                    return new Area
                },
                _updateGrouping: function() {
                    var commonSettings = this._commonSettings,
                        attributeName = commonSettings.colorGroupingField;
                    this._groupByColor(commonSettings.colorGroups, commonSettings.palette, function(proxy) {
                        return proxy.attribute(attributeName)
                    })
                },
                _arrangeItems: _noop
            });
        function getCoordinatesDefault(dataItem) {
            return dataItem.coordinates
        }
        function getCoordinatesGeoJson(dataItem) {
            var coordinates,
                type;
            if (dataItem.geometry) {
                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, {
            _project: function(projection, coords) {
                return projection.projectArea(coords)
            },
            _createRoot: function() {
                return this._ctx.renderer.path([], "area").data(this._ctx.dataKey, this._data)
            },
            _update: function(settings) {
                this._styles = {
                    normal: {
                        "class": "dxm-area",
                        stroke: settings.borderColor,
                        "stroke-width": settings.borderWidth,
                        fill: settings.color
                    },
                    hovered: {
                        "class": "dxm-area dxm-area-hovered",
                        stroke: settings.hoveredBorderColor,
                        "stroke-width": settings.hoveredBorderWidth,
                        fill: settings.hoveredColor
                    },
                    selected: {
                        "class": "dxm-area dxm-area-selected",
                        stroke: settings.selectedBorderColor,
                        "stroke-width": settings.selectedBorderWidth,
                        fill: settings.selectedColor
                    }
                };
                this._root.attr(this._styles.normal);
                return this
            },
            _transform: function(projection, coords) {
                return projection.getAreaCoordinates(coords)
            },
            _locate: function(coords) {
                this._root.attr({points: coords})
            },
            onHover: _noop,
            setDefaultState: function() {
                this._root.attr(this._styles.normal).toBackground()
            },
            setHoveredState: function() {
                this._root.attr(this._styles.hovered).toForeground()
            },
            setSelectedState: function() {
                this._root.attr(this._styles.selected).toForeground()
            },
            _createLabelRoot: function() {
                return this._ctx.renderer.g().attr({"class": "dxm-area-label"}).append(this._ctx.labelRoot)
            },
            _adjustLabel: function() {
                var that = this,
                    centroid = calculateAreaCentroid(that._coords),
                    bbox = that._label.text.getBBox(),
                    offset = -bbox.y - bbox.height / 2;
                that._centroid = centroid.coords;
                that._areaSize = _sqrt(centroid.area);
                that._labelSize = [bbox.width, bbox.height];
                that._label.text.attr({y: offset});
                that._label.tracker.attr({
                    x: bbox.x,
                    y: bbox.y + offset,
                    width: bbox.width,
                    height: bbox.height
                })
            },
            _locateLabel: function() {
                var that = this,
                    coords = that._ctx.projection.getPointCoordinates(that._centroid),
                    size = that._ctx.projection.getSquareSize([that._areaSize, that._areaSize]);
                that._label.root.attr({
                    translateX: coords.x,
                    translateY: coords.y,
                    visibility: that._labelSize[0] / size[0] < TOLERANCE && that._labelSize[1] / size[1] < TOLERANCE ? null : "hidden"
                })
            }
        });
        function calculatePolygonCentroid(coordinates) {
            var i = 0,
                ii = coordinates.length,
                v1,
                v2 = coordinates[ii - 1],
                cross,
                cx = 0,
                cy = 0,
                area = 0;
            for (; i < ii; ++i) {
                v1 = v2;
                v2 = coordinates[i];
                cross = v1[0] * v2[1] - v2[0] * v1[1];
                area += cross;
                cx += (v1[0] + v2[0]) * cross;
                cy += (v1[1] + v2[1]) * cross
            }
            area /= 2;
            cx /= 6 * area;
            cy /= 6 * area;
            return {
                    coords: [cx, cy],
                    area: _abs(area)
                }
        }
        function calculateAreaCentroid(coordinates) {
            var i = 0,
                ii = coordinates.length,
                centroid,
                resultCentroid,
                maxArea = 0;
            for (; i < ii; ++i) {
                centroid = calculatePolygonCentroid(coordinates[i]);
                if (centroid.area > maxArea) {
                    maxArea = centroid.area;
                    resultCentroid = centroid
                }
            }
            return resultCentroid
        }
        DX.viz.map._internal.AreasManager = AreasManager;
        DX.viz.map._internal.Area = Area;
        DX.viz.map._tests.AreasManager = AreasManager;
        DX.viz.map._tests.Area = Area;
        DX.viz.map.dxVectorMap.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,
            _math = Math,
            _round = _math.round,
            _max = _math.max,
            _min = _math.min,
            _extend = $.extend,
            _each = $.each,
            _isArray = DX.utils.isArray,
            CLASS_DEFAULT = "dxm-marker",
            CLASS_HOVERED = "dxm-marker dxm-marker-hovered",
            CLASS_SELECTED = "dxm-marker dxm-marker-selected",
            DOT = "dot",
            BUBBLE = "bubble",
            PIE = "pie",
            IMAGE = "image",
            DEFAULT_MARKER_TYPE = null,
            MARKER_TYPES = {};
        var MarkersManager = DX.viz.map.dxVectorMap.prototype._factory.MapItemsManager.inherit({
                _rootClass: "dxm-markers",
                _dataCategory: "markers",
                _eventNames: {
                    click: "markerClick",
                    hoverChanged: "markerHoverChanged",
                    selectionChanged: "markerSelectionChanged"
                },
                _init: function() {
                    var that = this;
                    that.callBase.apply(that, arguments);
                    that._context.getPieColors = function(count) {
                        return that._params.themeManager.getPieColors(that._commonSettings, count)
                    };
                    that._filter = that._params.renderer.shadowFilter("-40%", "-40%", "180%", "200%", 0, 1, 1, "#000000", 0.2)
                },
                _dispose: function() {
                    this.callBase.apply(this, arguments);
                    this._filter.dispose();
                    this._filter = null
                },
                _getItemCoordinates: function(dataItem) {
                    return dataItem.coordinates
                },
                _getItemAttributes: function(dataItem) {
                    return dataItem.attributes
                },
                _processSource: function(source) {
                    return source
                },
                _getCommonSettings: function(options) {
                    return this._params.themeManager.getCommonMarkerSettings(options)
                },
                _processOptions: function(options) {
                    var that = this;
                    that._commonType = parseMarkerType(options && options.type, DEFAULT_MARKER_TYPE);
                    that.callBase.apply(that, arguments);
                    that._commonSettings._filter = that._filter.ref
                },
                _arrangeBubbles: function() {
                    var markers = this._handles,
                        bubbles = [],
                        i,
                        ii = markers.length,
                        marker,
                        values = [],
                        minValue,
                        maxValue,
                        deltaValue;
                    if (this._commonSettings._bubble.sizeGroups)
                        return;
                    for (i = 0; i < ii; ++i) {
                        marker = markers[i];
                        if (marker.item.type === BUBBLE) {
                            bubbles.push(marker);
                            if (_isFinite(marker.proxy.value))
                                values.push(marker.proxy.value)
                        }
                    }
                    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.item.setSize(_isFinite(marker.proxy.value) ? (marker.proxy.value - minValue) / deltaValue : 0)
                    }
                },
                _itemType: "marker",
                _initProxy: function(proxy, dataItem) {
                    _each(dataItem, function(name, value) {
                        if (proxy[name] === undefined)
                            proxy[name] = value
                    });
                    proxy._TYPE = parseMarkerType(dataItem.type, null)
                },
                _getItemSettings: function(proxy, options) {
                    var type = proxy._TYPE || this._commonType,
                        settings = this._params.themeManager.getMarkerSettings(this._commonSettings, _extend({}, proxy.style, options), type);
                    proxy.text = proxy.text || settings.text;
                    return settings
                },
                _createItem: function(proxy) {
                    return new MARKER_TYPES[proxy._TYPE || this._commonType]
                },
                _updateGrouping: function() {
                    var that = this,
                        markerType = that._commonType,
                        colorDataField,
                        sizeDataField,
                        commonSettings = that._commonSettings["_" + markerType];
                    if (markerType === DOT || markerType === BUBBLE) {
                        colorDataField = commonSettings.colorGroupingField;
                        that._groupByColor(commonSettings.colorGroups, commonSettings.palette, function(proxy) {
                            return !proxy._TYPE || proxy._TYPE === markerType ? proxy.attribute(colorDataField) : NaN
                        })
                    }
                    sizeDataField = commonSettings.sizeGroupingField;
                    that._performGrouping(commonSettings.sizeGroups, "size", function(proxy) {
                        return !proxy._TYPE || proxy._TYPE === markerType ? proxy.value || proxy.attribute(sizeDataField) : NaN
                    }, function(count) {
                        var minSize = commonSettings.minSize > 0 ? _Number(commonSettings.minSize) : 0,
                            maxSize = commonSettings.maxSize >= minSize ? _Number(commonSettings.maxSize) : 0,
                            i = 0,
                            sizes = [];
                        for (i = 0; i < count; ++i)
                            sizes.push((minSize * (count - i - 1) + maxSize * i) / (count - 1));
                        return sizes
                    })
                },
                _updateLegendForPies: function() {
                    var count = 0;
                    _each(this._handles, function(_, handle) {
                        var proxy = handle.proxy,
                            values;
                        if (!proxy._TYPE || proxy._TYPE === PIE) {
                            values = proxy.values;
                            if (values && values.length > count)
                                count = values.length
                        }
                    });
                    if (count > 0)
                        this._params.dataExchanger.set(this._dataCategory, "color", $.map(this._context.getPieColors(count).slice(0, count), function(color, i) {
                            return {
                                    index: i,
                                    color: color
                                }
                        }))
                },
                _arrangeItems: function() {
                    this._arrangeBubbles();
                    this._updateLegendForPies()
                }
            });
        var baseMarkerBehavior = _extend({}, DX.viz.map._internal.mapItemBehavior, {
                _project: function(projection, coords) {
                    return projection.projectPoint(coords)
                },
                _createRoot: function() {
                    return this._ctx.renderer.g()
                },
                _update: function(settings) {
                    var that = this;
                    that._root.attr({"class": CLASS_DEFAULT}).clear();
                    that._create(settings, that._ctx.renderer, that._root);
                    return that
                },
                _transform: function(projection, coords) {
                    return projection.getPointCoordinates(coords)
                },
                _locate: function(coords) {
                    this._root.attr({
                        translateX: coords.x,
                        translateY: coords.y
                    })
                },
                onHover: function() {
                    this._root.toForeground()
                },
                setDefaultState: function() {
                    this._root.attr({"class": CLASS_DEFAULT}).toBackground();
                    this._applyDefault()
                },
                setHoveredState: function() {
                    this._root.attr({"class": CLASS_HOVERED});
                    this._applyHovered()
                },
                setSelectedState: function() {
                    this._root.attr({"class": CLASS_SELECTED}).toForeground();
                    this._applySelected()
                },
                _createLabelRoot: function() {
                    return this._root
                },
                _adjustLabel: function() {
                    var bbox = this._label.text.getBBox(),
                        x = _round(-bbox.x + this._size / 2) + 2,
                        y = _round(-bbox.y - bbox.height / 2) - 1;
                    this._label.text.attr({
                        x: x,
                        y: y
                    });
                    this._label.tracker.attr({
                        x: x + bbox.x - 1,
                        y: y + bbox.y - 1,
                        width: bbox.width + 2,
                        height: bbox.height + 2
                    })
                },
                _locateLabel: $.noop
            });
        function DotMarker(){}
        _extend(DotMarker.prototype, baseMarkerBehavior, {
            type: DOT,
            _create: function(style, renderer, root) {
                var that = this,
                    size = that._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),
                    r = size / 2;
                that._dotDefault = {
                    cx: 0,
                    cy: 0,
                    r: r,
                    stroke: style.borderColor,
                    "stroke-width": style.borderWidth,
                    fill: style.color,
                    filter: style.shadow ? style._filter : null
                };
                that._dotHovered = {
                    cx: 0,
                    cy: 0,
                    r: hoveredSize / 2,
                    stroke: style.hoveredBorderColor,
                    "stroke-width": style.hoveredBorderWidth,
                    fill: style.hoveredColor
                };
                that._dotSelected = {
                    cx: 0,
                    cy: 0,
                    r: selectedSize / 2,
                    stroke: style.selectedBorderColor,
                    "stroke-width": style.selectedBorderWidth,
                    fill: style.selectedColor
                };
                that._backDefault = {
                    cx: 0,
                    cy: 0,
                    r: r,
                    stroke: "none",
                    "stroke-width": 0,
                    fill: style.backColor,
                    opacity: style.backOpacity
                };
                that._backHovered = {
                    cx: 0,
                    cy: 0,
                    r: hoveredBackSize / 2,
                    stroke: "none",
                    "stroke-width": 0,
                    fill: style.backColor,
                    opacity: style.backOpacity
                };
                that._backSelected = {
                    cx: 0,
                    cy: 0,
                    r: selectedBackSize / 2,
                    stroke: "none",
                    "stroke-width": 0,
                    fill: style.backColor,
                    opacity: style.backOpacity
                };
                that._back = renderer.circle().sharp().attr(that._backDefault).data(that._ctx.dataKey, that._data).append(root);
                that._dot = renderer.circle().sharp().attr(that._dotDefault).data(that._ctx.dataKey, that._data).append(root)
            },
            _destroy: function() {
                this._back = this._dot = null
            },
            _applyDefault: function() {
                this._back.attr(this._backDefault);
                this._dot.attr(this._dotDefault)
            },
            _applyHovered: function() {
                this._back.attr(this._backHovered);
                this._dot.attr(this._dotHovered)
            },
            _applySelected: function() {
                this._back.attr(this._backSelected);
                this._dot.attr(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._proxy.value) ? _Number(that._proxy.value) : null;
                that._default = {
                    stroke: style.borderColor,
                    "stroke-width": style.borderWidth,
                    fill: style.color,
                    opacity: style.opacity
                };
                that._hovered = {
                    stroke: style.hoveredBorderColor,
                    "stroke-width": style.hoveredBorderWidth,
                    fill: style.hoveredColor,
                    opacity: style.hoveredOpacity
                };
                that._selected = {
                    stroke: style.selectedBorderColor,
                    "stroke-width": style.selectedBorderWidth,
                    fill: style.selectedColor,
                    opacity: style.selectedOpacity
                };
                that._bubble = renderer.circle(0, 0, 0).sharp().attr(that._default).data(that._ctx.dataKey, that._data).append(root);
                that.setSize(style.size / that._maxSize || 1)
            },
            _applyDefault: function() {
                this._bubble.attr(this._default)
            },
            _applyHovered: function() {
                this._bubble.attr(this._hovered)
            },
            _applySelected: function() {
                this._bubble.attr(this._selected)
            },
            setSize: function(ratio) {
                var that = this,
                    r = (that._minSize + ratio * (that._maxSize - that._minSize)) / 2;
                that._default.r = that._hovered.r = that._selected.r = r;
                that._size = 2 * r;
                that._bubble.attr({r: r});
                return that
            }
        });
        function PieMarker(){}
        _extend(PieMarker.prototype, baseMarkerBehavior, {
            type: PIE,
            _create: function(style, renderer, root) {
                var that = this,
                    r = (style.size > 0 ? _Number(style.size) : 0) / 2,
                    srcValues,
                    i = 0,
                    ii,
                    values,
                    value,
                    sum = 0,
                    translator,
                    startAngle,
                    endAngle,
                    colors;
                that._size = 2 * r;
                that._pieDefault = {opacity: style.opacity};
                that._pieHovered = {opacity: style.hoveredOpacity};
                that._pieSelected = {opacity: style.selectedOpacity};
                that._borderDefault = {
                    stroke: style.borderColor,
                    "stroke-width": style.borderWidth
                };
                that._borderHovered = {
                    stroke: style.hoveredBorderColor,
                    "stroke-width": style.hoveredBorderWidth
                };
                that._borderSelected = {
                    stroke: style.selectedBorderColor,
                    "stroke-width": style.selectedBorderWidth
                };
                srcValues = that._proxy.values;
                ii = _isArray(srcValues) ? srcValues.length : 0;
                values = [];
                for (; i < ii; ++i) {
                    value = _Number(srcValues[i]);
                    if (_isFinite(value)) {
                        values.push(value);
                        sum += value
                    }
                }
                that._pie = renderer.g().attr(that._pieDefault);
                translator = new DX.viz.core.Translator1D(0, sum, 90, 450);
                startAngle = translator.translate(0);
                colors = that._ctx.getPieColors(values.length);
                for (value = 0, i = 0, ii = values.length; i < ii; ++i) {
                    value += values[i];
                    endAngle = translator.translate(value);
                    renderer.arc(0, 0, 0, r, startAngle, endAngle).attr({
                        "stroke-linejoin": "round",
                        fill: colors[i]
                    }).data(that._ctx.dataKey, that._data).append(that._pie);
                    startAngle = endAngle
                }
                that._pie.append(root);
                that._border = renderer.circle(0, 0, r).sharp().attr(that._borderDefault).data(that._ctx.dataKey, that._data).append(root)
            },
            _applyDefault: function() {
                this._pie.attr(this._pieDefault);
                this._border.attr(this._borderDefault)
            },
            _applyHovered: function() {
                this._pie.attr(this._pieHovered);
                this._border.attr(this._borderHovered)
            },
            _applySelected: function() {
                this._pie.attr(this._pieSelected);
                this._border.attr(this._borderSelected)
            }
        });
        function ImageMarker(){}
        _extend(ImageMarker.prototype, baseMarkerBehavior, {
            type: IMAGE,
            _create: function(style, renderer, root) {
                var that = this,
                    size = that._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.image().attr(that._default).attr({
                    href: that._proxy.url,
                    location: "center"
                }).append(root);
                that._tracker = renderer.rect().attr(that._default).attr({
                    stroke: "none",
                    "stroke-width": 0,
                    fill: "#000000",
                    opacity: 0.0001
                }).data(that._ctx.dataKey, that._data).append(root)
            },
            _applyDefault: function() {
                this._image.attr(this._default);
                this._tracker.attr(this._default)
            },
            _applyHovered: function() {
                this._image.attr(this._hovered);
                this._tracker.attr(this._hovered)
            },
            _applySelected: function() {
                this._image.attr(this._selected);
                this._tracker.attr(this._selected)
            }
        });
        _each([DotMarker, BubbleMarker, PieMarker, ImageMarker], function(_, markerType) {
            DEFAULT_MARKER_TYPE = DEFAULT_MARKER_TYPE || markerType.prototype.type;
            MARKER_TYPES[markerType.prototype.type] = markerType
        });
        function parseMarkerType(type, defaultType) {
            var _type = _String(type).toLowerCase();
            return MARKER_TYPES[_type] ? _type : defaultType
        }
        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.dxVectorMap.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, undefined) {
        var DEFAULT_LINE_SPACING = 2,
            DEFAULT_EVENTS_DELAY = 200,
            TOUCH_EVENTS_DELAY = 1000,
            _extend = $.extend,
            _abs = Math.abs,
            core = DX.viz.core;
        function generateDefaultCustomizeTooltipCallback(fontOptions, rtlEnabled) {
            var lineSpacing = fontOptions.lineSpacing,
                lineHeight = (lineSpacing !== undefined && lineSpacing !== null ? lineSpacing : DEFAULT_LINE_SPACING) + fontOptions.size;
            DX.viz.sparklines.generated_customize_tooltip = function() {
                return {
                        lineHeight: lineHeight,
                        rtlEnabled: rtlEnabled
                    }
            };
            return function(customizeObject) {
                    var html = "",
                        vt = customizeObject.valueText;
                    for (var i = 0; i < vt.length; i += 2)
                        html += "
| " + vt[i] + " |  | " + vt[i + 1] + " | 
";
                    return {html: "
"}
                }
        }
        DX.viz.sparklines = {};
        DX.viz.sparklines.BaseSparkline = core.BaseWidget.inherit({
            _setDeprecatedOptions: function() {
                this.callBase();
                $.extend(this._deprecatedOptions, {
                    "tooltip.verticalAlignment": {
                        since: "15.1",
                        message: "Now tootips are aligned automatically"
                    },
                    "tooltip.horizontalAlignment": {
                        since: "15.1",
                        message: "Now tootips are aligned automatically"
                    }
                })
            },
            _clean: function() {
                var that = this;
                if (that._tooltipShown) {
                    that._tooltipShown = false;
                    that._tooltip.hide()
                }
                that._cleanWidgetElements();
                that._cleanTranslators()
            },
            _initCore: function() {
                var that = this;
                that._tooltipTracker = that._renderer.root;
                that._tooltipTracker.attr({"pointer-events": "visible"});
                that._createHtmlElements();
                that._initTooltipEvents()
            },
            _initTooltip: function() {
                this._initTooltipBase = this.callBase;
                return
            },
            _getDefaultSize: function() {
                return this._defaultSize
            },
            _isContainerVisible: function() {
                return true
            },
            _disposeCore: function() {
                this._disposeWidgetElements();
                this._disposeTooltipEvents();
                this._ranges = null
            },
            _render: function() {
                this._prepareOptions();
                this._updateWidgetElements();
                this._drawWidgetElements()
            },
            _updateWidgetElements: function() {
                this._updateRange();
                this._updateTranslator()
            },
            _applySize: function() {
                if (this._allOptions)
                    this._allOptions.size = {
                        width: this._canvas.width,
                        height: this._canvas.height
                    }
            },
            _cleanTranslators: function() {
                this._translatorX = null;
                this._translatorY = null
            },
            _setupResizeHandler: $.noop,
            _resize: function() {
                var that = this;
                that._redrawWidgetElements();
                if (that._tooltipShown) {
                    that._tooltipShown = false;
                    that._tooltip.hide()
                }
                that._drawn()
            },
            _prepareOptions: function() {
                return _extend(true, {}, this._themeManager.theme(), this.option())
            },
            _createThemeManager: function() {
                var themeManager = new DX.viz.core.BaseThemeManager;
                themeManager._themeSection = this._widgetType;
                themeManager._fontFields = ["tooltip.font"];
                return themeManager
            },
            _getTooltipCoords: function() {
                var canvas = this._canvas,
                    rootOffset = this._renderer.getRootOffset();
                return {
                        x: canvas.width / 2 + rootOffset.left,
                        y: canvas.height / 2 + rootOffset.top
                    }
            },
            _initTooltipEvents: function() {
                var that = this,
                    data = {widget: that};
                that._showTooltipCallback = function() {
                    var tooltip;
                    that._showTooltipTimeout = null;
                    if (!that._tooltipShown) {
                        that._tooltipShown = true;
                        tooltip = that._getTooltip();
                        tooltip.isEnabled() && that._tooltip.show(that._getTooltipData(), that._getTooltipCoords(), {})
                    }
                    that._DEBUG_showCallback && that._DEBUG_showCallback()
                };
                that._hideTooltipCallback = function() {
                    var tooltipWasShown = that._tooltipShown;
                    that._hideTooltipTimeout = null;
                    if (that._tooltipShown) {
                        that._tooltipShown = false;
                        that._tooltip.hide()
                    }
                    that._DEBUG_hideCallback && that._DEBUG_hideCallback(tooltipWasShown)
                };
                that._disposeCallbacks = function() {
                    that = that._showTooltipCallback = that._hideTooltipCallback = that._disposeCallbacks = null
                };
                that._tooltipTracker.on(mouseEvents, data).on(touchEvents, data).on(mouseWheelEvents, data);
                that._tooltipTracker.on(menuEvents)
            },
            _disposeTooltipEvents: function() {
                var that = this;
                clearTimeout(that._showTooltipTimeout);
                clearTimeout(that._hideTooltipTimeout);
                that._tooltipTracker.off();
                that._disposeCallbacks()
            },
            _updateTranslator: function() {
                var that = this,
                    canvas = this._canvas,
                    ranges = this._ranges;
                that._translatorX = new core.Translator2D(ranges.arg, canvas, {direction: "horizontal"});
                that._translatorY = new core.Translator2D(ranges.val, canvas)
            },
            _getTooltip: function() {
                var that = this;
                if (!that._tooltip) {
                    that._initTooltipBase();
                    that._setTooltipRendererOptions(that._tooltipRendererOptions);
                    that._tooltipRendererOptions = null;
                    that._setTooltipOptions()
                }
                return that._tooltip
            },
            _setTooltipRendererOptions: function(options) {
                if (this._tooltip)
                    this._tooltip.setRendererOptions(options);
                else
                    this._tooltipRendererOptions = options
            },
            _setTooltipOptions: function() {
                var tooltip = this._tooltip,
                    options = tooltip && this._getOption("tooltip");
                tooltip && tooltip.update($.extend({}, options, {
                    customizeTooltip: !$.isFunction(options.customizeTooltip) ? generateDefaultCustomizeTooltipCallback(options.font, this.option("rtlEnabled")) : options.customizeTooltip,
                    enabled: options.enabled && this._isTooltipEnabled()
                }))
            },
            _showTooltip: function(delay) {
                var that = this;
                ++that._DEBUG_clearHideTooltipTimeout;
                clearTimeout(that._hideTooltipTimeout);
                that._hideTooltipTimeout = null;
                clearTimeout(that._showTooltipTimeout);
                ++that._DEBUG_showTooltipTimeoutSet;
                that._showTooltipTimeout = setTimeout(that._showTooltipCallback, delay)
            },
            _hideTooltip: function(delay) {
                var that = this;
                ++that._DEBUG_clearShowTooltipTimeout;
                clearTimeout(that._showTooltipTimeout);
                that._showTooltipTimeout = null;
                clearTimeout(that._hideTooltipTimeout);
                if (delay) {
                    ++that._DEBUG_hideTooltipTimeoutSet;
                    that._hideTooltipTimeout = setTimeout(that._hideTooltipCallback, delay)
                }
                else
                    that._hideTooltipCallback()
            },
            _initLoadingIndicator: $.noop,
            _disposeLoadingIndicator: $.noop,
            _handleLoadingIndicatorOptionChanged: $.noop,
            showLoadingIndicator: $.noop,
            hideLoadingIndicator: $.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._showTooltip(DEFAULT_EVENTS_DELAY)
                },
                "mouseout.sparkline-tooltip": function(event) {
                    if (isPointerDownCalled)
                        return;
                    var widget = event.data.widget;
                    widget._tooltipTracker.off(mouseMoveEvents);
                    widget._hideTooltip(DEFAULT_EVENTS_DELAY)
                }
            };
        var mouseWheelEvents = {"dxmousewheel.sparkline-tooltip": function(event) {
                    event.data.widget._hideTooltip()
                }};
        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._showTooltip(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._hideTooltip(DEFAULT_EVENTS_DELAY);
                widget = active_touch_tooltip_widget = event.data.widget;
                widget._showTooltip(TOUCH_EVENTS_DELAY);
                widget._touch = true
            },
            touchstartDocumentProcessing = function() {
                var widget = active_touch_tooltip_widget;
                if (widget) {
                    if (!widget._touch) {
                        widget._hideTooltip(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._hideTooltip(DEFAULT_EVENTS_DELAY);
                        active_touch_tooltip_widget = null
                    }
            },
            isPointerDownCalled = false;
        var touchEvents = {
                "pointerdown.sparkline-tooltip": touchstartTooltipProcessing,
                "touchstart.sparkline-tooltip": touchstartTooltipProcessing
            };
        $(document).on({
            "pointerdown.sparkline-tooltip": function() {
                isPointerDownCalled = true;
                touchstartDocumentProcessing()
            },
            "touchstart.sparkline-tooltip": touchstartDocumentProcessing,
            "pointerup.sparkline-tooltip": touchendDocumentProcessing,
            "touchend.sparkline-tooltip": touchendDocumentProcessing
        });
        DX.viz.sparklines.BaseSparkline._DEBUG_reset = function() {
            active_touch_tooltip_widget = null
        }
    })(jQuery, DevExpress);
    /*! Module viz-sparklines, file sparkline.js */
    (function($, DX, undefined) {
        var viz = DX.viz,
            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,
            ALLOWED_TYPES = {
                line: true,
                spline: true,
                stepline: true,
                area: true,
                steparea: true,
                splinearea: true,
                bar: true,
                winloss: true
            },
            _map = $.map,
            _math = Math,
            _abs = _math.abs,
            _round = _math.round,
            _max = _math.max,
            _min = _math.min,
            _isFinite = isFinite,
            _isDefined = DX.utils.isDefined,
            _Number = Number,
            _String = String;
        DX.registerComponent("dxSparkline", viz.sparklines, viz.sparklines.BaseSparkline.inherit({
            _rootClassPrefix: "dxsl",
            _rootClass: "dxsl-sparkline",
            _widgetType: "sparkline",
            _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
            },
            _initCore: function() {
                this.callBase();
                this._refreshDataSource();
                this._createSeries()
            },
            _dataSourceChangedHandler: function() {
                if (this._initialized) {
                    this._clean();
                    this._updateWidgetElements();
                    this._drawWidgetElements()
                }
            },
            _updateWidgetElements: function() {
                this._updateSeries();
                this.callBase()
            },
            _dataSourceOptions: function() {
                return {paginate: false}
            },
            _redrawWidgetElements: function() {
                this._updateTranslator();
                this._correctPoints();
                this._series.draw({
                    x: this._translatorX,
                    y: this._translatorY
                });
                this._seriesGroup.append(this._renderer.root)
            },
            _disposeWidgetElements: function() {
                var that = this;
                delete that._seriesGroup;
                delete that._seriesLabelGroup;
                that._series && that._series.dispose();
                that._series = null
            },
            _cleanWidgetElements: function() {
                this._seriesGroup.remove();
                this._seriesLabelGroup.remove();
                this._seriesGroup.clear();
                this._seriesLabelGroup.clear()
            },
            _drawWidgetElements: function() {
                if (this._isDataSourceReady()) {
                    this._drawSeries();
                    this._drawn()
                }
            },
            _prepareOptions: function() {
                this._allOptions = this.callBase();
                this._allOptions.type = _String(this._allOptions.type).toLowerCase();
                if (!ALLOWED_TYPES[this._allOptions.type])
                    this._allOptions.type = "line"
            },
            _createHtmlElements: function() {
                this._seriesGroup = this._renderer.g().attr({"class": "dxsl-series"});
                this._seriesLabelGroup = this._renderer.g().attr({"class": "dxsl-series-labels"})
            },
            _createSeries: function() {
                this._series = new core.series.Series({
                    renderer: this._renderer,
                    seriesGroup: this._seriesGroup,
                    labelsGroup: this._seriesLabelGroup
                }, {
                    widgetType: "chart",
                    type: "line"
                })
            },
            getSeriesOptions: function() {
                return this._series.getOptions()
            },
            _updateSeries: function() {
                var that = this,
                    groupSeries,
                    dataValidator,
                    seriesOptions;
                that._prepareDataSource();
                seriesOptions = that._prepareSeriesOptions();
                that._series.updateOptions(seriesOptions);
                groupSeries = [[that._series]];
                groupSeries.argumentOptions = {type: seriesOptions.type === "bar" ? "discrete" : undefined};
                dataValidator = new core.DataValidator(that._simpleDataSource, groupSeries, that._incidentOccured, {
                    checkTypeForAllData: false,
                    convertToAxisDataType: true,
                    sortingMethod: true
                });
                that._simpleDataSource = dataValidator.validate();
                that._series.updateData(that._simpleDataSource)
            },
            _optionChanged: function(args) {
                if (args.name === "dataSource" && this._allOptions)
                    this._refreshDataSource();
                else
                    this.callBase.apply(this, arguments)
            },
            _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,
                    type = options.type === "winloss" ? "bar" : options.type;
                return {
                        visible: true,
                        argumentField: options.argumentField,
                        valueField: options.valueField,
                        color: options.lineColor,
                        width: options.lineWidth,
                        widgetType: "chart",
                        type: type,
                        opacity: type.indexOf("area") !== -1 ? that._allOptions.areaOpacity : undefined,
                        customizePoint: that._getCustomizeFunction(),
                        point: {
                            size: options.pointSize,
                            symbol: options.pointSymbol,
                            border: {
                                visible: true,
                                width: 2
                            },
                            color: options.pointColor,
                            visible: false,
                            hoverStyle: {border: {}},
                            selectionStyle: {border: {}}
                        },
                        border: {
                            color: options.lineColor,
                            width: options.lineWidth,
                            visible: type !== "bar"
                        }
                    }
            },
            _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
                    }
            },
            _updateRange: function() {
                var that = this,
                    series = that._series,
                    type = series.type,
                    isBarType = type === "bar",
                    isWinlossType = type === "winloss",
                    DEFAULT_VALUE_RANGE_MARGIN = 0.15,
                    DEFAULT_ARGUMENT_RANGE_MARGIN = 0.1,
                    WINLOSS_MAX_RANGE = 1,
                    WINLOSS_MIN_RANGE = -1,
                    rangeData = series.getRangeData(),
                    minValue = that._allOptions.minValue,
                    hasMinY = _isDefined(minValue) && _isFinite(minValue),
                    maxValue = that._allOptions.maxValue,
                    hasMaxY = _isDefined(maxValue) && _isFinite(maxValue),
                    valCoef,
                    argCoef;
                valCoef = (rangeData.val.max - rangeData.val.min) * DEFAULT_VALUE_RANGE_MARGIN;
                if (isBarType || isWinlossType || type === "area") {
                    if (rangeData.val.min !== 0)
                        rangeData.val.min -= valCoef;
                    if (rangeData.val.max !== 0)
                        rangeData.val.max += valCoef
                }
                else {
                    rangeData.val.min -= valCoef;
                    rangeData.val.max += valCoef
                }
                if (hasMinY || hasMaxY) {
                    if (hasMinY && hasMaxY) {
                        rangeData.val.minVisible = _min(minValue, maxValue);
                        rangeData.val.maxVisible = _max(minValue, maxValue)
                    }
                    else {
                        rangeData.val.minVisible = hasMinY ? _Number(minValue) : undefined;
                        rangeData.val.maxVisible = hasMaxY ? _Number(maxValue) : undefined
                    }
                    if (isWinlossType) {
                        rangeData.val.minVisible = hasMinY ? _max(rangeData.val.minVisible, WINLOSS_MIN_RANGE) : undefined;
                        rangeData.val.maxVisible = hasMaxY ? _min(rangeData.val.maxVisible, WINLOSS_MAX_RANGE) : undefined
                    }
                }
                if (series.getPoints().length > 1)
                    if (isBarType) {
                        argCoef = (rangeData.arg.max - rangeData.arg.min) * DEFAULT_ARGUMENT_RANGE_MARGIN;
                        rangeData.arg.min = rangeData.arg.min - argCoef;
                        rangeData.arg.max = rangeData.arg.max + argCoef
                    }
                    else
                        rangeData.arg.stick = true;
                that._ranges = rangeData
            },
            _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.root)
                }
            },
            _isTooltipEnabled: function() {
                return !!this._simpleDataSource.length
            },
            _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, undefined) {
        var 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,
            _Number = Number,
            _isFinite = isFinite;
        DX.registerComponent("dxBullet", DX.viz.sparklines, DX.viz.sparklines.BaseSparkline.inherit({
            _rootClassPrefix: "dxb",
            _rootClass: "dxb-bullet",
            _widgetType: "bullet",
            _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._updateTranslator();
                this._drawBarValue();
                this._drawTarget();
                this._drawZeroLevel()
            },
            _cleanWidgetElements: function() {
                this._zeroLevelPath.remove();
                this._targetPath.remove();
                this._barValuePath.remove()
            },
            _drawWidgetElements: function() {
                this._drawBullet();
                this._drawn()
            },
            _createHtmlElements: function() {
                var renderer = this._renderer;
                this._zeroLevelPath = renderer.path(undefined, "line").attr({
                    "class": "dxb-zero-level",
                    "stroke-linecap": "square"
                });
                this._targetPath = renderer.path(undefined, "line").attr({
                    "class": "dxb-target",
                    "stroke-linecap": "square"
                });
                this._barValuePath = renderer.path(undefined, "line").attr({
                    "class": "dxb-bar-value",
                    "stroke-linecap": "square"
                })
            },
            _prepareOptions: function() {
                var that = this,
                    options,
                    startScaleValue,
                    endScaleValue,
                    level,
                    value,
                    target,
                    isValueUndefined,
                    isTargetUndefined;
                that._allOptions = options = that.callBase();
                isValueUndefined = that._allOptions.value === undefined;
                isTargetUndefined = that._allOptions.target === undefined;
                that._tooltipEnabled = !(isValueUndefined && isTargetUndefined);
                if (isValueUndefined)
                    that._allOptions.value = 0;
                if (isTargetUndefined)
                    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
                }
            },
            _updateRange: 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()
                }
            },
            _getTargetParams: function() {
                var that = this,
                    options = that._allOptions,
                    translatorY = that._translatorY,
                    x = that._translatorX.translate(options.target);
                return {
                        points: [x, translatorY.translate(TARGET_MIN_Y), x, translatorY.translate(TARGET_MAX_Y)],
                        stroke: options.targetColor,
                        "stroke-width": 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 < x1 ? x1 : value
                }
                else {
                    x1 = endLevel >= 0 ? 0 : endLevel;
                    x2 = value < startLevel ? startLevel : value > x1 ? x1 : value
                }
                x1 = translatorX.translate(x1);
                x2 = translatorX.translate(x2);
                return {
                        points: [x1, y1, x2, y1, x2, y2, x1, y2],
                        fill: options.color
                    }
            },
            _getZeroLevelParams: function() {
                var that = this,
                    translatorY = that._translatorY,
                    x = that._translatorX.translate(0);
                return {
                        points: [x, translatorY.translate(TARGET_MIN_Y), x, translatorY.translate(TARGET_MAX_Y)],
                        stroke: that._allOptions.targetColor,
                        "stroke-width": 1
                    }
            },
            _drawZeroLevel: function() {
                var that = this,
                    options = that._allOptions;
                if (0 > options.endScaleValue || 0 < options.startScaleValue || !options.showZeroLevel)
                    return;
                that._zeroLevelPath.attr(that._getZeroLevelParams()).sharp().append(that._renderer.root)
            },
            _drawTarget: function() {
                var that = this,
                    options = that._allOptions,
                    target = options.target;
                if (target > options.endScaleValue || target < options.startScaleValue || !options.showTarget)
                    return;
                that._targetPath.attr(that._getTargetParams()).sharp().append(that._renderer.root)
            },
            _drawBarValue: function() {
                this._barValuePath.attr(this._getBarValueParams()).append(this._renderer.root)
            },
            _getTooltipCoords: function() {
                var canvas = this._canvas,
                    rootOffset = this._renderer.getRootOffset(),
                    bbox = this._barValuePath.getBBox();
                return {
                        x: bbox.x + bbox.width / 2 + rootOffset.left,
                        y: canvas.height / 2 + rootOffset.top
                    }
            },
            _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]
                    }
            },
            _isTooltipEnabled: function() {
                return this._tooltipEnabled
            }
        }))
    })(jQuery, DevExpress);
    DevExpress.MOD_VIZ_SPARKLINES = true
}