/*! * DevExtreme Web * Version: 15.1.4 * Build date: Jun 22, 2015 * * Copyright (c) 2012 - 2015 Developer Express Inc. ALL RIGHTS RESERVED * EULA: https://www.devexpress.com/Support/EULAs/DevExtreme.xml */ "use strict"; if (!window.DevExpress) { /*! Module core, file devexpress.js */ (function($, global, undefined) { global.DevExpress = global.DevExpress || {}; $.extend(global.DevExpress, { VERSION: "15.1.4", abstract: function() { throw global.DevExpress.Error("E0001"); }, stringFormat: function() { var s = arguments[0], replaceDollarCount, reg, argument; for (var i = 0; i < arguments.length - 1; i++) { reg = new RegExp("\\{" + i + "\\}", "gm"); argument = arguments[i + 1]; if ($.type(argument) === "string" && argument.indexOf("$") >= 0) { replaceDollarCount = "$".replace("$", "$$").length; argument = argument.replace("$", replaceDollarCount === 1 ? "$$$$" : "$$") } s = s.replace(reg, argument) } return s }, parseUrl: function() { var a = document.createElement("a"), props = ["protocol", "hostname", "port", "pathname", "search", "hash"]; var normalizePath = function(value) { if (value.charAt(0) !== "/") value = "/" + value; return value }; return function(url) { a.href = url; var result = {}; $.each(props, function() { result[this] = a[this] }); result.pathname = normalizePath(result.pathname); return result } }(), processHardwareBackButton: function() { this.hardwareBackButton.fire() }, hardwareBackButton: $.Callbacks(), viewPort: function() { var $current; return function(element) { if (!arguments.length) return $current; var $element = $(element); var isNewViewportFound = !!$element.length; var prevViewPort = this.viewPort(); $current = isNewViewportFound ? $element : $("body"); this.viewPortChanged.fire(isNewViewportFound ? this.viewPort() : $(), prevViewPort) } }(), viewPortChanged: $.Callbacks(), hideTopOverlayCallback: function() { var callbacks = []; return { add: function(callback) { var indexOfCallback = $.inArray(callback, callbacks); if (indexOfCallback === -1) callbacks.push(callback) }, remove: function(callback) { var indexOfCallback = $.inArray(callback, callbacks); if (indexOfCallback !== -1) callbacks.splice(indexOfCallback, 1) }, fire: function() { var callback = callbacks.pop(), result = !!callback; if (result) callback(); return result }, hasCallback: function() { return callbacks.length > 0 }, reset: function() { callbacks = [] } } }(), compareVersions: function(x, y, maxLevel) { function normalizeArg(value) { if (typeof value === "string") return value.split("."); if (typeof value === "number") return [value]; return value } x = normalizeArg(x); y = normalizeArg(y); var length = Math.max(x.length, y.length); if (isFinite(maxLevel)) length = Math.min(length, maxLevel); for (var i = 0; i < length; i++) { var xItem = parseInt(x[i] || 0, 10), yItem = parseInt(y[i] || 0, 10); if (xItem < yItem) return -1; if (xItem > yItem) return 1 } return 0 }, rtlEnabled: false }); $(function() { DevExpress.viewPort(".dx-viewport") }) })(jQuery, this); /*! Module core, file errors.js */ (function($, DX) { var ERROR_MESSAGES = { E0001: "Method is not implemented", E0002: "Member name collision: {0}", E0003: "A class must be instantiated using the 'new' keyword", E0004: "The NAME property of the component is not specified", E0005: "Unknown device", E0006: "Unknown endpoint key is requested", E0007: "'Invalidate' method is called outside the update transaction", E0008: "Type of the option name is not appropriate to create an action", E0009: "Component '{0}' has not been initialized for an element", E0010: "Animation configuration with the '{0}' type requires '{1}' configuration as {2}", E0011: "Unknown animation type '{0}'", E0012: "jQuery version is too old. Please upgrade jQuery to 1.10.0 or later", E0013: "KnockoutJS version is too old. Please upgrade KnockoutJS to 2.3.0 or later", E0014: "The 'release' method shouldn't be called for an unlocked Lock object", E0015: "Queued task returned an unexpected result", E0017: "Event namespace is not defined", E0018: "DevExpress.ui.dxPopup widget is required", E0020: "Template engine '{0}' is not supported", E0021: "Unknown theme is set: {0}", E0022: "LINK[rel=dx-theme] tags must go before DevExpress included scripts", E0023: "Template name is not specified", E0100: "Unknown validation type is detected", E0101: "Misconfigured range validation rule is detected", E0102: "Misconfigured comparison validation rule is detected", E0110: "Unknown validation group is detected", E0120: "Adapter for a dxValidator component cannot be configured", W0000: "'{0}' is deprecated in {1}. {2}", W0001: "{0} - '{1}' option is deprecated in {2}. {3}", W0002: "{0} - '{1}' method is deprecated in {2}. {3}", W0003: "{0} - '{1}' property is deprecated in {2}. {3}", W0004: "Timeout for theme loading is over: {0}", W0005: "'{0}' event is deprecated in {1}. {2}" }; var ERROR_URL = "http://js.devexpress.com/error/" + DX.VERSION.split(".").slice(0, 2).join("_") + "/"; var combineMessage = function(args) { var id = args[0]; args = args.slice(1); return formatMessage(id, formatDetails(id, args)) }; var formatDetails = function(id, args) { args = [DX.ERROR_MESSAGES[id]].concat(args); return DX.stringFormat.apply(this, args).replace(/\.*\s*?$/, '') }; var formatMessage = function(id, details) { return DX.stringFormat.apply(this, ["{0} - {1}. See:\n{2}", id, details, ERROR_URL + id]) }; var makeError = function(args) { var id, details, message; id = args[0]; args = args.slice(1); details = formatDetails(id, args); message = formatMessage(id, details); return $.extend(new Error(message), { __id: id, __details: details }) }; $.extend(DX, { Error: function() { return makeError($.makeArray(arguments)) }, log: function(id) { var method = "log", logger = DX.utils.logger; if (/^E\d+$/.test(id)) method = "error"; else if (/^W\d+$/.test(id)) method = "warn"; logger[method](method === "log" ? id : combineMessage($.makeArray(arguments))) }, ERROR_MESSAGES: ERROR_MESSAGES }) })(jQuery, DevExpress); /*! Module core, file class.js */ (function($, global, DX, undefined) { DX.Class = function() { var wrapOverridden = function(baseProto, methodName, method) { return function() { var prevCallBase = this.callBase; this.callBase = baseProto[methodName]; try { return method.apply(this, arguments) } finally { this.callBase = prevCallBase } } }; var clonePrototype = function(obj) { var func = function(){}; func.prototype = obj.prototype; return new func }; var classImpl = function(){}; var redefine = function(members) { var that = this; if (!members) return that; var memberNames = $.map(members, function(_, k) { return k }); $.each(["toString", "toLocaleString", "valueOf"], function() { if (members[this]) memberNames.push(this) }); $.each(memberNames, function() { var overridden = $.isFunction(that.prototype[this]) && $.isFunction(members[this]); that.prototype[this] = overridden ? wrapOverridden(that.parent.prototype, this, members[this]) : members[this] }); return that }; var include = function() { var classObj = this; $.each(arguments, function() { if (this.ctor) classObj._includedCtors.push(this.ctor); if (this.postCtor) classObj._includedPostCtors.push(this.postCtor); for (var name in this) { if (name === "ctor" || name === "postCtor") continue; if (name in classObj.prototype) throw DX.Error("E0002", name); classObj.prototype[name] = this[name] } }); return classObj }; var subclassOf = function(parentClass) { if (this.parent === parentClass) return true; if (!this.parent || !this.parent.subclassOf) return false; return this.parent.subclassOf(parentClass) }; classImpl.inherit = function(members) { var inheritor = function() { if (!this || this === global || typeof this.constructor !== "function") throw DX.Error("E0003"); var instance = this, ctor = instance.ctor; $.each(instance.constructor._includedCtors, function() { this.call(instance) }); if (ctor) ctor.apply(instance, arguments); $.each(instance.constructor._includedPostCtors, function() { this.call(instance) }) }; inheritor.prototype = clonePrototype(this); inheritor.inherit = this.inherit; inheritor.redefine = redefine; inheritor.include = include; inheritor.subclassOf = subclassOf; inheritor.parent = this; inheritor._includedCtors = this._includedCtors ? this._includedCtors.slice(0) : []; inheritor._includedPostCtors = this._includedPostCtors ? this._includedPostCtors.slice(0) : []; inheritor.prototype.constructor = inheritor; inheritor.redefine(members); return inheritor }; return classImpl }() })(jQuery, this, DevExpress); /*! Module core, file queue.js */ (function($, global, undefined) { var DX = global.DevExpress; function createQueue(discardPendingTasks) { var _tasks = [], _busy = false; function exec() { while (_tasks.length) { _busy = true; var task = _tasks.shift(), result = task(); if (result === undefined) continue; if (result.then) { $.when(result).always(exec); return } throw DX.Error("E0015"); } _busy = false } function add(task, removeTaskCallback) { if (!discardPendingTasks) _tasks.push(task); else { if (_tasks[0] && removeTaskCallback) removeTaskCallback(_tasks[0]); _tasks = [task] } if (!_busy) exec() } function busy() { return _busy } return { add: add, busy: busy } } $.extend(global.DevExpress, { createQueue: createQueue, enqueue: createQueue().add }) })(jQuery, this); /*! Module core, file inflector.js */ (function($, DX, undefined) { var _normalize = function(text) { if (text === undefined || text === null) return ""; return String(text) }; var _ucfirst = function(text) { return _normalize(text).charAt(0).toUpperCase() + text.substr(1) }; var _chop = function(text) { return _normalize(text).replace(/([a-z\d])([A-Z])/g, "$1 $2").split(/[\s_-]+/) }; var dasherize = function(text) { return $.map(_chop(text), function(p) { return p.toLowerCase() }).join("-") }; var underscore = function(text) { return dasherize(text).replace(/-/g, "_") }; var camelize = function(text, upperFirst) { return $.map(_chop(text), function(p, i) { p = p.toLowerCase(); if (upperFirst || i > 0) p = _ucfirst(p); return p }).join("") }; var humanize = function(text) { return _ucfirst(dasherize(text).replace(/-/g, " ")) }; var titleize = function(text) { return $.map(_chop(text), function(p) { return _ucfirst(p.toLowerCase()) }).join(" ") }; DX.inflector = { dasherize: dasherize, camelize: camelize, humanize: humanize, titleize: titleize, underscore: underscore } })(jQuery, DevExpress); /*! Module core, file eventsMixin.js */ (function($, DX, undefined) { var EventsMixin = { ctor: function() { this._events = {} }, fireEvent: function(eventName, eventArgs) { var callbacks = this._events[eventName]; if (callbacks) callbacks.fireWith(this, eventArgs); return this }, on: function(eventName, eventHandler) { if ($.isPlainObject(eventName)) $.each(eventName, $.proxy(function(e, h) { this.on(e, h) }, this)); else { var callbacks = this._events[eventName], addFn; if (!callbacks) { callbacks = $.Callbacks(); this._events[eventName] = callbacks } addFn = callbacks.originalAdd || callbacks.add; addFn.call(callbacks, eventHandler) } return this }, off: function(eventName, eventHandler) { var callbacks = this._events[eventName]; if (callbacks) if ($.isFunction(eventHandler)) callbacks.remove(eventHandler); else callbacks.empty(); return this }, _disposeEvents: function() { $.each(this._events, function() { this.empty() }) }, _callbacksToEvents: function(className, eventNames) { var that = this; $.each(eventNames, function(_, eventName) { var callbacksProperty = that[eventName], originalAdd; if (callbacksProperty !== undefined) { originalAdd = callbacksProperty.add; callbacksProperty.originalAdd = originalAdd; callbacksProperty.add = function() { DX.log("W0003", className, eventName, "14.2", "Use the '" + eventName + "' event instead"); return originalAdd.apply(that, arguments) }; that._events[eventName] = callbacksProperty } }) } }; $.extend(DX, {EventsMixin: EventsMixin}) })(jQuery, DevExpress); /*! Module core, file jquery.js */ (function($, DX) { if (DX.compareVersions($.fn.jquery, [1, 10]) < 0) throw DX.Error("E0012"); })(jQuery, DevExpress); /*! Module core, file jquery.selectors.js */ (function($) { var focusable = function(element, tabIndex) { var nodeName = element.nodeName.toLowerCase(), isTabIndexNotNaN = !isNaN(tabIndex), isVisible = visible(element), isDisabled = element.disabled, isDefaultFocus = /^(input|select|textarea|button|object)$/.test(nodeName), isHyperlink = nodeName === "a", isFocusable = true; if (isDefaultFocus) isFocusable = !isDisabled; else if (isHyperlink) isFocusable = element.href || isTabIndexNotNaN; else isFocusable = isTabIndexNotNaN; return isVisible ? isFocusable : false }; var visible = function(element) { var $element = $(element); return $element.is(":visible") && $element.css("visibility") !== "hidden" && $element.parents().css("visibility") !== "hidden" }; $.extend(jQuery.expr[':'], { "dx-focusable": function(element) { return focusable(element, $.attr(element, "tabindex")) }, "dx-tabbable": function(element) { var tabIndex = $.attr(element, "tabindex"); return (isNaN(tabIndex) || tabIndex >= 0) && focusable(element, tabIndex) } }) })(jQuery); /*! Module core, file utils.common.js */ (function($, DX, undefined) { var isDefined = function(object) { return object !== null && object !== undefined }; var isString = function(object) { return $.type(object) === 'string' }; var isNumber = function(object) { return typeof object === "number" && isFinite(object) || $.isNumeric(object) }; var isObject = function(object) { return $.type(object) === 'object' }; var isArray = function(object) { return $.type(object) === 'array' }; var isDate = function(object) { return $.type(object) === 'date' }; var isFunction = function(object) { return $.type(object) === 'function' }; var isExponential = function(value) { return isNumber(value) && value.toString().indexOf('e') !== -1 }; var ensureDefined = function(value, defaultValue) { return isDefined(value) ? value : defaultValue }; var getImageSourceType = function(source) { if (!isDefined(source)) return false; if (/^fa fa-|^fa-.* fa/.test(source)) return "faIcon"; else if (/^ion-.*|ion.*ion-.*/.test(source)) return "ionIcon"; else if (/^glyphicon glyphicon-|^glyphicon-.* glyphicon/.test(source)) return "glyphIcon"; else if (/data:.*base64|\.|\//.test(source)) return "image"; else if (/^[\w-_]+$/.test(source)) return "dxIcon"; else return false }; var getImageContainer = function(source) { var imageType = getImageSourceType(source), ICON_CLASS = "dx-icon"; switch (imageType) { case"image": return $("", {src: source}).addClass(ICON_CLASS); case"faIcon": case"glyphIcon": return $("", {"class": ICON_CLASS + " " + source}); case"ionIcon": var result = $("", {"class": ICON_CLASS + " " + source}); if (!result.hasClass("ion") && !result.hasClass("ionicons")) result.addClass("ion"); return result; case"dxIcon": return $("", {"class": ICON_CLASS + " " + ICON_CLASS + "-" + source}); default: return null } }; var extendFromObject = function(target, source, overrideExistingValues) { target = target || {}; for (var prop in source) if (source.hasOwnProperty(prop)) { var value = source[prop]; if (!(prop in target) || overrideExistingValues) target[prop] = value } return target }; var clone = function() { function Clone(){} return function(obj) { Clone.prototype = obj; return new Clone } }(); var executeAsync = function(action, context) { var deferred = $.Deferred(), normalizedContext = context || this, timerId, task = { promise: deferred.promise(), abort: function() { clearTimeout(timerId); deferred.rejectWith(normalizedContext) } }, callback = function() { var result = action.call(normalizedContext); if (result && result.done && $.isFunction(result.done)) result.done(function() { deferred.resolveWith(normalizedContext) }); else deferred.resolveWith(normalizedContext) }; timerId = (arguments[2] || setTimeout)(callback, 0); return task }; var findBestMatches = function(targetFilter, items, mapFn) { var bestMatches = [], maxMatchCount = 0; $.each(items, function(index, itemSrc) { var matchCount = 0, item = mapFn ? mapFn(itemSrc) : itemSrc; $.each(targetFilter, function(paramName) { var value = item[paramName]; if (value === undefined) return; if (value === targetFilter[paramName]) { matchCount++; return } matchCount = -1; return false }); if (matchCount < maxMatchCount) return; if (matchCount > maxMatchCount) { bestMatches.length = 0; maxMatchCount = matchCount } bestMatches.push(itemSrc) }); return bestMatches }; var preg_quote = function(str) { return (str + "").replace(/([\+\*\?\\\.\[\^\]\$\(\)\{\}\><\|\=\!\:])/g, "\\$1") }; var replaceAll = function(text, searchToken, replacementToken) { return text.replace(new RegExp("(" + preg_quote(searchToken) + ")", "gi"), replacementToken) }; var splitPair = function(raw) { switch (typeof raw) { case"string": return raw.split(/\s+/, 2); case"object": return [raw.x || raw.h, raw.y || raw.v]; case"number": return [raw]; default: return raw } }; var stringPairToObject = function(raw) { var pair = splitPair(raw), h = parseInt(pair && pair[0], 10), v = parseInt(pair && pair[1], 10); if (!isFinite(h)) h = 0; if (!isFinite(v)) v = h; return { h: h, v: v } }; var orderEach = function(map, func) { var keys = [], key, i; for (key in map) keys.push(key); keys.sort(function(x, y) { var isNumberX = DX.utils.isNumber(x), isNumberY = DX.utils.isNumber(y); if (isNumberX && isNumberY) return x - y; if (isNumberX && !isNumberY) return -1; if (!isNumberX && isNumberY) return 1; if (x < y) return -1; if (x > y) return 1; return 0 }); for (i = 0; i < keys.length; i++) { key = keys[i]; func(key, map[key]) } }; function icontains(elem, text) { var result = false; $.each($(elem).contents(), function(index, content) { if (content.nodeType === 3 && (content.textContent || content.nodeValue || "").toLowerCase().indexOf((text || "").toLowerCase()) > -1) { result = true; return false } }); return result } $.expr[":"].dxicontains = $.expr.createPseudo(function(text) { return function(elem) { return icontains(elem, text) } }); function deepExtendArraySafe(target, changes) { var prevValue, newValue; for (var name in changes) { prevValue = target[name]; newValue = changes[name]; if (target === newValue) continue; if ($.isPlainObject(newValue) && !(newValue instanceof $.Event)) target[name] = deepExtendArraySafe($.isPlainObject(prevValue) ? prevValue : {}, newValue); else if (newValue !== undefined) target[name] = newValue } return target } function unwrapObservable(value) { if (DX.support.hasKo) return ko.utils.unwrapObservable(value); return value } function normalizeIndexes(items, indexParameterName, currentItem, needIndexCallback) { var indexedItems = {}, parameterIndex = 0; $.each(items, function(index, item) { index = item[indexParameterName]; if (isDefined(index)) { indexedItems[index] = indexedItems[index] || []; if (item === currentItem) indexedItems[index].unshift(item); else indexedItems[index].push(item); delete item[indexParameterName] } }); orderEach(indexedItems, function(index, items) { $.each(items, function() { if (index >= 0) this[indexParameterName] = parameterIndex++ }) }); $.each(items, function() { if (!isDefined(this[indexParameterName]) && (!needIndexCallback || needIndexCallback(this))) this[indexParameterName] = parameterIndex++ }); return parameterIndex } DX.utils = { isDefined: isDefined, isString: isString, isNumber: isNumber, isObject: isObject, isArray: isArray, isDate: isDate, isFunction: isFunction, isExponential: isExponential, ensureDefined: ensureDefined, extendFromObject: extendFromObject, clone: clone, executeAsync: executeAsync, stringFormat: DX.stringFormat, findBestMatches: findBestMatches, replaceAll: replaceAll, deepExtendArraySafe: deepExtendArraySafe, splitPair: splitPair, stringPairToObject: stringPairToObject, normalizeIndexes: normalizeIndexes, orderEach: orderEach, unwrapObservable: unwrapObservable, getImageSourceType: getImageSourceType, getImageContainer: getImageContainer } })(jQuery, DevExpress); /*! Module core, file utils.console.js */ (function($, DX, undefined) { var logger = function() { var console = window.console; function info(text) { if (!console || !$.isFunction(console.info)) return; console.info(text) } function warn(text) { if (!console || !$.isFunction(console.warn)) return; console.warn(text) } function error(text) { if (!console || !$.isFunction(console.error)) return; console.error(text) } return { info: info, warn: warn, error: error } }(); var debug = function() { function assert(condition, message) { if (!condition) throw new Error(message); } function assertParam(parameter, message) { assert(parameter !== null && parameter !== undefined, message) } return { assert: assert, assertParam: assertParam } }(); $.extend(DX.utils, { logger: logger, debug: debug }) })(jQuery, DevExpress); /*! Module core, file utils.math.js */ (function($, DX, undefined) { var PI = Math.PI, LN10 = Math.LN10; var cos = Math.cos, sin = Math.sin, abs = Math.abs, log = Math.log, floor = Math.floor, ceil = Math.ceil, max = Math.max, isNaN = window.isNaN, Number = window.Number, NaN = window.NaN; var isNumber = DX.utils.isNumber, isExponential = DX.utils.isExponential; var getPrecision = function(value) { var stringFraction, stringValue = value.toString(), pointIndex = stringValue.indexOf('.'), startIndex, precision; if (isExponential(value)) { precision = getDecimalOrder(value); if (precision < 0) return Math.abs(precision); else return 0 } if (pointIndex !== -1) { startIndex = pointIndex + 1; stringFraction = stringValue.substring(startIndex, startIndex + 20); return stringFraction.length } return 0 }; var getLog = function(value, base) { if (!value) return NaN; return Math.log(value) / Math.log(base) }; var raiseTo = function(power, base) { return Math.pow(base, power) }; var sign = function(value) { if (value === 0) return 0; return value / abs(value) }; var normalizeAngle = function(angle) { return (angle % 360 + 360) % 360 }; var convertAngleToRendererSpace = function(angle) { return 90 - angle }; var degreesToRadians = function(value) { return PI * value / 180 }; var getCosAndSin = function(angle) { var angleInRadians = degreesToRadians(angle); return { cos: cos(angleInRadians), sin: sin(angleInRadians) } }; var DECIMAL_ORDER_THRESHOLD = 1E-14; var getDistance = function(x1, y1, x2, y2) { var diffX = x2 - x1, diffY = y2 - y1; return Math.sqrt(diffY * diffY + diffX * diffX) }; var getDecimalOrder = function(number) { var n = abs(number), cn; if (!isNaN(n)) { if (n > 0) { n = log(n) / LN10; cn = ceil(n); return cn - n < DECIMAL_ORDER_THRESHOLD ? cn : floor(n) } return 0 } return NaN }; var getAppropriateFormat = function(start, end, count) { var order = max(getDecimalOrder(start), getDecimalOrder(end)), precision = -getDecimalOrder(abs(end - start) / count), format; if (!isNaN(order) && !isNaN(precision)) { if (abs(order) <= 4) { format = 'fixedPoint'; precision < 0 && (precision = 0); precision > 4 && (precision = 4) } else { format = 'exponential'; precision += order - 1; precision > 3 && (precision = 3) } return { format: format, precision: precision } } return null }; var getFraction = function(value) { var valueString, dotIndex; if (isNumber(value)) { valueString = value.toString(); dotIndex = valueString.indexOf('.'); if (dotIndex >= 0) if (isExponential(value)) return valueString.substr(dotIndex + 1, valueString.indexOf('e') - dotIndex - 1); else { valueString = value.toFixed(20); return valueString.substr(dotIndex + 1, valueString.length - dotIndex + 1) } } return '' }; var getSignificantDigitPosition = function(value) { var fraction = getFraction(value), i; if (fraction) for (i = 0; i < fraction.length; i++) if (fraction.charAt(i) !== '0') return i + 1; return 0 }; var adjustValue = function(value) { var fraction = getFraction(value), nextValue, i; if (fraction) for (i = 1; i <= fraction.length; i++) { nextValue = roundValue(value, i); if (nextValue !== 0 && fraction[i - 2] && fraction[i - 1] && fraction[i - 2] === fraction[i - 1]) return nextValue } return value }; var roundValue = function(value, precision) { if (precision > 20) precision = 20; if (isNumber(value)) if (isExponential(value)) return Number(value.toExponential(precision)); else return Number(value.toFixed(precision)) }; var applyPrecisionByMinDelta = function(min, delta, value) { var minPrecision = getPrecision(min), deltaPrecision = getPrecision(delta); return roundValue(value, minPrecision < deltaPrecision ? deltaPrecision : minPrecision) }; var fitIntoRange = function(value, minValue, maxValue) { return Math.min(Math.max(value, minValue), maxValue) }; var getPower = function(value) { return value.toExponential().split("e")[1] }; $.extend(DX.utils, { getLog: getLog, raiseTo: raiseTo, sign: sign, normalizeAngle: normalizeAngle, convertAngleToRendererSpace: convertAngleToRendererSpace, degreesToRadians: degreesToRadians, getCosAndSin: getCosAndSin, getDecimalOrder: getDecimalOrder, getAppropriateFormat: getAppropriateFormat, getDistance: getDistance, getFraction: getFraction, adjustValue: adjustValue, roundValue: roundValue, applyPrecisionByMinDelta: applyPrecisionByMinDelta, getSignificantDigitPosition: getSignificantDigitPosition, getPower: getPower, fitIntoRange: fitIntoRange }); DX.utils.getPrecision = getPrecision })(jQuery, DevExpress); /*! Module core, file utils.date.js */ (function($, DX, undefined) { var isObject = DX.utils.isObject, isString = DX.utils.isString, isDate = DX.utils.isDate, isDefined = DX.utils.isDefined; var dateUnitIntervals = ['millisecond', 'second', 'minute', 'hour', 'day', 'week', 'month', 'quarter', 'year']; var addSubValues = function(value1, value2, isSub) { return value1 + (isSub ? -1 : 1) * value2 }; var toMilliseconds = function(value) { switch (value) { case'millisecond': return 1; case'second': return toMilliseconds('millisecond') * 1000; case'minute': return toMilliseconds('second') * 60; case'hour': return toMilliseconds('minute') * 60; case'day': return toMilliseconds('hour') * 24; case'week': return toMilliseconds('day') * 7; case'month': return toMilliseconds('day') * 30; case'quarter': return toMilliseconds('month') * 3; case'year': return toMilliseconds('day') * 365; default: return 0 } }; var convertMillisecondsToDateUnits = function(value) { var i, dateUnitCount, dateUnitInterval, dateUnitIntervals = ['millisecond', 'second', 'minute', 'hour', 'day', 'month', 'year'], result = {}; for (i = dateUnitIntervals.length - 1; i >= 0; i--) { dateUnitInterval = dateUnitIntervals[i]; dateUnitCount = Math.floor(value / toMilliseconds(dateUnitInterval)); if (dateUnitCount > 0) { result[dateUnitInterval + 's'] = dateUnitCount; value -= convertDateUnitToMilliseconds(dateUnitInterval, dateUnitCount) } } return result }; var dateToMilliseconds = function(tickInterval) { var milliseconds = 0; if (isObject(tickInterval)) $.each(tickInterval, function(key, value) { milliseconds += convertDateUnitToMilliseconds(key.substr(0, key.length - 1), value) }); if (isString(tickInterval)) milliseconds = convertDateUnitToMilliseconds(tickInterval, 1); return milliseconds }; var convertDateUnitToMilliseconds = function(dateUnit, count) { return toMilliseconds(dateUnit) * count }; var getDateUnitInterval = function(tickInterval) { var maxInterval = -1, i; if (isString(tickInterval)) return tickInterval; if (isObject(tickInterval)) { $.each(tickInterval, function(key, value) { for (i = 0; i < dateUnitIntervals.length; i++) if (value && (key === dateUnitIntervals[i] + 's' || key === dateUnitIntervals[i]) && maxInterval < i) maxInterval = i }); return dateUnitIntervals[maxInterval] } return '' }; var correctDateWithUnitBeginning = function(date, dateInterval, withCorrection) { var oldDate = new Date(date.getTime()), dayMonth, firstQuarterMonth, dateUnitInterval = getDateUnitInterval(dateInterval); switch (dateUnitInterval) { case'second': date.setMilliseconds(0); break; case'minute': date.setSeconds(0, 0); break; case'hour': date.setMinutes(0, 0, 0); break; case'year': date.setMonth(0); case'month': date.setDate(1); case'day': date.setHours(0, 0, 0, 0); break; case'week': dayMonth = date.getDate(); if (date.getDay() !== 0) dayMonth += 7 - date.getDay(); date.setDate(dayMonth); date.setHours(0, 0, 0, 0); break; case'quarter': firstQuarterMonth = DX.formatHelper.getFirstQuarterMonth(date.getMonth()); if (date.getMonth() !== firstQuarterMonth) date.setMonth(firstQuarterMonth); date.setDate(1); date.setHours(0, 0, 0, 0); break } if (withCorrection && dateUnitInterval !== "hour" && dateUnitInterval !== "minute" && dateUnitInterval !== "second") fixTimezoneGap(oldDate, date) }; var getDatesDifferences = function(date1, date2) { var differences, counter = 0; differences = { year: date1.getFullYear() !== date2.getFullYear(), month: date1.getMonth() !== date2.getMonth(), day: date1.getDate() !== date2.getDate(), hour: date1.getHours() !== date2.getHours(), minute: date1.getMinutes() !== date2.getMinutes(), second: date1.getSeconds() !== date2.getSeconds() }; $.each(differences, function(key, value) { if (value) counter++ }); differences.count = counter; return differences }; var addInterval = function(value, interval, isNegative) { var result = null, intervalObject; if (isDate(value)) { intervalObject = isString(interval) ? getDateIntervalByString(interval.toLowerCase()) : interval; result = new Date(value.getTime()); if (intervalObject.years) result.setFullYear(addSubValues(result.getFullYear(), intervalObject.years, isNegative)); if (intervalObject.quarters) result.setMonth(addSubValues(result.getMonth(), 3 * intervalObject.quarters, isNegative)); if (intervalObject.months) result.setMonth(addSubValues(result.getMonth(), intervalObject.months, isNegative)); if (intervalObject.weeks) result.setDate(addSubValues(result.getDate(), 7 * intervalObject.weeks, isNegative)); if (intervalObject.days) result.setDate(addSubValues(result.getDate(), intervalObject.days, isNegative)); if (intervalObject.hours) result.setHours(addSubValues(result.getHours(), intervalObject.hours, isNegative)); if (intervalObject.minutes) result.setMinutes(addSubValues(result.getMinutes(), intervalObject.minutes, isNegative)); if (intervalObject.seconds) result.setSeconds(addSubValues(result.getSeconds(), intervalObject.seconds, isNegative)); if (intervalObject.milliseconds) result.setMilliseconds(addSubValues(value.getMilliseconds(), intervalObject.milliseconds, isNegative)) } else result = addSubValues(value, interval, isNegative); return result }; var getFirstDateView = function(typeView, date) { if (!isDefined(date)) return; if (typeView === "month") return getFirstMonthDate(date); if (typeView === "year") return new Date(date.getFullYear(), 0, 1); if (typeView === "decade") return new Date(getFirstYearInDecade(date), 0, 1); if (typeView === "century") return new Date(getFirstDecadeInCentury(date), 0, 1) }; var getLastDateView = function(typeView, date) { if (typeView === "month") return new Date(date.getFullYear(), date.getMonth(), getLastDayOfMonth(date)); if (typeView === "year") return new Date(date.getFullYear(), 11, 1); if (typeView === "decade") return new Date(getFirstYearInDecade(date) + 9, 0, 1); if (typeView === "century") return new Date(getFirstDecadeInCentury(date) + 90, 0, 1) }; var sameView = function(view, date1, date2) { return DX.utils[DX.inflector.camelize("same " + view)](date1, date2) }; var getViewUp = function(typeView) { switch (typeView) { case"month": return "year"; case"year": return "decade"; case"decade": return "century"; default: break } }; var getViewDown = function(typeView) { switch (typeView) { case"century": return "decade"; case"decade": return "year"; case"year": return "month"; default: break } }; var getDifferenceInMonth = function(typeView) { var difference = 1; if (typeView === "year") difference = 12; if (typeView === "decade") difference = 12 * 10; if (typeView === "century") difference = 12 * 100; return difference }; var getDifferenceInMonthForCells = function(typeView) { var difference = 1; if (typeView === "decade") difference = 12; if (typeView === "century") difference = 12 * 10; return difference }; var getDateIntervalByString = function(intervalString) { var result = {}; switch (intervalString) { case'year': result.years = 1; break; case'month': result.months = 1; break; case'quarter': result.months = 3; break; case'week': result.days = 7; break; case'day': result.days = 1; break; case'hour': result.hours = 1; break; case'minute': result.minutes = 1; break; case'second': result.seconds = 1; break; case'millisecond': result.milliseconds = 1; break } return result }; var sameMonthAndYear = function(date1, date2) { return date1 && date2 && date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth() }; var sameYear = function(date1, date2) { return date1 && date2 && date1.getFullYear() === date2.getFullYear() }; var sameDecade = function(date1, date2) { if (!isDefined(date1) || !isDefined(date2)) return; var startDecadeDate1 = date1.getFullYear() - date1.getFullYear() % 10, startDecadeDate2 = date2.getFullYear() - date2.getFullYear() % 10; return date1 && date2 && startDecadeDate1 === startDecadeDate2 }; var sameCentury = function(date1, date2) { if (!isDefined(date1) || !isDefined(date2)) return; var startCenturyDate1 = date1.getFullYear() - date1.getFullYear() % 100, startCenturyDate2 = date2.getFullYear() - date2.getFullYear() % 100; return date1 && date2 && startCenturyDate1 === startCenturyDate2 }; var getFirstDecadeInCentury = function(date) { return date && date.getFullYear() - date.getFullYear() % 100 }; var getFirstYearInDecade = function(date) { return date && date.getFullYear() - date.getFullYear() % 10 }; var getShortDate = function(date) { return Globalize.format(date, "yyyy/M/d") }; var getLastDayOfMonth = function(date) { date = new Date(date.getFullYear(), date.getMonth() + 1, 0); return date.getDate() }; var getFirstMonthDate = function(date) { if (!isDefined(date)) return; var newDate = new Date(date.getFullYear(), date.getMonth(), 1); return newDate }; var getLastMonthDate = function(date) { if (!isDefined(date)) return; var newDate = new Date(date.getFullYear(), date.getMonth() + 1, 0); return newDate }; var getFirstWeekDate = function(date, firstDayOfWeek) { firstDayOfWeek = firstDayOfWeek || Globalize.culture().calendar.firstDay; var delta = (date.getDay() - firstDayOfWeek + 7) % 7; var result = new Date(date); result.setDate(date.getDate() - delta); return result }; var dateInRange = function(date, min, max) { return normalizeDate(date, min, max) === date }; var normalizeDate = function(date, min, max) { var normalizedDate = date; if (isDefined(min) && date < min) normalizedDate = min; if (isDefined(max) && date > max) normalizedDate = max; return normalizedDate }; var fixTimezoneGap = function(oldDate, newDate) { if (!DX.utils.isDefined(oldDate)) return; var diff = newDate.getHours() - oldDate.getHours(), sign, trial; if (diff === 0) return; sign = diff === 1 || diff === -23 ? -1 : 1, trial = new Date(newDate.getTime() + sign * 3600000); if (sign > 0 || trial.getDate() === newDate.getDate()) newDate.setTime(trial.getTime()) }; var makeDate = function(date) { if (!(date instanceof Date)) date = new Date(date); return date }; $.extend(DX.utils, { dateUnitIntervals: dateUnitIntervals, convertMillisecondsToDateUnits: convertMillisecondsToDateUnits, dateToMilliseconds: dateToMilliseconds, convertDateUnitToMilliseconds: convertDateUnitToMilliseconds, getDateUnitInterval: getDateUnitInterval, getDatesDifferences: getDatesDifferences, correctDateWithUnitBeginning: correctDateWithUnitBeginning, addInterval: addInterval, getDateIntervalByString: getDateIntervalByString, sameMonthAndYear: sameMonthAndYear, sameMonth: sameMonthAndYear, sameYear: sameYear, sameDecade: sameDecade, sameCentury: sameCentury, sameView: sameView, getDifferenceInMonth: getDifferenceInMonth, getDifferenceInMonthForCells: getDifferenceInMonthForCells, getFirstYearInDecade: getFirstYearInDecade, getFirstDecadeInCentury: getFirstDecadeInCentury, getShortDate: getShortDate, getFirstDateView: getFirstDateView, getLastDateView: getLastDateView, getViewDown: getViewDown, getViewUp: getViewUp, getLastMonthDate: getLastMonthDate, getFirstMonthDate: getFirstMonthDate, getFirstWeekDate: getFirstWeekDate, getLastDayOfMonth: getLastDayOfMonth, dateInRange: dateInRange, normalizeDate: normalizeDate, fixTimezoneGap: fixTimezoneGap, makeDate: makeDate }) })(jQuery, DevExpress); /*! Module core, file utils.recurrence.js */ (function($, DX, undefined) { var utils = DX.utils; var intervalMap = { secondly: "seconds", minutely: "minutes", hourly: "hours", daily: "days", weekly: "weeks", monthly: "months", yearly: "years" }; var dateSetterMap = { bysecond: function(date, value) { date.setSeconds(value) }, byminute: function(date, value) { date.setMinutes(value) }, byhour: function(date, value) { date.setHours(value) }, bymonth: function(date, value) { date.setMonth(value) }, bymonthday: function(date, value) { date.setDate(value) }, byday: function(date, dayOfWeek) { date.setDate(date.getDate() - date.getDay() + dayOfWeek) } }; var dateGetterMap = { bysecond: "getSeconds", byminute: "getMinutes", byhour: "getHours", bymonth: "getMonth", bymonthday: "getDate", byday: "getDay" }; var dateInRecurrenceRange = function(recurrenceString, currentDate, viewStartDate, viewEndDate) { var result = []; if (recurrenceString) result = getDatesByRecurrence(recurrenceString, currentDate, viewStartDate, viewEndDate); return !!result.length }; var normalizeInterval = function(freq, interval) { var intervalObject = {}, intervalField = intervalMap[freq.toLowerCase()]; intervalObject[intervalField] = interval; return intervalObject }; var getDatesByRecurrence = function(recurrenceString, recurrenceStartDate, viewStartDate, viewEndDate) { if (!recurrenceString) return []; var result = [], recurrenceRule = getRecurrenceRule(recurrenceString); if (!recurrenceRule.freq) return result; recurrenceRule.interval = normalizeInterval(recurrenceRule.freq, recurrenceRule.interval); viewEndDate = utils.normalizeDate(viewEndDate, viewStartDate, recurrenceRule.until); var recurrenceCounter = 0, dateCounter = 0, dateRules = splitDateRules(recurrenceRule), ruleDates = getDatesByRules(dateRules, recurrenceStartDate), currentDate = ruleDates[0], firstDate = new Date(recurrenceStartDate); utils.correctDateWithUnitBeginning(firstDate, recurrenceRule.interval); var firstDateInterval = getDatePartDiffs(recurrenceStartDate, firstDate); while (currentDate <= viewEndDate && recurrenceRule.count !== recurrenceCounter) { if (checkDateByRule(currentDate, dateRules)) { if (currentDate >= viewStartDate) { viewStartDate = new Date(currentDate); viewStartDate.setMilliseconds(viewStartDate.getMilliseconds() + 1); result.push(new Date(currentDate)) } recurrenceCounter++ } dateCounter++; currentDate = ruleDates[dateCounter % ruleDates.length]; if (dateCounter / ruleDates.length >= 1) { dateCounter = 0; firstDate = utils.addInterval(firstDate, recurrenceRule.interval); ruleDates = getDatesByRules(dateRules, utils.addInterval(firstDate, firstDateInterval)); currentDate = ruleDates[0] } } return result }; var getDatePartDiffs = function(date1, date2) { return { years: date1.getFullYear() - date2.getFullYear(), months: date1.getMonth() - date2.getMonth(), days: date1.getDate() - date2.getDate(), hours: date1.getHours() - date2.getHours(), minutes: date1.getMinutes() - date2.getMinutes(), seconds: date1.getSeconds() - date2.getSeconds() } }; var getRecurrenceRule = function(recurrence) { if (!recurrence) return {}; var ruleObject = {}, ruleStrings = recurrence.split(";"); for (var i = 0, len = ruleStrings.length; i < len; i++) { var rule = ruleStrings[i].split("="), ruleName = rule[0].toLowerCase(), ruleValue = rule[1]; ruleObject[ruleName] = ruleValue } return normalizeRRule(ruleObject) }; var normalizeRRule = function(rule) { var count = parseInt(rule.count); if (!isNaN(count)) rule.count = count; var interval = parseInt(rule.interval); rule.interval = isNaN(interval) ? 1 : interval; if (rule.freq && rule.until) rule.until = getDateByAsciiString(rule.until); return rule }; var getDateByAsciiString = function(string) { var date = Globalize.parseDate(string, "yyyyMMddThhmmss"); if (!date) date = Globalize.parseDate(string, "yyyyMMdd"); return date }; var getAsciiStringByDate = function(date) { return date.getFullYear() + ('0' + (date.getMonth() + 1)).slice(-2) + ('0' + date.getDate()).slice(-2) }; var splitDateRules = function(rule) { var result = []; for (var field in dateSetterMap) { if (!rule[field]) continue; var ruleFieldValues = rule[field].split(","), ruleArray = getDateRuleArray(field, ruleFieldValues); result = result.length ? extendObjectArray(ruleArray, result) : ruleArray } return result }; var getDateRuleArray = function(field, values) { var result = []; for (var i = 0, length = values.length; i < length; i++) { var dateRule = {}; dateRule[field] = handleRuleFieldValue(field, values[i]); result.push(dateRule) } return result }; var days = { SU: 0, MO: 1, TU: 2, WE: 3, TH: 4, FR: 5, SA: 6 }; var handleRuleFieldValue = function(field, value) { var result = parseInt(value); if (field === "bymonth") result -= 1; if (field === "byday") result = days[value]; return result }; var extendObjectArray = function(firstArray, secondArray) { var result = []; for (var i = 0, firstArrayLength = firstArray.length; i < firstArrayLength; i++) for (var j = 0, secondArrayLength = secondArray.length; j < secondArrayLength; j++) result.push($.extend({}, firstArray[i], secondArray[j])); return result }; var getDatesByRules = function(dateRules, startDate) { var updatedDate = new Date(startDate), result = []; for (var i = 0, len = dateRules.length; i < len; i++) { var current = dateRules[i]; for (var field in current) dateSetterMap[field](updatedDate, current[field]); result.push(new Date(updatedDate)) } if (!result.length) result.push(updatedDate); return result }; var checkDateByRule = function(date, rules) { var result = false; for (var i = 0; i < rules.length; i++) { var current = rules[i], currentRuleResult = true; for (var field in current) if (current[field] !== date[dateGetterMap[field]]()) currentRuleResult = false; result = result || currentRuleResult } return result || !rules.length }; var getRecurrenceString = function(object) { if (!object || !object.freq) return; var result = ""; for (var field in object) { if (field === "interval" && object[field] < 2) continue; result += field + "=" + object[field] + ";" } result = result.substring(0, result.length - 1); return result.toUpperCase() }; $.extend(DX.utils, { getRecurrenceString: getRecurrenceString, getRecurrenceRule: getRecurrenceRule, getAsciiStringByDate: getAsciiStringByDate, getDatesByRecurrence: getDatesByRecurrence, dateInRecurrenceRange: dateInRecurrenceRange }) })(jQuery, DevExpress); /*! Module core, file utils.dom.js */ (function($, DX, undefined) { var windowResizeCallbacks = function() { var prevSize, callbacks = $.Callbacks(), jqWindow = $(window), resizeEventHandlerAttached = false, originalCallbacksAdd = callbacks.add, originalCallbacksRemove = callbacks.remove; var formatSize = function() { return [jqWindow.width(), jqWindow.height()].join() }; var handleResize = function() { var now = formatSize(); if (now === prevSize) return; prevSize = now; setTimeout(callbacks.fire) }; prevSize = formatSize(); callbacks.add = function() { var result = originalCallbacksAdd.apply(callbacks, arguments); if (!resizeEventHandlerAttached && callbacks.has()) { jqWindow.on("resize", handleResize); resizeEventHandlerAttached = true } return result }; callbacks.remove = function() { var result = originalCallbacksRemove.apply(callbacks, arguments); if (!callbacks.has() && resizeEventHandlerAttached) { jqWindow.off("resize", handleResize); resizeEventHandlerAttached = false } return result }; return callbacks }(); var resetActiveElement = function() { var activeElement = document.activeElement; if (activeElement && activeElement !== document.body && activeElement.blur) activeElement.blur() }; var createMarkupFromString = function(str) { var tempElement = $("
"); if (window.WinJS) WinJS.Utilities.setInnerHTMLUnsafe(tempElement.get(0), str); else tempElement.append(str); return tempElement.contents() }; var initMobileViewport = function(options) { options = $.extend({}, options); var device = DX.devices.current(); var realDevice = DX.devices.real(); var allowZoom = options.allowZoom, allowPan = options.allowPan, allowSelection = "allowSelection" in options ? options.allowSelection : device.platform === "generic"; var metaSelector = "meta[name=viewport]"; if (!$(metaSelector).length) $("").attr("name", "viewport").appendTo("head"); var metaVerbs = ["width=device-width"], msTouchVerbs = []; if (allowZoom) msTouchVerbs.push("pinch-zoom"); else metaVerbs.push("initial-scale=1.0", "maximum-scale=1.0, user-scalable=no"); if (allowPan) msTouchVerbs.push("pan-x", "pan-y"); if (!allowPan && !allowZoom) $("html, body").css({ "-ms-content-zooming": "none", "-ms-user-select": "none", overflow: "hidden" }); else $("html").css("-ms-overflow-style", "-ms-autohiding-scrollbar"); if (!allowSelection && DX.support.supportProp("user-select")) $(".dx-viewport").css(DX.support.styleProp("user-select"), "none"); $(metaSelector).attr("content", metaVerbs.join()); $("html").css("-ms-touch-action", msTouchVerbs.join(" ") || "none"); if (DX.support.touch) $(document).off(".dxInitMobileViewport").on("dxpointermove.dxInitMobileViewport", function(e) { var count = e.pointers.length, isTouchEvent = e.pointerType === "touch", zoomDisabled = !allowZoom && count > 1, panDisabled = !allowPan && count === 1 && !e.isScrollingEvent; if (isTouchEvent && (zoomDisabled || panDisabled)) e.preventDefault() }); realDevice = DX.devices.real(); if (realDevice.ios) { var isPhoneGap = document.location.protocol === "file:"; if (!isPhoneGap) windowResizeCallbacks.add(function() { var windowWidth = $(window).width(); $("body").width(windowWidth) }) } if (realDevice.android) windowResizeCallbacks.add(function() { document.activeElement.scrollIntoViewIfNeeded() }) }; var triggerVisibilityChangeEvent = function(eventName) { var VISIBILITY_CHANGE_SELECTOR = ".dx-visibility-change-handler"; return function(element) { var $element = $(element || "body"); var $changeHandlers = $element.find(VISIBILITY_CHANGE_SELECTOR).add($element.filter(VISIBILITY_CHANGE_SELECTOR)); $changeHandlers.each(function() { $(this).triggerHandler(eventName) }) } }; var uniqueId = function() { var counter = 0; return function(prefix) { return (prefix || "") + counter++ } }(); DX.dataOptionsAttributeName = "data-options"; var getElementOptions = function(element) { var optionsString = $(element).attr(DX.dataOptionsAttributeName), result; if ($.trim(optionsString).charAt(0) !== "{") optionsString = "{" + optionsString + "}"; try { result = new Function("return " + optionsString)() } catch(ex) { throw DX.Error("E3018", ex, optionsString); } return result }; var createComponents = function(elements, componentTypes) { var result = [], selector = "[" + DX.dataOptionsAttributeName + "]"; elements.find(selector).addBack(selector).each(function(index, element) { var $element = $(element), options = getElementOptions(element); for (var componentName in options) if (!componentTypes || $.inArray(componentName, componentTypes) > -1) if ($element[componentName]) { $element[componentName](options[componentName]); result.push($element[componentName]("instance")) } }); return result }; var normalizeTemplateElement = function(element) { var $element = DX.utils.isDefined(element) && (element.nodeType || element.jquery) ? $(element) : $("
").html(element).contents(); if ($element.length === 1 && $element.is("script")) $element = normalizeTemplateElement(element.html()); return $element }; var clearSelection = function() { if (window.getSelection) { if (window.getSelection().empty) window.getSelection().empty(); else if (window.getSelection().removeAllRanges) window.getSelection().removeAllRanges() } else if (document.selection) document.selection.empty() }; var closestCommonParent = function(startTarget, endTarget) { var $startParents = $(startTarget).parents().addBack(), $endParents = $(endTarget).parents().addBack(), startingParent = Math.min($startParents.length, $endParents.length) - 1; for (var i = startingParent; i >= 0; i--) if ($startParents.eq(i).is($endParents.eq(i))) return $startParents.get(i) }; var toggleAttr = function($target, attr, value) { value ? $target.attr(attr, value) : $target.removeAttr(attr) }; var clipboardText = function(event, text) { var clipboard = event.originalEvent && event.originalEvent.clipboardData || window.clipboardData; if (arguments.length === 1) return clipboard && clipboard.getData("Text"); clipboard && clipboard.setData("Text", text) }; $.extend(DX.utils, { windowResizeCallbacks: windowResizeCallbacks, resetActiveElement: resetActiveElement, createMarkupFromString: createMarkupFromString, triggerShownEvent: triggerVisibilityChangeEvent("dxshown"), triggerHidingEvent: triggerVisibilityChangeEvent("dxhiding"), initMobileViewport: initMobileViewport, getElementOptions: getElementOptions, createComponents: createComponents, normalizeTemplateElement: normalizeTemplateElement, clearSelection: clearSelection, uniqueId: uniqueId, closestCommonParent: closestCommonParent, clipboardText: clipboardText, toggleAttr: toggleAttr }) })(jQuery, DevExpress); /*! Module core, file utils.caret.js */ (function($, DX, undefined) { var getCaret = function(input) { if (isObsoleteBrowser(input)) return getCaretForObsoleteBrowser(input); return { start: input.selectionStart, end: input.selectionEnd } }; var setCaret = function(input, position) { if (isObsoleteBrowser(input)) { setCaretForObsoleteBrowser(input, position); return } if (!$.contains(document, input)) return; input.selectionStart = position.start; input.selectionEnd = position.end }; var isObsoleteBrowser = function(input) { return !input.setSelectionRange }; var getCaretForObsoleteBrowser = function(input) { var range = document.selection.createRange(); var rangeCopy = range.duplicate(); range.move('character', -input.value.length); range.setEndPoint('EndToStart', rangeCopy); return { start: range.text.length, end: range.text.length + rangeCopy.text.length } }; var setCaretForObsoleteBrowser = function(input, position) { var range = input.createTextRange(); range.collapse(true); range.moveStart("character", position.start); range.moveEnd("character", position.end - position.start); range.select() }; var caret = function(input, position) { input = $(input).get(0); if (!DX.utils.isDefined(position)) return getCaret(input); setCaret(input, position) }; $.extend(DX.utils, {caret: caret}) })(jQuery, DevExpress); /*! Module core, file utils.graphics.js */ (function($, DX, undefined) { var _utils = DX.utils, isFunction = _utils.isFunction, _inArray = $.inArray, isDefined = _utils.isDefined; var processSeriesTemplate = function(seriesTemplate, items) { var customizeSeries = isFunction(seriesTemplate.customizeSeries) ? seriesTemplate.customizeSeries : $.noop, nameField = seriesTemplate.nameField || 'series', generatedSeries = {}, seriesOrder = [], series; for (var i = 0, length = items.length; i < length; i++) { var data = items[i]; if (nameField in data) { series = generatedSeries[data[nameField]]; if (!series) { series = generatedSeries[data[nameField]] = { name: data[nameField], data: [] }; seriesOrder.push(series.name) } series.data.push(data) } } return $.map(seriesOrder, function(orderedName) { var group = generatedSeries[orderedName], seriesOptions = customizeSeries.call(null, group.name); return $.extend(group, seriesOptions) }) }; var getCategoriesInfo = function(categories, startValue, endValue) { if (!(categories && categories.length > 0)) return {}; startValue = isDefined(startValue) ? startValue : categories[0]; endValue = isDefined(endValue) ? endValue : categories[categories.length - 1]; var categoriesValue = $.map(categories, function(category) { return category && category.valueOf() }), visibleCategories = [], indexStartValue = isDefined(startValue) ? _inArray(startValue.valueOf(), categoriesValue) : 0, indexEndValue = isDefined(endValue) ? _inArray(endValue.valueOf(), categoriesValue) : categories.length - 1, swapBuf, hasVisibleCategories, inverted = false, visibleCategoriesLen; indexStartValue < 0 && (indexStartValue = 0); indexEndValue < 0 && (indexEndValue = categories.length - 1); if (indexEndValue < indexStartValue) { swapBuf = indexEndValue; indexEndValue = indexStartValue; indexStartValue = swapBuf; inverted = true } visibleCategories = categories.slice(indexStartValue, indexEndValue + 1); visibleCategoriesLen = visibleCategories.length; hasVisibleCategories = visibleCategoriesLen > 0; return { categories: hasVisibleCategories ? visibleCategories : null, start: hasVisibleCategories ? visibleCategories[inverted ? visibleCategoriesLen - 1 : 0] : null, end: hasVisibleCategories ? visibleCategories[inverted ? 0 : visibleCategoriesLen - 1] : null, inverted: inverted } }; $.extend(_utils, { processSeriesTemplate: processSeriesTemplate, getCategoriesInfo: getCategoriesInfo }) })(jQuery, DevExpress); /*! Module core, file utils.arrays.js */ (function($, DX, undefined) { var isEmptyArray = function(entity) { return $.isArray(entity) && !entity.length }; var wrapToArray = function(entity) { return $.isArray(entity) ? entity : [entity] }; var removeDublicates = function(from, what) { if (!$.isArray(from) || from.length === 0) return []; if (!$.isArray(what) || what.length === 0) return from.slice(); var result = []; $.each(from, function(_, value) { var bIndex = $.inArray(value, what); if (bIndex === -1) result.push(value) }); return result }; $.extend(DX.utils, { isEmptyArray: isEmptyArray, wrapToArray: wrapToArray, removeDublicates: removeDublicates }) })(jQuery, DevExpress); /*! Module core, file devices.js */ (function($, DX, undefined) { var KNOWN_UA_TABLE = { iPhone: "iPhone", iPhone5: "iPhone", iPhone6: "iPhone", iPhone6plus: "iPhone", iPad: "iPad", iPadMini: "iPad Mini", androidPhone: "Android Mobile", androidTablet: "Android", win8: "MSAppHost", win8Phone: "Windows Phone 8", msSurface: "MSIE ARM Tablet PC", desktop: "desktop" }; var DEFAULT_DEVICE = { deviceType: "", platform: "", version: [], phone: false, tablet: false, android: false, ios: false, win8: false, generic: false, grade: "A", mac: false }; $.extend(DEFAULT_DEVICE, { platform: "generic", deviceType: "desktop", generic: true }); var uaParsers = { win8: function(userAgent) { var isPhone = /windows phone/i.test(userAgent) || userAgent.match(/WPDesktop/), isTablet = !isPhone && /arm(.*)trident/i.test(userAgent), isDesktop = !isPhone && !isTablet && /msapphost/i.test(userAgent); if (!(isPhone || isTablet || isDesktop)) return; var matches = userAgent.match(/windows phone (\d+).(\d+)/i) || userAgent.match(/windows nt (\d+).(\d+)/i), version = matches ? [parseInt(matches[1], 10), parseInt(matches[2], 10)] : []; return { deviceType: isPhone ? "phone" : isTablet ? "tablet" : "desktop", platform: "win8", version: version, grade: "A" } }, ios: function(userAgent) { if (!/ip(hone|od|ad)/i.test(userAgent)) return; var isPhone = /ip(hone|od)/i.test(userAgent), matches = userAgent.match(/os (\d+)_(\d+)_?(\d+)?/i), version = matches ? [parseInt(matches[1], 10), parseInt(matches[2], 10), parseInt(matches[3] || 0, 10)] : [], isIPhone4 = window.screen.height === 960 / 2, grade = isIPhone4 ? "B" : "A"; return { deviceType: isPhone ? "phone" : "tablet", platform: "ios", version: version, grade: grade } }, android: function(userAgent) { if (!/android|htc_|silk/i.test(userAgent)) return; var isPhone = /mobile/i.test(userAgent), matches = userAgent.match(/android (\d+)\.(\d+)\.?(\d+)?/i), version = matches ? [parseInt(matches[1], 10), parseInt(matches[2], 10), parseInt(matches[3] || 0, 10)] : [], worseThan4_4 = version.length > 1 && (version[0] < 4 || version[0] === 4 && version[1] < 4), grade = worseThan4_4 ? "B" : "A"; return { deviceType: isPhone ? "phone" : "tablet", platform: "android", version: version, grade: grade } } }; DX.Devices = DX.Class.inherit({ ctor: function(options) { this._window = options && options.window || window; this._realDevice = this._getDevice(); this._currentDevice = undefined; this._currentOrientation = undefined; this.orientationChanged = $.Callbacks(); this._callbacksToEvents("Devices", ["orientationChanged"]); this._recalculateOrientation(); DX.utils.windowResizeCallbacks.add($.proxy(this._recalculateOrientation, this)) }, current: function(deviceOrName) { if (deviceOrName) { this._currentDevice = this._getDevice(deviceOrName); this._forced = true; DX.ui.themes.init({_autoInit: true}) } else { if (!this._currentDevice) { deviceOrName = undefined; try { deviceOrName = this._getDeviceOrNameFromWindowScope() } catch(e) { deviceOrName = this._getDeviceNameFromSessionStorage() } finally { if (!deviceOrName) deviceOrName = this._getDeviceNameFromSessionStorage(); if (deviceOrName) this._forced = true } this._currentDevice = this._getDevice(deviceOrName) } return this._currentDevice } }, real: function() { var forceDevice = arguments[0]; if ($.isPlainObject(forceDevice)) { $.extend(this._realDevice, forceDevice); return } return $.extend({}, this._realDevice) }, orientation: function() { return this._currentOrientation }, isForced: function() { return this._forced }, isRippleEmulator: function() { return !!this._window.tinyHippos }, _getCssClasses: function(device) { var result = []; var realDevice = this._realDevice; device = device || this.current(); if (device.deviceType) { result.push("dx-device-" + device.deviceType); if (device.deviceType !== "desktop") result.push("dx-device-mobile") } result.push("dx-device-" + realDevice.platform); if (realDevice.version && realDevice.version.length) result.push("dx-device-" + realDevice.platform + "-" + realDevice.version[0]); if (DX.devices.isSimulator()) result.push("dx-simulator"); if (DX.rtlEnabled) result.push("dx-rtl"); return result }, attachCssClasses: function(element, device) { this._deviceClasses = this._getCssClasses(device).join(" "); $(element).addClass(this._deviceClasses) }, detachCssClasses: function(element) { $(element).removeClass(this._deviceClasses) }, isSimulator: function() { try { return this._isSimulator || this._window.top !== this._window.self && this._window.top["dx-force-device"] || this.isRippleEmulator() } catch(e) { return false } }, forceSimulator: function() { this._isSimulator = true }, _getDevice: function(deviceName) { if (deviceName === "genericPhone") deviceName = { deviceType: "phone", platform: "generic", generic: true }; if ($.isPlainObject(deviceName)) return this._fromConfig(deviceName); else { var ua; if (deviceName) { ua = KNOWN_UA_TABLE[deviceName]; if (!ua) throw DX.Error("E0005"); } else ua = navigator.userAgent; return this._fromUA(ua) } }, _getDeviceOrNameFromWindowScope: function() { var result; if (this._window.top["dx-force-device-object"] || this._window.top["dx-force-device"]) result = this._window.top["dx-force-device-object"] || this._window.top["dx-force-device"]; return result }, _getDeviceNameFromSessionStorage: function() { var sessionStorage; try { sessionStorage = this._window.sessionStorage } catch(e) {} if (!sessionStorage) return; var deviceOrName = sessionStorage.getItem("dx-force-device"); try { return $.parseJSON(deviceOrName) } catch(ex) { return deviceOrName } }, _fromConfig: function(config) { var shortcuts = { phone: config.deviceType === "phone", tablet: config.deviceType === "tablet", android: config.platform === "android", ios: config.platform === "ios", win8: config.platform === "win8", generic: config.platform === "generic" }; return $.extend({}, DEFAULT_DEVICE, this._currentDevice, shortcuts, config) }, _fromUA: function(ua) { var config; $.each(uaParsers, function(platform, parser) { config = parser(ua); return !config }); if (config) return this._fromConfig(config); var isMac = /(mac os)/.test(ua.toLowerCase()), deviceWithOS = DEFAULT_DEVICE; deviceWithOS.mac = isMac; return deviceWithOS }, _changeOrientation: function() { var $window = $(this._window), orientation = $window.height() > $window.width() ? "portrait" : "landscape"; if (this._currentOrientation === orientation) return; this._currentOrientation = orientation; this.orientationChanged.fire({orientation: orientation}) }, _recalculateOrientation: function() { var windowWidth = $(this._window).width(); if (this._currentWidth === windowWidth) return; this._currentWidth = windowWidth; this._changeOrientation() } }).include(DX.EventsMixin); DX.devices = new DX.Devices; DX.viewPortChanged.add(function(viewPort, prevViewport) { DX.devices.detachCssClasses(prevViewport); DX.devices.attachCssClasses(viewPort) }) })(jQuery, DevExpress); /*! Module core, file browser.js */ (function($, DX, global, undefined) { var webkitRegExp = /(webkit)[ \/]([\w.]+)/, operaRegExp = /(opera)(?:.*version)?[ \/]([\w.]+)/, ieRegExp = /(msie) (\d{1,2}\.\d)/, ie11RegExp = /(trident).*rv:(\d{1,2}\.\d)/, mozillaRegExp = /(mozilla)(?:.*? rv:([\w.]+))?/; var ua = navigator.userAgent.toLowerCase(); var browser = function() { var result = {}, matches = webkitRegExp.exec(ua) || operaRegExp.exec(ua) || ieRegExp.exec(ua) || ie11RegExp.exec(ua) || ua.indexOf("compatible") < 0 && mozillaRegExp.exec(ua) || [], browserName = matches[1], browserVersion = matches[2]; if (browserName === "trident") browserName = "msie"; if (browserName) { result[browserName] = true; result.version = browserVersion } return result }(); DX.browser = browser })(jQuery, DevExpress, this); /*! Module core, file support.js */ (function($, DX, window) { var jsPrefixes = ["", "Webkit", "Moz", "O", "Ms"], cssPrefixes = { "": "", Webkit: "-webkit-", Moz: "-moz-", O: "-o-", ms: "-ms-" }, styles = document.createElement("dx").style; var transitionEndEventNames = { webkitTransition: 'webkitTransitionEnd', MozTransition: 'transitionend', OTransition: 'oTransitionEnd', msTransition: 'MsTransitionEnd', transition: 'transitionend' }; var forEachPrefixes = function(prop, callBack) { prop = DX.inflector.camelize(prop, true); var result; for (var i = 0, cssPrefixesCount = jsPrefixes.length; i < cssPrefixesCount; i++) { var jsPrefix = jsPrefixes[i]; var prefixedProp = jsPrefix + prop; var lowerPrefixedProp = DX.inflector.camelize(prefixedProp); result = callBack(lowerPrefixedProp, jsPrefix); if (result === undefined) result = callBack(prefixedProp, jsPrefix); if (result !== undefined) break } return result }; var styleProp = function(prop) { return forEachPrefixes(prop, function(specific) { if (specific in styles) return specific }) }; var stylePropPrefix = function(prop) { return forEachPrefixes(prop, function(specific, jsPrefix) { if (specific in styles) return cssPrefixes[jsPrefix] }) }; var supportProp = function(prop) { return !!styleProp(prop) }; var isNativeScrollingSupported = function() { var realDevice = DX.devices.real(), realPlatform = realDevice.platform, realVersion = realDevice.version, isObsoleteAndroid = realVersion && realVersion[0] < 4 && realPlatform === "android", isNativeScrollDevice = !isObsoleteAndroid && $.inArray(realPlatform, ["ios", "android", "win8"]) > -1 || realDevice.mac; return isNativeScrollDevice }; DX.support = { touchEvents: "ontouchstart" in window, touch: "ontouchstart" in window || !!window.navigator.msMaxTouchPoints, pointer: window.navigator.pointerEnabled || window.navigator.msPointerEnabled, transform: supportProp("transform"), transition: supportProp("transition"), transitionEndEventName: transitionEndEventNames[styleProp("transition")], animation: supportProp("animation"), nativeScrolling: isNativeScrollingSupported(), winJS: "WinJS" in window, styleProp: styleProp, stylePropPrefix: stylePropPrefix, supportProp: supportProp, hasKo: !!window.ko, hasNg: !window.ko && !!window.angular, inputType: function(type) { if (type === "text") return true; var input = document.createElement("input"); try { input.setAttribute("type", type); input.value = "wrongValue"; return !input.value } catch(e) { return false } } } })(jQuery, DevExpress, this); /*! Module core, file position.js */ (function($, DX, undefined) { var horzRe = /left|right/, vertRe = /top|bottom/, collisionRe = /fit|flip|none/; var normalizeAlign = function(raw) { var result = { h: "center", v: "center" }; var pair = DX.utils.splitPair(raw); if (pair) $.each(pair, function() { var w = String(this).toLowerCase(); if (horzRe.test(w)) result.h = w; else if (vertRe.test(w)) result.v = w }); return result }; var normalizeOffset = function(raw) { return DX.utils.stringPairToObject(raw) }; var normalizeCollision = function(raw) { var pair = DX.utils.splitPair(raw), h = String(pair && pair[0]).toLowerCase(), v = String(pair && pair[1]).toLowerCase(); if (!collisionRe.test(h)) h = "none"; if (!collisionRe.test(v)) v = h; return { h: h, v: v } }; var getAlignFactor = function(align) { switch (align) { case"center": return 0.5; case"right": case"bottom": return 1; default: return 0 } }; var inverseAlign = function(align) { switch (align) { case"left": return "right"; case"right": return "left"; case"top": return "bottom"; case"bottom": return "top"; default: return align } }; var calculateOversize = function(data, bounds) { var oversize = 0; if (data.myLocation < bounds.min) oversize += bounds.min - data.myLocation; if (data.myLocation > bounds.max) oversize += data.myLocation - bounds.max; return oversize }; var initMyLocation = function(data) { data.myLocation = data.atLocation + getAlignFactor(data.atAlign) * data.atSize - getAlignFactor(data.myAlign) * data.mySize + data.offset }; var decolliders = { fit: function(data, bounds) { var result = false; if (data.myLocation > bounds.max) { data.myLocation = bounds.max; result = true } if (data.myLocation < bounds.min) { data.myLocation = bounds.min; result = true } return result }, flip: function(data, bounds) { if (data.myAlign === "center" && data.atAlign === "center") return false; if (data.myLocation < bounds.min || data.myLocation > bounds.max) { var inverseData = $.extend({}, data, { myAlign: inverseAlign(data.myAlign), atAlign: inverseAlign(data.atAlign), offset: -data.offset }); initMyLocation(inverseData); inverseData.oversize = calculateOversize(inverseData, bounds); if (inverseData.myLocation >= bounds.min && inverseData.myLocation <= bounds.max || inverseData.myLocation > data.myLocation || inverseData.oversize < data.oversize) { data.myLocation = inverseData.myLocation; data.oversize = inverseData.oversize; return true } } return false } }; var scrollbarWidth; var defaultPositionResult = { h: { location: 0, flip: false, fit: false, oversize: 0 }, v: { location: 0, flip: false, fit: false, oversize: 0 } }; var calculatePosition = function(what, options) { var $what = $(what), currentOffset = $what.offset(), result = $.extend(true, {}, defaultPositionResult, { h: {location: currentOffset.left}, v: {location: currentOffset.top} }); if (!options) return result; var my = normalizeAlign(options.my), at = normalizeAlign(options.at), of = options.of || window, offset = normalizeOffset(options.offset), collision = normalizeCollision(options.collision), boundary = options.boundary, boundaryOffset = normalizeOffset(options.boundaryOffset); var h = { mySize: $what.outerWidth(), myAlign: my.h, atAlign: at.h, offset: offset.h, collision: collision.h, boundaryOffset: boundaryOffset.h }; var v = { mySize: $what.outerHeight(), myAlign: my.v, atAlign: at.v, offset: offset.v, collision: collision.v, boundaryOffset: boundaryOffset.v }; if (of.preventDefault) { h.atLocation = of.pageX; v.atLocation = of.pageY; h.atSize = 0; v.atSize = 0 } else { of = $(of); if ($.isWindow(of[0])) { h.atLocation = of.scrollLeft(); v.atLocation = of.scrollTop(); h.atSize = of.width(); v.atSize = of.height() } else if (of[0].nodeType === 9) { h.atLocation = 0; v.atLocation = 0; h.atSize = of.width(); v.atSize = of.height() } else { var o = of.offset(); h.atLocation = o.left; v.atLocation = o.top; h.atSize = of.outerWidth(); v.atSize = of.outerHeight() } } initMyLocation(h); initMyLocation(v); var bounds = function() { var win = $(window), windowWidth = win.width(), windowHeight = win.height(), left = win.scrollLeft(), top = win.scrollTop(), hScrollbar = document.width > document.documentElement.clientWidth, vScrollbar = document.height > document.documentElement.clientHeight, hZoomLevel = DX.support.touch ? document.documentElement.clientWidth / (vScrollbar ? windowWidth - scrollbarWidth : windowWidth) : 1, vZoomLevel = DX.support.touch ? document.documentElement.clientHeight / (hScrollbar ? windowHeight - scrollbarWidth : windowHeight) : 1; if (scrollbarWidth === undefined) scrollbarWidth = calculateScrollbarWidth(); var boundaryWidth = windowWidth, boundaryHeight = windowHeight; if (boundary) { var $boundary = $(boundary), boundaryPosition = $boundary.offset(); left = boundaryPosition.left; top = boundaryPosition.top; boundaryWidth = $boundary.width(); boundaryHeight = $boundary.height() } return { h: { min: left + h.boundaryOffset, max: left + boundaryWidth / hZoomLevel - h.mySize - h.boundaryOffset }, v: { min: top + v.boundaryOffset, max: top + boundaryHeight / vZoomLevel - v.mySize - v.boundaryOffset } } }(); h.oversize = calculateOversize(h, bounds.h); v.oversize = calculateOversize(v, bounds.v); if (decolliders[h.collision]) result.h[h.collision] = decolliders[h.collision](h, bounds.h); if (decolliders[v.collision]) result.v[v.collision] = decolliders[v.collision](v, bounds.v); var preciser = function(number) { return options.precise ? number : Math.round(number) }; $.extend(true, result, { h: { location: preciser(h.myLocation), oversize: preciser(h.oversize) }, v: { location: preciser(v.myLocation), oversize: preciser(v.oversize) }, precise: options.precise }); return result }; var position = function(what, options) { var $what = $(what); if (!options) return $what.offset(); DX.translator.resetPosition($what); var offset = $what.offset(), targetPosition = options.h && options.v ? options : calculatePosition($what, options); var preciser = function(number) { return options.precise ? number : Math.round(number) }; DX.translator.move($what, { left: targetPosition.h.location - preciser(offset.left), top: targetPosition.v.location - preciser(offset.top) }); return targetPosition }; $.extend(DX, { calculatePosition: calculatePosition, position: position }); $.extend(DX.position, { inverseAlign: inverseAlign, normalizeAlign: normalizeAlign }); var calculateScrollbarWidth = function() { var $scrollDiv = $("
").css({ width: 100, height: 100, overflow: "scroll", position: "absolute", top: -9999 }).appendTo($("body")), result = $scrollDiv.get(0).offsetWidth - $scrollDiv.get(0).clientWidth; $scrollDiv.remove(); return result } })(jQuery, DevExpress); /*! Module core, file action.js */ (function($, DX, undefined) { var actionExecutors = {}; var registerExecutor = function(name, executor) { if ($.isPlainObject(name)) { $.each(name, registerExecutor); return } actionExecutors[name] = executor }; var unregisterExecutor = function() { var args = $.makeArray(arguments); $.each(args, function() { delete actionExecutors[this] }) }; registerExecutor({ func: {execute: function(e) { if ($.isFunction(e.action)) { e.result = e.action.apply(e.context, e.args); e.handled = true } }}, url: {execute: function(e) { if (typeof e.action === "string" && e.action.charAt(0) !== "#") document.location = e.action }}, hash: {execute: function(e) { if (typeof e.action === "string" && e.action.charAt(0) === "#") document.location.hash = e.action }} }); var Action = DX.Class.inherit({ ctor: function(action, config) { config = config || {}; this._action = action || $.noop; this._context = config.context || window; this._beforeExecute = config.beforeExecute || $.noop; this._afterExecute = config.afterExecute || $.noop; this._component = config.component; this._excludeValidators = config.excludeValidators; this._validatingTargetName = config.validatingTargetName }, execute: function() { var e = { action: this._action, args: Array.prototype.slice.call(arguments), context: this._context, component: this._component, validatingTargetName: this._validatingTargetName, cancel: false, handled: false }; if (!this._validateAction(e)) return; this._beforeExecute.call(this._context, e); if (e.cancel) return; var result = this._executeAction(e); this._afterExecute.call(this._context, e); return result }, _validateAction: function(e) { var excludeValidators = this._excludeValidators; $.each(actionExecutors, function(name, executor) { if (excludeValidators && $.inArray(name, excludeValidators) > -1) return; if (executor.validate) executor.validate(e); if (e.cancel) return false }); return !e.cancel }, _executeAction: function(e) { var result; $.each(actionExecutors, function(index, executor) { if (executor.execute) executor.execute(e); if (e.handled) { result = e.result; return false } }); return result } }); $.extend(DX, { registerActionExecutor: registerExecutor, unregisterActionExecutor: unregisterExecutor, Action: Action }); DX.__internals = {actionExecutors: actionExecutors} })(jQuery, DevExpress); /*! Module core, file translator.js */ (function($, DX, undefined) { var support = DX.support, TRANSLATOR_DATA_KEY = "dxTranslator", TRANSFORM_MATRIX_REGEX = /matrix(3d)?\((.+?)\)/, TRANSLATE_REGEX = /translate(?:3d)?\((.+?)\)/; var locate = function($element) { var translate = support.transform ? getTranslate($element) : getTranslateFallback($element); return { left: translate.x, top: translate.y } }; var move = function($element, position) { if (!support.transform) { $element.css(position); return } var translate = getTranslate($element), left = position.left, top = position.top; if (left !== undefined) translate.x = left || 0; if (top !== undefined) translate.y = top || 0; $element.css({transform: getTranslateCss(translate)}); if (isPersentValue(left) || isPersentValue(top)) clearCache($element) }; var isPersentValue = function(value) { return $.type(value) === "string" && value[value.length - 1] === "%" }; var getTranslateFallback = function($element) { var result; try { var originalTop = $element.css("top"), originalLeft = $element.css("left"); var position = $element.position(); $element.css({ transform: "none", top: 0, left: 0 }); clearCache($element); var finalPosition = $element.position(); result = { x: position.left - finalPosition.left || parseInt(originalLeft) || 0, y: position.top - finalPosition.top || parseInt(originalTop) || 0 }; $element.css({ top: originalTop, left: originalLeft }) } catch(e) { result = { x: 0, y: 0 } } return result }; var getTranslate = function($element) { var result = $element.data(TRANSLATOR_DATA_KEY); if (!result) { var transformValue = $element.css("transform") || getTranslateCss({ x: 0, y: 0 }), matrix = transformValue.match(TRANSFORM_MATRIX_REGEX), is3D = matrix && matrix[1]; if (matrix) { matrix = matrix[2].split(","); if (is3D === "3d") matrix = matrix.slice(12, 15); else { matrix.push(0); matrix = matrix.slice(4, 7) } } else matrix = [0, 0, 0]; result = { x: parseFloat(matrix[0]), y: parseFloat(matrix[1]), z: parseFloat(matrix[2]) }; cacheTranslate($element, result) } return result }; var cacheTranslate = function($element, translate) { $element.data(TRANSLATOR_DATA_KEY, translate) }; var clearCache = function($element) { $element.removeData(TRANSLATOR_DATA_KEY) }; var resetPosition = function($element) { $element.css({ left: 0, top: 0, transform: "none" }); clearCache($element) }; var parseTranslate = function(translateString) { var result = translateString.match(TRANSLATE_REGEX); if (!result || !result[1]) return; result = result[1].split(","); result = { x: parseFloat(result[0]), y: parseFloat(result[1]), z: parseFloat(result[2]) }; return result }; var getTranslateCss = function(translate) { translate.x = translate.x || 0; translate.y = translate.y || 0; var xValueString = isPersentValue(translate.x) ? translate.x : translate.x + "px"; var yValueString = isPersentValue(translate.y) ? translate.y : translate.y + "px"; return "translate(" + xValueString + ", " + yValueString + ")" }; DX.translator = { move: move, locate: locate, clearCache: clearCache, parseTranslate: parseTranslate, getTranslate: getTranslate, getTranslateCss: getTranslateCss, resetPosition: resetPosition } })(jQuery, DevExpress); /*! Module core, file animationFrame.js */ (function($, DX, undefined) { var FRAME_ANIMATION_STEP_TIME = 1000 / 60, requestAnimationFrame = function(callback) { return this.setTimeout(callback, FRAME_ANIMATION_STEP_TIME) }, cancelAnimationFrame = function(requestID) { this.clearTimeout(requestID) }, nativeRequestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame, nativeCancelAnimationFrame = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.oCancelAnimationFrame || window.msCancelAnimationFrame; if (nativeRequestAnimationFrame && nativeCancelAnimationFrame) { requestAnimationFrame = nativeRequestAnimationFrame; cancelAnimationFrame = nativeCancelAnimationFrame } if (nativeRequestAnimationFrame && !nativeCancelAnimationFrame) { var cancelledRequests = {}; requestAnimationFrame = function(callback) { var requestId = nativeRequestAnimationFrame.call(window, function() { try { if (requestId in cancelledRequests) return; callback.apply(this, arguments) } finally { delete cancelledRequests[requestId] } }); return requestId }; cancelAnimationFrame = function(requestId) { cancelledRequests[requestId] = true } } requestAnimationFrame = $.proxy(requestAnimationFrame, window); cancelAnimationFrame = $.proxy(cancelAnimationFrame, window); $.extend(DX, { requestAnimationFrame: requestAnimationFrame, cancelAnimationFrame: cancelAnimationFrame }) })(jQuery, DevExpress); /*! Module core, file animator.js */ (function($, DX, undefined) { DX.Animator = DX.Class.inherit({ ctor: function() { this._finished = true; this._stopped = false; this._proxiedStepCore = $.proxy(this._stepCore, this) }, start: function() { this._stopped = false; this._finished = false; this._stepCore() }, stop: function() { this._stopped = true; DX.cancelAnimationFrame(this._stepAnimationFrame) }, _stepCore: function() { if (this._isStopped()) { this._stop(); return } if (this._isFinished()) { this._finished = true; this._complete(); return } this._step(); this._stepAnimationFrame = DX.requestAnimationFrame.call(window, this._proxiedStepCore) }, _step: DX.abstract, _isFinished: $.noop, _stop: $.noop, _complete: $.noop, _isStopped: function() { return this._stopped }, inProgress: function() { return !(this._stopped || this._finished) } }) })(jQuery, DevExpress); /*! Module core, file fx.js */ (function($, DX, undefined) { var translator = DX.translator, support = DX.support, transitionEndEventName = support.transitionEndEventName + ".dxFX", removeEventName = "dxremove.dxFX"; var CSS_TRANSITION_EASING_REGEX = /cubic-bezier\((\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\)/, RELATIVE_VALUE_REGEX = /^([+-])=(.*)/i, ANIM_DATA_KEY = "dxAnimData", ANIM_QUEUE_KEY = "dxAnimQueue", TRANSFORM_PROP = "transform"; var TransitionAnimationStrategy = { initAnimation: function($element, config) { $element.css({transitionProperty: "none"}); if (typeof config.from === "string") $element.addClass(config.from); else setProps($element, config.from) }, animate: function($element, config) { var that = this, deferred = $.Deferred(), cleanupWhen = config.cleanupWhen; config.transitionAnimation = {finish: function() { that._finishTransition($element, config); if (cleanupWhen) $.when(deferred, cleanupWhen).always(function() { that._cleanup($element, config) }); else that._cleanup($element, config); deferred.resolveWith($element, [config, $element]) }}; this._startAnimation($element, config); this._completeAnimationCallback($element, config).done(function() { config.transitionAnimation.finish() }); if (!config.duration) config.transitionAnimation.finish(); return deferred.promise() }, _completeAnimationCallback: function($element, config) { var startTime = $.now() + config.delay, deferred = $.Deferred(), transitionEndFired = $.Deferred(), simulatedTransitionEndFired = $.Deferred(), simulatedEndEventTimer, waitForJSCompleteTimer; config.transitionAnimation.cleanup = function() { clearTimeout(simulatedEndEventTimer); clearTimeout(waitForJSCompleteTimer) }; $element.one(transitionEndEventName, function() { if ($.now() - startTime >= config.duration) transitionEndFired.reject() }).off(removeEventName).on(removeEventName, function() { config.transitionAnimation.cleanup() }); waitForJSCompleteTimer = setTimeout(function() { simulatedEndEventTimer = setTimeout(function() { simulatedTransitionEndFired.reject() }, config.duration + config.delay + DX.fx._simulatedTransitionEndDelay); $.when(transitionEndFired, simulatedTransitionEndFired).fail($.proxy(function() { deferred.resolve() }, this)) }); return deferred.promise() }, _startAnimation: function($element, config) { $element.css("transform"); $element.css({ transitionProperty: "all", transitionDelay: config.delay + "ms", transitionDuration: config.duration + "ms", transitionTimingFunction: config.easing }); if (typeof config.to === "string") $element.addClass(config.to); else if (config.to) setProps($element, config.to) }, _finishTransition: function($element, config) { $element.css("transition", "none") }, _cleanup: function($element, config) { $element.off(transitionEndEventName); config.transitionAnimation.cleanup(); if (typeof config.from === "string") { $element.removeClass(config.from); $element.removeClass(config.to) } }, stop: function($element, config, jumpToEnd) { if (!config) return; if (jumpToEnd) config.transitionAnimation.finish(); else { if ($.isPlainObject(config.to)) $.each(config.to, function(key) { $element.css(key, $element.css(key)) }); this._finishTransition($element, config); this._cleanup($element, config) } } }; var FrameAnimationStrategy = { initAnimation: function($element, config) { setProps($element, config.from) }, animate: function($element, config) { var deferred = $.Deferred(), that = this; if (!config) return deferred.reject().promise(); $.each(config.to, function(prop) { if (config.from[prop] === undefined) config.from[prop] = that._normalizeValue($element.css(prop)) }); if (config.to[TRANSFORM_PROP]) { config.from[TRANSFORM_PROP] = that._parseTransform(config.from[TRANSFORM_PROP]); config.to[TRANSFORM_PROP] = that._parseTransform(config.to[TRANSFORM_PROP]) } config.frameAnimation = { to: config.to, from: config.from, currentValue: config.from, easing: convertTransitionTimingFuncToJQueryEasing(config.easing), duration: config.duration, startTime: (new Date).valueOf(), finish: function() { this.currentValue = this.to; this.draw(); deferred.resolve() }, draw: function() { var currentValue = $.extend({}, this.currentValue); if (currentValue[TRANSFORM_PROP]) currentValue[TRANSFORM_PROP] = $.map(currentValue[TRANSFORM_PROP], function(value, prop) { if (prop === "translate") return translator.getTranslateCss(value); else if (prop === "scale") return "scale(" + value + ")"; else if (prop.substr(0, prop.length - 1) === "rotate") return prop + "(" + value + "deg)" }).join(" "); $element.css(currentValue) } }; if (config.delay) { config.frameAnimation.startTime += config.delay; config.frameAnimation.delayTimeout = setTimeout(function() { that._animationStep($element, config) }, config.delay) } else that._animationStep($element, config); return deferred.promise() }, _parseTransform: function(transformString) { var result = {}; $.each(transformString.match(/(\w|\d)+\([^\)]*\)\s*/g), function(i, part) { var translateData = translator.parseTranslate(part), scaleData = part.match(/scale\((.+?)\)/), rotateData = part.match(/(rotate.)\((.+)deg\)/); if (translateData) result.translate = translateData; if (scaleData && scaleData[1]) result.scale = parseFloat(scaleData[1]); if (rotateData && rotateData[1]) result[rotateData[1]] = parseFloat(rotateData[2]) }); return result }, stop: function($element, config, jumpToEnd) { var frameAnimation = config && config.frameAnimation; if (!frameAnimation) return; clearTimeout(frameAnimation.delayTimeout); if (jumpToEnd) frameAnimation.finish(); delete config.frameAnimation }, _animationStep: function($element, config) { var frameAnimation = config && config.frameAnimation; if (!frameAnimation) return; var now = (new Date).valueOf(); if (now >= frameAnimation.startTime + frameAnimation.duration) { frameAnimation.finish(); return } frameAnimation.currentValue = this._calcStepValue(frameAnimation, now - frameAnimation.startTime); frameAnimation.draw(); DX.requestAnimationFrame($.proxy(function() { this._animationStep($element, config) }, this)) }, _calcStepValue: function(frameAnimation, currentDuration) { var calcValueRecursively = function(from, to) { var result = $.isArray(to) ? [] : {}; var calcEasedValue = function(propName) { var x = currentDuration / frameAnimation.duration, t = currentDuration, b = 1 * from[propName], c = to[propName] - from[propName], d = frameAnimation.duration; return $.easing[frameAnimation.easing](x, t, b, c, d) }; $.each(to, function(propName, endPropValue) { if (typeof endPropValue === "string" && parseFloat(endPropValue, 10) === false) return true; result[propName] = typeof endPropValue === "object" ? calcValueRecursively(from[propName], endPropValue) : calcEasedValue(propName) }); return result }; return calcValueRecursively(frameAnimation.from, frameAnimation.to) }, _normalizeValue: function(value) { var numericValue = parseFloat(value, 10); if (numericValue === false) return value; return numericValue } }; var FallbackToNoAnimationStrategy = { initAnimation: function($element, config){}, animate: function($element, config) { return $.Deferred().resolve().promise() } }; var animationStrategies = { transition: support.transition ? TransitionAnimationStrategy : FrameAnimationStrategy, frame: FrameAnimationStrategy, noAnimation: FallbackToNoAnimationStrategy }; var getAnimationStrategy = function(config) { config = config || {}; var strategy = config.strategy || "transition"; if (config.type === "css" && !support.transition) strategy = "noAnimation"; return animationStrategies[strategy] }; var TransitionTimingFuncMap = { linear: "cubic-bezier(0, 0, 1, 1)", ease: "cubic-bezier(0.25, 0.1, 0.25, 1)", "ease-in": "cubic-bezier(0.42, 0, 1, 1)", "ease-out": "cubic-bezier(0, 0, 0.58, 1)", "ease-in-out": "cubic-bezier(0.42, 0, 0.58, 1)" }; var convertTransitionTimingFuncToJQueryEasing = function(cssTransitionEasing) { cssTransitionEasing = TransitionTimingFuncMap[cssTransitionEasing] || cssTransitionEasing; var bezCoeffs = cssTransitionEasing.match(CSS_TRANSITION_EASING_REGEX); if (!bezCoeffs) return "linear"; bezCoeffs = bezCoeffs.slice(1, 5); $.each(bezCoeffs, function(index, value) { bezCoeffs[index] = parseFloat(value) }); var easingName = "cubicbezier_" + bezCoeffs.join("_").replace(/\./g, "p"); if (!$.isFunction($.easing[easingName])) { var polynomBezier = function(x1, y1, x2, y2) { var Cx = 3 * x1, Bx = 3 * (x2 - x1) - Cx, Ax = 1 - Cx - Bx, Cy = 3 * y1, By = 3 * (y2 - y1) - Cy, Ay = 1 - Cy - By; var bezierX = function(t) { return t * (Cx + t * (Bx + t * Ax)) }; var bezierY = function(t) { return t * (Cy + t * (By + t * Ay)) }; var findXfor = function(t) { var x = t, i = 0, z; while (i < 14) { z = bezierX(x) - t; if (Math.abs(z) < 1e-3) break; x = x - z / derivativeX(x); i++ } return x }; var derivativeX = function(t) { return Cx + t * (2 * Bx + t * 3 * Ax) }; return function(t) { return bezierY(findXfor(t)) } }; $.easing[easingName] = function(x, t, b, c, d) { return c * polynomBezier(bezCoeffs[0], bezCoeffs[1], bezCoeffs[2], bezCoeffs[3])(t / d) + b } } return easingName }; var baseConfigValidator = function(config, animationType, validate, typeMessage) { $.each(["from", "to"], function() { if (!validate(config[this])) throw DX.Error("E0010", animationType, this, typeMessage); }) }; var isObjectConfigValidator = function(config, animationType) { return baseConfigValidator(config, animationType, function(target) { return $.isPlainObject(target) }, "a plain object") }; var isStringConfigValidator = function(config, animationType) { return baseConfigValidator(config, animationType, function(target) { return typeof target === "string" }, "a string") }; var CustomAnimationConfigurator = {setup: function($element, config){}}; var CssAnimationConfigurator = { validateConfig: function(config) { isStringConfigValidator(config, "css") }, setup: function($element, config){} }; var positionAliases = { top: { my: "bottom center", at: "top center" }, bottom: { my: "top center", at: "bottom center" }, right: { my: "left center", at: "right center" }, left: { my: "right center", at: "left center" } }; var SlideAnimationConfigurator = { validateConfig: function(config) { isObjectConfigValidator(config, "slide") }, setup: function($element, config) { var location = translator.locate($element); if (config.type !== "slide") { var positioningConfig = config.type === "slideIn" ? config.from : config.to; positioningConfig.position = $.extend({of: window}, positionAliases[config.direction]); setupPosition($element, positioningConfig) } this._setUpConfig(location, config.from); this._setUpConfig(location, config.to); translator.clearCache($element); if (!support.transform && $element.css("position") === "static") $element.css("position", "relative") }, _setUpConfig: function(location, config) { config.left = "left" in config ? config.left : "+=0"; config.top = "top" in config ? config.top : "+=0"; this._initNewPosition(location, config) }, _initNewPosition: function(location, config) { var position = { left: config.left, top: config.top }; delete config.left; delete config.top; var relativeValue = this._getRelativeValue(position.left); if (relativeValue !== undefined) position.left = relativeValue + location.left; else config.left = 0; relativeValue = this._getRelativeValue(position.top); if (relativeValue !== undefined) position.top = relativeValue + location.top; else config.top = 0; var translate = { x: 0, y: 0 }; if (support.transform) translate = { x: position.left, y: position.top }; else { config.left = position.left; config.top = position.top } config[TRANSFORM_PROP] = translator.getTranslateCss(translate) }, _getRelativeValue: function(value) { var relativeValue; if (typeof value === "string" && (relativeValue = RELATIVE_VALUE_REGEX.exec(value))) return parseInt(relativeValue[1] + "1") * relativeValue[2] } }; var FadeAnimationConfigurator = {setup: function($element, config) { var from = config.from, fromOpacity = $.isPlainObject(from) ? config.skipElementInitialStyles ? 0 : $element.css("opacity") : String(from), toOpacity; switch (config.type) { case"fadeIn": toOpacity = 1; break; case"fadeOut": toOpacity = 0; break; default: toOpacity = String(config.to) } config.from = { visibility: "visible", opacity: fromOpacity }; config.to = {opacity: toOpacity} }}; var PopAnimationConfigurator = { validateConfig: function(config) { isObjectConfigValidator(config, "pop") }, setup: function($element, config) { var from = config.from, to = config.to, fromOpacity = "opacity" in from ? from.opacity : $element.css("opacity"), toOpacity = "opacity" in to ? to.opacity : 1, fromScale = "scale" in from ? from.scale : 0, toScale = "scale" in to ? to.scale : 1; config.from = {opacity: fromOpacity}; var translate = translator.getTranslate($element); config.from[TRANSFORM_PROP] = this._getCssTransform(translate, fromScale); config.to = {opacity: toOpacity}; config.to[TRANSFORM_PROP] = this._getCssTransform(translate, toScale) }, _getCssTransform: function(translate, scale) { return translator.getTranslateCss(translate) + "scale(" + scale + ")" } }; var animationConfigurators = { custom: CustomAnimationConfigurator, slide: SlideAnimationConfigurator, slideIn: SlideAnimationConfigurator, slideOut: SlideAnimationConfigurator, fade: FadeAnimationConfigurator, fadeIn: FadeAnimationConfigurator, fadeOut: FadeAnimationConfigurator, pop: PopAnimationConfigurator, css: CssAnimationConfigurator }; var getAnimationConfigurator = function(config) { var result = animationConfigurators[config.type]; if (!result) throw DX.Error("E0011", config.type); return result }; var defaultJSConfig = { type: "custom", from: {}, to: {}, duration: 400, start: $.noop, complete: $.noop, easing: "ease", delay: 0 }, defaultCssConfig = { duration: 400, easing: "ease", delay: 0 }; var setupAnimationOnElement = function() { var animation = this, $element = animation.$element, config = animation.config; setupPosition($element, config.from); setupPosition($element, config.to); animation.configurator.setup($element, config); $element.data(ANIM_DATA_KEY, animation); if (DX.fx.off) config.duration = 0; animation.strategy.initAnimation($element, config); if (config.start) config.start.apply(this, [$element, config]) }; var startAnimationOnElement = function() { var animation = this, $element = animation.$element, config = animation.config; return animation.strategy.animate($element, config).done(function() { $element.removeData(ANIM_DATA_KEY); if (config.complete) config.complete.apply(this, [$element, config]); animation.deferred.resolveWith(this, [$element, config]) }) }; var createAnimation = function($element, initialConfig) { var defaultConfig = initialConfig.type === "css" ? defaultCssConfig : defaultJSConfig, config = $.extend(true, {}, defaultConfig, initialConfig), configurator = getAnimationConfigurator(config), strategy = getAnimationStrategy(config), animation = { $element: $element, config: config, configurator: configurator, strategy: strategy, setup: setupAnimationOnElement, start: startAnimationOnElement, deferred: $.Deferred() }; if ($.isFunction(configurator.validateConfig)) configurator.validateConfig(config); return animation }; var animate = function(element, config) { var $element = $(element); if (!$element.length) return $.Deferred().resolve().promise(); var animation = createAnimation($element, config); pushInAnimationQueue($element, animation); return animation.deferred.promise() }; var pushInAnimationQueue = function($element, animation) { var queueData = getAnimQueueData($element); writeAnimQueueData($element, queueData); queueData.push(animation); if (!isAnimating($element)) shiftFromAnimationQueue($element, queueData) }; var getAnimQueueData = function($element) { return $element.data(ANIM_QUEUE_KEY) || [] }; var writeAnimQueueData = function($element, queueData) { $element.data(ANIM_QUEUE_KEY, queueData) }; var destroyAnimQueueData = function($element) { $element.removeData(ANIM_QUEUE_KEY) }; var isAnimating = function($element) { return !!$element.data(ANIM_DATA_KEY) }; var shiftFromAnimationQueue = function($element, queueData) { queueData = getAnimQueueData($element); if (!queueData.length) return; var animation = queueData.shift(); if (queueData.length === 0) destroyAnimQueueData($element); executeAnimation(animation).done(function() { shiftFromAnimationQueue($element) }) }; var executeAnimation = function(animation) { animation.setup(); return animation.start() }; var setupPosition = function($element, config) { if (!config || !config.position) return; var position = DX.calculatePosition($element, config.position), offset = $element.offset(), currentPosition = $element.position(); $.extend(config, { left: position.h.location - offset.left + currentPosition.left, top: position.v.location - offset.top + currentPosition.top }); delete config.position }; var setProps = function($element, props) { $.each(props, function(key, value) { $element.css(key, value) }) }; var stop = function(element, jumpToEnd) { var $element = $(element), queueData = getAnimQueueData($element); $.each(queueData, function(_, animation) { animation.config.duration = 0 }); if (!isAnimating($element)) shiftFromAnimationQueue($element, queueData); var animation = $element.data(ANIM_DATA_KEY); if (animation) animation.strategy.stop($element, animation.config, jumpToEnd); $element.removeData(ANIM_DATA_KEY); destroyAnimQueueData($element) }; DX.fx = { off: false, animationTypes: animationConfigurators, animate: animate, createAnimation: createAnimation, isAnimating: isAnimating, stop: stop, _simulatedTransitionEndDelay: 100 }; DX.fx.__internals = {convertTransitionTimingFuncToJQueryEasing: convertTransitionTimingFuncToJQueryEasing} })(jQuery, DevExpress); /*! Module core, file dxProxyUrlFormatter.js */ (function($, DX, undefined) { var location = window.location, DXPROXY_HOST = "dxproxy.devexpress.com:8000", IS_DXPROXY_ORIGIN = location.host === DXPROXY_HOST, urlMapping = {}; var extractProxyAppId = function() { return location.pathname.split("/")[1] }; var urlFormatter = { isProxyUsed: function() { return IS_DXPROXY_ORIGIN }, formatProxyUrl: function(localUrl) { var urlData = DX.parseUrl(localUrl); if (!/^(localhost$|127\.)/i.test(urlData.hostname)) return localUrl; var proxyUrlPart = DXPROXY_HOST + "/" + extractProxyAppId() + "_" + urlData.port; urlMapping[proxyUrlPart] = urlData.hostname + ":" + urlData.port; var resultUrl = "http://" + proxyUrlPart + urlData.pathname + urlData.search; return resultUrl }, formatLocalUrl: function(proxyUrl) { if (proxyUrl.indexOf(DXPROXY_HOST) < 0) return proxyUrl; var resultUrl = proxyUrl; for (var proxyUrlPart in urlMapping) if (urlMapping.hasOwnProperty(proxyUrlPart)) if (proxyUrl.indexOf(proxyUrlPart) >= 0) { resultUrl = proxyUrl.replace(proxyUrlPart, urlMapping[proxyUrlPart]); break } return resultUrl } }; DX._proxyUrlFormatter = urlFormatter })(jQuery, DevExpress); /*! Module core, file endpointSelector.js */ (function($, DX, undefined) { var location = window.location, IS_WINJS_ORIGIN = location.protocol === "ms-appx:", IS_LOCAL_ORIGIN = isLocalHostName(location.hostname); function isLocalHostName(url) { return /^(localhost$|127\.)/i.test(url) } var EndpointSelector = DX.EndpointSelector = function(config) { this.config = config }; EndpointSelector.prototype = {urlFor: function(key) { var bag = this.config[key]; if (!bag) throw DX.Error("E0006"); if (DX._proxyUrlFormatter.isProxyUsed()) return DX._proxyUrlFormatter.formatProxyUrl(bag.local); if (bag.production) if (IS_WINJS_ORIGIN && !Debug.debuggerEnabled || !IS_WINJS_ORIGIN && !IS_LOCAL_ORIGIN) return bag.production; return bag.local }} })(jQuery, DevExpress); /*! Module core, file formatHelper.js */ (function($, DX, undefined) { var utils = DX.utils; DX.NumericFormat = { currency: 'C', fixedpoint: 'N', exponential: '', percent: 'P', decimal: 'D' }; DX.LargeNumberFormatPostfixes = { 1: 'K', 2: 'M', 3: 'B', 4: 'T' }; var MAX_LARGE_NUMBER_POWER = 4, DECIMAL_BASE = 10; DX.LargeNumberFormatPowers = { largenumber: 'auto', thousands: 1, millions: 2, billions: 3, trillions: 4 }; DX.DateTimeFormat = { longdate: 'D', longtime: 'T', monthandday: 'M', monthandyear: 'Y', quarterandyear: 'qq', shortdate: 'd', shorttime: 't', millisecond: 'fff', second: 'T', minute: 't', hour: 't', day: 'dd', week: 'dd', month: 'MMMM', quarter: 'qq', year: 'yyyy', longdatelongtime: 'D', shortdateshorttime: 'd', shortyear: 'yy' }; DX.formatHelper = { defaultQuarterFormat: 'Q{0}', romanDigits: ['I', 'II', 'III', 'IV'], _addFormatSeparator: function(format1, format2) { var separator = ' '; if (format2) return format1 + separator + format2; return format1 }, _getDateTimeFormatPattern: function(dateTimeFormat) { return Globalize.findClosestCulture().calendar.patterns[DX.DateTimeFormat[dateTimeFormat.toLowerCase()]] }, _isDateFormatContains: function(format) { var result = false; $.each(DX.DateTimeFormat, function(key) { result = key === format.toLowerCase(); return !result }); return result }, getQuarter: function(month) { return Math.floor(month / 3) }, getFirstQuarterMonth: function(month) { return this.getQuarter(month) * 3 }, _getQuarterString: function(date, format) { var quarter = this.getQuarter(date.getMonth()); switch (format) { case'q': return this.romanDigits[quarter]; case'qq': return utils.stringFormat(this.defaultQuarterFormat, this.romanDigits[quarter]); case'Q': return (quarter + 1).toString(); case'QQ': return utils.stringFormat(this.defaultQuarterFormat, (quarter + 1).toString()) } return '' }, _formatCustomString: function(value, format) { var regExp = /qq|q|QQ|Q/g, quarterFormat, result = '', index = 0; regExp.lastIndex = 0; while (index < format.length) { quarterFormat = regExp.exec(format); if (!quarterFormat || quarterFormat.index > index) result += Globalize.format(value, format.substring(index, quarterFormat ? quarterFormat.index : format.length)); if (quarterFormat) { result += this._getQuarterString(value, quarterFormat[0]); index = quarterFormat.index + quarterFormat[0].length } else index = format.length } return result }, _parseNumberFormatString: function(format) { var formatList, formatObject = {}; if (!format || typeof format !== 'string') return; formatList = format.toLowerCase().split(' '); $.each(formatList, function(index, value) { if (value in DX.NumericFormat) formatObject.formatType = value; else if (value in DX.LargeNumberFormatPowers) formatObject.power = DX.LargeNumberFormatPowers[value] }); if (formatObject.power && !formatObject.formatType) formatObject.formatType = 'fixedpoint'; if (formatObject.formatType) return formatObject }, _calculateNumberPower: function(value, base, minPower, maxPower) { var number = Math.abs(value); var power = 0; if (number > 1) while (number && number >= base && (maxPower === undefined || power < maxPower)) { power++; number = number / base } else if (number > 0 && number < 1) while (number < 1 && (minPower === undefined || power > minPower)) { power--; number = number * base } return power }, _getNumberByPower: function(number, power, base) { var result = number; while (power > 0) { result = result / base; power-- } while (power < 0) { result = result * base; power++ } return result }, _formatNumber: function(value, formatObject, precision) { var powerPostfix; if (formatObject.power === 'auto') formatObject.power = this._calculateNumberPower(value, 1000, 0, MAX_LARGE_NUMBER_POWER); if (formatObject.power) value = this._getNumberByPower(value, formatObject.power, 1000); powerPostfix = DX.LargeNumberFormatPostfixes[formatObject.power] || ''; return this._formatNumberCore(value, formatObject.formatType, precision) + powerPostfix }, _formatNumberExponential: function(value, precision) { var power = this._calculateNumberPower(value, DECIMAL_BASE), number = this._getNumberByPower(value, power, DECIMAL_BASE), powString; precision = precision === undefined ? 1 : precision; if (number.toFixed(precision || 0) >= DECIMAL_BASE) { power++; number = number / DECIMAL_BASE } powString = (power >= 0 ? '+' : '') + power.toString(); return this._formatNumberCore(number, 'fixedpoint', precision) + 'E' + powString }, _formatNumberCore: function(value, format, precision) { if (format === 'exponential') return this._formatNumberExponential(value, precision); else return Globalize.format(value, DX.NumericFormat[format] + (utils.isNumber(precision) ? precision : 0)) }, _formatDate: function(date, format) { var resultFormat = DX.DateTimeFormat[format.toLowerCase()]; format = format.toLowerCase(); if (format === 'quarterandyear') resultFormat = this._getQuarterString(date, resultFormat) + ' yyyy'; if (format === 'quarter') return this._getQuarterString(date, resultFormat); if (format === 'longdatelongtime') return this._formatDate(date, 'longdate') + ' ' + this._formatDate(date, 'longtime'); if (format === 'shortdateshorttime') return this._formatDate(date, 'shortDate') + ' ' + this._formatDate(date, 'shortTime'); return Globalize.format(date, resultFormat) }, format: function(value, format, precision) { if ($.isPlainObject(format) && format.format) if (format.dateType) return this._formatDateEx(value, format); else if (utils.isNumber(value) && isFinite(value)) return this._formatNumberEx(value, format); return this._format(value, format, precision) }, _format: function(value, format, precision) { var numberFormatObject; if (!utils.isString(format) || format === '' || !utils.isNumber(value) && !utils.isDate(value)) return utils.isDefined(value) ? value.toString() : ''; numberFormatObject = this._parseNumberFormatString(format); if (utils.isNumber(value) && numberFormatObject) return this._formatNumber(value, numberFormatObject, precision); if (utils.isDate(value) && this._isDateFormatContains(format)) return this._formatDate(value, format); if (!numberFormatObject && !this._isDateFormatContains(format)) return this._formatCustomString(value, format) }, _formatNumberEx: function(value, formatInfo) { var that = this, numericFormatType = DX.NumericFormat[formatInfo.format.toLowerCase()], numberFormat = Globalize.culture().numberFormat, currencyFormat = formatInfo.currencyCulture && Globalize.cultures[formatInfo.currencyCulture] ? Globalize.cultures[formatInfo.currencyCulture].numberFormat.currency : numberFormat.currency, percentFormat = numberFormat.percent, formatSettings = that._getUnitFormatSettings(value, formatInfo), unit = formatSettings.unit, precision = formatSettings.precision, showTrailingZeros = formatSettings.showTrailingZeros, includeGroupSeparator = formatSettings.includeGroupSeparator, groupSymbol = numberFormat[","], floatingSymbol = numberFormat["."], number, isNegative, pattern, currentFormat, regexParts = /n|\$|-|%/g, result = ""; if (!utils.isDefined(value)) return ''; value = that._applyUnitToValue(value, unit); number = Math.abs(value); isNegative = value < 0; switch (numericFormatType) { case DX.NumericFormat.decimal: pattern = "n"; number = Math[isNegative ? "ceil" : "floor"](number); if (precision > 0) { var str = "" + number; for (var i = str.length; i < precision; i += 1) str = "0" + str; number = str } if (isNegative) number = "-" + number; break; case DX.NumericFormat.fixedpoint: currentFormat = numberFormat; case DX.NumericFormat.currency: currentFormat = currentFormat || currencyFormat; case DX.NumericFormat.percent: currentFormat = currentFormat || percentFormat; pattern = isNegative ? currentFormat.pattern[0] : currentFormat.pattern[1] || "n"; number = Globalize.format(number * (numericFormatType === DX.NumericFormat.percent ? 100 : 1), "N" + precision); if (!showTrailingZeros) number = that._excludeTrailingZeros(number, floatingSymbol); if (!includeGroupSeparator) number = number.replace(new RegExp('\\' + groupSymbol, 'g'), ''); break; case DX.NumericFormat.exponential: return that._formatNumberExponential(value, precision); default: throw"Illegal numeric format: '" + numericFormatType + "'"; } for (; ; ) { var lastIndex = regexParts.lastIndex, matches = regexParts.exec(pattern); result += pattern.slice(lastIndex, matches ? matches.index : pattern.length); if (matches) switch (matches[0]) { case"-": if (/[1-9]/.test(number)) result += numberFormat["-"]; break; case"$": result += currencyFormat.symbol; break; case"%": result += percentFormat.symbol; break; case"n": result += number + unit; break } else break } return (formatInfo.plus && value > 0 ? "+" : '') + result }, _excludeTrailingZeros: function(strValue, floatingSymbol) { var floatingIndex = strValue.indexOf(floatingSymbol), stopIndex, i; if (floatingIndex < 0) return strValue; stopIndex = strValue.length; for (i = stopIndex - 1; i >= floatingIndex && (strValue[i] === '0' || i === floatingIndex); i--) stopIndex--; return strValue.substring(0, stopIndex) }, _getUnitFormatSettings: function(value, formatInfo) { var unit = formatInfo.unit || '', precision = formatInfo.precision || 0, includeGroupSeparator = formatInfo.includeGroupSeparator || false, showTrailingZeros = formatInfo.showTrailingZeros === undefined ? true : formatInfo.showTrailingZeros, significantDigits = formatInfo.significantDigits || 1, absValue; if (unit.toLowerCase() === 'auto') { showTrailingZeros = false; absValue = Math.abs(value); if (significantDigits < 1) significantDigits = 1; if (absValue >= 1000000000) { unit = 'B'; absValue /= 1000000000 } else if (absValue >= 1000000) { unit = 'M'; absValue /= 1000000 } else if (absValue >= 1000) { unit = 'K'; absValue /= 1000 } else unit = ''; if (absValue === 0) precision = 0; else if (absValue < 1) { precision = significantDigits; var smallValue = Math.pow(10, -significantDigits); while (absValue < smallValue) { smallValue /= 10; precision++ } } else if (absValue >= 100) precision = significantDigits - 3; else if (absValue >= 10) precision = significantDigits - 2; else precision = significantDigits - 1 } if (precision < 0) precision = 0; return { unit: unit, precision: precision, showTrailingZeros: showTrailingZeros, includeGroupSeparator: includeGroupSeparator } }, _applyUnitToValue: function(value, unit) { if (unit === 'B') return value.toFixed(1) / 1000000000; if (unit === 'M') return value / 1000000; if (unit === 'K') return value / 1000; return value }, _formatDateEx: function(value, formatInfo) { var that = this, format = formatInfo.format, dateType = formatInfo.dateType, calendar = Globalize.culture().calendars.standard, time, index, dateStr; format = format.toLowerCase(); if (!utils.isDefined(value)) return ''; if (dateType !== 'num' || format === 'dayofweek') switch (format) { case'monthyear': return that._formatDate(value, 'monthandyear'); case'quarteryear': return that._getQuarterString(value, 'QQ') + ' ' + value.getFullYear(); case'daymonthyear': return that._formatDate(value, dateType + 'Date'); case'datehour': time = new Date(value.getTime()); time.setMinutes(0); dateStr = dateType === 'timeOnly' ? '' : that._formatDate(value, dateType + 'Date'); return dateType === 'timeOnly' ? that._formatDate(time, 'shorttime') : dateStr + ' ' + that._formatDate(time, 'shorttime'); case'datehourminute': dateStr = dateType === 'timeOnly' ? '' : that._formatDate(value, dateType + 'Date'); return dateType === 'timeOnly' ? that._formatDate(value, 'shorttime') : dateStr + ' ' + that._formatDate(value, 'shorttime'); case'datehourminutesecond': dateStr = dateType === 'timeOnly' ? '' : that._formatDate(value, dateType + 'Date'); return dateType === 'timeOnly' ? that._formatDate(value, 'longtime') : dateStr + ' ' + that._formatDate(value, 'longtime'); case'year': dateStr = value.toString(); return dateType === 'abbr' ? dateStr.slice(2, 4) : dateStr; case'dateyear': return dateType === 'abbr' ? that._formatDate(value, 'shortyear') : that._formatDate(value, 'year'); case'quarter': return utils.stringFormat(that.defaultQuarterFormat, value.toString()); case'month': index = value - 1; return dateType === 'abbr' ? calendar.months.namesAbbr[index] : calendar.months.names[index]; case'hour': if (dateType === 'long') { time = new Date; time.setHours(value); time.setMinutes(0); return that._formatDate(time, 'shorttime') } return value.toString(); case'dayofweek': index = utils.isString(value) ? $.inArray(value, ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']) : value; if (dateType !== 'num') return dateType === 'abbr' ? calendar.days.namesAbbr[index] : calendar.days.names[index]; return ((index - calendar.firstDay + 1 + 7) % 8).toString(); default: return value.toString() } else return value.toString() }, getTimeFormat: function(showSecond) { if (showSecond) return this._getDateTimeFormatPattern('longtime'); return this._getDateTimeFormatPattern('shorttime') }, getDateFormatByDifferences: function(dateDifferences) { var resultFormat = ''; if (dateDifferences.millisecond) resultFormat = DX.DateTimeFormat.millisecond; if (dateDifferences.hour || dateDifferences.minute || dateDifferences.second) resultFormat = this._addFormatSeparator(this.getTimeFormat(dateDifferences.second), resultFormat); if (dateDifferences.year && dateDifferences.month && dateDifferences.day) return this._addFormatSeparator(this._getDateTimeFormatPattern('shortdate'), resultFormat); if (dateDifferences.year && dateDifferences.month) return DX.DateTimeFormat['monthandyear']; if (dateDifferences.year) return DX.DateTimeFormat['year']; if (dateDifferences.month && dateDifferences.day) return this._addFormatSeparator(this._getDateTimeFormatPattern('monthandday'), resultFormat); if (dateDifferences.month) return DX.DateTimeFormat['month']; if (dateDifferences.day) return this._addFormatSeparator('dddd, dd', resultFormat); return resultFormat }, getDateFormatByTicks: function(ticks) { var resultFormat, maxDif, currentDif, i; if (ticks.length > 1) { maxDif = utils.getDatesDifferences(ticks[0], ticks[1]); for (i = 1; i < ticks.length - 1; i++) { currentDif = utils.getDatesDifferences(ticks[i], ticks[i + 1]); if (maxDif.count < currentDif.count) maxDif = currentDif } } else maxDif = { year: true, month: true, day: true, hour: ticks[0].getHours() > 0, minute: ticks[0].getMinutes() > 0, second: ticks[0].getSeconds() > 0 }; resultFormat = this.getDateFormatByDifferences(maxDif); return resultFormat }, getDateFormatByTickInterval: function(startValue, endValue, tickInterval) { var resultFormat, dateDifferences, dateUnitInterval, dateDifferencesConverter = { quarter: 'month', week: 'day' }, correctDateDifferences = function(dateDifferences, tickInterval, value) { switch (tickInterval) { case'year': dateDifferences.month = value; case'quarter': case'month': dateDifferences.day = value; case'week': case'day': dateDifferences.hour = value; case'hour': dateDifferences.minute = value; case'minute': dateDifferences.second = value; case'second': dateDifferences.millisecond = value } }, correctDifferencesByMaxDate = function(differences, minDate, maxDate) { if (!maxDate.getMilliseconds() && maxDate.getSeconds()) { if (maxDate.getSeconds() - minDate.getSeconds() === 1) { differences.millisecond = true; differences.second = false } } else if (!maxDate.getSeconds() && maxDate.getMinutes()) { if (maxDate.getMinutes() - minDate.getMinutes() === 1) { differences.second = true; differences.minute = false } } else if (!maxDate.getMinutes() && maxDate.getHours()) { if (maxDate.getHours() - minDate.getHours() === 1) { differences.minute = true; differences.hour = false } } else if (!maxDate.getHours() && maxDate.getDate() > 1) { if (maxDate.getDate() - minDate.getDate() === 1) { differences.hour = true; differences.day = false } } else if (maxDate.getDate() === 1 && maxDate.getMonth()) { if (maxDate.getMonth() - minDate.getMonth() === 1) { differences.day = true; differences.month = false } } else if (!maxDate.getMonth() && maxDate.getFullYear()) if (maxDate.getFullYear() - minDate.getFullYear() === 1) { differences.month = true; differences.year = false } }; tickInterval = utils.isString(tickInterval) ? tickInterval.toLowerCase() : tickInterval; dateDifferences = utils.getDatesDifferences(startValue, endValue); if (startValue !== endValue) correctDifferencesByMaxDate(dateDifferences, startValue > endValue ? endValue : startValue, startValue > endValue ? startValue : endValue); dateUnitInterval = utils.getDateUnitInterval(dateDifferences); correctDateDifferences(dateDifferences, dateUnitInterval, true); dateUnitInterval = utils.getDateUnitInterval(tickInterval || 'second'); correctDateDifferences(dateDifferences, dateUnitInterval, false); dateDifferences[dateDifferencesConverter[dateUnitInterval] || dateUnitInterval] = true; resultFormat = this.getDateFormatByDifferences(dateDifferences); return resultFormat } } })(jQuery, DevExpress); /*! Module core, file color.js */ (function(DX, undefined) { var standardColorNames = { aliceblue: 'f0f8ff', antiquewhite: 'faebd7', aqua: '00ffff', aquamarine: '7fffd4', azure: 'f0ffff', beige: 'f5f5dc', bisque: 'ffe4c4', black: '000000', blanchedalmond: 'ffebcd', blue: '0000ff', blueviolet: '8a2be2', brown: 'a52a2a', burlywood: 'deb887', cadetblue: '5f9ea0', chartreuse: '7fff00', chocolate: 'd2691e', coral: 'ff7f50', cornflowerblue: '6495ed', cornsilk: 'fff8dc', crimson: 'dc143c', cyan: '00ffff', darkblue: '00008b', darkcyan: '008b8b', darkgoldenrod: 'b8860b', darkgray: 'a9a9a9', darkgreen: '006400', darkkhaki: 'bdb76b', darkmagenta: '8b008b', darkolivegreen: '556b2f', darkorange: 'ff8c00', darkorchid: '9932cc', darkred: '8b0000', darksalmon: 'e9967a', darkseagreen: '8fbc8f', darkslateblue: '483d8b', darkslategray: '2f4f4f', darkturquoise: '00ced1', darkviolet: '9400d3', deeppink: 'ff1493', deepskyblue: '00bfff', dimgray: '696969', dodgerblue: '1e90ff', feldspar: 'd19275', firebrick: 'b22222', floralwhite: 'fffaf0', forestgreen: '228b22', fuchsia: 'ff00ff', gainsboro: 'dcdcdc', ghostwhite: 'f8f8ff', gold: 'ffd700', goldenrod: 'daa520', gray: '808080', green: '008000', greenyellow: 'adff2f', honeydew: 'f0fff0', hotpink: 'ff69b4', indianred: 'cd5c5c', indigo: '4b0082', ivory: 'fffff0', khaki: 'f0e68c', lavender: 'e6e6fa', lavenderblush: 'fff0f5', lawngreen: '7cfc00', lemonchiffon: 'fffacd', lightblue: 'add8e6', lightcoral: 'f08080', lightcyan: 'e0ffff', lightgoldenrodyellow: 'fafad2', lightgrey: 'd3d3d3', lightgreen: '90ee90', lightpink: 'ffb6c1', lightsalmon: 'ffa07a', lightseagreen: '20b2aa', lightskyblue: '87cefa', lightslateblue: '8470ff', lightslategray: '778899', lightsteelblue: 'b0c4de', lightyellow: 'ffffe0', lime: '00ff00', limegreen: '32cd32', linen: 'faf0e6', magenta: 'ff00ff', maroon: '800000', mediumaquamarine: '66cdaa', mediumblue: '0000cd', mediumorchid: 'ba55d3', mediumpurple: '9370d8', mediumseagreen: '3cb371', mediumslateblue: '7b68ee', mediumspringgreen: '00fa9a', mediumturquoise: '48d1cc', mediumvioletred: 'c71585', midnightblue: '191970', mintcream: 'f5fffa', mistyrose: 'ffe4e1', moccasin: 'ffe4b5', navajowhite: 'ffdead', navy: '000080', oldlace: 'fdf5e6', olive: '808000', olivedrab: '6b8e23', orange: 'ffa500', orangered: 'ff4500', orchid: 'da70d6', palegoldenrod: 'eee8aa', palegreen: '98fb98', paleturquoise: 'afeeee', palevioletred: 'd87093', papayawhip: 'ffefd5', peachpuff: 'ffdab9', peru: 'cd853f', pink: 'ffc0cb', plum: 'dda0dd', powderblue: 'b0e0e6', purple: '800080', red: 'ff0000', rosybrown: 'bc8f8f', royalblue: '4169e1', saddlebrown: '8b4513', salmon: 'fa8072', sandybrown: 'f4a460', seagreen: '2e8b57', seashell: 'fff5ee', sienna: 'a0522d', silver: 'c0c0c0', skyblue: '87ceeb', slateblue: '6a5acd', slategray: '708090', snow: 'fffafa', springgreen: '00ff7f', steelblue: '4682b4', tan: 'd2b48c', teal: '008080', thistle: 'd8bfd8', tomato: 'ff6347', turquoise: '40e0d0', violet: 'ee82ee', violetred: 'd02090', wheat: 'f5deb3', white: 'ffffff', whitesmoke: 'f5f5f5', yellow: 'ffff00', yellowgreen: '9acd32' }; var standardColorTypes = [{ re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, process: function(colorString) { return [parseInt(colorString[1], 10), parseInt(colorString[2], 10), parseInt(colorString[3], 10)] } }, { re: /^rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*(\d*\.*\d+)\)$/, process: function(colorString) { return [parseInt(colorString[1], 10), parseInt(colorString[2], 10), parseInt(colorString[3], 10), parseFloat(colorString[4])] } }, { re: /^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/, process: function(colorString) { return [parseInt(colorString[1], 16), parseInt(colorString[2], 16), parseInt(colorString[3], 16)] } }, { re: /^#([a-f0-9]{1})([a-f0-9]{1})([a-f0-9]{1})$/, process: function(colorString) { return [parseInt(colorString[1] + colorString[1], 16), parseInt(colorString[2] + colorString[2], 16), parseInt(colorString[3] + colorString[3], 16)] } }, { re: /^hsv\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, process: function(colorString) { var h = parseInt(colorString[1], 10), s = parseInt(colorString[2], 10), v = parseInt(colorString[3], 10), rgb = hsvToRgb(h, s, v); return [rgb[0], rgb[1], rgb[2], 1, [h, s, v]] } }, { re: /^hsl\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, process: function(colorString) { var h = parseInt(colorString[1], 10), s = parseInt(colorString[2], 10), l = parseInt(colorString[3], 10), rgb = hslToRgb(h, s, l); return [rgb[0], rgb[1], rgb[2], 1, null, [h, s, l]] } }]; function Color(value) { this.baseColor = value; var color; if (value) { color = String(value).toLowerCase().replace(/ /g, ''); color = standardColorNames[color] ? '#' + standardColorNames[color] : color; color = parseColor(color) } if (!color) this.colorIsInvalid = true; color = color || {}; this.r = normalize(color[0]); this.g = normalize(color[1]); this.b = normalize(color[2]); this.a = normalize(color[3], 1, 1); if (color[4]) this.hsv = { h: color[4][0], s: color[4][1], v: color[4][2] }; else this.hsv = toHsvFromRgb(this.r, this.g, this.b); if (color[5]) this.hsl = { h: color[5][0], s: color[5][1], l: color[5][2] }; else this.hsl = toHslFromRgb(this.r, this.g, this.b) } function parseColor(color) { if (color === "transparent") return [0, 0, 0, 0]; var i = 0, ii = standardColorTypes.length, str; for (; i < ii; ++i) { str = standardColorTypes[i].re.exec(color); if (str) return standardColorTypes[i].process(str) } return null } function normalize(colorComponent, def, max) { def = def || 0; max = max || 255; return colorComponent < 0 || isNaN(colorComponent) ? def : colorComponent > max ? max : colorComponent } function toHexFromRgb(r, g, b) { return '#' + (0X01000000 | r << 16 | g << 8 | b).toString(16).slice(1) } function toHsvFromRgb(r, g, b) { var max = Math.max(r, g, b), min = Math.min(r, g, b), delta = max - min, H, S, V; V = max; S = max === 0 ? 0 : 1 - min / max; if (max === min) H = 0; else switch (max) { case r: H = 60 * ((g - b) / delta); if (g < b) H = H + 360; break; case g: H = 60 * ((b - r) / delta) + 120; break; case b: H = 60 * ((r - g) / delta) + 240; break } S *= 100; V *= 100 / 255; return { h: Math.round(H), s: Math.round(S), v: Math.round(V) } } function hsvToRgb(h, s, v) { var Vdec, Vinc, Vmin, Hi, a, r, g, b; Hi = Math.floor(h / 60); Vmin = (100 - s) * v / 100; a = (v - Vmin) * (h % 60 / 60); Vinc = Vmin + a; Vdec = v - a; switch (Hi) { case 0: r = v; g = Vinc; b = Vmin; break; case 1: r = Vdec; g = v; b = Vmin; break; case 2: r = Vmin; g = v; b = Vinc; break; case 3: r = Vmin; g = Vdec; b = v; break; case 4: r = Vinc; g = Vmin; b = v; break; case 5: r = v; g = Vmin; b = Vdec; break } return [Math.round(r * 2.55), Math.round(g * 2.55), Math.round(b * 2.55)] } function calculateHue(r, g, b, delta) { var max = Math.max(r, g, b); switch (max) { case r: return (g - b) / delta + (g < b ? 6 : 0); case g: return (b - r) / delta + 2; case b: return (r - g) / delta + 4 } } function toHslFromRgb(r, g, b) { r = convertTo01Bounds(r, 255); g = convertTo01Bounds(g, 255); b = convertTo01Bounds(b, 255); var max = Math.max(r, g, b), min = Math.min(r, g, b), maxMinSumm = max + min, h, s, l = maxMinSumm / 2; if (max === min) h = s = 0; else { var delta = max - min; if (l > 0.5) s = delta / (2 - maxMinSumm); else s = delta / maxMinSumm; h = calculateHue(r, g, b, delta); h /= 6 } return { h: _round(h * 360), s: _round(s * 100), l: _round(l * 100) } } function makeTc(colorPart, h) { var Tc = h; if (colorPart === "r") Tc = h + 1 / 3; if (colorPart === "b") Tc = h - 1 / 3; return Tc } function modifyTc(Tc) { if (Tc < 0) Tc += 1; if (Tc > 1) Tc -= 1; return Tc } function hueToRgb(p, q, Tc) { Tc = modifyTc(Tc); if (Tc < 1 / 6) return p + (q - p) * 6 * Tc; if (Tc < 1 / 2) return q; if (Tc < 2 / 3) return p + (q - p) * (2 / 3 - Tc) * 6; return p } function hslToRgb(h, s, l) { var r, g, b; h = convertTo01Bounds(h, 360), s = convertTo01Bounds(s, 100), l = convertTo01Bounds(l, 100); if (s === 0) r = g = b = l; else { var q = l < 0.5 ? l * (1 + s) : l + s - l * s, p = 2 * l - q; r = hueToRgb(p, q, makeTc("r", h)); g = hueToRgb(p, q, makeTc("g", h)); b = hueToRgb(p, q, makeTc("b", h)) } return [_round(r * 255), _round(g * 255), _round(b * 255)] } function convertTo01Bounds(n, max) { n = Math.min(max, Math.max(0, parseFloat(n))); if (Math.abs(n - max) < 0.000001) return 1; return n % max / parseFloat(max) } function isIntegerBtwMinAndMax(number, min, max) { min = min || 0; max = max || 255; if (number % 1 !== 0 || number < min || number > max || typeof number !== 'number' || isNaN(number)) return false; return true } var _round = Math.round; Color.prototype = { constructor: Color, highlight: function(step) { step = step || 10; return this.alter(step).toHex() }, darken: function(step) { step = step || 10; return this.alter(-step).toHex() }, alter: function(step) { var result = new Color; result.r = normalize(this.r + step); result.g = normalize(this.g + step); result.b = normalize(this.b + step); return result }, blend: function(blendColor, opacity) { var other = blendColor instanceof Color ? blendColor : new Color(blendColor), result = new Color; result.r = normalize(_round(this.r * (1 - opacity) + other.r * opacity)); result.g = normalize(_round(this.g * (1 - opacity) + other.g * opacity)); result.b = normalize(_round(this.b * (1 - opacity) + other.b * opacity)); return result }, toHex: function() { return toHexFromRgb(this.r, this.g, this.b) }, getPureColor: function() { var rgb = hsvToRgb(this.hsv.h, 100, 100); return new Color("rgb(" + rgb.join(",") + ")") }, isValidHex: function(hex) { return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(hex) }, isValidRGB: function(r, g, b) { if (!isIntegerBtwMinAndMax(r) || !isIntegerBtwMinAndMax(g) || !isIntegerBtwMinAndMax(b)) return false; return true }, isValidAlpha: function(a) { if (isNaN(a) || a < 0 || a > 1 || typeof a !== 'number') return false; return true }, colorIsInvalid: false }; DX.Color = Color })(DevExpress); /*! Module core, file localization.js */ (function($, DX, undefined) { Globalize.localize = function(key, cultureSelector) { var neutral = (cultureSelector || this.cultureSelector || "").substring(0, 2); return this.findClosestCulture(cultureSelector).messages[key] || this.findClosestCulture(neutral).messages[key] || this.cultures["default"].messages[key] }; var localization = function() { var newMessages = {}; return { setup: function(localizablePrefix) { this.localizeString = function(text) { var regex = new RegExp("(^|[^a-zA-Z_0-9" + localizablePrefix + "-]+)(" + localizablePrefix + "{1,2})([a-zA-Z_0-9-]+)", "g"), escapeString = localizablePrefix + localizablePrefix; return text.replace(regex, function(str, prefix, escape, localizationKey) { var result = prefix + localizablePrefix + localizationKey; if (escape !== escapeString) if (Globalize.cultures["default"].messages[localizationKey]) result = prefix + Globalize.localize(localizationKey); else newMessages[localizationKey] = DX.inflector.humanize(localizationKey); return result }) } }, localizeNode: function(node) { var that = this; $(node).each(function(index, nodeItem) { if (!nodeItem.nodeType) return; if (nodeItem.nodeType === 3) nodeItem.nodeValue = that.localizeString(nodeItem.nodeValue); else if (!$(nodeItem).is("iframe")) { $.each(nodeItem.attributes || [], function(index, attr) { if (typeof attr.value === "string") { var localizedValue = that.localizeString(attr.value); if (attr.value !== localizedValue) attr.value = localizedValue } }); $(nodeItem).contents().each(function(index, node) { that.localizeNode(node) }) } }) }, getDictionary: function(onlyNew) { if (onlyNew) return newMessages; return $.extend({}, newMessages, Globalize.cultures["default"].messages) } } }(); localization.setup("@"); DX.localization = localization })(jQuery, DevExpress); /*! Module core, file core.en.js */ Globalize.addCultureInfo("default", {messages: { Yes: "Yes", No: "No", Cancel: "Cancel", Clear: "Clear", Done: "Done", Loading: "Loading...", Select: "Select...", Search: "Search", Back: "Back", OK: "OK", "dxCollectionWidget-noDataText": "No data to display", "validation-required": "Required", "validation-required-formatted": "{0} is required", "validation-numeric": "Value must be a number", "validation-numeric-formatted": "{0} must be a number", "validation-range": "Value is out of range", "validation-range-formatted": "{0} is out of range", "validation-stringLength": "The length of the value is not correct", "validation-stringLength-formatted": "The length of {0} is not correct", "validation-custom": "Value is invalid", "validation-custom-formatted": "{0} is invalid", "validation-compare": "Values do not match", "validation-compare-formatted": "{0} does not match", "validation-pattern": "Value does not match pattern", "validation-pattern-formatted": "{0} does not match pattern", "validation-email": "Email is invalid", "validation-email-formatted": "{0} is invalid", "validation-mask": "Value is invalid" }}); /*! Module core, file widgets-base.en.js */ Globalize.addCultureInfo("default", {messages: { "dxLookup-searchPlaceholder": "Minimum character number: {0}", "dxList-pullingDownText": "Pull down to refresh...", "dxList-pulledDownText": "Release to refresh...", "dxList-refreshingText": "Refreshing...", "dxList-pageLoadingText": "Loading...", "dxList-nextButtonText": "More", "dxList-selectAll": "Select All", "dxListEditDecorator-delete": "Delete", "dxListEditDecorator-more": "More", "dxScrollView-pullingDownText": "Pull down to refresh...", "dxScrollView-pulledDownText": "Release to refresh...", "dxScrollView-refreshingText": "Refreshing...", "dxScrollView-reachBottomText": "Loading...", "dxDateBox-simulatedDataPickerTitleTime": "Select time", "dxDateBox-simulatedDataPickerTitleDate": "Select date", "dxDateBox-simulatedDataPickerTitleDateTime": "Select date and time", "dxDateBox-validation-datetime": "Value must be a date or time", "dxFileUploader-selectFile": "Select file", "dxFileUploader-dropFile": "or Drop file here", "dxFileUploader-bytes": "bytes", "dxFileUploader-kb": "kb", "dxFileUploader-Mb": "Mb", "dxFileUploader-Gb": "Gb", "dxFileUploader-upload": "Upload", "dxFileUploader-uploaded": "Uploaded", "dxFileUploader-readyToUpload": "Ready to upload", "dxFileUploader-uploadFailedMessage": "Upload failed", "dxRangeSlider-ariaFrom": "From {0}", "dxRangeSlider-ariaTill": "Till {0}", "dxSwitch-onText": "ON", "dxSwitch-offText": "OFF" }}); /*! Module core, file widgets-mobile.en.js */ /*! Module core, file widgets-web.en.js */ Globalize.addCultureInfo("default", {messages: { "dxDataGrid-columnChooserTitle": "Column Chooser", "dxDataGrid-columnChooserEmptyText": "Drag a column here to hide it", "dxDataGrid-groupContinuesMessage": "Continues on the next page", "dxDataGrid-groupContinuedMessage": "Continued from the previous page", "dxDataGrid-editingEditRow": "Edit", "dxDataGrid-editingSaveRowChanges": "Save", "dxDataGrid-editingCancelRowChanges": "Cancel", "dxDataGrid-editingDeleteRow": "Delete", "dxDataGrid-editingUndeleteRow": "Undelete", "dxDataGrid-editingConfirmDeleteMessage": "Are you sure you want to delete this record?", "dxDataGrid-editingConfirmDeleteTitle": "", "dxDataGrid-groupPanelEmptyText": "Drag a column header here to group by that column", "dxDataGrid-noDataText": "No data", "dxDataGrid-searchPanelPlaceholder": "Search...", "dxDataGrid-filterRowShowAllText": "(All)", "dxDataGrid-filterRowResetOperationText": "Reset", "dxDataGrid-filterRowOperationEquals": "Equals", "dxDataGrid-filterRowOperationNotEquals": "Does not equal", "dxDataGrid-filterRowOperationLess": "Less than", "dxDataGrid-filterRowOperationLessOrEquals": "Less than or equal to", "dxDataGrid-filterRowOperationGreater": "Greater than", "dxDataGrid-filterRowOperationGreaterOrEquals": "Greater than or equal to", "dxDataGrid-filterRowOperationStartsWith": "Starts with", "dxDataGrid-filterRowOperationContains": "Contains", "dxDataGrid-filterRowOperationNotContains": "Does not contain", "dxDataGrid-filterRowOperationEndsWith": "Ends with", "dxDataGrid-applyFilterText": "Apply filter", "dxDataGrid-trueText": "true", "dxDataGrid-falseText": "false", "dxDataGrid-sortingAscendingText": "Sort Ascending", "dxDataGrid-sortingDescendingText": "Sort Descending", "dxDataGrid-sortingClearText": "Clear Sorting", "dxDataGrid-editingSaveAllChanges": "Save changes", "dxDataGrid-editingCancelAllChanges": "Discard changes", "dxDataGrid-editingAddRow": "Add a row", "dxDataGrid-summaryMin": "Min: {0}", "dxDataGrid-summaryMinOtherColumn": "Min of {1} is {0}", "dxDataGrid-summaryMax": "Max: {0}", "dxDataGrid-summaryMaxOtherColumn": "Max of {1} is {0}", "dxDataGrid-summaryAvg": "Avg: {0}", "dxDataGrid-summaryAvgOtherColumn": "Avg of {1} is {0}", "dxDataGrid-summarySum": "Sum: {0}", "dxDataGrid-summarySumOtherColumn": "Sum of {1} is {0}", "dxDataGrid-summaryCount": "Count: {0}", "dxDataGrid-columnFixingFix": "Fix", "dxDataGrid-columnFixingUnfix": "Unfix", "dxDataGrid-columnFixingLeftPosition": "To the left", "dxDataGrid-columnFixingRightPosition": "To the right", "dxDataGrid-exportTo": "Export to", "dxDataGrid-exportToExcel": "Export to Excel file", "dxDataGrid-excelFormat": "Excel file", "dxDataGrid-selectedRows": "Selected rows", "dxDataGrid-headerFilterEmptyValue": "(Blanks)", "dxDataGrid-headerFilterOK": "OK", "dxDataGrid-headerFilterCancel": "Cancel", "dxDataGrid-ariaColumn": "Column", "dxDataGrid-ariaValue": "Value", "dxDataGrid-ariaFilterCell": "Filter cell", "dxDataGrid-ariaCollapse": "Collapse", "dxDataGrid-ariaExpand": "Expand", "dxDataGrid-ariaDataGrid": "Data grid", "dxDataGrid-ariaSearchInGrid": "Search in data grid", "dxDataGrid-ariaSelectAll": "Select all", "dxDataGrid-ariaSelectRow": "Select row", "dxPager-infoText": "Page {0} of {1}", "dxPivotGrid-grandTotal": "Grand Total", "dxPivotGrid-total": "{0} Total", "dxPivotGrid-fieldChooserTitle": "Field Chooser", "dxPivotGrid-showFieldChooser": "Show Field Chooser", "dxPivotGrid-expandAll": "Expand All", "dxPivotGrid-collapseAll": "Collapse All", "dxPivotGrid-sortColumnBySummary": "Sort \"{0}\" by This Column", "dxPivotGrid-sortRowBySummary": "Sort \"{0}\" by This Row", "dxPivotGrid-removeAllSorting": "Remove All Sorting", "dxPivotGrid-rowFields": "Row Fields", "dxPivotGrid-columnFields": "Column Fields", "dxPivotGrid-dataFields": "Data Fields", "dxPivotGrid-filterFields": "Filter Fields", "dxPivotGrid-allFields": "All Fields", "dxScheduler-editorLabelTitle": "Subject", "dxScheduler-editorLabelStartDate": "Start Date", "dxScheduler-editorLabelEndDate": "End Date", "dxScheduler-editorLabelDescription": "Description", "dxScheduler-editorLabelRecurrence": "Repeat", "dxScheduler-openAppointment": "Open appointment", "dxScheduler-recurrenceNever": "Never", "dxScheduler-recurrenceDaily": "Daily", "dxScheduler-recurrenceWeekly": "Weekly", "dxScheduler-recurrenceMonthly": "Monthly", "dxScheduler-recurrenceYearly": "Yearly", "dxScheduler-recurrenceEvery": "Every", "dxScheduler-recurrenceEnd": "End repeat", "dxScheduler-recurrenceAfter": "After", "dxScheduler-recurrenceOn": "On", "dxScheduler-recurrenceRepeatDaily": "day(s)", "dxScheduler-recurrenceRepeatWeekly": "week(s)", "dxScheduler-recurrenceRepeatMonthly": "month(s)", "dxScheduler-recurrenceRepeatYearly": "year(s)", "dxScheduler-switcherDay": "Day", "dxScheduler-switcherWeek": "Week", "dxScheduler-switcherWorkWeek": "Work week", "dxScheduler-switcherMonth": "Month", "dxScheduler-recurrenceRepeatOnDate": "on date", "dxScheduler-recurrenceRepeatCount": "occurrence(s)", "dxScheduler-allDay": "All day", "dxCalendar-todayButtonText": "Today", "dxCalendar-ariaWidgetName": "Calendar", "dxColorView-ariaRed": "Red", "dxColorView-ariaGreen": "Green", "dxColorView-ariaBlue": "Blue", "dxColorView-ariaAlpha": "Transparency", "dxColorView-ariaHex": "Color code" }}); /*! Module core, file validationEngine.js */ (function($, DX, undefined) { var utils = DX.utils; var rulesValidators = { required: { validate: function(value, rule) { if (!utils.isDefined(value)) return false; if (value === false) return false; value = String(value); if (rule.trim || !utils.isDefined(rule.trim)) value = $.trim(value); return value !== "" }, defaultMessage: function() { return Globalize.localize("validation-required") }, defaultFormattedMessage: function() { return Globalize.localize("validation-required-formatted") } }, numeric: { validate: function(value, rule) { if (!rulesValidators.required.validate(value, {})) return true; if (rule.useCultureSettings && utils.isString(value)) return !isNaN(Globalize.parseFloat(value)); else return $.isNumeric(value) }, defaultMessage: function() { return Globalize.localize("validation-numeric") }, defaultFormattedMessage: function() { return Globalize.localize("validation-numeric-formatted") } }, range: { validate: function(value, rule) { if (!rulesValidators.required.validate(value, {})) return true; var validNumber = rulesValidators["numeric"].validate(value, rule), validValue = utils.isDefined(value), number = validNumber ? parseFloat(value) : validValue && value.valueOf(), min = rule.min, max = rule.max; if (!(validNumber || utils.isDate(value)) && !validValue) return false; if (utils.isDefined(min)) { if (utils.isDefined(max)) return number >= min && number <= max; return number >= min } else if (utils.isDefined(max)) return number <= max; else throw DX.Error("E0101"); return false }, defaultMessage: function() { return Globalize.localize("validation-range") }, defaultFormattedMessage: function() { return Globalize.localize("validation-range-formatted") } }, stringLength: { validate: function(value, rule) { value = String(value); if (rule.trim || !utils.isDefined(rule.trim)) value = $.trim(value); return rulesValidators.range.validate(value.length, $.extend({}, rule)) }, defaultMessage: function() { return Globalize.localize("validation-stringLength") }, defaultFormattedMessage: function() { return Globalize.localize("validation-stringLength-formatted") } }, custom: { validate: function(value, rule) { return rule.validationCallback({ value: value, validator: rule.validator, rule: rule }) }, defaultMessage: function() { return Globalize.localize("validation-custom") }, defaultFormattedMessage: function() { return Globalize.localize("validation-custom-formatted") } }, compare: { validate: function(value, rule) { if (!rule.comparisonTarget) throw DX.Error("E0102"); $.extend(rule, {reevaluate: true}); var otherValue = rule.comparisonTarget(), type = rule.comparisonType || "=="; switch (type) { case"==": return value == otherValue; case"!=": return value != otherValue; case"===": return value === otherValue; case"!==": return value !== otherValue; case">": return value > otherValue; case">=": return value >= otherValue; case"<": return value < otherValue; case"<=": return value <= otherValue } }, defaultMessage: function() { return Globalize.localize("validation-compare") }, defaultFormattedMessage: function() { return Globalize.localize("validation-compare-formatted") } }, pattern: { validate: function(value, rule) { if (!rulesValidators.required.validate(value, {})) return true; var pattern = rule.pattern; if (utils.isString(pattern)) pattern = new RegExp(pattern); return pattern.test(value) }, defaultMessage: function() { return Globalize.localize("validation-pattern") }, defaultFormattedMessage: function() { return Globalize.localize("validation-pattern-formatted") } }, email: { validate: function(value, rule) { if (!rulesValidators.required.validate(value, {})) return true; return rulesValidators.pattern.validate(value, $.extend({}, rule, {pattern: /^[\d\w\._\-]+@([\d\w\._\-]+\.)+[\w]+$/i})) }, defaultMessage: function() { return Globalize.localize("validation-email") }, defaultFormattedMessage: function() { return Globalize.localize("validation-email-formatted") } } }; var GroupConfig = DX.Class.inherit({ ctor: function(group) { this.group = group; this.validators = [] }, validate: function() { var result = { isValid: true, brokenRules: [], validators: [] }; $.each(this.validators, function(_, validator) { var validatorResult = validator.validate(); result.isValid = result.isValid && validatorResult.isValid; if (validatorResult.brokenRule) result.brokenRules.push(validatorResult.brokenRule); result.validators.push(validator) }); this.fireEvent("validated", [{ validators: result.validators, brokenRules: result.brokenRules, isValid: result.isValid }]); return result }, reset: function() { $.each(this.validators, function(_, validator) { validator.reset() }) } }).include(DX.EventsMixin); DX.validationEngine = { groups: [], getGroupConfig: function(group) { var result = $.grep(this.groups, function(config) { return config.group === group }); if (result.length) return result[0] }, initGroups: function() { this.groups = []; this.addGroup() }, addGroup: function(group) { var config = this.getGroupConfig(group); if (!config) { config = new GroupConfig(group); this.groups.push(config) } return config }, removeGroup: function(group) { var config = this.getGroupConfig(group), index = $.inArray(config, this.groups); if (index > -1) this.groups.splice(index, 1); return config }, _setDefaultMessage: function(rule, validator, name) { if (!utils.isDefined(rule.message)) if (validator.defaultFormattedMessage && utils.isDefined(name)) rule.message = validator.defaultFormattedMessage().replace(/\{0\}/, name); else rule.message = validator.defaultMessage() }, validate: function validate(value, rules, name) { var result = { name: name, value: value, brokenRule: null, isValid: true, validationRules: rules }, that = this; $.each(rules || [], function(_, rule) { var ruleValidator = rulesValidators[rule.type], ruleValidationResult; if (ruleValidator) { if (utils.isDefined(rule.isValid) && rule.value === value && !rule.reevaluate) { if (!rule.isValid) { result.isValid = false; result.brokenRule = rule; return false } return true } rule.value = value; ruleValidationResult = ruleValidator.validate(value, rule); rule.isValid = ruleValidationResult; if (!ruleValidationResult) { result.isValid = false; that._setDefaultMessage(rule, ruleValidator, name); result.brokenRule = rule } if (!rule.isValid) return false } else throw DX.Error("E0100"); }); return result }, registerValidatorInGroup: function(group, validator) { var groupConfig = DX.validationEngine.addGroup(group); if ($.inArray(validator, groupConfig.validators) < 0) groupConfig.validators.push(validator) }, removeRegistredValidator: function(group, validator) { var config = DX.validationEngine.getGroupConfig(group), validatorsInGroup = config && config.validators; var index = $.inArray(validator, validatorsInGroup); if (index > -1) validatorsInGroup.splice(index, 1) }, validateGroup: function(group) { var groupConfig = DX.validationEngine.getGroupConfig(group); if (!groupConfig) throw DX.Error("E0110"); return groupConfig.validate() }, resetGroup: function(group) { var groupConfig = DX.validationEngine.getGroupConfig(group); if (!groupConfig) throw DX.Error("E0110"); return groupConfig.reset() } }; DX.validationEngine.initGroups() })(jQuery, DevExpress); /*! Module core, file data.errors.js */ (function($, DX) { $.extend(DX.ERROR_MESSAGES, { E4000: "[DevExpress.data]: {0}", E4001: "Unknown aggregating function is detected: '{0}'", E4002: "Unsupported OData protocol version is used", E4003: "Unknown filter operation is used: {0}", E4004: "The thenby() method is called before the sortby() method", E4005: "Store requires a key expression for this operation", E4006: "ArrayStore 'data' option must be an array", E4007: "Compound keys cannot be auto-generated", E4008: "Attempt to insert an item with the a duplicated key", E4009: "Data item with specified key value cannot be found", E4010: "CustomStore does not support creating queries", E4011: "Custom Store method is not implemented or is not a function: {0}", E4012: "Custom Store method returns an invalid value: {0}", E4013: "Local Store requires the 'name' configuration option is specified", E4014: "Unknown key type is detected: {0}", E4015: "Unknown entity name or alias is used: {0}", E4016: "The compileSetter(expr) method is called with 'self' passed as a parameter", E4017: "Keys cannot be modified" }) })(jQuery, DevExpress); /*! Module core, file data.js */ (function($, DX, undefined) { var bracketsToDots = function(expr) { return expr.replace(/\[/g, ".").replace(/\]/g, "") }; var unwrapObservable = DX.utils.unwrapObservable; var isObservable = function(value) { return DX.support.hasKo && ko.isObservable(value) }; var readPropValue = function(obj, propName) { if (propName === "this") return obj; return obj[propName] }; var assignPropValue = function(obj, propName, value, options) { if (propName === "this") throw new DX.Error("E4016"); var propValue = obj[propName]; if (options.unwrapObservables && isObservable(propValue)) propValue(value); else obj[propName] = value }; var prepareOptions = function(options) { options = options || {}; options.unwrapObservables = options.unwrapObservables !== undefined ? options.unwrapObservables : true; return options }; var unwrap = function(value, options) { return options.unwrapObservables ? unwrapObservable(value) : value }; var compileGetter = function(expr) { if (arguments.length > 1) expr = $.makeArray(arguments); if (!expr || expr === "this") return function(obj) { return obj }; if ($.isFunction(expr)) return expr; if ($.isArray(expr)) return combineGetters(expr); expr = bracketsToDots(expr); var path = expr.split("."); return function(obj, options) { options = prepareOptions(options); var current = unwrap(obj, options); $.each(path, function() { if (!current) return false; var next = unwrap(current[this], options); if ($.isFunction(next) && !options.functionsAsIs) next = next.call(current); current = next }); return current } }; var combineGetters = function(getters) { var compiledGetters = {}; $.each(getters, function() { compiledGetters[this] = compileGetter(this) }); return function(obj, options) { var result = {}; $.each(compiledGetters, function(name) { var value = this(obj, options), current, path, last, i; if (value === undefined) return; current = result; path = name.split("."); last = path.length - 1; for (i = 0; i < last; i++) current = current[path[i]] = {}; current[path[i]] = value }); return result } }; var compileSetter = function(expr) { expr = expr || "this"; expr = bracketsToDots(expr); var pos = expr.lastIndexOf("."), targetGetter = compileGetter(expr.substr(0, pos)), targetPropName = expr.substr(1 + pos); return function(obj, value, options) { options = prepareOptions(options); var target = targetGetter(obj, { functionsAsIs: options.functionsAsIs, unwrapObservables: options.unwrapObservables }), prevTargetValue = readPropValue(target, targetPropName); if (!options.functionsAsIs && $.isFunction(prevTargetValue) && !isObservable(prevTargetValue)) target[targetPropName](value); else { prevTargetValue = unwrap(prevTargetValue, options); if (options.merge && $.isPlainObject(value) && (prevTargetValue === undefined || $.isPlainObject(prevTargetValue)) && !(value instanceof $.Event)) { if (!prevTargetValue) assignPropValue(target, targetPropName, {}, options); DX.utils.deepExtendArraySafe(unwrap(readPropValue(target, targetPropName), options), value) } else assignPropValue(target, targetPropName, value, options) } } }; var normalizeBinaryCriterion = function(crit) { return [crit[0], crit.length < 3 ? "=" : String(crit[1]).toLowerCase(), crit.length < 2 ? true : crit[crit.length - 1]] }; var normalizeSortingInfo = function(info) { if (!$.isArray(info)) info = [info]; return $.map(info, function(i) { return { selector: $.isFunction(i) || typeof i === "string" ? i : i.getter || i.field || i.selector, desc: !!(i.desc || String(i.dir).charAt(0).toLowerCase() === "d") } }) }; var Guid = DX.Class.inherit({ ctor: function(value) { if (value) value = String(value); this._value = this._normalize(value || this._generate()) }, _normalize: function(value) { value = value.replace(/[^a-f0-9]/ig, "").toLowerCase(); while (value.length < 32) value += "0"; return [value.substr(0, 8), value.substr(8, 4), value.substr(12, 4), value.substr(16, 4), value.substr(20, 12)].join("-") }, _generate: function() { var value = ""; for (var i = 0; i < 32; i++) value += Math.round(Math.random() * 15).toString(16); return value }, toString: function() { return this._value }, valueOf: function() { return this._value }, toJSON: function() { return this._value } }); var toComparable = function(value, caseSensitive) { if (value instanceof Date) return value.getTime(); if (value instanceof Guid) return value.valueOf(); if (!caseSensitive && typeof value === "string") return value.toLowerCase(); return value }; var keysEqual = function(keyExpr, key1, key2) { if ($.isArray(keyExpr)) { var names = $.map(key1, function(v, k) { return k }), name; for (var i = 0; i < names.length; i++) { name = names[i]; if (toComparable(key1[name], true) != toComparable(key2[name], true)) return false } return true } return toComparable(key1, true) == toComparable(key2, true) }; var BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; var base64_encode = function(input) { if (!$.isArray(input)) input = stringToByteArray(String(input)); var result = ""; function getBase64Char(index) { return BASE64_CHARS.charAt(index) } for (var i = 0; i < input.length; i += 3) { var octet1 = input[i], octet2 = input[i + 1], octet3 = input[i + 2]; result += $.map([octet1 >> 2, (octet1 & 3) << 4 | octet2 >> 4, isNaN(octet2) ? 64 : (octet2 & 15) << 2 | octet3 >> 6, isNaN(octet3) ? 64 : octet3 & 63], getBase64Char).join("") } return result }; var stringToByteArray = function(str) { var bytes = [], code, i; for (i = 0; i < str.length; i++) { code = str.charCodeAt(i); if (code < 128) bytes.push(code); else if (code < 2048) bytes.push(192 + (code >> 6), 128 + (code & 63)); else if (code < 65536) bytes.push(224 + (code >> 12), 128 + (code >> 6 & 63), 128 + (code & 63)); else if (code < 2097152) bytes.push(240 + (code >> 18), 128 + (code >> 12 & 63), 128 + (code >> 6 & 63), 128 + (code & 63)) } return bytes }; var errorMessageFromXhr = function() { var textStatusMessages = { timeout: "Network connection timeout", error: "Unspecified network error", parsererror: "Unexpected server response" }; var textStatusDetails = { timeout: "possible causes: the remote host is not accessible, overloaded or is not included into the domain white-list when being run in the native container", error: "if the remote host is located on another domain, make sure it properly supports cross-origin resource sharing (CORS), or use the JSONP approach instead", parsererror: "the remote host did not respond with valid JSON data" }; var explainTextStatus = function(textStatus) { var result = textStatusMessages[textStatus]; if (!result) return textStatus; result += " (" + textStatusDetails[textStatus] + ")"; return result }; return function(xhr, textStatus) { if (xhr.status < 400) return explainTextStatus(textStatus); return xhr.statusText } }(); var aggregators = { count: { seed: 0, step: function(count) { return 1 + count } }, sum: { seed: 0, step: function(sum, item) { return sum + item } }, min: {step: function(min, item) { return item < min ? item : min }}, max: {step: function(max, item) { return item > max ? item : max }}, avg: { seed: [0, 0], step: function(pair, value) { return [pair[0] + value, pair[1] + 1] }, finalize: function(pair) { return pair[1] ? pair[0] / pair[1] : NaN } } }; function handleError(error) { var id = "E4000"; if (error && "__id" in error) id = error.__id; DX.log(id, error) } function multiLevelSearch(options) { var itemsGetter = options.itemsGetter, itemsSetter = options.itemsSetter, criteria = options.criteria, data = options.data; function selector(x) { var hash, items = itemsGetter(x); if (isNotAnEmptyArray(items)) { hash = {}; itemsSetter(hash, multiLevelSearch({ data: items, criteria: criteria, itemsGetter: itemsGetter, itemsSetter: itemsSetter })); return $.extend({}, x, hash) } return x } function criterion(x) { return isNotAnEmptyArray(itemsGetter(x)) } function isNotAnEmptyArray(x) { return $.isArray(x) && x.length > 0 } return DX.data.query(data).select(selector).filter([[criterion], "or", criteria]).toArray() } var data = DX.data = { utils: { compileGetter: compileGetter, compileSetter: compileSetter, normalizeBinaryCriterion: normalizeBinaryCriterion, normalizeSortingInfo: normalizeSortingInfo, toComparable: toComparable, keysEqual: keysEqual, errorMessageFromXhr: errorMessageFromXhr, aggregators: aggregators, multiLevelSearch: multiLevelSearch }, Guid: Guid, base64_encode: base64_encode, queryImpl: {}, queryAdapters: {}, query: function() { var impl = $.isArray(arguments[0]) ? "array" : "remote"; return data.queryImpl[impl].apply(this, arguments) }, errorHandler: null, _errorHandler: function(error) { handleError(error); if (data.errorHandler) data.errorHandler(error) } } })(jQuery, DevExpress); /*! Module core, file data.aggregateCalculator.js */ (function($, DX, undefined) { var data = DX.data, utils = data.utils; function isCount(aggregator) { return aggregator === utils.aggregators.count } function normalizeAggregate(aggregate) { var selector = utils.compileGetter(aggregate.selector), aggregator = aggregate.aggregator; if (typeof aggregator === "string") { aggregator = data.utils.aggregators[aggregator]; if (!aggregator) throw DX.Error("E4001", aggregate.aggregator); } return { selector: selector, aggregator: aggregator } } data.AggregateCalculator = DX.Class.inherit({ ctor: function(options) { this._data = options.data; this._groupLevel = options.groupLevel || 0; this._totalAggregates = $.map(options.totalAggregates || [], normalizeAggregate); this._groupAggregates = $.map(options.groupAggregates || [], normalizeAggregate); this._totals = [] }, calculate: function() { if (this._totalAggregates.length) this._calculateTotals(0, {items: this._data}); if (this._groupAggregates.length && this._groupLevel > 0) this._calculateGroups(0, {items: this._data}) }, totalAggregates: function() { return this._totals }, _aggregate: function(data, aggregates, container) { var i, j; for (i = 0; i < aggregates.length; i++) { if (isCount(aggregates[i].aggregator)) { container[i] = (container[i] || 0) + data.items.length; continue } for (j = 0; j < data.items.length; j++) this._accumulate(i, aggregates[i], container, data.items[j]) } }, _calculateTotals: function(level, data) { var i; if (level === 0) this._totals = this._seed(this._totalAggregates); if (level === this._groupLevel) this._aggregate(data, this._totalAggregates, this._totals); else for (i = 0; i < data.items.length; i++) this._calculateTotals(level + 1, data.items[i]); if (level === 0) this._totals = this._finalize(this._totalAggregates, this._totals) }, _calculateGroups: function(level, data, outerAggregates) { var i, innerAggregates; if (level === this._groupLevel) this._aggregate(data, this._groupAggregates, outerAggregates); else for (i = 0; i < data.items.length; i++) { innerAggregates = this._seed(this._groupAggregates); this._calculateGroups(level + 1, data.items[i], innerAggregates); data.items[i].aggregates = this._finalize(this._groupAggregates, innerAggregates); if (level > 0) { outerAggregates = outerAggregates || this._seed(this._groupAggregates); this._calculateGroups(level + 1, data.items[i], outerAggregates) } } }, _seed: function(aggregates) { return $.map(aggregates, function(aggregate) { var aggregator = aggregate.aggregator, seed = "seed" in aggregator ? aggregator.seed : NaN; return $.isArray(seed) ? [seed] : seed }) }, _accumulate: function(aggregateIndex, aggregate, results, item) { var value = aggregate.selector(item), aggregator = aggregate.aggregator; results[aggregateIndex] = results[aggregateIndex] !== results[aggregateIndex] ? value : aggregator.step(results[aggregateIndex], value) }, _finalize: function(aggregates, results) { return $.map(aggregates, function(aggregate, index) { var fin = aggregate.aggregator.finalize; return fin ? fin(results[index]) : results[index] }) } }) })(jQuery, DevExpress); /*! Module core, file data.query.array.js */ (function($, DX, undefined) { var Class = DX.Class, data = DX.data, queryImpl = data.queryImpl, compileGetter = data.utils.compileGetter, toComparable = data.utils.toComparable; var Iterator = Class.inherit({ toArray: function() { var result = []; this.reset(); while (this.next()) result.push(this.current()); return result }, countable: function() { return false } }); var ArrayIterator = Iterator.inherit({ ctor: function(array) { this.array = array; this.index = -1 }, next: function() { if (this.index + 1 < this.array.length) { this.index++; return true } return false }, current: function() { return this.array[this.index] }, reset: function() { this.index = -1 }, toArray: function() { return this.array.slice(0) }, countable: function() { return true }, count: function() { return this.array.length } }); var WrappedIterator = Iterator.inherit({ ctor: function(iter) { this.iter = iter }, next: function() { return this.iter.next() }, current: function() { return this.iter.current() }, reset: function() { return this.iter.reset() } }); var MapIterator = WrappedIterator.inherit({ ctor: function(iter, mapper) { this.callBase(iter); this.index = -1; this.mapper = mapper }, current: function() { return this.mapper(this.callBase(), this.index) }, next: function() { var hasNext = this.callBase(); if (hasNext) this.index++; return hasNext } }); var SortIterator = Iterator.inherit({ ctor: function(iter, getter, desc) { if (!(iter instanceof MapIterator)) iter = new MapIterator(iter, this._wrap); this.iter = iter; this.rules = [{ getter: getter, desc: desc }] }, thenBy: function(getter, desc) { var result = new SortIterator(this.sortedIter || this.iter, getter, desc); if (!this.sortedIter) result.rules = this.rules.concat(result.rules); return result }, next: function() { this._ensureSorted(); return this.sortedIter.next() }, current: function() { this._ensureSorted(); return this.sortedIter.current() }, reset: function() { delete this.sortedIter }, countable: function() { return this.sortedIter || this.iter.countable() }, count: function() { if (this.sortedIter) return this.sortedIter.count(); return this.iter.count() }, _ensureSorted: function() { if (this.sortedIter) return; $.each(this.rules, function() { this.getter = compileGetter(this.getter) }); this.sortedIter = new MapIterator(new ArrayIterator(this.iter.toArray().sort($.proxy(this._compare, this))), this._unwrap) }, _wrap: function(record, index) { return { index: index, value: record } }, _unwrap: function(wrappedItem) { return wrappedItem.value }, _compare: function(x, y) { var xIndex = x.index, yIndex = y.index; x = x.value; y = y.value; if (x === y) return xIndex - yIndex; for (var i = 0, rulesCount = this.rules.length; i < rulesCount; i++) { var rule = this.rules[i], xValue = toComparable(rule.getter(x)), yValue = toComparable(rule.getter(y)), factor = rule.desc ? -1 : 1; if (xValue < yValue) return -factor; if (xValue > yValue) return factor; if (xValue !== yValue) return !xValue ? -factor : factor } return xIndex - yIndex } }); var compileCriteria = function() { var compileGroup = function(crit) { var operands = [], bag = ["return function(d) { return "], index = 0, pushAnd = false; $.each(crit, function() { if ($.isArray(this) || $.isFunction(this)) { if (pushAnd) bag.push(" && "); operands.push(compileCriteria(this)); bag.push("op[", index, "](d)"); index++; pushAnd = true } else { bag.push(/and|&/i.test(this) ? " && " : " || "); pushAnd = false } }); bag.push(" }"); return new Function("op", bag.join(""))(operands) }; var toString = function(value) { return DX.utils.isDefined(value) ? value.toString() : '' }; var compileBinary = function(crit) { crit = data.utils.normalizeBinaryCriterion(crit); var getter = compileGetter(crit[0]), op = crit[1], value = crit[2]; value = toComparable(value); switch (op.toLowerCase()) { case"=": return compileEquals(getter, value); case"<>": return compileEquals(getter, value, true); case">": return function(obj) { return toComparable(getter(obj)) > value }; case"<": return function(obj) { return toComparable(getter(obj)) < value }; case">=": return function(obj) { return toComparable(getter(obj)) >= value }; case"<=": return function(obj) { return toComparable(getter(obj)) <= value }; case"startswith": return function(obj) { return toComparable(toString(getter(obj))).indexOf(value) === 0 }; case"endswith": return function(obj) { var getterValue = toComparable(toString(getter(obj))), searchValue = toString(value); if (getterValue.length < searchValue.length) return false; return getterValue.lastIndexOf(value) === getterValue.length - value.length }; case"contains": return function(obj) { return toComparable(toString(getter(obj))).indexOf(value) > -1 }; case"notcontains": return function(obj) { return toComparable(toString(getter(obj))).indexOf(value) === -1 } } throw DX.Error("E4003", op); }; function compileEquals(getter, value, negate) { return function(obj) { obj = toComparable(getter(obj)); var result = useStrictComparison(value) ? obj === value : obj == value; if (negate) result = !result; return result } } function useStrictComparison(value) { return value === "" || value === 0 || value === null || value === false || value === undefined } return function(crit) { if ($.isFunction(crit)) return crit; if ($.isArray(crit[0])) return compileGroup(crit); return compileBinary(crit) } }(); var FilterIterator = WrappedIterator.inherit({ ctor: function(iter, criteria) { this.callBase(iter); this.criteria = compileCriteria(criteria) }, next: function() { while (this.iter.next()) if (this.criteria(this.current())) return true; return false } }); var GroupIterator = Iterator.inherit({ ctor: function(iter, getter) { this.iter = iter; this.getter = getter }, next: function() { this._ensureGrouped(); return this.groupedIter.next() }, current: function() { this._ensureGrouped(); return this.groupedIter.current() }, reset: function() { delete this.groupedIter }, countable: function() { return !!this.groupedIter }, count: function() { return this.groupedIter.count() }, _ensureGrouped: function() { if (this.groupedIter) return; var hash = {}, keys = [], iter = this.iter, getter = compileGetter(this.getter); iter.reset(); while (iter.next()) { var current = iter.current(), key = getter(current); if (key in hash) hash[key].push(current); else { hash[key] = [current]; keys.push(key) } } this.groupedIter = new ArrayIterator($.map(keys, function(key) { return { key: key, items: hash[key] } })) } }); var SelectIterator = WrappedIterator.inherit({ ctor: function(iter, getter) { this.callBase(iter); this.getter = compileGetter(getter) }, current: function() { return this.getter(this.callBase()) }, countable: function() { return this.iter.countable() }, count: function() { return this.iter.count() } }); var SliceIterator = WrappedIterator.inherit({ ctor: function(iter, skip, take) { this.callBase(iter); this.skip = Math.max(0, skip); this.take = Math.max(0, take); this.pos = 0 }, next: function() { if (this.pos >= this.skip + this.take) return false; while (this.pos < this.skip && this.iter.next()) this.pos++; this.pos++; return this.iter.next() }, reset: function() { this.callBase(); this.pos = 0 }, countable: function() { return this.iter.countable() }, count: function() { return Math.min(this.iter.count() - this.skip, this.take) } }); queryImpl.array = function(iter, queryOptions) { queryOptions = queryOptions || {}; if (!(iter instanceof Iterator)) iter = new ArrayIterator(iter); var handleError = function(error) { var handler = queryOptions.errorHandler; if (handler) handler(error); data._errorHandler(error) }; var aggregateCore = function(aggregator) { var d = $.Deferred().fail(handleError), seed, step = aggregator.step, finalize = aggregator.finalize; try { iter.reset(); if ("seed" in aggregator) seed = aggregator.seed; else seed = iter.next() ? iter.current() : NaN; var accumulator = seed; while (iter.next()) accumulator = step(accumulator, iter.current()); d.resolve(finalize ? finalize(accumulator) : accumulator) } catch(x) { d.reject(x) } return d.promise() }; var aggregate = function(seed, step, finalize) { if (arguments.length < 2) return aggregateCore({step: arguments[0]}); return aggregateCore({ seed: seed, step: step, finalize: finalize }) }; var standardAggregate = function(name) { return aggregateCore(data.utils.aggregators[name]) }; var select = function(getter) { if (!$.isFunction(getter) && !$.isArray(getter)) getter = $.makeArray(arguments); return chainQuery(new SelectIterator(iter, getter)) }; var selectProp = function(name) { return select(compileGetter(name)) }; var chainQuery = function(iter) { return queryImpl.array(iter, queryOptions) }; return { toArray: function() { return iter.toArray() }, enumerate: function() { var d = $.Deferred().fail(handleError); try { d.resolve(iter.toArray()) } catch(x) { d.reject(x) } return d.promise() }, sortBy: function(getter, desc) { return chainQuery(new SortIterator(iter, getter, desc)) }, thenBy: function(getter, desc) { if (iter instanceof SortIterator) return chainQuery(iter.thenBy(getter, desc)); throw DX.Error("E4004"); }, filter: function(criteria) { if (!$.isArray(criteria)) criteria = $.makeArray(arguments); return chainQuery(new FilterIterator(iter, criteria)) }, slice: function(skip, take) { if (take === undefined) take = Number.MAX_VALUE; return chainQuery(new SliceIterator(iter, skip, take)) }, select: select, groupBy: function(getter) { return chainQuery(new GroupIterator(iter, getter)) }, aggregate: aggregate, count: function() { if (iter.countable()) { var d = $.Deferred().fail(handleError); try { d.resolve(iter.count()) } catch(x) { d.reject(x) } return d.promise() } return standardAggregate("count") }, sum: function(getter) { if (getter) return selectProp(getter).sum(); return standardAggregate("sum") }, min: function(getter) { if (getter) return selectProp(getter).min(); return standardAggregate("min") }, max: function(getter) { if (getter) return selectProp(getter).max(); return standardAggregate("max") }, avg: function(getter) { if (getter) return selectProp(getter).avg(); return standardAggregate("avg") } } } })(jQuery, DevExpress); /*! Module core, file data.query.remote.js */ (function($, DX, undefined) { var data = DX.data, queryImpl = data.queryImpl; queryImpl.remote = function(url, queryOptions, tasks) { tasks = tasks || []; queryOptions = queryOptions || {}; var createTask = function(name, args) { return { name: name, args: args } }; var exec = function(executorTask) { var d = $.Deferred(), _adapterFactory, _adapter, _taskQueue, _currentTask, _mergedSortArgs; var rejectWithNotify = function(error) { var handler = queryOptions.errorHandler; if (handler) handler(error); data._errorHandler(error); d.reject(error) }; function mergeSortTask(task) { switch (task.name) { case"sortBy": _mergedSortArgs = [task.args]; return true; case"thenBy": if (!_mergedSortArgs) throw DX.Error("E4004"); _mergedSortArgs.push(task.args); return true } return false } function unmergeSortTasks() { var head = _taskQueue[0], unmergedTasks = []; if (head && head.name === "multiSort") { _taskQueue.shift(); $.each(head.args[0], function() { unmergedTasks.push(createTask(unmergedTasks.length ? "thenBy" : "sortBy", this)) }) } _taskQueue = unmergedTasks.concat(_taskQueue) } try { _adapterFactory = queryOptions.adapter || "odata"; if (!$.isFunction(_adapterFactory)) _adapterFactory = data.queryAdapters[_adapterFactory]; _adapter = _adapterFactory(queryOptions); _taskQueue = [].concat(tasks).concat(executorTask); while (_taskQueue.length) { _currentTask = _taskQueue[0]; if (!mergeSortTask(_currentTask)) { if (_mergedSortArgs) { _taskQueue.unshift(createTask("multiSort", [_mergedSortArgs])); _mergedSortArgs = null; continue } if (String(_currentTask.name) !== "enumerate") if (!_adapter[_currentTask.name] || _adapter[_currentTask.name].apply(_adapter, _currentTask.args) === false) break } _taskQueue.shift() } unmergeSortTasks(); _adapter.exec(url).done(function(result, extra) { if (!_taskQueue.length) d.resolve(result, extra); else { var clientChain = queryImpl.array(result, {errorHandler: queryOptions.errorHandler}); $.each(_taskQueue, function() { clientChain = clientChain[this.name].apply(clientChain, this.args) }); clientChain.done(d.resolve).fail(d.reject) } }).fail(rejectWithNotify) } catch(x) { rejectWithNotify(x) } return d.promise() }; var query = {}; $.each(["sortBy", "thenBy", "filter", "slice", "select", "groupBy"], function() { var name = String(this); query[name] = function() { return queryImpl.remote(url, queryOptions, tasks.concat(createTask(name, arguments))) } }); $.each(["count", "min", "max", "sum", "avg", "aggregate", "enumerate"], function() { var name = String(this); query[name] = function() { return exec.call(this, createTask(name, arguments)) } }); return query } })(jQuery, DevExpress); /*! Module core, file data.odata.js */ (function($, DX, undefined) { var data = DX.data, utils = DX.utils, Guid = data.Guid, isDefined = utils.isDefined; var DEFAULT_PROTOCOL_VERSION = 2; var GUID_REGEX = /^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$/; var VERBOSE_DATE_REGEX = /^\/Date\((-?\d+)((\+|-)?(\d+)?)\)\/$/; var ISO8601_DATE_REGEX = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[-+]{1}\d{2}(:?)(\d{2})?)?$/; var JSON_VERBOSE_MIME_TYPE = "application/json;odata=verbose"; function formatISO8601(date, skipZeroTime, skipTimezone) { var ret = []; var pad = function(n) { if (n < 10) return "0".concat(n); return String(n) }; var isZeroTime = function() { return date.getHours() + date.getMinutes() + date.getSeconds() + date.getMilliseconds() < 1 }; ret.push(date.getFullYear()); ret.push("-"); ret.push(pad(date.getMonth() + 1)); ret.push("-"); ret.push(pad(date.getDate())); if (!(skipZeroTime && isZeroTime())) { ret.push("T"); ret.push(pad(date.getHours())); ret.push(":"); ret.push(pad(date.getMinutes())); ret.push(":"); ret.push(pad(date.getSeconds())); if (date.getMilliseconds()) { ret.push("."); ret.push(date.getMilliseconds()) } if (!skipTimezone) ret.push("Z") } return ret.join("") } function parseISO8601(isoString) { var result = new Date(0); var chunks = isoString.replace("Z", "").split("T"), date = /(\d{4})-(\d{2})-(\d{2})/.exec(chunks[0]), time = /(\d{2}):(\d{2}):(\d{2})\.?(\d{0,7})?/.exec(chunks[1]); result.setDate(Number(date[3])); result.setMonth(Number(date[2]) - 1); result.setFullYear(Number(date[1])); if ($.isArray(time) && time.length) { result.setHours(Number(time[1])); result.setMinutes(Number(time[2])); result.setSeconds(Number(time[3])); result.setMilliseconds(Number(String(time[4]).substr(0, 3)) || 0) } return result } function isAbsoluteUrl(url) { return /^(?:[a-z]+:)?\/\//i.test(url) } function toAbsoluteUrl(basePath, relativePath) { var part, baseParts = basePath.split("/"), relativeParts = relativePath.split("/"); baseParts.pop(); while (relativeParts.length) { part = relativeParts.shift(); if (part === "..") baseParts.pop(); else baseParts.push(part) } return baseParts.join("/") } var ajaxOptionsForRequest = function(protocolVersion, request, requestOptions) { request = $.extend({ method: "get", url: "", params: {}, payload: null, headers: {}, timeout: 30000 }, request); requestOptions = requestOptions || {}; var beforeSend = requestOptions.beforeSend; if (beforeSend) beforeSend(request); var method = (request.method || "get").toLowerCase(), isGet = method === "get", useJsonp = isGet && requestOptions.jsonp, params = $.extend({}, request.params), ajaxData = isGet ? params : formatPayload(request.payload), qs = !isGet && $.param(params), url = request.url, contentType = !isGet && JSON_VERBOSE_MIME_TYPE; if (qs) url += (url.indexOf("?") > -1 ? "&" : "?") + qs; if (useJsonp) ajaxData["$format"] = "json"; return { url: url, data: ajaxData, dataType: useJsonp ? "jsonp" : "json", jsonp: useJsonp && "$callback", type: method, timeout: request.timeout, headers: request.headers, contentType: contentType, accepts: {json: [JSON_VERBOSE_MIME_TYPE, "text/plain"].join()}, xhrFields: {withCredentials: requestOptions.withCredentials} }; function formatPayload(payload) { return JSON.stringify(payload, function(key, value) { if (!(this[key] instanceof Date)) return value; value = formatISO8601(this[key]); switch (protocolVersion) { case 2: return value.substr(0, value.length - 1); case 3: case 4: return value; default: throw DX.Error("E4002"); } }) } }; var sendRequest = function(protocolVersion, request, requestOptions) { var d = $.Deferred(); var options = ajaxOptionsForRequest(protocolVersion, request, requestOptions); $.ajax(options).always(function(obj, textStatus) { var tuplet = interpretJsonFormat(obj, textStatus), error = tuplet.error, data = tuplet.data, nextUrl = tuplet.nextUrl, extra; if (error) d.reject(error); else if (requestOptions.countOnly) d.resolve(tuplet.count); else if (nextUrl) { if (!isAbsoluteUrl(nextUrl)) nextUrl = toAbsoluteUrl(options.url, nextUrl); sendRequest(protocolVersion, {url: nextUrl}, requestOptions).fail(d.reject).done(function(nextData) { d.resolve(data.concat(nextData)) }) } else { if (isFinite(tuplet.count)) extra = {totalCount: tuplet.count}; d.resolve(data, extra) } }); return d.promise() }; var formatDotNetError = function(errorObj) { var message, currentError = errorObj; if ("message" in errorObj) if (errorObj.message.value) message = errorObj.message.value; else message = errorObj.message; while (currentError = currentError.innererror || currentError.internalexception) { message = currentError.message; if (currentError.internalexception && message.indexOf("inner exception") === -1) break } return message }; var errorFromResponse = function(obj, textStatus) { if (textStatus === "nocontent") return null; var httpStatus = 200, message = "Unknown error", response = obj; if (textStatus !== "success") { httpStatus = obj.status; message = data.utils.errorMessageFromXhr(obj, textStatus); try { response = $.parseJSON(obj.responseText) } catch(x) {} } var errorObj = response && (response.error || response["@odata.error"]); if (errorObj) { message = formatDotNetError(errorObj) || message; if (httpStatus === 200) httpStatus = 500; if (errorObj.code) httpStatus = Number(errorObj.code); return $.extend(Error(message), { httpStatus: httpStatus, errorDetails: errorObj }) } else if (httpStatus !== 200) return $.extend(Error(message), {httpStatus: httpStatus}) }; var interpretJsonFormat = function(obj, textStatus) { var error = errorFromResponse(obj, textStatus), value; if (error) return {error: error}; if (!$.isPlainObject(obj)) return {data: obj}; if ("d" in obj && (utils.isArray(obj.d) || utils.isObject(obj.d))) value = interpretVerboseJsonFormat(obj, textStatus); else value = interpretLightJsonFormat(obj, textStatus); transformTypes(value); return value }; var interpretVerboseJsonFormat = function(obj) { var data = obj.d; if (!isDefined(data)) return {error: Error("Malformed or unsupported JSON response received")}; data = data; if (isDefined(data.results)) data = data.results; return { data: data, nextUrl: obj.d.__next, count: parseInt(obj.d.__count, 10) } }; var interpretLightJsonFormat = function(obj) { var data = obj; if (isDefined(data.value)) data = data.value; return { data: data, nextUrl: obj["@odata.nextLink"], count: parseInt(obj["@odata.count"], 10) } }; var EdmLiteral = DX.Class.inherit({ ctor: function(value) { this._value = value }, valueOf: function() { return this._value } }); var transformTypes = function(obj) { $.each(obj, function(key, value) { if (value !== null && typeof value === "object") { if ("results" in value) obj[key] = value.results; transformTypes(obj[key]) } else if (typeof value === "string") if (GUID_REGEX.test(value)) obj[key] = new Guid(value); else if (value.match(VERBOSE_DATE_REGEX)) { var date = new Date(Number(RegExp.$1) + RegExp.$2 * 60 * 1000); obj[key] = new Date(date.valueOf() + date.getTimezoneOffset() * 60 * 1000) } else if (ISO8601_DATE_REGEX.test(value)) obj[key] = new Date(parseISO8601(obj[key]).valueOf()) }) }; var serializeDate = function(date) { return "datetime'" + formatISO8601(date, true, true) + "'" }; var serializeString = function(value) { return "'" + value.replace(/'/g, "''") + "'" }; var serializePropName = function(propName) { if (propName instanceof EdmLiteral) return propName.valueOf(); return propName.replace(/\./g, "/") }; var serializeValueV4 = function(value) { if (value instanceof Date) return formatISO8601(value, false, false); if (value instanceof Guid) return value.valueOf(); return serializeValueV2(value) }; var serializeValueV2 = function(value) { if (value instanceof Date) return serializeDate(value); if (value instanceof Guid) return "guid'" + value + "'"; if (value instanceof EdmLiteral) return value.valueOf(); if (typeof value === "string") return serializeString(value); return String(value) }; var serializeValue = function(value, protocolVersion) { switch (protocolVersion) { case 2: case 3: return serializeValueV2(value); case 4: return serializeValueV4(value); default: throw DX.Error("E4002"); } }; var serializeKey = function(key, protocolVersion) { if ($.isPlainObject(key)) { var parts = []; $.each(key, function(k, v) { parts.push(serializePropName(k) + "=" + serializeValue(v, protocolVersion)) }); return parts.join() } return serializeValue(key, protocolVersion) }; var keyConverters = { String: function(value) { return value + "" }, Int32: function(value) { return Math.floor(value) }, Int64: function(value) { if (value instanceof EdmLiteral) return value; return new EdmLiteral(value + "L") }, Guid: function(value) { if (value instanceof Guid) return value; return new Guid(value) }, Boolean: function(value) { return !!value }, Single: function(value) { if (value instanceof EdmLiteral) return value; return new EdmLiteral(value + "f") }, Decimal: function(value) { if (value instanceof EdmLiteral) return value; return new EdmLiteral(value + "m") } }; var compileCriteria = function() { var createBinaryOperationFormatter = function(op) { return function(prop, val, bag) { bag.push(prop, " ", op, " ", val) } }; var createStringFuncFormatter = function(op, reverse) { return function(prop, val, bag) { if (reverse) bag.push(op, "(", val, ",", prop, ")"); else bag.push(op, "(", prop, ",", val, ")") } }; var formatters = { "=": createBinaryOperationFormatter("eq"), "<>": createBinaryOperationFormatter("ne"), ">": createBinaryOperationFormatter("gt"), ">=": createBinaryOperationFormatter("ge"), "<": createBinaryOperationFormatter("lt"), "<=": createBinaryOperationFormatter("le"), startswith: createStringFuncFormatter("startswith"), endswith: createStringFuncFormatter("endswith") }; var formattersV2 = $.extend({}, formatters, { contains: createStringFuncFormatter("substringof", true), notcontains: createStringFuncFormatter("not substringof", true) }); var formattersV4 = $.extend({}, formatters, { contains: createStringFuncFormatter("contains"), notcontains: createStringFuncFormatter("not contains") }); var compileBinary = function(criteria, bag, protocolVersion) { criteria = data.utils.normalizeBinaryCriterion(criteria); var op = criteria[1], formatters = protocolVersion === 4 ? formattersV4 : formattersV2, formatter = formatters[op.toLowerCase()]; if (!formatter) throw DX.Error("E4003", op); formatter(serializePropName(criteria[0]), serializeValue(criteria[2], protocolVersion), bag) }; var compileGroup = function(criteria, bag, protocolVersion) { var pushAnd = false; $.each(criteria, function() { if ($.isArray(this)) { if (pushAnd) bag.push(" and "); bag.push("("); compileCore(this, bag, protocolVersion); bag.push(")"); pushAnd = true } else { bag.push(/and|&/i.test(this) ? " and " : " or "); pushAnd = false } }) }; var compileCore = function(criteria, bag, protocolVersion) { if ($.isArray(criteria[0])) compileGroup(criteria, bag, protocolVersion); else compileBinary(criteria, bag, protocolVersion) }; return function(criteria, protocolVersion) { var bag = []; compileCore(criteria, bag, protocolVersion); return bag.join("") } }(); var createODataQueryAdapter = function(queryOptions) { var _sorting = [], _criteria = [], _select, _skip, _take, _countQuery; var hasSlice = function() { return _skip || _take !== undefined }; var hasFunction = function(criterion) { for (var i = 0; i < criterion.length; i++) { if ($.isFunction(criterion[i])) return true; if ($.isArray(criterion[i]) && hasFunction(criterion[i])) return true } return false }; var generateExpand = function() { var hash = {}; if (queryOptions.expand) $.each($.makeArray(queryOptions.expand), function() { hash[serializePropName(this)] = 1 }); if (_select) $.each(_select, function() { var path = this.split("."); if (path.length < 2) return; path.pop(); hash[serializePropName(path.join("."))] = 1 }); return $.map(hash, function(k, v) { return v }).join() || undefined }; var requestData = function() { var result = {}; if (!_countQuery) { if (_sorting.length) result["$orderby"] = _sorting.join(","); if (_skip) result["$skip"] = _skip; if (_take !== undefined) result["$top"] = _take; if (_select) result["$select"] = serializePropName(_select.join()); result["$expand"] = generateExpand() } if (_criteria.length) result["$filter"] = compileCriteria(_criteria.length < 2 ? _criteria[0] : _criteria, queryOptions.version); if (_countQuery) result["$top"] = 0; if (queryOptions.requireTotalCount || _countQuery) if (queryOptions.version !== 4) result["$inlinecount"] = "allpages"; else result["$count"] = "true"; return result }; queryOptions.version = queryOptions.version || DEFAULT_PROTOCOL_VERSION; return { exec: function(url) { return sendRequest(queryOptions.version, { url: url, params: $.extend(requestData(), queryOptions && queryOptions.params) }, { beforeSend: queryOptions.beforeSend, jsonp: queryOptions.jsonp, withCredentials: queryOptions.withCredentials, countOnly: _countQuery }) }, multiSort: function(args) { var rules; if (hasSlice()) return false; for (var i = 0; i < args.length; i++) { var getter = args[i][0], desc = !!args[i][1], rule; if (typeof getter !== "string") return false; rule = serializePropName(getter); if (desc) rule += " desc"; rules = rules || []; rules.push(rule) } _sorting = rules }, slice: function(skipCount, takeCount) { if (hasSlice()) return false; _skip = skipCount; _take = takeCount }, filter: function(criterion) { if (hasSlice() || $.isFunction(criterion)) return false; if (!$.isArray(criterion)) criterion = $.makeArray(arguments); if (hasFunction(criterion)) return false; if (_criteria.length) _criteria.push("and"); _criteria.push(criterion) }, select: function(expr) { if (_select || $.isFunction(expr)) return false; if (!$.isArray(expr)) expr = $.makeArray(arguments); _select = expr }, count: function() { _countQuery = true } } }; $.extend(true, data, { EdmLiteral: EdmLiteral, utils: {odata: { sendRequest: sendRequest, serializePropName: serializePropName, serializeValue: serializeValue, serializeKey: serializeKey, keyConverters: keyConverters }}, queryAdapters: {odata: createODataQueryAdapter} }); data.OData__internals = {interpretJsonFormat: interpretJsonFormat} })(jQuery, DevExpress); /*! Module core, file data.store.abstract.js */ (function($, DX, undefined) { var Class = DX.Class, abstract = DX.abstract, data = DX.data, normalizeSortingInfo = data.utils.normalizeSortingInfo; var STORE_CALLBACK_NAMES = ["loading", "loaded", "modifying", "modified", "inserting", "inserted", "updating", "updated", "removing", "removed"]; function multiLevelGroup(query, groupInfo) { query = query.groupBy(groupInfo[0].selector); if (groupInfo.length > 1) query = query.select(function(g) { return $.extend({}, g, {items: multiLevelGroup(data.query(g.items), groupInfo.slice(1)).toArray()}) }); return query } data.utils.multiLevelGroup = multiLevelGroup; function arrangeSortingInfo(groupInfo, sortInfo) { var filteredGroup = []; $.each(groupInfo, function(_, group) { var collision = $.grep(sortInfo, function(sort) { return group.selector === sort.selector }); if (collision.length < 1) filteredGroup.push(group) }); return filteredGroup.concat(sortInfo) } data.utils.arrangeSortingInfo = arrangeSortingInfo; data.Store = Class.inherit({ ctor: function(options) { var that = this; options = options || {}; $.each(STORE_CALLBACK_NAMES, function() { var eventName = this; var callbacks = that[eventName] = $.Callbacks(); var originalAdd = callbacks.add; callbacks.add = function() { DX.log("W0003", "Store", eventName, "14.2", "Use the '" + eventName + "' event instead"); return originalAdd.apply(eventName, arguments) }; if (eventName in options) callbacks.add(options[eventName]); var propertyName = "on" + eventName.charAt(0).toUpperCase() + eventName.slice(1); if (propertyName in options) that.on(eventName, options[propertyName]) }); this._key = options.key; this._errorHandler = options.errorHandler; this._useDefaultSearch = true }, _customLoadOptions: function() { return null }, key: function() { return this._key }, keyOf: function(obj) { if (!this._keyGetter) this._keyGetter = data.utils.compileGetter(this.key()); return this._keyGetter(obj) }, _requireKey: function() { if (!this.key()) throw DX.Error("E4005"); }, load: function(options) { var that = this; options = options || {}; this.fireEvent("loading", [options]); this.loading.fire(options); return this._loadImpl(options).done(function(result, extra) { that.fireEvent("loaded", [result, options]); that.loaded.fire(result, extra) }) }, _loadImpl: function(options) { var filter = options.filter, sort = options.sort, select = options.select, group = options.group, skip = options.skip, take = options.take, q = this.createQuery(options); if (filter) q = q.filter(filter); if (group) group = normalizeSortingInfo(group); if (sort || group) { sort = normalizeSortingInfo(sort || []); if (group) sort = arrangeSortingInfo(group, sort); $.each(sort, function(index) { q = q[index ? "thenBy" : "sortBy"](this.selector, this.desc) }) } if (select) q = q.select(select); if (group) q = multiLevelGroup(q, group); if (take || skip) q = q.slice(skip || 0, take); return q.enumerate() }, createQuery: abstract, totalCount: function(options) { return this._addFailHandlers(this._totalCountImpl(options)) }, _totalCountImpl: function(options) { options = options || {}; var q = this.createQuery(), group = options.group, filter = options.filter; if (filter) q = q.filter(filter); if (group) { group = normalizeSortingInfo(group); q = multiLevelGroup(q, group) } return q.count() }, byKey: function(key, extraOptions) { return this._addFailHandlers(this._byKeyImpl(key, extraOptions)) }, _byKeyImpl: abstract, insert: function(values) { var that = this; that.fireEvent("modifying"); that.fireEvent("inserting", [values]); that.modifying.fire(); that.inserting.fire(values); return that._addFailHandlers(that._insertImpl(values).done(function(callbackValues, callbackKey) { that.fireEvent("inserted", [callbackValues, callbackKey]); that.fireEvent("modified"); that.inserted.fire(callbackValues, callbackKey); that.modified.fire() })) }, _insertImpl: abstract, update: function(key, values) { var that = this; that.fireEvent("modifying"); that.fireEvent("updating", [key, values]); that.modifying.fire(); that.updating.fire(key, values); return that._addFailHandlers(that._updateImpl(key, values).done(function(callbackKey, callbackValues) { that.fireEvent("updated", [callbackKey, callbackValues]); that.fireEvent("modified"); that.updated.fire(callbackKey, callbackValues); that.modified.fire() })) }, _updateImpl: abstract, remove: function(key) { var that = this; that.fireEvent("modifying"); that.fireEvent("removing", [key]); that.modifying.fire(); that.removing.fire(key); return that._addFailHandlers(that._removeImpl(key).done(function(callbackKey) { that.fireEvent("removed", [callbackKey]); that.fireEvent("modified"); that.removed.fire(callbackKey); that.modified.fire() })) }, _removeImpl: abstract, _addFailHandlers: function(deferred) { return deferred.fail(this._errorHandler, data._errorHandler) } }).include(DX.EventsMixin) })(jQuery, DevExpress); /*! Module core, file data.store.array.js */ (function($, DX, undefined) { var data = DX.data, Guid = data.Guid; var trivialPromise = function() { var d = $.Deferred(); return d.resolve.apply(d, arguments).promise() }; var rejectedPromise = function() { var d = $.Deferred(); return d.reject.apply(d, arguments).promise() }; data.ArrayStore = data.Store.inherit({ ctor: function(options) { if ($.isArray(options)) options = {data: options}; else options = options || {}; this.callBase(options); var initialArray = options.data; if (initialArray && !$.isArray(initialArray)) throw DX.Error("E4006"); this._array = initialArray || [] }, createQuery: function() { return data.query(this._array, {errorHandler: this._errorHandler}) }, _byKeyImpl: function(key) { var index = this._indexByKey(key); if (index === -1) return rejectedPromise(DX.Error("E4009")); return trivialPromise(this._array[index]) }, _insertImpl: function(values) { var keyExpr = this.key(), keyValue, obj; if ($.isPlainObject(values)) obj = $.extend({}, values); else obj = values; if (keyExpr) { keyValue = this.keyOf(obj); if (keyValue === undefined || typeof keyValue === "object" && $.isEmptyObject(keyValue)) { if ($.isArray(keyExpr)) throw DX.Error("E4007"); keyValue = obj[keyExpr] = String(new Guid) } else if (this._array[this._indexByKey(keyValue)] !== undefined) return rejectedPromise(DX.Error("E4008")) } else keyValue = obj; this._array.push(obj); return trivialPromise(values, keyValue) }, _updateImpl: function(key, values) { var target, index; if (this.key()) { if (this.keyOf(values)) if (!data.utils.keysEqual(this.key(), key, this.keyOf(values))) return rejectedPromise(DX.Error("E4017")); index = this._indexByKey(key); if (index < 0) return rejectedPromise(DX.Error("E4009")); target = this._array[index] } else target = key; DX.utils.deepExtendArraySafe(target, values); return trivialPromise(key, values) }, _removeImpl: function(key) { var index = this._indexByKey(key); if (index > -1) this._array.splice(index, 1); return trivialPromise(key) }, _indexByKey: function(key) { for (var i = 0, arrayLength = this._array.length; i < arrayLength; i++) if (data.utils.keysEqual(this.key(), this.keyOf(this._array[i]), key)) return i; return -1 }, clear: function() { this._array = [] } }) })(jQuery, DevExpress); /*! Module core, file data.store.local.js */ (function($, DX, undefined) { var Class = DX.Class, abstract = DX.abstract, data = DX.data; var LocalStoreBackend = Class.inherit({ ctor: function(store, storeOptions) { this._store = store; this._dirty = false; var immediate = this._immediate = storeOptions.immediate; var flushInterval = Math.max(100, storeOptions.flushInterval || 10 * 1000); if (!immediate) { var saveProxy = $.proxy(this.save, this); setInterval(saveProxy, flushInterval); $(window).on("beforeunload", saveProxy); if (window.cordova) document.addEventListener("pause", saveProxy, false) } }, notifyChanged: function() { this._dirty = true; if (this._immediate) this.save() }, load: function() { this._store._array = this._loadImpl(); this._dirty = false }, save: function() { if (!this._dirty) return; this._saveImpl(this._store._array); this._dirty = false }, _loadImpl: abstract, _saveImpl: abstract }); var DomLocalStoreBackend = LocalStoreBackend.inherit({ ctor: function(store, storeOptions) { this.callBase(store, storeOptions); var name = storeOptions.name; if (!name) throw DX.Error("E4013"); this._key = "dx-data-localStore-" + name }, _loadImpl: function() { var raw = localStorage.getItem(this._key); if (raw) return JSON.parse(raw); return [] }, _saveImpl: function(array) { if (!array.length) localStorage.removeItem(this._key); else localStorage.setItem(this._key, JSON.stringify(array)) } }); var localStoreBackends = {dom: DomLocalStoreBackend}; data.LocalStore = data.ArrayStore.inherit({ ctor: function(options) { if (typeof options === "string") options = {name: options}; else options = options || {}; this.callBase(options); this._backend = new localStoreBackends[options.backend || "dom"](this, options); this._backend.load() }, clear: function() { this.callBase(); this._backend.notifyChanged() }, _insertImpl: function(values) { var b = this._backend; return this.callBase(values).done($.proxy(b.notifyChanged, b)) }, _updateImpl: function(key, values) { var b = this._backend; return this.callBase(key, values).done($.proxy(b.notifyChanged, b)) }, _removeImpl: function(key) { var b = this._backend; return this.callBase(key).done($.proxy(b.notifyChanged, b)) } }) })(jQuery, DevExpress); /*! Module core, file data.store.odata.js */ (function($, DX, undefined) { var Class = DX.Class, data = DX.data, utils = DX.utils, odataUtils = data.utils.odata; var DEFAULT_PROTOCOL_VERSION = 2; var formatFunctionInvocationUrl = function(baseUrl, args) { return DX.stringFormat("{0}({1})", baseUrl, $.map(args || {}, function(value, key) { return DX.stringFormat("{0}={1}", key, value) }).join(",")) }; var escapeServiceOperationParams = function(params, version) { if (!params) return params; var result = {}; $.each(params, function(k, v) { result[k] = odataUtils.serializeValue(v, version) }); return result }; var convertSimpleKey = function(keyType, keyValue) { var converter = odataUtils.keyConverters[keyType]; if (!converter) throw DX.Error("E4014", keyType); return converter(keyValue) }; var SharedMethods = { _extractServiceOptions: function(options) { options = options || {}; this._url = String(options.url).replace(/\/+$/, ""); this._beforeSend = options.beforeSend; this._jsonp = options.jsonp; this._version = options.version || DEFAULT_PROTOCOL_VERSION; this._withCredentials = options.withCredentials }, _sendRequest: function(url, method, params, payload) { return odataUtils.sendRequest(this.version(), { url: url, method: method, params: params || {}, payload: payload }, { beforeSend: this._beforeSend, jsonp: this._jsonp, withCredentials: this._withCredentials }) }, version: function() { return this._version } }; var ODataStore = data.Store.inherit({ ctor: function(options) { this.callBase(options); this._extractServiceOptions(options); this._keyType = options.keyType; if (this.version() === 2) this._updateMethod = "MERGE"; else this._updateMethod = "PATCH" }, _customLoadOptions: function() { return ["expand", "customQueryParams"] }, _byKeyImpl: function(key, extraOptions) { var params = {}; if (extraOptions) if (extraOptions.expand) params["$expand"] = $.map($.makeArray(extraOptions.expand), odataUtils.serializePropName).join(); return this._sendRequest(this._byKeyUrl(key), "GET", params) }, createQuery: function(loadOptions) { var url, queryOptions; loadOptions = loadOptions || {}; queryOptions = { beforeSend: this._beforeSend, errorHandler: this._errorHandler, jsonp: this._jsonp, version: this._version, withCredentials: this._withCredentials, expand: loadOptions.expand, requireTotalCount: loadOptions.requireTotalCount }; if (utils.isDefined(loadOptions.urlOverride)) url = loadOptions.urlOverride; else url = this._url; if ("customQueryParams" in loadOptions) { var params = escapeServiceOperationParams(loadOptions.customQueryParams, this.version()); if (this.version() === 4) url = formatFunctionInvocationUrl(url, params); else queryOptions.params = params } return data.query(url, queryOptions) }, _insertImpl: function(values) { this._requireKey(); var that = this, d = $.Deferred(); $.when(this._sendRequest(this._url, "POST", null, values)).done(function(serverResponse) { d.resolve(values, that.keyOf(serverResponse)) }).fail(d.reject); return d.promise() }, _updateImpl: function(key, values) { var d = $.Deferred(); $.when(this._sendRequest(this._byKeyUrl(key), this._updateMethod, null, values)).done(function() { d.resolve(key, values) }).fail(d.reject, d); return d.promise() }, _removeImpl: function(key) { var d = $.Deferred(); $.when(this._sendRequest(this._byKeyUrl(key), "DELETE")).done(function() { d.resolve(key) }).fail(d.reject, d); return d.promise() }, _byKeyUrl: function(key, useOriginalHost) { var keyObj = key, keyType = this._keyType, baseUrl = useOriginalHost ? DX._proxyUrlFormatter.formatLocalUrl(this._url) : this._url; if ($.isPlainObject(keyType)) { keyObj = {}; $.each(keyType, function(subKeyName, subKeyType) { keyObj[subKeyName] = convertSimpleKey(subKeyType, key[subKeyName]) }) } else if (keyType) keyObj = convertSimpleKey(keyType, key); return baseUrl + "(" + encodeURIComponent(odataUtils.serializeKey(keyObj, this._version)) + ")" } }).include(SharedMethods); var ODataContext = Class.inherit({ ctor: function(options) { var that = this; that._extractServiceOptions(options); that._errorHandler = options.errorHandler; $.each(options.entities || [], function(entityAlias, entityOptions) { that[entityAlias] = new ODataStore($.extend({}, options, {url: that._url + "/" + encodeURIComponent(entityOptions.name || entityAlias)}, entityOptions)) }) }, get: function(operationName, params) { return this.invoke(operationName, params, "GET") }, invoke: function(operationName, params, httpMethod) { params = params || {}; httpMethod = (httpMethod || "POST").toLowerCase(); var d = $.Deferred(), url = this._url + "/" + encodeURIComponent(operationName), payload; if (this.version() === 4) if (httpMethod === "get") { url = formatFunctionInvocationUrl(url, escapeServiceOperationParams(params, this.version())); params = null } else if (httpMethod === "post") { payload = params; params = null } $.when(this._sendRequest(url, httpMethod, escapeServiceOperationParams(params, this.version()), payload)).done(function(r) { if ($.isPlainObject(r) && operationName in r) r = r[operationName]; d.resolve(r) }).fail([this._errorHandler, data._errorHandler, d.reject]); return d.promise() }, objectLink: function(entityAlias, key) { var store = this[entityAlias]; if (!store) throw DX.Error("E4015", entityAlias); if (!utils.isDefined(key)) return null; return {__metadata: {uri: store._byKeyUrl(key, true)}} } }).include(SharedMethods); $.extend(data, { ODataStore: ODataStore, ODataContext: ODataContext }) })(jQuery, DevExpress); /*! Module core, file data.store.custom.js */ (function($, DX, undefined) { var data = DX.data; var TOTAL_COUNT = "totalCount", LOAD = "load", BY_KEY = "byKey", INSERT = "insert", UPDATE = "update", REMOVE = "remove"; function isPromise(obj) { return obj && $.isFunction(obj.then) } function trivialPromise(value) { return $.Deferred().resolve(value).promise() } function ensureRequiredFuncOption(name, obj) { if (!$.isFunction(obj)) throw DX.Error("E4011", name); } function throwInvalidUserFuncResult(name) { throw DX.Error("E4012", name); } function createUserFuncFailureHandler(pendingDeferred) { function errorMessageFromXhr(promiseArguments) { var xhr = promiseArguments[0], textStatus = promiseArguments[1]; if (!xhr || !xhr.getResponseHeader) return null; return data.utils.errorMessageFromXhr(xhr, textStatus) } return function(arg) { var error; if (arg instanceof Error) error = arg; else error = new Error(errorMessageFromXhr(arguments) || arg && String(arg) || "Unknown error"); pendingDeferred.reject(error) } } data.CustomStore = data.Store.inherit({ ctor: function(options) { options = options || {}; this.callBase(options); this._useDefaultSearch = false; this._loadFunc = options[LOAD]; this._totalCountFunc = options[TOTAL_COUNT]; this._byKeyFunc = options[BY_KEY]; this._insertFunc = options[INSERT]; this._updateFunc = options[UPDATE]; this._removeFunc = options[REMOVE] }, createQuery: function() { throw DX.Error("E4010"); }, _totalCountImpl: function(options) { var userFunc = this._totalCountFunc, userResult, d = $.Deferred(); ensureRequiredFuncOption(TOTAL_COUNT, userFunc); userResult = userFunc(options); if (!isPromise(userResult)) { userResult = Number(userResult); if (!isFinite(userResult)) throwInvalidUserFuncResult(TOTAL_COUNT); userResult = trivialPromise(userResult) } userResult.then(function(count) { d.resolve(Number(count)) }, createUserFuncFailureHandler(d)); return d.promise() }, _loadImpl: function(options) { var userFunc = this._loadFunc, userResult, d = $.Deferred(); ensureRequiredFuncOption(LOAD, userFunc); userResult = userFunc(options); if ($.isArray(userResult)) userResult = trivialPromise(userResult); else if (userResult === null || userResult === undefined) userResult = trivialPromise([]); else if (!isPromise(userResult)) throwInvalidUserFuncResult(LOAD); userResult.then(function(data, extra) { d.resolve(data, extra) }, createUserFuncFailureHandler(d)); return this._addFailHandlers(d.promise()) }, _byKeyImpl: function(key, extraOptions) { var userFunc = this._byKeyFunc, userResult, d = $.Deferred(); ensureRequiredFuncOption(BY_KEY, userFunc); userResult = userFunc(key, extraOptions); if (!isPromise(userResult)) userResult = trivialPromise(userResult); userResult.then(function(obj) { d.resolve(obj) }, createUserFuncFailureHandler(d)); return d.promise() }, _insertImpl: function(values) { var userFunc = this._insertFunc, userResult, d = $.Deferred(); ensureRequiredFuncOption(INSERT, userFunc); userResult = userFunc(values); if (!isPromise(userResult)) userResult = trivialPromise(userResult); userResult.then(function(newKey) { d.resolve(values, newKey) }, createUserFuncFailureHandler(d)); return d.promise() }, _updateImpl: function(key, values) { var userFunc = this._updateFunc, userResult, d = $.Deferred(); ensureRequiredFuncOption(UPDATE, userFunc); userResult = userFunc(key, values); if (!isPromise(userResult)) userResult = trivialPromise(); userResult.then(function() { d.resolve(key, values) }, createUserFuncFailureHandler(d)); return d.promise() }, _removeImpl: function(key) { var userFunc = this._removeFunc, userResult, d = $.Deferred(); ensureRequiredFuncOption(REMOVE, userFunc); userResult = userFunc(key); if (!isPromise(userResult)) userResult = trivialPromise(); userResult.then(function() { d.resolve(key) }, createUserFuncFailureHandler(d)); return d.promise() } }) })(jQuery, DevExpress); /*! Module core, file data.dataSource.js */ (function($, DX, undefined) { var data = DX.data, CustomStore = data.CustomStore, Class = DX.Class; var storeTypeRegistry = { jaydata: "JayDataStore", breeze: "BreezeStore", odata: "ODataStore", local: "LocalStore", array: "ArrayStore" }; var nextLoadOperationId = function() { var id = -1; return function() { return ++id } }(); var canceledOperationsRegistry = function() { var registry = {}; return { add: function(operationId) { registry[operationId] = true }, has: function(operationId) { return operationId in registry }, remove: function(operationId) { delete registry[operationId] } } }(); var ensureIsNotRejected = function(loadOperationId, pendingDeferred) { if (canceledOperationsRegistry.has(loadOperationId)) { canceledOperationsRegistry.remove(loadOperationId); pendingDeferred.reject("canceled"); return false } return true }; function normalizeDataSourceOptions(options) { var store; function createCustomStoreFromLoadFunc() { var storeConfig = {}; $.each(["key", "load", "byKey", "lookup", "totalCount", "insert", "update", "remove"], function() { storeConfig[this] = options[this]; delete options[this] }); return new CustomStore(storeConfig) } function createStoreFromConfig(storeConfig) { var storeCtor = data[storeTypeRegistry[storeConfig.type]]; delete storeConfig.type; return new storeCtor(storeConfig) } function createCustomStoreFromUrl(url) { return new CustomStore({load: function() { return $.getJSON(url) }}) } if (typeof options === "string") options = createCustomStoreFromUrl(options); if (options === undefined) options = []; if ($.isArray(options) || options instanceof data.Store) options = {store: options}; else options = $.extend({}, options); if (options.store === undefined) options.store = []; store = options.store; if ("load" in options) store = createCustomStoreFromLoadFunc(); else if ($.isArray(store)) store = new data.ArrayStore(store); else if ($.isPlainObject(store)) store = createStoreFromConfig($.extend({}, store)); options.store = store; return options } function normalizeStoreLoadOptionAccessorArguments(originalArguments) { switch (originalArguments.length) { case 0: return undefined; case 1: return originalArguments[0] } return $.makeArray(originalArguments) } function generateStoreLoadOptionAccessor(optionName) { return function() { var args = normalizeStoreLoadOptionAccessorArguments(arguments); if (args !== undefined) this._storeLoadOptions[optionName] = args; return this._storeLoadOptions[optionName] } } function mapDataRespectingGrouping(items, mapper, groupInfo) { function mapRecursive(items, level) { if (!DX.utils.isArray(items)) return items; return level ? mapGroup(items, level) : $.map(items, mapper) } function mapGroup(group, level) { return $.map(group, function(item) { var result = { key: item.key, items: mapRecursive(item.items, level - 1) }; if ("aggregates" in item) result.aggregates = item.aggregates; return result }) } return mapRecursive(items, groupInfo ? data.utils.normalizeSortingInfo(groupInfo).length : 0) } var DataSource = Class.inherit({ ctor: function(options) { options = normalizeDataSourceOptions(options); this._store = options.store; this._storeLoadOptions = this._extractLoadOptions(options); this._mapFunc = options.map; this._postProcessFunc = options.postProcess; this._pageIndex = options.pageIndex !== undefined ? options.pageIndex : 0; this._pageSize = options.pageSize !== undefined ? options.pageSize : 20; this._items = []; this._totalCount = -1; this._isLoaded = false; this._loadingCount = 0; this._loadQueue = this._createLoadQueue(); this._searchValue = "searchValue" in options ? options.searchValue : null; this._searchOperation = options.searchOperation || "contains"; this._searchExpr = options.searchExpr; this._paginate = options.paginate; if (this._paginate === undefined) this._paginate = !this.group(); this._isLastPage = !this._paginate; this._userData = {}; $.each(["changed", "loadError", "loadingChanged"], $.proxy(function(_, eventName) { var callbacks = this[eventName] = $.Callbacks(); var originalAdd = callbacks.add; callbacks.add = function() { DX.log("W0003", "DataSource", eventName, "14.2", "Use the '" + eventName + "' event instead"); return originalAdd.apply(eventName, arguments) } }, this)); $.each(["changed", "loadError", "loadingChanged", "customizeLoadResult", "customizeStoreLoadOptions"], $.proxy(function(_, eventName) { var optionName = "on" + eventName[0].toUpperCase() + eventName.slice(1); if (options.hasOwnProperty(optionName)) this.on(eventName, options[optionName]) }, this)) }, dispose: function() { this.changed.empty(); this.loadError.empty(); this.loadingChanged.empty(); this._disposeEvents(); delete this._store; if (this._delayedLoadTask) this._delayedLoadTask.abort(); this._disposed = true }, _extractLoadOptions: function(options) { var result = {}, names = ["sort", "filter", "select", "group", "requireTotalCount"], customNames = this._store._customLoadOptions(); if (customNames) names = names.concat(customNames); $.each(names, function() { result[this] = options[this] }); return result }, loadOptions: function() { return this._storeLoadOptions }, items: function() { return this._items }, pageIndex: function(newIndex) { if (newIndex !== undefined) { this._pageIndex = newIndex; this._isLastPage = !this._paginate } return this._pageIndex }, paginate: function(value) { if (arguments.length < 1) return this._paginate; value = !!value; if (this._paginate !== value) { this._paginate = value; this.pageIndex(0) } }, pageSize: function(value) { if (arguments.length < 1) return this._pageSize; this._pageSize = value }, isLastPage: function() { return this._isLastPage }, sort: generateStoreLoadOptionAccessor("sort"), filter: function() { var newFilter = normalizeStoreLoadOptionAccessorArguments(arguments); if (newFilter !== undefined) { this._storeLoadOptions.filter = newFilter; this.pageIndex(0) } return this._storeLoadOptions.filter }, group: generateStoreLoadOptionAccessor("group"), select: generateStoreLoadOptionAccessor("select"), requireTotalCount: generateStoreLoadOptionAccessor("requireTotalCount"), searchValue: function(value) { if (value !== undefined) { this.pageIndex(0); this._searchValue = value } return this._searchValue }, searchOperation: function(op) { if (op !== undefined) { this.pageIndex(0); this._searchOperation = op } return this._searchOperation }, searchExpr: function(expr) { var argc = arguments.length; if (argc) { if (argc > 1) expr = $.makeArray(arguments); this.pageIndex(0); this._searchExpr = expr } return this._searchExpr }, store: function() { return this._store }, key: function() { return this._store && this._store.key() }, totalCount: function() { return this._totalCount }, isLoaded: function() { return this._isLoaded }, isLoading: function() { return this._loadingCount > 0 }, _createLoadQueue: function() { return DX.createQueue() }, _changeLoadingCount: function(increment) { var oldLoading = this.isLoading(), newLoading; this._loadingCount += increment; newLoading = this.isLoading(); if (oldLoading ^ newLoading) { this.fireEvent("loadingChanged", [newLoading]); this.loadingChanged.fire(newLoading) } }, _scheduleLoadCallbacks: function(deferred) { var that = this; that._changeLoadingCount(1); deferred.always(function() { that._changeLoadingCount(-1) }) }, _scheduleChangedCallbacks: function(deferred) { var that = this; deferred.done(function() { that.fireEvent("changed"); that.changed.fire() }) }, loadSingle: function(propName, propValue) { var that = this; var d = $.Deferred().fail(function() { that.fireEvent("loadError", arguments); that.loadError.fire.apply(that, arguments) }), key = this.key(), store = this._store, loadOptions = this._createStoreLoadOptions(); function handleSuccess(data) { if (data === null || typeof data === "undefined" || $.isArray(data) && data.length < 1) d.reject(); else d.resolve(that._transformLoadedData(data)[0]) } if (arguments.length < 2) { propValue = propName; propName = key } delete loadOptions.skip; delete loadOptions.group; delete loadOptions.refresh; delete loadOptions.pageIndex; delete loadOptions.searchString; if (propName === key || store instanceof data.CustomStore) store.byKey(propValue, loadOptions).done(handleSuccess).fail(d.reject); else { loadOptions.take = 1; loadOptions.filter = loadOptions.filter ? [loadOptions.filter, [propName, propValue]] : [propName, propValue]; store.load(loadOptions).done(handleSuccess).fail(d.reject) } return d.promise() }, load: function() { var that = this, d = $.Deferred(), loadOptions; this._scheduleLoadCallbacks(d); this._scheduleChangedCallbacks(d); loadOptions = this._createLoadOptions(); this.fireEvent("customizeStoreLoadOptions", [loadOptions]); if (!ensureIsNotRejected(loadOptions.operationId, d)) return d.promise(); function errorCallback() { if (arguments[0] !== "canceled") { that.fireEvent("loadError", arguments); that.loadError.fire.apply(that.loadError, arguments) } } function loadTask() { if (that._disposed) return undefined; return that._loadFromStore(loadOptions, d) } this._loadQueue.add(function() { if (typeof loadOptions.delay === "number") that._delayedLoadTask = DX.utils.executeAsync(loadTask, loadOptions.delay); else loadTask(); return d.promise() }); return d.promise({loadOperationId: loadOptions.operationId}).fail(errorCallback) }, reload: function() { var prop, userData = this._userData; for (prop in userData) if (userData.hasOwnProperty(prop)) delete userData[prop]; this._totalCount = -1; this._isLoaded = false; return this.load() }, cancel: function(loadOperationId) { canceledOperationsRegistry.add(loadOperationId) }, _addSearchOptions: function(storeLoadOptions) { if (this._disposed) return; if (this.store()._useDefaultSearch) this._addSearchFilter(storeLoadOptions); else { storeLoadOptions.searchOperation = this._searchOperation; storeLoadOptions.searchValue = this._searchValue; storeLoadOptions.searchExpr = this._searchExpr } }, _createStoreLoadOptions: function() { var result = $.extend({}, this._storeLoadOptions); this._addSearchOptions(result); if (this._paginate) if (this._pageSize) { result.skip = this._pageIndex * this._pageSize; result.take = this._pageSize } result.userData = this._userData; return result }, _createLoadOptions: function() { return { operationId: nextLoadOperationId(), storeLoadOptions: this._createStoreLoadOptions() } }, _addSearchFilter: function(storeLoadOptions) { var value = this._searchValue, op = this._searchOperation, selector = this._searchExpr, searchFilter = []; if (!value) return; if (!selector) selector = "this"; if (!$.isArray(selector)) selector = [selector]; $.each(selector, function(i, item) { if (searchFilter.length) searchFilter.push("or"); searchFilter.push([item, op, value]) }); if (storeLoadOptions.filter) storeLoadOptions.filter = [searchFilter, storeLoadOptions.filter]; else storeLoadOptions.filter = searchFilter }, _loadFromStore: function(loadOptions, pendingDeferred) { var that = this; function handleSuccess(data, extra) { function processResult() { var loadResult; loadResult = $.extend({ data: data, extra: extra }, loadOptions); that.fireEvent("customizeLoadResult", [loadResult]); if (ensureIsNotRejected(loadOptions.operationId, pendingDeferred)) that._processStoreLoadResult(loadResult, pendingDeferred) } if (that._disposed) return; processResult() } if (!ensureIsNotRejected(loadOptions.operationId, pendingDeferred)) return pendingDeferred.promise(); return this.store().load(loadOptions.storeLoadOptions).done(handleSuccess).fail(pendingDeferred.reject) }, _processStoreLoadResult: function(loadResult, pendingDeferred) { var that = this; var data = loadResult.data, extra = loadResult.extra, storeLoadOptions = loadResult.storeLoadOptions; function resolvePendingDeferred() { if (!ensureIsNotRejected(loadResult.operationId, pendingDeferred)) return pendingDeferred; that._isLoaded = true; that._totalCount = isFinite(extra.totalCount) ? extra.totalCount : -1; return pendingDeferred.resolve(data, extra) } function proceedLoadingTotalCount() { that.store().totalCount(storeLoadOptions).done(function(count) { extra.totalCount = count; resolvePendingDeferred() }).fail(function(){}) } if (that._disposed) return; data = that._transformLoadedData(data); if (!$.isPlainObject(extra)) extra = {}; that._items = data; if (!data.length || !that._paginate || that._pageSize && data.length < that._pageSize) that._isLastPage = true; if (storeLoadOptions.requireTotalCount && !isFinite(extra.totalCount)) proceedLoadingTotalCount(); else resolvePendingDeferred() }, _transformLoadedData: function(data) { var result = $.makeArray(data); if (this._mapFunc) result = mapDataRespectingGrouping(result, this._mapFunc, this.group()); if (this._postProcessFunc) result = this._postProcessFunc(result); return result } }).include(DX.EventsMixin); $.extend(true, data, { DataSource: DataSource, utils: { storeTypeRegistry: storeTypeRegistry, normalizeDataSourceOptions: normalizeDataSourceOptions } }) })(jQuery, DevExpress); /*! Module core, file ko.js */ (function($, DX) { if (DX.support.hasKo && DX.compareVersions(ko.version, [2, 3]) < 0) throw DX.Error("E0013"); })(jQuery, DevExpress); /*! Module core, file ng.js */ (function($, DX, undefined) { if (!DX.support.hasNg) return; DX.ng = {module: window.angular.module("dx", ["ngSanitize"])} })(jQuery, DevExpress); /*! Module core, file component.js */ (function($, DX, undefined) { var utils = DX.utils, dataUtils = DX.data.utils, inflector = DX.inflector; var Component = DX.Class.inherit({ NAME: "Component", _setDeprecatedOptions: function() { this._deprecatedOptions = {} }, _getDeprecatedOptions: function() { return this._deprecatedOptions }, _setOptionAliases: function() { var aliases = this._optionAliases = {}; $.each(this._getDeprecatedOptions(), function(optionName, info) { var optionAlias = info.alias; if (optionAlias) aliases[optionName] = optionAlias }) }, _getOptionAliases: function() { return this._optionAliases }, _getOptionAliasesByName: function(optionName) { return $.map(this._getOptionAliases(), function(aliasedOption, aliasName) { return optionName === aliasedOption ? aliasName : undefined }) }, _setDefaultOptions: function() { this.option({ onInitialized: null, onOptionChanged: null, onDisposing: null, defaultOptionsRules: null }) }, _defaultOptionsRules: function() { return [] }, _setOptionsByDevice: function(userRules) { var rules = this._defaultOptionsRules(); if (this._customRules) rules = rules.concat(this._customRules); if ($.isArray(userRules)) rules = rules.concat(userRules); this.option(this._convertRulesToOptions(rules)) }, _convertRulesToOptions: function(rules) { var options = {}; var currentDevice = DX.devices.current(); var deviceMatch = function(device, filter) { filter = $.makeArray(filter); return filter.length === 1 && $.isEmptyObject(filter[0]) || utils.findBestMatches(device, filter).length > 0 }; $.each(rules, function(index, rule) { var deviceFilter = rule.device || {}, match; if ($.isFunction(deviceFilter)) match = deviceFilter(currentDevice); else match = deviceMatch(currentDevice, deviceFilter); if (match) $.extend(options, rule.options) }); return options }, _isInitialOptionValue: function(name) { var isCustomOption = this._customRules && this._convertRulesToOptions(this._customRules).hasOwnProperty(name); var isInitialOption = this.option(name) === this._initialOptions[name]; return !isCustomOption && isInitialOption }, _setOptionsByReference: function() { this._optionsByReference = {} }, _getOptionsByReference: function() { return this._optionsByReference }, ctor: function(options) { if (!this.NAME) throw DX.Error("E0004"); options = options || {}; this._options = {}; this._cachedGetters = {}; this._updateLockCount = 0; this._optionChangedCallbacks = options._optionChangedCallbacks || $.Callbacks(); this._disposingCallbacks = options._disposingCallbacks || $.Callbacks(); this.optionChanged = $.Callbacks(); this.disposing = $.Callbacks(); $.each(["optionChanged", "disposing"], $.proxy(function(_, propertyName) { var that = this, originalAdd = this[propertyName].add; this[propertyName].add = function() { DX.log("W0003", that.NAME, propertyName, "14.2", "Use the '" + propertyName + "' event instead"); return originalAdd.apply(this, arguments) } }, this)); this.beginUpdate(); try { this._suppressDeprecatedWarnings(); this._setOptionsByReference(); this._setDeprecatedOptions(); this._setOptionAliases(); this._setDefaultOptions(); this._setOptionsByDevice(options.defaultOptionsRules); this._resumeDeprecatedWarnings(); this._initialOptions = $.extend({}, this.option()); this._initOptions(options) } finally { this.endUpdate() } }, _initOptions: function(options) { this.option(options) }, _optionValuesEqual: function(name, oldValue, newValue) { oldValue = dataUtils.toComparable(oldValue, true); newValue = dataUtils.toComparable(newValue, true); if (oldValue && newValue && oldValue.jquery && newValue.jquery) return newValue.is(oldValue); var oldValueIsNaN = oldValue !== oldValue, newValueIsNaN = newValue !== newValue; if (oldValueIsNaN && newValueIsNaN) return true; if (oldValue === null || typeof oldValue !== "object") return oldValue === newValue; return false }, _init: function() { this._createOptionChangedAction(); this._createDisposingAction(); this.on("optionChanged", function(args) { this._optionChangedCallbacks.fireWith(this, [args]) }); this.on("disposing", function(args) { this._disposingCallbacks.fireWith(this, [args]) }) }, _createOptionChangedAction: function() { this._optionChangedAction = this._createActionByOption("onOptionChanged", {excludeValidators: ["disabled", "readOnly"]}) }, _createDisposingAction: function() { this._disposingAction = this._createActionByOption("onDisposing", {excludeValidators: ["disabled", "readOnly"]}) }, _optionChanged: function(args) { switch (args.name) { case"onInitialized": break; case"onOptionChanged": this._createOptionChangedAction(); break; case"onDisposing": this._createDisposingAction(); break; case"defaultOptionsRules": break } }, _dispose: function() { this.optionChanged.empty(); this.disposing.fireWith(this).empty(); this._disposingAction(); this._disposeEvents(); this._disposed = true }, instance: function() { return this }, beginUpdate: function() { this._updateLockCount++ }, endUpdate: function() { this._updateLockCount--; if (!this._updateLockCount) if (!this._initializing && !this._initialized) { this._initializing = true; try { this._init() } finally { this._initializing = false; this._initialized = true; this._createActionByOption("onInitialized")() } } }, _logWarningIfDeprecated: function(option) { var info = this._getDeprecatedOptions()[option]; if (info && !this._deprecatedOptionsSuppressed) this._logDeprecatedWarning(option, info) }, _logDeprecatedWarningCount: 0, _logDeprecatedWarning: function(option, info) { var message = info.message || "Use the '" + info.alias + "' option instead"; DX.log("W0001", this.NAME, option, info.since, message); ++this._logDeprecatedWarningCount }, _suppressDeprecatedWarnings: function() { this._deprecatedOptionsSuppressed = true }, _resumeDeprecatedWarnings: function() { this._deprecatedOptionsSuppressed = false }, _notifyOptionChanged: function(option, value, previousValue) { var that = this; if (this._initialized) $.each(that._getOptionAliasesByName(option).concat([option]), function(index, name) { var args = { name: name.split(/[.\[]/)[0], fullName: name, value: value, previousValue: previousValue }; that.optionChanged.fireWith(that, [args.name, value, previousValue]); that._optionChangedAction($.extend({}, args)); if (!that._disposed) that._optionChanged(args) }) }, initialOption: function(optionName) { var options = this._initialOptions; return options[optionName] }, _defaultActionConfig: function() { return { context: this, component: this } }, _defaultActionArgs: function() { return {component: this} }, _createAction: function(actionSource, config) { var that = this, action = new DX.Action(actionSource, $.extend(config, that._defaultActionConfig())); return function(e) { if (!arguments.length) e = {}; if (e instanceof $.Event) throw Error("Action must be executed with jQuery.Event like action({ jQueryEvent: event })"); if (!$.isPlainObject(e)) e = {actionValue: e}; return action.execute.call(action, $.extend(e, that._defaultActionArgs())) } }, _createActionByOption: function(optionName, config) { config = config || {}; if (typeof optionName !== "string") throw DX.Error("E0008"); var matches = /^on(\w+)/.exec(optionName); if (matches) { var eventName = inflector.camelize(matches[1]), afterExecute = config.afterExecute || $.noop, that = this; config.afterExecute = function(args) { that.fireEvent(eventName, args.args); return afterExecute.apply(this, arguments) } } else { var optionAlias = this._getOptionAliasesByName(optionName), isOptionDeprecated = Boolean(this._getDeprecatedOptions()[optionName]); if (isOptionDeprecated) { if (optionAlias.length) throw Error("The '" + optionName + "' is deprecated and has alias '" + optionAlias + "'"); } else throw Error("The '" + optionName + "' option name should start with 'on' prefix"); } this._suppressDeprecatedWarnings(); var action = this._createAction(this.option(optionName), config); this._resumeDeprecatedWarnings(); return action }, option: function(options) { var that = this, name = options, value = arguments[1], optionAliases = this._getOptionAliases(); var normalizeOptionName = function(name) { if (name) { that._logWarningIfDeprecated(name); if (optionAliases[name]) name = optionAliases[name] } return name }; var getOptionValue = function(name, unwrapObservables) { if (!that._cachedGetters[name]) that._cachedGetters[name] = dataUtils.compileGetter(name); return that._cachedGetters[name](that._options, { functionsAsIs: true, unwrapObservables: unwrapObservables }) }; if (arguments.length < 2 && $.type(name) !== "object") { name = normalizeOptionName(name); return getOptionValue(name) } if (typeof name === "string") { options = {}; options[name] = value } that.beginUpdate(); try { $.each(options, function(name, value) { name = normalizeOptionName(name); var prevValue = getOptionValue(name, false); if (that._optionValuesEqual(name, prevValue, value)) return; dataUtils.compileSetter(name)(that._options, value, { functionsAsIs: true, merge: !that._getOptionsByReference()[name], unwrapObservables: false }); that._notifyOptionChanged(name, value, prevValue) }) } finally { that.endUpdate() } } }).include(DX.EventsMixin); $.extend(DX, {Component: Component}) })(jQuery, DevExpress); /*! Module core, file transitionExecutor.js */ (function($, DX) { var directionPostfixes = { forward: " dx-forward", backward: " dx-backward", none: " dx-no-direction", undefined: " dx-no-direction" }; var addToAnimate = function(targetArray, $elements, animationConfig, type) { $elements.each(function() { var resultAnimationConfig = prepareElementAnimationConfig(animationConfig, type); if (resultAnimationConfig) targetArray.push({ $element: $(this), animationConfig: resultAnimationConfig }) }) }; var prepareElementAnimationConfig = function(config, type) { var result; if (typeof config === "string") { var presetName = config; config = DX.animationPresets.getPreset(presetName) } if (!config) result = undefined; else if ($.isFunction(config[type])) result = config[type]; else { var cssClass = "dx-" + type; result = $.extend({skipElementInitialStyles: true}, config); if (!result.type || result.type === "css") { var extraCssClasses = result.extraCssClasses ? " " + result.extraCssClasses : ""; result.type = "css"; result.from = result.from || cssClass + extraCssClasses; result.to = result.to || cssClass + "-active" } } return result }; var setupAnimations = function(items, config) { var result = []; $.each(items, function(index, item) { var animationConfig = item.animationConfig, $element = item.$element, animationInstance; if ($.isPlainObject(animationConfig)) { var fxConfig = getFXConfig(animationConfig, config); fxConfig.staggerDelay = fxConfig.staggerDelay || 0; fxConfig.delay = index * fxConfig.staggerDelay + fxConfig.delay; animationInstance = DX.fx.createAnimation($element, fxConfig) } else if ($.isFunction(animationConfig)) animationInstance = animationConfig($element, config); animationInstance.setup(); result.push({ $element: $element, animationInstance: animationInstance }) }); return result }; var startAnimations = function(items) { for (var i = 0; i < items.length; i++) items[i].animationInstance.start() }; var getFXConfig = function(animation, config) { var result = animation; result.cleanupWhen = config.cleanupWhen; result.delay = result.delay || 0; if (result.type === "css") { var direction = animation.direction || config.direction, directionPostfix = directionPostfixes[direction]; result.from += directionPostfix } return result }; var TransitionExecutor = DevExpress.Class.inherit({ ctor: function() { this.toEnterItems = []; this.toLeaveItems = []; this.reset() }, reset: function() { this.toEnterItems.length = 0; this.toLeaveItems.length = 0 }, enter: function($elements, animation) { animation = animation || {}; addToAnimate(this.toEnterItems, $elements, animation, "enter") }, leave: function($elements, animation) { animation = animation || {}; addToAnimate(this.toLeaveItems, $elements, animation, "leave") }, start: function(config) { config = $.extend({}, config); var that = this, result; if (!this.toEnterItems.length && !this.toLeaveItems.length) { that.reset(); result = $.Deferred().resolve().promise() } else { var animationItems = [], animationDeferreds, completeDeferred = $.Deferred(); config.cleanupWhen = completeDeferred.promise(); animationItems.push.apply(animationItems, setupAnimations(this.toEnterItems, config)); animationItems.push.apply(animationItems, setupAnimations(this.toLeaveItems, config)); animationDeferreds = $.map(animationItems, function(item) { return item.animationInstance.deferred }); result = $.when.apply($, animationDeferreds).always(function() { completeDeferred.resolve(); that.reset() }); DX.utils.executeAsync(function() { startAnimations(animationItems) }) } return result } }); var optionPrefix = "preset_"; var AnimationPresetCollection = DevExpress.Component.inherit({ ctor: function() { this.callBase.apply(this, arguments); this._customRules = []; this._registeredPresets = []; this.resetToDefaults() }, _setDefaultOptions: function() { this.callBase(); this.option({ defaultAnimationDuration: 400, defaultAnimationDelay: 0, defaultStaggerAnimationDuration: 300, defaultStaggerAnimationDelay: 40, defaultStaggerAnimationStartDelay: 500 }) }, _defaultOptionsRules: function() { return this.callBase().concat([{ device: function(device) { return device.phone }, options: { defaultStaggerAnimationDuration: 350, defaultStaggerAnimationDelay: 50, defaultStaggerAnimationStartDelay: 0 } }, { device: function(device) { return device.android }, options: {defaultAnimationDelay: 100} }]) }, _getPresetOptionName: function(animationName) { return optionPrefix + animationName }, resetToDefaults: function() { this.clear(); this.registerDefaultPresets(); this.applyChanges() }, clear: function(name) { var that = this, newRegisteredPresets = []; $.each(this._registeredPresets, function(index, preset) { if (!name || name === preset.name) that.option(that._getPresetOptionName(preset.name), undefined); else newRegisteredPresets.push(preset) }); this._registeredPresets = newRegisteredPresets; this.applyChanges() }, registerPreset: function(name, config) { this._registeredPresets.push({ name: name, config: config }) }, applyChanges: function() { var that = this; this._customRules.length = 0; $.each(this._registeredPresets, function(index, preset) { var rule = { device: preset.config.device, options: {} }; rule.options[that._getPresetOptionName(preset.name)] = preset.config.animation; that._customRules.push(rule) }); this._setOptionsByDevice() }, getPreset: function(name) { var result = name; while (typeof result === "string") result = this.option(this._getPresetOptionName(result)); return result }, registerDefaultPresets: function() { this.registerPreset("fade", {animation: { extraCssClasses: "dx-fade-animation", delay: this.option("defaultAnimationDelay"), duration: this.option("defaultAnimationDuration") }}); this.registerPreset("slide", {animation: { extraCssClasses: "dx-slide-animation", delay: this.option("defaultAnimationDelay"), duration: this.option("defaultAnimationDuration") }}); this.registerPreset("ios7-slide", {animation: { extraCssClasses: "dx-ios7-slide-animation", delay: this.option("defaultAnimationDelay"), duration: this.option("defaultAnimationDuration") }}); this.registerPreset("overflow", {animation: { extraCssClasses: "dx-overflow-animation", delay: this.option("defaultAnimationDelay"), duration: this.option("defaultAnimationDuration") }}); this.registerPreset("ios7-toolbar", {animation: { extraCssClasses: "dx-ios7-toolbar-animation", delay: this.option("defaultAnimationDelay"), duration: this.option("defaultAnimationDuration") }}); this.registerPreset("stagger-fade", {animation: { extraCssClasses: "dx-fade-animation", staggerDelay: this.option("defaultStaggerAnimationDelay"), duration: this.option("defaultStaggerAnimationDuration"), delay: this.option("defaultStaggerAnimationStartDelay") }}); this.registerPreset("stagger-slide", {animation: { extraCssClasses: "dx-slide-animation", staggerDelay: this.option("defaultStaggerAnimationDelay"), duration: this.option("defaultStaggerAnimationDuration"), delay: this.option("defaultStaggerAnimationStartDelay") }}); this.registerPreset("stagger-fade-slide", {animation: { extraCssClasses: "dx-fade-slide-animation", staggerDelay: this.option("defaultStaggerAnimationDelay"), duration: this.option("defaultStaggerAnimationDuration"), delay: this.option("defaultStaggerAnimationStartDelay") }}); this.registerPreset("stagger-drop", {animation: { extraCssClasses: "dx-drop-animation", staggerDelay: this.option("defaultStaggerAnimationDelay"), duration: this.option("defaultStaggerAnimationDuration"), delay: this.option("defaultStaggerAnimationStartDelay") }}); this.registerPreset("stagger-fade-drop", {animation: { extraCssClasses: "dx-fade-drop-animation", staggerDelay: this.option("defaultStaggerAnimationDelay"), duration: this.option("defaultStaggerAnimationDuration"), delay: this.option("defaultStaggerAnimationStartDelay") }}); this.registerPreset("stagger-3d-drop", {animation: { extraCssClasses: "dx-3d-drop-animation", staggerDelay: this.option("defaultStaggerAnimationDelay"), duration: this.option("defaultStaggerAnimationDuration"), delay: this.option("defaultStaggerAnimationStartDelay") }}); this.registerPreset("stagger-fade-zoom", {animation: { extraCssClasses: "dx-fade-zoom-animation", staggerDelay: this.option("defaultStaggerAnimationDelay"), duration: this.option("defaultStaggerAnimationDuration"), delay: this.option("defaultStaggerAnimationStartDelay") }}) } }); DX.TransitionExecutor = TransitionExecutor; DX.AnimationPresetCollection = AnimationPresetCollection; DX.animationPresets = new AnimationPresetCollection })(jQuery, DevExpress); /*! Module core, file DOMComponent.js */ (function($, DX, undefined) { var windowResizeCallbacks = DX.utils.windowResizeCallbacks; var RTL_DIRECTION_CLASS = "dx-rtl", COMPONENT_NAMES_DATA_KEY = "dxComponents", VISIBILITY_CHANGE_CLASS = "dx-visibility-change-handler", VISIBILITY_CHANGE_EVENTNAMESPACE = "dxVisibilityChange"; var DOMComponent = DX.Component.inherit({ NAME: "DOMComponent", _setDefaultOptions: function() { this.callBase(); this.option({ width: undefined, height: undefined, rtlEnabled: DX.rtlEnabled }) }, ctor: function(element, options) { this._$element = $(element); this.element().data(this.NAME, this); this._attachInstanceToElement(this._$element); this.callBase(options) }, _attachInstanceToElement: $.noop, _visibilityChanged: DX.abstract, _dimensionChanged: DX.abstract, _init: function() { this.callBase(); this._attachWindowResizeCallback() }, _attachWindowResizeCallback: function() { if (this._isDimensionChangeSupported()) { var windowResizeCallBack = this._windowResizeCallBack = $.proxy(this._dimensionChanged, this); windowResizeCallbacks.add(windowResizeCallBack) } }, _isDimensionChangeSupported: function() { return this._dimensionChanged !== DX.abstract }, _render: function() { this._toggleRTLDirection(this.option("rtlEnabled")); this._renderVisibilityChange(); this._renderDimensions() }, _renderVisibilityChange: function() { if (!this._isVisibilityChangeSupported()) return; this.element().addClass(VISIBILITY_CHANGE_CLASS); this._attachVisiblityChangeHandlers() }, _renderDimensions: function() { var width = this.option("width"), height = this.option("height"), $element = this.element(); $element.outerWidth(width); $element.outerHeight(height) }, _attachVisiblityChangeHandlers: function() { var that = this; that.element().off("." + VISIBILITY_CHANGE_EVENTNAMESPACE).on("dxhiding." + VISIBILITY_CHANGE_EVENTNAMESPACE, function() { that._visibilityChanged(false) }).on("dxshown." + VISIBILITY_CHANGE_EVENTNAMESPACE, function() { that._visibilityChanged(true) }) }, _isVisibilityChangeSupported: function() { return this._visibilityChanged !== DX.abstract }, _clean: $.noop, _modelByElement: $.noop, _invalidate: function() { if (!this._updateLockCount) throw DX.Error("E0007"); this._requireRefresh = true }, _refresh: function() { this._clean(); this._render() }, _dispose: function() { this.callBase(); this._clean(); this._detachWindowResizeCallback() }, _detachWindowResizeCallback: function() { if (this._isDimensionChangeSupported()) windowResizeCallbacks.remove(this._windowResizeCallBack) }, _toggleRTLDirection: function(rtl) { this.element().toggleClass(RTL_DIRECTION_CLASS, rtl) }, _createComponent: function(element, name, config) { config = config || {}; this._extendConfig(config, {rtlEnabled: this.option("rtlEnabled")}); var $element = $(element)[name](config); return $element[name]("instance") }, _extendConfig: function(config, extendConfig) { $.each(extendConfig, function(key, value) { config[key] = config.hasOwnProperty(key) ? config[key] : value }) }, _defaultActionConfig: function() { return $.extend(this.callBase(), {context: this._modelByElement(this.element())}) }, _defaultActionArgs: function() { var element = this.element(), model = this._modelByElement(this.element()); return $.extend(this.callBase(), { element: element, model: model }) }, _optionChanged: function(args) { switch (args.name) { case"width": case"height": this._renderDimensions(); break; case"rtlEnabled": this._invalidate(); break; default: this.callBase(args); break } }, endUpdate: function() { var requireRender = !this._initializing && !this._initialized; this.callBase.apply(this, arguments); if (!this._updateLockCount) if (requireRender) this._render(); else if (this._requireRefresh) { this._requireRefresh = false; this._refresh() } }, element: function() { return this._$element } }); var registerComponent = function(name, namespace, componentClass) { if (!componentClass) { componentClass = namespace; namespace = DX } componentClass.redefine({_attachInstanceToElement: function($element) { $element.data(name, this); if (!$element.data(COMPONENT_NAMES_DATA_KEY)) $element.data(COMPONENT_NAMES_DATA_KEY, []); $element.data(COMPONENT_NAMES_DATA_KEY).push(name) }}); namespace[name] = componentClass; componentClass.prototype.NAME = name; componentClass.defaultOptions = function(rule) { componentClass.prototype._customRules = componentClass.prototype._customRules || []; componentClass.prototype._customRules.push(rule) }; $.fn[name] = function(options) { var isMemberInvoke = typeof options === "string", result; if (isMemberInvoke) { var memberName = options, memberArgs = $.makeArray(arguments).slice(1); this.each(function() { var instance = $(this).data(name); if (!instance) throw DX.Error("E0009", name); var member = instance[memberName], memberValue = member.apply(instance, memberArgs); if (result === undefined) result = memberValue }) } else { this.each(function() { var instance = $(this).data(name); if (instance) instance.option(options); else new componentClass(this, options) }); result = this } return result } }; var getComponents = function(element) { element = $(element); var names = element.data(COMPONENT_NAMES_DATA_KEY); if (!names) return []; return $.map(names, function(name) { return element.data(name) }) }; var disposeComponents = function() { $.each(getComponents(this), function() { this._dispose() }) }; var originalCleanData = $.cleanData; $.cleanData = function(element) { $.each(element, disposeComponents); return originalCleanData.apply(this, arguments) }; registerComponent("DOMComponent", DOMComponent); DX.registerComponent = registerComponent })(jQuery, DevExpress); /*! Module core, file ui.js */ (function($, DX, undefined) { DX.ui = {}; var createValidatorByTargetElement = function(condition) { return function(e) { if (!e.args.length) return; var args = e.args[0], element = args[e.validatingTargetName] || args.element; if (element && condition(element)) e.cancel = true } }; DX.registerActionExecutor({ designMode: {validate: function(e) { if (DX.designMode) e.cancel = true }}, disabled: {validate: createValidatorByTargetElement(function($target) { return $target.is(".dx-state-disabled, .dx-state-disabled *") })}, readOnly: {validate: createValidatorByTargetElement(function($target) { return $target.is(".dx-state-readonly, .dx-state-readonly *") })} }) })(jQuery, DevExpress); /*! Module core, file ui.templates.js */ (function($, DX, undefined) { var ui = DX.ui, triggerShownEvent = DX.utils.triggerShownEvent; var getWidgetName = function(widgetConstructor) { return widgetConstructor.prototype.NAME }; var TemplateProviderBase = DX.Class.inherit({ ctor: function() { this.widgetTemplatesCache = {} }, createTemplate: DX.abstract, getTemplates: function(widget) { return this._getWidgetTemplates(widget.constructor) }, _getWidgetTemplates: function(widgetConstructor) { if (!getWidgetName(widgetConstructor)) return {}; return this._getCachedWidgetTemplates(widgetConstructor) }, _getCachedWidgetTemplates: function(widgetConstructor) { var widgetName = getWidgetName(widgetConstructor), templatesCache = this.widgetTemplatesCache; if (!templatesCache[widgetName]) templatesCache[widgetName] = $.extend({}, this._getWidgetTemplates(widgetConstructor.parent), this._templatesForWidget(widgetName)); return templatesCache[widgetName] }, _templatesForWidget: DX.abstract }); var TemplateBase = DX.Class.inherit({ ctor: function(element, owner) { this._element = $(element); this._owner = owner }, owner: function() { return this._owner }, render: function(data, $container, index) { if (data instanceof jQuery) { $container = data; data = undefined } if ($container) data = this._prepareDataForContainer(data, $container); var $result = this._renderCore(data, index, $container); if (this._shouldAppend && $container) { $container.append($result); if ($.contains(document.body, $container.get(0))) triggerShownEvent($result) } return $result }, source: function() { return this._element.clone() }, _prepareDataForContainer: function(data) { return data }, _renderCore: DX.abstract, _shouldAppend: true, dispose: function() { this._owner = null } }); $.extend(ui, { TemplateProviderBase: TemplateProviderBase, TemplateBase: TemplateBase }) })(jQuery, DevExpress); /*! Module core, file jquery.templates.js */ (function($, DX, undefined) { var ui = DX.ui, utils = DX.utils, isString = DX.utils.isString, currentTemplateEngine, templateEngines = {}; var Template = ui.TemplateBase.inherit({ ctor: function(element, owner) { this.callBase(element, owner); this._compiledTemplate = currentTemplateEngine.compile(element) }, _renderCore: function(data) { return $("
").append(currentTemplateEngine.render(this._compiledTemplate, data)).contents() } }); var setTemplateEngine = function(templateEngine) { if (isString(templateEngine)) { currentTemplateEngine = templateEngines[templateEngine]; if (!currentTemplateEngine) throw DX.Error("E0020", templateEngine); } else currentTemplateEngine = templateEngine }; var registerTemplateEngine = function(name, templateEngine) { templateEngines[name] = templateEngine }; var outerHtml = function(element) { element = $(element); if (!element.length || element[0].nodeName.toLowerCase() !== "script") element = $("
").append(element); return element.html() }; registerTemplateEngine("default", { compile: function(element) { return DX.utils.normalizeTemplateElement(element) }, render: function(template, data) { return template.clone() } }); registerTemplateEngine("jquery-tmpl", { compile: function(element) { return $("
").append(DX.utils.normalizeTemplateElement(element)) }, render: function(template, data) { return template.tmpl(data) } }); registerTemplateEngine("jsrender", { compile: function(element) { return $.templates(outerHtml(element)) }, render: function(template, data) { return template.render(data) } }); registerTemplateEngine("mustache", { compile: function(element) { return Mustache.compile(outerHtml(element)) }, render: function(template, data) { return template(data) } }); registerTemplateEngine("hogan", { compile: function(element) { return Hogan.compile(outerHtml(element)) }, render: function(template, data) { return template.render(data) } }); registerTemplateEngine("underscore", { compile: function(element) { return _.template(outerHtml(element)) }, render: function(template, data) { return template(data) } }); registerTemplateEngine("handlebars", { compile: function(element) { return Handlebars.compile(outerHtml(element)) }, render: function(template, data) { return template(data) } }); registerTemplateEngine("doT", { compile: function(element) { return doT.template(outerHtml(element)) }, render: function(template, data) { return template(data) } }); setTemplateEngine("default"); var DefaultTemplate = ui.TemplateBase.inherit({ ctor: function(render, owner) { this.callBase($("
"), owner); this._render = render }, _renderCore: function(data, index, container) { return DX.utils.normalizeTemplateElement(this._render(data, index, container)) } }); var TemplateProvider = new(ui.TemplateProviderBase.inherit({ createTemplate: function(element, owner) { return new ui.Template(element, owner) }, _templatesForWidget: function(widgetName) { var templateGenerators = TEMPLATE_GENERATORS[widgetName] || {}, templates = {}; $.each(templateGenerators, function(name, generator) { templates[name] = new ui.DefaultTemplate(function() { var $markup = generator.apply(this, arguments); if (name !== "itemFrame") $markup = $markup.contents(); return $markup }, TemplateProvider) }); return templates } })); var TEMPLATE_GENERATORS = {}; var emptyTemplate = function() { return $() }; var ITEM_CONTENT_PLACEHOLDER_CLASS = "dx-item-content-placeholder"; TEMPLATE_GENERATORS.CollectionWidget = { item: function(itemData) { var $itemContent = $("
"); if ($.isPlainObject(itemData)) { if (itemData.text) $itemContent.text(itemData.text); if (itemData.html) $itemContent.html(itemData.html) } else $itemContent.html(String(itemData)); return $itemContent }, itemFrame: function(itemData) { var $itemFrame = $("
"); $itemFrame.toggleClass("dx-state-invisible", itemData.visible !== undefined && !itemData.visible); $itemFrame.toggleClass("dx-state-disabled", !!itemData.disabled); var $placeholder = $("
").addClass(ITEM_CONTENT_PLACEHOLDER_CLASS); $itemFrame.append($placeholder); return $itemFrame } }; var BUTTON_TEXT_CLASS = "dx-button-text"; TEMPLATE_GENERATORS.dxButton = {content: function(itemData) { var $itemContent = $("
"), $iconElement = utils.getImageContainer(itemData.icon), $textContainer = itemData.text ? $("").text(itemData.text).addClass(BUTTON_TEXT_CLASS) : undefined; $itemContent.append($iconElement).append($textContainer); return $itemContent }}; var LIST_ITEM_BADGE_CONTAINER_CLASS = "dx-list-item-badge-container", LIST_ITEM_BADGE_CLASS = "dx-list-item-badge", BADGE_CLASS = "dx-badge", LIST_ITEM_CHEVRON_CONTAINER_CLASS = "dx-list-item-chevron-container", LIST_ITEM_CHEVRON_CLASS = "dx-list-item-chevron"; TEMPLATE_GENERATORS.dxList = { item: function(itemData) { var $itemContent = TEMPLATE_GENERATORS.CollectionWidget.item(itemData); if (itemData.key) { var $key = $("
").text(itemData.key); $key.appendTo($itemContent) } return $itemContent }, itemFrame: function(itemData) { var $itemFrame = TEMPLATE_GENERATORS.CollectionWidget.itemFrame(itemData); if (itemData.badge) { var $badgeContainer = $("
").addClass(LIST_ITEM_BADGE_CONTAINER_CLASS), $badge = $("
").addClass(LIST_ITEM_BADGE_CLASS).addClass(BADGE_CLASS); $badge.text(itemData.badge); $badgeContainer.append($badge).appendTo($itemFrame) } if (itemData.showChevron) { var $chevronContainer = $("
").addClass(LIST_ITEM_CHEVRON_CONTAINER_CLASS), $chevron = $("
").addClass(LIST_ITEM_CHEVRON_CLASS); $chevronContainer.append($chevron).appendTo($itemFrame) } return $itemFrame }, group: function(groupData) { var $groupContent = $("
"); if ($.isPlainObject(groupData)) { if (groupData.key) $groupContent.text(groupData.key) } else $groupContent.html(String(groupData)); return $groupContent } }; TEMPLATE_GENERATORS.dxDropDownMenu = {item: TEMPLATE_GENERATORS.dxList.item}; TEMPLATE_GENERATORS.dxDropDownList = {item: TEMPLATE_GENERATORS.dxList.item}; TEMPLATE_GENERATORS.dxRadioGroup = {item: TEMPLATE_GENERATORS.CollectionWidget.item}; TEMPLATE_GENERATORS.dxScheduler = {item: function(itemData) { var $itemContent = TEMPLATE_GENERATORS.CollectionWidget.item(itemData); var $details = $("
").addClass("dx-scheduler-appointment-content-details"); if (itemData.startDate) $("").text(Globalize.format(DX.utils.makeDate(itemData.startDate), "t")).appendTo($details); if (itemData.endDate) $("").text(" - " + Globalize.format(DX.utils.makeDate(itemData.endDate), "t")).appendTo($details); $details.appendTo($itemContent); if (itemData.recurrenceRule) $("").addClass("dx-scheduler-appointment-recurrence-icon").appendTo($itemContent); return $itemContent }}; TEMPLATE_GENERATORS.dxOverlay = {content: emptyTemplate}; TEMPLATE_GENERATORS.dxSlideOutView = { menu: emptyTemplate, content: emptyTemplate }; TEMPLATE_GENERATORS.dxSlideOut = { menuItem: TEMPLATE_GENERATORS.dxList.item, menuGroup: TEMPLATE_GENERATORS.dxList.group, content: emptyTemplate }; TEMPLATE_GENERATORS.dxAccordion = { title: function(titleData) { var $titleContent = $("
"), icon = titleData.icon, iconSrc = titleData.iconSrc, $iconElement = utils.getImageContainer(icon || iconSrc); if ($.isPlainObject(titleData)) { if (titleData.title) $titleContent.text(titleData.title) } else $titleContent.html(String(titleData)); $iconElement && $iconElement.prependTo($titleContent); return $titleContent }, item: TEMPLATE_GENERATORS.CollectionWidget.item }; TEMPLATE_GENERATORS.dxActionSheet = {item: function(itemData) { return $("
").append($("
").dxButton($.extend({onClick: itemData.click}, itemData))) }}; TEMPLATE_GENERATORS.dxGallery = {item: function(itemData) { var $itemContent = $("
"); if (itemData.imageSrc) $('').attr('src', itemData.imageSrc).appendTo($itemContent); else $('').attr('src', String(itemData)).appendTo($itemContent); return $itemContent }}; var DX_MENU_ITEM_CAPTION_CLASS = 'dx-menu-item-text', DX_MENU_ITEM_POPOUT_CLASS = 'dx-menu-item-popout', DX_MENU_ITEM_POPOUT_CONTAINER_CLASS = 'dx-menu-item-popout-container'; TEMPLATE_GENERATORS.dxMenuBase = {item: function(itemData) { var $itemContent = $("
"), icon = itemData.icon, iconSrc = itemData.iconSrc, $iconElement = utils.getImageContainer(icon || iconSrc); $iconElement && $iconElement.appendTo($itemContent); var $itemCaption; if ($.isPlainObject(itemData) && itemData.text) $itemCaption = $('').addClass(DX_MENU_ITEM_CAPTION_CLASS).text(itemData.text); else if (!$.isPlainObject(itemData)) $itemCaption = $('').addClass(DX_MENU_ITEM_CAPTION_CLASS).html(String(itemData)); $itemContent.append($itemCaption); var $popOutImage, $popOutContainer; if (itemData.items && itemData.items.length > 0) { $popOutContainer = $('').addClass(DX_MENU_ITEM_POPOUT_CONTAINER_CLASS).appendTo($itemContent); $popOutImage = $('
').addClass(DX_MENU_ITEM_POPOUT_CLASS).appendTo($popOutContainer) } return $itemContent }}; var PANORAMA_ITEM_TITLE_CLASS = "dx-panorama-item-title"; TEMPLATE_GENERATORS.dxPanorama = {itemFrame: function(itemData) { var $itemContent = TEMPLATE_GENERATORS.CollectionWidget.itemFrame(itemData); if (itemData.title) { var $itemHeader = $("
").addClass(PANORAMA_ITEM_TITLE_CLASS).text(itemData.title); $itemContent.prepend($itemHeader) } return $itemContent }}; TEMPLATE_GENERATORS.dxPivotTabs = {item: function(itemData) { var $itemContent = $("
"); var $itemText; if ($.isPlainObject(itemData)) $itemText = $("").text(itemData.title); else $itemText = $("").text(String(itemData)); $itemContent.html($itemText); return $itemContent }}; TEMPLATE_GENERATORS.dxPivot = { title: TEMPLATE_GENERATORS.dxPivotTabs.item, content: emptyTemplate }; var TABS_ITEM_TEXT_CLASS = "dx-tab-text"; TEMPLATE_GENERATORS.dxTabs = { item: function(itemData) { var $itemContent = TEMPLATE_GENERATORS.CollectionWidget.item(itemData); if (itemData.html) return $itemContent; var icon = itemData.icon, iconSrc = itemData.iconSrc, $iconElement = utils.getImageContainer(icon || iconSrc); if (!itemData.html) $itemContent.wrapInner($("").addClass(TABS_ITEM_TEXT_CLASS)); $iconElement && $iconElement.prependTo($itemContent); return $itemContent }, itemFrame: function(itemData) { var $badge = $(), $itemFrame = TEMPLATE_GENERATORS.CollectionWidget.itemFrame(itemData); if (itemData.badge) $badge = $("
", {"class": "dx-tabs-item-badge dx-badge"}).text(itemData.badge); $itemFrame.append($badge); return $itemFrame } }; TEMPLATE_GENERATORS.dxTabPanel = { item: TEMPLATE_GENERATORS.CollectionWidget.item, title: function(itemData) { var itemTitleData = itemData; if ($.isPlainObject(itemData)) itemTitleData = $.extend({}, itemData, {text: itemData.title}); var $title = TEMPLATE_GENERATORS.dxTabs.item(itemTitleData); return $title } }; var NAVBAR_ITEM_BADGE_CLASS = "dx-navbar-item-badge"; TEMPLATE_GENERATORS.dxNavBar = {itemFrame: function(itemData) { var $itemFrame = TEMPLATE_GENERATORS.CollectionWidget.itemFrame(itemData); if (itemData.badge) { var $badge = $("
").addClass(NAVBAR_ITEM_BADGE_CLASS).addClass(BADGE_CLASS); $badge.text(itemData.badge); $badge.appendTo($itemFrame) } return $itemFrame }}; TEMPLATE_GENERATORS.dxToolbar = { item: function(itemData) { var $itemContent = TEMPLATE_GENERATORS.CollectionWidget.item(itemData); var widget = itemData.widget; if (widget) { var widgetElement = $("
").appendTo($itemContent), widgetName = DX.inflector.camelize("dx-" + widget), options = itemData.options || {}; widgetElement[widgetName](options) } else if (itemData.text) $itemContent.wrapInner("
"); return $itemContent }, menuItem: TEMPLATE_GENERATORS.dxList.item, actionSheetItem: TEMPLATE_GENERATORS.dxActionSheet.item }; TEMPLATE_GENERATORS.dxTreeView = {item: function(itemData) { var $itemContent = $("
"), icon = itemData.icon, iconSrc = itemData.iconSrc, $iconElement = utils.getImageContainer(icon || iconSrc); if (itemData.html) $itemContent.html(itemData.html); else { $iconElement && $iconElement.appendTo($itemContent); $("").text(itemData.text).appendTo($itemContent) } return $itemContent }}; var popupTitleAndBottom = function(itemData) { return $("
").append($("
").dxToolbar({items: itemData})) }; TEMPLATE_GENERATORS.dxPopup = { title: popupTitleAndBottom, bottom: popupTitleAndBottom }; TEMPLATE_GENERATORS.dxLookup = { title: TEMPLATE_GENERATORS.dxPopup.title, group: TEMPLATE_GENERATORS.dxList.group }; TEMPLATE_GENERATORS.dxTagBox = {tag: function(itemData) { return $("
").append($("").text(itemData)) }}; TEMPLATE_GENERATORS.dxCalendar = {cell: function(itemData) { return $("
").text(itemData.text || String(itemData)) }}; $.extend(ui, { TemplateProvider: TemplateProvider, Template: Template, DefaultTemplate: DefaultTemplate, setTemplateEngine: setTemplateEngine }) })(jQuery, DevExpress); /*! Module core, file ko.components.js */ (function($, DX, undefined) { if (!DX.support.hasKo) return; var ko = window.ko, ui = DX.ui, LOCKS_DATA_KEY = "dxKoLocks", CREATED_WITH_KO_DATA_KEY = "dxKoCreation"; var Locks = function() { var info = {}; var currentCount = function(lockName) { return info[lockName] || 0 }; return { obtain: function(lockName) { info[lockName] = currentCount(lockName) + 1 }, release: function(lockName) { var count = currentCount(lockName); if (count < 1) throw DX.Error("E0014"); if (count === 1) delete info[lockName]; else info[lockName] = count - 1 }, locked: function(lockName) { return currentCount(lockName) > 0 } } }; var editorsBingindHandlers = []; var registerComponentKoBinding = function(componentName, componentClass) { if (componentClass.subclassOf(ui.Editor)) editorsBingindHandlers.push(componentName); ko.bindingHandlers[componentName] = {init: function(domNode, valueAccessor) { var $element = $(domNode), optionChangedCallbacks = $.Callbacks(), ctorOptions = { templateProvider: ui.KoTemplateProvider, _optionChangedCallbacks: optionChangedCallbacks }, optionNameToModelMap = {}; var applyModelValueToOption = function(optionName, modelValue) { var component = $element.data(componentName), locks = $element.data(LOCKS_DATA_KEY), optionValue = ko.unwrap(modelValue); if (ko.isWriteableObservable(modelValue)) optionNameToModelMap[optionName] = modelValue; if (component) { if (locks.locked(optionName)) return; locks.obtain(optionName); try { component.option(optionName, optionValue) } finally { locks.release(optionName) } } else ctorOptions[optionName] = optionValue }; var handleOptionChanged = function(args) { var optionName = args.fullName, optionValue = args.value; if (!(optionName in optionNameToModelMap)) return; var $element = this._$element, locks = $element.data(LOCKS_DATA_KEY); if (locks.locked(optionName)) return; locks.obtain(optionName); try { optionNameToModelMap[optionName](optionValue) } finally { locks.release(optionName) } }; var createComponent = function() { optionChangedCallbacks.add(handleOptionChanged); $element.data(CREATED_WITH_KO_DATA_KEY, true).data(LOCKS_DATA_KEY, new Locks)[componentName](ctorOptions); ctorOptions = null }; var unwrapModelValue = function(option, model) { var modelUnwrapped; ko.computed(function() { applyModelValueToOption(option, model); modelUnwrapped = ko.unwrap(model) }, null, {disposeWhenNodeIsRemoved: domNode}); if ($.isPlainObject(modelUnwrapped)) $.each(modelUnwrapped, function(optionName, modelValue) { unwrapModelValue(option + "." + optionName, modelValue) }) }; ko.computed(function() { var component = $element.data(componentName); if (component) component.beginUpdate(); $.each(ko.unwrap(valueAccessor()), function(optionName, modelValue) { unwrapModelValue(optionName, modelValue) }); if (component) component.endUpdate(); else createComponent() }, null, {disposeWhenNodeIsRemoved: domNode}); return {controlsDescendantBindings: componentClass.subclassOf(ui.Widget)} }}; if (componentName === "dxValidator") ko.bindingHandlers["dxValidator"].after = editorsBingindHandlers }; DX.DOMComponent.redefine({_modelByElement: function(element) { if (element.length) return ko.dataFor(element.get(0)) }}); var originalRegisterComponent = DX.registerComponent; var registerKoComponent = function(componentName, _, componentClass) { componentClass = componentClass || _; originalRegisterComponent.apply(this, arguments); registerComponentKoBinding(componentName, componentClass) }; DX.registerComponent = registerKoComponent; var cleanKoData = function(element, andSelf) { var cleanNode = function() { ko.cleanNode(this) }; if (andSelf) element.each(cleanNode); else element.find("*").each(cleanNode) }; var originalEmpty = $.fn.empty; $.fn.empty = function() { cleanKoData(this, false); return originalEmpty.apply(this, arguments) }; var originalRemove = $.fn.remove; $.fn.remove = function(selector, keepData) { if (!keepData) { var subject = this; if (selector) subject = subject.filter(selector); cleanKoData(subject, true) } return originalRemove.call(this, selector, keepData) }; var originalHtml = $.fn.html; $.fn.html = function(value) { if (typeof value === "string") cleanKoData(this, false); return originalHtml.apply(this, arguments) }; ko.bindingHandlers.dxAction = {update: function(element, valueAccessor, allBindingsAccessor, viewModel) { var $element = $(element); var unwrappedValue = ko.utils.unwrapObservable(valueAccessor()), actionSource = unwrappedValue, actionOptions = {context: element}; if (unwrappedValue.execute) { actionSource = unwrappedValue.execute; $.extend(actionOptions, unwrappedValue) } var action = new DX.Action(actionSource, actionOptions); $element.off(".dxActionBinding").on("dxclick.dxActionBinding", function(e) { action.execute({ element: $element, model: viewModel, evaluate: function(expression) { var context = viewModel; if (expression.length > 0 && expression[0] === "$") context = ko.contextFor(element); var getter = DX.data.utils.compileGetter(expression); return getter(context) }, jQueryEvent: e }); if (!actionOptions.bubbling) e.stopPropagation() }) }}; ko.bindingHandlers.dxControlsDescendantBindings = {init: function(_, valueAccessor) { return {controlsDescendantBindings: ko.unwrap(valueAccessor())} }}; var render = function($element, options, viewModel, bindingContext) { var result = $.Deferred(); $element.removeClass("dx-pending-rendering-manual"); $element.addClass("dx-pending-rendering-active"); if (options.showLoadIndicator && options.showLoadIndicatorImmediately !== true) showLoadIndicator($element); DX.utils.executeAsync(function() { renderImpl($element, options, viewModel, bindingContext).done(function() { var shownArgs = {element: $element}; if (options.onShown) options.onShown.apply(viewModel, [shownArgs]); result.resolve(shownArgs) }).fail(function() { result.rejectWith(result, arguments) }) }); return result.promise() }; var showLoadIndicator = function($container) { var $indicator = $('
').dxLoadIndicator({visible: true}).addClass("dx-defered-rendering-load-indicator"); $container.append($indicator) }; var isElementInViewport = function(element) { var rect = element.getBoundingClientRect(); return rect.bottom >= 0 && rect.right >= 0 && rect.top <= (window.innerHeight || document.documentElement.clientHeight) && rect.left <= (window.innerWidth || document.documentElement.clientWidth) }; var renderImpl = function($element, options, viewModel, bindingContext) { var animatePromise, childBindingContext = bindingContext.createChildContext(viewModel), renderedArgs = {element: $element}; $element.find(".dx-defered-rendering-load-indicator").remove(); ko.applyBindingsToDescendants(childBindingContext, $element[0]); options._renderedDeferred.resolve(renderedArgs); if (options.onRendered) options.onRendered.apply(viewModel, [renderedArgs]); $element.children().removeClass("dx-invisible-while-pending-rendering"); DX.utils.triggerShownEvent($element.children()); $element.removeClass("dx-pending-rendering"); $element.removeClass("dx-pending-rendering-active"); if (options.animation) { var transitionExecutor = new DX.TransitionExecutor; if (options.staggerItemSelector) { $element.find(options.staggerItemSelector).each(function() { if (isElementInViewport(this)) transitionExecutor.enter($(this), options.animation) }); animatePromise = $.when(animatePromise, transitionExecutor.start()) } else { transitionExecutor.enter($element, options.animation || "content-rendered"); animatePromise = transitionExecutor.start() } } else animatePromise = $.Deferred().resolve().promise(); return animatePromise }; var initElement = function($element, options) { $element.addClass("dx-defer-rendering dx-pending-rendering dx-loadindicator-container"); $element.data("dx-rendered-promise", options._renderedDeferred.promise()); if (options.hiddenUntilRendered) $element.children().addClass("dx-invisible-while-pending-rendering"); if (options.showLoadIndicator && options.showLoadIndicatorImmediately) showLoadIndicator($element) }; var initRender = function($element, options, viewModel, bindingContext) { var doRender = function() { return render($element, options, viewModel, bindingContext) }; if (options.renderWhen) options.renderWhen.done(doRender); else { $element.data("dx-render-delegate", doRender); $element.addClass("dx-pending-rendering-manual") } }; ko.bindingHandlers.dxDeferRendering = {init: function(element, valueAccessor, allBindings, viewModel, bindingContext) { var $element = $(element), passedOptions = ko.unwrap(valueAccessor()), showLoadIndicatorImmediately = ko.unwrap(passedOptions.showLoadIndicatorImmediately), hiddenUntilRendered = ko.unwrap(passedOptions.hiddenUntilRendered), options = { showLoadIndicator: ko.unwrap(passedOptions.showLoadIndicator) || false, showLoadIndicatorImmediately: showLoadIndicatorImmediately !== undefined ? showLoadIndicatorImmediately : true, hiddenUntilRendered: hiddenUntilRendered !== undefined ? hiddenUntilRendered : true, renderWhen: ko.unwrap(passedOptions.renderWhen), animation: ko.unwrap(passedOptions.animation), staggerItemSelector: ko.unwrap(passedOptions.staggerItemSelector), onRendered: ko.unwrap(passedOptions.onRendered), onShown: ko.unwrap(passedOptions.onShown), _renderedDeferred: $.Deferred() }; initElement($element, options); initRender($element, options, viewModel, bindingContext); return {controlsDescendantBindings: true} }}; ko.bindingHandlers.dxIcon = { init: function(element, valueAccessor, allBindings, viewModel, bindingContext) { var options = ko.utils.unwrapObservable(valueAccessor()) || {}, iconElement = DevExpress.utils.getImageContainer(options); ko.virtualElements.emptyNode(element); if (iconElement) ko.virtualElements.prepend(element, iconElement.get(0)) }, update: function(element, valueAccessor, allBindings, viewModel, bindingContext) { var options = ko.utils.unwrapObservable(valueAccessor()) || {}, iconElement = DevExpress.utils.getImageContainer(options); ko.virtualElements.emptyNode(element); if (iconElement) ko.virtualElements.prepend(element, iconElement.get(0)) } }; ko.virtualElements.allowedBindings.dxIcon = true })(jQuery, DevExpress); /*! Module core, file ng.components.js */ (function($, DX, undefined) { if (!DX.support.hasNg) return; var ui = DX.ui, compileSetter = DX.data.utils.compileSetter, compileGetter = DX.data.utils.compileGetter; var ITEM_ALIAS_ATTRIBUTE_NAME = "dxItemAlias", DEFAULT_MODEL_ALIAS = "scopeValue"; var SKIP_APPLY_ACTION_CATEGORIES = ["rendering"]; var phoneJsModule = DX.ng.module; var safeApply = function(func, scope) { if (scope.$root.$$phase) func(scope); else scope.$apply(function() { func(scope) }) }; var ComponentBuilder = DX.Class.inherit({ ctor: function(options) { this._$element = options.$element; this._$templates = options.$templates; this._componentClass = options.componentClass; this._scope = options.scope; this._parse = options.parse; this._compile = options.compile; this._ngOptions = this._normalizeOptions(options.ngOptions); this._itemAlias = options.itemAlias; this._componentDisposing = $.Callbacks(); if (options.ngOptions.data) this._initDataScope(options.ngOptions.data) }, _normalizeOptions: function(options) { var result = $.extend({}, options); if (options.bindingOptions) $.each(options.bindingOptions, function(key, value) { if ($.type(value) === 'string') result.bindingOptions[key] = {dataPath: value} }); return result }, initComponentWithBindings: function() { this._initComponentBindings(); this._initComponent(this._scope); this._shownEventTimer = setTimeout($.proxy(function() { DX.utils.triggerShownEvent(this._$element) }, this)) }, _initDataScope: function(data) { if (typeof data === "string") { var dataStr = data, rootScope = this._scope; data = rootScope.$eval(data); this._scope = rootScope.$new(); this._synchronizeDataScopes(rootScope, this._scope, data, dataStr) } $.extend(this._scope, data) }, _synchronizeDataScopes: function(parentScope, childScope, data, parentPrefix) { var that = this; $.each(data, function(fieldPath) { that._synchronizeScopeField({ parentScope: parentScope, childScope: childScope, fieldPath: fieldPath, parentPrefix: parentPrefix }) }) }, _initComponent: function(scope) { this._component = new this._componentClass(this._$element, this._evalOptions(scope)) }, _initComponentBindings: function() { var that = this, optionDependencies = {}; that._disposingCallbacks = $.Callbacks(); if (that._ngOptions.bindingOptions) $.each(that._ngOptions.bindingOptions, function(optionPath, value) { var separatorIndex = optionPath.search(/\[|\./), optionForSubscribe = separatorIndex > -1 ? optionPath.substring(0, separatorIndex) : optionPath, prevWatchMethod, clearWatcher, valuePath = value.dataPath, deepWatch = true, forcePlainWatchMethod = false; if (value.deep !== undefined) forcePlainWatchMethod = deepWatch = !!value.deep; if (!optionDependencies[optionForSubscribe]) optionDependencies[optionForSubscribe] = {}; optionDependencies[optionForSubscribe][optionPath] = valuePath; var watchCallback = function(newValue, oldValue) { if (newValue !== oldValue) { that._component.option(optionPath, newValue); updateWatcher() } }; var updateWatcher = function() { var watchMethod = $.isArray(that._scope.$eval(valuePath)) && !forcePlainWatchMethod ? "$watchCollection" : "$watch"; if (prevWatchMethod !== watchMethod) { if (clearWatcher) clearWatcher(); clearWatcher = that._scope[watchMethod](valuePath, watchCallback, deepWatch); prevWatchMethod = watchMethod } }; updateWatcher(); that._disposingCallbacks.add(function() { clearWatcher(); that._componentDisposing.fire() }) }); that._optionChangedCallbacks = $.Callbacks().add(function(args) { var optionName = args.name, optionValue = args.value; if (that._scope.$root.$$phase === "$digest" || !optionDependencies || !optionDependencies[optionName]) return; safeApply(function(scope) { $.each(optionDependencies[optionName], function(optionPath, valuePath) { var getter = compileGetter(optionPath); var tmpData = {}; tmpData[optionName] = optionValue; that._parse(valuePath).assign(that._scope, getter(tmpData)) }) }, that._scope) }); that._disposingCallbacks.add(function() { clearTimeout(that._shownEventTimer) }) }, _compilerByTemplate: function(template) { var that = this, scopeItemsPath = this._getScopeItemsPath(); return function(data, index) { var $resultMarkup = $(template).clone(), templateScope; if (data !== undefined) { var dataIsScope = data.$id; templateScope = dataIsScope ? data : that._createScopeWithData(data); $resultMarkup.on("$destroy", function() { var destroyAlreadyCalled = !templateScope.$parent; if (destroyAlreadyCalled) return; templateScope.$destroy() }) } else templateScope = that._scope; if (scopeItemsPath) that._synchronizeScopes(templateScope, scopeItemsPath, index); safeApply(that._compile($resultMarkup), templateScope); return $resultMarkup } }, _getScopeItemsPath: function() { if (this._componentClass.subclassOf(ui.CollectionWidget) && this._ngOptions.bindingOptions && this._ngOptions.bindingOptions.items) return this._ngOptions.bindingOptions.items.dataPath }, _createScopeWithData: function(data) { var newScope = this._scope.$new(true); data = this._enshureDataIsPlainObject(data); $.extend(newScope, data); return newScope }, _synchronizeScopes: function(itemScope, parentPrefix, itemIndex) { var that = this, item = compileGetter(parentPrefix + "[" + itemIndex + "]")(this._scope); item = that._enshureDataIsPlainObject(item); $.each(item, function(itemPath) { that._synchronizeScopeField({ parentScope: that._scope, childScope: itemScope, fieldPath: itemPath, parentPrefix: parentPrefix, itemIndex: itemIndex }) }) }, _synchronizeScopeField: function(args) { var parentScope = args.parentScope, childScope = args.childScope, fieldPath = args.fieldPath, parentPrefix = args.parentPrefix, itemIndex = args.itemIndex; var innerPathSuffix = fieldPath === (this._itemAlias || DEFAULT_MODEL_ALIAS) ? "" : "." + fieldPath, collectionField = itemIndex !== undefined, optionOuterBag = [parentPrefix], optionOuterPath; if (collectionField) optionOuterBag.push("[", itemIndex, "]"); optionOuterBag.push(innerPathSuffix); optionOuterPath = optionOuterBag.join(""); var clearParentWatcher = parentScope.$watch(optionOuterPath, function(newValue, oldValue) { if (newValue !== oldValue) compileSetter(fieldPath)(childScope, newValue) }); var clearItemWatcher = childScope.$watch(fieldPath, function(newValue, oldValue) { if (newValue !== oldValue) { if (collectionField && !compileGetter(parentPrefix)(parentScope)[itemIndex]) { clearItemWatcher(); return } compileSetter(optionOuterPath)(parentScope, newValue) } }); this._componentDisposing.add([clearParentWatcher, clearItemWatcher]) }, _evalOptions: function(scope) { var result = $.extend({}, this._ngOptions); delete result.data; delete result.bindingOptions; if (this._ngOptions.bindingOptions) $.each(this._ngOptions.bindingOptions, function(key, value) { result[key] = scope.$eval(value.dataPath) }); result._optionChangedCallbacks = this._optionChangedCallbacks; result._disposingCallbacks = this._disposingCallbacks; result.templateProvider = ui.NgTemplateProvider; result.templateCompiler = $.proxy(function($template) { return this._compilerByTemplate($template) }, this); return result }, _enshureDataIsPlainObject: function(object) { var result; if ($.isPlainObject(object)) result = object; else { result = {}; result[DEFAULT_MODEL_ALIAS] = object } if (this._itemAlias) result[this._itemAlias] = object; return result } }); ComponentBuilder = ComponentBuilder.inherit({ ctor: function(options) { this.callBase.apply(this, arguments); this._componentName = options.componentName; this._ngModel = options.ngModel; this._ngModelController = options.ngModelController }, _isNgModelRequired: function() { return this._componentClass.subclassOf(ui.Editor) && this._ngModel }, _initComponentBindings: function() { this.callBase.apply(this, arguments); this._initNgModelBinding() }, _initNgModelBinding: function() { if (!this._isNgModelRequired()) return; var that = this; var ngModelWatcher = this._scope.$watch(this._ngModel, function(newValue, oldValue) { if (newValue === oldValue) return; that._component.option(that._ngModelOption(), newValue) }); that._optionChangedCallbacks.add(function(args) { if (args.name !== that._ngModelOption()) return; that._ngModelController.$setViewValue(args.value) }); this._disposingCallbacks.add(function() { ngModelWatcher() }) }, _ngModelOption: function() { if ($.inArray(this._componentName, ["dxFileUploader", "dxTagBox"]) > -1) return "values"; return "value" }, _evalOptions: function() { if (!this._isNgModelRequired()) return this.callBase.apply(this, arguments); var result = this.callBase.apply(this, arguments); result[this._ngModelOption()] = this._parse(this._ngModel)(this._scope); return result } }); var NgComponent = DX.DOMComponent.inherit({ _modelByElement: function(element) { if (element.length) return element.scope() }, _createActionByOption: function(optionName, config) { var action = this.callBase.apply(this, arguments); if (config && $.inArray(config.category, SKIP_APPLY_ACTION_CATEGORIES) > -1) return action; var component = this, wrappedAction = function() { var that = this, scope = component._modelByElement(component.element()), args = arguments; if (!scope || !scope.$root || scope.$root.$$phase) return action.apply(that, args); return scope.$apply(function() { return action.apply(that, args) }) }; return wrappedAction }, _createComponent: function(element, name, config) { return this.callBase(element, name, $.extend({templateCompiler: this.option("templateCompiler")}, config)) } }); var registeredComponents = {}; var originalRegisterComponent = DX.registerComponent; var registerNgComponent = function(componentName, _, componentClass) { componentClass = componentClass || _; originalRegisterComponent.apply(this, arguments); if (!registeredComponents[componentName]) registerComponentDirective(componentName); registeredComponents[componentName] = componentClass }; var registerComponentDirective = function(componentName) { var priority = componentName !== "dxValidator" ? 1 : 10; phoneJsModule.directive(componentName, ["$compile", "$parse", function($compile, $parse) { return { restrict: "A", require: "^?ngModel", priority: priority, compile: function($element) { var componentClass = registeredComponents[componentName], $content = componentClass.subclassOf(ui.Widget) ? $element.contents().detach() : null; return function(scope, $element, attrs, ngModelController) { $element.append($content); var componentBuilder = new ComponentBuilder({ componentClass: componentClass, componentName: componentName, compile: $compile, parse: $parse, $element: $element, scope: scope, ngOptions: attrs[componentName] ? scope.$eval(attrs[componentName]) : {}, ngModel: attrs.ngModel, ngModelController: ngModelController, itemAlias: attrs[ITEM_ALIAS_ATTRIBUTE_NAME] }); componentBuilder.initComponentWithBindings() } } } }]) }; phoneJsModule.filter('dxGlobalize', function() { return function(input, param) { return Globalize.format(input, param) } }); phoneJsModule.directive("dxIcon", ["$compile", function($compile) { return { restrict: 'E', link: function($scope, $element, $attrs) { var html = DX.utils.getImageContainer($scope.icon || $scope.iconSrc); if (html) { var e = $compile(html.get(0))($scope); $element.replaceWith(e) } } } }]); DX.registerComponent = registerNgComponent; registerNgComponent("DOMComponent", NgComponent) })(jQuery, DevExpress); /*! Module core, file ko.templates.js */ (function($, DX, undefined) { if (!DX.support.hasKo) return; var ko = window.ko, ui = DX.ui; var KoTemplate = ui.TemplateBase.inherit({ ctor: function(element) { this.callBase.apply(this, arguments); this._template = $("
").append(DX.utils.normalizeTemplateElement(element)); this._registerKoTemplate() }, _registerKoTemplate: function() { var template = this._template.get(0); new ko.templateSources.anonymousTemplate(template)['nodes'](template) }, _prepareDataForContainer: function(data, container) { var result = data, containerElement, containerContext; if (container.length) { containerElement = container.get(0); data = data !== undefined ? data : ko.dataFor(containerElement) || {}; containerContext = ko.contextFor(containerElement); if (containerContext) result = data === containerContext.$data ? containerContext : containerContext.createChildContext(data); else result = data } return result }, _renderCore: function(data) { var $renderBag = $("
"); ko.renderTemplate(this._template.get(0), data, null, $renderBag.get(0)); var $result = $renderBag.contents().detach(); $renderBag.remove(); return $result }, dispose: function() { this.callBase(); this._template.remove() } }); var KoTemplateProvider = new(ui.TemplateProviderBase.inherit({ createTemplate: function(element, owner) { return new KoTemplate(element, owner) }, applyTemplate: function(element, model) { ko.applyBindings(model, element) }, _templatesForWidget: function(widgetName) { var templateGenerators = TEMPLATE_GENERATORS[widgetName] || {}, templates = {}; $.each(templateGenerators, function(name, generator) { var $markup = DX.utils.createMarkupFromString(generator()); if (name !== "itemFrame") $markup = $markup.contents(); templates[name] = new KoTemplate($markup, KoTemplateProvider) }); return templates } })); var createElementWithBindAttr = function(tagName, bindings, closeTag, additionalProperties) { closeTag = closeTag === undefined ? true : closeTag; var bindAttr = $.map(bindings, function(value, key) { return key + ":" + value }).join(","); additionalProperties = additionalProperties || ""; return "<" + tagName + " data-bind=\"" + bindAttr + "\" " + additionalProperties + ">" + (closeTag ? "" : "") }; var defaultKoTemplateBasicBindings = {css: "{ 'dx-state-disabled': $data.disabled, 'dx-state-invisible': !($data.visible === undefined || ko.unwrap($data.visible)) }"}; var TEMPLATE_GENERATORS = {}; var emptyTemplate = function() { return "" }; TEMPLATE_GENERATORS.CollectionWidget = { itemFrame: function() { var markup = [createElementWithBindAttr("div", defaultKoTemplateBasicBindings, false), "
", "
"]; return markup.join("") }, item: function() { var htmlBinding = createElementWithBindAttr("div", {html: "html"}), textBinding = createElementWithBindAttr("div", {text: "text"}), primitiveBinding = createElementWithBindAttr("div", {text: "String($data)"}); var markup = ["
", "", htmlBinding, "", "", textBinding, "", "", primitiveBinding, "", "
"]; return markup.join("") } }; var BUTTON_TEXT_CLASS = "dx-button-text"; TEMPLATE_GENERATORS.dxButton = {content: function() { var textBinding = createElementWithBindAttr("span", { text: "$data.text", css: "{ '" + BUTTON_TEXT_CLASS + "' : !!$data.text }" }); var markup = ["
", "", textBinding, "
"]; return markup.join("") }}; var LIST_ITEM_BADGE_CONTAINER_CLASS = "dx-list-item-badge-container", LIST_ITEM_BADGE_CLASS = "dx-list-item-badge", BADGE_CLASS = "dx-badge", LIST_ITEM_CHEVRON_CONTAINER_CLASS = "dx-list-item-chevron-container", LIST_ITEM_CHEVRON_CLASS = "dx-list-item-chevron"; TEMPLATE_GENERATORS.dxList = { item: function() { var template = TEMPLATE_GENERATORS.CollectionWidget.item(), keyBinding = createElementWithBindAttr("div", {text: "key"}); template = [template.substring(0, template.length - 6), "" + keyBinding + "", "
"]; return template.join("") }, itemFrame: function() { var template = TEMPLATE_GENERATORS.CollectionWidget.itemFrame(), badgeBinding = createElementWithBindAttr("div", {text: "badge"}, true, 'class="' + LIST_ITEM_BADGE_CLASS + " " + BADGE_CLASS + '"'); var markup = [template.substring(0, template.length - 6), "", "
", badgeBinding, "
", "", "", "
", "
", "
", "", "
"]; return markup.join("") }, group: function() { var keyBinding = createElementWithBindAttr("div", {text: "key"}), primitiveBinding = createElementWithBindAttr("div", {text: "String($data)"}); var markup = ["
", "", keyBinding, "", "", primitiveBinding, "", "
"]; return markup.join("") } }; TEMPLATE_GENERATORS.dxDropDownMenu = {item: TEMPLATE_GENERATORS.dxList.item}; TEMPLATE_GENERATORS.dxDropDownList = {item: TEMPLATE_GENERATORS.dxList.item}; TEMPLATE_GENERATORS.dxRadioGroup = {item: TEMPLATE_GENERATORS.CollectionWidget.item}; TEMPLATE_GENERATORS.dxScheduler = {item: function() { var template = TEMPLATE_GENERATORS.CollectionWidget.item(), startDateBinding = createElementWithBindAttr("strong", {text: "Globalize.format(DevExpress.utils.makeDate($data.startDate), 't')"}), endDateBinding = createElementWithBindAttr("strong", {text: "' - ' + Globalize.format(DevExpress.utils.makeDate($data.endDate), 't')"}); template = [template.substring(0, template.length - 6), "
", "" + startDateBinding + "", "" + endDateBinding + "", "
", "", "
"]; return template.join("") }}; TEMPLATE_GENERATORS.dxOverlay = {content: emptyTemplate}; TEMPLATE_GENERATORS.dxSlideOutView = { menu: emptyTemplate, content: emptyTemplate }; TEMPLATE_GENERATORS.dxSlideOut = { menuItem: TEMPLATE_GENERATORS.dxList.item, menuGroup: TEMPLATE_GENERATORS.dxList.group, content: emptyTemplate }; TEMPLATE_GENERATORS.dxAccordion = { title: function() { var titleBinding = createElementWithBindAttr("span", {text: "$.isPlainObject($data) ? $data.title : String($data)"}); var markup = ["
", "", titleBinding, "
"]; return markup.join("") }, item: TEMPLATE_GENERATORS.CollectionWidget.item }; TEMPLATE_GENERATORS.dxResponsiveBox = {item: TEMPLATE_GENERATORS.CollectionWidget.item}, TEMPLATE_GENERATORS.dxPivotTabs = {item: function() { var titleBinding = createElementWithBindAttr("span", {text: "title"}), primitiveBinding = createElementWithBindAttr("div", {text: "String($data)"}); var markup = ["
", "", titleBinding, "", "", primitiveBinding, "", "
"]; return markup.join("") }}; TEMPLATE_GENERATORS.dxPivot = { title: TEMPLATE_GENERATORS.dxPivotTabs.item, content: emptyTemplate }; var PANORAMA_ITEM_TITLE_CLASS = "dx-panorama-item-title"; TEMPLATE_GENERATORS.dxPanorama = {itemFrame: function() { var template = TEMPLATE_GENERATORS.CollectionWidget.itemFrame(), headerBinding = createElementWithBindAttr("div", {text: "title"}, true, 'class="' + PANORAMA_ITEM_TITLE_CLASS + '"'); var divInnerStart = template.indexOf(">") + 1; template = [template.substring(0, divInnerStart), "", headerBinding, "", template.substring(divInnerStart, template.length)]; return template.join("") }}; TEMPLATE_GENERATORS.dxActionSheet = {item: function() { return ["
", createElementWithBindAttr("div", {dxButton: "{ text: $data.text, onClick: $data.clickAction || $data.onClick, type: $data.type, disabled: !!ko.unwrap($data.disabled) }"}), "
"].join("") }}; TEMPLATE_GENERATORS.dxToolbar = { item: function() { var template = TEMPLATE_GENERATORS.CollectionWidget.item(); template = [template.substring(0, template.length - 6), ""]; $.each(["button", "tabs", "dropDownMenu"], function() { var bindingName = DX.inflector.camelize(["dx", "-", this].join("")), bindingObj = {}; bindingObj[bindingName] = "$data.options"; template.push("", createElementWithBindAttr("div", bindingObj), "") }); template.push(""); return template.join("") }, menuItem: TEMPLATE_GENERATORS.dxList.item, actionSheetItem: TEMPLATE_GENERATORS.dxActionSheet.item }; TEMPLATE_GENERATORS.dxGallery = {item: function() { var template = TEMPLATE_GENERATORS.CollectionWidget.item(), primitiveBinding = createElementWithBindAttr("div", {text: "String($data)"}), imgBinding = createElementWithBindAttr("img", {attr: "{ src: String($data) }"}, false); template = [template.substring(0, template.length - 6).replace(primitiveBinding, imgBinding), "", createElementWithBindAttr("img", {attr: "{ src: $data.imageSrc }"}, false), ""].join(""); return template }}; TEMPLATE_GENERATORS.dxTabs = { item: function() { var template = TEMPLATE_GENERATORS.CollectionWidget.item(), basePrimitiveBinding = createElementWithBindAttr("div", {text: "String($data)"}), primitiveBinding = "", baseTextBinding = createElementWithBindAttr("div", {text: "text"}), textBinding = "" + ""; template = template.replace("", "").replace(basePrimitiveBinding, primitiveBinding).replace(baseTextBinding, textBinding); return template }, itemFrame: function() { var template = TEMPLATE_GENERATORS.CollectionWidget.itemFrame(), badgeBinding = createElementWithBindAttr("div", { attr: "{ 'class': 'dx-tabs-item-badge dx-badge' }", text: "badge" }); var markup = [template.substring(0, template.length - 6), "", badgeBinding, "", "
"]; return markup.join("") } }; TEMPLATE_GENERATORS.dxTabPanel = { item: TEMPLATE_GENERATORS.CollectionWidget.item, title: function() { var template = TEMPLATE_GENERATORS.dxTabs.item(); return template.replace(/\$data\.text/g, '$data.title') } }; var NAVBAR_ITEM_BADGE_CLASS = "dx-navbar-item-badge"; TEMPLATE_GENERATORS.dxNavBar = {itemFrame: function() { var template = TEMPLATE_GENERATORS.CollectionWidget.itemFrame(), badgeBinding = createElementWithBindAttr("div", {text: "badge"}, true, 'class="' + NAVBAR_ITEM_BADGE_CLASS + " " + BADGE_CLASS + '"'); var markup = [template.substring(0, template.length - 6), "", badgeBinding, "", "
"]; return markup.join("") }}; TEMPLATE_GENERATORS.dxMenuBase = {item: function() { var template = [createElementWithBindAttr("div", defaultKoTemplateBasicBindings, false)], textBinding = createElementWithBindAttr("span", { text: "text", css: "{ 'dx-menu-item-text': true }" }), primitiveBinding = createElementWithBindAttr("span", { text: "String($data)", css: "{ 'dx-menu-item-text': true }" }), popout = "
"; template.push("", "", textBinding, "", "", primitiveBinding, "", "", popout, "", "
"); return template.join("") }}; TEMPLATE_GENERATORS.dxTreeView = {item: function() { var node = [], link = createElementWithBindAttr("span", {text: "text"}, true), htmlBinding = createElementWithBindAttr("div", {html: "html"}); node.push("
", "", htmlBinding, "", "", "" + link + "", "
"); return node.join("") }}; TEMPLATE_GENERATORS.dxCalendar = {cell: function() { var textBinding = createElementWithBindAttr("span", {text: "text"}), primitiveBinding = createElementWithBindAttr("span", {text: "String($data)"}); var markup = ["
", "", textBinding, "", "", primitiveBinding, "", "
"]; return markup.join("") }}; var popupTitleAndBottom = function() { return ["
", createElementWithBindAttr("div", {dxToolbar: "{ items: $data }"}), "
"].join("") }; TEMPLATE_GENERATORS.dxPopup = { title: popupTitleAndBottom, bottom: popupTitleAndBottom }; TEMPLATE_GENERATORS.dxLookup = { title: TEMPLATE_GENERATORS.dxPopup.title, group: TEMPLATE_GENERATORS.dxList.group }; TEMPLATE_GENERATORS.dxTagBox = {tag: function() { return ["
", createElementWithBindAttr("span", {text: "$data"})].join("") }}; $.extend(ui, { KoTemplateProvider: KoTemplateProvider, KoTemplate: KoTemplate }) })(jQuery, DevExpress); /*! Module core, file ng.templates.js */ (function($, DX, undefined) { if (!DX.support.hasNg) return; var ui = DX.ui; var TEMPLATE_WRAPPER_CLASS = "dx-template-wrapper"; var NgTemplate = ui.TemplateBase.inherit({ ctor: function() { this.callBase.apply(this, arguments); this.setCompiler(this._getParentTemplateCompiler()) }, _getParentTemplateCompiler: function() { var templateCompiler = null, owner = this.owner(); while (!templateCompiler && owner) { templateCompiler = $.isFunction(owner.option) ? owner.option("templateCompiler") : null; owner = $.isFunction(owner.owner) ? owner.owner() : null } return templateCompiler }, _renderCore: function(data, index, $container) { var compiledTemplate = this._compiledTemplate, result = $.isFunction(compiledTemplate) ? compiledTemplate(data, index, $container) : compiledTemplate; return result }, setCompiler: function(templateCompiler) { if (!templateCompiler) return; this._compiledTemplate = templateCompiler(DX.utils.normalizeTemplateElement(this._element)) } }); var NgTemplateProvider = new(ui.TemplateProviderBase.inherit({ createTemplate: function(element, owner) { return new NgTemplate(element, owner) }, getTemplates: function(widget) { var templateCompiler = widget.option("templateCompiler"), templates = this.callBase.apply(this, arguments); $.each(templates, function(_, template) { template.setCompiler(templateCompiler) }); return templates }, _templatesForWidget: function(widgetName) { var templateGenerators = TEMPLATE_GENERATORS[widgetName] || {}, templates = {}; $.each(templateGenerators, function(name, generator) { var $markup = DX.utils.createMarkupFromString(generator()); templates[name] = new NgTemplate($markup.wrap(), NgTemplateProvider) }); return templates } })); var baseElements = { container: function() { return $("
").addClass(TEMPLATE_WRAPPER_CLASS) }, html: function() { return $("
").attr("ng-if", "html").attr("ng-bind-html", "html") }, text: function() { return $("
").attr("ng-if", "text").attr("ng-bind", "text") }, primitive: function() { return $("
").attr("ng-if", "scopeValue").attr("ng-bind-html", "'' + scopeValue") } }; var TEMPLATE_GENERATORS = {}; var emptyTemplate = function() { return $() }; TEMPLATE_GENERATORS.CollectionWidget = { item: function() { return baseElements.container().append(baseElements.html()).append(baseElements.text()).append(baseElements.primitive()) }, itemFrame: function() { var $container = $("
").attr("ng-class", "{ 'dx-state-invisible': !visible && visible != undefined, 'dx-state-disabled': !!disabled }"), $placeholder = $("
").addClass("dx-item-content-placeholder"); $container.append($placeholder); return $container } }; var BUTTON_TEXT_CLASS = "dx-button-text"; TEMPLATE_GENERATORS.dxButton = {content: function() { var $titleBinding = $("").attr("ng-bind", "text").attr("ng-class", "{ '" + BUTTON_TEXT_CLASS + "' : !!text }"), icon = $(""); return baseElements.container().append(icon).append($titleBinding).append(baseElements.primitive()) }}; var LIST_ITEM_BADGE_CONTAINER_CLASS = "dx-list-item-badge-container", LIST_ITEM_BADGE_CLASS = "dx-list-item-badge", BADGE_CLASS = "dx-badge", LIST_ITEM_CHEVRON_CONTAINER_CLASS = "dx-list-item-chevron-container", LIST_ITEM_CHEVRON_CLASS = "dx-list-item-chevron"; TEMPLATE_GENERATORS.dxList = { item: function() { return TEMPLATE_GENERATORS.CollectionWidget.item().append($("
").attr("ng-if", "key").attr("ng-bind", "key")) }, itemFrame: function() { var $badgeContainer = $("
").addClass(LIST_ITEM_BADGE_CONTAINER_CLASS).attr("ng-if", "badge"), $badge = $("
").addClass(LIST_ITEM_BADGE_CLASS).addClass(BADGE_CLASS).attr("ng-bind", "badge"); var $chevronContainer = $("
").addClass(LIST_ITEM_CHEVRON_CONTAINER_CLASS).attr("ng-if", "showChevron"), $chevron = $("
").addClass(LIST_ITEM_CHEVRON_CLASS); return TEMPLATE_GENERATORS.CollectionWidget.itemFrame().append($badgeContainer.append($badge)).append($chevronContainer.append($chevron)) }, group: function() { var $keyBinding = $("
").attr("ng-if", "key").attr("ng-bind", "key"); return baseElements.container().append($keyBinding).append(baseElements.primitive()) } }; TEMPLATE_GENERATORS.dxDropDownMenu = {item: TEMPLATE_GENERATORS.dxList.item}; TEMPLATE_GENERATORS.dxDropDownList = {item: TEMPLATE_GENERATORS.dxList.item}; TEMPLATE_GENERATORS.dxRadioGroup = {item: TEMPLATE_GENERATORS.CollectionWidget.item}; TEMPLATE_GENERATORS.dxScheduler = {item: function() { var $itemContent = TEMPLATE_GENERATORS.CollectionWidget.item(); var $details = $("
").addClass("dx-scheduler-appointment-content-details"); $("").attr("ng-if", "startDate").text("{{startDate | date : 'shortTime' }}").appendTo($details); $("").attr("ng-if", "endDate").text(" - {{endDate | date : 'shortTime' }}").appendTo($details); $details.appendTo($itemContent); $("").attr("ng-if", "recurrenceRule").addClass("dx-scheduler-appointment-recurrence-icon").appendTo($itemContent); return $itemContent }}; TEMPLATE_GENERATORS.dxOverlay = {content: emptyTemplate}; TEMPLATE_GENERATORS.dxSlideOutView = { menu: emptyTemplate, content: emptyTemplate }; TEMPLATE_GENERATORS.dxSlideOut = { menuItem: TEMPLATE_GENERATORS.dxList.item, menuGroup: TEMPLATE_GENERATORS.dxList.group, content: emptyTemplate }; TEMPLATE_GENERATORS.dxAccordion = { title: function() { var $titleBinding = $("").attr("ng-if", "title").attr("ng-bind", "title"), icon = $(""); return baseElements.container().append(icon).append($titleBinding).append(baseElements.primitive()) }, content: TEMPLATE_GENERATORS.CollectionWidget.item }; TEMPLATE_GENERATORS.dxPivotTabs = {item: function() { return baseElements.container().append($("").attr("ng-if", "title").attr("ng-bind", "title")).append(baseElements.primitive()) }}; TEMPLATE_GENERATORS.dxPivot = { title: TEMPLATE_GENERATORS.dxPivotTabs.item, content: emptyTemplate }; var PANORAMA_ITEM_TITLE_CLASS = "dx-panorama-item-title"; TEMPLATE_GENERATORS.dxPanorama = {itemFrame: function() { return TEMPLATE_GENERATORS.CollectionWidget.itemFrame().prepend($("
").addClass(PANORAMA_ITEM_TITLE_CLASS).attr("ng-if", "title").attr("ng-bind", "title")) }}; TEMPLATE_GENERATORS.dxActionSheet = {item: function() { return baseElements.container().append($("
").attr("dx-button", "{ bindingOptions: { text: 'text', onClick: 'onClick', type: 'type', disabled: 'disabled' } }")) }}; TEMPLATE_GENERATORS.dxToolbar = { item: function() { var template = TEMPLATE_GENERATORS.CollectionWidget.item(); $.each(["button", "tabs", "dropDownMenu"], function(i, widgetName) { var bindingName = "dx-" + DX.inflector.dasherize(this); $("
").attr("ng-if", "widget === '" + widgetName + "'").attr(bindingName, "options").appendTo(template) }); return template }, menuItem: TEMPLATE_GENERATORS.dxList.item, actionSheetItem: TEMPLATE_GENERATORS.dxActionSheet.item }; TEMPLATE_GENERATORS.dxGallery = {item: function() { return baseElements.container().append(baseElements.html()).append(baseElements.text()).append($("").attr("ng-if", "scopeValue").attr("ng-src", "{{'' + scopeValue}}")).append($("").attr("ng-if", "imageSrc").attr("ng-src", "{{imageSrc}}")) }}; var TABS_ITEM_TEXT_CLASS = "dx-tab-text"; TEMPLATE_GENERATORS.dxTabs = { item: function() { var container = baseElements.container(); var text = $("").addClass(TABS_ITEM_TEXT_CLASS).attr("ng-bind", "text").attr("ng-if", "text"), icon = $(""); return container.append(baseElements.html()).append(icon).append(text).append(baseElements.primitive().addClass(TABS_ITEM_TEXT_CLASS)) }, itemFrame: function() { var $badge = $("
").addClass("dx-tabs-item-badge dx-badge").attr("ng-bind", "badge").attr("ng-if", "badge"); return TEMPLATE_GENERATORS.CollectionWidget.itemFrame().append($badge) } }; var NAVBAR_ITEM_BADGE_CLASS = "dx-navbar-item-badge"; TEMPLATE_GENERATORS.dxNavBar = {itemFrame: function() { var $badge = $("
").addClass(NAVBAR_ITEM_BADGE_CLASS).addClass(BADGE_CLASS).attr("ng-if", "badge").attr("ng-bind", "badge"); return TEMPLATE_GENERATORS.CollectionWidget.itemFrame().append($badge) }}; TEMPLATE_GENERATORS.dxMenuBase = {item: function() { var container = baseElements.container(); var text = $("").attr("ng-if", "text").addClass("dx-menu-item-text").attr("ng-bind", "text"), icon = $(""), popout = $("").addClass("dx-menu-item-popout-container").attr("ng-if", "items").append($("
").addClass("dx-menu-item-popout")); container.append(baseElements.html()).append(icon).append(text).append(popout).append(baseElements.primitive()).appendTo(container); return container }}; TEMPLATE_GENERATORS.dxTreeView = {item: function() { var content = baseElements.container(), link = $("").attr("ng-bind", "text"), icon = $(""); content.append(baseElements.html()).append(icon).append(link).append(baseElements.primitive()); return content }}; TEMPLATE_GENERATORS.dxTabPanel = { item: TEMPLATE_GENERATORS.CollectionWidget.item, title: function() { var content = TEMPLATE_GENERATORS.dxTabs.item(); content.find(".dx-tab-text").eq(0).attr("ng-bind", "title").attr("ng-if", "title"); return content } }; var popupTitleAndBottom = function() { return $("
").attr("dx-toolbar", "{ bindingOptions: { items: 'scopeValue' } }") }; TEMPLATE_GENERATORS.dxPopup = { title: popupTitleAndBottom, bottom: popupTitleAndBottom }; TEMPLATE_GENERATORS.dxLookup = { title: TEMPLATE_GENERATORS.dxPopup.title, group: TEMPLATE_GENERATORS.dxList.group }; TEMPLATE_GENERATORS.dxTagBox = {tag: function() { return $("
").append($("").attr("ng-bind", "scopeValue")) }}; TEMPLATE_GENERATORS.dxCalendar = {cell: function() { var $cell = $("").attr("ng-if", "text").attr("ng-bind", "text"); return baseElements.container().append($cell).append(baseElements.primitive()) }}; $.extend(ui, { NgTemplate: NgTemplate, NgTemplateProvider: NgTemplateProvider }) })(jQuery, DevExpress); /*! Module core, file ko.validation.js */ (function($, DX, undefined) { if (!DX.support.hasKo) return; var ko = window.ko; var koDxValidator = DX.Class.inherit({ ctor: function(target, option) { var that = this; that.target = target; that.validationRules = option.validationRules; that.name = option.name; that.isValid = ko.observable(true); that.validationError = ko.observable(); $.each(this.validationRules, function(_, rule) { rule.validator = that }) }, validate: function() { var result = DevExpress.validationEngine.validate(this.target(), this.validationRules, this.name); this._applyValidationResult(result); return result }, reset: function() { this.target(null); var result = { isValid: true, brokenRule: null }; this._applyValidationResult(result); return result }, _applyValidationResult: function(result) { result.validator = this; this.target.dxValidator.isValid(result.isValid); this.target.dxValidator.validationError(result.brokenRule); this.fireEvent("validated", [result]) } }).include(DX.EventsMixin); ko.extenders.dxValidator = function(target, option) { target.dxValidator = new koDxValidator(target, option); target.subscribe($.proxy(target.dxValidator.validate, target.dxValidator)); return target }; DevExpress.validationEngine.registerModelForValidation = function(model) { $.each(model, function(name, member) { if (ko.isObservable(member) && member.dxValidator) DevExpress.validationEngine.registerValidatorInGroup(model, member.dxValidator) }) }; DevExpress.validationEngine.validateModel = DevExpress.validationEngine.validateGroup })(jQuery, DevExpress); /*! Module core, file ui.themes.js */ (function($, DX, undefined) { var DX_LINK_SELECTOR = "link[rel=dx-theme]", THEME_ATTR = "data-theme", ACTIVE_ATTR = "data-active"; var context, $activeThemeLink, knownThemes, currentThemeName, pendingThemeName; var THEME_MARKER_PREFIX = "dx."; function readThemeMarker() { var element = $("
", context).addClass("dx-theme-marker").appendTo(context.documentElement), result; try { result = element.css("font-family"); if (!result) return null; result = result.replace(/["']/g, ""); if (result.substr(0, THEME_MARKER_PREFIX.length) !== THEME_MARKER_PREFIX) return null; return result.substr(THEME_MARKER_PREFIX.length) } finally { element.remove() } } function waitForThemeLoad(themeName, callback) { var timerId, waitStartTime; pendingThemeName = themeName; function handleLoaded() { pendingThemeName = null; callback() } if (isPendingThemeLoaded()) handleLoaded(); else { waitStartTime = $.now(); timerId = setInterval(function() { var isLoaded = isPendingThemeLoaded(), isTimeout = !isLoaded && $.now() - waitStartTime > 15 * 1000; if (isTimeout) DX.log("W0004", pendingThemeName); if (isLoaded || isTimeout) { clearInterval(timerId); handleLoaded() } }, 10) } } function isPendingThemeLoaded() { return !pendingThemeName || readThemeMarker() === pendingThemeName } function processMarkup() { var $allThemeLinks = $(DX_LINK_SELECTOR, context); if (!$allThemeLinks.length) return; knownThemes = {}; $activeThemeLink = $(DX.utils.createMarkupFromString(""), context); $allThemeLinks.each(function() { var link = $(this, context), fullThemeName = link.attr(THEME_ATTR), url = link.attr("href"), isActive = link.attr(ACTIVE_ATTR) === "true"; knownThemes[fullThemeName] = { url: url, isActive: isActive } }); $allThemeLinks.last().after($activeThemeLink); $allThemeLinks.remove() } function resolveFullThemeName(desiredThemeName) { var desiredThemeParts = desiredThemeName.split("."), result = null; if (knownThemes) $.each(knownThemes, function(knownThemeName, themeData) { var knownThemeParts = knownThemeName.split("."); if (knownThemeParts[0] !== desiredThemeParts[0]) return; if (desiredThemeParts[1] && desiredThemeParts[1] !== knownThemeParts[1]) return; if (desiredThemeParts[2] && desiredThemeParts[2] !== knownThemeParts[2]) return; if (!result || themeData.isActive) result = knownThemeName; if (themeData.isActive) return false }); return result } function initContext(newContext) { try { if (newContext !== context) knownThemes = null } catch(x) { knownThemes = null } context = newContext } function init(options) { options = options || {}; initContext(options.context || document); processMarkup(); currentThemeName = undefined; current(options) } function current(options) { if (!arguments.length) return currentThemeName || readThemeMarker(); detachCssClasses(DX.viewPort(), currentThemeName); options = options || {}; if (typeof options === "string") options = {theme: options}; var isAutoInit = options._autoInit, loadCallback = options.loadCallback, currentThemeData; currentThemeName = options.theme || currentThemeName; if (isAutoInit && !currentThemeName) currentThemeName = themeNameFromDevice(DX.devices.current()); currentThemeName = resolveFullThemeName(currentThemeName); if (currentThemeName) currentThemeData = knownThemes[currentThemeName]; if (currentThemeData) { $activeThemeLink.attr("href", knownThemes[currentThemeName].url); if (loadCallback) waitForThemeLoad(currentThemeName, loadCallback); else if (pendingThemeName) pendingThemeName = currentThemeName } else if (isAutoInit) { if (loadCallback) loadCallback() } else throw DX.Error("E0021", currentThemeName); attachCssClasses(DX.viewPort(), currentThemeName) } function themeNameFromDevice(device) { var themeName = device.platform; if (themeName === "ios") themeName += "7"; if (themeName === "android") themeName += "5"; return themeName } function getCssClasses(themeName) { themeName = themeName || current(); var result = [], themeNameParts = themeName && themeName.split("."); if (themeNameParts) { result.push("dx-theme-" + themeNameParts[0], "dx-theme-" + themeNameParts[0] + "-typography"); if (themeNameParts.length > 1) result.push("dx-color-scheme-" + themeNameParts[1]) } return result } var themeClasses; function attachCssClasses(element, themeName) { themeClasses = getCssClasses(themeName).join(" "); $(element).addClass(themeClasses) } function detachCssClasses(element, themeName) { $(element).removeClass(themeClasses) } $.holdReady(true); init({ _autoInit: true, loadCallback: function() { $.holdReady(false) } }); $(function() { if ($(DX_LINK_SELECTOR, context).length) throw DX.Error("E0022"); }); DX.viewPortChanged.add(function(viewPort, prevViewPort) { detachCssClasses(prevViewPort); attachCssClasses(viewPort) }); DX.ui.themes = { init: init, current: current, attachCssClasses: attachCssClasses, detachCssClasses: detachCssClasses }; DX.ui.themes.__internals = { themeNameFromDevice: themeNameFromDevice, waitForThemeLoad: waitForThemeLoad, resetTheme: function() { $activeThemeLink.attr("href", "about:blank"); currentThemeName = null; pendingThemeName = null } } })(jQuery, DevExpress); /*! Module core, file ui.events.js */ (function($, DX, undefined) { var ui = DX.ui, eventNS = $.event, hooksNS = eventNS.fixHooks, specialNS = eventNS.special, EVENT_SOURCES_REGEX = { dx: /^dx/i, mouse: /(mouse|wheel)/i, touch: /^touch/i, keyboard: /^key/i, pointer: /^(ms)?pointer/i }; var eventSource = function(e) { var result = "other"; $.each(EVENT_SOURCES_REGEX, function(key) { if (this.test(e.type)) { result = key; return false } }); return result }; var isDxEvent = function(e) { return eventSource(e) === "dx" }; var isNativeMouseEvent = function(e) { return eventSource(e) === "mouse" }; var isNativeTouchEvent = function(e) { return eventSource(e) === "touch" }; var isPointerEvent = function(e) { return eventSource(e) === "pointer" }; var isMouseEvent = function(e) { return isNativeMouseEvent(e) || (isPointerEvent(e) || isDxEvent(e)) && e.pointerType === "mouse" }; var isTouchEvent = function(e) { return isNativeTouchEvent(e) || (isPointerEvent(e) || isDxEvent(e)) && e.pointerType === "touch" }; var isKeyboardEvent = function(e) { return eventSource(e) === "keyboard" }; var eventData = function(e) { return { x: e.pageX, y: e.pageY, time: e.timeStamp } }; var eventDelta = function(from, to) { return { x: to.x - from.x, y: to.y - from.y, time: to.time - from.time || 1 } }; var hasTouches = function(e) { if (isNativeTouchEvent(e)) return (e.originalEvent.touches || []).length; if (isDxEvent(e)) return (e.pointers || []).length; return 0 }; var needSkipEvent = function(e) { var $target = $(e.target), touchInInput = $target.is("input, textarea, select"); if (e.type === 'dxmousewheel') return $target.is("input[type='number'], textarea, select") && $target.is(':focus'); if (isMouseEvent(e)) return touchInInput || e.which > 1; if (isTouchEvent(e)) return touchInInput && $target.is(":focus") }; var createEvent = function(originalEvent, args) { var event = $.Event(originalEvent), fixHook = hooksNS[originalEvent.type] || eventNS.mouseHooks; var props = fixHook.props ? eventNS.props.concat(fixHook.props) : eventNS.props, propIndex = props.length; while (propIndex--) { var prop = props[propIndex]; event[prop] = originalEvent[prop] } if (args) $.extend(event, args); return fixHook.filter ? fixHook.filter(event, originalEvent) : event }; var fireEvent = function(props) { var event = createEvent(props.originalEvent, props); eventNS.trigger(event, null, props.delegateTarget || event.target); return event }; var addNamespace = function(eventNames, namespace) { if (!namespace) throw DX.Error("E0017"); if (typeof eventNames === "string") return addNamespace(eventNames.split(/\s+/g), namespace); $.each(eventNames, function(index, eventName) { eventNames[index] = eventName + "." + namespace }); return eventNames.join(" ") }; var dxEventHook = {props: eventNS.mouseHooks.props.concat(["pointerType", "pointerId", "pointers"])}; var registerEvent = function(eventName, eventObject) { var strategy = {}; if ("noBubble" in eventObject) strategy.noBubble = eventObject.noBubble; if ("bindType" in eventObject) strategy.bindType = eventObject.bindType; if ("delegateType" in eventObject) strategy.delegateType = eventObject.delegateType; $.each(["setup", "teardown", "add", "remove", "trigger", "handle", "_default", "dispose"], function(_, methodName) { if (!eventObject[methodName]) return; strategy[methodName] = function() { var args = $.makeArray(arguments); args.unshift(this); return eventObject[methodName].apply(eventObject, args) } }); hooksNS[eventName] = dxEventHook; specialNS[eventName] = strategy }; ui.events = { eventSource: eventSource, isPointerEvent: isPointerEvent, isMouseEvent: isMouseEvent, isTouchEvent: isTouchEvent, isKeyboardEvent: isKeyboardEvent, hasTouches: hasTouches, eventData: eventData, eventDelta: eventDelta, needSkipEvent: needSkipEvent, createEvent: createEvent, fireEvent: fireEvent, addNamespace: addNamespace, registerEvent: registerEvent } })(jQuery, DevExpress); /*! Module core, file ko.events.js */ (function($, DX, undefined) { if (!DX.support.hasKo) return; var ko = window.ko, events = DX.ui.events; var originalRegisterEvent = events.registerEvent; var registerKoEvent = function(eventName, eventObject) { originalRegisterEvent(eventName, eventObject); var koBindingEventName = events.addNamespace(eventName, eventName + "Binding"); ko.bindingHandlers[eventName] = {update: function(element, valueAccessor, allBindingsAccessor, viewModel) { var $element = $(element), unwrappedValue = ko.utils.unwrapObservable(valueAccessor()), eventSource = unwrappedValue.execute ? unwrappedValue.execute : unwrappedValue; $element.off(koBindingEventName).on(koBindingEventName, $.isPlainObject(unwrappedValue) ? unwrappedValue : {}, function(e) { eventSource.call(viewModel, viewModel, e) }) }} }; $.extend(events, {registerEvent: registerKoEvent}) })(jQuery, DevExpress); /*! Module core, file ng.events.js */ (function($, DX, undefined) { if (!DX.support.hasNg) return; var events = DX.ui.events; var originalRegisterEvent = events.registerEvent; var registerNgEvent = function(eventName, eventObject) { originalRegisterEvent(eventName, eventObject); var ngEventName = eventName.slice(0, 2) + eventName.charAt(2).toUpperCase() + eventName.slice(3); DX.ng.module.directive(ngEventName, ['$parse', function($parse) { return function(scope, element, attr) { var attrValue = $.trim(attr[ngEventName]), handler, eventOptions = {}; if (attrValue.charAt(0) === "{") { eventOptions = scope.$eval(attrValue); handler = $parse(eventOptions.execute) } else handler = $parse(attr[ngEventName]); element.on(eventName, eventOptions, function(e) { scope.$apply(function() { handler(scope, {$event: e}) }) }) } }]) }; $.extend(events, {registerEvent: registerNgEvent}) })(jQuery, DevExpress); /*! Module core, file ui.keyboardProcessor.js */ (function($, DX, undefined) { var ui = DX.ui, events = ui.events; ui.KeyboardProcessor = DX.Class.inherit({ _keydown: events.addNamespace("keydown", "KeyboardProcessor"), codes: { "8": "backspace", "9": "tab", "13": "enter", "27": "escape", "33": "pageUp", "34": "pageDown", "35": "end", "36": "home", "37": "leftArrow", "38": "upArrow", "39": "rightArrow", "40": "downArrow", "46": "del", "32": "space", "70": "F", "65": "A", "106": "asterisk", "109": "minus" }, ctor: function(options) { var _this = this; options = options || {}; if (options.element) this._element = $(options.element); if (options.focusTarget) this._focusTarget = options.focusTarget; this._handler = options.handler; this._context = options.context; this._childProcessors = []; if (this._element) this._element.on(this._keydown, function(e) { _this.process(e) }) }, dispose: function() { if (this._element) this._element.off(this._keydown); this._element = undefined; this._handler = undefined; this._context = undefined; this._childProcessors = undefined }, clearChildren: function() { this._childProcessors = [] }, push: function(child) { if (!this._childProcessors) this.clearChildren(); this._childProcessors.push(child); return child }, attachChildProcessor: function() { var childProcessor = new ui.KeyboardProcessor; this._childProcessors.push(childProcessor); return childProcessor }, reinitialize: function(childHandler, childContext) { this._context = childContext; this._handler = childHandler; return this }, process: function(e) { if (this._focusTarget && this._focusTarget !== e.target && $.inArray(e.target, this._focusTarget) < 0) return false; var args = { key: this.codes[e.which] || e.which, ctrl: e.ctrlKey, shift: e.shiftKey, alt: e.altKey, originalEvent: e }; var handlerResult = this._handler && this._handler.call(this._context, args); if (handlerResult && this._childProcessors) $.each(this._childProcessors, function(index, childProcessor) { childProcessor.process(e) }) } }) })(jQuery, DevExpress); /*! Module core, file ui.dialog.js */ (function($, DX, undefined) { var ui = DX.ui, utils = DX.utils; var DEFAULT_BUTTON = { text: "OK", onClick: function() { return true } }; var DX_DIALOG_CLASSNAME = "dx-dialog", DX_DIALOG_WRAPPER_CLASSNAME = DX_DIALOG_CLASSNAME + "-wrapper", DX_DIALOG_ROOT_CLASSNAME = DX_DIALOG_CLASSNAME + "-root", DX_DIALOG_CONTENT_CLASSNAME = DX_DIALOG_CLASSNAME + "-content", DX_DIALOG_MESSAGE_CLASSNAME = DX_DIALOG_CLASSNAME + "-message", DX_DIALOG_BUTTONS_CLASSNAME = DX_DIALOG_CLASSNAME + "-buttons", DX_DIALOG_BUTTON_CLASSNAME = DX_DIALOG_CLASSNAME + "-button"; var FakeDialogComponent = DX.Component.inherit({ NAME: "dxDialog", ctor: function(element, options) { this.callBase(options) }, _defaultOptionsRules: function() { return this.callBase().concat([{ device: {platform: "ios"}, options: {width: 276} }, { device: {platform: "android"}, options: { lWidth: "60%", pWidth: "80%" } }, { device: { platform: "win8", phone: false }, options: {width: function() { return $(window).width() }} }, { device: { platform: "win8", phone: true }, options: {position: { my: "top center", at: "top center", of: window, offset: "0 0" }} }]) } }); var dialog = function(options) { if (!ui.dxPopup) throw DX.Error("E0018"); var deferred = $.Deferred(); var defaultOptions = (new FakeDialogComponent).option(); options = $.extend(defaultOptions, options); var $element = $("
").addClass(DX_DIALOG_CLASSNAME).appendTo(DX.viewPort()); var $message = $("
").addClass(DX_DIALOG_MESSAGE_CLASSNAME).html(String(options.message)); var popupButtons = []; $.each(options.buttons || [DEFAULT_BUTTON], function() { if (this.clickAction) { DX.log("W0001", "Dialog", "clickAction", "14.2", "Use 'onClick' option instead"); this.onClick = this.clickAction } var action = new DX.Action(this.onClick || this.clickAction, {context: popupInstance}); popupButtons.push({ toolbar: 'bottom', location: 'center', widget: 'button', options: { text: this.text, onClick: function() { var result = action.execute(arguments); hide(result) } } }) }); var popupInstance = $element.dxPopup({ title: options.title || this.title, showTitle: function() { var isTitle = options.showTitle === undefined ? true : options.showTitle; return isTitle }(), height: "auto", width: function() { var isPortrait = $(window).height() > $(window).width(), key = (isPortrait ? "p" : "l") + "Width", widthOption = options.hasOwnProperty(key) ? options[key] : options["width"]; return $.isFunction(widthOption) ? widthOption() : widthOption }, showCloseButton: false, focusStateEnabled: false, onContentReady: function(args) { args.component.content().addClass(DX_DIALOG_CONTENT_CLASSNAME).append($message) }, onShowing: function(e) { e.component.bottomToolbar().addClass(DX_DIALOG_BUTTONS_CLASSNAME).find(".dx-button").addClass(DX_DIALOG_BUTTON_CLASSNAME).first().focus() }, buttons: popupButtons, animation: { show: { type: "pop", duration: 400 }, hide: { type: "pop", duration: 400, to: { opacity: 0, scale: 0 }, from: { opacity: 1, scale: 1 } } }, rtlEnabled: DX.rtlEnabled, boundaryOffset: { h: 10, v: 0 } }).dxPopup("instance"); popupInstance._wrapper().addClass(DX_DIALOG_WRAPPER_CLASSNAME); if (options.position) popupInstance.option("position", options.position); popupInstance._wrapper().addClass(DX_DIALOG_ROOT_CLASSNAME); function show() { popupInstance.show(); utils.resetActiveElement(); return deferred.promise() } function hide(value) { popupInstance.hide().done(function() { popupInstance.element().remove() }); deferred.resolve(value) } return { show: show, hide: hide } }; var alert = function(message, title, showTitle) { var dialogInstance, options = $.isPlainObject(message) ? message : { title: title, message: message, showTitle: showTitle }; dialogInstance = ui.dialog.custom(options); return dialogInstance.show() }; var confirm = function(message, title, showTitle) { var dialogInstance, options = $.isPlainObject(message) ? message : { title: title, message: message, showTitle: showTitle, buttons: [{ text: Globalize.localize("Yes"), onClick: function() { return true } }, { text: Globalize.localize("No"), onClick: function() { return false } }] }; dialogInstance = ui.dialog.custom(options); return dialogInstance.show() }; var $notify = null; var notify = function(message, type, displayTime) { var options = $.isPlainObject(message) ? message : {message: message}; if (!ui.dxToast) { alert(options.message); return } if (options.hiddenAction) { DX.log("W0001", "Dialog", "hiddenAction", "14.2", "Use 'onHidden' option instead"); options.onHidden = options.hiddenAction } var userHiddenAction = options.onHidden; $.extend(options, { type: type, displayTime: displayTime, onHidden: function(args) { args.element.remove(); new DX.Action(userHiddenAction, {context: args.model}).execute(arguments) } }); $notify = $("
").appendTo(DX.viewPort()).dxToast(options); $notify.dxToast("instance").show() }; $.extend(ui, { notify: notify, dialog: { custom: dialog, alert: alert, confirm: confirm } }); ui.dialog.FakeDialogComponent = FakeDialogComponent })(jQuery, DevExpress); /*! Module core, file ui.dataHelper.js */ (function($, DX, undefined) { var data = DX.data; var DATA_SOURCE_OPTIONS_METHOD = "_dataSourceOptions", DATA_SOURCE_CHANGED_METHOD = "_dataSourceChangedHandler", DATA_SOURCE_LOAD_ERROR_METHOD = "_dataSourceLoadErrorHandler", DATA_SOURCE_LOADING_CHANGED_METHOD = "_dataSourceLoadingChangedHandler"; DX.ui.DataHelperMixin = { postCtor: function() { this.on("disposing", function() { this._disposeDataSource() }) }, _isDataSourceReady: function() { return !this._dataSource || this._dataSource.isLoaded() }, _refreshDataSource: function() { this._initDataSource(); this._loadDataSource() }, _initDataSource: function() { var dataSourceOptions = this.option("dataSource"), widgetDataSourceOptions, dataSourceType; this._disposeDataSource(); if (dataSourceOptions) { if (dataSourceOptions instanceof data.DataSource) { this._isSharedDataSource = true; this._dataSource = dataSourceOptions } else { widgetDataSourceOptions = DATA_SOURCE_OPTIONS_METHOD in this ? this[DATA_SOURCE_OPTIONS_METHOD]() : {}; dataSourceType = this._dataSourceType ? this._dataSourceType() : data.DataSource; this._dataSource = new dataSourceType($.extend(true, {}, widgetDataSourceOptions, data.utils.normalizeDataSourceOptions(dataSourceOptions))) } this._addDataSourceHandlers() } }, _addDataSourceHandlers: function() { if (DATA_SOURCE_CHANGED_METHOD in this) this._addDataSourceChangeHandler(); if (DATA_SOURCE_LOAD_ERROR_METHOD in this) this._addDataSourceLoadErrorHandler(); if (DATA_SOURCE_LOADING_CHANGED_METHOD in this) this._addDataSourceLoadingChangedHandler(); this._addReadyWatcher() }, _addReadyWatcher: function() { this._dataSource.on("loadingChanged", $.proxy(function(isLoading) { this._ready && this._ready(!isLoading) }, this)) }, _addDataSourceChangeHandler: function() { var dataSource = this._dataSource; this._proxiedDataSourceChangedHandler = $.proxy(function() { this[DATA_SOURCE_CHANGED_METHOD](dataSource.items()) }, this); dataSource.on("changed", this._proxiedDataSourceChangedHandler) }, _addDataSourceLoadErrorHandler: function() { this._proxiedDataSourceLoadErrorHandler = $.proxy(this[DATA_SOURCE_LOAD_ERROR_METHOD], this); this._dataSource.on("loadError", this._proxiedDataSourceLoadErrorHandler) }, _addDataSourceLoadingChangedHandler: function() { this._proxiedDataSourceLoadingChangedHandler = $.proxy(this[DATA_SOURCE_LOADING_CHANGED_METHOD], this); this._dataSource.on("loadingChanged", this._proxiedDataSourceLoadingChangedHandler) }, _loadDataSource: function() { if (this._dataSource) { var dataSource = this._dataSource; if (dataSource.isLoaded()) this._proxiedDataSourceChangedHandler && this._proxiedDataSourceChangedHandler(); else dataSource.load() } }, _loadSingle: function(key, value) { key = key === "this" ? this._dataSource.key() || "this" : key; return this._dataSource.loadSingle(key, value) }, _isLastPage: function() { return !this._dataSource || this._dataSource.isLastPage() || !this._dataSource._pageSize }, _isDataSourceLoading: function() { return this._dataSource && this._dataSource.isLoading() }, _disposeDataSource: function() { if (this._dataSource) { if (this._isSharedDataSource) { delete this._isSharedDataSource; this._proxiedDataSourceChangedHandler && this._dataSource.off("changed", this._proxiedDataSourceChangedHandler); this._proxiedDataSourceLoadErrorHandler && this._dataSource.off("loadError", this._proxiedDataSourceLoadErrorHandler); this._proxiedDataSourceLoadingChangedHandler && this._dataSource.off("loadingChanged", this._proxiedDataSourceLoadingChangedHandler) } else this._dataSource.dispose(); delete this._dataSource; delete this._proxiedDataSourceChangedHandler; delete this._proxiedDataSourceLoadErrorHandler; delete this._proxiedDataSourceLoadingChangedHandler } } } })(jQuery, DevExpress); /*! Module core, file ui.dataExpression.js */ (function($, DX, undefined) { var ui = DX.ui, utils = DX.utils, dataUtils = DX.data.utils; ui.DataExpressionMixin = $.extend(ui.DataHelperMixin, { _dataExpressionDeprecatedOptions: function() { return {itemRender: { since: "14.2", alias: "itemTemplate" }} }, _dataExpressionDefaultOptions: function() { return { items: [], dataSource: null, itemTemplate: "item", value: null, valueExpr: "this", displayExpr: undefined } }, _initDataExpressions: function() { this._compileValueGetter(); this._compileDisplayGetter(); this._initDynamicTemplates(); this._initDataSource(); this._itemsToDataSource() }, _itemsToDataSource: function() { if (!this.option("dataSource")) this._dataSource = new DevExpress.data.DataSource({ store: new DevExpress.data.ArrayStore(this.option("items")), pageSize: 0 }) }, _compileDisplayGetter: function() { this._displayGetter = dataUtils.compileGetter(this._displayGetterExpr()) }, _displayGetterExpr: function() { return this.option("displayExpr") }, _compileValueGetter: function() { this._valueGetter = dataUtils.compileGetter(this._valueGetterExpr()) }, _valueGetterExpr: function() { return this.option("valueExpr") || "this" }, _loadValue: function(value) { var deferred = $.Deferred(); value = this._unwrappedValue(value); if (!utils.isDefined(value)) return deferred.reject().promise(); this._loadSingle(this._valueGetterExpr(), value).done($.proxy(function(item) { this._isValueEquals(this._valueGetter(item), value) ? deferred.resolve(item) : deferred.reject() }, this)).fail(function() { deferred.reject() }); return deferred.promise() }, _unwrappedValue: function(value) { value = DX.utils.isDefined(value) ? value : this.option("value"); if (value && this._dataSource && this._valueGetterExpr() === "this") { var key = this._dataSource.key(); if (key && typeof value === "object") value = value[key] } return utils.unwrapObservable(value) }, _isValueEquals: function(value1, value2) { var isDefined = utils.isDefined; var ensureDefined = utils.ensureDefined; var unwrapObservable = utils.unwrapObservable; var dataSourceKey = this._dataSource && this._dataSource.key(); var result = this._compareValues(value1, value2); if (!result && isDefined(value1) && isDefined(value2) && dataSourceKey) { var valueKey1 = ensureDefined(unwrapObservable(value1[dataSourceKey]), value1); var valueKey2 = ensureDefined(unwrapObservable(value2[dataSourceKey]), value2); result = this._compareValues(valueKey1, valueKey2) } return result }, _compareValues: function(value1, value2) { return dataUtils.toComparable(value1) === dataUtils.toComparable(value2) }, _initDynamicTemplates: function() { if (this._displayGetterExpr()) this._dynamicTemplates["item"] = new ui.DefaultTemplate($.proxy(function(data) { return this._displayGetter(data) }, this)); else delete this._dynamicTemplates["item"] }, _setCollectionWidgetItemTemplate: function() { this._initDynamicTemplates(); this._setCollectionWidgetOption("itemTemplate", this._getTemplateByOption("itemTemplate")) }, _dataExpressionOptionChanged: function(args) { switch (args.name) { case"items": this._itemsToDataSource(); this._setCollectionWidgetOption("items"); break; case"dataSource": this._initDataSource(); break; case"itemTemplate": this._setCollectionWidgetItemTemplate(); break; case"valueExpr": this._compileValueGetter(); break; case"displayExpr": this._compileDisplayGetter(); this._setCollectionWidgetItemTemplate(); break } } }) })(jQuery, DevExpress); /*! Module core, file ui.events.pointer.touchHooks.js */ (function($, DX, undefined) { var touchEventHook = { filter: function(event, originalEvent) { var touches = originalEvent.touches.length ? originalEvent.touches : originalEvent.changedTouches; $.each(["pageX", "pageY", "screenX", "screenY", "clientX", "clientY"], function() { event[this] = touches[0][this] }); return event }, props: $.event.mouseHooks.props.concat(["touches", "changedTouches", "targetTouches", "detail", "result", "originalTarget", "charCode", "prevValue"]) }; $.each(["touchstart", "touchmove", "touchend", "touchcancel"], function() { $.event.fixHooks[this] = touchEventHook }) })(jQuery, DevExpress); /*! Module core, file ui.events.pointer.mspointerHooks.js */ (function($, DX, undefined) { var POINTER_TYPE_MAP = { 2: "touch", 3: "pen", 4: "mouse" }; var pointerEventHook = { filter: function(event, originalEvent) { var pointerType = originalEvent.pointerType; if ($.isNumeric(pointerType)) event.pointerType = POINTER_TYPE_MAP[pointerType]; return event }, props: $.event.mouseHooks.props.concat(["pointerId", "pointerType", "originalTarget", "width", "height", "pressure", "result", "tiltX", "charCode", "tiltY", "detail", "isPrimary", "prevValue"]) }; $.each(["MSPointerDown", "MSPointerMove", "MSPointerUp", "MSPointerCancel", "MSPointerOver", "MSPointerOut", "mouseenter", "mouseleave", "pointerdown", "pointermove", "pointerup", "pointercancel", "pointerover", "pointerout", "pointerenter", "pointerleave"], function() { $.event.fixHooks[this] = pointerEventHook }) })(jQuery, DevExpress); /*! Module core, file ui.events.pointer.base.js */ (function($, DX, undefined) { var ui = DX.ui, events = ui.events; var POINTER_EVENTS_NAMESPACE = "dxPointerEvents"; var BaseStrategy = DX.Class.inherit({ ctor: function(eventName, originalEvents) { this._eventName = eventName; this._eventNamespace = [POINTER_EVENTS_NAMESPACE, ".", this._eventName].join(""); this._originalEvents = originalEvents; this._handlerCount = 0; this.noBubble = this._isNoBubble() }, _isNoBubble: function() { var eventName = this._eventName; return eventName === "dxpointerenter" || eventName === "dxpointerleave" }, _handler: function(e) { var delegateTarget = this._getDelegateTarget(e); return this._fireEvent({ type: this._eventName, pointerType: e.pointerType || events.eventSource(e), originalEvent: e, delegateTarget: delegateTarget }) }, _getDelegateTarget: function(e) { var delegateTarget; if (this.noBubble) delegateTarget = e.delegateTarget; return delegateTarget }, _fireEvent: function(args) { return events.fireEvent(args) }, setup: function() { return true }, add: function(element, handleObj) { if (this._handlerCount <= 0 || this.noBubble) { this._selector = handleObj.selector; element = this.noBubble ? element : document; $(element).on(events.addNamespace(this._originalEvents, this._eventNamespace), this._selector, $.proxy(this._handler, this)) } if (!this.noBubble) this._handlerCount++ }, remove: function(element) { if (!this.noBubble) this._handlerCount-- }, teardown: function(element) { if (this._handlerCount && !this.noBubble) return; element = this.noBubble ? element : document; $(element).off("." + this._eventNamespace, this._selector) }, dispose: function(element) { element = this.noBubble ? element : document; $(element).off("." + this._eventNamespace) } }); events.pointer = {}; events.pointer.BaseStrategy = BaseStrategy })(jQuery, DevExpress); /*! Module core, file ui.events.pointer.mouse.js */ (function($, DX, undefined) { var ui = DX.ui, events = ui.events, pointer = events.pointer; var MouseStrategyEventMap = { dxpointerdown: "mousedown", dxpointermove: "mousemove", dxpointerup: "mouseup", dxpointercancel: "", dxpointerover: "mouseover", dxpointerout: "mouseout", dxpointerenter: "mouseenter", dxpointerleave: "mouseleave" }; var normalizeMouseEvent = function(e) { var pointers = []; e.pointerId = 1; if (e.type !== "mouseup") pointers.push(e); return { pointers: pointers, pointerId: 1 } }; var MouseStrategy = pointer.BaseStrategy.inherit({_fireEvent: function(args) { return this.callBase($.extend(normalizeMouseEvent(args.originalEvent), args)) }}); pointer.mouse = { strategy: MouseStrategy, map: MouseStrategyEventMap, normalize: normalizeMouseEvent } })(jQuery, DevExpress); /*! Module core, file ui.events.pointer.touch.js */ (function($, DX, undefined) { var ui = DX.ui, device = $.proxy(DX.devices.real, DX.devices), events = ui.events, pointer = events.pointer; var TouchStrategyEventMap = { dxpointerdown: "touchstart", dxpointermove: "touchmove", dxpointerup: "touchend", dxpointercancel: "touchcancel" }; var normalizeTouchEvent = function(e) { var pointers = []; $.each(e.touches, function(_, touch) { pointers.push($.extend({pointerId: touch.identifier}, touch)) }); return { pointers: pointers, pointerId: e.changedTouches[0].identifier } }; var skipTouchWithSameIdentifier = function(pointerEvent) { return device().platform === "ios" && (pointerEvent === "dxpointerdown" || pointerEvent === "dxpointerup") }; var TouchStrategy = pointer.BaseStrategy.inherit({ ctor: function() { this.callBase.apply(this, arguments); this._pointerId = 0 }, _handler: function(e) { if (skipTouchWithSameIdentifier(this._eventName)) { var touch = e.changedTouches[0]; if (this._pointerId === touch.identifier && this._pointerId !== 0) return; this._pointerId = touch.identifier } return this.callBase.apply(this, arguments) }, _fireEvent: function(args) { return this.callBase($.extend(normalizeTouchEvent(args.originalEvent), args)) } }); pointer.touch = { strategy: TouchStrategy, map: TouchStrategyEventMap, normalize: normalizeTouchEvent } })(jQuery, DevExpress); /*! Module core, file ui.events.pointer.mouseAndTouch.js */ (function($, DX, undefined) { var ui = DX.ui, events = ui.events, pointer = events.pointer; var MouseAndTouchStrategyEventMap = { dxpointerdown: "touchstart mousedown", dxpointermove: "touchmove mousemove", dxpointerup: "touchend mouseup", dxpointercancel: "touchcancel", dxpointerover: "mouseover", dxpointerout: "mouseout", dxpointerenter: "mouseenter", dxpointerleave: "mouseleave" }; var MouseAndTouchStrategy = pointer.BaseStrategy.inherit({ EVENT_LOCK_TIMEOUT: 100, _handler: function(e) { var isMouseEvent = events.isMouseEvent(e); if (!isMouseEvent) this._skipNextEvents = true; if (isMouseEvent && this._mouseLocked) return; if (isMouseEvent && this._skipNextEvents) { this._skipNextEvents = false; this._mouseLocked = true; clearTimeout(this._unlockMouseTimer); this._unlockMouseTimer = setTimeout($.proxy(function() { this._mouseLocked = false }, this), this.EVENT_LOCK_TIMEOUT); return } return this.callBase(e) }, _fireEvent: function(args) { var isMouseEvent = events.isMouseEvent(args.originalEvent), normalizer = isMouseEvent ? pointer.mouse.normalize : pointer.touch.normalize; return this.callBase($.extend(normalizer(args.originalEvent), args)) }, dispose: function() { this.callBase(); this._skipNextEvents = false; this._mouseLocked = false; clearTimeout(this._unlockMouseTimer) } }); pointer.mouseAndTouch = { strategy: MouseAndTouchStrategy, map: MouseAndTouchStrategyEventMap } })(jQuery, DevExpress); /*! Module core, file ui.events.pointer.mspointer.js */ (function($, DX, undefined) { var ui = DX.ui, events = ui.events, pointer = events.pointer; var MsPointerStrategyEventMap = { dxpointerdown: "MSPointerDown pointerdown", dxpointermove: "MSPointerMove pointermove", dxpointerup: "MSPointerUp pointerup", dxpointercancel: "MSPointerCancel pointercancel", dxpointerover: "MSPointerOver pointerover", dxpointerout: "MSPointerOut pointerout", dxpointerenter: "mouseenter", dxpointerleave: "mouseleave" }; var pointers = []; var getPointerIndex = function(e) { var index = -1; $.each(pointers, function(i, pointer) { if (e.pointerId === pointer.pointerId) { index = i; return true } }); return index }; var addPointer = function(e) { if (getPointerIndex(e) === -1) pointers.push(e) }; var removePointer = function(e) { pointers.splice(getPointerIndex(e), 1) }; var updatePointer = function(e) { pointers[getPointerIndex(e)] = e }; var addEventsListner = function(events, handler) { events = events.split(" "); $.each(events, function(_, event) { document.addEventListener(event, handler, true) }) }; var activateMspointerStrategy = function() { var eventMap = MsPointerStrategyEventMap; addEventsListner(eventMap.dxpointerdown, addPointer); addEventsListner(eventMap.dxpointermove, updatePointer); addEventsListner(eventMap.dxpointerup, removePointer); addEventsListner(eventMap.dxpointercancel, removePointer); activateMspointerStrategy = $.noop }; var MsPointerStrategy = pointer.BaseStrategy.inherit({ ctor: function() { this.callBase.apply(this, arguments); activateMspointerStrategy() }, _fireEvent: function(args) { return this.callBase($.extend({ pointers: pointers, pointerId: args.originalEvent.pointerId }, args)) } }); pointer.msPointer = { strategy: MsPointerStrategy, map: MsPointerStrategyEventMap }; DX.ui.events.__internals = DX.ui.events.__internals || {}; $.extend(DX.ui.events.__internals, {cleanMsPointers: function() { pointers = [] }}) })(jQuery, DevExpress); /*! Module core, file ui.events.pointer.js */ (function($, DX, undefined) { var ui = DX.ui, support = DX.support, device = $.proxy(DX.devices.real, DX.devices), events = ui.events, pointer = events.pointer; var eventType = function() { if (support.pointer) return pointer.msPointer; if (support.touch && !(device().tablet || device().phone)) return pointer.mouseAndTouch; if (support.touch) return pointer.touch; return pointer.mouse }(); $.each(eventType.map, function(pointerEvent, originalEvents) { events.registerEvent(pointerEvent, new eventType.strategy(pointerEvent, originalEvents)) }) })(jQuery, DevExpress); /*! Module core, file ui.events.wheel.js */ (function($, DX, undefined) { var ui = DX.ui, events = ui.events; var EVENT_NAME = "dxmousewheel", EVENT_NAMESPACE = "dxWheel"; $.event.fixHooks["wheel"] = $.event.mouseHooks; var wheelEvent = document.onmousewheel !== undefined ? "mousewheel" : "wheel"; var wheel = { setup: function(element, data) { var $element = $(element); $element.on(events.addNamespace(wheelEvent, EVENT_NAMESPACE), $.proxy(wheel._wheelHandler, wheel)) }, teardown: function(element) { var $element = $(element); $element.off("." + EVENT_NAMESPACE) }, _wheelHandler: function(e) { var delta = this._getWheelDelta(e.originalEvent); events.fireEvent({ type: EVENT_NAME, originalEvent: e, delta: delta, pointerType: "mouse" }); e.stopPropagation() }, _getWheelDelta: function(event) { return event.wheelDelta ? event.wheelDelta : -event.deltaY * 30 } }; events.registerEvent(EVENT_NAME, wheel) })(jQuery, DevExpress); /*! Module core, file ui.events.hover.js */ (function($, DX, undefined) { var ui = DX.ui, events = ui.events; var HOVERSTART_NAMESPACE = "dxHoverStart", HOVERSTART = "dxhoverstart", POINTERENTER_NAMESPACED_EVENT_NAME = events.addNamespace("dxpointerenter", HOVERSTART_NAMESPACE), POINTERDOWN_NAMESPACED_EVENT_NAME = events.addNamespace("dxpointerdown", HOVERSTART_NAMESPACE), POINTERUP_NAMESPACED_EVENT_NAME = events.addNamespace("dxpointerup", HOVERSTART_NAMESPACE), HOVEREND_NAMESPACE = "dxHoverEnd", HOVEREND = "dxhoverend", POINTERLEAVE_NAMESPACED_EVENT_NAME = events.addNamespace("dxpointerleave", HOVEREND_NAMESPACE); var Hover = DX.Class.inherit({ noBubble: true, add: function(element, handleObj) { var $element = $(element); $element.off("." + this._namespace).on(this._originalEventName, handleObj.selector, $.proxy(this._handler, this)) }, _handler: function(e) { if (events.isTouchEvent(e)) return; events.fireEvent({ type: this._eventName, originalEvent: e, delegateTarget: e.delegateTarget }) }, teardown: function(element) { $(element).off("." + this._namespace) } }); var HoverStart = Hover.inherit({ ctor: function() { this._eventName = HOVERSTART; this._originalEventName = POINTERENTER_NAMESPACED_EVENT_NAME; this._namespace = HOVERSTART_NAMESPACE; this._isMouseDown = false; this._eventsAttached = 0 }, _handler: function(e) { if (!this._isMouseDown) this.callBase.apply(this, arguments) }, setup: function() { $(document).off("." + HOVERSTART_NAMESPACE).on(POINTERDOWN_NAMESPACED_EVENT_NAME, $.proxy(function() { this._isMouseDown = true }, this)).on(POINTERUP_NAMESPACED_EVENT_NAME, $.proxy(function() { this._isMouseDown = false }, this)); this._eventsAttached++ }, teardown: function() { this._eventsAttached--; if (this._eventsAttached === 0) $(document).off("." + HOVERSTART_NAMESPACE) } }); var HoverEnd = Hover.inherit({ctor: function() { this._eventName = HOVEREND; this._originalEventName = POINTERLEAVE_NAMESPACED_EVENT_NAME; this._namespace = HOVEREND_NAMESPACE }}); events.registerEvent(HOVERSTART, new HoverStart); events.registerEvent(HOVEREND, new HoverEnd) })(jQuery, DevExpress); /*! Module core, file ui.events.manager.js */ (function($, DX, undefined) { var ui = DX.ui, events = ui.events; var MANAGER_EVENT = "dxEventManager", EMITTER_DATA = "dxEmitter"; var EventManager = DX.Class.inherit({ ctor: function() { this._attachHandlers(); this.reset(); this._proxiedCancelHandler = $.proxy(this._cancelHandler, this); this._proxiedAcceptHandler = $.proxy(this._acceptHandler, this) }, _attachHandlers: function() { $(document).on(events.addNamespace("dxpointerdown", MANAGER_EVENT), $.proxy(this._pointerDownHandler, this)).on(events.addNamespace("dxpointermove", MANAGER_EVENT), $.proxy(this._pointerMoveHandler, this)).on(events.addNamespace("dxpointerup dxpointercancel", MANAGER_EVENT), $.proxy(this._pointerUpHandler, this)).on(events.addNamespace("dxmousewheel", MANAGER_EVENT), $.proxy(this._mouseWheelHandler, this)) }, _eachEmitter: function(callback) { var activeEmitters = this._activeEmitters || []; var i = 0; while (activeEmitters.length > i) { var emitter = activeEmitters[i]; if (callback(emitter) === false) break; if (activeEmitters[i] === emitter) i++ } }, _applyToEmitters: function(method, arg) { this._eachEmitter(function(emitter) { emitter[method].call(emitter, arg) }) }, reset: function() { this._eachEmitter(this._proxiedCancelHandler); this._activeEmitters = [] }, resetEmitter: function(emitter) { this._proxiedCancelHandler(emitter) }, _pointerDownHandler: function(e) { if (events.isMouseEvent(e) && e.which > 1) return; this._updateEmitters(e) }, _updateEmitters: function(e) { if (!this._isSetChanged(e)) return; this._cleanEmitters(e); this._fetchEmitters(e) }, _isSetChanged: function(e) { var currentSet = this._closestEmitter(e); var previousSet = this._emittersSet || []; var setChanged = currentSet.length !== previousSet.length; $.each(currentSet, function(index, emitter) { setChanged = setChanged || previousSet[index] !== emitter; return !setChanged }); this._emittersSet = currentSet; return setChanged }, _closestEmitter: function(e) { var that = this, result = [], $element = $(e.target); function handleEmitter(_, emitter) { if (!!emitter && emitter.validatePointers(e) && emitter.validate(e)) { emitter.addCancelCallback(that._proxiedCancelHandler); emitter.addAcceptCallback(that._proxiedAcceptHandler); result.push(emitter) } } while ($element.length) { var emitters = $.data($element.get(0), EMITTER_DATA) || []; $.each(emitters, handleEmitter); $element = $element.parent() } return result }, _acceptHandler: function(acceptedEmitter, e) { var that = this; this._eachEmitter(function(emitter) { if (emitter !== acceptedEmitter) that._cancelEmitter(emitter, e) }) }, _cancelHandler: function(canceledEmitter, e) { this._cancelEmitter(canceledEmitter, e) }, _cancelEmitter: function(emitter, e) { var activeEmitters = this._activeEmitters; if (e) emitter.cancel(e); else emitter.reset(); emitter.removeCancelCallback(); emitter.removeAcceptCallback(); var emitterIndex = $.inArray(emitter, activeEmitters); if (emitterIndex > -1) activeEmitters.splice(emitterIndex, 1) }, _cleanEmitters: function(e) { this._applyToEmitters("end", e); this.reset(e) }, _fetchEmitters: function(e) { this._activeEmitters = this._emittersSet.slice(); this._applyToEmitters("start", e) }, _pointerMoveHandler: function(e) { this._applyToEmitters("move", e) }, _pointerUpHandler: function(e) { this._updateEmitters(e) }, _mouseWheelHandler: function(e) { var allowInterruption = true; this._eachEmitter(function(emitter) { allowInterruption = emitter.allowInterruptionByMousewheel() && allowInterruption; return allowInterruption }); if (!allowInterruption) return; e.pointers = [null]; this._pointerDownHandler(e); this._eachEmitter(function(emitter) { var direction = emitter.getDirection ? emitter.getDirection(e) : "", prop = direction !== "horizontal" ? "pageY" : "pageX"; if (direction) e[prop] += e.delta; return !direction }); this._pointerMoveHandler(e); e.pointers = []; this._pointerUpHandler(e) }, isActive: function(element) { var result = false; this._eachEmitter(function(emitter) { result = result || emitter.getElement().is(element) }); return result } }); var eventManager = new EventManager; var EMITTER_SUBSCRIPTION_DATA = "dxEmitterSubscription"; var registerEmitter = function(emitterConfig) { var emitterClass = emitterConfig.emitter, emitterName = emitterConfig.events[0], emitterEvents = emitterConfig.events; $.each(emitterEvents, function(_, eventName) { events.registerEvent(eventName, { noBubble: !emitterConfig.bubble, setup: function(element, data) { var subscriptions = $.data(element, EMITTER_SUBSCRIPTION_DATA) || {}, emitters = $.data(element, EMITTER_DATA) || {}, emitter = emitters[emitterName] || new emitterClass(element); subscriptions[eventName] = true; emitters[emitterName] = emitter; $.data(element, EMITTER_DATA, emitters); $.data(element, EMITTER_SUBSCRIPTION_DATA, subscriptions) }, add: function(element, handleObj) { var emitters = $.data(element, EMITTER_DATA), emitter = emitters[emitterName]; emitter.configurate($.extend({delegateSelector: handleObj.selector}, handleObj.data), handleObj.type) }, teardown: function(element) { var subscriptions = $.data(element, EMITTER_SUBSCRIPTION_DATA), emitters = $.data(element, EMITTER_DATA), emitter = emitters[emitterName]; delete subscriptions[eventName]; var disposeEmitter = true; $.each(emitterEvents, function(_, eventName) { disposeEmitter = disposeEmitter && !subscriptions[eventName]; return disposeEmitter }); if (disposeEmitter) { if (eventManager.isActive(element)) eventManager.resetEmitter(emitter); emitter && emitter.dispose(); delete emitters[emitterName] } } }) }) }; $.extend(events, {registerEmitter: registerEmitter}) })(jQuery, DevExpress); /*! Module core, file ui.events.emitter.js */ (function($, DX, undefined) { var ui = DX.ui, events = ui.events; var Emitter = DX.Class.inherit({ ctor: function(element) { this._$element = $(element); this._cancelCallback = $.Callbacks(); this._acceptCallback = $.Callbacks() }, getElement: function() { return this._$element }, validate: function(e) { return e.type !== "dxmousewheel" }, validatePointers: function(e) { return events.hasTouches(e) === 1 }, allowInterruptionByMousewheel: function() { return true }, configurate: function(data) { $.extend(this, data) }, addCancelCallback: function(callback) { this._cancelCallback.add(callback) }, removeCancelCallback: function() { this._cancelCallback.empty() }, _cancel: function(e) { this._cancelCallback.fire(this, e) }, addAcceptCallback: function(callback) { this._acceptCallback.add(callback) }, removeAcceptCallback: function() { this._acceptCallback.empty() }, _accept: function(e) { this._acceptCallback.fire(this, e) }, _requestAccept: function(e) { this._acceptRequestEvent = e }, _forgetAccept: function() { this._accept(this._acceptRequestEvent); this._acceptRequestEvent = null }, start: $.noop, move: $.noop, end: $.noop, cancel: $.noop, reset: function() { if (this._acceptRequestEvent) this._accept(this._acceptRequestEvent) }, _fireEvent: function(eventName, e, params) { var eventData = $.extend({ type: eventName, originalEvent: e, target: this._getEmitterTarget(e), delegateTarget: this.getElement().get(0) }, params); e = events.fireEvent(eventData); if (e.cancel) this._cancel(e); return e }, _getEmitterTarget: function(e) { return (this.delegateSelector ? $(e.target).closest(this.delegateSelector) : this.getElement()).get(0) }, dispose: $.noop }); $.extend(events, {Emitter: Emitter}) })(jQuery, DevExpress); /*! Module core, file ui.events.emitter.feedback.js */ (function($, DX, undefined) { var ui = DX.ui, events = ui.events, ACTIVE_EVENT_NAME = "dxactive", INACTIVE_EVENT_NAME = "dxinactive", ACTIVE_TIMEOUT = 30, INACTIVE_TIMEOUT = 400; var activeEmitter; var FeedbackEmitter = events.Emitter.inherit({ configurate: function(data, eventName) { switch (eventName) { case ACTIVE_EVENT_NAME: data.activeTimeout = data.timeout; break; case INACTIVE_EVENT_NAME: data.inactiveTimeout = data.timeout; break } this.callBase(data) }, start: function(e) { var element = this.getElement().get(0); var activeElement = activeEmitter && activeEmitter.getElement().get(0); var activeChildExists = $.contains(element, activeElement); var childJustActivated = activeEmitter && activeEmitter._activeTimer !== null; if (activeChildExists && childJustActivated) this._cancel(); else { if (activeEmitter) activeEmitter._forceInactiveTimer(); activeEmitter = this; var eventTarget = this._getEmitterTarget(e); this._forceActiveTimer = $.proxy(this._fireActive, this, e, eventTarget); this._forceInactiveTimer = $.proxy(this._fireInctive, this, e, eventTarget); this._startActiveTimer(e) } }, cancel: function(e) { this.end(e) }, end: function(e) { var skipTimers = e.type !== "dxpointerup"; if (skipTimers) this._stopActiveTimer(); else this._forceActiveTimer(); this._startInactiveTimer(e); if (skipTimers) this._forceInactiveTimer() }, dispose: function() { this._stopActiveTimer(); this._stopInactiveTimer(); this.callBase() }, _startActiveTimer: function(e) { var activeTimeout = "activeTimeout" in this ? this.activeTimeout : ACTIVE_TIMEOUT; this._activeTimer = window.setTimeout(this._forceActiveTimer, activeTimeout) }, _fireActive: function(e, eventTarget) { this._stopActiveTimer(); this._fireEvent(ACTIVE_EVENT_NAME, e, {target: eventTarget}) }, _stopActiveTimer: function() { clearTimeout(this._activeTimer); this._activeTimer = null }, _forceActiveTimer: $.noop, _startInactiveTimer: function(e) { var inactiveTimeout = "inactiveTimeout" in this ? this.inactiveTimeout : INACTIVE_TIMEOUT; this._inactiveTimer = window.setTimeout(this._forceInactiveTimer, inactiveTimeout) }, _fireInctive: function(e, eventTarget) { this._stopInactiveTimer(); activeEmitter = null; this._fireEvent(INACTIVE_EVENT_NAME, e, {target: eventTarget}) }, _stopInactiveTimer: function() { clearTimeout(this._inactiveTimer); this._inactiveTimer = null }, _forceInactiveTimer: $.noop, lockInactive: function() { this._forceActiveTimer(); this._stopInactiveTimer(); activeEmitter = null; this._cancel(); return this._forceInactiveTimer } }); ui.events = $.extend(ui.events, {lockFeedback: function(deferred) { var lockInactive = activeEmitter ? activeEmitter.lockInactive() : $.noop; $.when(deferred).always(lockInactive) }}); events.registerEmitter({ emitter: FeedbackEmitter, events: [ACTIVE_EVENT_NAME, INACTIVE_EVENT_NAME] }) })(jQuery, DevExpress); /*! Module core, file ui.events.emitter.click.js */ (function($, DX, wnd, undefined) { var ui = DX.ui, utils = DX.utils, events = ui.events, abs = Math.abs, CLICK_EVENT_NAME = "dxclick", TOUCH_BOUNDARY = 10; var isInput = function(element) { return $(element).is("input, textarea, select, button ,:focus, :focus *") }; var misc = {requestAnimationFrame: DX.requestAnimationFrame}; var ClickEmitter = events.Emitter.inherit({ ctor: function(element) { this.callBase(element); this._makeElementClickable($(element)) }, _makeElementClickable: function($element) { if (!$element.attr("onclick")) $element.attr("onclick", "void(0)") }, start: function(e) { this._blurPrevented = e.dxPreventBlur; this._startTarget = e.target; this._startEventData = events.eventData(e) }, end: function(e) { if (this._eventOutOfElement(e, this.getElement().get(0)) || e.type === "dxpointercancel") { this._cancel(e); return } if (!isInput(e.target) && !this._blurPrevented) utils.resetActiveElement(); this._accept(e); misc.requestAnimationFrame($.proxy(function() { this._fireClickEvent(e) }, this)) }, _eventOutOfElement: function(e, element) { var target = e.target, targetChanged = !$.contains(element, target) && element !== target, gestureDelta = events.eventDelta(events.eventData(e), this._startEventData), boundsExceeded = abs(gestureDelta.x) > TOUCH_BOUNDARY || abs(gestureDelta.y) > TOUCH_BOUNDARY; return targetChanged || boundsExceeded }, _fireClickEvent: function(e) { this._fireEvent(CLICK_EVENT_NAME, e, {target: utils.closestCommonParent(this._startTarget, e.target)}) } }); (function() { var useNativeClick = DX.devices.real().generic; if (useNativeClick) { var prevented = null; ClickEmitter = ClickEmitter.inherit({ start: function() { prevented = null }, end: $.noop, cancel: function() { prevented = true } }); var clickHandler = function(e) { if ((!e.which || e.which === 1) && !prevented) events.fireEvent({ type: CLICK_EVENT_NAME, originalEvent: e }) }; $(document).on(events.addNamespace("click", "NATIVE_DXCLICK_STRATEGY"), clickHandler) } $.extend(events.__internals, {useNativeClick: useNativeClick}) })(); (function() { var fixBuggyInertia = DX.devices.real().ios; if (fixBuggyInertia) { var GESTURE_LOCK_KEY = "dxGestureLock"; ClickEmitter = ClickEmitter.inherit({_fireClickEvent: function(e) { var $element = $(e.target); while ($element.length) { if ($.data($element.get(0), GESTURE_LOCK_KEY)) return; $element = $element.parent() } this.callBase.apply(this, arguments) }}) } $.extend(events.__internals, {fixBuggyInertia: fixBuggyInertia}) })(); (function() { var desktopDevice = DX.devices.real().generic; if (!desktopDevice) { var startTarget = null, blurPrevented = false; var pointerDownHandler = function(e) { startTarget = e.target; blurPrevented = e.dxPreventBlur }; var clickHandler = function(e) { var $target = $(e.target); if (!blurPrevented && startTarget && !$target.is(startTarget) && !$(startTarget).is("label") && isInput($target)) utils.resetActiveElement(); startTarget = null; blurPrevented = false }; var NATIVE_CLICK_FIXER_NAMESPACE = "NATIVE_CLICK_FIXER"; $(document).on(events.addNamespace("dxpointerdown", NATIVE_CLICK_FIXER_NAMESPACE), pointerDownHandler).on(events.addNamespace("click", NATIVE_CLICK_FIXER_NAMESPACE), clickHandler) } })(); events.registerEmitter({ emitter: ClickEmitter, bubble: true, events: [CLICK_EVENT_NAME] }); $.extend(events.__internals, { useFastClick: !events.__internals.useNativeClick && !events.__internals.fixBuggyInertia, misc: misc }) })(jQuery, DevExpress, window); /*! Module core, file ui.events.emitter.hold.js */ (function($, DX, undefined) { var ui = DX.ui, events = ui.events, abs = Math.abs, HOLD_EVENT_NAME = "dxhold", HOLD_TIMEOUT = 750, TOUCH_BOUNDARY = 5; var HoldEmitter = events.Emitter.inherit({ start: function(e) { this._startEventData = events.eventData(e); this._startTimer(e) }, _startTimer: function(e) { var holdTimeout = "timeout" in this ? this.timeout : HOLD_TIMEOUT; this._holdTimer = setTimeout($.proxy(function() { this._requestAccept(e); this._fireEvent(HOLD_EVENT_NAME, e, {target: e.target}); this._forgetAccept() }, this), holdTimeout) }, move: function(e) { if (this._touchWasMoved(e)) this._cancel(e) }, _touchWasMoved: function(e) { var delta = events.eventDelta(this._startEventData, events.eventData(e)); return abs(delta.x) > TOUCH_BOUNDARY || abs(delta.y) > TOUCH_BOUNDARY }, end: function() { this._stopTimer() }, _stopTimer: function() { clearTimeout(this._holdTimer) }, cancel: function() { this._stopTimer() } }); events.registerEmitter({ emitter: HoldEmitter, bubble: true, events: [HOLD_EVENT_NAME] }) })(jQuery, DevExpress); /*! Module core, file ui.events.emitter.gesture.js */ (function($, DX, undefined) { var ui = DX.ui, utils = DX.utils, events = ui.events, devices = DX.devices, support = DX.support, abs = Math.abs; var SLEEP = 0, INITED = 1, STARTED = 2, TOUCH_BOUNDARY = 10, IMMEDIATE_TOUCH_BOUNDARY = 0, IMMEDIATE_TIMEOUT = 180; var isMousewheelEvent = function(e) { return e && e.type === "dxmousewheel" }; var GestureEmitter = events.Emitter.inherit({ configurate: function(data) { this.getElement().css("msTouchAction", data.immediate ? "pinch-zoom" : ""); this.callBase(data) }, allowInterruptionByMousewheel: function() { return this._stage !== STARTED }, getDirection: function() { return this.direction }, _cancel: function(e) { this.callBase.apply(this, arguments); this._togglePointerAddons(true); this._stage = SLEEP }, start: function(e) { if (events.needSkipEvent(e)) { this._cancel(e); return } this._startEvent = events.createEvent(e); this._startEventData = events.eventData(e); this._prevEventData = this._startEventData; this._stage = INITED; this._init(e); this._setupImmediateTimer() }, _setupImmediateTimer: function() { clearTimeout(this._immediateTimer); this._immedeateAccepted = false; if (!this.immediate) return; this._immediateTimer = setTimeout($.proxy(function() { this._immedeateAccepted = true }, this), IMMEDIATE_TIMEOUT) }, move: function(e) { if (this._stage === INITED && this._directionConfirmed(e)) { this._stage = STARTED; this._resetActiveElement(); this._togglePointerAddons(false, e); this._clearSelection(e); this._adjustStartEvent(e); this._start(this._startEvent); this._prevEventData = events.eventData(this._startEvent); if (this._stage === SLEEP) return; this._requestAccept(e); this._move(e); this._forgetAccept() } else if (this._stage === STARTED) this._move(e); this._prevEventData = events.eventData(e) }, _directionConfirmed: function(e) { var touchBoundary = this._getTouchBoundary(e), delta = events.eventDelta(this._startEventData, events.eventData(e)), deltaX = abs(delta.x), deltaY = abs(delta.y); var horizontalMove = this._validateMove(touchBoundary, deltaX, deltaY), verticalMove = this._validateMove(touchBoundary, deltaY, deltaX); var direction = this.getDirection(e), bothAccepted = direction === "both" && (horizontalMove || verticalMove), horizontalAccepted = direction === "horizontal" && horizontalMove, verticalAccepted = direction === "vertical" && verticalMove; return bothAccepted || horizontalAccepted || verticalAccepted || this._immedeateAccepted }, _validateMove: function(touchBoundary, mainAxis, crossAxis) { return mainAxis && mainAxis >= touchBoundary && (this.immediate ? mainAxis >= crossAxis : true) }, _getTouchBoundary: function(e) { return this.immediate || isMousewheelEvent(e) ? IMMEDIATE_TOUCH_BOUNDARY : TOUCH_BOUNDARY }, _adjustStartEvent: function(e) { var touchBoundary = this._getTouchBoundary(e), delta = events.eventDelta(this._startEventData, events.eventData(e)); this._startEvent.pageX += utils.sign(delta.x) * touchBoundary; this._startEvent.pageY += utils.sign(delta.y) * touchBoundary }, _resetActiveElement: function() { if (devices.real().platform === "ios" && $(":focus", this.getElement()).length) utils.resetActiveElement() }, _togglePointerAddons: function(toggle, e) { var isStarted = this._stage === STARTED; if (isStarted) { this._togglePointerInteration(toggle); if (!isMousewheelEvent(e)) this._togglePointerCursor(toggle) } }, _togglePointerInteration: function(toggle) { var isDesktop = devices.real().platform === "generic"; if (isDesktop) { $("body").css("pointer-events", toggle ? "" : "none"); if (support.supportProp("user-select")) $("body").css(support.styleProp("user-select"), toggle ? "" : "none") } }, _togglePointerCursor: function(toggle) { if (toggle) $("html").css("cursor", this._originalCursor); else { this._originalCursor = $("html").css("cursor"); $("html").css("cursor", this.getElement().css("cursor")) } }, _clearSelection: function(e) { if (isMousewheelEvent(e) || events.isTouchEvent(e)) return; utils.clearSelection() }, end: function(e) { this._togglePointerAddons(true, e); if (this._stage === STARTED) this._end(e); else if (this._stage === INITED) this._stop(e); this._stage = SLEEP }, dispose: function() { clearTimeout(this._immediateTimer); this.callBase.apply(this, arguments); this._togglePointerAddons(true) }, _init: $.noop, _start: $.noop, _move: $.noop, _stop: $.noop, _end: $.noop }); $.extend(events, {GestureEmitter: GestureEmitter}); var ORIG_TOUCH_BOUNDARY = TOUCH_BOUNDARY; $.extend(DX.ui.events.__internals, { GESTURE_TOUCH_BOUNDARY: ORIG_TOUCH_BOUNDARY, resetTouchBoundary: function() { TOUCH_BOUNDARY = ORIG_TOUCH_BOUNDARY; events.__internals.GESTURE_TOUCH_BOUNDARY = ORIG_TOUCH_BOUNDARY }, cleanTouchBoundary: function() { TOUCH_BOUNDARY = 0 } }) })(jQuery, DevExpress); /*! Module core, file ui.events.emitter.gesture.scroll.js */ (function($, DX, undefined) { var ui = DX.ui, events = ui.events; var SCROLL_INIT_EVENT = "dxscrollinit", SCROLL_START_EVENT = "dxscrollstart", SCROLL_MOVE_EVENT = "dxscroll", SCROLL_END_EVENT = "dxscrollend", SCROLL_STOP_EVENT = "dxscrollstop", SCROLL_CANCEL_EVENT = "dxscrollcancel", INERTIA_TIMEOUT = 100, VELOCITY_CALC_TIMEOUT = 200, FRAME_DURATION = Math.round(1000 / 60), GESTURE_LOCK_KEY = "dxGestureLock", GESTURE_LOCK_TIMEOUT = 200, NAMESPACED_SCROLL_EVENT = events.addNamespace("scroll", "dxScrollEmitter"); var ScrollEmitter = events.GestureEmitter.inherit({ ctor: function(element) { this.callBase.apply(this, arguments); this.direction = "both"; $.data(element, "scroll", $.proxy(this._treatScroll, this)); $(element).on(NAMESPACED_SCROLL_EVENT, $.proxy(this._treatScroll, this)) }, validate: function() { return true }, _domElement: function() { return this.getElement().get(0) }, _treatScroll: function() { this._prepareGesture(); this._forgetGesture() }, _prepareGesture: function() { if (this._gestureEndTimer) this._clearGestureTimer(); else $.data(this._domElement(), GESTURE_LOCK_KEY, true) }, _forgetGesture: function() { var that = this; this._gestureEndTimer = setTimeout(function() { $.data(that._domElement(), GESTURE_LOCK_KEY, false); that._gestureEndTimer = null }, GESTURE_LOCK_TIMEOUT) }, _init: function(e) { if ($.data(this._domElement(), GESTURE_LOCK_KEY)) this._accept(e); this._fireEvent(SCROLL_INIT_EVENT, e) }, move: function(e) { this.callBase.apply(this, arguments); e.isScrollingEvent = this.isNative || e.isScrollingEvent }, _start: function(e) { this._savedEventData = events.eventData(e); this._fireEvent(SCROLL_START_EVENT, e, {delta: events.eventDelta(this._savedEventData, events.eventData(e))}) }, _move: function(e) { var currentEventData = events.eventData(e); this._fireEvent(SCROLL_MOVE_EVENT, e, {delta: events.eventDelta(this._prevEventData, currentEventData)}); var eventDelta = events.eventDelta(this._savedEventData, currentEventData); if (eventDelta.time > VELOCITY_CALC_TIMEOUT) this._savedEventData = this._prevEventData }, _end: function(e) { var endEventDelta = events.eventDelta(this._prevEventData, events.eventData(e)); var velocity = { x: 0, y: 0 }; var isWheelEvent = e.type === "dxmousewheel"; if (endEventDelta.time < INERTIA_TIMEOUT) { var deltaEventData = events.eventDelta(this._savedEventData, this._prevEventData); velocity = { x: isWheelEvent ? 0 : deltaEventData.x * FRAME_DURATION / deltaEventData.time, y: isWheelEvent ? 0 : deltaEventData.y * FRAME_DURATION / deltaEventData.time } } this._fireEvent(SCROLL_END_EVENT, e, {velocity: velocity}) }, _stop: function(e) { this._fireEvent(SCROLL_STOP_EVENT, e) }, cancel: function(e) { this.callBase.apply(this, arguments); this._fireEvent(SCROLL_CANCEL_EVENT, e) }, dispose: function() { this.callBase.apply(this, arguments); $.data(this._domElement(), GESTURE_LOCK_KEY, false); this._clearGestureTimer(); this.getElement().off(NAMESPACED_SCROLL_EVENT) }, _clearGestureTimer: function() { clearTimeout(this._gestureEndTimer); this._gestureEndTimer = null } }); events.registerEmitter({ emitter: ScrollEmitter, events: [SCROLL_INIT_EVENT, SCROLL_START_EVENT, SCROLL_MOVE_EVENT, SCROLL_END_EVENT, SCROLL_STOP_EVENT, SCROLL_CANCEL_EVENT] }) })(jQuery, DevExpress); /*! Module core, file ui.events.emitter.gesture.swipe.js */ (function($, DX, undefined) { var ui = DX.ui, events = ui.events, SWIPE_START_EVENT = "dxswipestart", SWIPE_EVENT = "dxswipe", SWIPE_END_EVENT = "dxswipeend"; var HorizontalStrategy = { defaultItemSizeFunc: function() { return this.getElement().width() }, getBounds: function() { return [this._maxLeftOffset, this._maxRightOffset] }, calcOffsetRatio: function(e) { var endEventData = events.eventData(e); return (endEventData.x - (this._savedEventData && this._savedEventData.x || 0)) / this._itemSizeFunc().call(this, e) }, isFastSwipe: function(e) { var endEventData = events.eventData(e); return this.FAST_SWIPE_SPEED_LIMIT * Math.abs(endEventData.x - this._tickData.x) >= endEventData.time - this._tickData.time } }; var VerticalStrategy = { defaultItemSizeFunc: function() { return this.getElement().height() }, getBounds: function() { return [this._maxTopOffset, this._maxBottomOffset] }, calcOffsetRatio: function(e) { var endEventData = events.eventData(e); return (endEventData.y - (this._savedEventData && this._savedEventData.y || 0)) / this._itemSizeFunc().call(this, e) }, isFastSwipe: function(e) { var endEventData = events.eventData(e); return this.FAST_SWIPE_SPEED_LIMIT * Math.abs(endEventData.y - this._tickData.y) >= endEventData.time - this._tickData.time } }; var STRATEGIES = { horizontal: HorizontalStrategy, vertical: VerticalStrategy }; var SwipeEmitter = events.GestureEmitter.inherit({ TICK_INTERVAL: 300, FAST_SWIPE_SPEED_LIMIT: 5, ctor: function(element) { this.callBase(element); this.direction = "horizontal"; this.elastic = true }, _getStrategy: function() { return STRATEGIES[this.direction] }, _defaultItemSizeFunc: function() { return this._getStrategy().defaultItemSizeFunc.call(this) }, _itemSizeFunc: function() { return this.itemSizeFunc || this._defaultItemSizeFunc }, _start: function(e) { this._savedEventData = events.eventData(e); this._tickData = {time: 0}; e = this._fireEvent(SWIPE_START_EVENT, e); if (!e.cancel) { this._maxLeftOffset = e.maxLeftOffset; this._maxRightOffset = e.maxRightOffset; this._maxTopOffset = e.maxTopOffset; this._maxBottomOffset = e.maxBottomOffset } }, _move: function(e) { var strategy = this._getStrategy(), moveEventData = events.eventData(e), offset = strategy.calcOffsetRatio.call(this, e); offset = this._fitOffset(offset, this.elastic); if (moveEventData.time - this._tickData.time > this.TICK_INTERVAL) this._tickData = moveEventData; this._fireEvent(SWIPE_EVENT, e, {offset: offset}); e.preventDefault() }, _end: function(e) { var strategy = this._getStrategy(), offsetRatio = strategy.calcOffsetRatio.call(this, e), isFast = strategy.isFastSwipe.call(this, e), startOffset = offsetRatio, targetOffset = this._calcTargetOffset(offsetRatio, isFast); startOffset = this._fitOffset(startOffset, this.elastic); targetOffset = this._fitOffset(targetOffset, false); this._fireEvent(SWIPE_END_EVENT, e, { offset: startOffset, targetOffset: targetOffset }) }, _fitOffset: function(offset, elastic) { var strategy = this._getStrategy(), bounds = strategy.getBounds.call(this); if (offset < -bounds[0]) return elastic ? (-2 * bounds[0] + offset) / 3 : -bounds[0]; if (offset > bounds[1]) return elastic ? (2 * bounds[1] + offset) / 3 : bounds[1]; return offset }, _calcTargetOffset: function(offsetRatio, isFast) { var result; if (isFast) { result = Math.ceil(Math.abs(offsetRatio)); if (offsetRatio < 0) result = -result } else result = Math.round(offsetRatio); return result } }); events.registerEmitter({ emitter: SwipeEmitter, events: [SWIPE_START_EVENT, SWIPE_EVENT, SWIPE_END_EVENT] }) })(jQuery, DevExpress); /*! Module core, file ui.events.emitter.gesture.drag.js */ (function($, DX, undefined) { var ui = DX.ui, utils = DX.utils, events = ui.events, wrapToArray = utils.wrapToArray; var DRAG_START_EVENT = "dxdragstart", DRAG_EVENT = "dxdrag", DRAG_END_EVENT = "dxdragend", DRAG_ENTER_EVENT = "dxdragenter", DRAG_LEAVE_EVENT = "dxdragleave", DROP_EVENT = "dxdrop"; var knownDropTargets = [], knownDropTargetSelectors = [], knownDropTargetConfigs = []; var dropTargetRegistration = { setup: function(element, data) { var knownDropTarget = $.inArray(element, knownDropTargets) !== -1; if (!knownDropTarget) { knownDropTargets.push(element); knownDropTargetSelectors.push([]); knownDropTargetConfigs.push(data || {}) } }, add: function(element, handleObj) { var index = $.inArray(element, knownDropTargets); var selector = handleObj.selector; if ($.inArray(selector, knownDropTargetSelectors[index]) === -1) knownDropTargetSelectors[index].push(selector) }, teardown: function(element, data) { var elementEvents = $._data(element, "events"), handlersCount = 0; $.each([DRAG_ENTER_EVENT, DRAG_LEAVE_EVENT, DROP_EVENT], function(_, eventName) { var eventHandlers = elementEvents[eventName]; if (eventHandlers) handlersCount += eventHandlers.length }); if (!handlersCount) { var index = $.inArray(element, knownDropTargets); knownDropTargets.splice(index, 1); knownDropTargetSelectors.splice(index, 1); knownDropTargetConfigs.splice(index, 1) } } }; events.registerEvent(DRAG_ENTER_EVENT, dropTargetRegistration); events.registerEvent(DRAG_LEAVE_EVENT, dropTargetRegistration); events.registerEvent(DROP_EVENT, dropTargetRegistration); var getItemDelegatedTargets = function($element) { var dropTargetIndex = $.inArray($element.get(0), knownDropTargets), dropTargetSelectors = knownDropTargetSelectors[dropTargetIndex]; var $delegatedTargets = $element.find(dropTargetSelectors.join(", ")); if ($.inArray(undefined, dropTargetSelectors) !== -1) $delegatedTargets = $delegatedTargets.addBack(); return $delegatedTargets }; var getItemConfig = function($element) { var dropTargetIndex = $.inArray($element.get(0), knownDropTargets); return knownDropTargetConfigs[dropTargetIndex] }; var getItemPosition = function(dropTargetConfig, $element) { if (dropTargetConfig.itemPositionFunc) return dropTargetConfig.itemPositionFunc($element); else return $element.offset() }; var getItemSize = function(dropTargetConfig, $element) { if (dropTargetConfig.itemSizeFunc) return dropTargetConfig.itemSizeFunc($element); return { width: $element.width(), height: $element.height() } }; var DragEmitter = events.GestureEmitter.inherit({ ctor: function(element) { this.callBase(element); this.direction = "both" }, _init: function(e) { this._initEvent = e }, _start: function(e) { e = this._fireEvent(DRAG_START_EVENT, this._initEvent); this._maxLeftOffset = e.maxLeftOffset; this._maxRightOffset = e.maxRightOffset; this._maxTopOffset = e.maxTopOffset; this._maxBottomOffset = e.maxBottomOffset; var dropTargets = wrapToArray(e.targetElements || (e.targetElements === null ? [] : knownDropTargets)); this._dropTargets = $.map(dropTargets, function(element) { return $(element).get(0) }) }, _move: function(e) { var eventData = events.eventData(e), dragOffset = this._calculateOffset(eventData); this._fireEvent(DRAG_EVENT, e, {offset: dragOffset}); this._processDropTargets(e, dragOffset); e.preventDefault() }, _calculateOffset: function(eventData) { return { x: this._calculateXOffset(eventData), y: this._calculateYOffset(eventData) } }, _calculateXOffset: function(eventData) { if (this.direction !== "vertical") { var offset = eventData.x - this._startEventData.x; return this._fitOffset(offset, this._maxLeftOffset, this._maxRightOffset) } return 0 }, _calculateYOffset: function(eventData) { if (this.direction !== "horizontal") { var offset = eventData.y - this._startEventData.y; return this._fitOffset(offset, this._maxTopOffset, this._maxBottomOffset) } return 0 }, _fitOffset: function(offset, minOffset, maxOffset) { if (minOffset != null) offset = Math.max(offset, -minOffset); if (maxOffset != null) offset = Math.min(offset, maxOffset); return offset }, _processDropTargets: function(e, dragOffset) { var target = this._findDropTarget(e), sameTarget = target === this._currentDropTarget; if (!sameTarget) { this._fireDropTargetEvent(e, DRAG_LEAVE_EVENT); this._currentDropTarget = target; this._fireDropTargetEvent(e, DRAG_ENTER_EVENT) } }, _fireDropTargetEvent: function(event, eventName) { if (!this._currentDropTarget) return; var eventData = { type: eventName, originalEvent: event, draggingElement: this._$element.get(0), target: this._currentDropTarget }; events.fireEvent(eventData) }, _findDropTarget: function(e) { var that = this, result; $.each(knownDropTargets, function(_, target) { if (!that._checkDropTargetActive(target)) return; var $target = $(target); $.each(getItemDelegatedTargets($target), function(_, delegatedTarget) { var $delegatedTarget = $(delegatedTarget); if (that._checkDropTarget(getItemConfig($target), $delegatedTarget, e)) result = delegatedTarget }) }); return result }, _checkDropTargetActive: function(target) { var active = false; $.each(this._dropTargets, function(_, activeTarget) { active = active || activeTarget === target || $.contains(activeTarget, target); return !active }); return active }, _checkDropTarget: function(config, $target, e) { var isDraggingElement = $target.get(0) === this._$element.get(0); if (isDraggingElement) return false; var targetPosition = getItemPosition(config, $target); if (e.pageX < targetPosition.left) return false; if (e.pageY < targetPosition.top) return false; var targetSize = getItemSize(config, $target); if (e.pageX > targetPosition.left + targetSize.width) return false; if (e.pageY > targetPosition.top + targetSize.height) return false; return $target }, _end: function(e) { var eventData = events.eventData(e); this._fireEvent(DRAG_END_EVENT, e, {offset: this._calculateOffset(eventData)}); this._fireDropTargetEvent(e, DROP_EVENT); delete this._currentDropTarget } }); events.registerEmitter({ emitter: DragEmitter, events: [DRAG_START_EVENT, DRAG_EVENT, DRAG_END_EVENT] }); DX.ui.events.__internals = DX.ui.events.__internals || {}; $.extend(DX.ui.events.__internals, {dropTargets: knownDropTargets}) })(jQuery, DevExpress); /*! Module core, file ui.events.emitter.transform.js */ (function($, DX, undefined) { var ui = DX.ui, utils = DX.utils, events = ui.events, fitIntoRange = utils.fitIntoRange; var DX_PREFIX = "dx", TRANSFORM = "transform", TRANSLATE = "translate", ZOOM = "zoom", PINCH = "pinch", ROTATE = "rotate", START_POSTFIX = "start", UPDATE_POSTFIX = "", END_POSTFIX = "end"; var eventAliases = []; var addAlias = function(eventName, eventArgs) { eventAliases.push({ name: eventName, args: eventArgs }) }; addAlias(TRANSFORM, { scale: true, deltaScale: true, rotation: true, deltaRotation: true, translation: true, deltaTranslation: true }); addAlias(TRANSLATE, { translation: true, deltaTranslation: true }); addAlias(ZOOM, { scale: true, deltaScale: true }); addAlias(PINCH, { scale: true, deltaScale: true }); addAlias(ROTATE, { rotation: true, deltaRotation: true }); var getVector = function(first, second) { return { x: second.pageX - first.pageX, y: -second.pageY + first.pageY, centerX: (second.pageX + first.pageX) * 0.5, centerY: (second.pageY + first.pageY) * 0.5 } }; var getEventVector = function(e) { var pointers = e.pointers; return getVector(pointers[0], pointers[1]) }; var getDistance = function(vector) { return Math.sqrt(vector.x * vector.x + vector.y * vector.y) }; var getScale = function(firstVector, secondVector) { return getDistance(firstVector) / getDistance(secondVector) }; var getRotation = function(firstVector, secondVector) { var scalarProduct = firstVector.x * secondVector.x + firstVector.y * secondVector.y; var distanceProduct = getDistance(firstVector) * getDistance(secondVector); if (distanceProduct === 0) return 0; var sign = utils.sign(firstVector.x * secondVector.y - secondVector.x * firstVector.y); var angle = Math.acos(fitIntoRange(scalarProduct / distanceProduct, -1, 1)); return sign * angle }; var getTranslation = function(firstVector, secondVector) { return { x: firstVector.centerX - secondVector.centerX, y: firstVector.centerY - secondVector.centerY } }; var TransformEmitter = events.Emitter.inherit({ configurate: function(data, eventName) { if (eventName.indexOf(ZOOM) > -1) DX.log("W0005", eventName, "15.1", "Use '" + eventName.replace(ZOOM, PINCH) + "' event instead"); this.callBase(data) }, validatePointers: function(e) { return events.hasTouches(e) > 1 }, start: function(e) { this._accept(e); var startVector = getEventVector(e); this._startVector = startVector; this._prevVector = startVector; this._fireEventAliases(START_POSTFIX, e) }, move: function(e) { var currentVector = getEventVector(e), eventArgs = this._getEventArgs(currentVector); this._fireEventAliases(UPDATE_POSTFIX, e, eventArgs); this._prevVector = currentVector }, end: function(e) { var eventArgs = this._getEventArgs(this._prevVector); this._fireEventAliases(END_POSTFIX, e, eventArgs) }, _getEventArgs: function(vector) { return { scale: getScale(vector, this._startVector), deltaScale: getScale(vector, this._prevVector), rotation: getRotation(vector, this._startVector), deltaRotation: getRotation(vector, this._prevVector), translation: getTranslation(vector, this._startVector), deltaTranslation: getTranslation(vector, this._prevVector) } }, _fireEventAliases: function(eventPostfix, originalEvent, eventArgs) { eventArgs = eventArgs || {}; $.each(eventAliases, $.proxy(function(_, eventAlias) { var args = {}; $.each(eventAlias.args, function(name) { if (name in eventArgs) args[name] = eventArgs[name] }); this._fireEvent(DX_PREFIX + eventAlias.name + eventPostfix, originalEvent, args) }, this)) } }); events.registerEmitter({ emitter: TransformEmitter, events: $.map(eventAliases, function(eventAlias) { var eventNames = []; $.each([START_POSTFIX, UPDATE_POSTFIX, END_POSTFIX], function(_, eventPostfix) { eventNames.push(DX_PREFIX + eventAlias.name + eventPostfix) }); return eventNames }) }) })(jQuery, DevExpress); /*! Module core, file ui.events.dblclick.js */ (function($, DX, undefined) { var ui = DX.ui, events = ui.events, utils = DX.utils, DBLCLICK_EVENT_NAME = "dxdblclick", DBLCLICK_NAMESPACE = "dxDblClick", NAMESPACED_CLICK_EVENT = events.addNamespace("dxclick", DBLCLICK_NAMESPACE), DBLCLICK_TIMEOUT = 300; var DblClick = DX.Class.inherit({ ctor: function() { this._handlerCount = 0; this._forgetLastClick() }, _forgetLastClick: function() { this._firstClickTarget = null; this._lastClickTimeStamp = -DBLCLICK_TIMEOUT }, add: function() { if (this._handlerCount <= 0) $(document).on(NAMESPACED_CLICK_EVENT, $.proxy(this._clickHandler, this)); this._handlerCount++ }, _clickHandler: function(e) { var timeStamp = e.timeStamp || $.now(); if (timeStamp - this._lastClickTimeStamp < DBLCLICK_TIMEOUT) { events.fireEvent({ type: DBLCLICK_EVENT_NAME, target: utils.closestCommonParent(this._firstClickTarget, e.target), originalEvent: e }); this._forgetLastClick() } else { this._firstClickTarget = e.target; this._lastClickTimeStamp = timeStamp } }, remove: function() { this._handlerCount--; if (this._handlerCount <= 0) { this._forgetLastClick(); $(document).off(NAMESPACED_CLICK_EVENT) } } }); events.registerEvent(DBLCLICK_EVENT_NAME, new DblClick) })(jQuery, DevExpress); /*! Module core, file ui.events.remove.js */ (function($) { (function(cleanData) { $.cleanData = function(elements) { $.each(elements, function() { $(this).triggerHandler("dxremove") }); return cleanData.apply(this, arguments) } })($.cleanData) })(jQuery); /*! Module core, file ui.events.contextmenu.js */ (function($, DX, undefined) { var ui = DX.ui, events = ui.events, support = DX.support, CONTEXTMENU_NAMESPACE = "dxContexMenu", CONTEXTMENU_NAMESPACED_EVENT_NAME = events.addNamespace("contextmenu", CONTEXTMENU_NAMESPACE), HOLD_NAMESPACED_EVENT_NAME = events.addNamespace("dxhold", CONTEXTMENU_NAMESPACE), CONTEXTMENU_EVENT_NAME = "dxcontextmenu"; var ContextMenu = DX.Class.inherit({ setup: function(element, data) { var $element = $(element); $element.on(CONTEXTMENU_NAMESPACED_EVENT_NAME, $.proxy(this._contextMenuHandler, this)); if (support.touch || DX.devices.isSimulator()) $element.on(HOLD_NAMESPACED_EVENT_NAME, $.proxy(this._holdHandler, this)) }, _holdHandler: function(e) { if (events.isMouseEvent(e) && !DX.devices.isSimulator()) return; this._fireContextMenu(e) }, _contextMenuHandler: function(e) { e = this._fireContextMenu(e); if (!e.cancel) e.preventDefault() }, _fireContextMenu: function(e) { return events.fireEvent({ type: CONTEXTMENU_EVENT_NAME, originalEvent: e }) }, teardown: function(element) { $(element).off("." + CONTEXTMENU_NAMESPACE) } }); events.registerEvent(CONTEXTMENU_EVENT_NAME, new ContextMenu) })(jQuery, DevExpress); /*! Module core, file ui.widget.js */ (function($, DX, undefined) { var ui = DX.ui, utils = DX.utils, events = ui.events, UI_FEEDBACK = "UIFeedback", WIDGET_CLASS = "dx-widget", ACTIVE_STATE_CLASS = "dx-state-active", DISABLED_STATE_CLASS = "dx-state-disabled", INVISIBLE_STATE_CLASS = "dx-state-invisible", HOVER_STATE_CLASS = "dx-state-hover", FOCUSED_STATE_CLASS = "dx-state-focused", FEEDBACK_SHOW_TIMEOUT = 30, FEEDBACK_HIDE_TIMEOUT = 400, HOVER_START = "dxhoverstart", HOVER_END = "dxhoverend", FOCUS_NAMESPACE = "Focus", ANONYMOUS_TEMPLATE_NAME = "template", TEXT_NODE = 3, TEMPLATE_SELECTOR = "[data-options*='dxTemplate']", TEMPLATE_WRAPPER_CLASS = "dx-template-wrapper"; var DynamicTemplate = ui.TemplateBase.inherit({ ctor: function(compileFunction, owner) { this.callBase($(), owner); this._compileFunction = compileFunction }, _renderCore: function(data, index, container) { if (data === undefined && index === undefined) { data = container; container = undefined } var compiledTemplate = index === undefined ? this._compileFunction(data, container) : this._compileFunction(data, index, container); var renderResult = compiledTemplate.render(data, container, index); if (compiledTemplate.owner() === this) compiledTemplate.dispose(); return renderResult } }); var EmptyTemplate = ui.TemplateBase.inherit({ ctor: function(owner) { this.callBase($(), owner) }, _renderCore: function(data, index, container) { return $() } }); var RendererTemplate = ui.TemplateBase.inherit({_renderCore: function() { return this._element }}); ui.Widget = DX.DOMComponent.inherit({ NAME: "Widget", _supportedKeys: function() { return {} }, _setDeprecatedOptions: function() { this.callBase(); $.extend(this._deprecatedOptions, {contentReadyAction: { since: "14.2", alias: "onContentReady" }}) }, _setDefaultOptions: function() { this.callBase(); this.option({ disabled: false, visible: true, hint: undefined, activeStateEnabled: false, onContentReady: null, hoverStateEnabled: false, focusStateEnabled: false, tabIndex: 0, accessKey: null, onFocusIn: null, onFocusOut: null, templateProvider: ui.TemplateProvider, _keyboardProcessor: undefined, _templates: {} }) }, _init: function() { this.callBase(); this._feedbackShowTimeout = FEEDBACK_SHOW_TIMEOUT; this._feedbackHideTimeout = FEEDBACK_HIDE_TIMEOUT; this._tempTemplates = []; this._dynamicTemplates = {}; this._initTemplates(); this._initContentReadyAction(); this._initFocusActions() }, _initTemplates: function() { this._extractTemplates(); this._extractAnonimousTemplate() }, _extractTemplates: function() { var templates = this.option("_templates"), templateElements = this.element().contents().filter(TEMPLATE_SELECTOR); var templatesMap = {}; templateElements.each(function(_, template) { var templateOptions = utils.getElementOptions(template).dxTemplate; if (!templateOptions) return; if (!templateOptions.name) throw DX.Error("E0023"); $(template).addClass(TEMPLATE_WRAPPER_CLASS).detach(); templatesMap[templateOptions.name] = templatesMap[templateOptions.name] || []; templatesMap[templateOptions.name].push(template) }); $.each(templatesMap, $.proxy(function(templateName, value) { var deviceTemplate = this._findTemplateByDevice(value); if (deviceTemplate) templates[templateName] = this._createTemplate(deviceTemplate, this) }, this)) }, _findTemplateByDevice: function(templates) { var suitableTemplate = DX.utils.findBestMatches(DX.devices.current(), templates, function(template) { return utils.getElementOptions(template).dxTemplate })[0]; $.each(templates, function(index, template) { if (template !== suitableTemplate) $(template).remove() }); return suitableTemplate }, _extractAnonimousTemplate: function() { var templates = this.option("_templates"), anonimiousTemplateName = this._getAnonimousTemplateName(), $anonimiousTemplate = this.element().contents().detach(); var $notJunkTemplateContent = $anonimiousTemplate.filter(function(_, element) { var isTextNode = element.nodeType === TEXT_NODE, isEmptyText = $.trim($(element).text()).length < 1; return !(isTextNode && isEmptyText) }), onlyJunkTemplateContent = $notJunkTemplateContent.length < 1; if (!templates[anonimiousTemplateName] && !onlyJunkTemplateContent) templates[anonimiousTemplateName] = this._createTemplate($anonimiousTemplate, this) }, _getAriaTarget: function() { return this.element() }, _getAnonimousTemplateName: function() { return ANONYMOUS_TEMPLATE_NAME }, _getTemplateByOption: function(optionName) { return this._getTemplate(this.option(optionName)) }, _getTemplate: function(templateSource) { if ($.isFunction(templateSource)) { var that = this; return new DynamicTemplate(function() { var templateSourceResult = templateSource.apply(that, arguments); if (utils.isDefined(templateSourceResult)) return that._acquireTemplate(templateSourceResult, this, true); else return new EmptyTemplate }, this) } return this._acquireTemplate(templateSource, this) }, _acquireTemplate: function(templateSource, owner, preferRenderer) { if (templateSource == null) return this._createTemplate(utils.normalizeTemplateElement(templateSource), owner); if (templateSource instanceof ui.TemplateBase) return templateSource; if (templateSource.nodeType || templateSource.jquery) { templateSource = $(templateSource); if (preferRenderer && !templateSource.is("script")) return new RendererTemplate(templateSource, owner); return this._createTemplate(templateSource, owner) } if (typeof templateSource === "string") { var userTemplate = this.option("_templates")[templateSource]; if (userTemplate) return userTemplate; var dynamicTemplate = this._dynamicTemplates[templateSource]; if (dynamicTemplate) return dynamicTemplate; var defaultTemplate = this.option("templateProvider").getTemplates(this)[templateSource]; if (defaultTemplate) return defaultTemplate; return this._createTemplate(utils.normalizeTemplateElement(templateSource), owner) } return this._acquireTemplate(templateSource.toString(), owner) }, _createTemplate: function(element, owner) { var template = this.option("templateProvider").createTemplate(element, owner); this._tempTemplates.push(template); return template }, _cleanTemplates: function() { var that = this; $.each(this.option("_templates"), function(_, template) { if (that === template.owner()) template.dispose() }); $.each(this._tempTemplates, function(_, template) { template.dispose() }) }, _initContentReadyAction: function() { this._contentReadyAction = this._createActionByOption("onContentReady", {excludeValidators: ["designMode", "disabled", "readOnly"]}) }, _initFocusActions: function() { var focusInAction = this._createActionByOption("onFocusIn", {excludeValidators: ["readOnly"]}); var focusOutAction = this._createActionByOption("onFocusOut", {excludeValidators: ["readOnly"]}); this._focusInAction = this._createAction(function(e) { e.component._focusInHandler(e.jQueryEvent); focusInAction(e) }, {excludeValidators: ["readOnly"]}); this._focusOutAction = this._createAction(function(e) { e.component._focusOutHandler(e.jQueryEvent); focusOutAction(e) }, {excludeValidators: ["readOnly"]}) }, _render: function() { this.element().addClass(WIDGET_CLASS); this.callBase(); this._toggleDisabledState(this.option("disabled")); this._toggleVisibility(this.option("visible")); this._renderHint(); this._renderContent(); this._renderFocusState(); this._attachFeedbackEvents(); this._attachHoverEvents() }, _renderHint: function() { utils.toggleAttr(this.element(), "title", this.option("hint")) }, _renderContent: function() { this._renderContentImpl(); this._fireContentReadyAction() }, _renderContentImpl: $.noop, _fireContentReadyAction: function() { this._contentReadyAction() }, _dispose: function() { this._cleanTemplates(); this._contentReadyAction = null; this.callBase() }, _clean: function() { this._cleanFocusState(); this.callBase(); this.element().empty() }, _toggleVisibility: function(visible) { this.element().toggleClass(INVISIBLE_STATE_CLASS, !visible); this.setAria("hidden", !visible || undefined) }, _renderFocusState: function() { if (!this.option("focusStateEnabled") || this.option("disabled")) return; this._renderFocusTarget(); this._attachFocusEvents(); this._attachKeyboardEvents(); this._renderAccessKey() }, _renderAccessKey: function() { var focusTarget = this._focusTarget(); focusTarget.attr("accesskey", this.option("accessKey")); var clickNamespace = events.addNamespace("dxclick", UI_FEEDBACK); focusTarget.off(clickNamespace); this.option("accessKey") && focusTarget.on(clickNamespace, $.proxy(function(e) { if (e.screenX === 0 && !e.offsetX && e.pageX === 0) { e.stopImmediatePropagation(); this.focus() } }, this)) }, _eventBindingTarget: function() { return this.element() }, _focusTarget: function() { return this._getActiveElement() }, _getActiveElement: function() { var activeElement = this._eventBindingTarget(); if (this._activeStateUnit) activeElement = activeElement.find(this._activeStateUnit).not("." + DISABLED_STATE_CLASS); return activeElement }, _renderFocusTarget: function() { this._focusTarget().attr("tabindex", this.option("tabIndex")) }, _keyboardEventBindingTarget: function() { return this._eventBindingTarget() }, _attachFocusEvents: function() { var focusInEvent = events.addNamespace("focusin", this.NAME + FOCUS_NAMESPACE); var focusOutEvent = events.addNamespace("focusout", this.NAME + FOCUS_NAMESPACE); var beforeactivateEventNamespace = events.addNamespace("beforeactivate", this.NAME + FOCUS_NAMESPACE); this._focusTarget().off("." + this.NAME + FOCUS_NAMESPACE).on(focusInEvent, $.proxy(function(e) { this._focusInAction({jQueryEvent: e}) }, this)).on(focusOutEvent, $.proxy(function(e) { this._focusOutAction({jQueryEvent: e}) }, this)).on(beforeactivateEventNamespace, function(e) { if (!$(e.target).is(":dx-focusable")) e.preventDefault() }) }, _focusInHandler: function(e) { this._updateFocusState(e, true) }, _focusOutHandler: function(e) { this._updateFocusState(e, false) }, _updateFocusState: function(e, isFocused) { var currentTarget = e.currentTarget, focusTargets = this._focusTarget(); if ($.inArray(currentTarget, focusTargets) !== -1) $(e.currentTarget).toggleClass(FOCUSED_STATE_CLASS, isFocused) }, _attachKeyboardEvents: function() { var processor = this.option("_keyboardProcessor") || new ui.KeyboardProcessor({ element: this._keyboardEventBindingTarget(), focusTarget: this._focusTarget() }); this._keyboardProcessor = processor.reinitialize(this._keyboardHandler, this) }, _keyboardHandler: function(options) { var e = options.originalEvent, key = options.key; var keys = this._supportedKeys(), func = keys[key]; if (func !== undefined) { var handler = $.proxy(func, this); return handler(e) || false } else return true }, _refreshFocusState: function() { this._cleanFocusState(); this._renderFocusState() }, _cleanFocusState: function() { var $element = this._focusTarget(); $element.off("." + this.NAME + FOCUS_NAMESPACE); $element.removeClass(FOCUSED_STATE_CLASS); $element.removeAttr("tabindex"); if (this._keyboardProcessor) this._keyboardProcessor.dispose() }, _attachHoverEvents: function() { var that = this, hoverableSelector = that._activeStateUnit, nameStart = events.addNamespace(HOVER_START, UI_FEEDBACK), nameEnd = events.addNamespace(HOVER_END, UI_FEEDBACK); that._eventBindingTarget().off(nameStart, hoverableSelector).off(nameEnd, hoverableSelector); if (that.option("hoverStateEnabled")) { var startAction = new DX.Action(function(args) { that._hoverStartHandler(args.event); var $target = args.element; that._refreshHoveredElement($target) }); that._eventBindingTarget().on(nameStart, hoverableSelector, function(e) { startAction.execute({ element: $(e.target), event: e }) }).on(nameEnd, hoverableSelector, function(e) { that._hoverEndHandler(e); that._forgetHoveredElement() }) } else that._toggleHoverClass(false) }, _hoverStartHandler: $.noop, _hoverEndHandler: $.noop, _attachFeedbackEvents: function() { var that = this, feedbackSelector = that._activeStateUnit, activeEventName = events.addNamespace("dxactive", UI_FEEDBACK), inactiveEventName = events.addNamespace("dxinactive", UI_FEEDBACK); that._eventBindingTarget().off(activeEventName, feedbackSelector).off(inactiveEventName, feedbackSelector); if (that.option("activeStateEnabled")) { var feedbackActionHandler = function(args) { var $element = args.element, value = args.value; that._toggleActiveState($element, value) }; var feedbackAction = new DX.Action(function(args) { feedbackActionHandler(args) }), feedbackActionDisabled = new DX.Action(function(args) { feedbackActionHandler(args) }, {excludeValidators: ["disabled", "readOnly"]}); that._eventBindingTarget().on(activeEventName, feedbackSelector, {timeout: that._feedbackShowTimeout}, function(e) { feedbackAction.execute({ element: $(e.currentTarget), value: true }) }).on(inactiveEventName, feedbackSelector, {timeout: that._feedbackHideTimeout}, function(e) { feedbackActionDisabled.execute({ element: $(e.currentTarget), value: false }) }) } }, _toggleActiveState: function($element, value) { this._toggleHoverClass(!value); $element.toggleClass(ACTIVE_STATE_CLASS, value) }, _refreshHoveredElement: function(hoveredElement) { var selector = this._activeStateUnit || this.element(); this._forgetHoveredElement(); this._hoveredElement = hoveredElement.closest(selector); this._toggleHoverClass(true) }, _forgetHoveredElement: function() { this._toggleHoverClass(false); delete this._hoveredElement }, _toggleHoverClass: function(value) { if (this._hoveredElement) this._hoveredElement.toggleClass(HOVER_STATE_CLASS, value && this.option("hoverStateEnabled")) }, _toggleDisabledState: function(value) { this.element().toggleClass(DISABLED_STATE_CLASS, Boolean(value)); this._toggleHoverClass(!value); this.setAria("disabled", value || undefined) }, _setWidgetOption: function(widgetName, args) { if (!this[widgetName]) return; if ($.isPlainObject(args[0])) { $.each(args[0], $.proxy(function(option, value) { this._setWidgetOption(widgetName, [option, value]) }, this)); return } var optionName = args[0]; var value = args[1]; if (args.length === 1) value = this.option(optionName); var widgetOptionMap = this[widgetName + "OptionMap"]; this[widgetName].option(widgetOptionMap ? widgetOptionMap(optionName) : optionName, value) }, _createComponent: function(element, name, config) { config = config || {}; this._extendConfig(config, { templateProvider: this.option("templateProvider"), _templates: this.option("_templates") }); return this.callBase(element, name, config) }, _optionChanged: function(args) { switch (args.name) { case"disabled": this._toggleDisabledState(args.value); this._refreshFocusState(); break; case"hint": this._renderHint(); break; case"activeStateEnabled": this._attachFeedbackEvents(); break; case"hoverStateEnabled": this._attachHoverEvents(); break; case"tabIndex": case"_keyboardProcessor": case"focusStateEnabled": this._refreshFocusState(); break; case"onFocusIn": case"onFocusOut": this._initFocusActions(); break; case"accessKey": this._renderAccessKey(); break; case"visible": var visible = args.value; this._toggleVisibility(visible); if (this._isVisibilityChangeSupported()) this._visibilityChanged(visible); break; case"onContentReady": this._initContentReadyAction(); break; case"_templates": case"templateProvider": this._refresh(); break; default: this.callBase(args) } }, beginUpdate: function() { this._ready(false); this.callBase() }, endUpdate: function() { this.callBase(); if (this._initialized) this._ready(true) }, _ready: function(value) { if (arguments.length === 0) return this._isReady; this._isReady = value }, setAria: function() { var setAttribute = function(option) { var attrName = $.inArray(option.name, ["role", "id"]) + 1 ? option.name : "aria-" + option.name, attrValue = option.value; if (attrValue === null || attrValue === undefined) attrValue = undefined; else attrValue = attrValue.toString(); utils.toggleAttr(option.target, attrName, attrValue) }; if (!$.isPlainObject(arguments[0])) setAttribute({ name: arguments[0], value: arguments[1], target: arguments[2] || this._getAriaTarget() }); else { var $target = arguments[1] || this._getAriaTarget(); $.each(arguments[0], function(key, value) { setAttribute({ name: key, value: value, target: $target }) }) } }, isReady: function() { return this._ready() }, repaint: function() { this._refresh() }, focus: function() { this._focusTarget().focus() }, registerKeyHandler: function(key, handler) { var currentKeys = this._supportedKeys(), addingKeys = {}; addingKeys[key] = handler; this._supportedKeys = function() { return $.extend(currentKeys, addingKeys) } } }) })(jQuery, DevExpress); /*! Module core, file ui.editor.js */ (function($, DX, undefined) { var ui = DX.ui, READONLY_STATE_CLASS = "dx-state-readonly", INVALID_CLASS = "dx-invalid", INVALID_MESSAGE = "dx-invalid-message", INVALID_MESSAGE_AUTO = "dx-invalid-message-auto", INVALID_MESSAGE_ALWAYS = "dx-invalid-message-always"; ui.validation = ui.validation || {}; ui.validation.findGroup = function() { var group = this.option("validationGroup"), $dxGroup; if (!group) { $dxGroup = this.element().parents(".dx-validationgroup:first"); if ($dxGroup.length) group = $dxGroup.dxValidationGroup("instance"); else group = this._modelByElement(this.element()) } return group }; ui.Editor = ui.Widget.inherit({ _init: function() { this.callBase(); this.validationRequest = $.Callbacks(); var $element = this.element(); if ($element) { $element.data("dx-validation-target", this); this.on("disposing", function() { $element.data("dx-validation-target", null) }) } this._createValueChangeAction() }, _setDeprecatedOptions: function() { this.callBase(); $.extend(this._deprecatedOptions, {valueChangeAction: { since: "14.2", alias: "onValueChanged", message: "'onValueChanged' option instead" }}) }, _setDefaultOptions: function() { this.callBase(); this.option({ value: null, onValueChanged: null, activeStateEnabled: true, readOnly: false, isValid: true, validationError: null, validationMessageMode: "auto", validationTooltipOffset: { h: 0, v: -10 } }) }, _defaultOptionsRules: function() { return this.callBase().concat([{ device: function(device) { return device.platform === "android" }, options: {invalidTooltipOffset: { h: 9, v: -7 }} }, { device: {platform: "win8"}, options: {invalidTooltipOffset: { h: 9, v: -4 }} }]) }, _attachKeyboardEvents: function() { if (this.option("readOnly")) return; this.callBase.apply(this, arguments); this._attachChildKeyboardEvents() }, _attachChildKeyboardEvents: $.noop, _setOptionsByReference: function() { this.callBase(); $.extend(this._optionsByReference, {validationError: true}) }, _createValueChangeAction: function() { this._valueChangeAction = this._createActionByOption("onValueChanged", {excludeValidators: ["disabled", "readOnly"]}) }, _suppressValueChangeAction: function() { this._valueChangeActionSuppressed = true }, _resumeValueChangeAction: function() { this._valueChangeActionSuppressed = false }, _render: function() { this._renderValidationState(); this._toggleReadOnlyState(); this.callBase() }, _raiseValueChangeAction: function(value, previousValue, extraArguments) { this._valueChangeAction(this._valueChangeArgs(value, previousValue)) }, _valueChangeArgs: function(value, previousValue) { return { value: value, previousValue: previousValue, jQueryEvent: this._valueChangeEventInstance } }, _saveValueChangeEvent: function(e) { this._valueChangeEventInstance = e }, _renderValidationState: function() { var isValid = this.option("isValid"), validationError = this.option("validationError"), validationMessageMode = this.option("validationMessageMode"), $element = this.element(); $element.toggleClass(INVALID_CLASS, !isValid); this.setAria("invalid", !isValid || undefined); if (this._$validationMessage) { this._$validationMessage.remove(); this._$validationMessage = null } if (!isValid && validationError && validationError.message) { this._$validationMessage = $("
", {"class": INVALID_MESSAGE}).text(validationError.message).appendTo($element); this._createComponent(this._$validationMessage, "dxTooltip", { target: $element, container: $element, position: this._getValidationTooltipPosition("below"), closeOnOutsideClick: false, closeOnTargetScroll: false, animation: null, visible: true }); this._$validationMessage.toggleClass(INVALID_MESSAGE_AUTO, validationMessageMode === "auto").toggleClass(INVALID_MESSAGE_ALWAYS, validationMessageMode === "always") } }, _getValidationTooltipPosition: function(positionRequest) { var rtlEnabled = this.option("rtlEnabled"), tooltipPositionSide = rtlEnabled ? "right" : "left", tooltipOriginalOffset = this.option("validationTooltipOffset"), tooltipOffset = { h: tooltipOriginalOffset.h, v: tooltipOriginalOffset.v }, verticalPositions = positionRequest === "below" ? [" top", " bottom"] : [" bottom", " top"]; if (rtlEnabled) tooltipOffset.h = -tooltipOffset.h; if (positionRequest !== "below") tooltipOffset.v = -tooltipOffset.v; return { offset: tooltipOffset, my: tooltipPositionSide + verticalPositions[0], at: tooltipPositionSide + verticalPositions[1], collision: "none" } }, _toggleReadOnlyState: function() { this.element().toggleClass(READONLY_STATE_CLASS, this.option("readOnly")); this.setAria("readonly", this.option("readOnly") || undefined) }, _optionChanged: function(args) { switch (args.name) { case"onValueChanged": this._createValueChangeAction(); break; case"isValid": case"validationError": case"validationMessageMode": this._renderValidationState(); break; case"readOnly": this._toggleReadOnlyState(); this._refreshFocusState(); break; case"value": if (!this._valueChangeActionSuppressed) { this._raiseValueChangeAction(args.value, args.previousValue); this._saveValueChangeEvent(undefined) } if (args.value != args.previousValue) this.validationRequest.fire({ value: args.value, editor: this }); break; default: this.callBase(args) } }, reset: function() { this.option("value", null) } }) })(jQuery, DevExpress); /*! Module core, file ui.CollectionWidget.js */ (function($, DX, undefined) { var ui = DX.ui, utils = DX.utils, events = ui.events; var COLLECTION_CLASS = "dx-collection", ITEM_CLASS = "dx-item", CONTENT_CLASS_POSTFIX = "-content", ITEM_CONTENT_PLACEHOLDER_CLASS = "dx-item-content-placeholder", ITEM_DATA_KEY = "dxItemData", ITEM_TEMPLATE_ID_PREFIX = "tmpl-", ITEMS_SELECTOR = "[data-options*='dxItem']", SELECTED_ITEM_CLASS = "dx-item-selected", FOCUSED_STATE_CLASS = "dx-state-focused", ITEM_RESPONSE_WAIT_CLASS = "dx-item-response-wait", EMPTY_COLLECTION = "dx-empty-collection", TEMPLATE_WRAPPER_CLASS = "dx-template-wrapper"; var FOCUS_UP = "up", FOCUS_DOWN = "down", FOCUS_LEFT = "left", FOCUS_RIGHT = "right", FOCUS_PAGE_UP = "pageup", FOCUS_PAGE_DOWN = "pagedown", FOCUS_LAST = "last", FOCUS_FIRST = "first"; var CollectionWidget = ui.Widget.inherit({ NAME: "CollectionWidget", _activeStateUnit: "." + ITEM_CLASS, _supportedKeys: function() { var click = function(e) { var $itemElement = this.option("focusedElement"); if (!$itemElement) return; e.target = $itemElement; e.currentTarget = $itemElement; this._itemClickHandler(e) }, move = function(location, e) { e.preventDefault(); e.stopPropagation(); this._moveFocus(location, e) }; return $.extend(this.callBase(), { space: click, enter: click, leftArrow: $.proxy(move, this, FOCUS_LEFT), rightArrow: $.proxy(move, this, FOCUS_RIGHT), upArrow: $.proxy(move, this, FOCUS_UP), downArrow: $.proxy(move, this, FOCUS_DOWN), pageUp: $.proxy(move, this, FOCUS_UP), pageDown: $.proxy(move, this, FOCUS_DOWN), home: $.proxy(move, this, FOCUS_FIRST), end: $.proxy(move, this, FOCUS_LAST) }) }, _setDeprecatedOptions: function() { this.callBase(); $.extend(this._deprecatedOptions, { itemClickAction: { since: "14.2", alias: "onItemClick" }, itemHoldAction: { since: "14.2", alias: "onItemHold" }, itemRenderedAction: { since: "14.2", alias: "onItemRendered" }, itemRender: { since: "14.2", alias: "itemTemplate" } }) }, _setDefaultOptions: function() { this.callBase(); this.option({ selectOnFocus: false, loopItemFocus: true, items: [], itemTemplate: "item", onItemRendered: null, onItemClick: null, onItemHold: null, itemHoldTimeout: 750, onItemContextMenu: null, onFocusedItemChanged: null, noDataText: Globalize.localize("dxCollectionWidget-noDataText"), dataSource: null, _itemAttributes: {}, itemTemplateProperty: "template", focusOnSelectedItem: true, focusedElement: null }) }, _getAnonimousTemplateName: function() { return "item" }, _init: function() { this.callBase(); this._cleanRenderedItems(); this._refreshDataSource() }, _initTemplates: function() { this._initItemsFromMarkup(); this.callBase() }, _initItemsFromMarkup: function() { var $items = this.element().contents().filter(ITEMS_SELECTOR); if (!$items.length || this.option("items").length) return; var items = $.map($items, $.proxy(function(item) { var $item = $(item); var result = utils.getElementOptions(item).dxItem; var isTemplateRequired = $.trim($item.html()) && !result.template; if (isTemplateRequired) result.template = this._prepareItemTemplate($item); else $item.remove(); return result }, this)); this.option("items", items) }, _prepareItemTemplate: function($item) { var templateId = ITEM_TEMPLATE_ID_PREFIX + new DX.data.Guid; var templateOptions = "dxTemplate: { name: \"" + templateId + "\" }"; $item.attr("data-options", templateOptions).data("options", templateOptions); return templateId }, _dataSourceOptions: function() { return {paginate: false} }, _cleanRenderedItems: function() { this._renderedItemsCount = 0 }, _focusTarget: function() { return this.element() }, _focusInHandler: function(e) { this.callBase.apply(this, arguments); var $focusedElement = this.option("focusedElement"); if ($focusedElement && $focusedElement.length) this._setFocusedItem($focusedElement); else { var $activeItem = this._getActiveItem(); this.option("focusedElement", $activeItem) } }, _focusOutHandler: function(e) { this.callBase.apply(this, arguments); var $target = this.option("focusedElement"); if ($target) $target.removeClass(FOCUSED_STATE_CLASS) }, _getActiveItem: function(last) { var $focusedElement = this.option("focusedElement"); if ($focusedElement && $focusedElement.length) return $focusedElement; var index = this.option("focusOnSelectedItem") ? this.option("selectedIndex") : 0, activeElements = this._getActiveElement(), lastIndex = activeElements.length - 1; if (index < 0) index = last ? lastIndex : 0; return activeElements.eq(index) }, _renderFocusTarget: function() { this.callBase.apply(this, arguments); this._refreshActiveDescendant() }, _moveFocus: function(location) { var $items = this._itemElements().filter(":visible").not(".dx-state-disabled"), $newTarget; switch (location) { case FOCUS_PAGE_UP: case FOCUS_UP: $newTarget = this._prevItem($items); break; case FOCUS_PAGE_DOWN: case FOCUS_DOWN: $newTarget = this._nextItem($items); break; case FOCUS_RIGHT: $newTarget = this.option("rtlEnabled") ? this._prevItem($items) : this._nextItem($items); break; case FOCUS_LEFT: $newTarget = this.option("rtlEnabled") ? this._nextItem($items) : this._prevItem($items); break; case FOCUS_FIRST: $newTarget = $items.first(); break; case FOCUS_LAST: $newTarget = $items.last(); break; default: return false } if ($newTarget.length !== 0) this.option("focusedElement", $newTarget) }, _prevItem: function($items) { var $target = this._getActiveItem(), targetIndex = $items.index($target), $last = $items.last(), $item = $($items[targetIndex - 1]), loop = this.option("loopItemFocus"); if ($item.length === 0 && loop) $item = $last; return $item }, _nextItem: function($items) { var $target = this._getActiveItem(true), targetIndex = $items.index($target), $first = $items.first(), $item = $($items[targetIndex + 1]), loop = this.option("loopItemFocus"); if ($item.length === 0 && loop) $item = $first; return $item }, _selectFocusedItem: function($target) { this.selectItem($target) }, _removeFocusedItem: function($target) { if ($target && $target.length) { $target.removeClass(FOCUSED_STATE_CLASS); $target.removeAttr("id") } }, _refreshActiveDescendant: function() { this.setAria("activedescendant", ""); this.setAria("activedescendant", this.getFocusedItemId()) }, _setFocusedItem: function($target) { if (!$target || !$target.length) return; $target.attr("id", this.getFocusedItemId()); $target.addClass(FOCUSED_STATE_CLASS); this.onFocusedItemChanged(this.getFocusedItemId()); this._refreshActiveDescendant(); if (this.option("selectOnFocus")) this._selectFocusedItem($target) }, _optionChanged: function(args) { switch (args.name) { case"items": case"_itemAttributes": case"itemTemplateProperty": this._cleanRenderedItems(); this._invalidate(); break; case"dataSource": this._refreshDataSource(); if (!this._dataSource) this.option("items", []); this._renderEmptyMessage(); break; case"noDataText": this._renderEmptyMessage(); break; case"itemTemplate": this._invalidate(); break; case"onItemRendered": this._createItemRenderAction(); break; case"onItemClick": break; case"onItemHold": case"itemHoldTimeout": this._attachHoldEvent(); break; case"onItemContextMenu": this._attachContextMenuEvent(); break; case"onFocusedItemChanged": this.onFocusedItemChanged = this._createActionByOption("onFocusedItemChanged"); break; case"selectOnFocus": case"loopItemFocus": case"focusOnSelectedItem": break; case"focusedElement": this._removeFocusedItem(args.previousValue); this._setFocusedItem(args.value); break; default: this.callBase(args) } }, _loadNextPage: function() { var dataSource = this._dataSource; this._expectNextPageLoading(); dataSource.pageIndex(1 + dataSource.pageIndex()); return dataSource.load() }, _expectNextPageLoading: function() { this._startIndexForAppendedItems = 0 }, _expectLastItemLoading: function() { this._startIndexForAppendedItems = -1 }, _forgetNextPageLoading: function() { this._startIndexForAppendedItems = null }, _dataSourceChangedHandler: function(newItems) { var items = this.option("items"); if (this._initialized && items && this._shouldAppendItems()) { this._renderedItemsCount = items.length; if (!this._isLastPage() || this._startIndexForAppendedItems !== -1) this.option().items = items.concat(newItems.slice(this._startIndexForAppendedItems)); this._forgetNextPageLoading(); this._renderContent(); this._renderFocusTarget() } else this.option("items", newItems) }, _dataSourceLoadErrorHandler: function() { this._forgetNextPageLoading(); this.option("items", this.option("items")) }, _shouldAppendItems: function() { return this._startIndexForAppendedItems != null && this._allowDinamicItemsAppend() }, _allowDinamicItemsAppend: function() { return false }, _clean: function() { this._cleanFocusState(); this._cleanItemContainer() }, _cleanItemContainer: function() { this._itemContainer().empty() }, _refresh: function() { this._cleanRenderedItems(); this.callBase.apply(this, arguments) }, _itemContainer: function() { return this.element() }, _itemClass: function() { return ITEM_CLASS }, _itemContentClass: function() { return this._itemClass() + CONTENT_CLASS_POSTFIX }, _selectedItemClass: function() { return SELECTED_ITEM_CLASS }, _itemResponseWaitClass: function() { return ITEM_RESPONSE_WAIT_CLASS }, _itemSelector: function() { return "." + this._itemClass() }, _itemDataKey: function() { return ITEM_DATA_KEY }, _itemElements: function() { return this._itemContainer().find(this._itemSelector()) }, _render: function() { this.callBase(); this.element().addClass(COLLECTION_CLASS); this._attachClickEvent(); this._attachHoldEvent(); this._attachContextMenuEvent(); this.onFocusedItemChanged = this._createActionByOption("onFocusedItemChanged") }, _attachClickEvent: function() { var itemSelector = this._itemSelector(), clickEventNamespace = events.addNamespace("dxclick", this.NAME), pointerDownEventNamespace = events.addNamespace("dxpointerdown", this.NAME), that = this; var pointerDownAction = new DX.Action(function(args) { var event = args.event; that._itemPointerDownHandler(event) }); this._itemContainer().off(clickEventNamespace, itemSelector).off(pointerDownEventNamespace, itemSelector).on(clickEventNamespace, itemSelector, $.proxy(this._itemClickHandler, this)).on(pointerDownEventNamespace, itemSelector, function(e) { pointerDownAction.execute({ element: $(e.target), event: e }) }) }, _itemClickHandler: function(e) { this._itemJQueryEventHandler(e, "onItemClick") }, _itemPointerDownHandler: function(e) { if (!this.option("focusStateEnabled")) return; var elementClass = this._itemClass(), $target = $(e.target).closest("." + elementClass); if ($target.hasClass(elementClass)) this.option("focusedElement", $target) }, _attachHoldEvent: function() { var $itemContainer = this._itemContainer(), itemSelector = this._itemSelector(), eventName = events.addNamespace("dxhold", this.NAME); $itemContainer.off(eventName, itemSelector); if (this._shouldAttachHoldEvent()) $itemContainer.on(eventName, itemSelector, {timeout: this._getHoldTimeout()}, $.proxy(this._itemHoldHandler, this)) }, _getHoldTimeout: function() { return this.option("itemHoldTimeout") }, _shouldAttachHoldEvent: function() { return this.option("onItemHold") }, _itemHoldHandler: function(e) { this._itemJQueryEventHandler(e, "onItemHold") }, _attachContextMenuEvent: function() { var $itemContainer = this._itemContainer(), itemSelector = this._itemSelector(), eventName = events.addNamespace("dxcontextmenu", this.NAME); $itemContainer.off(eventName, itemSelector); if (this._shouldAttachContextMenuEvent()) $itemContainer.on(eventName, itemSelector, $.proxy(this._itemContextMenuHandler, this)) }, _shouldAttachContextMenuEvent: function() { return this.option("onItemContextMenu") }, _itemContextMenuHandler: function(e) { this._itemJQueryEventHandler(e, "onItemContextMenu") }, _renderContentImpl: function() { var items = this.option("items") || []; if (this._renderedItemsCount) this._renderItems(items.slice(this._renderedItemsCount)); else this._renderItems(items) }, _renderItems: function(items) { if (items.length) $.each(items, $.proxy(this._renderItem, this)); this._renderEmptyMessage() }, _renderItem: function(index, itemData, $container) { $container = $container || this._itemContainer(); var $itemFrame = this._renderItemFrame(index, itemData, $container); this._setElementData($itemFrame, itemData); var $itemContent = $itemFrame.find("." + ITEM_CONTENT_PLACEHOLDER_CLASS); $itemContent.removeClass(ITEM_CONTENT_PLACEHOLDER_CLASS); $itemContent = this._renderItemContent(index, itemData, $itemContent); this._postprocessRenderItem({ itemElement: $itemFrame, itemContent: $itemContent, itemData: itemData, itemIndex: index }); this._executeItemRenderAction(index, itemData, $itemFrame); this._attachItemClickEvent(itemData, $itemFrame); return $itemFrame.attr(this.option("_itemAttributes")) }, _attachItemClickEvent: function(itemData, $itemElement) { if (!itemData || !itemData.onClick) return; $itemElement.on("dxclick", $.proxy(function(e) { this._itemEventHandlerByHandler($itemElement, itemData.onClick, {jQueryEvent: e}) }, this)) }, _renderItemContent: function(index, itemData, $container) { var $itemNode = itemData && itemData.node; var itemTemplateName = this._getItemTemplateName(itemData); var itemTemplate = this._getTemplate(itemTemplateName, itemData, index, $container); var renderArgs = { index: index, item: itemData, container: $container }; if ($itemNode) { $container.replaceWith($itemNode); $container = $itemNode; this._addItemContentClasses($container, itemData) } else { this._addItemContentClasses($container, itemData); var $result = this._createItemByTemplate(itemTemplate, renderArgs); if ($result.hasClass(TEMPLATE_WRAPPER_CLASS)) { $container.replaceWith($result); $container = $result; this._addItemContentClasses($container, itemData) } } return $container }, _addItemContentClasses: function($container) { $container.addClass([ITEM_CLASS + CONTENT_CLASS_POSTFIX, this._itemContentClass()].join(" ")) }, _renderItemFrame: function(index, itemData, $container) { var itemFrameTemplate = this.option("templateProvider").getTemplates(this)["itemFrame"], $itemFrame = itemFrameTemplate.render(utils.isDefined(itemData) ? itemData : {}, $container, index); $itemFrame.appendTo($container); return $itemFrame }, _postprocessRenderItem: $.noop, _executeItemRenderAction: function(index, itemData, itemElement) { this._getItemRenderAction()({ itemElement: itemElement, itemIndex: index, itemData: itemData }) }, _setElementData: function(element, data) { element.addClass([ITEM_CLASS, this._itemClass()].join(" ")).data(this._itemDataKey(), data) }, _createItemRenderAction: function() { return this._itemRenderAction = this._createActionByOption("onItemRendered", { element: this.element(), excludeValidators: ["designMode", "disabled", "readOnly"], category: "rendering" }) }, _getItemRenderAction: function() { return this._itemRenderAction || this._createItemRenderAction() }, _getItemTemplateName: function(itemData) { var templateProperty = this.option("itemTemplateProperty"); return itemData && itemData[templateProperty] || this.option("itemTemplate") }, _createItemByTemplate: function(itemTemplate, renderArgs) { return itemTemplate.render(renderArgs.item, renderArgs.container, renderArgs.index, "ignoreTarget") }, _renderEmptyMessage: function() { var noDataText = this.option("noDataText"), items = this.option("items"), hideNoData = !noDataText || items && items.length || this._isDataSourceLoading(); if (hideNoData && this._$nodata) { this._$nodata.remove(); this._$nodata = null; this.setAria("label", undefined) } if (!hideNoData) { this._$nodata = this._$nodata || $("
").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: "" + 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 }