").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
}