/*! * DevExtreme Web * Version: 14.1.9-pre * Build date: Nov 7, 2014 * * Copyright (c) 2012 - 2014 Developer Express Inc. ALL RIGHTS RESERVED * EULA: https://www.devexpress.com/Support/EULAs/DevExtreme.xml */ "use strict"; if (!window.DevExpress) { /*! Module core, file devexpress.js */ (function($, global, undefined) { (function checkjQueryVersion(version) { version = version.split("."); if (version[0] < 1 || version[0] == 1 && version[1] < 10) throw Error("Your version of jQuery is too old. Please upgrade jQuery to 1.10.0 or later."); })($.fn.jquery); var Class = function() { var wrapOverridden = function(baseProto, methodName, method) { return function() { var prevCallBase = this.callBase; this.callBase = baseProto[methodName]; try { return method.apply(this, arguments) } finally { this.callBase = prevCallBase } } }; var clonePrototype = function(obj) { var func = function(){}; func.prototype = obj.prototype; return new func }; var classImpl = function(){}; var redefine = function(members) { var that = this; if (!members) return that; var memberNames = $.map(members, function(_, k) { return k }); $.each(["toString", "toLocaleString", "valueOf"], function() { if (members[this]) memberNames.push(this) }); $.each(memberNames, function() { var overridden = $.isFunction(that.prototype[this]) && $.isFunction(members[this]); that.prototype[this] = overridden ? wrapOverridden(that.parent.prototype, this, members[this]) : members[this] }); return that }; var include = function() { var classObj = this; $.each(arguments, function() { if (this.ctor) classObj._includedCtors.push(this.ctor); for (var name in this) { if (name === "ctor") continue; if (name in classObj.prototype) throw Error("Member name collision: " + name); classObj.prototype[name] = this[name] } }); return classObj }; var subclassOf = function(parentClass) { if (this.parent === parentClass) return true; if (!this.parent || !this.parent.subclassOf) return false; return this.parent.subclassOf(parentClass) }; classImpl.inherit = function(members) { var inheritor = function() { if (!this || this === global || typeof this.constructor !== "function") throw Error("A class must be instantiated using the 'new' keyword"); var instance = this, ctor = instance.ctor; if (ctor) ctor.apply(instance, arguments); $.each(instance.constructor._includedCtors, function() { this.call(instance) }) }; inheritor.prototype = clonePrototype(this); inheritor.inherit = this.inherit; inheritor.redefine = redefine; inheritor.include = include; inheritor.subclassOf = subclassOf; inheritor.parent = this; inheritor._includedCtors = this._includedCtors ? this._includedCtors.slice(0) : []; inheritor.prototype.constructor = inheritor; inheritor.redefine(members); return inheritor }; return classImpl }(); function createQueue(discardPendingTasks) { var _tasks = [], _busy = false; function exec() { while (_tasks.length) { _busy = true; var task = _tasks.shift(), result = task(); if (result === undefined) continue; if (result.then) { $.when(result).always(exec); return } throw Error("Queued task returned unexpected result"); } _busy = false } function add(task, removeTaskCallback) { if (!discardPendingTasks) _tasks.push(task); else { if (_tasks[0] && removeTaskCallback) removeTaskCallback(_tasks[0]); _tasks = [task] } if (!_busy) exec() } function busy() { return _busy } return { add: add, busy: busy } } var parseUrl = function() { var a = document.createElement("a"), props = ["protocol", "hostname", "port", "pathname", "search", "hash"]; var normalizePath = function(value) { if (value.charAt(0) !== "/") value = "/" + value; return value }; return function(url) { a.href = url; var result = {}; $.each(props, function() { result[this] = a[this] }); result.pathname = normalizePath(result.pathname); return result } }(); global.DevExpress = global.DevExpress || {}; var enqueueAsync = function(task) { var deferred = $.Deferred(); setTimeout(function() { deferred.resolve(task()) }, 60); return deferred }; var hideTopOverlayCallback = function() { var callbacks = []; return { add: function(callback) { var indexOfCallback = $.inArray(callback, callbacks); if (indexOfCallback === -1) callbacks.push(callback) }, remove: function(callback) { var indexOfCallback = $.inArray(callback, callbacks); if (indexOfCallback !== -1) callbacks.splice(indexOfCallback, 1) }, fire: function() { var callback = callbacks.pop(), result = !!callback; if (result) callback(); return result }, hasCallback: function() { return callbacks.length > 0 }, reset: function() { callbacks = [] } } }(); var overlayTargetContainer = function() { var defaultTargetContainer = "body"; return function(targetContainer) { if (arguments.length) defaultTargetContainer = targetContainer; return defaultTargetContainer } }(); $.extend(global.DevExpress, { VERSION: "14.1.8", abstract: function() { throw Error("Not implemented"); }, Class: Class, createQueue: createQueue, enqueue: createQueue().add, enqueueAsync: enqueueAsync, parseUrl: parseUrl, hideTopOverlayCallback: hideTopOverlayCallback, hardwareBackButton: $.Callbacks(), overlayTargetContainer: overlayTargetContainer, rtlEnabled: false }) })(jQuery, this); /*! Module core, file inflector.js */ (function($, DX, undefined) { var _normalize = function(text) { if (text === undefined || text === null) return ""; return String(text) }; var _ucfirst = function(text) { return _normalize(text).charAt(0).toUpperCase() + text.substr(1) }; var _chop = function(text) { return _normalize(text).replace(/([a-z\d])([A-Z])/g, "$1 $2").split(/[\s_-]+/) }; var dasherize = function(text) { return $.map(_chop(text), function(p) { return p.toLowerCase() }).join("-") }; var underscore = function(text) { return dasherize(text).replace(/-/g, "_") }; var camelize = function(text, upperFirst) { return $.map(_chop(text), function(p, i) { p = p.toLowerCase(); if (upperFirst || i > 0) p = _ucfirst(p); return p }).join("") }; var humanize = function(text) { return _ucfirst(dasherize(text).replace(/-/g, " ")) }; var titleize = function(text) { return $.map(_chop(text), function(p) { return _ucfirst(p.toLowerCase()) }).join(" ") }; DX.inflector = { dasherize: dasherize, camelize: camelize, humanize: humanize, titleize: titleize, underscore: underscore } })(jQuery, DevExpress); /*! Module core, file utils.common.js */ (function($, DX, undefined) { var isDefined = function(object) { return object !== null && object !== undefined }; var isString = function(object) { return $.type(object) === 'string' }; var isNumber = function(object) { return typeof object === "number" && isFinite(object) || $.isNumeric(object) }; var isObject = function(object) { return $.type(object) === 'object' }; var isArray = function(object) { return $.type(object) === 'array' }; var isDate = function(object) { return $.type(object) === 'date' }; var isFunction = function(object) { return $.type(object) === 'function' }; var isExponential = function(value) { return isNumber(value) && value.toString().indexOf('e') !== -1 }; var extendFromObject = function(target, source, overrideExistingValues) { target = target || {}; for (var prop in source) if (source.hasOwnProperty(prop)) { var value = source[prop]; if (!(prop in target) || overrideExistingValues) target[prop] = value } return target }; var clone = function() { function Clone(){} return function(obj) { Clone.prototype = obj; return new Clone } }(); var executeAsync = function(action, context) { var deferred = $.Deferred(), normalizedContext = context || this; setTimeout(function() { var result = action.call(normalizedContext); if (result && result.done && $.isFunction(result.done)) result.done(function() { deferred.resolveWith(normalizedContext) }); else deferred.resolveWith(normalizedContext) }, 0); return deferred.promise() }; var stringFormat = function() { var s = arguments[0]; for (var i = 0; i < arguments.length - 1; i++) { var reg = new RegExp("\\{" + i + "\\}", "gm"); s = s.replace(reg, arguments[i + 1]) } return s }; var findBestMatches = function(targetFilter, items, mapFn) { var bestMatches = [], maxMatchCount = 0; $.each(items, function(index, itemSrc) { var matchCount = 0, item = mapFn ? mapFn(itemSrc) : itemSrc; $.each(targetFilter, function(paramName) { var value = item[paramName]; if (value === undefined) return; if (value === targetFilter[paramName]) { matchCount++; return } matchCount = -1; return false }); if (matchCount < maxMatchCount) return; if (matchCount > maxMatchCount) { bestMatches.length = 0; maxMatchCount = matchCount } bestMatches.push(itemSrc) }); return bestMatches }; var preg_quote = function(str) { return (str + "").replace(/([\+\*\?\\\.\[\^\]\$\(\)\{\}\>\<\|\=\!\:])/g, "\\$1") }; var replaceAll = function(text, searchToken, replacementToken) { return text.replace(new RegExp("(" + preg_quote(searchToken) + ")", "gi"), replacementToken) }; var splitPair = function(raw) { switch (typeof raw) { case"string": return raw.split(/\s+/, 2); case"object": return [raw.x || raw.h, raw.y || raw.v]; case"number": return [raw]; default: return raw } }; var stringPairToObject = function(raw) { var pair = splitPair(raw), x = parseInt(pair && pair[0], 10), y = parseInt(pair && pair[1], 10); if (!isFinite(x)) x = 0; if (!isFinite(y)) y = x; return { x: x, y: y } }; function icontains(elem, text) { var result = false; $.each($(elem).contents(), function(index, content) { if (content.nodeType === 3 && (content.textContent || content.nodeValue || "").toLowerCase().indexOf((text || "").toLowerCase()) > -1) { result = true; return false } }); return result } $.expr[":"].dxicontains = $.expr.createPseudo(function(text) { return function(elem) { return icontains(elem, text) } }); function deepExtendArraySafe(target, changes) { var prevValue, newValue; for (var name in changes) { prevValue = target[name]; newValue = changes[name]; if (target === newValue) continue; if ($.isPlainObject(newValue) && !(newValue instanceof $.Event)) target[name] = deepExtendArraySafe($.isPlainObject(prevValue) ? prevValue : {}, newValue); else if (newValue !== undefined) target[name] = newValue } return target } function unwrapObservable(value) { if (DX.support.hasKo) return ko.utils.unwrapObservable(value); return value } DX.utils = { isDefined: isDefined, isString: isString, isNumber: isNumber, isObject: isObject, isArray: isArray, isDate: isDate, isFunction: isFunction, isExponential: isExponential, extendFromObject: extendFromObject, clone: clone, executeAsync: executeAsync, stringFormat: stringFormat, findBestMatches: findBestMatches, replaceAll: replaceAll, deepExtendArraySafe: deepExtendArraySafe, splitPair: splitPair, stringPairToObject: stringPairToObject, unwrapObservable: unwrapObservable } })(jQuery, DevExpress); /*! Module core, file utils.console.js */ (function($, DX, undefined) { var logger = function() { var console = window.console; function info(text) { if (!console || !$.isFunction(console.info)) return; console.info(text) } function warn(text) { if (!console || !$.isFunction(console.warn)) return; console.warn(text) } function error(text) { if (!console || !$.isFunction(console.error)) return; console.error(text) } return { info: info, warn: warn, error: error } }(); var debug = function() { function assert(condition, message) { if (!condition) throw new Error(message); } function assertParam(parameter, message) { assert(parameter !== null && parameter !== undefined, message) } return { assert: assert, assertParam: assertParam } }(); $.extend(DX.utils, { logger: logger, debug: debug }) })(jQuery, DevExpress); /*! Module core, file utils.math.js */ (function($, DX, undefined) { var PI = Math.PI, LN10 = Math.LN10; var cos = Math.cos, sin = Math.sin, abs = Math.abs, log = Math.log, floor = Math.floor, ceil = Math.ceil, max = Math.max, min = Math.min, isNaN = window.isNaN, Number = window.Number, NaN = window.NaN; var isNumber = DX.utils.isNumber, isExponential = DX.utils.isExponential; var getPrecision = function(value) { var stringFraction, stringValue = value.toString(), pointIndex = stringValue.indexOf('.'), startIndex, precision; if (isExponential(value)) { precision = getDecimalOrder(value); if (precision < 0) return Math.abs(precision); else return 0 } if (pointIndex !== -1) { startIndex = pointIndex + 1; stringFraction = stringValue.substring(startIndex, startIndex + 20); return stringFraction.length } return 0 }; var getLog = function(value, base) { if (!value) return 0; return Math.log(value) / Math.log(base) }; var raiseTo = function(power, base) { return Math.pow(base, power) }; var sign = function(value) { if (value === 0) return 0; return value / abs(value) }; var normalizeAngle = function(angle) { return (angle % 360 + 360) % 360 }; var convertAngleToRendererSpace = function(angle) { return 90 - angle }; var degreesToRadians = function(value) { return PI * value / 180 }; var getCosAndSin = function(angle) { var angleInRadians = degreesToRadians(angle); return { cos: cos(angleInRadians), sin: sin(angleInRadians) } }; var DECIMAL_ORDER_THRESHOLD = 1E-14; var getDecimalOrder = function(number) { var n = abs(number), cn; if (!isNaN(n)) { if (n > 0) { n = log(n) / LN10; cn = ceil(n); return cn - n < DECIMAL_ORDER_THRESHOLD ? cn : floor(n) } return 0 } return NaN }; var getAppropriateFormat = function(start, end, count) { var order = max(getDecimalOrder(start), getDecimalOrder(end)), precision = -getDecimalOrder(abs(end - start) / count), format; if (!isNaN(order) && !isNaN(precision)) { if (abs(order) <= 4) { format = 'fixedPoint'; precision < 0 && (precision = 0); precision > 4 && (precision = 4) } else { format = 'exponential'; precision += order - 1; precision > 3 && (precision = 3) } return { format: format, precision: precision } } return null }; var getFraction = function(value) { var valueString, dotIndex; if (isNumber(value)) { valueString = value.toString(); dotIndex = valueString.indexOf('.'); if (dotIndex >= 0) if (isExponential(value)) return valueString.substr(dotIndex + 1, valueString.indexOf('e') - dotIndex - 1); else { valueString = value.toFixed(20); return valueString.substr(dotIndex + 1, valueString.length - dotIndex + 1) } } return '' }; var getSignificantDigitPosition = function(value) { var fraction = getFraction(value), i; if (fraction) for (i = 0; i < fraction.length; i++) if (fraction.charAt(i) !== '0') return i + 1; return 0 }; var adjustValue = function(value) { var fraction = getFraction(value), nextValue, i; if (fraction) for (i = 1; i <= fraction.length; i++) { nextValue = roundValue(value, i); if (nextValue !== 0 && fraction[i - 2] && fraction[i - 1] && fraction[i - 2] === fraction[i - 1]) return nextValue } return value }; var roundValue = function(value, precision) { if (precision > 20) precision = 20; if (isNumber(value)) if (isExponential(value)) return Number(value.toExponential(precision)); else return Number(value.toFixed(precision)) }; var applyPrecisionByMinDelta = function(min, delta, value) { var minPrecision = getPrecision(min), deltaPrecision = getPrecision(delta); return roundValue(value, minPrecision < deltaPrecision ? deltaPrecision : minPrecision) }; $.extend(DX.utils, { getLog: getLog, raiseTo: raiseTo, sign: sign, normalizeAngle: normalizeAngle, convertAngleToRendererSpace: convertAngleToRendererSpace, degreesToRadians: degreesToRadians, getCosAndSin: getCosAndSin, getDecimalOrder: getDecimalOrder, getAppropriateFormat: getAppropriateFormat, getFraction: getFraction, adjustValue: adjustValue, roundValue: roundValue, applyPrecisionByMinDelta: applyPrecisionByMinDelta, getSignificantDigitPosition: getSignificantDigitPosition }); DX.utils.getPrecision = getPrecision })(jQuery, DevExpress); /*! Module core, file utils.date.js */ (function($, DX, undefined) { var isObject = DX.utils.isObject, isString = DX.utils.isString, isDate = DX.utils.isDate, 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 } }; function parseISO8601(isoString) { var result = new Date(0); var chunks = isoString.replace("Z", "").split("T"), date = String(chunks[0]).split("-"), time = String(chunks[1]).split(":"); var year, month, day, hours, minutes, seconds, milliseconds; year = Number(date[0]); month = Number(date[1]) - 1; day = Number(date[2]); result.setDate(day); result.setMonth(month); result.setFullYear(year); if (time.length) { hours = Number(time[0]); minutes = Number(time[1]); seconds = Number(String(time[2]).split(".")[0]); milliseconds = Number(String(time[2]).split(".")[1]) || 0; result.setHours(hours); result.setMinutes(minutes); result.setSeconds(seconds); result.setMilliseconds(milliseconds) } return result } function formatISO8601(date) { function pad(n) { if (n < 10) return "0".concat(n); return String(n) } return [date.getFullYear(), "-", pad(date.getMonth() + 1), "-", pad(date.getDate()), "T", pad(date.getHours()), ":", pad(date.getMinutes()), ":", pad(date.getSeconds()), "Z"].join("") } var convertMillisecondsToDateUnits = function(value) { var i, dateUnitCount, dateUnitInterval, dateUnitIntervals = ['millisecond', 'second', 'minute', 'hour', 'day', 'month', 'year'], result = {}; for (i = dateUnitIntervals.length - 1; i >= 0; i--) { dateUnitInterval = dateUnitIntervals[i]; dateUnitCount = Math.floor(value / toMilliseconds(dateUnitInterval)); if (dateUnitCount > 0) { result[dateUnitInterval + 's'] = dateUnitCount; value -= convertDateUnitToMilliseconds(dateUnitInterval, dateUnitCount) } } return result }; var convertDateTickIntervalToMilliseconds = function(tickInterval) { var milliseconds = 0; if (isObject(tickInterval)) $.each(tickInterval, function(key, value) { milliseconds += convertDateUnitToMilliseconds(key.substr(0, key.length - 1), value) }); if (isString(tickInterval)) milliseconds = convertDateUnitToMilliseconds(tickInterval, 1); return milliseconds }; var convertDateUnitToMilliseconds = function(dateUnit, count) { return toMilliseconds(dateUnit) * count }; var getDateUnitInterval = function(tickInterval) { var maxInterval = -1, i; if (isString(tickInterval)) return tickInterval; if (isObject(tickInterval)) { $.each(tickInterval, function(key, value) { for (i = 0; i < dateUnitIntervals.length; i++) if (value && (key === dateUnitIntervals[i] + 's' || key === dateUnitIntervals[i]) && maxInterval < i) maxInterval = i }); return dateUnitIntervals[maxInterval] } return '' }; var correctDateWithUnitBeginning = function(date, dateInterval) { var dayMonth, firstQuarterMonth, dateUnitInterval = getDateUnitInterval(dateInterval); switch (dateUnitInterval) { case'second': date.setMilliseconds(0); break; case'minute': date.setSeconds(0, 0); break; case'hour': date.setMinutes(0, 0, 0); break; case'year': date.setMonth(0); case'month': date.setDate(1); case'day': date.setHours(0, 0, 0, 0); break; case'week': dayMonth = date.getDate(); if (date.getDay() !== 0) dayMonth += 7 - date.getDay(); date.setDate(dayMonth); date.setHours(0, 0, 0, 0); break; case'quarter': firstQuarterMonth = DX.formatHelper.getFirstQuarterMonth(date.getMonth()); if (date.getMonth() !== firstQuarterMonth) date.setMonth(firstQuarterMonth); date.setDate(1); date.setHours(0, 0, 0, 0); break } }; var getDatesDifferences = function(date1, date2) { var differences, counter = 0; differences = { year: date1.getFullYear() !== date2.getFullYear(), month: date1.getMonth() !== date2.getMonth(), day: date1.getDate() !== date2.getDate(), hour: date1.getHours() !== date2.getHours(), minute: date1.getMinutes() !== date2.getMinutes(), second: date1.getSeconds() !== date2.getSeconds() }; $.each(differences, function(key, value) { if (value) counter++ }); differences.count = counter; return differences }; var addInterval = function(value, interval, isNegative) { var result = null, intervalObject; if (isDate(value)) { intervalObject = isString(interval) ? getDateIntervalByString(interval.toLowerCase()) : interval; result = new Date(value.getTime()); if (intervalObject.years) result.setFullYear(addSubValues(result.getFullYear(), intervalObject.years, isNegative)); if (intervalObject.quarters) result.setMonth(addSubValues(result.getMonth(), 3 * intervalObject.quarters, isNegative)); if (intervalObject.months) result.setMonth(addSubValues(result.getMonth(), intervalObject.months, isNegative)); if (intervalObject.weeks) result.setDate(addSubValues(result.getDate(), 7 * intervalObject.weeks, isNegative)); if (intervalObject.days) result.setDate(addSubValues(result.getDate(), intervalObject.days, isNegative)); if (intervalObject.hours) result.setHours(addSubValues(result.getHours(), intervalObject.hours, isNegative)); if (intervalObject.minutes) result.setMinutes(addSubValues(result.getMinutes(), intervalObject.minutes, isNegative)); if (intervalObject.seconds) result.setSeconds(addSubValues(result.getSeconds(), intervalObject.seconds, isNegative)); if (intervalObject.milliseconds) result.setMilliseconds(addSubValues(value.getMilliseconds(), intervalObject.milliseconds, isNegative)) } else result = addSubValues(value, interval, isNegative); return result }; var getDateIntervalByString = function(intervalString) { var result = {}; switch (intervalString) { case'year': result.years = 1; break; case'month': result.months = 1; break; case'quarter': result.months = 3; break; case'week': result.days = 7; break; case'day': result.days = 1; break; case'hour': result.hours = 1; break; case'minute': result.minutes = 1; break; case'second': result.seconds = 1; break; case'millisecond': result.milliseconds = 1; break } return result }; var sameMonthAndYear = function(date1, date2) { return date1 && date2 && date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth() }; var getFirstMonthDate = function(date) { return new Date(date.getFullYear(), date.getMonth(), 1) }; var dateInRange = function(date, min, max) { return normalizeDate(date, min, max) === date }; var normalizeDate = function(date, min, max) { var normalizedDate = date; if (isDefined(min) && date < min) normalizedDate = min; if (isDefined(max) && date > max) normalizedDate = max; return normalizedDate }; var getPower = function(value) { return value.toExponential().split("e")[1] }; $.extend(DX.utils, { dateUnitIntervals: dateUnitIntervals, parseIso8601Date: parseISO8601, formatIso8601Date: formatISO8601, convertMillisecondsToDateUnits: convertMillisecondsToDateUnits, convertDateTickIntervalToMilliseconds: convertDateTickIntervalToMilliseconds, convertDateUnitToMilliseconds: convertDateUnitToMilliseconds, getDateUnitInterval: getDateUnitInterval, getDatesDifferences: getDatesDifferences, correctDateWithUnitBeginning: correctDateWithUnitBeginning, addInterval: addInterval, getDateIntervalByString: getDateIntervalByString, sameMonthAndYear: sameMonthAndYear, getFirstMonthDate: getFirstMonthDate, dateInRange: dateInRange, normalizeDate: normalizeDate, getPower: getPower }) })(jQuery, DevExpress); /*! Module core, file utils.dom.js */ (function($, DX, undefined) { var IOS_APP_BAR_HEIGHT = "20px"; var timeRedrawOnResize = 100; var createResizeHandler = function(callback) { var $window = $(window), timeout; var debug_callback = arguments[1]; var handler = function() { var width = $window.width(), height = $window.height(); clearTimeout(timeout); timeout = setTimeout(function() { $window.width() === width && $window.height() === height && callback(); debug_callback && debug_callback() }, timeRedrawOnResize) }; handler.stop = function() { clearTimeout(timeout); return this }; return handler }; var windowResizeCallbacks = function() { var prevSize, callbacks = $.Callbacks(), jqWindow = $(window), resizeEventHandlerAttached = false, originalCallbacksAdd = callbacks.add, originalCallbacksRemove = callbacks.remove; var formatSize = function() { return [jqWindow.width(), jqWindow.height()].join() }; var handleResize = function() { var now = formatSize(); if (now === prevSize) return; prevSize = now; setTimeout(callbacks.fire) }; prevSize = formatSize(); callbacks.add = function() { var result = originalCallbacksAdd.apply(callbacks, arguments); if (!resizeEventHandlerAttached && callbacks.has()) { jqWindow.on("resize", handleResize); resizeEventHandlerAttached = true } return result }; callbacks.remove = function() { var result = originalCallbacksRemove.apply(callbacks, arguments); if (!callbacks.has() && resizeEventHandlerAttached) { jqWindow.off("resize", handleResize); resizeEventHandlerAttached = false } return result }; return callbacks }(); var resetActiveElement = function() { var activeElement = document.activeElement; if (activeElement && activeElement !== document.body && activeElement.blur) activeElement.blur() }; var createMarkupFromString = function(str) { var tempElement = $("
"); if (window.WinJS) WinJS.Utilities.setInnerHTMLUnsafe(tempElement.get(0), str); else tempElement.append(str); return tempElement.contents() }; var initMobileViewport = function(options) { options = $.extend({}, options); var device = DX.devices.current(); var realDevice = DX.devices.real(); var allowZoom = options.allowZoom, allowPan = options.allowPan, allowSelection = "allowSelection" in options ? options.allowSelection : device.platform == "desktop"; DX.overlayTargetContainer(".dx-viewport"); var metaSelector = "meta[name=viewport]"; if (!$(metaSelector).length) $("").attr("name", "viewport").appendTo("head"); var metaVerbs = ["width=device-width"], msTouchVerbs = []; if (allowZoom) msTouchVerbs.push("pinch-zoom"); else metaVerbs.push("initial-scale=1.0", "maximum-scale=1.0, user-scalable=no"); if (allowPan) msTouchVerbs.push("pan-x", "pan-y"); if (!allowPan && !allowZoom) $("html, body").css({ "-ms-content-zooming": "none", "-ms-user-select": "none", overflow: "hidden" }); else $("html").css("-ms-overflow-style", "-ms-autohiding-scrollbar"); if (!allowSelection) { if (realDevice.ios) $(document).on("selectstart", function() { return false }); $(".dx-viewport").css("user-select", "none") } $(metaSelector).attr("content", metaVerbs.join()); $("html").css("-ms-touch-action", msTouchVerbs.join(" ") || "none"); if (DX.support.touch) $(document).off(".dxInitMobileViewport").on("touchmove.dxInitMobileViewport", function(e) { var count = e.originalEvent.touches.length, zoomDisabled = !allowZoom && count > 1, panDisabled = !allowPan && count === 1 && !e.isScrollingEvent; if (zoomDisabled || panDisabled) e.preventDefault() }); realDevice = DX.devices.real(); if (realDevice.ios) { var isPhoneGap = document.location.protocol === "file:"; if (!isPhoneGap) windowResizeCallbacks.add(function() { var windowWidth = $(window).width(); $("body").width(windowWidth) }); else if (realDevice.version[0] > 6) { $(".dx-viewport").css("position", "relative"); $("body").css({"box-sizing": "border-box"}); $("body").css("padding-top", IOS_APP_BAR_HEIGHT); if (realDevice.version[0] === 7 && realDevice.version[1] < 1) { var setDeviceHeight = function() { var deviceHeight = "height=device-" + (Math.abs(window.orientation) === 90 ? "width" : "height"); $(metaSelector).attr("content", metaVerbs.join() + "," + deviceHeight) }; $(window).on("orientationchange", setDeviceHeight); setDeviceHeight() } } } }; var triggerVisibilityChangeEvent = function(event) { return function(element) { $(element || "body").find(".dx-visibility-change-handler").each(function() { $(this).triggerHandler(event) }) } }; $.extend(DX.utils, { createResizeHandler: createResizeHandler, windowResizeCallbacks: windowResizeCallbacks, resetActiveElement: resetActiveElement, createMarkupFromString: createMarkupFromString, triggerShownEvent: triggerVisibilityChangeEvent("dxshown"), triggerHidingEvent: triggerVisibilityChangeEvent("dxhiding"), initMobileViewport: initMobileViewport }); DX.utils.__timeRedrawOnResize = timeRedrawOnResize })(jQuery, DevExpress); /*! Module core, file utils.graphics.js */ (function($, DX, undefined) { var isFunction = DX.utils.isFunction, iDevice = /iphone|ipad/.test(navigator.userAgent.toLowerCase()); var processSeriesTemplate = function(seriesTemplate, items) { var customizeSeries = isFunction(seriesTemplate.customizeSeries) ? seriesTemplate.customizeSeries : $.noop, nameField = seriesTemplate.nameField || 'series', generatedSeries = {}, seriesOrder = [], series; for (var i = 0, length = items.length; i < length; i++) { var data = items[i]; if (nameField in data) { series = generatedSeries[data[nameField]]; if (!series) { series = generatedSeries[data[nameField]] = { name: data[nameField], data: [] }; seriesOrder.push(series.name) } series.data.push(data) } } return $.map(seriesOrder, function(orderedName) { var group = generatedSeries[orderedName], seriesOptions = customizeSeries.call(null, group.name); return $.extend(group, seriesOptions) }) }; var getNextDefsSvgId = function() { var numDefsSvgElements = 1; return function() { return 'DevExpress_' + numDefsSvgElements++ } }(); var getRootOffset = function(renderer) { var node, result = { left: 0, top: 0 }, pointTransform, root = renderer.getRoot(); if (root) { node = root.element; if (node.getScreenCTM && !iDevice) { var ctm = node.getScreenCTM(); if (ctm) { pointTransform = node.createSVGPoint().matrixTransform(ctm); result.left = pointTransform.x + (document.body.scrollLeft || document.documentElement.scrollLeft); result.top = pointTransform.y + (document.body.scrollTop || document.documentElement.scrollTop) } else { result.left = document.body.scrollLeft || document.documentElement.scrollLeft; result.top = document.body.scrollTop || document.documentElement.scrollTop } } else result = $(node).offset() } return result }; $.extend(DX.utils, { processSeriesTemplate: processSeriesTemplate, getNextDefsSvgId: getNextDefsSvgId, getRootOffset: getRootOffset }) })(jQuery, DevExpress); /*! Module core, file utils.arrays.js */ (function($, DX, undefined) { var wrapToArray = function(entity) { return $.isArray(entity) ? entity : [entity] }; var removeDublicates = function(from, what) { if (!$.isArray(from) || from.length === 0) return []; if (!$.isArray(what) || what.length === 0) return from.slice(); var result = []; $.each(from, function(_, value) { var bIndex = $.inArray(value, what); if (bIndex === -1) result.push(value) }); return result }; $.extend(DX.utils, { wrapToArray: wrapToArray, removeDublicates: removeDublicates }) })(jQuery, DevExpress); /*! Module core, file devices.js */ (function($, DX, undefined) { var KNOWN_UA_TABLE = { iPhone: "iPhone", iPhone5: "iPhone 5", iPad: "iPad", iPadMini: "iPad Mini", androidPhone: "Android Mobile", androidTablet: "Android", win8: "MSAppHost", win8Phone: "Windows Phone 8", msSurface: "MSIE ARM Tablet PC", desktop: "desktop", tizen: "Tizen Mobile" }; var DEFAULT_DEVICE = { deviceType: "", platform: "", version: [], phone: false, tablet: false, android: false, ios: false, win8: false, tizen: false, generic: false }; var GENERIC_DEVICE = $.extend(DEFAULT_DEVICE, { platform: "generic", deviceType: "desktop", generic: true }); var uaParsers = { win8: function(userAgent) { var isPhone = /windows phone/i.test(userAgent), isTablet = !isPhone && /arm(.*)trident/i.test(userAgent), isDesktop = !isPhone && !isTablet && /msapphost/i.test(userAgent); if (!(isPhone || isTablet || isDesktop)) return; var matches = userAgent.match(/windows phone (\d+).(\d+)/i) || userAgent.match(/windows nt (\d+).(\d+)/i), version = matches ? [parseInt(matches[1], 10), parseInt(matches[2], 10)] : []; return { deviceType: isPhone ? "phone" : isTablet ? "tablet" : "desktop", platform: "win8", version: version } }, ios: function(userAgent) { if (!/ip(hone|od|ad)/i.test(userAgent)) return; var isPhone = /ip(hone|od)/i.test(userAgent); var matches = userAgent.match(/os (\d+)_(\d+)_?(\d+)?/i); var version = matches ? [parseInt(matches[1], 10), parseInt(matches[2], 10), parseInt(matches[3] || 0, 10)] : []; return { deviceType: isPhone ? "phone" : "tablet", platform: "ios", version: version } }, android: function(userAgent) { if (!/android|htc_|silk/i.test(userAgent)) return; var isPhone = /mobile/i.test(userAgent); var matches = userAgent.match(/android (\d+)\.(\d+)\.?(\d+)?/i); var version = matches ? [parseInt(matches[1], 10), parseInt(matches[2], 10), parseInt(matches[3] || 0, 10)] : []; return { deviceType: isPhone ? "phone" : "tablet", platform: "android", version: version } }, tizen: function(userAgent) { if (!/tizen/i.test(userAgent)) return; var isPhone = /mobile/i.test(userAgent); var matches = userAgent.match(/tizen (\d+)\.(\d+)/i); var version = matches ? [parseInt(matches[1], 10), parseInt(matches[2], 10)] : []; return { deviceType: isPhone ? "phone" : "tablet", platform: "tizen", version: version } } }; DX.Devices = DX.Class.inherit({ ctor: function(options) { this._window = options && options.window || window; this._realDevice = this._getDevice(); this._currentDevice = undefined; this._currentOrientation = undefined; this.orientationChanged = $.Callbacks(); this._recalculateOrientation(); DX.utils.windowResizeCallbacks.add($.proxy(this._recalculateOrientation, this)) }, current: function(deviceOrName) { if (deviceOrName) { this._currentDevice = this._getDevice(deviceOrName); DX.ui.themes.init({_autoInit: true}) } else { if (!this._currentDevice) { deviceOrName = undefined; try { deviceOrName = this._getDeviceOrNameFromWindowScope() } catch(e) { deviceOrName = this._getDeviceNameFromSessionStorage() } finally { if (!deviceOrName) deviceOrName = this._getDeviceNameFromSessionStorage() } this._currentDevice = this._getDevice(deviceOrName) } return this._currentDevice } }, real: function() { var forceDevice = arguments[0]; if ($.isPlainObject(forceDevice)) { $.extend(this._realDevice, forceDevice); return } return $.extend({}, this._realDevice) }, orientation: function() { return this._currentOrientation }, isRippleEmulator: function() { return !!this._window.tinyHippos }, attachCssClasses: function(element, device) { var realDevice = this._realDevice, $element = $(element); device = device || this.current(); if (device.deviceType) $element.addClass("dx-device-" + device.deviceType); $element.addClass("dx-device-" + realDevice.platform); if (realDevice.version && realDevice.version.length) $element.addClass("dx-device-" + realDevice.platform + "-" + realDevice.version[0]); if (DX.devices.isSimulator()) $element.addClass("dx-simulator"); if (DX.rtlEnabled) $element.addClass("dx-rtl") }, isSimulator: function() { try { return this._isSimulator || this._window.top !== this._window.self && this._window.top["dx-force-device"] || this.isRippleEmulator() } catch(e) { return false } }, forceSimulator: function() { this._isSimulator = true }, _getDevice: function(deviceName) { if (deviceName === "genericPhone") deviceName = { deviceType: "phone", platform: "generic", generic: true }; if ($.isPlainObject(deviceName)) return this._fromConfig(deviceName); else { var ua; if (deviceName) { ua = KNOWN_UA_TABLE[deviceName]; if (!ua) throw Error("Unknown device"); } else ua = navigator.userAgent; return this._fromUA(ua) } }, _getDeviceOrNameFromWindowScope: function() { var result; if (this._window.top["dx-force-device-object"] || this._window.top["dx-force-device"]) result = this._window.top["dx-force-device-object"] || this._window.top["dx-force-device"]; return result }, _getDeviceNameFromSessionStorage: function() { return this._window.sessionStorage && (sessionStorage.getItem("dx-force-device") || sessionStorage.getItem("dx-simulator-device")) }, _fromConfig: function(config) { var shortcuts = { phone: config.deviceType === "phone", tablet: config.deviceType === "tablet", android: config.platform === "android", ios: config.platform === "ios", win8: config.platform === "win8", tizen: config.platform === "tizen", generic: config.platform === "generic" }; return $.extend({}, DEFAULT_DEVICE, this._currentDevice, shortcuts, config) }, _fromUA: function(ua) { var config; $.each(uaParsers, function(platform, parser) { config = parser(ua); return !config }); if (config) return this._fromConfig(config); return GENERIC_DEVICE }, _changeOrientation: function() { var $window = $(this._window), orientation = $window.height() > $window.width() ? "portrait" : "landscape"; if (this._currentOrientation === orientation) return; this._currentOrientation = orientation; this.orientationChanged.fire({orientation: orientation}) }, _recalculateOrientation: function() { var windowWidth = $(this._window).width(); if (this._currentWidth === windowWidth) return; this._currentWidth = windowWidth; this._changeOrientation() } }); DX.devices = new DX.Devices })(jQuery, DevExpress); /*! Module core, file browser.js */ (function($, DX, global, undefined) { var webkitRegExp = /(webkit)[ \/]([\w.]+)/, operaRegExp = /(opera)(?:.*version)?[ \/]([\w.]+)/, ieRegExp = /(msie) (\d{1,2}\.\d)/, ie11RegExp = /(trident).*rv:(\d{1,2}\.\d)/, mozillaRegExp = /(mozilla)(?:.*? rv:([\w.]+))?/; var ua = navigator.userAgent.toLowerCase(); var browser = function() { var result = {}, matches = webkitRegExp.exec(ua) || operaRegExp.exec(ua) || ieRegExp.exec(ua) || ie11RegExp.exec(ua) || ua.indexOf("compatible") < 0 && mozillaRegExp.exec(ua) || [], browserName = matches[1], browserVersion = matches[2]; if (browserName === "trident") browserName = "msie"; if (browserName) { result[browserName] = true; result.version = browserVersion } return result }(); DX.browser = browser })(jQuery, DevExpress, this); /*! Module core, file support.js */ (function($, DX, window) { var cssPrefixes = ["", "Webkit", "Moz", "O", "ms"], styles = document.createElement("dx").style; var transitionEndEventNames = { WebkitTransition: 'webkitTransitionEnd', MozTransition: 'transitionend', OTransition: 'oTransitionEnd', msTransition: 'MsTransitionEnd', transition: 'transitionend' }; var styleProp = function(prop) { prop = DX.inflector.camelize(prop, true); for (var i = 0, cssPrefixesCount = cssPrefixes.length; i < cssPrefixesCount; i++) { var specific = cssPrefixes[i] + prop; if (specific in styles) return specific } }; var supportProp = function(prop) { return !!styleProp(prop) }; var isNativeScrollingSupported = function(device) { var realDevice = DX.devices.real(), realPlatform = realDevice.platform, realVersion = realDevice.version, isObsoleteAndroid = realVersion && realVersion[0] < 4 && realPlatform === "android", isNativeScrollDevice = !isObsoleteAndroid && $.inArray(realPlatform, ["ios", "android", "win8"]) > -1; return isNativeScrollDevice }; DX.support = { touch: "ontouchstart" in window || !!window.navigator.msMaxTouchPoints, pointer: window.navigator.pointerEnabled || window.navigator.msPointerEnabled, transform3d: supportProp("transform"), transition: supportProp("transition"), transitionEndEventName: transitionEndEventNames[styleProp("transition")], animation: supportProp("animation"), nativeScrolling: isNativeScrollingSupported(), winJS: "WinJS" in window, styleProp: styleProp, supportProp: supportProp, hasKo: !!window.ko, hasNg: !window.ko && !!window.angular, inputType: function(type) { if (type === "text") return true; var input = document.createElement("input"); try { input.setAttribute("type", type); input.value = "wrongValue"; return !input.value } catch(e) { return false } } } })(jQuery, DevExpress, this); /*! Module core, file position.js */ (function($, DX, undefined) { var horzRe = /left|right/, vertRe = /top|bottom/, collisionRe = /fit|flip|none/; var normalizeAlign = function(raw) { var result = { h: "center", v: "center" }; var pair = DX.utils.splitPair(raw); if (pair) $.each(pair, function() { var w = String(this).toLowerCase(); if (horzRe.test(w)) result.h = w; else if (vertRe.test(w)) result.v = w }); return result }; var normalizeOffset = function(raw) { var values = DX.utils.stringPairToObject(raw); return { h: values.x, v: values.y } }; var normalizeCollision = function(raw) { var pair = DX.utils.splitPair(raw), h = String(pair && pair[0]).toLowerCase(), v = String(pair && pair[1]).toLowerCase(); if (!collisionRe.test(h)) h = "none"; if (!collisionRe.test(v)) v = h; return { h: h, v: v } }; var getAlignFactor = function(align) { switch (align) { case"center": return 0.5; case"right": case"bottom": return 1; default: return 0 } }; var inverseAlign = function(align) { switch (align) { case"left": return "right"; case"right": return "left"; case"top": return "bottom"; case"bottom": return "top"; default: return align } }; var calculateOversize = function(data, bounds) { var oversize = 0; if (data.myLocation < bounds.min) oversize += bounds.min - data.myLocation; if (data.myLocation > bounds.max) oversize += data.myLocation - bounds.max; return oversize }; var initMyLocation = function(data) { data.myLocation = data.atLocation + getAlignFactor(data.atAlign) * data.atSize - getAlignFactor(data.myAlign) * data.mySize + data.offset }; var decolliders = { fit: function(data, bounds) { var result = false; if (data.myLocation > bounds.max) { data.myLocation = bounds.max; result = true } if (data.myLocation < bounds.min) { data.myLocation = bounds.min; result = true } return result }, flip: function(data, bounds) { if (data.myAlign === "center" && data.atAlign === "center") return false; if (data.myLocation < bounds.min || data.myLocation > bounds.max) { var inverseData = $.extend({}, data, { myAlign: inverseAlign(data.myAlign), atAlign: inverseAlign(data.atAlign), offset: -data.offset }); initMyLocation(inverseData); inverseData.oversize = calculateOversize(inverseData, bounds); if (inverseData.myLocation >= bounds.min && inverseData.myLocation <= bounds.max || inverseData.myLocation > data.myLocation || inverseData.oversize < data.oversize) { data.myLocation = inverseData.myLocation; data.oversize = inverseData.oversize; return true } } return false } }; var scrollbarWidth; var defaultPositionResult = { h: { location: 0, flip: false, fit: false, oversize: 0 }, v: { location: 0, flip: false, fit: false, oversize: 0 } }; var calculatePosition = function(what, options) { var $what = $(what), currentOffset = $what.offset(), result = $.extend(true, {}, defaultPositionResult, { h: {location: currentOffset.left}, v: {location: currentOffset.top} }); if (!options) return result; var my = normalizeAlign(options.my), at = normalizeAlign(options.at), of = options.of || window, offset = normalizeOffset(options.offset), collision = normalizeCollision(options.collision), boundaryOffset = normalizeOffset(options.boundaryOffset); var h = { mySize: $what.outerWidth(), myAlign: my.h, atAlign: at.h, offset: offset.h, collision: collision.h, boundaryOffset: boundaryOffset.h }; var v = { mySize: $what.outerHeight(), myAlign: my.v, atAlign: at.v, offset: offset.v, collision: collision.v, boundaryOffset: boundaryOffset.v }; if (of.preventDefault) { h.atLocation = of.pageX; v.atLocation = of.pageY; h.atSize = 0; v.atSize = 0 } else { of = $(of); if ($.isWindow(of[0])) { h.atLocation = of.scrollLeft(); v.atLocation = of.scrollTop(); h.atSize = of.width(); v.atSize = of.height() } else if (of[0].nodeType === 9) { h.atLocation = 0; v.atLocation = 0; h.atSize = of.width(); v.atSize = of.height() } else { var o = of.offset(); h.atLocation = o.left; v.atLocation = o.top; h.atSize = of.outerWidth(); v.atSize = of.outerHeight() } } initMyLocation(h); initMyLocation(v); var bounds = function() { var win = $(window), windowWidth = win.width(), windowHeight = win.height(), left = win.scrollLeft(), top = win.scrollTop(), hScrollbar = document.width > document.documentElement.clientWidth, vScrollbar = document.height > document.documentElement.clientHeight, hZoomLevel = DX.support.touch ? document.documentElement.clientWidth / (vScrollbar ? windowWidth - scrollbarWidth : windowWidth) : 1, vZoomLevel = DX.support.touch ? document.documentElement.clientHeight / (hScrollbar ? windowHeight - scrollbarWidth : windowHeight) : 1; if (scrollbarWidth === undefined) scrollbarWidth = calculateScrollbarWidth(); return { h: { min: left + h.boundaryOffset, max: left + windowWidth / hZoomLevel - h.mySize - h.boundaryOffset }, v: { min: top + v.boundaryOffset, max: top + windowHeight / vZoomLevel - v.mySize - v.boundaryOffset } } }(); h.oversize = calculateOversize(h, bounds.h); v.oversize = calculateOversize(v, bounds.v); if (decolliders[h.collision]) result.h[h.collision] = decolliders[h.collision](h, bounds.h); if (decolliders[v.collision]) result.v[v.collision] = decolliders[v.collision](v, bounds.v); $.extend(true, result, { h: { location: Math.round(h.myLocation), oversize: Math.round(h.oversize) }, v: { location: Math.round(v.myLocation), oversize: Math.round(v.oversize) } }); return result }; var position = function(what, options) { var $what = $(what); if (!options) return $what.offset(); DX.translator.resetPosition($what); var offset = $what.offset(), targetPosition = options.h && options.v ? options : calculatePosition($what, options); DX.translator.move($what, { left: Math.round(targetPosition.h.location - offset.left), top: Math.round(targetPosition.v.location - offset.top) }); return targetPosition }; $.extend(DX, { calculatePosition: calculatePosition, position: position, inverseAlign: inverseAlign }); var calculateScrollbarWidth = function() { var $scrollDiv = $("
").css({ width: 100, height: 100, overflow: "scroll", position: "absolute", top: -9999 }).appendTo($("body")), result = $scrollDiv.get(0).offsetWidth - $scrollDiv.get(0).clientWidth; $scrollDiv.remove(); return result } })(jQuery, DevExpress); /*! Module core, file action.js */ (function($, DX, undefined) { var actionExecutors = {}; var registerExecutor = function(name, executor) { if ($.isPlainObject(name)) { $.each(name, registerExecutor); return } actionExecutors[name] = executor }; var unregisterExecutor = function(name) { var args = $.makeArray(arguments); $.each(args, function() { delete actionExecutors[this] }) }; registerExecutor({ func: {execute: function(e) { if ($.isFunction(e.action)) { e.result = e.action.apply(e.context, e.args); e.handled = true } }}, url: {execute: function(e) { if (typeof e.action === "string" && e.action.charAt(0) !== "#") document.location = e.action }}, hash: {execute: function(e) { if (typeof e.action === "string" && e.action.charAt(0) === "#") document.location.hash = e.action }} }); var Action = DX.Class.inherit({ ctor: function(action, config) { config = config || {}; this._action = action || $.noop; this._context = config.context || window; this._beforeExecute = config.beforeExecute || $.noop; this._afterExecute = config.afterExecute || $.noop; this._component = config.component; this._excludeValidators = config.excludeValidators; 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 result, position, finalPosition; if (support.transform3d) { var translate = getTranslate($element); result = { left: translate.x, top: translate.y } } else { var originalTop = $element.css("top"), originalLeft = $element.css("left"); position = $element.position(); $element.css({ transform: "none", top: 0, left: 0 }); clearCache($element); finalPosition = $element.position(); result = { left: position.left - finalPosition.left || parseInt(originalLeft) || 0, top: position.top - finalPosition.top || parseInt(originalTop) || 0 }; $element.css({ top: originalTop, left: originalLeft }) } return result }; var move = function($element, position) { if (!support.transform3d) { $element.css(position); return } var translate = getTranslate($element), left = position.left, top = position.top; if (left !== undefined) translate.x = left || 0; if (top !== undefined) translate.y = top || 0; $element.css({transform: getTranslateCss(translate)}); if (isPersentValue(left) || isPersentValue(top)) clearCache($element) }; var isPersentValue = function(value) { return $.type(value) === "string" && value[value.length - 1] === "%" }; var getTranslate = function($element) { var result = $element.data(TRANSLATOR_DATA_KEY); if (!result) { var transformValue = $element.css("transform") || getTranslateCss({ x: 0, y: 0 }), matrix = transformValue.match(TRANSFORM_MATRIX_REGEX), is3D = matrix && matrix[1]; if (matrix) { matrix = matrix[2].split(","); if (is3D === "3d") matrix = matrix.slice(12, 15); else { matrix.push(0); matrix = matrix.slice(4, 7) } } else matrix = [0, 0, 0]; result = { x: parseFloat(matrix[0]), y: parseFloat(matrix[1]), z: parseFloat(matrix[2]) }; cacheTranslate($element, result) } return result }; var cacheTranslate = function($element, translate) { $element.data(TRANSLATOR_DATA_KEY, translate) }; var clearCache = function($element) { $element.removeData(TRANSLATOR_DATA_KEY) }; var resetPosition = function($element) { $element.css({ left: 0, top: 0, transform: "none" }); clearCache($element) }; var parseTranslate = function(translateString) { var result = translateString.match(TRANSLATE_REGEX); if (!result || !result[1]) return; result = result[1].split(","); result = { x: parseFloat(result[0]), y: parseFloat(result[1]), z: parseFloat(result[2]) }; return result }; var getTranslateCss = function(translate) { translate.x = translate.x || 0; translate.y = translate.y || 0; var xValueString = isPersentValue(translate.x) ? translate.x : translate.x + "px"; var yValueString = isPersentValue(translate.y) ? translate.y : translate.y + "px"; return "translate(" + xValueString + ", " + yValueString + ")" }; DX.translator = { move: move, locate: locate, clearCache: clearCache, parseTranslate: parseTranslate, getTranslate: getTranslate, getTranslateCss: getTranslateCss, resetPosition: resetPosition } })(jQuery, DevExpress); /*! Module core, file animationFrame.js */ (function($, DX, undefined) { var FRAME_ANIMATION_STEP_TIME = 1000 / 60, requestAnimationFrame = function(callback, element) { return this.setTimeout(callback, FRAME_ANIMATION_STEP_TIME) }, cancelAnimationFrame = function(requestID) { return this.clearTimeout(requestID) }, nativeRequestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame, nativeCancelAnimationFrame = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.oCancelAnimationFrame || window.msCancelAnimationFrame; if (nativeRequestAnimationFrame && nativeCancelAnimationFrame) { requestAnimationFrame = nativeRequestAnimationFrame; cancelAnimationFrame = nativeCancelAnimationFrame } if (nativeRequestAnimationFrame && !nativeCancelAnimationFrame) { var cancelledRequests = {}; requestAnimationFrame = function(callback) { var requestId = nativeRequestAnimationFrame.call(window, function() { try { if (requestId in cancelledRequests) return; callback.apply(this, arguments) } finally { delete cancelledRequests[requestId] } }); return requestId }; cancelAnimationFrame = function(requestId) { cancelledRequests[requestId] = true } } requestAnimationFrame = $.proxy(requestAnimationFrame, window); cancelAnimationFrame = $.proxy(cancelAnimationFrame, window); $.extend(DX, { requestAnimationFrame: requestAnimationFrame, cancelAnimationFrame: cancelAnimationFrame }) })(jQuery, DevExpress); /*! Module core, file animator.js */ (function($, DX, undefined) { DX.Animator = DX.Class.inherit({ ctor: function() { this._finished = true; this._stopped = false }, start: function() { this._stopped = false; this._finished = false; this._stepCore() }, stop: function() { this._stopped = true }, _stepCore: function() { if (this._isStopped()) { this._stop(); return } if (this._isFinished()) { this._finished = true; this._complete(); return } this._step(); DX.requestAnimationFrame.call(window, $.proxy(this._stepCore, this)) }, _step: DX.abstract, _isFinished: $.noop, _stop: $.noop, _complete: $.noop, _isStopped: function() { return this._stopped }, inProgress: function() { return !(this._stopped || this._finished) } }) })(jQuery, DevExpress); /*! Module core, file fx.js */ (function($, DX, undefined) { var translator = DX.translator, support = DX.support, transitionEndEventName = support.transitionEndEventName + ".dxFX"; var CSS_TRANSITION_EASING_REGEX = /cubic-bezier\((\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\)/, RELATIVE_VALUE_REGEX = /^([+-])=(.*)/i, ANIM_DATA_KEY = "dxAnimData", ANIM_QUEUE_KEY = "dxAnimQueue", TRANSFORM_PROP = "transform"; var TransitionAnimationStrategy = { animate: function($element, config) { var that = this, deferred = $.Deferred(); config.transitionAnimation = {finish: function() { that._cleanup($element, config); deferred.resolveWith($element, [config, $element]) }}; this._startAnimation($element, config); this._completeAnimationCallback($element, config).done(function() { config.transitionAnimation.finish() }); if (!config.duration) config.transitionAnimation.finish(); return deferred.promise() }, _completeAnimationCallback: function($element, config) { var startTime = $.now() + config.delay, deferred = $.Deferred(), transitionEndFired = $.Deferred(), simulatedTransitionEndFired = $.Deferred(); $element.one(transitionEndEventName, function(e) { if ($.now() - startTime >= config.duration) transitionEndFired.reject() }); config.transitionAnimation.simulatedEndEventTimer = setTimeout(function() { simulatedTransitionEndFired.reject() }, config.duration + config.delay); $.when(transitionEndFired, simulatedTransitionEndFired).fail($.proxy(function() { deferred.resolve() }, this)); return deferred.promise() }, _startAnimation: function($element, config) { $element.css("transform"); $element.css({ transitionProperty: "all", transitionDelay: config.delay + "ms", transitionDuration: config.duration + "ms", transitionTimingFunction: config.easing }); setProps($element, config.to) }, _cleanup: function($element, config) { $element.css("transition", "none").off(transitionEndEventName); clearTimeout(config.transitionAnimation.simulatedEndEventTimer) }, stop: function($element, config, jumpToEnd) { if (!config) return; if (jumpToEnd) config.transitionAnimation.finish(); else { $.each(config.to, function(key) { $element.css(key, $element.css(key)) }); this._cleanup($element, config) } } }; var FrameAnimationStrategy = { animate: function($element, config) { var deferred = $.Deferred(), that = this; if (!config) return deferred.reject().promise(); $.each(config.to, function(prop) { if (config.from[prop] === undefined) config.from[prop] = that._normalizeValue($element.css(prop)) }); if (config.to[TRANSFORM_PROP]) { config.from[TRANSFORM_PROP] = that._parseTransform(config.from[TRANSFORM_PROP]); config.to[TRANSFORM_PROP] = that._parseTransform(config.to[TRANSFORM_PROP]) } config.frameAnimation = { to: config.to, from: config.from, currentValue: config.from, easing: convertTransitionTimingFuncToJQueryEasing(config.easing), duration: config.duration, startTime: (new Date).valueOf(), finish: function() { this.currentValue = this.to; this.draw(); deferred.resolve() }, draw: function() { var currentValue = $.extend({}, this.currentValue); if (currentValue[TRANSFORM_PROP]) currentValue[TRANSFORM_PROP] = $.map(currentValue[TRANSFORM_PROP], function(value, prop) { if (prop === "translate") return translator.getTranslateCss(value); else if (prop === "scale") return "scale(" + value + ")"; else if (prop.substr(0, prop.length - 1) === "rotate") return prop + "(" + value + "deg)" }).join(" "); $element.css(currentValue) } }; if (config.delay) { config.frameAnimation.startTime += config.delay; config.frameAnimation.delayTimeout = setTimeout(function() { that._animationStep($element, config) }, config.delay) } else that._animationStep($element, config); return deferred.promise() }, _parseTransform: function(transformString) { var result = {}; $.each(transformString.match(/(\w|\d)+\([^\)]*\)\s*/g), function(i, part) { var translateData = translator.parseTranslate(part), scaleData = part.match(/scale\((.+?)\)/), rotateData = part.match(/(rotate.)\((.+)deg\)/); if (translateData) result.translate = translateData; if (scaleData && scaleData[1]) result.scale = parseFloat(scaleData[1]); if (rotateData && rotateData[1]) result[rotateData[1]] = parseFloat(rotateData[2]) }); return result }, stop: function($element, config, jumpToEnd) { var frameAnimation = config && config.frameAnimation; if (!frameAnimation) return; clearTimeout(frameAnimation.delayTimeout); if (jumpToEnd) frameAnimation.finish(); delete config.frameAnimation }, _animationStep: function($element, config) { var frameAnimation = config && config.frameAnimation; if (!frameAnimation) return; var now = (new Date).valueOf(); if (now >= frameAnimation.startTime + frameAnimation.duration) { frameAnimation.finish(); return } frameAnimation.currentValue = this._calcStepValue(frameAnimation, now - frameAnimation.startTime); frameAnimation.draw(); DX.requestAnimationFrame($.proxy(function() { this._animationStep($element, config) }, this)) }, _calcStepValue: function(frameAnimation, currentDuration) { var calcValueRecursively = function(from, to) { var result = $.isArray(to) ? [] : {}; var calcEasedValue = function(propName) { var x = currentDuration / frameAnimation.duration, t = currentDuration, b = 1 * from[propName], c = to[propName] - from[propName], d = frameAnimation.duration; return $.easing[frameAnimation.easing](x, t, b, c, d) }; $.each(to, function(propName, endPropValue) { if (typeof endPropValue === "string" && parseFloat(endPropValue, 10) === false) return true; result[propName] = typeof endPropValue === "object" ? calcValueRecursively(from[propName], endPropValue) : calcEasedValue(propName) }); return result }; return calcValueRecursively(frameAnimation.from, frameAnimation.to) }, _normalizeValue: function(value) { var numericValue = parseFloat(value, 10); if (numericValue === false) return value; return numericValue } }; var animationStrategies = { transition: support.transition ? TransitionAnimationStrategy : FrameAnimationStrategy, frame: FrameAnimationStrategy }; var getAnimationStrategy = function(config) { return animationStrategies[config && config.strategy || "transition"] }; var TransitionTimingFuncMap = { linear: "cubic-bezier(0, 0, 1, 1)", ease: "cubic-bezier(0.25, 0.1, 0.25, 1)", "ease-in": "cubic-bezier(0.42, 0, 1, 1)", "ease-out": "cubic-bezier(0, 0, 0.58, 1)", "ease-in-out": "cubic-bezier(0.42, 0, 0.58, 1)" }; var convertTransitionTimingFuncToJQueryEasing = function(cssTransitionEasing) { cssTransitionEasing = TransitionTimingFuncMap[cssTransitionEasing] || cssTransitionEasing; var bezCoeffs = cssTransitionEasing.match(CSS_TRANSITION_EASING_REGEX); if (!bezCoeffs) return "linear"; bezCoeffs = bezCoeffs.slice(1, 5); $.each(bezCoeffs, function(index, value) { bezCoeffs[index] = parseFloat(value) }); var easingName = "cubicbezier_" + bezCoeffs.join("_").replace(/\./g, "p"); if (!$.isFunction($.easing[easingName])) { var polynomBezier = function(x1, y1, x2, y2) { var Cx = 3 * x1, Bx = 3 * (x2 - x1) - Cx, Ax = 1 - Cx - Bx, Cy = 3 * y1, By = 3 * (y2 - y1) - Cy, Ay = 1 - Cy - By; var bezierX = function(t) { return t * (Cx + t * (Bx + t * Ax)) }; var bezierY = function(t) { return t * (Cy + t * (By + t * Ay)) }; var findXfor = function(t) { var x = t, i = 0, z; while (i < 14) { z = bezierX(x) - t; if (Math.abs(z) < 1e-3) break; x = x - z / derivativeX(x); i++ } return x }; var derivativeX = function(t) { return Cx + t * (2 * Bx + t * 3 * Ax) }; return function(t) { return bezierY(findXfor(t)) } }; $.easing[easingName] = function(x, t, b, c, d) { return c * polynomBezier(bezCoeffs[0], bezCoeffs[1], bezCoeffs[2], bezCoeffs[3])(t / d) + b } } return easingName }; var baseConfigValidator = function(config, animationType) { $.each(["from", "to"], function() { if (!$.isPlainObject(config[this])) throw Error("Animation with the '" + animationType + "' type requires '" + this + "' configuration as an plain object."); }) }; var CustomAnimationConfigurator = {setup: function($element, config){}}; var SlideAnimationConfigurator = { validateConfig: function(config) { baseConfigValidator(config, "slide") }, setup: function($element, config) { var location = translator.locate($element); this._setUpConfig(location, config.from); this._setUpConfig(location, config.to); translator.clearCache($element); if (!support.transform3d && $element.css("position") === "static") $element.css("position", "relative") }, _setUpConfig: function(location, config) { config.left = "left" in config ? config.left : "+=0"; config.top = "top" in config ? config.top : "+=0"; this._initNewPosition(location, config) }, _initNewPosition: function(location, config) { var position = { left: config.left, top: config.top }; delete config.left; delete config.top; var relativeValue = this._getRelativeValue(position.left); if (relativeValue !== undefined) position.left = relativeValue + location.left; else config.left = 0; relativeValue = this._getRelativeValue(position.top); if (relativeValue !== undefined) position.top = relativeValue + location.top; else config.top = 0; var translate = { x: 0, y: 0 }; if (support.transform3d) translate = { x: position.left, y: position.top }; else { config.left = position.left; config.top = position.top } config[TRANSFORM_PROP] = translator.getTranslateCss(translate) }, _getRelativeValue: function(value) { var relativeValue; if (typeof value === "string" && (relativeValue = RELATIVE_VALUE_REGEX.exec(value))) return parseInt(relativeValue[1] + "1") * relativeValue[2] } }; var FadeAnimationConfigurator = {setup: function($element, config) { var from = config.from, fromOpacity = $.isPlainObject(from) ? $element.css("opacity") : String(from), toOpacity = String(config.to); config.from = {opacity: fromOpacity}; config.to = {opacity: toOpacity} }}; var PopAnimationConfigurator = { validateConfig: function(config) { baseConfigValidator(config, "pop") }, setup: function($element, config) { var from = config.from, to = config.to, fromOpacity = "opacity" in from ? from.opacity : $element.css("opacity"), toOpacity = "opacity" in to ? to.opacity : 1, fromScale = "scale" in from ? from.scale : 0, toScale = "scale" in to ? to.scale : 1; config.from = {opacity: fromOpacity}; var translate = translator.getTranslate($element); config.from[TRANSFORM_PROP] = this._getCssTransform(translate, fromScale); config.to = {opacity: toOpacity}; config.to[TRANSFORM_PROP] = this._getCssTransform(translate, toScale) }, _getCssTransform: function(translate, scale) { return translator.getTranslateCss(translate) + "scale(" + scale + ")" } }; var animationConfigurators = { custom: CustomAnimationConfigurator, slide: SlideAnimationConfigurator, fade: FadeAnimationConfigurator, pop: PopAnimationConfigurator }; var getAnimationConfigurator = function(type) { var result = animationConfigurators[type]; if (!result) throw Error("Unknown animation type \"" + type + "\""); return result }; var defaultConfig = { type: "custom", from: {}, to: {}, duration: 400, start: $.noop, complete: $.noop, easing: "ease", delay: 0 }; var animate = function(element, config) { var $element = $(element); config = $.extend(true, {}, defaultConfig, config); if (!$element.length) return $.Deferred().resolve().promise(); var configurator = getAnimationConfigurator(config.type); if ($.isFunction(configurator.validateConfig)) configurator.validateConfig(config); return pushInAnimationQueue($element, config) }; var pushInAnimationQueue = function($element, config) { config.deferred = config.deferred || $.Deferred(); var queueData = getAnimQueueData($element); writeAnimQueueData($element, queueData); queueData.push(config); if (!isAnimating($element)) shiftFromAnimationQueue($element, queueData); return config.deferred.promise() }; var getAnimQueueData = function($element) { return $element.data(ANIM_QUEUE_KEY) || [] }; var writeAnimQueueData = function($element, queueData) { $element.data(ANIM_QUEUE_KEY, queueData) }; var destroyAnimQueueData = function($element) { $element.removeData(ANIM_QUEUE_KEY) }; var isAnimating = function($element) { return !!$element.data(ANIM_DATA_KEY) }; var shiftFromAnimationQueue = function($element, queueData) { var queueData = getAnimQueueData($element); if (!queueData.length) return; var config = queueData.shift(); if (queueData.length === 0) destroyAnimQueueData($element); executeAnimation($element, config).done(function() { shiftFromAnimationQueue($element) }) }; var executeAnimation = function($element, config) { setupPosition($element, config.from); setupPosition($element, config.to); var configurator = getAnimationConfigurator(config.type); configurator.setup($element, config); $element.data(ANIM_DATA_KEY, config); if (DX.fx.off) config.duration = 0; setProps($element, config.from); config.start.apply(this, [$element, config]); return getAnimationStrategy(config).animate($element, config).done(function() { $element.removeData(ANIM_DATA_KEY); config.complete.apply(this, [$element, config]); config.deferred.resolveWith(this, [$element, config]) }) }; var setupPosition = function($element, config) { if (!config.position) return; var position = DX.calculatePosition($element, config.position), offset = $element.offset(), currentPosition = $element.position(); $.extend(config, { left: position.h.location - offset.left + currentPosition.left, top: position.v.location - offset.top + currentPosition.top }); delete config.position }; var setProps = function($element, props) { $.each(props, function(key, value) { $element.css(key, value) }) }; var stop = function(element, jumpToEnd) { var $element = $(element), queueData = getAnimQueueData($element); $.each(queueData, function(_, config) { config.duration = 0 }); var config = $element.data(ANIM_DATA_KEY); getAnimationStrategy(config).stop($element, config, jumpToEnd); $element.removeData(ANIM_DATA_KEY); destroyAnimQueueData($element) }; DX.fx = { off: false, animationTypes: animationConfigurators, animate: animate, isAnimating: isAnimating, stop: stop }; DX.fx.__internals = {convertTransitionTimingFuncToJQueryEasing: convertTransitionTimingFuncToJQueryEasing} })(jQuery, DevExpress); /*! Module core, file endpointSelector.js */ (function($, DX, undefined) { var location = window.location, DXPROXY_HOST = "dxproxy.devexpress.com:8000", WIN_JS = location.protocol === "ms-appx:", IS_DXPROXY = location.host === DXPROXY_HOST, IS_LOCAL = isLocalHostName(location.hostname); function isLocalHostName(url) { return /^(localhost$|127\.)/i.test(url) } var extractProxyAppId = function() { return location.pathname.split("/")[1] }; var formatProxyUrl = function(localUrl) { var urlData = DX.parseUrl(localUrl); if (!isLocalHostName(urlData.hostname)) return localUrl; return "http://" + DXPROXY_HOST + "/" + extractProxyAppId() + "_" + urlData.port + urlData.pathname + urlData.search }; var EndpointSelector = DX.EndpointSelector = function(config) { this.config = config }; EndpointSelector.prototype = {urlFor: function(key) { var bag = this.config[key]; if (!bag) throw Error("Unknown endpoint key"); if (IS_DXPROXY) return formatProxyUrl(bag.local); if (bag.production) if (WIN_JS && !Debug.debuggerEnabled || !WIN_JS && !IS_LOCAL) return bag.production; return bag.local }} })(jQuery, DevExpress); /*! Module core, file formatHelper.js */ (function($, DX, undefined) { var utils = DX.utils; DX.NumericFormat = { currency: 'C', fixedpoint: 'N', exponential: '', percent: 'P', decimal: 'D' }; DX.LargeNumberFormatPostfixes = { 1: 'K', 2: 'M', 3: 'B', 4: 'T' }; var MAX_LARGE_NUMBER_POWER = 4, DECIMAL_BASE = 10; DX.LargeNumberFormatPowers = { largenumber: 'auto', thousands: 1, millions: 2, billions: 3, trillions: 4 }; DX.DateTimeFormat = { longdate: 'D', longtime: 'T', monthandday: 'M', monthandyear: 'Y', quarterandyear: 'qq', shortdate: 'd', shorttime: 't', millisecond: 'fff', second: 'T', minute: 't', hour: 't', day: 'dd', week: 'dd', month: 'MMMM', quarter: 'qq', year: 'yyyy', longdatelongtime: 'D', shortdateshorttime: 'd' }; DX.formatHelper = { defaultQuarterFormat: 'Q{0}', romanDigits: ['I', 'II', 'III', 'IV'], _addFormatSeparator: function(format1, format2) { var separator = ' '; if (format2) return format1 + separator + format2; return format1 }, _getDateTimeFormatPattern: function(dateTimeFormat) { return Globalize.findClosestCulture().calendar.patterns[DX.DateTimeFormat[dateTimeFormat.toLowerCase()]] }, _isDateFormatContains: function(format) { var result = false; $.each(DX.DateTimeFormat, function(key, value) { result = key === format.toLowerCase(); return !result }); return result }, getQuarter: function(month) { return Math.floor(month / 3) }, getFirstQuarterMonth: function(month) { return this.getQuarter(month) * 3 }, _getQuarterString: function(date, format) { var quarter = this.getQuarter(date.getMonth()); switch (format) { case'q': return this.romanDigits[quarter]; case'qq': return utils.stringFormat(this.defaultQuarterFormat, this.romanDigits[quarter]); case'Q': return (quarter + 1).toString(); case'QQ': return utils.stringFormat(this.defaultQuarterFormat, (quarter + 1).toString()) } return '' }, _formatCustomString: function(value, format) { var regExp = /qq|q|QQ|Q/g, quarterFormat, result = '', index = 0; regExp.lastIndex = 0; while (index < format.length) { quarterFormat = regExp.exec(format); if (!quarterFormat || quarterFormat.index > index) result += Globalize.format(value, format.substring(index, quarterFormat ? quarterFormat.index : format.length)); if (quarterFormat) { result += this._getQuarterString(value, quarterFormat[0]); index = quarterFormat.index + quarterFormat[0].length } else index = format.length } return result }, _parseNumberFormatString: function(format) { var formatList, formatObject = {}; if (!format || typeof format !== 'string') return; formatList = format.toLowerCase().split(' '); $.each(formatList, function(index, value) { if (value in DX.NumericFormat) formatObject.formatType = value; else if (value in DX.LargeNumberFormatPowers) formatObject.power = DX.LargeNumberFormatPowers[value] }); if (formatObject.power && !formatObject.formatType) formatObject.formatType = 'fixedpoint'; if (formatObject.formatType) return formatObject }, _calculateNumberPower: function(value, base, minPower, maxPower) { var number = Math.abs(value); var power = 0; if (number > 1) while (number && number >= base && (maxPower === undefined || power < maxPower)) { power++; number = number / base } else if (number > 0 && number < 1) while (number < 1 && (minPower === undefined || power > minPower)) { power--; number = number * base } return power }, _getNumberByPower: function(number, power, base) { var result = number; while (power > 0) { result = result / base; power-- } while (power < 0) { result = result * base; power++ } return result }, _formatNumber: function(value, formatObject, precision) { var powerPostfix; if (formatObject.power === 'auto') formatObject.power = this._calculateNumberPower(value, 1000, 0, MAX_LARGE_NUMBER_POWER); if (formatObject.power) value = this._getNumberByPower(value, formatObject.power, 1000); powerPostfix = DX.LargeNumberFormatPostfixes[formatObject.power] || ''; return this._formatNumberCore(value, formatObject.formatType, precision) + powerPostfix }, _formatNumberExponential: function(value, precision) { var power = this._calculateNumberPower(value, DECIMAL_BASE), number = this._getNumberByPower(value, power, DECIMAL_BASE), powString; precision = precision === undefined ? 1 : precision; if (number.toFixed(precision || 0) >= DECIMAL_BASE) { power++; number = number / DECIMAL_BASE } powString = (power >= 0 ? '+' : '') + power.toString(); return this._formatNumberCore(number, 'fixedpoint', precision) + 'E' + powString }, _formatNumberCore: function(value, format, precision) { if (format === 'exponential') return this._formatNumberExponential(value, precision); else return Globalize.format(value, DX.NumericFormat[format] + (utils.isNumber(precision) ? precision : 0)) }, _formatDate: function(date, format, formatString) { var resultFormat = DX.DateTimeFormat[format.toLowerCase()]; format = format.toLowerCase(); if (format === 'quarterandyear') resultFormat = this._getQuarterString(date, resultFormat) + ' yyyy'; if (format === 'quarter') return this._getQuarterString(date, resultFormat); if (format === 'longdatelongtime') return this._formatDate(date, 'longdate') + ' ' + this._formatDate(date, 'longtime'); if (format === 'shortdateshorttime') return this._formatDate(date, 'shortDate') + ' ' + this._formatDate(date, 'shortTime'); return Globalize.format(date, resultFormat) }, format: function(value, format, precision) { if (format && format.format) if (format.dateType) return this._formatDateEx(value, format); else if (utils.isNumber(value) && isFinite(value)) return this._formatNumberEx(value, format); return this._format(value, format, precision) }, _format: function(value, format, precision) { var numberFormatObject; if (!utils.isString(format) || format === '' || !utils.isNumber(value) && !utils.isDate(value)) return utils.isDefined(value) ? value.toString() : ''; numberFormatObject = this._parseNumberFormatString(format); if (utils.isNumber(value) && numberFormatObject) return this._formatNumber(value, numberFormatObject, precision); if (utils.isDate(value) && this._isDateFormatContains(format)) return this._formatDate(value, format); if (!numberFormatObject && !this._isDateFormatContains(format)) return this._formatCustomString(value, format) }, _formatNumberEx: function(value, formatInfo) { var that = this, numericFormatType = DX.NumericFormat[formatInfo.format.toLowerCase()], numberFormat = Globalize.culture().numberFormat, currencyFormat = formatInfo.currencyCulture && Globalize.cultures[formatInfo.currencyCulture] ? Globalize.cultures[formatInfo.currencyCulture].numberFormat.currency : numberFormat.currency, percentFormat = numberFormat.percent, formatSettings = that._getUnitFormatSettings(value, formatInfo), unit = formatSettings.unit, precision = formatSettings.precision, showTrailingZeros = formatSettings.showTrailingZeros, includeGroupSeparator = formatSettings.includeGroupSeparator, groupSymbol = numberFormat[","], floatingSymbol = numberFormat["."], number, isNegative, pattern, currentFormat, regexParts = /n|\$|-|%/g, result = ""; 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 = undefined, 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'quarter': return utils.stringFormat(that.defaultQuarterFormat, value.toString()); case'month': index = value - 1; return dateType === 'abbr' ? calendar.months.namesAbbr[index] : calendar.months.names[index]; case'hour': if (dateType === 'long') { time = new Date; time.setHours(value); time.setMinutes(0); return that._formatDate(time, 'shorttime') } else return value.toString(); case'dayofweek': index = utils.isString(value) ? $.inArray(value, ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']) : value; if (dateType !== 'num') return dateType === 'abbr' ? calendar.days.namesAbbr[index] : calendar.days.names[index]; else return ((index - calendar.firstDay + 1 + 7) % 8).toString(); default: return value.toString() } else return value.toString() }, getTimeFormat: function(showSecond) { if (showSecond) return this._getDateTimeFormatPattern('longtime'); return this._getDateTimeFormatPattern('shorttime') }, getDateFormatByDifferences: function(dateDifferences) { var resultFormat = ''; if (dateDifferences.millisecond) resultFormat = DX.DateTimeFormat.millisecond; if (dateDifferences.hour || dateDifferences.minute || dateDifferences.second) resultFormat = this._addFormatSeparator(this.getTimeFormat(dateDifferences.second), resultFormat); if (dateDifferences.year && dateDifferences.month && dateDifferences.day) return this._addFormatSeparator(this._getDateTimeFormatPattern('shortdate'), resultFormat); if (dateDifferences.year && dateDifferences.month) return DX.DateTimeFormat['monthandyear']; if (dateDifferences.year) return DX.DateTimeFormat['year']; if (dateDifferences.month && dateDifferences.day) return this._addFormatSeparator(this._getDateTimeFormatPattern('monthandday'), resultFormat); if (dateDifferences.month) return DX.DateTimeFormat['month']; if (dateDifferences.day) return this._addFormatSeparator('dddd, dd', resultFormat); return resultFormat }, getDateFormatByTicks: function(ticks) { var resultFormat, maxDif, currentDif, i, dateUnitInterval; if (ticks.length > 1) { maxDif = utils.getDatesDifferences(ticks[0], ticks[1]); for (i = 1; i < ticks.length - 1; i++) { currentDif = utils.getDatesDifferences(ticks[i], ticks[i + 1]); if (maxDif.count < currentDif.count) maxDif = currentDif } } else maxDif = { year: true, month: true, day: true, hour: ticks[0].getHours() > 0, minute: ticks[0].getMinutes() > 0, second: ticks[0].getSeconds() > 0 }; resultFormat = this.getDateFormatByDifferences(maxDif); return resultFormat }, getDateFormatByTickInterval: function(startValue, endValue, tickInterval) { var resultFormat, dateDifferences, dateUnitInterval, dateDifferencesConverter = { quarter: 'month', week: 'day' }, correctDateDifferences = function(dateDifferences, tickInterval, value) { switch (tickInterval) { case'year': dateDifferences.month = value; case'quarter': case'month': dateDifferences.day = value; case'week': case'day': dateDifferences.hour = value; case'hour': dateDifferences.minute = value; case'minute': dateDifferences.second = value; case'second': dateDifferences.millisecond = value } }, correctDifferencesByMaxDate = function(differences, minDate, maxDate) { if (!maxDate.getMilliseconds() && maxDate.getSeconds()) { if (maxDate.getSeconds() - minDate.getSeconds() === 1) { differences.millisecond = true; differences.second = false } } else if (!maxDate.getSeconds() && maxDate.getMinutes()) { if (maxDate.getMinutes() - minDate.getMinutes() === 1) { differences.second = true; differences.minute = false } } else if (!maxDate.getMinutes() && maxDate.getHours()) { if (maxDate.getHours() - minDate.getHours() === 1) { differences.minute = true; differences.hour = false } } else if (!maxDate.getHours() && maxDate.getDate() > 1) { if (maxDate.getDate() - minDate.getDate() === 1) { differences.hour = true; differences.day = false } } else if (maxDate.getDate() === 1 && maxDate.getMonth()) { if (maxDate.getMonth() - minDate.getMonth() === 1) { differences.day = true; differences.month = false } } else if (!maxDate.getMonth() && maxDate.getFullYear()) if (maxDate.getFullYear() - minDate.getFullYear() === 1) { differences.month = true; differences.year = false } }; tickInterval = utils.isString(tickInterval) ? tickInterval.toLowerCase() : tickInterval; dateDifferences = utils.getDatesDifferences(startValue, endValue); if (startValue !== endValue) correctDifferencesByMaxDate(dateDifferences, startValue > endValue ? endValue : startValue, startValue > endValue ? startValue : endValue); dateUnitInterval = utils.getDateUnitInterval(dateDifferences); correctDateDifferences(dateDifferences, dateUnitInterval, true); dateUnitInterval = utils.getDateUnitInterval(tickInterval || 'second'); correctDateDifferences(dateDifferences, dateUnitInterval, false); dateDifferences[dateDifferencesConverter[dateUnitInterval] || dateUnitInterval] = true; resultFormat = this.getDateFormatByDifferences(dateDifferences); return resultFormat } } })(jQuery, DevExpress); /*! Module core, file color.js */ (function(DX, undefined) { var standardColorNames = { aliceblue: 'f0f8ff', antiquewhite: 'faebd7', aqua: '00ffff', aquamarine: '7fffd4', azure: 'f0ffff', beige: 'f5f5dc', bisque: 'ffe4c4', black: '000000', blanchedalmond: 'ffebcd', blue: '0000ff', blueviolet: '8a2be2', brown: 'a52a2a', burlywood: 'deb887', cadetblue: '5f9ea0', chartreuse: '7fff00', chocolate: 'd2691e', coral: 'ff7f50', cornflowerblue: '6495ed', cornsilk: 'fff8dc', crimson: 'dc143c', cyan: '00ffff', darkblue: '00008b', darkcyan: '008b8b', darkgoldenrod: 'b8860b', darkgray: 'a9a9a9', darkgreen: '006400', darkkhaki: 'bdb76b', darkmagenta: '8b008b', darkolivegreen: '556b2f', darkorange: 'ff8c00', darkorchid: '9932cc', darkred: '8b0000', darksalmon: 'e9967a', darkseagreen: '8fbc8f', darkslateblue: '483d8b', darkslategray: '2f4f4f', darkturquoise: '00ced1', darkviolet: '9400d3', deeppink: 'ff1493', deepskyblue: '00bfff', dimgray: '696969', dodgerblue: '1e90ff', feldspar: 'd19275', firebrick: 'b22222', floralwhite: 'fffaf0', forestgreen: '228b22', fuchsia: 'ff00ff', gainsboro: 'dcdcdc', ghostwhite: 'f8f8ff', gold: 'ffd700', goldenrod: 'daa520', gray: '808080', green: '008000', greenyellow: 'adff2f', honeydew: 'f0fff0', hotpink: 'ff69b4', indianred: 'cd5c5c', indigo: '4b0082', ivory: 'fffff0', khaki: 'f0e68c', lavender: 'e6e6fa', lavenderblush: 'fff0f5', lawngreen: '7cfc00', lemonchiffon: 'fffacd', lightblue: 'add8e6', lightcoral: 'f08080', lightcyan: 'e0ffff', lightgoldenrodyellow: 'fafad2', lightgrey: 'd3d3d3', lightgreen: '90ee90', lightpink: 'ffb6c1', lightsalmon: 'ffa07a', lightseagreen: '20b2aa', lightskyblue: '87cefa', lightslateblue: '8470ff', lightslategray: '778899', lightsteelblue: 'b0c4de', lightyellow: 'ffffe0', lime: '00ff00', limegreen: '32cd32', linen: 'faf0e6', magenta: 'ff00ff', maroon: '800000', mediumaquamarine: '66cdaa', mediumblue: '0000cd', mediumorchid: 'ba55d3', mediumpurple: '9370d8', mediumseagreen: '3cb371', mediumslateblue: '7b68ee', mediumspringgreen: '00fa9a', mediumturquoise: '48d1cc', mediumvioletred: 'c71585', midnightblue: '191970', mintcream: 'f5fffa', mistyrose: 'ffe4e1', moccasin: 'ffe4b5', navajowhite: 'ffdead', navy: '000080', oldlace: 'fdf5e6', olive: '808000', olivedrab: '6b8e23', orange: 'ffa500', orangered: 'ff4500', orchid: 'da70d6', palegoldenrod: 'eee8aa', palegreen: '98fb98', paleturquoise: 'afeeee', palevioletred: 'd87093', papayawhip: 'ffefd5', peachpuff: 'ffdab9', peru: 'cd853f', pink: 'ffc0cb', plum: 'dda0dd', powderblue: 'b0e0e6', purple: '800080', red: 'ff0000', rosybrown: 'bc8f8f', royalblue: '4169e1', saddlebrown: '8b4513', salmon: 'fa8072', sandybrown: 'f4a460', seagreen: '2e8b57', seashell: 'fff5ee', sienna: 'a0522d', silver: 'c0c0c0', skyblue: '87ceeb', slateblue: '6a5acd', slategray: '708090', snow: 'fffafa', springgreen: '00ff7f', steelblue: '4682b4', tan: 'd2b48c', teal: '008080', thistle: 'd8bfd8', tomato: 'ff6347', turquoise: '40e0d0', violet: 'ee82ee', violetred: 'd02090', wheat: 'f5deb3', white: 'ffffff', whitesmoke: 'f5f5f5', yellow: 'ffff00', yellowgreen: '9acd32' }; var standardColorTypes = [{ re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, process: function(colorString) { return [parseInt(colorString[1], 10), parseInt(colorString[2], 10), parseInt(colorString[3], 10)] } }, { re: /^rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*(\d*\.*\d+)\)$/, process: function(colorString) { return [parseInt(colorString[1], 10), parseInt(colorString[2], 10), parseInt(colorString[3], 10), parseFloat(colorString[4])] } }, { re: /^#(\w{2})(\w{2})(\w{2})$/, process: function(colorString) { return [parseInt(colorString[1], 16), parseInt(colorString[2], 16), parseInt(colorString[3], 16)] } }, { re: /^#(\w{1})(\w{1})(\w{1})$/, process: function(colorString) { return [parseInt(colorString[1] + colorString[1], 16), parseInt(colorString[2] + colorString[2], 16), parseInt(colorString[3] + colorString[3], 16)] } }, { re: /^hsv\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, process: function(colorString) { var h = parseInt(colorString[1], 10), s = parseInt(colorString[2], 10), v = parseInt(colorString[3], 10), rgb = hsvToRgb(h, s, v); return [rgb[0], rgb[1], rgb[2], 1, [h, s, v]] } }, { re: /^hsl\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, process: function(colorString) { var h = parseInt(colorString[1], 10), s = parseInt(colorString[2], 10), l = parseInt(colorString[3], 10), rgb = hslToRgb(h, s, l); return [rgb[0], rgb[1], rgb[2], 1, null, [h, s, l]] } }]; function Color(value) { this.baseColor = value; var color; if (value) { color = String(value).toLowerCase().replace(/ /g, ''); color = standardColorNames[color] ? '#' + standardColorNames[color] : color; color = parseColor(color) } if (!color) this.colorIsInvalid = true; color = color || {}; this.r = normalize(color[0]); this.g = normalize(color[1]); this.b = normalize(color[2]); this.a = normalize(color[3], 1, 1); if (color[4]) this.hsv = { h: color[4][0], s: color[4][1], v: color[4][2] }; else this.hsv = toHsvFromRgb(this.r, this.g, this.b); if (color[5]) this.hsl = { h: color[5][0], s: color[5][1], l: color[5][2] }; else this.hsl = toHslFromRgb(this.r, this.g, this.b) } function parseColor(color) { if (color === "transparent") return [0, 0, 0, 0]; var result, i = 0, ii = standardColorTypes.length, str; for (; i < ii; ++i) { str = standardColorTypes[i].re.exec(color); if (str) return standardColorTypes[i].process(str) } return null } function normalize(colorComponent, def, max) { def = def || 0; max = max || 255; return colorComponent < 0 || isNaN(colorComponent) ? def : colorComponent > max ? max : colorComponent } function toHexFromRgb(r, g, b) { return '#' + (0X01000000 | r << 16 | g << 8 | b).toString(16).slice(1) } function toHsvFromRgb(r, g, b) { var max = Math.max(r, g, b), min = Math.min(r, g, b), delta = max - min, H, S, V; V = max; S = max === 0 ? 0 : 1 - min / max; if (max === min) H = 0; else switch (max) { case r: H = 60 * ((g - b) / delta); if (g < b) H = H + 360; break; case g: H = 60 * ((b - r) / delta) + 120; break; case b: H = 60 * ((r - g) / delta) + 240; break } S *= 100; V *= 100 / 255; return { h: Math.round(H), s: Math.round(S), v: Math.round(V) } } function hsvToRgb(h, s, v) { var Vdec, Vinc, Vmin, Hi, a, r, g, b; Hi = Math.floor(h / 60); Vmin = (100 - s) * v / 100; a = (v - Vmin) * (h % 60 / 60); Vinc = Vmin + a; Vdec = v - a; switch (Hi) { case 0: r = v; g = Vinc; b = Vmin; break; case 1: r = Vdec; g = v; b = Vmin; break; case 2: r = Vmin; g = v; b = Vinc; break; case 3: r = Vmin; g = Vdec; b = v; break; case 4: r = Vinc; g = Vmin; b = v; break; case 5: r = v; g = Vmin; b = Vdec; break } return [Math.round(r * 2.55), Math.round(g * 2.55), Math.round(b * 2.55)] } function calculateHue(r, g, b, delta) { var max = Math.max(r, g, b); switch (max) { case r: return (g - b) / delta + (g < b ? 6 : 0); case g: return (b - r) / delta + 2; case b: return (r - g) / delta + 4 } } function toHslFromRgb(r, g, b) { r = convertTo01Bounds(r, 255); g = convertTo01Bounds(g, 255); b = convertTo01Bounds(b, 255); var max = Math.max(r, g, b), min = Math.min(r, g, b), maxMinSumm = max + min, h, s, l = maxMinSumm / 2; if (max === min) h = s = 0; else { var delta = max - min; if (l > 0.5) s = delta / (2 - maxMinSumm); else s = delta / maxMinSumm; h = calculateHue(r, g, b, delta); h /= 6 } return { h: _round(h * 360), s: _round(s * 100), l: _round(l * 100) } } function makeTc(colorPart, h) { var Tc = h; if (colorPart === "r") Tc = h + 1 / 3; if (colorPart === "b") Tc = h - 1 / 3; return Tc } function modifyTc(Tc) { if (Tc < 0) Tc += 1; if (Tc > 1) Tc -= 1; return Tc } function hueToRgb(p, q, Tc) { Tc = modifyTc(Tc); if (Tc < 1 / 6) return p + (q - p) * 6 * Tc; if (Tc < 1 / 2) return q; if (Tc < 2 / 3) return p + (q - p) * (2 / 3 - Tc) * 6; return p } function hslToRgb(h, s, l) { var r, g, b, h = convertTo01Bounds(h, 360), s = convertTo01Bounds(s, 100), l = convertTo01Bounds(l, 100); if (s === 0) r = g = b = l; else { var q = l < 0.5 ? l * (1 + s) : l + s - l * s, p = 2 * l - q; r = hueToRgb(p, q, makeTc("r", h)); g = hueToRgb(p, q, makeTc("g", h)); b = hueToRgb(p, q, makeTc("b", h)) } return [_round(r * 255), _round(g * 255), _round(b * 255)] } function convertTo01Bounds(n, max) { n = Math.min(max, Math.max(0, parseFloat(n))); if (Math.abs(n - max) < 0.000001) return 1; return n % max / parseFloat(max) } function isIntegerBtwMinAndMax(number, min, max) { min = min || 0; max = max || 255; if (number % 1 !== 0 || number < min || number > max || typeof number !== 'number' || isNaN(number)) return false; return true } var _round = Math.round; Color.prototype = { constructor: Color, highlight: function(step) { step = step || 10; return this.alter(step).toHex() }, darken: function(step) { step = step || 10; return this.alter(-step).toHex() }, alter: function(step) { var result = new Color; result.r = normalize(this.r + step); result.g = normalize(this.g + step); result.b = normalize(this.b + step); return result }, blend: function(blendColor, opacity) { var other = blendColor instanceof Color ? blendColor : new Color(blendColor), result = new Color; result.r = normalize(_round(this.r * (1 - opacity) + other.r * opacity)); result.g = normalize(_round(this.g * (1 - opacity) + other.g * opacity)); result.b = normalize(_round(this.b * (1 - opacity) + other.b * opacity)); return result }, toHex: function() { return toHexFromRgb(this.r, this.g, this.b) }, getPureColor: function() { var rgb = hsvToRgb(this.hsv.h, 100, 100); return new Color("rgb(" + rgb.join(",") + ")") }, isValidHex: function(hex) { return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(hex) }, isValidRGB: function(r, g, b) { if (!isIntegerBtwMinAndMax(r) || !isIntegerBtwMinAndMax(g) || !isIntegerBtwMinAndMax(b)) return false; return true }, isValidAlpha: function(a) { if (isNaN(a) || a < 0 || a > 1 || typeof a !== 'number') return false; return true }, colorIsInvalid: false }; DX.Color = Color })(DevExpress); /*! Module core, file localization.js */ (function($, DX, undefined) { Globalize.localize = function(key, cultureSelector) { var neutral = (cultureSelector || this.cultureSelector || "").substring(0, 2); return this.findClosestCulture(cultureSelector).messages[key] || this.findClosestCulture(neutral).messages[key] || this.cultures["default"].messages[key] }; var localization = function() { var newMessages = {}; return { setup: function(localizablePrefix) { this.localizeString = function(text) { var regex = new RegExp("(^|[^a-zA-Z_0-9" + localizablePrefix + "-]+)(" + localizablePrefix + "{1,2})([a-zA-Z_0-9-]+)", "g"), escapeString = localizablePrefix + localizablePrefix; return text.replace(regex, function(str, prefix, escape, localizationKey) { var result = prefix + localizablePrefix + localizationKey; if (escape !== escapeString) if (Globalize.cultures["default"].messages[localizationKey]) result = prefix + Globalize.localize(localizationKey); else newMessages[localizationKey] = DX.inflector.humanize(localizationKey); return result }) } }, localizeNode: function(node) { var that = this; $(node).each(function(index, nodeItem) { if (!nodeItem.nodeType) return; if (nodeItem.nodeType === 3) nodeItem.nodeValue = that.localizeString(nodeItem.nodeValue); else { $.each(nodeItem.attributes || [], function(index, attr) { if (typeof attr.value === "string") { var localizedValue = that.localizeString(attr.value); if (attr.value !== localizedValue) attr.value = localizedValue } }); $(nodeItem).contents().each(function(index, node) { that.localizeNode(node) }) } }) }, getDictionary: function(onlyNew) { if (onlyNew) return newMessages; return $.extend({}, newMessages, Globalize.cultures["default"].messages) } } }(); localization.setup("@"); DX.localization = localization })(jQuery, DevExpress); /*! Module core, file localization.en.js */ Globalize.addCultureInfo("default", {messages: { Yes: "Yes", No: "No", Cancel: "Cancel", Clear: "Clear", Done: "Done", Loading: "Loading...", Select: "Select...", Search: "Search", Back: "Back", OK: "OK", "dxLookup-searchPlaceholder": "Minimum character number: {0}", "dxCollectionContainerWidget-noDataText": "No data to display", "dxList-pullingDownText": "Pull down to refresh...", "dxList-pulledDownText": "Release to refresh...", "dxList-refreshingText": "Refreshing...", "dxList-pageLoadingText": "Loading...", "dxList-nextButtonText": "More", "dxListEditDecorator-delete": "Delete", "dxListEditDecorator-more": "More", "dxScrollView-pullingDownText": "Pull down to refresh...", "dxScrollView-pulledDownText": "Release to refresh...", "dxScrollView-refreshingText": "Refreshing...", "dxScrollView-reachBottomText": "Loading...", "dxSwitch-onText": "ON", "dxSwitch-offText": "OFF", "dxDateBox-simulatedDataPickerTitleTime": "Select time", "dxDateBox-simulatedDataPickerTitleDate": "Select date", "dxDateBox-simulatedDataPickerTitleDateTime": "Select date and time", "dxDataGrid-columnChooserTitle": "Column Chooser", "dxDataGrid-columnChooserEmptyText": "Drag a column here to hide it", "dxDataGrid-groupContinuesMessage": "Continues on the next page", "dxDataGrid-groupContinuedMessage": "Continued from the previous page", "dxDataGrid-editingEditRow": "Edit", "dxDataGrid-editingSaveRowChanges": "Save", "dxDataGrid-editingCancelRowChanges": "Cancel", "dxDataGrid-editingDeleteRow": "Delete", "dxDataGrid-editingUndeleteRow": "Undelete", "dxDataGrid-editingConfirmDeleteMessage": "Are you sure you want to delete this record?", "dxDataGrid-editingConfirmDeleteTitle": "", "dxDataGrid-groupPanelEmptyText": "Drag a column header here to group by that column", "dxDataGrid-noDataText": "No data", "dxDataGrid-searchPanelPlaceholder": "Search...", "dxDataGrid-filterRowShowAllText": "(All)", "dxDataGrid-filterRowResetOperationText": "Reset", "dxDataGrid-filterRowOperationEquals": "Equals", "dxDataGrid-filterRowOperationNotEquals": "Does not equal", "dxDataGrid-filterRowOperationLess": "Less than", "dxDataGrid-filterRowOperationLessOrEquals": "Less than or equal to", "dxDataGrid-filterRowOperationGreater": "Greater than", "dxDataGrid-filterRowOperationGreaterOrEquals": "Greater than or equal to", "dxDataGrid-filterRowOperationStartsWith": "Starts with", "dxDataGrid-filterRowOperationContains": "Contains", "dxDataGrid-filterRowOperationNotContains": "Does not contain", "dxDataGrid-filterRowOperationEndsWith": "Ends with", "dxDataGrid-trueText": "true", "dxDataGrid-falseText": "false", "dxDataGrid-sortingAscendingText": "Sort Ascending", "dxDataGrid-sortingDescendingText": "Sort Descending", "dxDataGrid-sortingClearText": "Clear Sorting" }}); /*! Module core, file data.js */ (function($, DX, undefined) { var bracketsToDots = function(expr) { return expr.replace(/\[/g, ".").replace(/\]/g, "") }; var unwrapObservable = DX.utils.unwrapObservable; var isObservable = function(value) { return DX.support.hasKo && ko.isObservable(value) }; var readPropValue = function(obj, propName) { if (propName === "this") return obj; return obj[propName] }; var assignPropValue = function(obj, propName, value) { if (propName === "this") throw Error("Cannot assign to self"); var propValue = obj[propName]; if (isObservable(propValue)) propValue(value); else obj[propName] = value }; var compileGetter = function(expr) { if (arguments.length > 1) expr = $.makeArray(arguments); if (!expr || expr === "this") return function(obj) { return obj }; if ($.isFunction(expr)) return expr; if ($.isArray(expr)) return combineGetters(expr); expr = bracketsToDots(expr); var path = expr.split("."); return function(obj, options) { options = options || {}; var current = unwrapObservable(obj); $.each(path, function() { if (!current) return false; var next = unwrapObservable(current[this]); if ($.isFunction(next) && !options.functionsAsIs) next = next.call(current); current = next }); return current } }; var combineGetters = function(getters) { var compiledGetters = {}; $.each(getters, function() { compiledGetters[this] = compileGetter(this) }); return function(obj, options) { var result = {}; $.each(compiledGetters, function(name) { var value = this(obj, options), current, path, last, i; if (value === undefined) return; current = result; path = name.split("."); last = path.length - 1; for (i = 0; i < last; i++) current = current[path[i]] = {}; current[path[i]] = value }); return result } }; var compileSetter = function(expr) { expr = expr || "this"; expr = bracketsToDots(expr); var pos = expr.lastIndexOf("."), targetGetter = compileGetter(expr.substr(0, pos)), targetPropName = expr.substr(1 + pos); return function(obj, value, options) { options = options || {}; var target = targetGetter(obj, {functionsAsIs: options.functionsAsIs}), prevTargetValue = readPropValue(target, targetPropName); if (!options.functionsAsIs && $.isFunction(prevTargetValue) && !isObservable(prevTargetValue)) target[targetPropName](value); else { prevTargetValue = unwrapObservable(prevTargetValue); if (options.merge && $.isPlainObject(value) && (prevTargetValue === undefined || $.isPlainObject(prevTargetValue)) && !(value instanceof $.Event)) { if (!prevTargetValue) assignPropValue(target, targetPropName, {}); DX.utils.deepExtendArraySafe(unwrapObservable(readPropValue(target, targetPropName)), value) } else assignPropValue(target, targetPropName, value) } } }; var normalizeBinaryCriterion = function(crit) { return [crit[0], crit.length < 3 ? "=" : String(crit[1]).toLowerCase(), crit.length < 2 ? true : crit[crit.length - 1]] }; var normalizeSortingInfo = function(info) { if (!$.isArray(info)) info = [info]; return $.map(info, function(i) { return { selector: $.isFunction(i) || typeof i === "string" ? i : i.getter || i.field || i.selector, desc: !!(i.desc || String(i.dir).charAt(0).toLowerCase() === "d") } }) }; var Guid = DX.Class.inherit({ ctor: function(value) { if (value) value = String(value); this._value = this._normalize(value || this._generate()) }, _normalize: function(value) { value = value.replace(/[^a-f0-9]/ig, "").toLowerCase(); while (value.length < 32) value += "0"; return [value.substr(0, 8), value.substr(8, 4), value.substr(12, 4), value.substr(16, 4), value.substr(20, 12)].join("-") }, _generate: function() { var value = ""; for (var i = 0; i < 32; i++) value += Math.round(Math.random() * 15).toString(16); return value }, toString: function() { return this._value }, valueOf: function() { return this._value }, toJSON: function() { return this._value } }); var toComparable = function(value, caseSensitive) { if (value instanceof Date) return value.getTime(); if (value instanceof Guid) return value.valueOf(); if (!caseSensitive && typeof value === "string") return value.toLowerCase(); return value }; var keysEqual = function(keyExpr, key1, key2) { if ($.isArray(keyExpr)) { var names = $.map(key1, function(v, k) { return k }), name; for (var i = 0; i < names.length; i++) { name = names[i]; if (toComparable(key1[name], true) != toComparable(key2[name], true)) return false } return true } return toComparable(key1, true) == toComparable(key2, true) }; var BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; var base64_encode = function(input) { if (!$.isArray(input)) input = stringToByteArray(String(input)); var result = ""; for (var i = 0; i < input.length; i += 3) { var octet1 = input[i], octet2 = input[i + 1], octet3 = input[i + 2]; result += $.map([octet1 >> 2, (octet1 & 3) << 4 | octet2 >> 4, isNaN(octet2) ? 64 : (octet2 & 15) << 2 | octet3 >> 6, isNaN(octet3) ? 64 : octet3 & 63], function(item) { return BASE64_CHARS.charAt(item) }).join("") } return result }; var stringToByteArray = function(str) { var bytes = [], code, i; for (i = 0; i < str.length; i++) { code = str.charCodeAt(i); if (code < 128) bytes.push(code); else if (code < 2048) bytes.push(192 + (code >> 6), 128 + (code & 63)); else if (code < 65536) bytes.push(224 + (code >> 12), 128 + (code >> 6 & 63), 128 + (code & 63)); else if (code < 2097152) bytes.push(240 + (code >> 18), 128 + (code >> 12 & 63), 128 + (code >> 6 & 63), 128 + (code & 63)) } return bytes }; var errorMessageFromXhr = function() { var textStatusMessages = { timeout: "Network connection timeout", error: "Unspecified network error", parsererror: "Unexpected server response" }; var textStatusDetails = { timeout: "possible causes: the remote host is not accessible, overloaded or is not included into the domain white-list when being run in the native container", error: "if the remote host is located on another domain, make sure it properly supports cross-origin resource sharing (CORS), or use the JSONP approach instead", parsererror: "the remote host did not respond with valid JSON data" }; var explainTextStatus = function(textStatus) { var result = textStatusMessages[textStatus]; if (!result) return textStatus; result += " (" + textStatusDetails[textStatus] + ")"; return result }; return function(xhr, textStatus) { if (xhr.status < 400) return explainTextStatus(textStatus); return xhr.statusText } }(); var data = DX.data = { utils: { compileGetter: compileGetter, compileSetter: compileSetter, normalizeBinaryCriterion: normalizeBinaryCriterion, normalizeSortingInfo: normalizeSortingInfo, toComparable: toComparable, keysEqual: keysEqual, errorMessageFromXhr: errorMessageFromXhr }, Guid: Guid, base64_encode: base64_encode, queryImpl: {}, queryAdapters: {}, query: function() { var impl = $.isArray(arguments[0]) ? "array" : "remote"; return data.queryImpl[impl].apply(this, arguments) }, errorHandler: null, _handleError: function(error) { if (window.console) console.warn("[DevExpress.data]: " + error); if (data.errorHandler) data.errorHandler(error) } } })(jQuery, DevExpress); /*! Module core, file data.query.array.js */ (function($, DX, undefined) { var Class = DX.Class, data = DX.data, queryImpl = data.queryImpl, compileGetter = data.utils.compileGetter, toComparable = data.utils.toComparable; var Iterator = Class.inherit({ toArray: function() { var result = []; this.reset(); while (this.next()) result.push(this.current()); return result }, countable: function() { return false } }); var ArrayIterator = Iterator.inherit({ ctor: function(array) { this.array = array; this.index = -1 }, next: function() { if (this.index + 1 < this.array.length) { this.index++; return true } return false }, current: function() { return this.array[this.index] }, reset: function() { this.index = -1 }, toArray: function() { return this.array.slice(0) }, countable: function() { return true }, count: function() { return this.array.length } }); var WrappedIterator = Iterator.inherit({ ctor: function(iter) { this.iter = iter }, next: function() { return this.iter.next() }, current: function() { return this.iter.current() }, reset: function() { return this.iter.reset() } }); var MapIterator = WrappedIterator.inherit({ ctor: function(iter, mapper) { this.callBase(iter); this.index = -1; this.mapper = mapper }, current: function() { return this.mapper(this.callBase(), this.index) }, next: function() { var hasNext = this.callBase(); if (hasNext) this.index++; return hasNext } }); var SortIterator = Iterator.inherit({ ctor: function(iter, getter, desc) { if (!(iter instanceof MapIterator)) iter = new MapIterator(iter, this._wrap); this.iter = iter; this.rules = [{ getter: getter, desc: desc }] }, thenBy: function(getter, desc) { var result = new SortIterator(this.sortedIter || this.iter, getter, desc); if (!this.sortedIter) result.rules = this.rules.concat(result.rules); return result }, next: function() { this._ensureSorted(); return this.sortedIter.next() }, current: function() { this._ensureSorted(); return this.sortedIter.current() }, reset: function() { delete this.sortedIter }, countable: function() { return this.sortedIter || this.iter.countable() }, count: function() { if (this.sortedIter) return this.sortedIter.count(); return this.iter.count() }, _ensureSorted: function() { if (this.sortedIter) return; $.each(this.rules, function() { this.getter = compileGetter(this.getter) }); this.sortedIter = new MapIterator(new ArrayIterator(this.iter.toArray().sort($.proxy(this._compare, this))), this._unwrap) }, _wrap: function(record, index) { return { index: index, value: record } }, _unwrap: function(wrappedItem) { return wrappedItem.value }, _compare: function(x, y) { var xIndex = x.index, yIndex = y.index; x = x.value; y = y.value; if (x === y) return xIndex - yIndex; for (var i = 0, rulesCount = this.rules.length; i < rulesCount; i++) { var rule = this.rules[i], xValue = toComparable(rule.getter(x)), yValue = toComparable(rule.getter(y)), factor = rule.desc ? -1 : 1; if (xValue < yValue) return -factor; if (xValue > yValue) return factor; if (xValue !== yValue) return !xValue ? -factor : factor } return xIndex - yIndex } }); var compileCriteria = function() { var compileGroup = function(crit) { var operands = [], bag = ["return function(d) { return "], index = 0, pushAnd = false; $.each(crit, function() { if ($.isArray(this) || $.isFunction(this)) { if (pushAnd) bag.push(" && "); operands.push(compileCriteria(this)); bag.push("op[", index, "](d)"); index++; pushAnd = true } else { bag.push(/and|&/i.test(this) ? " && " : " || "); pushAnd = false } }); bag.push(" }"); return new Function("op", bag.join(""))(operands) }; var toString = function(value) { return DX.utils.isDefined(value) ? value.toString() : '' }; var compileBinary = function(crit) { crit = data.utils.normalizeBinaryCriterion(crit); var getter = compileGetter(crit[0]), op = crit[1], value = crit[2]; value = toComparable(value); switch (op.toLowerCase()) { case"=": return compileEquals(getter, value); case"<>": return compileEquals(getter, value, true); case">": return function(obj) { return toComparable(getter(obj)) > value }; case"<": return function(obj) { return toComparable(getter(obj)) < value }; case">=": return function(obj) { return toComparable(getter(obj)) >= value }; case"<=": return function(obj) { return toComparable(getter(obj)) <= value }; case"startswith": return function(obj) { return toComparable(toString(getter(obj))).indexOf(value) === 0 }; case"endswith": return function(obj) { var getterValue = toComparable(toString(getter(obj))); return getterValue.lastIndexOf(value) === getterValue.length - toString(value).length }; case"contains": return function(obj) { return toComparable(toString(getter(obj))).indexOf(value) > -1 }; case"notcontains": return function(obj) { return toComparable(toString(getter(obj))).indexOf(value) === -1 } } throw Error("Unknown filter operation: " + op); }; function compileEquals(getter, value, negate) { return function(obj) { obj = toComparable(getter(obj)); var result = useStrictComparison(value) ? obj === value : obj == value; if (negate) result = !result; return result } } function useStrictComparison(value) { return value === "" || value === 0 || value === null || value === false || value === undefined } return function(crit) { if ($.isFunction(crit)) return crit; if ($.isArray(crit[0])) return compileGroup(crit); return compileBinary(crit) } }(); var FilterIterator = WrappedIterator.inherit({ ctor: function(iter, criteria) { this.callBase(iter); this.criteria = compileCriteria(criteria) }, next: function() { while (this.iter.next()) if (this.criteria(this.current())) return true; return false } }); var GroupIterator = Iterator.inherit({ ctor: function(iter, getter) { this.iter = iter; this.getter = getter }, next: function() { this._ensureGrouped(); return this.groupedIter.next() }, current: function() { this._ensureGrouped(); return this.groupedIter.current() }, reset: function() { delete this.groupedIter }, countable: function() { return !!this.groupedIter }, count: function() { return this.groupedIter.count() }, _ensureGrouped: function() { if (this.groupedIter) return; var hash = {}, keys = [], iter = this.iter, getter = compileGetter(this.getter); iter.reset(); while (iter.next()) { var current = iter.current(), key = getter(current); if (key in hash) hash[key].push(current); else { hash[key] = [current]; keys.push(key) } } this.groupedIter = new ArrayIterator($.map(keys, function(key) { return { key: key, items: hash[key] } })) } }); var SelectIterator = WrappedIterator.inherit({ ctor: function(iter, getter) { this.callBase(iter); this.getter = compileGetter(getter) }, current: function() { return this.getter(this.callBase()) }, countable: function() { return this.iter.countable() }, count: function() { return this.iter.count() } }); var SliceIterator = WrappedIterator.inherit({ ctor: function(iter, skip, take) { this.callBase(iter); this.skip = Math.max(0, skip); this.take = Math.max(0, take); this.pos = 0 }, next: function() { if (this.pos >= this.skip + this.take) return false; while (this.pos < this.skip && this.iter.next()) this.pos++; this.pos++; return this.iter.next() }, reset: function() { this.callBase(); this.pos = 0 }, countable: function() { return this.iter.countable() }, count: function() { return Math.min(this.iter.count() - this.skip, this.take) } }); queryImpl.array = function(iter, queryOptions) { queryOptions = queryOptions || {}; if (!(iter instanceof Iterator)) iter = new ArrayIterator(iter); var handleError = function(error) { var handler = queryOptions.errorHandler; if (handler) handler(error); data._handleError(error) }; var aggregate = function(seed, step, finalize) { var d = $.Deferred().fail(handleError); try { iter.reset(); if (arguments.length < 2) { step = arguments[0]; seed = iter.next() ? iter.current() : undefined } var accumulator = seed; while (iter.next()) accumulator = step(accumulator, iter.current()); d.resolve(finalize ? finalize(accumulator) : accumulator) } catch(x) { d.reject(x) } return d.promise() }; var select = function(getter) { if (!$.isFunction(getter) && !$.isArray(getter)) getter = $.makeArray(arguments); return chainQuery(new SelectIterator(iter, getter)) }; var selectProp = function(name) { return select(compileGetter(name)) }; var chainQuery = function(iter) { return queryImpl.array(iter, queryOptions) }; return { toArray: function() { return iter.toArray() }, enumerate: function() { var d = $.Deferred().fail(handleError); try { d.resolve(iter.toArray()) } catch(x) { d.reject(x) } return d.promise() }, sortBy: function(getter, desc) { return chainQuery(new SortIterator(iter, getter, desc)) }, thenBy: function(getter, desc) { if (iter instanceof SortIterator) return chainQuery(iter.thenBy(getter, desc)); throw Error(); }, filter: function(criteria) { if (!$.isArray(criteria)) criteria = $.makeArray(arguments); return chainQuery(new FilterIterator(iter, criteria)) }, slice: function(skip, take) { if (take === undefined) take = Number.MAX_VALUE; return chainQuery(new SliceIterator(iter, skip, take)) }, select: select, groupBy: function(getter) { return chainQuery(new GroupIterator(iter, getter)) }, aggregate: aggregate, count: function() { if (iter.countable()) { var d = $.Deferred().fail(handleError); try { d.resolve(iter.count()) } catch(x) { d.reject(x) } return d.promise() } return aggregate(0, function(count) { return 1 + count }) }, sum: function(getter) { if (getter) return selectProp(getter).sum(); return aggregate(0, function(sum, item) { return sum + item }) }, min: function(getter) { if (getter) return selectProp(getter).min(); return aggregate(function(min, item) { return item < min ? item : min }) }, max: function(getter) { if (getter) return selectProp(getter).max(); return aggregate(function(max, item) { return item > max ? item : max }) }, avg: function(getter) { if (getter) return selectProp(getter).avg(); var count = 0; return aggregate(0, function(sum, item) { count++; return sum + item }, function(sum) { return count ? sum / count : undefined }) } } } })(jQuery, DevExpress); /*! Module core, file data.query.remote.js */ (function($, DX, undefined) { var data = DX.data, queryImpl = data.queryImpl; queryImpl.remote = function(url, queryOptions, tasks) { tasks = tasks || []; queryOptions = queryOptions || {}; var createTask = function(name, args) { return { name: name, args: args } }; var exec = function(executorTask) { var d = $.Deferred(), adapterFactory, adapter, taskQueue, currentTask; var rejectWithNotify = function(error) { var handler = queryOptions.errorHandler; if (handler) handler(error); data._handleError(error); d.reject(error) }; try { adapterFactory = queryOptions.adapter || "odata"; if (!$.isFunction(adapterFactory)) adapterFactory = data.queryAdapters[adapterFactory]; adapter = adapterFactory(queryOptions); taskQueue = [].concat(tasks).concat(executorTask); while (taskQueue.length) { currentTask = taskQueue[0]; if (String(currentTask.name) !== "enumerate") if (!adapter[currentTask.name] || adapter[currentTask.name].apply(adapter, currentTask.args) === false) break; taskQueue.shift() } adapter.exec(url).done(function(result, extra) { if (!taskQueue.length) d.resolve(result, extra); else { var clientChain = queryImpl.array(result, {errorHandler: queryOptions.errorHandler}); $.each(taskQueue, function() { clientChain = clientChain[this.name].apply(clientChain, this.args) }); clientChain.done($.proxy(d.resolve, d)).fail($.proxy(d.reject, d)) } }).fail(rejectWithNotify) } catch(x) { rejectWithNotify(x) } return d.promise() }; var query = {}; $.each(["sortBy", "thenBy", "filter", "slice", "select", "groupBy"], function() { var name = this; query[name] = function() { return queryImpl.remote(url, queryOptions, tasks.concat(createTask(name, arguments))) } }); $.each(["count", "min", "max", "sum", "avg", "aggregate", "enumerate"], function() { var name = this; query[name] = function() { return exec.call(this, createTask(name, arguments)) } }); return query } })(jQuery, DevExpress); /*! Module core, file data.odata.js */ (function($, DX, undefined) { var data = DX.data, utils = DX.utils, Guid = data.Guid; var 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})(?:-?W(\d+)(?:-?(\d+)D?)?|(?:-(\d+))?-(\d+))(?:[T ](\d+):(\d+)(?::(\d+)(?:\.(\d+))?)?)?(?:Z(-?\d*))?$/; var TIMEZONE_OFFSET = (new Date).getTimezoneOffset() * 60 * 1000; var JSON_VERBOSE_MIME_TYPE = "application/json;odata=verbose"; function stringify(object) { return JSON.stringify(object, replacer); function replacer(key, value) { if (this[key] instanceof Date) return utils.formatIso8601Date(this[key]); return value } } var ajaxOptionsForRequest = function(request, requestOptions) { request = $.extend({ method: "get", url: "", params: {}, payload: null, headers: {} }, request); requestOptions = requestOptions || {}; var beforeSend = requestOptions.beforeSend; if (beforeSend) beforeSend(request); var method = (request.method || "get").toLowerCase(), isGet = method === "get", useJsonp = isGet && requestOptions.jsonp, params = $.extend({}, request.params), ajaxData = isGet ? params : stringify(request.payload), qs = !isGet && $.param(params), url = request.url, contentType = !isGet && JSON_VERBOSE_MIME_TYPE; if (qs) url += (url.indexOf("?") > -1 ? "&" : "?") + qs; if (useJsonp) ajaxData["$format"] = "json"; return { url: url, data: ajaxData, dataType: useJsonp ? "jsonp" : "json", jsonp: useJsonp && "$callback", type: method, timeout: 30000, headers: request.headers, contentType: contentType, accepts: {json: [JSON_VERBOSE_MIME_TYPE, "text/plain"].join()}, xhrFields: {withCredentials: requestOptions.withCredentials} } }; var sendRequest = function(request, requestOptions) { var d = $.Deferred(); $.ajax(ajaxOptionsForRequest(request, requestOptions)).always(function(obj, textStatus) { var tuplet = interpretJsonFormat(obj, textStatus), error = tuplet.error, data = tuplet.data, nextUrl = tuplet.nextUrl, extra; if (error) d.reject(error); else if (requestOptions.countOnly) d.resolve(tuplet.count); else if (nextUrl) sendRequest({url: nextUrl}, requestOptions).fail($.proxy(d.reject, d)).done(function(nextData) { d.resolve(data.concat(nextData)) }); else { if (isFinite(tuplet.count)) extra = {totalCount: tuplet.count}; d.resolve(data, extra) } }); return d.promise() }; var formatDotNetError = function(errorObj) { var message, currentError = errorObj; if ("message" in errorObj) if (errorObj.message.value) message = errorObj.message.value; else message = errorObj.message; while (currentError = currentError.innererror || currentError.internalexception) { message = currentError.message; if (currentError.internalexception && message.indexOf("inner exception") === -1) break } return message }; var errorFromResponse = function(obj, textStatus) { if (textStatus === "nocontent") return null; var httpStatus = 200, message = "Unknown error", response = obj; if (textStatus !== "success") { httpStatus = obj.status; message = data.utils.errorMessageFromXhr(obj, textStatus); try { response = $.parseJSON(obj.responseText) } catch(x) {} } var errorObj = response && (response.error || response["@odata.error"]); if (errorObj) { message = formatDotNetError(errorObj) || message; if (httpStatus === 200) httpStatus = 500; if (errorObj.code) httpStatus = Number(errorObj.code); return $.extend(Error(message), { httpStatus: httpStatus, errorDetails: errorObj }) } else if (httpStatus !== 200) return $.extend(Error(message), {httpStatus: httpStatus}) }; var interpretJsonFormat = function(obj, textStatus) { var error = errorFromResponse(obj, textStatus), value; if (error) return {error: error}; if (!$.isPlainObject(obj)) return {data: obj}; if ("d" in obj && (utils.isArray(obj.d) || utils.isObject(obj.d))) value = interpretVerboseJsonFormat(obj, textStatus); else value = interpretLightJsonFormat(obj, textStatus); transformTypes(value); return value }; var interpretVerboseJsonFormat = function(obj, textStatus) { var data = obj.d; if (!data) return {error: Error("Malformed or unsupported JSON response received")}; data = data.results || data; return { data: data, nextUrl: obj.d.__next, count: parseInt(obj.d.__count, 10) } }; var interpretLightJsonFormat = function(obj, textStatus) { var data = obj.value || obj; if (!data) return {error: Error("Malformed or unsupported JSON response received")}; return { data: data, nextUrl: obj["@odata.nextLink"], count: parseInt(obj["@odata.count"], 10) } }; var EdmLiteral = DX.Class.inherit({ ctor: function(value) { this._value = value }, valueOf: function() { return this._value } }); var transformTypes = function(obj) { $.each(obj, function(key, value) { if (value !== null && typeof value === "object") transformTypes(value); else if (typeof value === "string") if (GUID_REGEX.test(value)) obj[key] = new Guid(value); else if (value.match(VERBOSE_DATE_REGEX)) obj[key] = new Date(TIMEZONE_OFFSET + Number(RegExp.$1) + RegExp.$2 * 60000); else if (ISO8601_DATE_REGEX.test(value)) obj[key] = new Date(utils.parseIso8601Date(obj[key]).valueOf()) }) }; var serializeDate = function() { var pad = function(part) { part = String(part); if (part.length < 2) part = "0" + part; return part }; return function(date) { var result = ["datetime'", date.getFullYear(), "-", pad(date.getMonth() + 1), "-", pad(date.getDate())]; if (date.getHours() || date.getMinutes() || date.getSeconds() || date.getMilliseconds()) { result.push("T", pad(date.getHours()), ":", pad(date.getMinutes()), ":", pad(date.getSeconds())); if (date.getMilliseconds()) result.push(".", date.getMilliseconds()) } result.push("'"); return result.join("") } }(); var serializeString = function(value) { return "'" + value.replace(/": createBinaryOperationFormatter("ne"), ">": createBinaryOperationFormatter("gt"), ">=": createBinaryOperationFormatter("ge"), "<": createBinaryOperationFormatter("lt"), "<=": createBinaryOperationFormatter("le"), startswith: createStringFuncFormatter("startswith"), endswith: createStringFuncFormatter("endswith") }; var formattersV2 = $.extend({}, formatters, { contains: createStringFuncFormatter("substringof", true), notcontains: createStringFuncFormatter("not substringof", true) }); var formattersV4 = $.extend({}, formatters, { contains: createStringFuncFormatter("contains"), notcontains: createStringFuncFormatter("not contains") }); var compileBinary = function(criteria, bag, protocolVersion) { criteria = data.utils.normalizeBinaryCriterion(criteria); var op = criteria[1], formatters = protocolVersion === 4 ? formattersV4 : formattersV2, formatter = formatters[op.toLowerCase()]; if (!formatter) throw Error("Unknown filter operation: " + op); formatter(serializePropName(criteria[0]), serializeValue(criteria[2], protocolVersion), bag) }; var compileGroup = function(criteria, bag, protocolVersion) { var pushAnd = false; $.each(criteria, function() { if ($.isArray(this)) { if (pushAnd) bag.push(" and "); bag.push("("); compileCore(this, bag, protocolVersion); bag.push(")"); pushAnd = true } else { bag.push(/and|&/i.test(this) ? " and " : " or "); pushAnd = false } }) }; var compileCore = function(criteria, bag, protocolVersion) { if ($.isArray(criteria[0])) compileGroup(criteria, bag, protocolVersion); else compileBinary(criteria, bag, protocolVersion) }; return function(criteria, protocolVersion) { var bag = []; compileCore(criteria, bag, protocolVersion); return bag.join("") } }(); var createODataQueryAdapter = function(queryOptions) { var sorting = [], criteria = [], select, skip, take, countQuery; var hasSlice = function() { return skip || take !== undefined }; var sortCore = function(getter, desc, reset) { if (hasSlice() || typeof getter !== "string") return false; if (reset) sorting = []; var rule = serializePropName(getter); if (desc) rule += " desc"; sorting.push(rule) }; var generateExpand = function() { var hash = {}; if (queryOptions.expand) $.each($.makeArray(queryOptions.expand), function() { hash[serializePropName(this)] = 1 }); if (select) $.each(select, function() { var path = this.split("."); if (path.length < 2) return; path.pop(); hash[serializePropName(path.join("."))] = 1 }); return $.map(hash, function(k, v) { return v }).join() || undefined }; var requestData = function() { var result = {}; if (!countQuery) { if (sorting.length) result["$orderby"] = sorting.join(","); if (skip) result["$skip"] = skip; if (take !== undefined) result["$top"] = take; if (select) result["$select"] = serializePropName(select.join()); result["$expand"] = generateExpand() } if (criteria.length) result["$filter"] = compileCriteria(criteria.length < 2 ? criteria[0] : criteria, queryOptions.version); if (countQuery) result["$top"] = 0; if (queryOptions.requireTotalCount || countQuery) if (queryOptions.version !== 4) result["$inlinecount"] = "allpages"; else result["$count"] = "true"; return result }; return { exec: function(url) { return sendRequest({ url: url, params: $.extend(requestData(), queryOptions && queryOptions.params) }, { beforeSend: queryOptions.beforeSend, jsonp: queryOptions.jsonp, withCredentials: queryOptions.withCredentials, countOnly: countQuery }) }, sortBy: function(getter, desc) { return sortCore(getter, desc, true) }, thenBy: function(getter, desc) { return sortCore(getter, desc, false) }, slice: function(skipCount, takeCount) { if (hasSlice()) return false; skip = skipCount; take = takeCount }, filter: function(criterion) { if (hasSlice() || $.isFunction(criterion)) return false; if (!$.isArray(criterion)) criterion = $.makeArray(arguments); if (criteria.length) criteria.push("and"); criteria.push(criterion) }, select: function(expr) { if (select || $.isFunction(expr)) return false; if (!$.isArray(expr)) expr = $.makeArray(arguments); select = expr }, count: function() { countQuery = true } } }; $.extend(true, data, { EdmLiteral: EdmLiteral, utils: {odata: { sendRequest: sendRequest, serializePropName: serializePropName, serializeValue: serializeValue, serializeKey: serializeKey, keyConverters: keyConverters }}, queryAdapters: {odata: createODataQueryAdapter} }); data.OData__internals = {interpretJsonFormat: interpretJsonFormat} })(jQuery, DevExpress); /*! Module core, file data.store.abstract.js */ (function($, DX, undefined) { var Class = DX.Class, abstract = DX.abstract, data = DX.data, normalizeSortingInfo = data.utils.normalizeSortingInfo; var STORE_CALLBACK_NAMES = ["loading", "loaded", "modifying", "modified", "inserting", "inserted", "updating", "updated", "removing", "removed"]; function multiLevelGroup(query, groupInfo) { query = query.groupBy(groupInfo[0].selector); if (groupInfo.length > 1) query = query.select(function(g) { return $.extend({}, g, {items: multiLevelGroup(data.query(g.items), groupInfo.slice(1)).toArray()}) }); return query } data.utils.multiLevelGroup = multiLevelGroup; function arrangeSortingInfo(groupInfo, sortInfo) { var filteredGroup = []; $.each(groupInfo, function(_, group) { var collision = $.grep(sortInfo, function(sort) { return group.selector == sort.selector }); if (collision.length < 1) filteredGroup.push(group) }); return filteredGroup.concat(sortInfo) } data.Store = Class.inherit({ ctor: function(options) { var that = this; options = options || {}; $.each(STORE_CALLBACK_NAMES, function() { var callbacks = that[this] = $.Callbacks(); if (this in options) callbacks.add(options[this]) }); this._key = options.key; this._errorHandler = options.errorHandler; this._useDefaultSearch = true }, _customLoadOptions: function() { return null }, key: function() { return this._key }, keyOf: function(obj) { if (!this._keyGetter) this._keyGetter = data.utils.compileGetter(this.key()); return this._keyGetter(obj) }, _requireKey: function() { if (!this.key()) throw Error("Key expression is required for this operation"); }, load: function(options) { var that = this; options = options || {}; this.loading.fire(options); return this._loadImpl(options).done(function(result, extra) { that.loaded.fire(result, extra) }) }, _loadImpl: function(options) { var filter = options.filter, sort = options.sort, select = options.select, group = options.group, skip = options.skip, take = options.take, q = this.createQuery(options); if (filter) q = q.filter(filter); if (group) group = normalizeSortingInfo(group); if (sort || group) { sort = normalizeSortingInfo(sort || []); if (group) sort = arrangeSortingInfo(group, sort); $.each(sort, function(index) { q = q[index ? "thenBy" : "sortBy"](this.selector, this.desc) }) } if (select) q = q.select(select); if (group) q = multiLevelGroup(q, group); if (take || skip) q = q.slice(skip || 0, take); return q.enumerate() }, createQuery: abstract, totalCount: function(options) { return this._addFailHandlers(this._totalCountImpl(options)) }, _totalCountImpl: function(options) { options = options || {}; var q = this.createQuery(), group = options.group, filter = options.filter; if (filter) q = q.filter(filter); if (group) { group = normalizeSortingInfo(group); q = multiLevelGroup(q, group) } return q.count() }, byKey: function(key, extraOptions) { return this._addFailHandlers(this._byKeyImpl(key, extraOptions)) }, _byKeyImpl: abstract, insert: function(values) { var that = this; that.modifying.fire(); that.inserting.fire(values); return that._addFailHandlers(that._insertImpl(values).done(function(callbackValues, callbackKey) { that.inserted.fire(callbackValues, callbackKey); that.modified.fire() })) }, _insertImpl: abstract, update: function(key, values) { var that = this; that.modifying.fire(); that.updating.fire(key, values); return that._addFailHandlers(that._updateImpl(key, values).done(function(callbackKey, callbackValues) { that.updated.fire(callbackKey, callbackValues); that.modified.fire() })) }, _updateImpl: abstract, remove: function(key) { var that = this; that.modifying.fire(); that.removing.fire(key); return that._addFailHandlers(that._removeImpl(key).done(function(callbackKey) { that.removed.fire(callbackKey); that.modified.fire() })) }, _removeImpl: abstract, _addFailHandlers: function(deferred) { return deferred.fail(this._errorHandler, data._handleError) } }) })(jQuery, DevExpress); /*! Module core, file data.store.array.js */ (function($, DX, undefined) { var data = DX.data, Guid = data.Guid; var trivialPromise = function(_) { var d = $.Deferred(); return d.resolve.apply(d, arguments).promise() }; var rejectedPromise = function(_) { var d = $.Deferred(); return d.reject.apply(d, arguments).promise() }; data.ArrayStore = data.Store.inherit({ ctor: function(options) { if ($.isArray(options)) options = {data: options}; else options = options || {}; this.callBase(options); var initialArray = options.data; if (initialArray && !$.isArray(initialArray)) throw Error("Invalid 'data' option value"); this._array = initialArray || [] }, createQuery: function() { return data.query(this._array, {errorHandler: this._errorHandler}) }, _byKeyImpl: function(key) { return trivialPromise(this._array[this._indexByKey(key)]) }, _insertImpl: function(values) { var keyExpr = this.key(), keyValue, obj = {}; $.extend(obj, values); if (keyExpr) { keyValue = this.keyOf(obj); if (keyValue === undefined || typeof keyValue === "object" && $.isEmptyObject(keyValue)) { if ($.isArray(keyExpr)) throw Error("Compound keys cannot be auto-generated"); keyValue = obj[keyExpr] = String(new Guid) } else if (this._array[this._indexByKey(keyValue)] !== undefined) return rejectedPromise(Error("Attempt to insert an item with the duplicate key")) } else keyValue = obj; this._array.push(obj); return trivialPromise(values, keyValue) }, _updateImpl: function(key, values) { var target; if (this.key()) { var index = this._indexByKey(key); if (index < 0) return rejectedPromise(Error("Data item not found")); target = this._array[index] } else target = key; DX.utils.deepExtendArraySafe(target, values); return trivialPromise(key, values) }, _removeImpl: function(key) { var index = this._indexByKey(key); if (index > -1) this._array.splice(index, 1); return trivialPromise(key) }, _indexByKey: function(key) { for (var i = 0, arrayLength = this._array.length; i < arrayLength; i++) if (data.utils.keysEqual(this.key(), this.keyOf(this._array[i]), key)) return i; return -1 }, clear: function() { this._array = [] } }) })(jQuery, DevExpress); /*! Module core, file data.store.local.js */ (function($, DX, undefined) { var Class = DX.Class, abstract = DX.abstract, data = DX.data; var LocalStoreBackend = Class.inherit({ ctor: function(store, storeOptions) { this._store = store; this._dirty = false; var immediate = this._immediate = storeOptions.immediate; var flushInterval = Math.max(100, storeOptions.flushInterval || 10 * 1000); if (!immediate) { var saveProxy = $.proxy(this.save, this); setInterval(saveProxy, flushInterval); $(window).on("beforeunload", saveProxy); if (window.cordova) document.addEventListener("pause", saveProxy, false) } }, notifyChanged: function() { this._dirty = true; if (this._immediate) this.save() }, load: function() { this._store._array = this._loadImpl(); this._dirty = false }, save: function() { if (!this._dirty) return; this._saveImpl(this._store._array); this._dirty = false }, _loadImpl: abstract, _saveImpl: abstract }); var DomLocalStoreBackend = LocalStoreBackend.inherit({ ctor: function(store, storeOptions) { this.callBase(store, storeOptions); var name = storeOptions.name; if (!name) throw Error("Name is required"); this._key = "dx-data-localStore-" + name }, _loadImpl: function() { var raw = localStorage.getItem(this._key); if (raw) return JSON.parse(raw); return [] }, _saveImpl: function(array) { if (!array.length) localStorage.removeItem(this._key); else localStorage.setItem(this._key, JSON.stringify(array)) } }); var localStoreBackends = {dom: DomLocalStoreBackend}; data.LocalStore = data.ArrayStore.inherit({ ctor: function(options) { if (typeof options === "string") options = {name: options}; else options = options || {}; this.callBase(options); this._backend = new localStoreBackends[options.backend || "dom"](this, options); this._backend.load() }, clear: function() { this.callBase(); this._backend.notifyChanged() }, _insertImpl: function(values) { var b = this._backend; return this.callBase(values).done($.proxy(b.notifyChanged, b)) }, _updateImpl: function(key, values) { var b = this._backend; return this.callBase(key, values).done($.proxy(b.notifyChanged, b)) }, _removeImpl: function(key) { var b = this._backend; return this.callBase(key).done($.proxy(b.notifyChanged, b)) } }) })(jQuery, DevExpress); /*! Module core, file data.store.odata.js */ (function($, DX, undefined) { var Class = DX.Class, data = DX.data, utils = DX.utils, odataUtils = data.utils.odata; var escapeServiceOperationParams = function(params, version) { if (!params) return params; var result = {}; $.each(params, function(k, v) { result[k] = odataUtils.serializeValue(v, version) }); return result }; var convertSimpleKey = function(keyType, keyValue) { var converter = odataUtils.keyConverters[keyType]; if (!converter) throw Error("Unknown key type: " + keyType); return converter(keyValue) }; var SharedMethods = { _extractServiceOptions: function(options) { options = options || {}; this._url = String(options.url).replace(/\/+$/, ""); this._beforeSend = options.beforeSend; this._jsonp = options.jsonp; this._version = options.version; this._withCredentials = options.withCredentials }, _sendRequest: function(url, method, params, payload) { return odataUtils.sendRequest({ url: url, method: method, params: params || {}, payload: payload }, { beforeSend: this._beforeSend, jsonp: this._jsonp, withCredentials: this._withCredentials }) }, version: function() { return this._version } }; var ODataStore = data.Store.inherit({ ctor: function(options) { this.callBase(options); this._extractServiceOptions(options); this._keyType = options.keyType }, _customLoadOptions: function() { return ["expand", "customQueryParams"] }, _byKeyImpl: function(key, extraOptions) { var params = {}; if (extraOptions) if (extraOptions.expand) params["$expand"] = $.map($.makeArray(extraOptions.expand), odataUtils.serializePropName).join(); return this._sendRequest(this._byKeyUrl(key), "GET", params) }, createQuery: function(loadOptions) { loadOptions = loadOptions || {}; return data.query(this._url, { beforeSend: this._beforeSend, errorHandler: this._errorHandler, jsonp: this._jsonp, version: this._version, withCredentials: this._withCredentials, params: escapeServiceOperationParams(loadOptions.customQueryParams, this._version), expand: loadOptions.expand, requireTotalCount: loadOptions.requireTotalCount }) }, _insertImpl: function(values) { this._requireKey(); var that = this, d = $.Deferred(); $.when(this._sendRequest(this._url, "POST", null, values)).done(function(serverResponse) { d.resolve(values, that.keyOf(serverResponse)) }).fail($.proxy(d.reject, d)); return d.promise() }, _updateImpl: function(key, values) { var d = $.Deferred(); $.when(this._sendRequest(this._byKeyUrl(key), "MERGE", null, values)).done(function() { d.resolve(key, values) }).fail($.proxy(d.reject, d)); return d.promise() }, _removeImpl: function(key) { var d = $.Deferred(); $.when(this._sendRequest(this._byKeyUrl(key), "DELETE")).done(function() { d.resolve(key) }).fail($.proxy(d.reject, d)); return d.promise() }, _byKeyUrl: function(key) { var keyType = this._keyType; if ($.isPlainObject(keyType)) $.each(keyType, function(subKeyName, subKeyType) { key[subKeyName] = convertSimpleKey(subKeyType, key[subKeyName]) }); else if (keyType) key = convertSimpleKey(keyType, key); return this._url + "(" + encodeURIComponent(odataUtils.serializeKey(key, this._version)) + ")" } }).include(SharedMethods); var ODataContext = Class.inherit({ ctor: function(options) { var that = this; that._extractServiceOptions(options); that._errorHandler = options.errorHandler; $.each(options.entities || [], function(entityAlias, entityOptions) { that[entityAlias] = new ODataStore($.extend({}, options, {url: that._url + "/" + encodeURIComponent(entityOptions.name || entityAlias)}, entityOptions)) }) }, get: function(operationName, params) { return this.invoke(operationName, params, "GET") }, invoke: function(operationName, params, httpMethod) { httpMethod = httpMethod || "POST"; var d = $.Deferred(); $.when(this._sendRequest(this._url + "/" + encodeURIComponent(operationName), httpMethod, escapeServiceOperationParams(params, this._version))).done(function(r) { if (r && operationName in r) r = r[operationName]; d.resolve(r) }).fail([this._errorHandler, data._handleError, $.proxy(d.reject, d)]); return d.promise() }, objectLink: function(entityAlias, key) { var store = this[entityAlias]; if (!store) throw Error("Unknown entity name or alias: " + entityAlias); if (!utils.isDefined(key)) return null; return {__metadata: {uri: store._byKeyUrl(key)}} } }).include(SharedMethods); $.extend(data, { ODataStore: ODataStore, ODataContext: ODataContext }) })(jQuery, DevExpress); /*! Module core, file data.store.rest.js */ (function($, DX, undefined) { var data = DX.data; function createAjaxFailureHandler(deferred) { return function(xhr, textStatus) { if (!xhr || !xhr.getResponseHeader) deferred.reject.apply(deferred, arguments); else deferred.reject(Error(data.utils.errorMessageFromXhr(xhr, textStatus))) } } function operationCustomizerPropName(operationName) { return "_customize" + DX.inflector.camelize(operationName, true) } function pathPropName(operationName) { return "_" + operationName + "Path" } data.RestStore = data.Store.inherit({ ctor: function(options) { DX.utils.logger.warn("RestStore is deprecated, use CustomStore instead"); var that = this; that.callBase(options); options = options || {}; that._url = String(options.url).replace(/\/+$/, ""); that._jsonp = options.jsonp; that._withCredentials = options.withCredentials; $.each(["Load", "Insert", "Update", "Remove", "ByKey", "Operation"], function() { var value = options["customize" + this]; if (value) that[operationCustomizerPropName(this)] = value }); $.each(["load", "insert", "update", "remove", "byKey"], function() { var value = options[this + "Path"]; if (value) that[pathPropName(this)] = value }) }, _loadImpl: function(options) { var d = $.Deferred(), ajaxOptions = { url: this._formatUrlNoKey("load"), type: "GET" }; $.when(this._createAjax(ajaxOptions, "load", options)).done($.proxy(d.resolve, d)).fail(createAjaxFailureHandler(d)); return this._addFailHandlers(d.promise()) }, createQuery: function() { throw Error("Not supported"); }, _insertImpl: function(values) { var d = $.Deferred(), that = this, ajaxOptions = { url: this._formatUrlNoKey("insert"), type: "POST", contentType: "application/json", data: JSON.stringify(values) }; $.when(this._createAjax(ajaxOptions, "insert")).done(function(serverResponse) { d.resolve(values, that.key() && that.keyOf(serverResponse)) }).fail(createAjaxFailureHandler(d)); return d.promise() }, _updateImpl: function(key, values) { var d = $.Deferred(), ajaxOptions = { url: this._formatUrlWithKey("update", key), type: "PUT", contentType: "application/json", data: JSON.stringify(values) }; $.when(this._createAjax(ajaxOptions, "update")).done(function() { d.resolve(key, values) }).fail(createAjaxFailureHandler(d)); return d.promise() }, _removeImpl: function(key) { var d = $.Deferred(), ajaxOptions = { url: this._formatUrlWithKey("remove", key), type: "DELETE" }; $.when(this._createAjax(ajaxOptions, "remove")).done(function() { d.resolve(key) }).fail(createAjaxFailureHandler(d)); return d.promise() }, _byKeyImpl: function(key) { var d = $.Deferred(), ajaxOptions = { url: this._formatUrlWithKey("byKey", key), type: "GET" }; $.when(this._createAjax(ajaxOptions, "byKey")).done(function(data) { d.resolve(data) }).fail(createAjaxFailureHandler(d)); return d.promise() }, _createAjax: function(ajaxOptions, operationName, extra) { var customizationFunc, customizationResult; function isDeferred(obj) { return "done" in obj && "fail" in obj } if (this._jsonp && ajaxOptions.type === "GET") ajaxOptions.dataType = "jsonp"; else $.extend(true, ajaxOptions, {xhrFields: {withCredentials: this._withCredentials}}); customizationFunc = this[operationCustomizerPropName("operation")]; if (customizationFunc) { customizationResult = customizationFunc(ajaxOptions, operationName, extra); if (customizationResult) { if (isDeferred(customizationResult)) return customizationResult; ajaxOptions = customizationResult } } customizationFunc = this[operationCustomizerPropName(operationName)]; if (customizationFunc) { customizationResult = customizationFunc(ajaxOptions, extra); if (customizationResult) { if (isDeferred(customizationResult)) return customizationResult; ajaxOptions = customizationResult } } return $.ajax(ajaxOptions) }, _formatUrlNoKey: function(operationName) { var url = this._url, path = this[pathPropName(operationName)]; if (!path) return url; if ($.isFunction(path)) return path(url); return url + "/" + path }, _formatUrlWithKey: function(operationName, key) { var url = this._url, path = this[pathPropName(operationName)]; if (!path) return url + "/" + encodeURIComponent(key); if ($.isFunction(path)) return path(url, key); return url + "/" + path + "/" + encodeURIComponent(key) } }) })(jQuery, DevExpress); /*! Module core, file data.store.custom.js */ (function($, DX, undefined) { var data = DX.data; var ERROR_QUERY_NOT_SUPPORTED = "CustomStore does not support creating queries", ERROR_MISSING_USER_FUNC = "Required option is not specified or is not a function: ", ERROR_INVALID_RETURN = "Invalid return value: "; var TOTAL_COUNT = "totalCount", LOAD = "load", BY_KEY = "byKey", INSERT = "insert", UPDATE = "update", REMOVE = "remove"; function isPromise(obj) { return obj && $.isFunction(obj.done) && $.isFunction(obj.fail) && $.isFunction(obj.promise) } function trivialPromise(value) { return $.Deferred().resolve(value).promise() } function ensureRequiredFuncOption(name, obj) { if (!$.isFunction(obj)) throw Error(ERROR_MISSING_USER_FUNC + name); } function throwInvalidUserFuncResult(name) { throw Error(ERROR_INVALID_RETURN + name); } function createUserFuncFailureHandler(pendingDeferred) { function errorMessageFromXhr(promiseArguments) { var xhr = promiseArguments[0], textStatus = promiseArguments[1]; if (!xhr || !xhr.getResponseHeader) return null; return data.utils.errorMessageFromXhr(xhr, textStatus) } return function(arg) { var error; if (arg instanceof Error) error = arg; else error = Error(errorMessageFromXhr(arguments) || arg && String(arg) || "Unknown error"); pendingDeferred.reject(error) } } data.CustomStore = data.Store.inherit({ ctor: function(options) { options = options || {}; this.callBase(options); this._useDefaultSearch = false; this._loadFunc = options[LOAD]; this._totalCountFunc = options[TOTAL_COUNT]; this._byKeyFunc = options[BY_KEY] || options.lookup; this._insertFunc = options[INSERT]; this._updateFunc = options[UPDATE]; this._removeFunc = options[REMOVE] }, createQuery: function() { throw Error(ERROR_QUERY_NOT_SUPPORTED); }, _totalCountImpl: function(options) { var userFunc = this._totalCountFunc, userResult, d = $.Deferred(); ensureRequiredFuncOption(TOTAL_COUNT, userFunc); userResult = userFunc(options); if (!isPromise(userResult)) { userResult = Number(userResult); if (!isFinite(userResult)) throwInvalidUserFuncResult(TOTAL_COUNT); userResult = trivialPromise(userResult) } userResult.done(function(count) { d.resolve(Number(count)) }).fail(createUserFuncFailureHandler(d)); return d.promise() }, _loadImpl: function(options) { var userFunc = this._loadFunc, userResult, d = $.Deferred(); ensureRequiredFuncOption(LOAD, userFunc); userResult = userFunc(options); if ($.isArray(userResult)) userResult = trivialPromise(userResult); else if (userResult === null || userResult === undefined) userResult = trivialPromise([]); else if (!isPromise(userResult)) throwInvalidUserFuncResult(LOAD); userResult.done(function(data, extra) { d.resolve(data, extra) }).fail(createUserFuncFailureHandler(d)); return this._addFailHandlers(d.promise()) }, _byKeyImpl: function(key) { var userFunc = this._byKeyFunc, userResult, d = $.Deferred(); ensureRequiredFuncOption(BY_KEY, userFunc); userResult = userFunc(key); if (!isPromise(userResult)) userResult = trivialPromise(userResult); userResult.done(function(obj) { d.resolve(obj) }).fail(createUserFuncFailureHandler(d)); return d.promise() }, _insertImpl: function(values) { var userFunc = this._insertFunc, userResult, d = $.Deferred(); ensureRequiredFuncOption(INSERT, userFunc); userResult = userFunc(values); if (!isPromise(userResult)) userResult = trivialPromise(userResult); userResult.done(function(newKey) { d.resolve(values, newKey) }).fail(createUserFuncFailureHandler(d)); return d.promise() }, _updateImpl: function(key, values) { var userFunc = this._updateFunc, userResult, d = $.Deferred(); ensureRequiredFuncOption(UPDATE, userFunc); userResult = userFunc(key, values); if (!isPromise(userResult)) userResult = trivialPromise(); userResult.done(function() { d.resolve(key, values) }).fail(createUserFuncFailureHandler(d)); return d.promise() }, _removeImpl: function(key) { var userFunc = this._removeFunc, userResult, d = $.Deferred(); ensureRequiredFuncOption(REMOVE, userFunc); userResult = userFunc(key); if (!isPromise(userResult)) userResult = trivialPromise(); userResult.done(function() { d.resolve(key) }).fail(createUserFuncFailureHandler(d)); return d.promise() } }); data.CustomStore_internals = {ERRORS: { QUERY_NOT_SUPPORTED: ERROR_QUERY_NOT_SUPPORTED, MISSING_USER_FUNC: ERROR_MISSING_USER_FUNC, INVALID_RETURN: ERROR_INVALID_RETURN }} })(jQuery, DevExpress); /*! Module core, file data.dataSource.js */ (function($, DX, undefined) { var data = DX.data, CustomStore = data.CustomStore, Class = DX.Class; var storeTypeRegistry = { jaydata: "JayDataStore", breeze: "BreezeStore", odata: "ODataStore", local: "LocalStore", array: "ArrayStore" }; function normalizeDataSourceOptions(options) { var store; function createCustomStoreFromLoadFunc() { var storeConfig = {}; $.each(["key", "load", "byKey", "lookup", "totalCount", "insert", "update", "remove"], function() { storeConfig[this] = options[this]; delete options[this] }); return new CustomStore(storeConfig) } function createStoreFromConfig(storeConfig) { var storeCtor = data[storeTypeRegistry[storeConfig.type]]; delete storeConfig.type; return new storeCtor(storeConfig) } function createCustomStoreFromUrl(url) { return new CustomStore({load: function() { return $.getJSON(url) }}) } if (typeof options === "string") options = createCustomStoreFromUrl(options); if (options === undefined) options = []; if ($.isArray(options) || options instanceof data.Store) options = {store: options}; else options = $.extend({}, options); if (options.store === undefined) options.store = []; store = options.store; if ("load" in options) store = createCustomStoreFromLoadFunc(); else if ($.isArray(store)) store = new data.ArrayStore(store); else if ($.isPlainObject(store)) store = createStoreFromConfig($.extend({}, store)); options.store = store; return options } function normalizeStoreLoadOptionAccessorArguments(originalArguments) { switch (originalArguments.length) { case 0: return undefined; case 1: return originalArguments[0] } return $.makeArray(originalArguments) } function generateStoreLoadOptionAccessor(optionName) { return function() { var args = normalizeStoreLoadOptionAccessorArguments(arguments); if (args !== undefined) this._storeLoadOptions[optionName] = args; return this._storeLoadOptions[optionName] } } function addOldUserDataSourceBackwardCompatibilityOptions(dataSource, storeLoadOptions) { storeLoadOptions.refresh = !dataSource._paginate || dataSource._pageIndex === 0; if (storeLoadOptions.searchValue !== null) storeLoadOptions.searchString = storeLoadOptions.searchValue } var DataSource = Class.inherit({ ctor: function(options) { options = normalizeDataSourceOptions(options); this._store = options.store; this._storeLoadOptions = this._extractLoadOptions(options); this._mapFunc = options.map; this._postProcessFunc = options.postProcess; this._pageIndex = 0; this._pageSize = options.pageSize !== undefined ? options.pageSize : 20; this._items = []; this._totalCount = -1; this._isLoaded = false; this._loadingCount = 0; this._preferSync = options._preferSync; this._loadQueue = this._createLoadQueue(); this._searchValue = "searchValue" in options ? options.searchValue : null; this._searchOperation = options.searchOperation || "contains"; this._searchExpr = options.searchExpr; this._paginate = options.paginate; if (this._paginate === undefined) this._paginate = !this.group(); this._isLastPage = !this._paginate; this._userData = {}; this.changed = $.Callbacks(); this.loadError = $.Callbacks(); this.loadingChanged = $.Callbacks() }, dispose: function() { this.changed.empty(); this.loadError.empty(); this.loadingChanged.empty(); delete this._store; this._disposed = true }, _extractLoadOptions: function(options) { var result = {}, names = ["sort", "filter", "select", "group", "requireTotalCount"], customNames = this._store._customLoadOptions(); if (customNames) names = names.concat(customNames); $.each(names, function() { result[this] = options[this] }); return result }, loadOptions: function() { return this._storeLoadOptions }, items: function() { return this._items }, pageIndex: function(newIndex) { if (newIndex !== undefined) { this._pageIndex = newIndex; this._isLastPage = !this._paginate } return this._pageIndex }, paginate: function(value) { if (arguments.length < 1) return this._paginate; value = !!value; if (this._paginate !== value) { this._paginate = value; this.pageIndex(0) } }, isLastPage: function() { return this._isLastPage }, sort: generateStoreLoadOptionAccessor("sort"), filter: function() { var newFilter = normalizeStoreLoadOptionAccessorArguments(arguments); if (newFilter !== undefined) { this._storeLoadOptions.filter = newFilter; this.pageIndex(0) } return this._storeLoadOptions.filter }, group: generateStoreLoadOptionAccessor("group"), select: generateStoreLoadOptionAccessor("select"), searchValue: function(value) { if (value !== undefined) { this.pageIndex(0); this._searchValue = value } return this._searchValue }, searchOperation: function(op) { if (op !== undefined) { this.pageIndex(0); this._searchOperation = op } return this._searchOperation }, searchExpr: function(expr) { var argc = arguments.length; if (argc) { if (argc > 1) expr = $.makeArray(arguments); this.pageIndex(0); this._searchExpr = expr } return this._searchExpr }, store: function() { return this._store }, key: function() { return this._store && this._store.key() }, totalCount: function() { return this._totalCount }, isLoaded: function() { return this._isLoaded }, isLoading: function() { return this._loadingCount > 0 }, _createLoadQueue: function() { return DX.createQueue() }, _changeLoadingCount: function(increment) { var oldLoading = this.isLoading(), newLoading; this._loadingCount += increment; newLoading = this.isLoading(); if (oldLoading ^ newLoading) this.loadingChanged.fire(newLoading) }, _scheduleLoadCallbacks: function(deferred) { var thisSource = this; thisSource._changeLoadingCount(1); deferred.always(function() { thisSource._changeLoadingCount(-1) }) }, _scheduleChangedCallbacks: function(deferred) { var that = this; deferred.done(function() { that.changed.fire() }) }, loadSingle: function(propName, propValue) { var that = this; var d = $.Deferred().fail(this.loadError.fire), key = this.key(), store = this._store, loadOptions = this._createStoreLoadOptions(); function handleSuccess(data) { d.resolve(that._transformLoadedData(data)[0]) } if (arguments.length < 2) { propValue = propName; propName = key } delete loadOptions.skip; delete loadOptions.group; delete loadOptions.refresh; delete loadOptions.pageIndex; delete loadOptions.searchString; if (propName === key || store instanceof data.CustomStore) store.byKey(propValue, loadOptions).done(handleSuccess).fail(d.reject); else { loadOptions.take = 1; loadOptions._preferSync = true; loadOptions.filter = loadOptions.filter ? [loadOptions.filter, [propName, propValue]] : [propName, propValue]; store.load(loadOptions).done(handleSuccess).fail(d.reject) } return d.promise() }, load: function() { var thisSource = this, d = $.Deferred(), errorCallback = this.loadError, storeLoadOptions; this._scheduleLoadCallbacks(d); this._scheduleChangedCallbacks(d); storeLoadOptions = this._createStoreLoadOptions(); function loadTask() { if (thisSource._disposed) return undefined; return thisSource._loadFromStore(storeLoadOptions, d) } this._loadQueue.add(function() { loadTask(); return d.promise() }, function() { thisSource._changeLoadingCount(-1) }); return d.promise().fail($.proxy(errorCallback.fire, errorCallback)) }, _addSearchOptions: function(storeLoadOptions) { if (this._disposed) return; if (this.store()._useDefaultSearch) this._addSearchFilter(storeLoadOptions); else { storeLoadOptions.searchValue = this._searchValue; storeLoadOptions.searchExpr = this._searchExpr } }, _createStoreLoadOptions: function() { var result = $.extend({}, this._storeLoadOptions); this._addSearchOptions(result); if (this._paginate) { result.pageIndex = this._pageIndex; if (this._pageSize) { result.skip = this._pageIndex * this._pageSize; result.take = this._pageSize } } result.userData = this._userData; addOldUserDataSourceBackwardCompatibilityOptions(this, result); return result }, _addSearchFilter: function(storeLoadOptions) { var value = this._searchValue, op = this._searchOperation, selector = this._searchExpr, searchFilter = []; if (!value) return; if (!selector) selector = "this"; if (!$.isArray(selector)) selector = [selector]; $.each(selector, function(i, item) { if (searchFilter.length) searchFilter.push("or"); searchFilter.push([item, op, value]) }); if (storeLoadOptions.filter) storeLoadOptions.filter = [searchFilter, storeLoadOptions.filter]; else storeLoadOptions.filter = searchFilter }, _loadFromStore: function(storeLoadOptions, pendingDeferred) { var thisSource = this; function handleSuccess(data, extra) { function processResult() { thisSource._processStoreLoadResult(data, extra, storeLoadOptions, pendingDeferred) } if (thisSource._preferSync) processResult(); else DX.utils.executeAsync(processResult) } return this.store().load(storeLoadOptions).done(handleSuccess).fail($.proxy(pendingDeferred.reject, pendingDeferred)) }, _processStoreLoadResult: function(data, extra, storeLoadOptions, pendingDeferred) { var thisSource = this; function resolvePendingDeferred() { thisSource._isLoaded = true; thisSource._totalCount = isFinite(extra.totalCount) ? extra.totalCount : -1; return pendingDeferred.resolve(data, extra) } function proceedLoadingTotalCount() { thisSource.store().totalCount(storeLoadOptions).done(function(count) { extra.totalCount = count; resolvePendingDeferred() }).fail(function(){}) } if (thisSource._disposed) return; data = thisSource._transformLoadedData(data); if (!$.isPlainObject(extra)) extra = {}; thisSource._items = data; if (!data.length || !thisSource._paginate || thisSource._pageSize && data.length < thisSource._pageSize) thisSource._isLastPage = true; if (storeLoadOptions.requireTotalCount && !isFinite(extra.totalCount)) proceedLoadingTotalCount(); else resolvePendingDeferred() }, _transformLoadedData: function(data) { var result = $.makeArray(data); if (this._mapFunc) result = $.map(result, this._mapFunc); if (this._postProcessFunc) result = this._postProcessFunc(result); return result } }); data.Store.redefine({toDataSource: function(options) { DX.utils.logger.warn("toDataSource() method is deprecated, use 'new DevExpress.data.DataSource(...)' instead"); return new DataSource($.extend({store: this}, options)) }}); $.extend(true, data, { DataSource: DataSource, createDataSource: function(options) { DX.utils.logger.warn("createDataSource() method is deprecated, use 'new DevExpress.data.DataSource(...)' instead"); return new DataSource(options) }, utils: { storeTypeRegistry: storeTypeRegistry, normalizeDataSourceOptions: normalizeDataSourceOptions } }) })(jQuery, DevExpress); /*! Module core, file ko.js */ (function($, DX, undefined) { if (!DX.support.hasKo) return; var ko = window.ko; (function checkKnockoutVersion(version) { version = version.split("."); if (version[0] < 2 || version[0] == 2 && version[1] < 3) throw Error("Your version of KnockoutJS is too old. Please upgrade KnockoutJS to 2.3.0 or later."); })(ko.version) })(jQuery, DevExpress); /*! Module core, file ng.js */ (function($, DX, undefined) { if (!DX.support.hasNg) return; DX.ng = {module: window.angular.module("dx", ["ngSanitize"])} })(jQuery, DevExpress); /*! Module core, file component.js */ (function($, DX, undefined) { var ui = DX.ui, utils = DX.utils, dataUtils = DX.data.utils; var Component = DX.Class.inherit({ NAME: "Component", _deprecatedOptions: {}, _optionAliases: {}, _setDefaultOptions: function(){}, _defaultOptionsRules: function() { return [] }, _setOptionsByDevice: function() { var rules = this._defaultOptionsRules(), currentDevice = DX.devices.current(), result = {}; if (this._customRules) rules = rules.concat(this._customRules); var deviceMatch = function(device, filter) { filter = $.makeArray(filter); return filter.length === 1 && $.isEmptyObject(filter[0]) || utils.findBestMatches(device, filter).length > 0 }; $.each(rules, function(index, rule) { var deviceFilter = rule.device || {}, match; if ($.isFunction(deviceFilter)) match = deviceFilter(currentDevice); else match = deviceMatch(currentDevice, deviceFilter); if (match) $.extend(result, rule.options) }); this.option(result) }, _optionsByReference: function() { return {} }, ctor: function(options) { if (!this.NAME) throw Error("NAME is not specified"); this._options = {}; this._updateLockCount = 0; this.optionChanged = $.Callbacks(); this.beginUpdate(); try { this._suppressDeprecatedWarnings(); this._setDefaultOptions(); this._setOptionsByDevice(); this._resumeDeprecatedWarnings(); this._initialOptions = $.extend({}, this.option()); this._initOptions(options || {}) } finally { this.endUpdate() } }, _initOptions: function(options) { this.option(options) }, _optionValuesEqual: function(name, oldValue, newValue) { oldValue = dataUtils.toComparable(oldValue, true); newValue = dataUtils.toComparable(newValue, true); if (oldValue && newValue && oldValue.jquery && newValue.jquery) return newValue.is(oldValue); if (oldValue === null || typeof oldValue !== "object") return oldValue === newValue; return false }, _init: $.noop, _optionChanged: $.noop, instance: function() { return this }, beginUpdate: function() { this._updateLockCount++ }, endUpdate: function() { this._updateLockCount--; if (!this._updateLockCount) if (!this._initializing && !this._initialized) { this._initializing = true; try { this._init() } finally { this._initializing = false; this._initialized = true } } }, _logWarningIfDeprecated: function(option) { var info = this._deprecatedOptions[option]; if (info && !this._deprecatedOptionsSuppressed) this._logDeprecatedWarning(option, info) }, _logDeprecatedWarningCount: 0, _logDeprecatedWarning: function(option, info) { utils.logger.warn("'" + option + "' option is deprecated since " + info.since + ". " + info.message); ++this._logDeprecatedWarningCount }, _suppressDeprecatedWarnings: function() { this._deprecatedOptionsSuppressed = true }, _resumeDeprecatedWarnings: function() { this._deprecatedOptionsSuppressed = false }, _getOptionAliases: function(option) { return $.map(this._optionAliases, function(aliasedOption, alias) { return option === aliasedOption ? alias : undefined }) }, _notifyOptionChanged: function(option, value, previousValue) { var that = this, optionWithAliases; if (this._initialized) { optionWithAliases = this._getOptionAliases(option); optionWithAliases.push(option); $.each(optionWithAliases, function(index, name) { var topLevelName = name.split(/[.\[]/)[0]; that.optionChanged.fireWith(that, [topLevelName, value, previousValue]); that._optionChanged(topLevelName, value, previousValue) }) } }, initialOption: function(optionName) { var options = this._initialOptions; return options[optionName] }, option: function(options) { var that = this, name = options, value = arguments[1]; if (arguments.length < 2 && $.type(name) !== "object") { if (name) { this._logWarningIfDeprecated(name); if (this._optionAliases[name]) name = this._optionAliases[name] } $.each(this._optionAliases, function(alias, option) { that._options[alias] = dataUtils.compileGetter(option)(that._options, {functionsAsIs: true}) }); return dataUtils.compileGetter(name)(that._options, {functionsAsIs: true}) } if (typeof name === "string") { options = {}; options[name] = value } that.beginUpdate(); try { $.each(options, function(name, value) { that._logWarningIfDeprecated(name); if (that._optionAliases[name]) name = that._optionAliases[name]; var prevValue = dataUtils.compileGetter(name)(that._options, {functionsAsIs: true}); if (that._optionValuesEqual(name, prevValue, value)) return; dataUtils.compileSetter(name)(that._options, value, { functionsAsIs: true, merge: !that._optionsByReference()[name] }); that._notifyOptionChanged(name, value, prevValue) }) } finally { that.endUpdate() } } }); $.extend(DX, {Component: Component}) })(jQuery, DevExpress); /*! Module core, file DOMComponent.js */ (function($, DX, undefined) { var windowResizeCallbacks = DX.utils.windowResizeCallbacks; var RTL_DIRECTION_CLASS = "dx-rtl", COMPONENT_NAMES_DATA_KEY = "dxComponents", VISIBILITY_CHANGE_CLASS = "dx-visibility-change-handler", VISIBILITY_CHANGE_EVENTNAMESPACE = "dxVisibilityChange"; var DOMComponent = DX.Component.inherit({ NAME: "DOMComponent", NAMESPACE: DX, _setDefaultOptions: function() { this.callBase(); this.option({rtlEnabled: DX.rtlEnabled}) }, ctor: function(element, options) { this._$element = $(element); this._element().data(this.NAME, this); this._attachInstanceToElement(this._$element); this.disposing = $.Callbacks(); this.callBase(options) }, _attachInstanceToElement: $.noop, _visibilityChanged: DX.abstract, _dimensionChanged: DX.abstract, _init: function() { this.callBase(); this._attachWindowResizeCallback() }, _attachWindowResizeCallback: function() { if (this._isDimensionChangeSupported()) { var windowResizeCallBack = this._windowResizeCallBack = $.proxy(this._dimensionChanged, this); windowResizeCallbacks.add(windowResizeCallBack) } }, _isDimensionChangeSupported: function() { return this._dimensionChanged !== DX.abstract }, _render: function() { this._toggleRTLDirection(this.option("rtlEnabled")); this._renderVisiblityChange() }, _renderVisiblityChange: function() { if (!this._isVisibilityChangeSupported()) return; this._element().addClass(VISIBILITY_CHANGE_CLASS); this._attachVisiblityChangeHandlers() }, _attachVisiblityChangeHandlers: function() { var that = this; that._element().off("." + VISIBILITY_CHANGE_EVENTNAMESPACE).on("dxhiding." + VISIBILITY_CHANGE_EVENTNAMESPACE, function() { that._visibilityChanged(false) }).on("dxshown." + VISIBILITY_CHANGE_EVENTNAMESPACE, function() { that._visibilityChanged(true) }) }, _isVisibilityChangeSupported: function() { return this._visibilityChanged !== DX.abstract }, _clean: $.noop, _modelByElement: $.noop, _invalidate: function() { if (!this._updateLockCount) throw Error("Invalidate called outside update transaction"); this._requireRefresh = true }, _refresh: function() { this._clean(); this._render() }, _dispose: function() { this._clean(); this._detachWindowResizeCallback(); this.optionChanged.empty(); this.disposing.fireWith(this).empty() }, _detachWindowResizeCallback: function() { if (this._isDimensionChangeSupported()) windowResizeCallbacks.remove(this._windowResizeCallBack) }, _toggleRTLDirection: function(rtl) { this._element().toggleClass(RTL_DIRECTION_CLASS, rtl) }, _createAction: function(actionSource, config) { var that = this; config = $.extend({}, config); var element = config.element || that._element(), model = that._modelByElement(element); config.context = model || that; config.component = that; var action = new DX.Action(actionSource, config); return function(e) { if (!arguments.length) e = {}; if (e instanceof $.Event) throw Error("Action must be executed with jQuery.Event like action({ jQueryEvent: event })"); if (!$.isPlainObject(e)) e = {actionValue: e}; return action.execute.call(action, $.extend(e, { component: that, element: element, model: model })) } }, _createActionByOption: function(optionName, config) { if (typeof optionName !== "string") throw Error("Option name type is unexpected"); this._suppressDeprecatedWarnings(); var action = this._createAction(this.option(optionName), config); this._resumeDeprecatedWarnings(); return action }, _optionChanged: function(name, value, prevValue) { if (name === "rtlEnabled") this._invalidate() }, _element: function() { return this._$element }, endUpdate: function() { var requireRender = !this._initializing && !this._initialized; this.callBase.apply(this, arguments); if (!this._updateLockCount) if (requireRender) this._render(); else if (this._requireRefresh) { this._requireRefresh = false; this._refresh() } } }); var registerComponent = function(name, componentClass) { componentClass.redefine({_attachInstanceToElement: function($element) { $element.data(name, this); if (!$element.data(COMPONENT_NAMES_DATA_KEY)) $element.data(COMPONENT_NAMES_DATA_KEY, []); $element.data(COMPONENT_NAMES_DATA_KEY).push(name) }}); componentClass.prototype.NAMESPACE[name] = componentClass; componentClass.prototype.NAME = name; componentClass.defaultOptions = function(rule) { componentClass.prototype._customRules = componentClass.prototype._customRules || []; componentClass.prototype._customRules.push(rule) }; $.fn[name] = function(options) { var isMemberInvoke = typeof options === "string", result; if (isMemberInvoke) { var memberName = options, memberArgs = $.makeArray(arguments).slice(1); this.each(function() { var instance = $(this).data(name); if (!instance) throw Error(DX.utils.stringFormat("Component {0} has not been initialized on this element", name)); var member = instance[memberName], memberValue = member.apply(instance, memberArgs); if (result === undefined) result = memberValue }) } else { this.each(function() { var instance = $(this).data(name); if (instance) instance.option(options); else new componentClass(this, options) }); result = this } return result } }; var getComponents = function(element) { element = $(element); var names = element.data(COMPONENT_NAMES_DATA_KEY); if (!names) return []; return $.map(names, function(name) { return element.data(name) }) }; var disposeComponents = function() { $.each(getComponents(this), function() { this._dispose() }) }; var originalCleanData = $.cleanData; $.cleanData = function(element) { $.each(element, disposeComponents); return originalCleanData.apply(this, arguments) }; registerComponent("DOMComponent", DOMComponent); DX.registerComponent = registerComponent })(jQuery, DevExpress); /*! Module core, file social.js */ DevExpress.social = {}; /*! Module core, file facebook.js */ (function($, DX, undefined) { function notifyDeprecated() { DX.utils.logger.warn("DevExpress.social API is deprecated. Use official Facebook library instead") } var social = DX.social; var location = window.location, navigator = window.navigator, encodeURIComponent = window.encodeURIComponent, decodeURIComponent = window.decodeURIComponent, iosStandaloneMode = navigator.standalone, cordovaMode = false; if (window.cordova) $(document).on("deviceready", function() { cordovaMode = true }); var ACCESS_TOKEN_KEY = "dx-facebook-access-token", IOS_STANDALONE_STEP1_KEY = "dx-facebook-step1", IOS_STANDALONE_STEP2_KEY = "dx-facebook-step2"; var accessToken = null, expires = null, connectionChanged = $.Callbacks(); var pendingLoginRedirectUrl; var isConnected = function() { return !!accessToken }; var getAccessTokenObject = function() { return { accessToken: accessToken, expiresIn: accessToken ? expires : 0 } }; var FB = social.Facebook = { loginRedirectUrl: "FacebookLoginCallback.html", connectionChanged: connectionChanged, isConnected: isConnected, getAccessTokenObject: getAccessTokenObject, jsonp: false }; var login = function(appId, options) { notifyDeprecated(); options = options || {}; if (cordovaMode) pendingLoginRedirectUrl = "https://www.facebook.com/connect/login_success.html"; else pendingLoginRedirectUrl = formatLoginRedirectUrl(); var scope = (options.permissions || []).join(), url = "https://www.facebook.com/dialog/oauth?display=popup&client_id=" + appId + "&redirect_uri=" + encodeURIComponent(pendingLoginRedirectUrl) + "&scope=" + encodeURIComponent(scope) + "&response_type=token"; if (iosStandaloneMode) putData(IOS_STANDALONE_STEP1_KEY, location.href); if (cordovaMode) startLogin_cordova(url); else startLogin_browser(url) }; var formatLoginRedirectUrl = function() { var pathSegments = location.pathname.split(/\//g); pathSegments.pop(); pathSegments.push(FB.loginRedirectUrl); return location.protocol + "//" + location.host + pathSegments.join("/") }; var startLogin_browser = function(loginUrl) { var width = 512, height = 320, left = (screen.width - width) / 2, top = (screen.height - height) / 2; window.open(loginUrl, null, "width=" + width + ",height=" + height + ",toolbar=0,scrollbars=0,status=0,resizable=0,menuBar=0,left=" + left + ",top=" + top) }; var startLogin_cordova = function(loginUrl) { var ref = window.open(loginUrl, "_blank"); ref.addEventListener('exit', function(event) { pendingLoginRedirectUrl = null }); ref.addEventListener('loadstop', function(event) { var url = unescape(event.url); if (url.indexOf(pendingLoginRedirectUrl) === 0) { ref.close(); _processLoginRedirectUrl(url) } }) }; var handleLoginRedirect = function() { var opener = window.opener; if (iosStandaloneMode) { putData(IOS_STANDALONE_STEP2_KEY, location.href); location.href = getData(IOS_STANDALONE_STEP1_KEY) } else if (opener && opener.DevExpress) { opener.DevExpress.social.Facebook._processLoginRedirectUrl(location.href); window.close() } }; var _processLoginRedirectUrl = function(url) { var params = parseUrlFragment(url); expires = params.expires_in; changeToken(params.access_token); pendingLoginRedirectUrl = null }; var parseUrlFragment = function(url) { var hash = url.split("#")[1]; if (!hash) return {}; var pairs = hash.split(/&/g), result = {}; $.each(pairs, function(i) { var splitPair = this.split("="); result[splitPair[0]] = decodeURIComponent(splitPair[1]) }); return result }; var logout = function() { notifyDeprecated(); changeToken(null) }; var changeToken = function(value) { if (value === accessToken) return; accessToken = value; putData(ACCESS_TOKEN_KEY, value); connectionChanged.fire(!!value) }; var api = function(resource, method, params) { notifyDeprecated(); if (!isConnected()) throw Error("Not connected"); if (typeof method !== "string") { params = method; method = undefined } method = (method || "get").toLowerCase(); var d = $.Deferred(); var args = arguments; $.ajax({ url: "https://graph.facebook.com/" + resource, type: method, data: $.extend({access_token: accessToken}, params), dataType: FB.jsonp && method === "get" ? "jsonp" : "json" }).done(function(response) { response = response || simulateErrorResponse(); if (response.error) d.reject(response.error); else d.resolve(response) }).fail(function(xhr) { var response; try { response = $.parseJSON(xhr.responseText); var tries = args[3] || 0; if (tries++ < 3 && response.error.code == 190 && response.error.error_subcode == 466) { setTimeout(function() { api(resource, method, params, tries).done(function(result) { d.resolve(result) }).fail(function(error) { d.reject(error) }) }, 500); return } } catch(x) { response = simulateErrorResponse() } d.reject(response.error) }); return d.promise() }; var simulateErrorResponse = function() { return {error: {message: "Unknown error"}} }; var ensureStorageBackend = function() { if (!hasStorageBackend()) throw Error("HTML5 sessionStorage or jQuery.cookie plugin is required"); }; var hasStorageBackend = function() { return !!($.cookie || window.sessionStorage) }; var putData = function(key, data) { ensureStorageBackend(); data = JSON.stringify(data); if (window.sessionStorage) if (data === null) sess.removeItem(key); else sessionStorage.setItem(key, data); else $.cookie(key, data) }; var getData = function(key) { ensureStorageBackend(); try { return JSON.parse(window.sessionStorage ? sessionStorage.getItem(key) : $.cookie(key)) } catch(x) { return null } }; if (hasStorageBackend()) accessToken = getData(ACCESS_TOKEN_KEY); if (iosStandaloneMode) { var url = getData(IOS_STANDALONE_STEP2_KEY); if (url) { _processLoginRedirectUrl(url); putData(IOS_STANDALONE_STEP1_KEY, null); putData(IOS_STANDALONE_STEP2_KEY, null) } } $.extend(FB, { login: login, logout: logout, handleLoginRedirect: handleLoginRedirect, _processLoginRedirectUrl: _processLoginRedirectUrl, api: api }) })(jQuery, DevExpress); /*! Module core, file ui.js */ (function($, DX, undefined) { var ui = DX.ui = {}; var TemplateProvider = DX.Class.inherit({ getTemplateClass: function() { return Template }, supportDefaultTemplate: function() { return false }, getDefaultTemplate: function() { return null } }); var Template = DX.Class.inherit({ ctor: function(element, owner) { this._template = this._element = $(element).detach(); this._owner = owner }, render: function(container) { var renderedTemplate = this._template.clone(); container.append(renderedTemplate); return renderedTemplate }, dispose: function() { this._owner = null }, owner: function() { return this._owner } }); var GESTURE_LOCK_KEY = "dxGestureLock"; DX.registerActionExecutor({ designMode: {validate: function(e) { if (DX.designMode) e.cancel = true }}, gesture: {validate: function(e) { if (!e.args.length) return; var args = e.args[0], element = args[e.validatingTargetName] || args.element; while (element && element.length) { if (element.data(GESTURE_LOCK_KEY)) { e.cancel = true; break } element = element.parent() } }}, disabled: {validate: function(e) { if (!e.args.length) return; var args = e.args[0], element = args[e.validatingTargetName] || args.element; if (element && element.is(".dx-state-disabled, .dx-state-disabled *")) e.cancel = true }} }); $.extend(ui, { TemplateProvider: TemplateProvider, Template: Template, initViewport: function() { DX.utils.logger.warn("DevExpress.ui.initViewport is deprecated. Use DX.utils.initMobileViewport instead"); DX.utils.initMobileViewport() } }); ui.__internals = ui.__internals || {}; $.extend(ui.__internals, {Template: Template}) })(jQuery, DevExpress); /*! Module core, file ko.components.js */ (function($, DX, undefined) { if (!DX.support.hasKo) return; var ko = window.ko, ui = DX.ui, LOCKS_DATA_KEY = "dxKoLocks", CREATED_WITH_KO_DATA_KEY = "dxKoCreation"; var Locks = function() { var info = {}; var currentCount = function(lockName) { return info[lockName] || 0 }; return { obtain: function(lockName) { info[lockName] = currentCount(lockName) + 1 }, release: function(lockName) { var count = currentCount(lockName); if (count < 1) throw Error("Not locked"); if (count === 1) delete info[lockName]; else info[lockName] = count - 1 }, locked: function(lockName) { return currentCount(lockName) > 0 } } }; var registerComponentKoBinding = function(componentName) { ko.bindingHandlers[componentName] = {init: function(domNode, valueAccessor) { var element = $(domNode), ctorOptions = {}, optionNameToModelMap = {}; var applyModelValueToOption = function(optionName, modelValue) { var component = element.data(componentName), locks = element.data(LOCKS_DATA_KEY), optionValue = ko.utils.unwrapObservable(modelValue); if (ko.isWriteableObservable(modelValue)) optionNameToModelMap[optionName] = modelValue; if (component) { if (locks.locked(optionName)) return; locks.obtain(optionName); try { component.option(optionName, optionValue) } finally { locks.release(optionName) } } else ctorOptions[optionName] = optionValue }; var handleOptionChanged = function(optionName, optionValue) { if (!(optionName in optionNameToModelMap)) return; var element = this._$element, locks = element.data(LOCKS_DATA_KEY); if (locks.locked(optionName)) return; locks.obtain(optionName); try { optionNameToModelMap[optionName](optionValue) } finally { locks.release(optionName) } }; var createComponent = function() { element.data(CREATED_WITH_KO_DATA_KEY, true); element[componentName](ctorOptions); ctorOptions = null; element.data(LOCKS_DATA_KEY, new Locks); element.data(componentName).optionChanged.add(handleOptionChanged) }; ko.computed(function() { var component = element.data(componentName); if (component) component.beginUpdate(); $.each(ko.unwrap(valueAccessor()), function(modelName, modelValueExpr) { ko.computed(function() { applyModelValueToOption(modelName, modelValueExpr) }, null, {disposeWhenNodeIsRemoved: domNode}) }); if (component) component.endUpdate(); else createComponent() }, null, {disposeWhenNodeIsRemoved: domNode}); return {controlsDescendantBindings: ui[componentName] && ui[componentName].subclassOf(ui.Widget)} }} }; var KoComponent = DX.DOMComponent.inherit({_modelByElement: function(element) { if (element.length) return ko.dataFor(element.get(0)) }}); var originalRegisterComponent = DX.registerComponent; var registerKoComponent = function(name, componentClass) { originalRegisterComponent(name, componentClass); registerComponentKoBinding(name) }; ko.bindingHandlers.dxAction = {update: function(element, valueAccessor, allBindingsAccessor, viewModel) { var $element = $(element); var unwrappedValue = ko.utils.unwrapObservable(valueAccessor()), actionSource = unwrappedValue, actionOptions = {context: element}; if (unwrappedValue.execute) { actionSource = unwrappedValue.execute; $.extend(actionOptions, unwrappedValue) } var action = new DX.Action(actionSource, actionOptions); $element.off(".dxActionBinding").on("dxclick.dxActionBinding", function(e) { action.execute({ element: $element, model: viewModel, evaluate: function(expression) { var context = viewModel; if (expression.length > 0 && expression[0] === "$") context = ko.contextFor(element); var getter = DX.data.utils.compileGetter(expression); return getter(context) }, jQueryEvent: e }); if (!actionOptions.bubbling) e.stopPropagation() }) }}; var cleanKoData = function(element, andSelf) { var cleanNode = function() { ko.cleanNode(this) }; if (andSelf) element.each(cleanNode); else element.find("*").each(cleanNode) }; var originalEmpty = $.fn.empty; $.fn.empty = function() { cleanKoData(this, false); return originalEmpty.apply(this, arguments) }; var originalRemove = $.fn.remove; $.fn.remove = function(selector, keepData) { if (!keepData) { var subject = this; if (selector) subject = subject.filter(selector); cleanKoData(subject, true) } return originalRemove.call(this, selector, keepData) }; var originalHtml = $.fn.html; $.fn.html = function(value) { if (typeof value === "string") cleanKoData(this, false); return originalHtml.apply(this, arguments) }; DX.registerComponent = registerKoComponent; registerKoComponent("DOMComponent", KoComponent) })(jQuery, DevExpress); /*! Module core, file ng.components.js */ (function($, DX, undefined) { if (!DX.support.hasNg) return; var ui = DX.ui, compileSetter = DX.data.utils.compileSetter, compileGetter = DX.data.utils.compileGetter; var CREATED_WITH_NG_DATA_KEY = "dxNgCreation", TEMPLATES_DATA_KEY = "dxTemplates", COMPILER_DATA_KEY = "dxNgCompiler", DEFAULT_COMPILER_DATA_KEY = "dxDefaultCompilerGetter", ANONYMOUS_TEMPLATE_NAME = "template"; var phoneJsModule = DX.ng.module; var ComponentBuilder = DX.Class.inherit({ ctor: function(options) { this._componentName = options.componentName; this._$element = options.$element; this._$templates = options.$templates; this._scope = options.scope; this._compile = options.compile; this._ngOptions = options.ngOptions; this._componentDisposing = $.Callbacks(); this._$element.data(CREATED_WITH_NG_DATA_KEY, true); if (options.ngOptions.data) this._initDataScope(options.ngOptions.data) }, initDefaultCompilerGetter: function() { var that = this; that._$element.data(DEFAULT_COMPILER_DATA_KEY, function($template) { return that._compilerByTemplate($template) }) }, initTemplateCompilers: function() { var that = this; if (this._$templates) this._$templates.each(function(i, template) { $(template).data(COMPILER_DATA_KEY, that._compilerByTemplate(template)) }) }, initComponentWithBindings: function() { this._initComponent(this._scope); this._initComponentBindings() }, _initDataScope: function(data) { if (typeof data === "string") { var dataStr = data, rootScope = this._scope; data = rootScope.$eval(data); this._scope = rootScope.$new(); this._synchronizeDataScopes(rootScope, this._scope, data, dataStr) } $.extend(this._scope, data) }, _synchronizeDataScopes: function(parentScope, childScope, data, parentPrefix) { var that = this; $.each(data, function(fieldPath) { that._synchronizeScopeField({ parentScope: parentScope, childScope: childScope, fieldPath: fieldPath, parentPrefix: parentPrefix }) }) }, _initComponent: function(scope) { this._component = this._$element[this._componentName](this._evalOptions(scope)).data(this._componentName) }, _initComponentBindings: function() { var that = this, optionDependencies = {}; if (that._ngOptions.bindingOptions) $.each(that._ngOptions.bindingOptions, function(optionPath, valuePath) { var separatorIndex = optionPath.search(/\[|\./), optionForSubscribe = separatorIndex > -1 ? optionPath.substring(0, separatorIndex) : optionPath, prevWatchMethod, clearWatcher; 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)) ? "$watchCollection" : "$watch"; if (prevWatchMethod !== watchMethod) { if (clearWatcher) clearWatcher(); clearWatcher = that._scope[watchMethod](valuePath, watchCallback, true); prevWatchMethod = watchMethod } }; updateWatcher(); that._component.disposing.add(function() { clearWatcher(); that._componentDisposing.fire() }) }); that._component.optionChanged.add(function(optionName, optionValue) { if (that._scope.$root.$$phase === "$digest" || !optionDependencies || !optionDependencies[optionName]) return; safeApply(function(scope) { $.each(optionDependencies[optionName], function(optionPath, valuePath) { var setter = compileSetter(valuePath), getter = compileGetter(optionPath); var tmpData = {}; tmpData[optionName] = optionValue; setter(scope, getter(tmpData)) }) }, that._scope) }) }, _compilerByTemplate: function(template) { var that = this, scopeItemsPath = this._getScopeItemsPath(); return function(data, index) { var $resultMarkup = $(template).clone(), templateScope; if (data !== undefined) { var dataIsScope = data.$id, templateScope = dataIsScope ? data : that._createScopeWithData(data); $resultMarkup.on("$destroy", function() { var destroyAlreadyCalled = !templateScope.$parent; if (destroyAlreadyCalled) return; templateScope.$destroy() }) } else templateScope = that._scope; if (scopeItemsPath) that._synchronizeScopes(templateScope, scopeItemsPath, index); safeApply(that._compile($resultMarkup), templateScope); return $resultMarkup } }, _getScopeItemsPath: function() { if (ui[this._componentName].subclassOf(ui.CollectionContainerWidget) && this._ngOptions.bindingOptions) return this._ngOptions.bindingOptions.items }, _createScopeWithData: function(data) { var newScope = this._scope.$new(true); if (typeof data === "object") $.extend(newScope, data); else newScope.scopeValue = data; return newScope }, _synchronizeScopes: function(itemScope, parentPrefix, itemIndex) { var that = this, item = compileGetter(parentPrefix + "[" + itemIndex + "]")(this._scope); if (!$.isPlainObject(item)) item = {scopeValue: item}; $.each(item, function(itemPath) { that._synchronizeScopeField({ parentScope: that._scope, childScope: itemScope, fieldPath: itemPath, parentPrefix: parentPrefix, itemIndex: itemIndex }) }) }, _synchronizeScopeField: function(args) { var parentScope = args.parentScope, childScope = args.childScope, fieldPath = args.fieldPath, parentPrefix = args.parentPrefix, itemIndex = args.itemIndex; var innerPathSuffix = fieldPath === "scopeValue" ? "" : "." + fieldPath, collectionField = itemIndex !== undefined, optionOuterBag = [parentPrefix], optionOuterPath; if (collectionField) optionOuterBag.push("[", itemIndex, "]"); optionOuterBag.push(innerPathSuffix); optionOuterPath = optionOuterBag.join(""); var clearParentWatcher = parentScope.$watch(optionOuterPath, function(newValue, oldValue) { if (newValue !== oldValue) compileSetter(fieldPath)(childScope, newValue) }); var clearItemWatcher = childScope.$watch(fieldPath, function(newValue, oldValue) { if (newValue !== oldValue) { if (collectionField && !compileGetter(parentPrefix)(parentScope)[itemIndex]) { clearItemWatcher(); return } compileSetter(optionOuterPath)(parentScope, newValue) } }); this._componentDisposing.add([clearParentWatcher, clearItemWatcher]) }, _evalOptions: function(scope) { var result = $.extend({}, this._ngOptions); delete result.data; delete result.bindingOptions; if (this._ngOptions.bindingOptions) $.each(this._ngOptions.bindingOptions, function(key, value) { result[key] = scope.$eval(value) }); return result } }); var safeApply = function(func, scope) { if (scope.$root.$$phase) func(scope); else scope.$apply(function() { func(scope) }) }; var extractTemplates = function($element, componentName) { if ($element.data(TEMPLATES_DATA_KEY)) return $element.data(TEMPLATES_DATA_KEY); var $templates; if (ui[componentName] && ui[componentName].subclassOf(ui.Widget) && $.trim($element.html())) { var isAnonymousTemplate = !$element.children().first().attr("data-options"); if (isAnonymousTemplate) $templates = $("
").attr("data-options", "dxTemplate: { name: '" + ANONYMOUS_TEMPLATE_NAME + "' }").append($element.contents()); else $templates = $element.children().detach(); $element.data(TEMPLATES_DATA_KEY, $templates) } return $templates }; var NgComponent = DX.DOMComponent.inherit({ _modelByElement: function(element) { if (element.length) return element.scope() }, _createAction: function() { var action = this.callBase.apply(this, arguments); var component = this, wrappedAction = function() { var that = this, scope = component._modelByElement(component._element()), args = arguments; if (!scope || scope.$root.$$phase) return action.apply(that, args); return scope.$apply(function() { return action.apply(that, args) }) }; return wrappedAction } }); var originalRegisterComponent = DX.registerComponent; var registerNgComponent = function(componentName, componentClass) { originalRegisterComponent(componentName, componentClass); phoneJsModule.directive(componentName, ["$compile", function(compile) { return { restrict: "A", compile: function($element) { var $templates = extractTemplates($element, componentName); return function(scope, $element, attrs) { var componentBuilder = new ComponentBuilder({ componentName: componentName, compile: compile, $element: $element, scope: scope, ngOptions: attrs[componentName] ? scope.$eval(attrs[componentName]) : {}, $templates: $templates }); componentBuilder.initTemplateCompilers(); componentBuilder.initDefaultCompilerGetter(); componentBuilder.initComponentWithBindings() } } } }]) }; DX.registerComponent = registerNgComponent; registerNgComponent("DOMComponent", NgComponent) })(jQuery, DevExpress); /*! Module core, file ko.templates.js */ (function($, DX, undefined) { if (!DX.support.hasKo) return; var ko = window.ko, ui = DX.ui, CREATED_WITH_KO_DATA_KEY = "dxKoCreation"; var KoTemplate = ui.Template.inherit({ ctor: function(element) { this.callBase.apply(this, arguments); this._template = $("
").append(element); this._registerKoTemplate() }, _cleanTemplateElement: function() { this._element.each(function() { ko.cleanNode(this) }) }, _registerKoTemplate: function() { var template = this._template.get(0); new ko.templateSources.anonymousTemplate(template)['nodes'](template) }, render: function(container, data) { data = data !== undefined ? data : ko.dataFor(container.get(0)) || {}; var containerBindingContext = ko.contextFor(container[0]); var bindingContext = containerBindingContext ? containerBindingContext.createChildContext(data) : data; var renderBag = $("
").appendTo(container); ko.renderTemplate(this._template.get(0), bindingContext, null, renderBag.get(0)); var result = renderBag.contents(); container.append(result); renderBag.remove(); return result }, dispose: function() { this.callBase(); this._template.remove() } }); var KoTemplateProvider = ui.TemplateProvider.inherit({ getTemplateClass: function(widget) { return this._createdWithKo(widget) ? KoTemplate : this.callBase(widget) }, supportDefaultTemplate: function(widget) { return this._createdWithKo(widget) ? true : this.callBase(widget) }, getDefaultTemplate: function(widget) { if (this._createdWithKo(widget)) return defaultKoTemplate(widget.NAME) }, _createdWithKo: function(widget) { return !!widget._element().data(CREATED_WITH_KO_DATA_KEY) } }); var defaultKoTemplate = function() { var cache = {}; return function(widgetName) { if (!DEFAULT_ITEM_TEMPLATE_GENERATORS[widgetName]) widgetName = "base"; if (!cache[widgetName]) { var html = DEFAULT_ITEM_TEMPLATE_GENERATORS[widgetName](), markup = DX.utils.createMarkupFromString(html); cache[widgetName] = new KoTemplate(markup) } return cache[widgetName] } }(); var createElementWithBindAttr = function(tagName, bindings, closeTag, additionalProperties) { closeTag = closeTag === undefined ? true : closeTag; var bindAttr = $.map(bindings, function(value, key) { return key + ":" + value }).join(","); additionalProperties = additionalProperties || ""; return "<" + tagName + " data-bind=\"" + bindAttr + "\" " + additionalProperties + ">" + (closeTag ? "" : "") }; var defaultKoTemplateBasicBindings = {css: "{ 'dx-state-disabled': $data.disabled, 'dx-state-invisible': !($data.visible === undefined || ko.unwrap($data.visible)) }"}; var DEFAULT_ITEM_TEMPLATE_GENERATORS = {base: function() { var template = [createElementWithBindAttr("div", defaultKoTemplateBasicBindings, false)], htmlBinding = createElementWithBindAttr("div", {html: "html"}), textBinding = createElementWithBindAttr("div", {text: "text"}), primitiveBinding = createElementWithBindAttr("div", {text: "String($data)"}); template.push("", htmlBinding, "", "", textBinding, "", "", primitiveBinding, "", "
"); return template.join("") }}; DEFAULT_ITEM_TEMPLATE_GENERATORS.dxPivotTabs = function() { var template = DEFAULT_ITEM_TEMPLATE_GENERATORS.base(), titleBinding = createElementWithBindAttr("span", {text: "title"}); var divInnerStart = template.indexOf(">") + 1, divInnerFinish = template.length - 6; template = [template.substring(0, divInnerStart), titleBinding, template.substring(divInnerFinish, template.length)]; return template.join("") }; DEFAULT_ITEM_TEMPLATE_GENERATORS.dxPanorama = function() { var template = DEFAULT_ITEM_TEMPLATE_GENERATORS.base(), headerBinding = createElementWithBindAttr("div", {text: "header"}, true, 'class="dx-panorama-item-header"'); var divInnerStart = template.indexOf(">") + 1; template = [template.substring(0, divInnerStart), "", headerBinding, "", template.substring(divInnerStart, template.length)]; return template.join("") }; DEFAULT_ITEM_TEMPLATE_GENERATORS.dxList = function() { var template = DEFAULT_ITEM_TEMPLATE_GENERATORS.base(), keyBinding = createElementWithBindAttr("div", {text: "key"}); template = [template.substring(0, template.length - 6), "" + keyBinding + "", "
"]; return template.join("") }; DEFAULT_ITEM_TEMPLATE_GENERATORS.dxToolbar = function() { var template = DEFAULT_ITEM_TEMPLATE_GENERATORS.base(); 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("") }; DEFAULT_ITEM_TEMPLATE_GENERATORS.dxGallery = function() { var template = DEFAULT_ITEM_TEMPLATE_GENERATORS.base(), primitiveBinding = createElementWithBindAttr("div", {text: "String($data)"}), imgBinding = createElementWithBindAttr("img", {attr: "{ src: String($data) }"}, false); template = template.replace(primitiveBinding, imgBinding); return template }; DEFAULT_ITEM_TEMPLATE_GENERATORS.dxTabs = function() { var template = DEFAULT_ITEM_TEMPLATE_GENERATORS.base(), baseTextBinding = createElementWithBindAttr("div", {text: "text"}), iconBinding = createElementWithBindAttr("span", { attr: "{ 'class': 'dx-icon-' + $data.icon }", css: "{ 'dx-icon': true }" }), iconSrcBinding = createElementWithBindAttr("img", { attr: "{ src: $data.iconSrc }", css: "{ 'dx-icon': true }" }, false), textBinding = "" + iconBinding + "" + "" + iconSrcBinding + "" + ""; template = template.replace("", "").replace(baseTextBinding, textBinding); return template }; DEFAULT_ITEM_TEMPLATE_GENERATORS.dxActionSheet = function() { return createElementWithBindAttr("div", {dxButton: "{ text: $data.text, clickAction: $data.clickAction, type: $data.type, disabled: !!ko.unwrap($data.disabled) }"}) }; DEFAULT_ITEM_TEMPLATE_GENERATORS.dxNavBar = DEFAULT_ITEM_TEMPLATE_GENERATORS.dxTabs; DEFAULT_ITEM_TEMPLATE_GENERATORS.dxMenu = function() { var template = [createElementWithBindAttr("div", defaultKoTemplateBasicBindings, false)], iconBinding = createElementWithBindAttr("span", { attr: "{ 'class': 'dx-icon-' + $data.icon }", css: "{ 'dx-icon': true }" }), iconSrcBinding = createElementWithBindAttr("img", { attr: "{ src: $data.iconSrc }", css: "{ 'dx-icon': true }" }), textBinding = createElementWithBindAttr("span", { text: "text", css: "{ 'dx-menu-item-text': true }" }), primitiveBinding = createElementWithBindAttr("span", { text: "String($data)", css: "{ 'dx-menu-item-text': true }" }), popout = '
'; template.push('
', '', iconBinding, '', '', iconSrcBinding, '', '', textBinding, '', '', primitiveBinding, '', '', popout, '', '
', '
'); return template.join("") }; DEFAULT_ITEM_TEMPLATE_GENERATORS.dxContextMenu = DEFAULT_ITEM_TEMPLATE_GENERATORS.dxMenu; $.extend(ui, { TemplateProvider: KoTemplateProvider, Template: KoTemplate, defaultTemplate: defaultKoTemplate }); ui.__internals = ui.__internals || {}; $.extend(ui.__internals, {KoTemplate: KoTemplate}) })(jQuery, DevExpress); /*! Module core, file ng.templates.js */ (function($, DX, undefined) { if (!DX.support.hasNg) return; var ui = DX.ui; var CREATED_WITH_NG_DATA_KEY = "dxNgCreation", COMPILER_DATA_KEY = "dxNgCompiler", DEFAULT_COMPILER_DATA_KEY = "dxDefaultCompilerGetter"; var NgTemplate = ui.Template.inherit({ ctor: function() { this.callBase.apply(this, arguments); this._compiler = this._template.data(COMPILER_DATA_KEY) }, render: function(container, data, index) { var compiler = this._compiler, result = $.isFunction(compiler) ? compiler(data, index) : compiler; container.append(result); return result }, setCompiler: function(compilerGetter) { this._compiler = compilerGetter(this._element) } }); var NgTemplateProvider = ui.TemplateProvider.inherit({ getTemplateClass: function(widget) { if (this._createdWithNg(widget)) return NgTemplate; return this.callBase(widget) }, supportDefaultTemplate: function(widget) { return this._createdWithNg(widget) ? true : this.callBase(widget) }, getDefaultTemplate: function(widget) { if (this._createdWithNg(widget)) { var compilerGetter = widget._element().data(DEFAULT_COMPILER_DATA_KEY), template = defaultNgTemplate(widget.NAME); template.setCompiler(compilerGetter); return template } }, _createdWithNg: function(widget) { return !!widget._element().data(CREATED_WITH_NG_DATA_KEY) } }); var defaultNgTemplate = function() { var cache = {}; return function(widgetName) { if (!DEFAULT_ITEM_TEMPLATE_GENERATORS[widgetName]) widgetName = "base"; if (!cache[widgetName]) cache[widgetName] = DEFAULT_ITEM_TEMPLATE_GENERATORS[widgetName](); return new NgTemplate(cache[widgetName]) } }(); var baseElements = { container: function() { return $("
").attr("ng-class", "{ 'dx-state-invisible': !visible && visible != undefined, 'dx-state-disabled': !!disabled }") }, 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 DEFAULT_ITEM_TEMPLATE_GENERATORS = {base: function() { return baseElements.container().append(baseElements.html()).append(baseElements.text()).append(baseElements.primitive()) }}; DEFAULT_ITEM_TEMPLATE_GENERATORS.dxList = function() { return DEFAULT_ITEM_TEMPLATE_GENERATORS.base().append($("
").attr("ng-if", "key").attr("ng-bind", "key")) }; DEFAULT_ITEM_TEMPLATE_GENERATORS.dxToolbar = function() { var template = DEFAULT_ITEM_TEMPLATE_GENERATORS.base(); $.each(["button", "tabs", "dropDownMenu"], function(i, widgetName) { var bindingName = "dx-" + DX.inflector.dasherize(this); $("
").attr("ng-if", "widget === '" + widgetName + "'").attr(bindingName, "options").appendTo(template) }); return template }; DEFAULT_ITEM_TEMPLATE_GENERATORS.dxGallery = function() { return baseElements.container().append(baseElements.html()).append(baseElements.text()).append($("").attr("ng-if", "scopeValue").attr("ng-src", "{{'' + scopeValue}}")) }; DEFAULT_ITEM_TEMPLATE_GENERATORS.dxTabs = function() { var container = baseElements.container(); var text = $("").addClass("dx-tab-text").attr("ng-bind", "text").attr("ng-if", "text"), icon = $("").attr("ng-if", "icon").addClass("dx-icon").attr("ng-class", "'dx-icon-' + icon"), iconSrc = $("").attr("ng-if", "iconSrc").addClass("dx-icon").attr("ng-src", "{{iconSrc}}"); return container.append(baseElements.html()).append(icon).append(iconSrc).append(text).append(baseElements.primitive()) }; DEFAULT_ITEM_TEMPLATE_GENERATORS.dxMenu = function() { var container = baseElements.container(); var content = $("
").addClass("dx-menu-item-content"), text = $("").attr("ng-if", "text").addClass("dx-menu-item-text").attr("ng-bind", "text"), icon = $("").attr("ng-if", "icon").addClass("dx-icon").attr("ng-class", "'dx-icon-' + icon"), iconSrc = $("").attr("ng-if", "iconSrc").addClass("dx-icon").attr("ng-src", "{{iconSrc}}"), popout = $("").addClass("dx-menu-item-popout-container").attr("ng-if", "items").append($("
").addClass("dx-menu-item-popout")); content.append(baseElements.html()).append(icon).append(iconSrc).append(text).append(popout).append(baseElements.primitive()).appendTo(container); return container }, DEFAULT_ITEM_TEMPLATE_GENERATORS.dxActionSheet = function() { return $("
").attr("dx-button", "{ bindingOptions: { text: 'text', clickAction: 'clickAction', type: 'type', disabled: 'disabled' } }") }; DEFAULT_ITEM_TEMPLATE_GENERATORS.dxNavBar = DEFAULT_ITEM_TEMPLATE_GENERATORS.dxTabs; $.extend(ui, { Template: NgTemplate, TemplateProvider: NgTemplateProvider }) })(jQuery, DevExpress); /*! Module core, file ui.themes.js */ (function($, DX, undefined) { var DX_LINK_SELECTOR = "link[rel=dx-theme]", THEME_ATTR = "data-theme", ACTIVE_ATTR = "data-active"; var context, $activeThemeLink, knownThemes, currentThemeName, pendingThemeName; var THEME_MARKER_PREFIX = "dx."; function readThemeMarker() { var element = $("
", context).addClass("dx-theme-marker").appendTo(context.documentElement), result; try { result = element.css("font-family"); if (!result) return null; result = result.replace(/["']/g, ""); if (result.substr(0, THEME_MARKER_PREFIX.length) !== THEME_MARKER_PREFIX) return null; return result.substr(THEME_MARKER_PREFIX.length) } finally { element.remove() } } function waitForThemeLoad(themeName, callback) { var timerId, waitStartTime; pendingThemeName = themeName; function handleLoaded() { pendingThemeName = null; callback() } if (isPendingThemeLoaded()) handleLoaded(); else { waitStartTime = $.now(); timerId = setInterval(function() { var isLoaded = isPendingThemeLoaded(), isTimeout = !isLoaded && $.now() - waitStartTime > 15 * 1000; if (isTimeout) DX.utils.logger.warn("Theme loading timed out: " + pendingThemeName); if (isLoaded || isTimeout) { clearInterval(timerId); handleLoaded() } }, 10) } } function isPendingThemeLoaded() { return !pendingThemeName || readThemeMarker() === pendingThemeName } function processMarkup() { var $allThemeLinks = $(DX_LINK_SELECTOR, context); if (!$allThemeLinks.length) return; knownThemes = {}; $activeThemeLink = $(DX.utils.createMarkupFromString(""), context); $allThemeLinks.each(function() { var link = $(this, context), fullThemeName = link.attr(THEME_ATTR), url = link.attr("href"), isActive = link.attr(ACTIVE_ATTR) === "true"; knownThemes[fullThemeName] = { url: url, isActive: isActive } }); $allThemeLinks.last().after($activeThemeLink); $allThemeLinks.remove() } function resolveFullThemeName(desiredThemeName) { var desiredThemeParts = desiredThemeName.split("."), result = null; if (knownThemes) $.each(knownThemes, function(knownThemeName, themeData) { var knownThemeParts = knownThemeName.split("."); if (knownThemeParts[0] !== desiredThemeParts[0]) return; if (desiredThemeParts[1] && desiredThemeParts[1] !== knownThemeParts[1]) return; if (!result || themeData.isActive) result = knownThemeName; if (themeData.isActive) return false }); return result } function initContext(newContext) { try { if (newContext !== context) knownThemes = null } catch(x) { knownThemes = null } context = newContext } function init(options) { options = options || {}; initContext(options.context || document); processMarkup(); currentThemeName = undefined; current(options) } function current(options) { if (!arguments.length) return currentThemeName || readThemeMarker(); options = options || {}; if (typeof options === "string") options = {theme: options}; var isAutoInit = options._autoInit, loadCallback = options.loadCallback, currentThemeData; currentThemeName = options.theme || currentThemeName; if (isAutoInit && !currentThemeName) currentThemeName = themeNameFromDevice(DX.devices.current()); currentThemeName = resolveFullThemeName(currentThemeName); if (currentThemeName) currentThemeData = knownThemes[currentThemeName]; if (currentThemeData) { $activeThemeLink.removeAttr("href"); $activeThemeLink.attr("href", knownThemes[currentThemeName].url); if (loadCallback) waitForThemeLoad(currentThemeName, loadCallback); else if (pendingThemeName) pendingThemeName = currentThemeName } else if (isAutoInit) { if (loadCallback) loadCallback() } else throw Error("Unknown theme: " + currentThemeName); } function themeNameFromDevice(device) { var themeName = device.platform, majorVersion = device.version && device.version[0]; if (themeName === "ios" && (!majorVersion || majorVersion > 6)) themeName += "7"; return themeName } function getCssClasses(themeName) { themeName = themeName || current(); var result = [], themeNameParts = themeName && themeName.split("."); if (themeNameParts) { result.push("dx-theme-" + themeNameParts[0], "dx-theme-" + themeNameParts[0] + "-typography"); if (themeNameParts.length > 1) result.push("dx-color-scheme-" + themeNameParts[1]) } return result } function attachCssClasses(element, themeName) { $(element).addClass(getCssClasses(themeName).join(" ")) } function detachCssClasses(element, themeName) { $(element).removeClass(getCssClasses(themeName).join(" ")) } $.holdReady(true); init({ _autoInit: true, loadCallback: function() { $.holdReady(false) } }); $(function() { if ($(DX_LINK_SELECTOR, context).length) throw Error("LINK[rel=dx-theme] tags must go before DevExpress included scripts"); }); DX.ui.themes = { init: init, current: current, attachCssClasses: attachCssClasses, detachCssClasses: detachCssClasses }; DX.ui.themes.__internals = { themeNameFromDevice: themeNameFromDevice, waitForThemeLoad: waitForThemeLoad, resetTheme: function() { $activeThemeLink.attr("href", "about:blank"); currentThemeName = null; pendingThemeName = null } } })(jQuery, DevExpress); /*! Module core, file ui.events.js */ (function($, DX, undefined) { var ui = DX.ui, eventNS = $.event, specialNS = eventNS.special, EVENT_SOURCES_REGEX = { mouse: /(mouse|wheel|click)/i, wheel: /wheel/i, touch: /^touch/i, keyboard: /^key/i, pointer: /pointer/i }; var eventSource = function(e) { var result = "other"; $.each(EVENT_SOURCES_REGEX, function(key) { if (this.test(e.type)) { result = key; return false } }); return result }; var isPointerEvent = function(e) { return eventSource(e) === "pointer" }; var isMouseEvent = function(e) { return eventSource(e) === "mouse" || isPointerEvent(e) && e.pointerType === "mouse" }; var isTouchEvent = function(e) { return eventSource(e) === "touch" || isPointerEvent(e) && e.pointerType === "touch" }; var isKeyboardEvent = function(e) { return eventSource(e) === "keyboard" }; var isMouseWheelEvent = function(e) { return EVENT_SOURCES_REGEX["wheel"].test(e.type) }; var addNamespace = function(eventNames, namespace) { if (!namespace) throw Error("Namespace is not defined"); if (typeof eventNames === "string") return addNamespace(eventNames.split(/\s+/g), namespace); $.each(eventNames, function(index, eventName) { eventNames[index] = eventName + "." + namespace }); return eventNames.join(" ") }; var eventData = function(e) { if (isPointerEvent(e) && isTouchEvent(e)) { var touch = (e.originalEvent.originalEvent || e.originalEvent).changedTouches[0]; return { x: touch.pageX, y: touch.pageY, time: e.timeStamp } } if (isMouseEvent(e)) return { x: e.pageX, y: e.pageY, time: e.timeStamp }; if (isTouchEvent(e)) { var touch = (e.changedTouches || e.originalEvent.changedTouches)[0]; return { x: touch.pageX, y: touch.pageY, time: e.timeStamp } } }; var eventDelta = function(from, to) { return { x: to.x - from.x, y: to.y - from.y, time: to.time - from.time || 1 } }; var hasTouches = function(e) { if (isTouchEvent(e)) return (e.originalEvent.touches || []).length; return 0 }; var needSkipEvent = function(e) { var $target = $(e.target), touchInInput = $target.is("input, textarea, select"); if (isMouseWheelEvent(e) && touchInInput) return false; if (isMouseEvent(e)) return touchInInput || e.which > 1; if (isTouchEvent(e)) return touchInInput && $target.is(":focus") || (e.originalEvent.changedTouches || e.originalEvent.originalEvent.changedTouches).length !== 1 }; var createEvent = function(sourceEvent, props) { var event = $.Event(sourceEvent), originalEvent = event.originalEvent, propNames = $.event.props.slice(); if (isMouseEvent(sourceEvent) || isTouchEvent(sourceEvent)) $.merge(propNames, $.event.mouseHooks.props); if (isKeyboardEvent(sourceEvent)) $.merge(propNames, $.event.keyHooks.props); if (originalEvent) $.each(propNames, function() { event[this] = originalEvent[this] }); if (props) $.extend(event, props); return event }; var fireEvent = function(props) { var event = createEvent(props.originalEvent, props); $.event.trigger(event, null, props.target || event.target); return event }; var handleGestureEvent = function(e, type) { var gestureEvent = $(e.target).data("dxGestureEvent"); if (!gestureEvent || gestureEvent === type) { $(e.target).data("dxGestureEvent", type); return true } return false }; var registerEvent = function(eventName, eventObject) { var strategy = {}; if ("noBubble" in eventObject) strategy.noBubble = eventObject.noBubble; if ("bindType" in eventObject) strategy.bindType = eventObject.bindType; if ("delegateType" in eventObject) strategy.delegateType = eventObject.delegateType; $.each(["setup", "teardown", "add", "remove", "trigger", "handle", "_default", "dispose"], function(_, methodName) { if (!eventObject[methodName]) return; strategy[methodName] = function() { var args = $.makeArray(arguments); args.unshift(this); return eventObject[methodName].apply(eventObject, args) } }); specialNS[eventName] = strategy }; ui.events = { eventSource: eventSource, isPointerEvent: isPointerEvent, isMouseEvent: isMouseEvent, isTouchEvent: isTouchEvent, isKeyboardEvent: isKeyboardEvent, addNamespace: addNamespace, hasTouches: hasTouches, eventData: eventData, eventDelta: eventDelta, needSkipEvent: needSkipEvent, createEvent: createEvent, fireEvent: fireEvent, handleGestureEvent: handleGestureEvent, registerEvent: registerEvent } })(jQuery, DevExpress); /*! Module core, file ko.events.js */ (function($, DX, undefined) { if (!DX.support.hasKo) return; var ko = window.ko, events = DX.ui.events; var originalRegisterEvent = events.registerEvent; var registerKoEvent = function(eventName, eventObject) { originalRegisterEvent(eventName, eventObject); var koBindingEventName = events.addNamespace(eventName, eventName + "Binding"); ko.bindingHandlers[eventName] = {update: function(element, valueAccessor, allBindingsAccessor, viewModel) { var $element = $(element), unwrappedValue = ko.utils.unwrapObservable(valueAccessor()), eventSource = unwrappedValue.execute ? unwrappedValue.execute : unwrappedValue; $element.off(koBindingEventName).on(koBindingEventName, $.isPlainObject(unwrappedValue) ? unwrappedValue : {}, function(e) { eventSource(viewModel, e) }) }} }; $.extend(events, {registerEvent: registerKoEvent}) })(jQuery, DevExpress); /*! Module core, file ng.events.js */ (function($, DX, undefined) { if (!DX.support.hasNg) return; var events = DX.ui.events; var originalRegisterEvent = events.registerEvent; var registerNgEvent = function(eventName, eventObject) { originalRegisterEvent(eventName, eventObject); var ngEventName = eventName.slice(0, 2) + eventName.charAt(2).toUpperCase() + eventName.slice(3); DX.ng.module.directive(ngEventName, ['$parse', function($parse) { return function(scope, element, attr) { var attrValue = $.trim(attr[ngEventName]), handler, eventOptions = {}; if (attrValue.charAt(0) === "{") { eventOptions = scope.$eval(attrValue); handler = $parse(eventOptions.execute) } else handler = $parse(attr[ngEventName]); element.on(eventName, eventOptions, function(e) { scope.$apply(function() { handler(scope, {$event: e}) }) }) } }]) }; $.extend(events, {registerEvent: registerNgEvent}) })(jQuery, DevExpress); /*! Module core, file ui.hierarchicalKeyDownProcessor.js */ (function($, DX, undefined) { var ui = DX.ui, events = ui.events; ui.HierarchicalKeyDownProcessor = DX.Class.inherit({ _keydown: events.addNamespace("keydown", "HierarchicalKeyDownProcessor"), codes: { "9": "tab", "13": "enter", "27": "escape", "33": "pageUp", "34": "pageDown", "37": "leftArrow", "38": "upArrow", "39": "rightArrow", "40": "downArrow", "32": "space", "70": "F", "65": "A" }, ctor: function(options) { var _this = this; options = options || {}; if (options.element) this._element = $(options.element); this._handler = options.handler; this._context = options.context; this._childProcessors = []; if (this._element) this._element.on(this._keydown, function(e) { _this.process(e) }) }, dispose: function() { if (this._element) this._element.off(this._keydown); this._element = undefined; this._handler = undefined; this._context = undefined; this._childProcessors = undefined }, attachChildProcessor: function() { var childProcessor = new ui.HierarchicalKeyDownProcessor; this._childProcessors.push(childProcessor); return childProcessor }, reinitialize: function(childHandler, childContext) { this._context = childContext; this._handler = childHandler; return this }, process: function(e) { var args = { key: this.codes[e.which], ctrl: e.ctrlKey, shift: e.shiftKey, originalEvent: e }; if (this.codes[e.which] && this._handler && this._handler.call(this._context, args)) $.each(this._childProcessors, function(index, childProcessor) { childProcessor.process(e) }) } }) })(jQuery, DevExpress); /*! Module core, file ui.dialog.js */ (function($, DX, undefined) { var ui = DX.ui, utils = DX.utils; var DEFAULT_BUTTON = { text: "OK", clickAction: function() { return true } }; var DX_DIALOG_CLASSNAME = "dx-dialog", DX_DIALOG_WRAPPER_CLASSNAME = DX_DIALOG_CLASSNAME + "-wrapper", DX_DIALOG_ROOT_CLASSNAME = DX_DIALOG_CLASSNAME + "-root", DX_DIALOG_CONTENT_CLASSNAME = DX_DIALOG_CLASSNAME + "-content", DX_DIALOG_MESSAGE_CLASSNAME = DX_DIALOG_CLASSNAME + "-message", DX_DIALOG_BUTTONS_CLASSNAME = DX_DIALOG_CLASSNAME + "-buttons", DX_DIALOG_BUTTON_CLASSNAME = DX_DIALOG_CLASSNAME + "-button"; var FakeDialogComponent = DX.Component.inherit({ NAME: "dxDialog", ctor: function(element, options) { this.callBase(options) }, _defaultOptionsRules: function() { return this.callBase().slice(0).concat([{ device: [{platform: "ios"}, {platform: "ios7"}], options: {width: 276} }, { device: {platform: "android"}, options: { lWidth: "60%", pWidth: "80%" } }, { device: { platform: "win8", phone: false }, options: {width: function() { return $(window).width() }} }, { device: { platform: "win8", phone: true }, options: {position: { my: "top center", at: "top center", of: window, offset: "0 0" }} }]) } }); var dialog = function(options) { var that = this, result; if (!ui.dxPopup) throw new Error("DevExpress.ui.dxPopup required"); var deferred = $.Deferred(); var defaultOptions = (new FakeDialogComponent).option(); options = $.extend(defaultOptions, options); var $holder = $(DX.overlayTargetContainer()); var $element = $("
").addClass(DX_DIALOG_CLASSNAME).appendTo($holder); var $message = $("
").addClass(DX_DIALOG_MESSAGE_CLASSNAME).html(String(options.message)); var $buttons = $("
").addClass(DX_DIALOG_BUTTONS_CLASSNAME); var popupInstance = $element.dxPopup({ title: options.title || that.title, height: "auto", width: function() { var isPortrait = $(window).height() > $(window).width(), key = (isPortrait ? "p" : "l") + "Width", widthOption = options.hasOwnProperty(key) ? options[key] : options["width"]; return $.isFunction(widthOption) ? widthOption() : widthOption }, contentReadyAction: function() { popupInstance.content().addClass(DX_DIALOG_CONTENT_CLASSNAME).append($message).append($buttons) }, animation: { show: { type: "pop", duration: 400 }, hide: { type: "pop", duration: 400, to: { opacity: 0, scale: 0 }, from: { opacity: 1, scale: 1 } } }, rtlEnabled: DX.rtlEnabled }).data("dxPopup"); popupInstance._wrapper().addClass(DX_DIALOG_WRAPPER_CLASSNAME); if (options.position) popupInstance.option("position", options.position); $.each(options.buttons || [DEFAULT_BUTTON], function() { var button = $("
").addClass(DX_DIALOG_BUTTON_CLASSNAME).appendTo($buttons); var action = new DX.Action(this.clickAction, {context: popupInstance}); button.dxButton($.extend(this, {clickAction: function() { result = action.execute(arguments); hide() }})) }); popupInstance._wrapper().addClass(DX_DIALOG_ROOT_CLASSNAME); function show() { popupInstance.show(); utils.resetActiveElement(); return deferred.promise() } function hide(value) { popupInstance.hide().done(function() { popupInstance._element().remove() }); deferred.resolve(result || value) } return { show: show, hide: hide } }; var alert = function(message, title) { var dialogInstance, options = $.isPlainObject(message) ? message : { title: title, message: message }; dialogInstance = ui.dialog.custom(options); return dialogInstance.show() }; var confirm = function(message, title) { var dialogInstance, options = $.isPlainObject(message) ? message : { title: title, message: message, buttons: [{ text: Globalize.localize("Yes"), clickAction: function() { return true } }, { text: Globalize.localize("No"), clickAction: function() { return false } }] }; dialogInstance = ui.dialog.custom(options); return dialogInstance.show() }; var notify = function(message, type, displayTime) { var options = $.isPlainObject(message) ? message : {message: message}; if (!ui.dxToast) { alert(options.message); return } var userHiddenAction = options.hiddenAction; $.extend(options, { type: type, displayTime: displayTime, hiddenAction: function(args) { args.element.remove(); new DX.Action(userHiddenAction, {context: args.model}).execute(arguments) } }); $("
").appendTo(DX.overlayTargetContainer()).dxToast(options).dxToast("instance").show() }; $.extend(ui, { notify: notify, dialog: { custom: dialog, alert: alert, confirm: confirm, FakeDialogComponent: FakeDialogComponent } }) })(jQuery, DevExpress); /*! Module core, file ui.dataHelper.js */ (function($, DX, undefined) { var data = DX.data; var DATA_SOURCE_OPTIONS_METHOD = "_dataSourceOptions", DATA_SOURCE_CHANGED_METHOD = "_handleDataSourceChanged", DATA_SOURCE_LOAD_ERROR_METHOD = "_handleDataSourceLoadError", DATA_SOURCE_LOADING_CHANGED_METHOD = "_handleDataSourceLoadingChanged"; DX.ui.DataHelperMixin = { ctor: function() { this.disposing.add(function() { this._disposeDataSource() }) }, _refreshDataSource: function() { this._initDataSource(); this._loadDataSource() }, _initDataSource: function() { var dataSourceOptions = this.option("dataSource"), widgetDataSourceOptions, dataSourceType; this._disposeDataSource(); if (dataSourceOptions) { if (dataSourceOptions instanceof data.DataSource) { this._isSharedDataSource = true; this._dataSource = dataSourceOptions } else { widgetDataSourceOptions = DATA_SOURCE_OPTIONS_METHOD in this ? this[DATA_SOURCE_OPTIONS_METHOD]() : {}; dataSourceType = this._dataSourceType ? this._dataSourceType() : data.DataSource; this._dataSource = new dataSourceType($.extend(true, {}, widgetDataSourceOptions, data.utils.normalizeDataSourceOptions(dataSourceOptions))) } this._addDataSourceHandlers() } }, _addDataSourceHandlers: function() { if (DATA_SOURCE_CHANGED_METHOD in this) this._addDataSourceChangeHandler(); if (DATA_SOURCE_LOAD_ERROR_METHOD in this) this._addDataSourceLoadErrorHandler(); if (DATA_SOURCE_LOADING_CHANGED_METHOD in this) this._addDataSourceLoadingChangedHandler() }, _addDataSourceChangeHandler: function() { var that = this, dataSource = this._dataSource; this._dataSourceChangedHandler = function() { that[DATA_SOURCE_CHANGED_METHOD](dataSource.items()) }; dataSource.changed.add(this._dataSourceChangedHandler) }, _addDataSourceLoadErrorHandler: function() { this._dataSourceLoadErrorHandler = $.proxy(this[DATA_SOURCE_LOAD_ERROR_METHOD], this); this._dataSource.loadError.add(this._dataSourceLoadErrorHandler) }, _addDataSourceLoadingChangedHandler: function() { this._dataSourceLoadingChangedHandler = $.proxy(this[DATA_SOURCE_LOADING_CHANGED_METHOD], this); this._dataSource.loadingChanged.add(this._dataSourceLoadingChangedHandler) }, _loadDataSource: function() { if (this._dataSource) { var dataSource = this._dataSource; if (dataSource.isLoaded()) this._dataSourceChangedHandler(); else dataSource.load() } }, _loadSingle: function(key, value) { key = key === "this" ? this._dataSource.key() || "this" : key; return this._dataSource.loadSingle(key, value) }, _disposeDataSource: function() { if (this._dataSource) { if (this._isSharedDataSource) { delete this._isSharedDataSource; this._dataSource.changed.remove(this._dataSourceChangedHandler); this._dataSource.loadError.remove(this._dataSourceLoadErrorHandler); this._dataSource.loadingChanged.remove(this._dataSourceLoadingChangedHandler) } else this._dataSource.dispose(); delete this._dataSource; delete this._dataSourceChangedHandler; delete this._dataSourceLoadErrorHandler; delete this._dataSourceLoadingChangedHandler } } } })(jQuery, DevExpress); /*! Module core, file ui.events.mspointer.js */ (function($, DX, undefined) { var POINTER_TYPE_MAP = { 2: "touch", 3: "pen", 4: "mouse" }; var pointerEventHook = { filter: function(event, originalEvent) { var pointerType = originalEvent.pointerType; if ($.isNumeric(pointerType)) event.pointerType = POINTER_TYPE_MAP[pointerType]; return event }, props: $.event.mouseHooks.props.concat(["pointerId", "originalTarget", "namespace", "width", "height", "pressure", "result", "tiltX", "charCode", "tiltY", "detail", "isPrimary", "prevValue"]) }; $.each(["MSPointerDown", "MSPointerMove", "MSPointerUp", "MSPointerCancel", "MSPointerOver", "MSPointerOut", "MSPointerEnter", "MSPointerLeave", "pointerdown", "pointermove", "pointerup", "pointercancel", "pointerover", "pointerout", "pointerenter", "pointerleave"], function() { $.event.fixHooks[this] = pointerEventHook }) })(jQuery, DevExpress); /*! Module core, file ui.events.touch.js */ (function($, DX, undefined) { var touchEventHook = { filter: function(event, originalEvent) { if (originalEvent.changedTouches.length) $.each(["pageX", "pageY", "screenX", "screenY", "clientX", "clientY"], function() { event[this] = originalEvent.changedTouches[0][this] }); return event }, props: $.event.mouseHooks.props.concat(["touches", "changedTouches", "targetTouches", "detail", "result", "namespace", "originalTarget", "charCode", "prevValue"]) }; $.each(["touchstart", "touchmove", "touchend", "touchcancel"], function() { $.event.fixHooks[this] = touchEventHook }) })(jQuery, DevExpress); /*! Module core, file ui.events.pointer.js */ (function($, DX, undefined) { var ui = DX.ui, support = DX.support, device = $.proxy(DX.devices.real, DX.devices), events = ui.events; var POINTER_EVENTS_NAMESPACE = "dxPointerEvents", MouseStrategyEventMap = { dxpointerdown: "mousedown", dxpointermove: "mousemove", dxpointerup: "mouseup", dxpointercancel: "" }, TouchStrategyEventMap = { dxpointerdown: "touchstart", dxpointermove: "touchmove", dxpointerup: "touchend", dxpointercancel: "touchcancel" }, PointerStrategyEventMap = { dxpointerdown: "pointerdown", dxpointermove: "pointermove", dxpointerup: "pointerup", dxpointercancel: "pointercancel" }, MouseAndTouchStrategyEventMap = { dxpointerdown: "touchstart mousedown", dxpointermove: "touchmove mousemove", dxpointerup: "touchend mouseup", dxpointercancel: "touchcancel" }; var eventMap = function() { if (support.touch && !(device().tablet || device().phone)) return MouseAndTouchStrategyEventMap; if (support.pointer) return MouseStrategyEventMap; if (support.touch) return TouchStrategyEventMap; return MouseStrategyEventMap }(); var skipTouchWithSameIdentifier = function(pointerEvent) { return device().platform === "ios" && (pointerEvent === "dxpointerdown" || pointerEvent === "dxpointerup") }; var SingleEventStrategy = DX.Class.inherit({ ctor: function(eventName, originalEvents) { this._eventName = eventName; this._eventNamespace = [POINTER_EVENTS_NAMESPACE, ".", this._eventName].join(""); this._originalEvents = originalEvents; this._pointerId = 0; this._handlerCount = 0 }, _handler: function(e) { if (this._eventName === "dxpointerdown") $(e.target).data("dxGestureEvent", null); if (events.isTouchEvent(e) && skipTouchWithSameIdentifier(this._eventName)) { var touch = e.changedTouches[0]; if (this._pointerId === touch.identifier && this._pointerId !== 0) return; this._pointerId = touch.identifier } return events.fireEvent({ type: this._eventName, pointerType: events.eventSource(e), originalEvent: e }) }, setup: function() { if (this._handlerCount > 0) return; $(document).on(events.addNamespace(this._originalEvents, this._eventNamespace), $.proxy(this._handler, this)) }, add: function() { this._handlerCount++ }, remove: function() { this._handlerCount-- }, teardown: function() { if (this._handlerCount) return; $(document).off("." + this._eventNamespace) }, dispose: function() { $(document).off("." + this._eventNamespace) } }); var MultiEventStrategy = SingleEventStrategy.inherit({ EVENT_LOCK_TIMEOUT: 100, _handler: function(e) { if (events.isTouchEvent(e)) this._skipNextEvents = true; if (events.isMouseEvent(e) && this._mouseLocked) return; if (events.isMouseEvent(e) && this._skipNextEvents) { this._skipNextEvents = false; this._mouseLocked = true; clearTimeout(this._unlockMouseTimer); this._unlockMouseTimer = setTimeout($.proxy(function() { this._mouseLocked = false }, this), this.EVENT_LOCK_TIMEOUT); return } return this.callBase(e) }, dispose: function() { this.callBase(); this._skipNextEvents = false; this._mouseLocked = false; clearTimeout(this._unlockMouseTimer) } }); var getStrategy = function() { return eventMap === MouseAndTouchStrategyEventMap ? MultiEventStrategy : SingleEventStrategy }; $.each(eventMap, function(pointerEvent, originalEvents) { var Strategy = getStrategy(); events.registerEvent(pointerEvent, new Strategy(pointerEvent, originalEvents)) }); DX.ui.events.__internals = DX.ui.events.__internals || {}; $.extend(DX.ui.events.__internals, { SingleEventStrategy: SingleEventStrategy, MultiEventStrategy: MultiEventStrategy, MouseStrategyEventMap: MouseStrategyEventMap, TouchStrategyEventMap: TouchStrategyEventMap, PointerStrategyEventMap: PointerStrategyEventMap, MouseAndTouchStrategyEventMap: MouseAndTouchStrategyEventMap, eventMap: eventMap }) })(jQuery, DevExpress); /*! Module core, file ui.events.click.js */ (function($, DX, wnd, undefined) { var ua = navigator.userAgent, screen = wnd.screen, ui = DX.ui, utils = DX.utils, events = ui.events, support = DX.support, device = $.proxy(DX.devices.real, DX.devices), EVENTS_NAME_SPACE = "dxSpecialEvents", CLICK_NAME_SPACE = "dxClick" + EVENTS_NAME_SPACE, CLICK_EVENT_NAME = "dxclick", SCROLLABLE_PARENT_DATA_KEY = "dxClickScrollableParent", SCROLLABLE_PARENT_SCROLL_OFFSET_DATA_KEY = "dxClickScrollableParentOffset", preferNativeClick = function() { var iPhone4SAndElder = device().deviceType === "phone" && screen.height <= 480, iPad2AndElder = device().deviceType === "tablet" && wnd.devicePixelRatio < 2, IOS7AndNewer = device().platform === "ios" && device().version[0] > 6; return IOS7AndNewer && (iPhone4SAndElder || iPad2AndElder) }(), useNativeClick = function() { if (!support.touch) return true; var chromeInfo = ua.match(/Chrome\/([0-9]+)/) || [], chrome = !!chromeInfo[0], chromeVersion = ~~chromeInfo[1], android = device().platform === "android"; if (chrome) if (android) { if ($("meta[name=viewport][content*='width=device-width']").length) return false; if (chromeVersion > 31 && wnd.innerWidth <= screen.width) return true; if ($("meta[name=viewport][content*='user-scalable=no']").length) return true } else return true; return false }(); var SimulatedStrategy = DX.Class.inherit({ TOUCH_BOUNDARY: 10, ctor: function() { this._startX = 0; this._startY = 0; this._handlerCount = 0; this._target = null }, _touchWasMoved: function(e) { var boundary = this.TOUCH_BOUNDARY; return Math.abs(e.pageX - this._startX) > boundary || Math.abs(e.pageY - this._startY) > boundary }, _getClosestScrollable: function($element) { var $scrollParent = $(); if ($element.data(SCROLLABLE_PARENT_DATA_KEY)) $scrollParent = $element.data(SCROLLABLE_PARENT_DATA_KEY); else { var $current = $element; while ($current.length) { if ($current[0].scrollHeight - $current[0].offsetHeight > 1) { $scrollParent = $current; $element.data(SCROLLABLE_PARENT_DATA_KEY, $scrollParent); break } $current = $current.parent() } } return $scrollParent }, _saveClosestScrollableOffset: function($element) { var $scrollable = this._getClosestScrollable($element); if ($scrollable.length) $element.data(SCROLLABLE_PARENT_SCROLL_OFFSET_DATA_KEY, $scrollable.scrollTop()) }, _closestScrollableWasMoved: function($element) { var $scrollable = $element.data(SCROLLABLE_PARENT_DATA_KEY); return $scrollable && $scrollable.scrollTop() !== $element.data(SCROLLABLE_PARENT_SCROLL_OFFSET_DATA_KEY) }, _hasClosestScrollable: function($element) { var $scrollable = this._getClosestScrollable($element); if (!$scrollable.length) return false; if ($scrollable.is("body")) return false; if ($scrollable === window) return false; if ($scrollable.css("overflow") === "hidden") return false; return true }, _handleStart: function(e) { this._reset(); if (events.isMouseEvent(e) && e.which !== 1) return; this._saveClosestScrollableOffset($(e.target)); this._target = e.target; this._startX = e.pageX; this._startY = e.pageY }, _handleEnd: function(e) { var $target = $(e.target); if (!$target.is(this._target) || this._touchWasMoved(e)) return; if (this._nativeClickShouldBeUsed($target) || this._closestScrollableWasMoved($target)) return; var targetIsInput = $target.is("input, textarea"); if (!targetIsInput && !e.dxPreventBlur) utils.resetActiveElement(); this._fireClickEvent(e) }, _handleCancel: function(e) { this._reset() }, _reset: function() { this._target = null }, _handleClick: function(e) { var $target = $(e.target); if ($target.is(this._target)) { if (this._nativeClickShouldBeUsed($target)) this._fireClickEvent(e) } else if ($target.is("input, textarea")) utils.resetActiveElement() }, _nativeClickShouldBeUsed: function($target) { return preferNativeClick && this._hasClosestScrollable($target) }, _fireClickEvent: function(e) { if (events.handleGestureEvent(e, CLICK_EVENT_NAME)) events.fireEvent({ type: CLICK_EVENT_NAME, originalEvent: e }) }, _makeElementClickable: function($element) { if (!$element.attr("onclick")) $element.attr("onclick", "void(0)") }, setup: function(element) { var $element = $(element); this._makeElementClickable($element); if (this._handlerCount > 0) return; var $doc = $(document).on(events.addNamespace("dxpointerdown", CLICK_NAME_SPACE), $.proxy(this._handleStart, this)).on(events.addNamespace("dxpointerup", CLICK_NAME_SPACE), $.proxy(this._handleEnd, this)).on(events.addNamespace("dxpointercancel", CLICK_NAME_SPACE), $.proxy(this._handleCancel, this)).on(events.addNamespace("click", CLICK_NAME_SPACE), $.proxy(this._handleClick, this)) }, add: function() { this._handlerCount++ }, remove: function() { this._handlerCount-- }, teardown: function(element) { if (this._handlerCount) return; $(element).off("." + CLICK_NAME_SPACE); this.dispose() }, dispose: function() { $(document).off("." + CLICK_NAME_SPACE) } }); var NativeStrategy = DX.Class.inherit({ bindType: "click", delegateType: "click", handle: function(element, event) { event.type = "dxclick"; if (events.handleGestureEvent(event, CLICK_EVENT_NAME)) return event.handleObj.handler.call(element, event) } }); events.registerEvent(CLICK_EVENT_NAME, new(useNativeClick ? NativeStrategy : SimulatedStrategy)); DX.ui.events.__internals = DX.ui.events.__internals || {}; $.extend(DX.ui.events.__internals, { NativeClickStrategy: NativeStrategy, SimulatedClickStrategy: SimulatedStrategy, preferNativeClickAccessor: function(value) { if (!arguments.length) return preferNativeClick; preferNativeClick = value } }) })(jQuery, DevExpress, window); /*! Module core, file ui.events.hold.js */ (function($, DX, undefined) { var ui = DX.ui, events = ui.events, jqSpecialEvent = $.event.special, EVENTS_NAME_SPACE = "dxSpecialEvents", HOLD_NAME_SPACE = "dxHold", HOLD_EVENT_NAME = "dxhold", HOLD_TIMER_DATA_KEY = EVENTS_NAME_SPACE + "HoldTimer"; var Hold = DX.Class.inherit({ HOLD_TIMEOUT: 750, TOUCH_BOUNDARY: 5, _startX: 0, _startY: 0, _touchWasMoved: function(e) { var boundary = this.TOUCH_BOUNDARY; return Math.abs(e.pageX - this._startX) > boundary || Math.abs(e.pageY - this._startY) > boundary }, setup: function(element, data) { var $target, holdInited = false; var handleStart = function(e) { if (holdInited) return; $target = $(e.target); holdInited = true; if ($target.data(HOLD_TIMER_DATA_KEY)) return; this._startX = e.pageX; this._startY = e.pageY; var holdTimeout = data && "timeout" in data ? data.timeout : this.HOLD_TIMEOUT; var holdTimer = setTimeout(function() { $target.removeData(HOLD_TIMER_DATA_KEY); if (events.handleGestureEvent(e, HOLD_EVENT_NAME)) events.fireEvent({ type: HOLD_EVENT_NAME, originalEvent: e }) }, holdTimeout); $target.data(HOLD_TIMER_DATA_KEY, holdTimer) }; var handleMove = function(e) { if (!this._touchWasMoved(e)) return; handleEnd() }; var handleEnd = function() { if ($target) { clearTimeout($target.data(HOLD_TIMER_DATA_KEY)); $target.removeData(HOLD_TIMER_DATA_KEY); $target = null; holdInited = false } }; $(element).on(events.addNamespace("dxpointerdown", HOLD_NAME_SPACE), $.proxy(handleStart, this)).on(events.addNamespace("dxpointermove", HOLD_NAME_SPACE), $.proxy(handleMove, this)).on(events.addNamespace("dxpointerup", HOLD_NAME_SPACE), $.proxy(handleEnd, this)) }, teardown: function(element) { element = $(element); clearTimeout(element.data(HOLD_TIMER_DATA_KEY)); element.removeData(HOLD_TIMER_DATA_KEY).off("." + HOLD_NAME_SPACE) } }); events.registerEvent(HOLD_EVENT_NAME, new Hold) })(jQuery, DevExpress); /*! Module core, file ui.events.hover.js */ (function($, DX, undefined) { var ui = DX.ui, events = ui.events; var HOVER_EVENTS_NAMESPACE = "dxSpecialEvents", HOVER_START = "dxhoverstart", HOVER_END = "dxhoverend", MOUSE_ENTER = "mouseenter", MOUSE_LEAVE = "mouseleave", TOUCH_START = "dxpointerdown"; var HoverStart = DX.Class.inherit({ ctor: function() { this._wasTouch = false; this._selector = undefined }, setup: function(element, data) { var $element = $(element); this._selector = data ? data.selector : undefined; if (!!$element.data("dxHoverStart")) return; $element.data("dxHoverStart", true).on(events.addNamespace(MOUSE_ENTER, HOVER_EVENTS_NAMESPACE), this._selector, $.proxy(this._handleEnter, this)).on(events.addNamespace(TOUCH_START, HOVER_EVENTS_NAMESPACE), $.proxy(this._handleTouchStart, this)) }, _handleEnter: function(e) { if (!this._wasTouch) events.fireEvent({ type: HOVER_START, originalEvent: e }) }, _handleTouchStart: function(e) { this._wasTouch = events.isTouchEvent(e) }, teardown: function(element) { $(element).data("dxHoverStart", false).off(events.addNamespace(MOUSE_ENTER, HOVER_EVENTS_NAMESPACE), this._selector).off(events.addNamespace(TOUCH_START, HOVER_EVENTS_NAMESPACE)) } }); var HoverEnd = DX.Class.inherit({ ctor: function() { this._wasTouch = false; this._selector = undefined }, setup: function(element, data) { var $element = $(element); this._selector = data ? data.selector : undefined; if (!!$element.data("dxHoverEnd")) return; $element.data("dxHoverEnd", true).on(events.addNamespace(MOUSE_LEAVE, HOVER_EVENTS_NAMESPACE), this._selector, $.proxy(this._handleLeave, this)).on(events.addNamespace(TOUCH_START, HOVER_EVENTS_NAMESPACE), $.proxy(this._handleTouchStart, this)) }, _handleLeave: function(e) { if (!this._wasTouch) events.fireEvent({ type: HOVER_END, originalEvent: e }) }, _handleTouchStart: function(e) { this._wasTouch = events.isTouchEvent(e) }, teardown: function(element) { $(element).data("dxHoverEnd", false).off(events.addNamespace(MOUSE_LEAVE, HOVER_EVENTS_NAMESPACE), this._selector).off(events.addNamespace(TOUCH_START, HOVER_EVENTS_NAMESPACE)) } }); events.registerEvent(HOVER_START, new HoverStart); events.registerEvent(HOVER_END, new HoverEnd) })(jQuery, DevExpress); /*! Module core, file ui.events.wheel.js */ (function($, DX, undefined) { var ui = DX.ui, events = ui.events; var EVENT_NAME = "dxmousewheel", EVENT_NAMESPACE = "dxWheel"; var WHEEL_DISTANCE = 10; $.event.fixHooks["wheel"] = $.event.mouseHooks; var wheelEvent = document.onmousewheel !== undefined ? "mousewheel" : "wheel"; var wheel = { setup: function(element, data) { var $element = $(element); $element.on(events.addNamespace(wheelEvent, EVENT_NAMESPACE), $.proxy(wheel._handleWheel, wheel)) }, teardown: function(element) { var $element = $(element); $element.off("." + EVENT_NAMESPACE) }, _handleWheel: function(e) { $(e.target).data("dxGestureEvent", null); var delta = this._getWheelDelta(e.originalEvent); events.fireEvent({ type: EVENT_NAME, originalEvent: e, delta: delta }); e.stopPropagation() }, _getWheelDelta: function(event) { return event.wheelDelta / 60 || -event.deltaY } }; events.registerEvent(EVENT_NAME, wheel) })(jQuery, DevExpress); /*! Module core, file ui.gestureEmitter.js */ (function($, DX, undefined) { var ui = DX.ui, events = ui.events; var GestureEmitter = DX.Class.inherit({ ctor: function(element) { this._$element = $(element); this._cancelCallback = $.Callbacks() }, getElement: function() { return this._$element }, getDirection: function() { return this.direction }, validate: function(e) { return e.type !== "dxmousewheel" }, configurate: function(data) { $.extend(this, data) }, addCancelCallback: function(callback) { this._cancelCallback.add(callback) }, removeCancelCallback: function() { this._cancelCallback.empty() }, init: $.noop, start: $.noop, move: $.noop, end: $.noop, cancel: $.noop, wheel: $.noop, _fireEvent: function(eventName, event, params) { var eventData = { type: eventName, originalEvent: event, target: this.getElement().get(0) }; event = events.fireEvent($.extend(eventData, params)); if (event.cancel) this._cancel(event); return event }, _cancel: function(e) { this._cancelCallback.fire() } }); var gestureEmitters = []; $.extend(ui, { GestureEmitter: GestureEmitter, gestureEmitters: gestureEmitters }) })(jQuery, DevExpress); /*! Module core, file ui.scrollEmitter.js */ (function($, DX, undefined) { var ui = DX.ui, events = ui.events; var SCROLL_INIT_EVENT = "dxscrollinit", SCROLL_START_EVENT = "dxscrollstart", SCROLL_MOVE_EVENT = "dxscroll", SCROLL_END_EVENT = "dxscrollend", SCROLL_STOP_EVENT = "dxscrollstop", SCROLL_CANCEL_EVENT = "dxscrollcancel", SCROLL_WHEEL_EVENT = "dxscrollwheel", INERTIA_TIMEOUT = 100, VELOCITY_CALC_TIMEOUT = 200, FRAME_DURATION = Math.round(1000 / 60); var ScrollEmitter = ui.GestureEmitter.inherit({ ctor: function(element) { this.callBase(element); this.direction = "vertical" }, init: function(e) { this._savedEventData = this._prevEventData = events.eventData(e); this._fireEvent(SCROLL_INIT_EVENT, e) }, start: function(e) { this._fireEvent(SCROLL_START_EVENT, e, {delta: events.eventDelta(this._prevEventData, events.eventData(e))}) }, move: function(e) { var currentEventData = events.eventData(e); this._fireEvent(SCROLL_MOVE_EVENT, e, {delta: events.eventDelta(this._prevEventData, currentEventData)}); var eventDelta = events.eventDelta(this._savedEventData, currentEventData); if (eventDelta.time > VELOCITY_CALC_TIMEOUT) this._savedEventData = this._prevEventData; this._prevEventData = currentEventData }, end: function(e) { var endEventDelta = events.eventDelta(this._prevEventData, events.eventData(e)); var velocity = { x: 0, y: 0 }; if (endEventDelta.time < INERTIA_TIMEOUT) { var deltaEventData = events.eventDelta(this._savedEventData, this._prevEventData); velocity = { x: deltaEventData.x * FRAME_DURATION / deltaEventData.time, y: deltaEventData.y * FRAME_DURATION / deltaEventData.time } } this._fireEvent(SCROLL_END_EVENT, e, {velocity: velocity}) }, stop: function(e) { this._fireEvent(SCROLL_STOP_EVENT, e) }, cancel: function(e) { this._fireEvent(SCROLL_CANCEL_EVENT, e) }, wheel: function(e) { this._fireEvent(SCROLL_WHEEL_EVENT, e, {delta: e.delta}) } }); ui.gestureEmitters.push({ emitter: ScrollEmitter, events: [SCROLL_INIT_EVENT, SCROLL_START_EVENT, SCROLL_MOVE_EVENT, SCROLL_END_EVENT, SCROLL_STOP_EVENT, SCROLL_CANCEL_EVENT, SCROLL_WHEEL_EVENT] }) })(jQuery, DevExpress); /*! Module core, file ui.swipeEmitter.js */ (function($, DX, undefined) { var ui = DX.ui, utils = DX.utils, events = ui.events, SWIPE_START_EVENT = "dxswipestart", SWIPE_EVENT = "dxswipe", SWIPE_END_EVENT = "dxswipeend"; var HorizontalStrategy = { defaultItemSizeFunc: function() { return this.getElement().width() }, getBounds: function() { return [this._maxLeftOffset, this._maxRightOffset] }, calcOffsetRatio: function(e) { var endEventData = events.eventData(e); return (endEventData.x - (this._startEventData && this._startEventData.x || 0)) / this._itemSizeFunc().call(this, e) }, isFastSwipe: function(e) { var endEventData = events.eventData(e); return this.FAST_SWIPE_SPEED_LIMIT * Math.abs(endEventData.x - this._tickData.x) >= endEventData.time - this._tickData.time } }; var VerticalStrategy = { defaultItemSizeFunc: function() { return this.getElement().height() }, getBounds: function() { return [this._maxTopOffset, this._maxBottomOffset] }, calcOffsetRatio: function(e) { var endEventData = events.eventData(e); return (endEventData.y - (this._startEventData && this._startEventData.y || 0)) / this._itemSizeFunc().call(this, e) }, isFastSwipe: function(e) { var endEventData = events.eventData(e); return this.FAST_SWIPE_SPEED_LIMIT * Math.abs(endEventData.y - this._tickData.y) >= endEventData.time - this._tickData.time } }; var STRATEGIES = { horizontal: HorizontalStrategy, vertical: VerticalStrategy }; var SwipeEmitter = ui.GestureEmitter.inherit({ TICK_INTERVAL: 300, FAST_SWIPE_SPEED_LIMIT: 5, ctor: function(element) { this.callBase(element); this.direction = "horizontal"; this.elastic = true }, _getStrategy: function() { return STRATEGIES[this.direction] }, _defaultItemSizeFunc: function() { return this._getStrategy().defaultItemSizeFunc.call(this) }, _itemSizeFunc: function() { return this.itemSizeFunc || this._defaultItemSizeFunc }, init: function(e) { this._startEventData = events.eventData(e); this._tickData = {time: 0} }, start: function(e) { e = this._fireEvent(SWIPE_START_EVENT, e); if (!e.cancel) { this._maxLeftOffset = e.maxLeftOffset; this._maxRightOffset = e.maxRightOffset; this._maxTopOffset = e.maxTopOffset; this._maxBottomOffset = e.maxBottomOffset } }, move: function(e) { var strategy = this._getStrategy(), moveEventData = events.eventData(e), offset = strategy.calcOffsetRatio.call(this, e); offset = this._fitOffset(offset, this.elastic); if (moveEventData.time - this._tickData.time > this.TICK_INTERVAL) this._tickData = moveEventData; this._fireEvent(SWIPE_EVENT, e, {offset: offset}); e.preventDefault() }, end: function(e) { var strategy = this._getStrategy(), offsetRatio = strategy.calcOffsetRatio.call(this, e), isFast = strategy.isFastSwipe.call(this, e), startOffset = offsetRatio, targetOffset = this._calcTargetOffset(offsetRatio, isFast); startOffset = this._fitOffset(startOffset, this.elastic); targetOffset = this._fitOffset(targetOffset, false); this._fireEvent(SWIPE_END_EVENT, e, { offset: startOffset, targetOffset: targetOffset }) }, _fitOffset: function(offset, elastic) { var strategy = this._getStrategy(), bounds = strategy.getBounds.call(this); if (offset < -bounds[0]) return elastic ? (-2 * bounds[0] + offset) / 3 : -bounds[0]; if (offset > bounds[1]) return elastic ? (2 * bounds[1] + offset) / 3 : bounds[1]; return offset }, _calcTargetOffset: function(offsetRatio, isFast) { var result; if (isFast) { result = Math.ceil(Math.abs(offsetRatio)); if (offsetRatio < 0) result = -result } else result = Math.round(offsetRatio); return result } }); ui.gestureEmitters.push({ emitter: SwipeEmitter, events: [SWIPE_START_EVENT, SWIPE_EVENT, SWIPE_END_EVENT] }) })(jQuery, DevExpress); /*! Module core, file ui.dragEmitter.js */ (function($, DX, undefined) { var ui = DX.ui, utils = DX.utils, events = ui.events, wrapToArray = utils.wrapToArray; var DRAG_START_EVENT = "dxdragstart", DRAG_EVENT = "dxdrag", DRAG_END_EVENT = "dxdragend", DRAG_ENTER_EVENT = "dxdragenter", DRAG_LEAVE_EVENT = "dxdragleave", DROP_EVENT = "dxdrop"; var knownDropTargets = [], knownDropTargetConfigs = []; var dropTargetRegistration = { setup: function(element, data) { var knownDropTarget = $.inArray(element, knownDropTargets) !== -1; if (!knownDropTarget) { knownDropTargets.push(element); knownDropTargetConfigs.push(data || {}) } }, teardown: function(element, data) { var elementEvents = $._data(element, "events"), handlersCount = 0; $.each([DRAG_ENTER_EVENT, DRAG_LEAVE_EVENT, DROP_EVENT], function(_, eventName) { var eventHandlers = elementEvents[eventName]; if (eventHandlers) handlersCount += eventHandlers.length }); if (!handlersCount) { var index = $.inArray(element, knownDropTargets); knownDropTargets.splice(index, 1); knownDropTargetConfigs.splice(index, 1) } } }; events.registerEvent(DRAG_ENTER_EVENT, dropTargetRegistration); events.registerEvent(DRAG_LEAVE_EVENT, dropTargetRegistration); events.registerEvent(DROP_EVENT, dropTargetRegistration); var getItemConfig = function($element) { var dropTargetIndex = $.inArray($element.get(0), knownDropTargets); return knownDropTargetConfigs[dropTargetIndex] }; var getItemPosition = function($element) { var dropTargetConfig = getItemConfig($element); if (dropTargetConfig.itemPositionFunc) return dropTargetConfig.itemPositionFunc(); else return $element.offset() }; var getItemSize = function($element) { var dropTargetConfig = getItemConfig($element); if (dropTargetConfig.itemSizeFunc) return dropTargetConfig.itemSizeFunc(); else return { width: $element.width(), height: $element.height() } }; var DragEmitter = ui.GestureEmitter.inherit({ ctor: function(element) { this.callBase(element); this.direction = "both" }, init: function(e) { var eventData = events.eventData(e); this._startEventData = eventData }, start: function(e) { e = this._fireEvent(DRAG_START_EVENT, e); this._maxLeftOffset = e.maxLeftOffset; this._maxRightOffset = e.maxRightOffset; this._maxTopOffset = e.maxTopOffset; this._maxBottomOffset = e.maxBottomOffset; var dropTargets = wrapToArray(e.targetElements || knownDropTargets); this._$dropTargetElements = $.map(dropTargets, function(element) { return $(element) }) }, move: function(e) { var eventData = events.eventData(e), dragOffset = this._calculateOffset(eventData); this._fireEvent(DRAG_EVENT, e, {offset: dragOffset}); this._processDropTargets(e, dragOffset); e.preventDefault() }, _calculateOffset: function(eventData) { return { x: this._calculateXOffset(eventData), y: this._calculateYOffset(eventData) } }, _calculateXOffset: function(eventData) { if (this.direction !== "vertical") { var offset = eventData.x - this._startEventData.x; return this._fitOffset(offset, this._maxLeftOffset, this._maxRightOffset) } return 0 }, _calculateYOffset: function(eventData) { if (this.direction !== "horizontal") { var offset = eventData.y - this._startEventData.y; return this._fitOffset(offset, this._maxTopOffset, this._maxBottomOffset) } return 0 }, _fitOffset: function(offset, minOffset, maxOffset) { if (minOffset != null) offset = Math.max(offset, -minOffset); if (maxOffset != null) offset = Math.min(offset, maxOffset); return offset }, _processDropTargets: function(e, dragOffset) { var target = this._findDropTarget(e), sameTarget = target === this._$currentDropTarget; if (!sameTarget) { this._fireDropTargetEvent(e, DRAG_LEAVE_EVENT); this._$currentDropTarget = target; this._fireDropTargetEvent(e, DRAG_ENTER_EVENT) } }, _fireDropTargetEvent: function(event, eventName) { if (!this._$currentDropTarget) return; var eventData = { type: eventName, originalEvent: event, draggingElement: this._$element.get(0), target: this._$currentDropTarget.get(0) }; events.fireEvent(eventData) }, _findDropTarget: function(e) { var that = this, $result; $.each(this._$dropTargetElements, function(_, $target) { if (that._checkDropTarget($target, e)) { $result = $target; return false } }); return $result }, _checkDropTarget: function($target, e) { var isDraggingElement = $target.get(0) === this._$element.get(0); if (isDraggingElement) return false; var targetPosition = getItemPosition($target); if (e.pageX < targetPosition.left) return false; if (e.pageY < targetPosition.top) return false; var targetSize = getItemSize($target); if (e.pageX > targetPosition.left + targetSize.width) return false; if (e.pageY > targetPosition.top + targetSize.height) return false; return $target }, end: function(e) { var eventData = events.eventData(e); this._fireEvent(DRAG_END_EVENT, e, {offset: this._calculateOffset(eventData)}); this._fireDropTargetEvent(e, DROP_EVENT); delete this._$currentDropTarget } }); ui.gestureEmitters.push({ emitter: DragEmitter, events: [DRAG_START_EVENT, DRAG_EVENT, DRAG_END_EVENT] }); DX.ui.events.__internals = DX.ui.events.__internals || {}; $.extend(DX.ui.events.__internals, {dropTargets: knownDropTargets}) })(jQuery, DevExpress); /*! Module core, file ui.events.gesture.js */ (function($, DX, undefined) { var ui = DX.ui, events = ui.events, utils = DX.utils; var abs = Math.abs; var GESTURE_EVENT = "dxGesture", GESTURE_EVENT_DATA = "dxGestureEmitter", GESTURE_LOCK_KEY = "dxGestureLock", GESTURE_UNLOCK_TIMEOUT = 400, TOUCH_BOUNDARY = 10, HORIZONTAL = "horizontal", VERTICAL = "vertical", BOTH = "both"; var GestureEventManager = DX.Class.inherit({ SLEEP: 0, INITED: 1, STARTED: 2, ctor: function() { this._attachHandlers(); this.reset() }, _attachHandlers: function() { $(document).on(events.addNamespace("dxpointerdown", GESTURE_EVENT), $.proxy(this._handlePointerDown, this)).on(events.addNamespace("dxpointermove", GESTURE_EVENT), $.proxy(this._handlePointerMove, this)).on(events.addNamespace("dxpointerup dxpointercancel", GESTURE_EVENT), $.proxy(this._handlePointerUp, this)).on(events.addNamespace("dxmousewheel", GESTURE_EVENT), $.proxy(this._handleMouseWheel, this)) }, _eachEmitter: function(callback) { $.each(this._activeEmitters || {}, function(direction, emitter) { return callback(emitter, direction) }) }, _noEmitters: function() { return $.isEmptyObject(this._activeEmitters) }, reset: function() { this._eachEmitter(function(emitter) { emitter.removeCancelCallback() }); this._forgetGesture(); this._stage = this.SLEEP; this._activeEmitters = {} }, _handlePointerDown: function(e) { if (events.needSkipEvent(e) || events.hasTouches(e) > 1) return; this.reset(); this._activeEmitters = this._closestEmitter(e); if (this._noEmitters()) return; this._startEvent = e; this._startEventData = events.eventData(e); this._stage = this.INITED; this._applyToActive("init", e) }, _applyToActive: function(method) { var args = $.makeArray(arguments).slice(1); this._eachEmitter(function(emitter) { if (method in emitter) emitter[method].apply(emitter, args) }) }, _closestEmitter: function(e) { var result = {}, foundForAllDirections = false, $element = $(e.target); while ($element.length && !foundForAllDirections) { var emitter = $element.data(GESTURE_EVENT_DATA); if (emitter && emitter.validate(e)) { var direction = emitter.getDirection(e); if (direction) { emitter.addCancelCallback($.proxy(this._handleCancel, this, emitter, e)); result[direction] = result[direction] || emitter } } foundForAllDirections = result[HORIZONTAL] && result[VERTICAL] || result[BOTH]; $element = $element.parent() } return result }, _handleCancel: function(canceledEmitter, e) { var canceledDirection; this._eachEmitter(function(emitter, direction) { if (emitter === canceledEmitter) { canceledDirection = direction; emitter.removeCancelCallback() } }); this._forgetGesture([canceledEmitter]); this._cancelEmitter(canceledEmitter, e); if (this._noEmitters()) this.reset() }, _handlePointerMove: function(e) { if (this._stage === this.INITED && this._directionDetected(e)) this._handleStart(e); if (this._stage === this.STARTED) this._handleMove(e) }, _directionDetected: function(e) { var delta = events.eventDelta(this._startEventData, events.eventData(e)); return delta.x || delta.y }, _handleStart: function(e) { this._filterEmitters(e); if (this._noEmitters()) return; this._resetActiveElement(); this._applyToActive("start", this._startEvent); this._stage = this.STARTED }, _resetActiveElement: function() { if (DX.devices.real().platform !== "ios") return; this._eachEmitter(function(emitter) { if ($(":focus", emitter.getElement()).length) utils.resetActiveElement() }) }, _filterEmitters: function(e) { this._filterByDirection(e); if (this._emitersAmount() > 1) this._takeFirstEmitter() }, _emitersAmount: function() { var result = 0; this._eachEmitter(function() { result++ }); return result }, _filterByDirection: function(e) { var delta = events.eventDelta(this._startEventData, events.eventData(e)), horizontalMove = abs(delta.y) < abs(delta.x), verticalMove = abs(delta.y) > abs(delta.x), horizontalEmmiter = this._activeEmitters[HORIZONTAL], verticalEmmiter = this._activeEmitters[VERTICAL], bothEmitter = this._activeEmitters[BOTH], existsHorizontalEmitter = horizontalEmmiter || bothEmitter, existsVerticalEmitter = verticalEmmiter || bothEmitter; if (horizontalMove && existsHorizontalEmitter) this._cancelEmitter(verticalEmmiter, e); else if (verticalMove && existsVerticalEmitter) this._cancelEmitter(horizontalEmmiter, e) }, _cancelEmitter: function(canceledEmmiter, e) { if (!canceledEmmiter) return; canceledEmmiter.cancel(e); delete this._activeEmitters[canceledEmmiter.getDirection(e)] }, _takeFirstEmitter: function() { var activeEmitters = {}; this._eachEmitter(function(emitter, direction) { activeEmitters[direction] = emitter; return false }); this._activeEmitters = activeEmitters }, _prepareGesture: function() { this._gestureLocked = true; clearTimeout(this._gestureEndTimer); this._eachEmitter(function(emitter) { emitter.getElement().data(GESTURE_LOCK_KEY, true) }); ui.feedback.reset() }, _handleMove: function(e) { if (!this._gestureLocked) { var delta = events.eventDelta(this._startEventData, events.eventData(e)); if (abs(delta.x) > TOUCH_BOUNDARY || abs(delta.y) > TOUCH_BOUNDARY) { events.handleGestureEvent(e, GESTURE_EVENT); this._prepareGesture() } } this._applyToActive("move", e) }, _forgetGesture: function(activeEmitters) { activeEmitters = activeEmitters || this._activeEmitters; if (this._noEmitters()) return; this._gestureLocked = false; this._gestureEndTimer = setTimeout(function() { $.each(activeEmitters, function(_, emitter) { emitter.getElement().data(GESTURE_LOCK_KEY, false) }) }, GESTURE_UNLOCK_TIMEOUT) }, _handlePointerUp: function(e) { if (!DX.devices.isRippleEmulator() && events.hasTouches(e)) return; if (this._stage === this.STARTED) this._applyToActive("end", e); else if (this._stage === this.INITED) this._applyToActive("stop", e); this.reset() }, _handleMouseWheel: function(e) { this._handlePointerDown(e); if (this._stage !== this.INITED) return; this._takeFirstEmitter(); this._eachEmitter(function(emitter, direction) { var prop = direction !== "horizontal" ? "pageY" : "pageX"; e[prop] += e.delta }); this._handlePointerMove(e); this._handlePointerUp(e) }, isActive: function(element) { var result = false; this._eachEmitter(function(emitter) { result = result || emitter.getElement().is(element) }); return result } }); var gestureEventManager = new GestureEventManager; var registerEmitter = function(emitterConfig) { var emitterClass = emitterConfig.emitter; $.each(emitterConfig.events, function(_, eventName) { events.registerEvent(eventName, { noBubble: true, setup: function(element, data) { var emitter = $(element).data(GESTURE_EVENT_DATA) || new emitterClass(element); emitter.configurate(data); $(element).data(GESTURE_EVENT_DATA, emitter) }, teardown: function(element) { if (gestureEventManager.isActive(element)) gestureEventManager.reset(); $(element).removeData(GESTURE_EVENT_DATA) } }) }) }; $.each(ui.gestureEmitters, function(_, emitterConfig) { registerEmitter(emitterConfig) }); events.__internals = events.__internals || {}; $.extend(events.__internals, {registerEmitter: registerEmitter}) })(jQuery, DevExpress); /*! Module core, file ui.widget.js */ (function($, DX, undefined) { var ui = DX.ui, UI_FEEDBACK = "UIFeedback", UI_FEEDBACK_CLASS = "dx-feedback", ACTIVE_STATE_CLASS = "dx-state-active", DISABLED_STATE_CLASS = "dx-state-disabled", INVISIBLE_STATE_CLASS = "dx-state-invisible", HOVER_STATE_CLASS = "dx-state-hover", FEEDBACK_SHOW_TIMEOUT = 30, FEEDBACK_HIDE_TIMEOUT = 400, HOVER_START = "dxhoverstart", HOVER_END = "dxhoverend", ANONYMOUS_TEMPLATE_NAME = "template", TEMPLATE_SELECTOR = "[data-options*='dxTemplate']", TEMPLATES_DATA_KEY = "dxTemplates"; var getTemplateOptions = function(element) { var options = $(element).data("options"); if ($.trim(options).charAt(0) !== "{") options = "{" + options + "}"; return new Function("return " + options)().dxTemplate }; var activeElement, events = ui.events; ui.feedback = {reset: function() { handleEnd(true) }}; ui.Widget = DX.DOMComponent.inherit({ NAME: "Widget", NAMESPACE: ui, _setDefaultOptions: function() { this.callBase(); this.option({ disabled: false, visible: true, activeStateEnabled: true, width: undefined, height: undefined, contentReadyAction: null, hoverStateEnabled: false }) }, _init: function() { this.callBase(); this._feedbackShowTimeout = FEEDBACK_SHOW_TIMEOUT; this._feedbackHideTimeout = FEEDBACK_HIDE_TIMEOUT; if (this._templatesSupported()) { this._initTemplates(); this._initContentReadyAction() } }, _templatesSupported: function() { return this._renderContentImpl !== DX.abstract }, _initTemplates: function() { var that = this, templates = {}, dataTemplateElements = this._element().data(TEMPLATES_DATA_KEY), templateElements = dataTemplateElements ? dataTemplateElements : this._element().contents().filter(TEMPLATE_SELECTOR); this._templateProvider = new ui.TemplateProvider; this._templateClass = this._templateProvider.getTemplateClass(this); if (templateElements.length) { var templatesMap = {}; templateElements.each(function() { var templateOptions = getTemplateOptions(this); if (!templateOptions) return; if (!templateOptions.name) throw Error("Template name was not specified"); templatesMap[templateOptions.name] = templatesMap[templateOptions.name] || []; templatesMap[templateOptions.name].push(this) }); $.each(templatesMap, function(templateName, value) { var deviceTemplate = that._findTemplateByDevice(value); if (deviceTemplate) templates[templateName] = that._createTemplate(deviceTemplate) }) } else templates[ANONYMOUS_TEMPLATE_NAME] = that._createTemplate(that._element().contents()); this.option("_templates", templates) }, _getTemplateByOption: function(optionName) { return this._getTemplate(this.option(optionName)) }, _getTemplate: function(templateName) { var result = this._acquireTemplate.apply(this, arguments); if (!result && this._templateProvider.supportDefaultTemplate(this)) { result = this._templateProvider.getDefaultTemplate(this); if (!result) throw Error(DX.utils.stringFormat("Template \"{0}\" was not found and no default template specified!", templateName)); } return result }, _acquireTemplate: function(templateSource) { if (templateSource == null) return templateSource; if (templateSource instanceof this._templateClass) return templateSource; if (templateSource.nodeType || templateSource.jquery) { templateSource = $(templateSource); if (templateSource.is("script")) templateSource = templateSource.html(); return this._createTemplate(templateSource) } if (typeof templateSource === "string") return this.option("_templates")[templateSource]; if ($.isFunction(templateSource)) { var args = $.makeArray(arguments).slice(1); return this._acquireTemplate(templateSource.apply(this, args)) } return this._acquireTemplate(templateSource.toString()) }, _createTemplate: function(element) { return new this._templateClass(element, this) }, _findTemplateByDevice: function(templates) { var suitableTemplate = DX.utils.findBestMatches(DX.devices.current(), templates, function(template) { return getTemplateOptions(template) })[0]; $.each(templates, function(index, template) { if (template !== suitableTemplate) $(template).remove() }); return suitableTemplate }, _cleanTemplates: function() { var that = this; $.each(this.option("_templates"), function(templateName, template) { if (that === template.owner()) template.dispose() }) }, _initContentReadyAction: function() { this._contentReadyAction = this._createActionByOption("contentReadyAction", {excludeValidators: ["gesture", "designMode", "disabled"]}) }, _render: function() { this.callBase(); this._element().addClass("dx-widget"); this._toggleDisabledState(this.option("disabled")); this._toggleVisibility(this.option("visible")); this._refreshFeedback(); this._renderDimensions(); if (this._templatesSupported()) this._renderContent(); this._attachHoverEvents() }, _renderContent: function() { this._renderContentImpl(); this._fireContentReadyAction() }, _renderContentImpl: DX.abstract, _fireContentReadyAction: function() { this._contentReadyAction({excludeValidators: ["disabled", "gesture"]}) }, _dispose: function() { if (this._templatesSupported()) this._cleanTemplates(); this._contentReadyAction = null; this._clearTimers(); if (activeElement && activeElement.closest(this._element()).length) activeElement = null; this.callBase() }, _clean: function() { this.callBase(); this._element().empty() }, _clearTimers: function() { clearTimeout(this._feedbackHideTimer); clearTimeout(this._feedbackShowTimer) }, _toggleVisibility: function(visible) { this._element().toggleClass(INVISIBLE_STATE_CLASS, !visible) }, _attachHoverEvents: function() { var that = this, hoverableSelector = that._activeStateUnit, nameStart = events.addNamespace(HOVER_START, UI_FEEDBACK), nameEnd = events.addNamespace(HOVER_END, UI_FEEDBACK); that._element().off(nameStart, hoverableSelector).off(nameEnd, hoverableSelector); if (this.option("hoverStateEnabled")) { var startAction = new DX.Action(function(args) { var $target = args.element; that._refreshHoveredElement($target) }); that._element().on(nameStart, hoverableSelector, {selector: hoverableSelector}, function(e) { startAction.execute({element: $(e.target)}) }).on(nameEnd, hoverableSelector, {selector: hoverableSelector}, function(e) { e.stopImmediatePropagation(); that._forgetHoveredElement() }) } else this._toggleHoverClass(false) }, _refreshHoveredElement: function(hoveredElement) { var selector = this._activeStateUnit || this._element(); this._forgetHoveredElement(); this._hoveredElement = hoveredElement.closest(selector); this._toggleHoverClass(true) }, _forgetHoveredElement: function() { this._toggleHoverClass(false); delete this._hoveredElement }, _toggleHoverClass: function(value) { if (this._hoveredElement) this._hoveredElement.toggleClass(HOVER_STATE_CLASS, value && this.option("hoverStateEnabled")) }, _renderDimensions: function() { var width = this.option("width"), height = this.option("height"); this._setDimension(width, "width"); this._setDimension(height, "height") }, _setDimension: function(dimensionSize, dimension) { var $element = this._element(); dimensionSize = $.isFunction(dimensionSize) ? dimensionSize() : dimensionSize; if ($.isNumeric(dimensionSize)) dimensionSize = dimensionSize + "px"; if (!dimensionSize && dimension === "width") dimensionSize = this._calculateWidth(); $element.css(dimension, dimensionSize) }, _calculateWidth: function() { var $element = this._element(), explicitWidth = $element[0].style.width, calculatedWidth; if (explicitWidth[explicitWidth.length - 1] === "%" && !this.option("width")) return explicitWidth; else calculatedWidth = explicitWidth && explicitWidth !== "auto" && explicitWidth !== "inherit" ? $element.outerWidth() : this.option("width"); return calculatedWidth }, _refreshFeedback: function() { if (this._feedbackDisabled()) { this._feedbackOff(true); this._element().removeClass(UI_FEEDBACK_CLASS) } else this._element().addClass(UI_FEEDBACK_CLASS) }, _feedbackDisabled: function() { return !this.option("activeStateEnabled") || this.option("disabled") }, _feedbackOn: function(element, immediate) { if (this._feedbackDisabled()) return; this._clearTimers(); if (immediate) this._feedbackShow(element); else this._feedbackShowTimer = window.setTimeout($.proxy(this._feedbackShow, this, element), this._feedbackShowTimeout); this._saveActiveElement() }, _feedbackShow: function(element) { var activeStateElement = this._element(); if (this._activeStateUnit) activeStateElement = $(element).closest(this._activeStateUnit); if (!activeStateElement.hasClass(DISABLED_STATE_CLASS)) { activeStateElement.addClass(ACTIVE_STATE_CLASS); this._toggleHoverClass(false) } }, _saveActiveElement: function() { activeElement = this._element() }, _feedbackOff: function(immediate) { this._clearTimers(); if (immediate) this._feedbackHide(); else this._feedbackHideTimer = window.setTimeout($.proxy(this._feedbackHide, this), this._feedbackHideTimeout) }, _feedbackHide: function() { var activeStateElement = this._element(); if (this._activeStateUnit) activeStateElement = activeStateElement.find(this._activeStateUnit); activeStateElement.removeClass(ACTIVE_STATE_CLASS); this._toggleHoverClass(!this.option("disabled")); this._clearActiveElement() }, _clearActiveElement: function() { var rootDomElement = this._element().get(0), activeDomElement = activeElement && activeElement.get(0); if (activeDomElement && (activeDomElement === rootDomElement || $.contains(rootDomElement, activeDomElement))) activeElement = null }, _toggleDisabledState: function(value) { this._element().toggleClass(DISABLED_STATE_CLASS, Boolean(value)); this._toggleHoverClass(!value) }, _optionChanged: function(name, value) { switch (name) { case"disabled": this._toggleDisabledState(value); this._refreshFeedback(); break; case"activeStateEnabled": this._refreshFeedback(); break; case"hoverStateEnabled": this._attachHoverEvents(); break; case"visible": this._toggleVisibility(value); break; case"width": case"height": this._renderDimensions(); break; case"contentReadyAction": this._initContentReadyAction(); break; case"_templates": this._refresh(); break; default: this.callBase.apply(this, arguments) } }, repaint: function() { this._refresh() } }); var handleStart = function(args, immediate) { var e = args.jQueryEvent, $target = args.element, widget; if (events.needSkipEvent(e)) return; if (activeElement) { widget = getWidget(activeElement); if (widget) widget._feedbackOff(true) } var closestFeedbackElement = $target.closest("." + UI_FEEDBACK_CLASS); if (closestFeedbackElement.length) { widget = getWidget(closestFeedbackElement); if (!widget) return; widget._feedbackOn($target, immediate); if (immediate) widget._feedbackOff() } }; var handleEnd = function(immediate) { if (!activeElement) return; var widget = getWidget(activeElement); if (widget) widget._feedbackOff(immediate) }; var getWidget = function(widgetElement) { var result; $.each(widgetElement.data("dxComponents") || [], function(index, componentName) { if (ui[componentName] && ui[componentName].subclassOf(ui.Widget)) { result = widgetElement.data(componentName); return false } }); return result }; $(function() { var startAction = new DX.Action(handleStart); $(document).on(events.addNamespace("dxpointerdown", UI_FEEDBACK), function(e) { startAction.execute({ jQueryEvent: e, element: $(e.target) }) }).on(events.addNamespace("dxpointerup dxpointercancel", UI_FEEDBACK), function(e) { var activeElementClicked = activeElement && $(e.target).closest("." + UI_FEEDBACK_CLASS).get(0) === activeElement.get(0); if (activeElementClicked) startAction.execute({ jQueryEvent: e, element: $(e.target) }, true); handleEnd() }) }) })(jQuery, DevExpress); /*! Module core, file ui.editor.js */ (function($, DX, undefined) { var ui = DX.ui; DX.registerComponent("dxEditor", ui.Widget.inherit({ _setDefaultOptions: function() { this.callBase(); this.option({ value: undefined, valueChangeAction: undefined }) }, _recreateValueChangeAction: function() { this._valueChangeAction = this._createActionByOption("valueChangeAction") }, _suppressValueChangeAction: function() { this._valueChangeActionSuppressed = true }, _resumeValueChangeAction: function() { this._valueChangeActionSuppressed = false }, _render: function() { this._recreateValueChangeAction(); this.callBase() }, _raiseValueChangeAction: function(value, previousValue, extraArguments) { var args = { value: value, previousValue: previousValue, jQueryEvent: this._valueChangeEventInstance }; if (extraArguments) args = $.extend(args, extraArguments); this._valueChangeAction(args) }, _optionChanged: function(name, value, previousValue) { switch (name) { case"valueChangeAction": this._recreateValueChangeAction(); break; case"value": if (!this._valueChangeActionSuppressed) this._raiseValueChangeAction(value, previousValue); this._valueChangeEventInstance = undefined; break; default: this.callBase.apply(this, arguments) } } })) })(jQuery, DevExpress); /*! Module core, file ui.template.js */ (function($, DX, undefined) { var isString = DX.utils.isString; var currentTemplateEngine; var templateEngines = []; var BaseTemplate = DevExpress.Class.inherit({ _compile: function(html, element) { return element }, _render: function(template, data) { return template }, ctor: function(element) { this._element = $(element); if (this._element.length === 1) { if (this._element[0].nodeName.toLowerCase() !== "script") this._element = $("
").append(this._element); this._template = this._compile(this._element.html() || "", this._element) } }, render: function(container, data) { var result; if (this._template) { result = this._render(this._template, data); if (isString(result)) result = $.parseHTML(result); result = $(result); if (container) container.append(result); return result } }, owner: $.noop, dispose: $.noop }); var createTemplateEngine = function(options) { if (options && options.compile && options.render) return BaseTemplate.inherit({ allowRenderToDetachedContainer: options.allowRenderToDetachedContainer !== false, _compile: options.compile, _render: options.render }); else throw Error("Template Engine must contains compile and render methods"); }; if (window.ko) { var koCustomTemplateEngine = function(){}; koCustomTemplateEngine.prototype = ko.utils.extend(new ko.templateEngine, { renderTemplateSource: function(templateSource, bindingContext, options) { var precompiledTemplate = templateSource["data"]("precompiledTemplate"); if (!precompiledTemplate) { precompiledTemplate = new currentTemplateEngine(templateSource.domElement); templateSource["data"]("precompiledTemplate", precompiledTemplate) } return precompiledTemplate.render(null, bindingContext.$data) }, allowTemplateRewriting: false }) } DevExpress.ui.setTemplateEngine = function(templateEngine) { if (isString(templateEngine)) { currentTemplateEngine = templateEngines && templateEngines[templateEngine]; if (!currentTemplateEngine && templateEngine !== "default") throw Error(DX.utils.stringFormat("Template Engine \"{0}\" is not supported", templateEngine)); } else currentTemplateEngine = createTemplateEngine(templateEngine) || currentTemplateEngine; if (window.ko) ko.setTemplateEngine(currentTemplateEngine ? new koCustomTemplateEngine : new ko.nativeTemplateEngine) }; DevExpress.ui.TemplateProvider = DevExpress.ui.TemplateProvider.inherit({getTemplateClass: function() { if (currentTemplateEngine) return currentTemplateEngine; return this.callBase.apply(this, arguments) }}); var registerTemplateEngine = function(name, templateOptions) { templateEngines[name] = createTemplateEngine(templateOptions) }; registerTemplateEngine("jquery-tmpl", { compile: function(html, element) { return element }, render: function(template, data) { return template.tmpl(data) } }); registerTemplateEngine("jsrender", { compile: function(html) { return $.templates(html) }, render: function(template, data) { return template.render(data) } }); registerTemplateEngine("mustache", { compile: function(html) { return Mustache.compile(html) }, render: function(template, data) { return template(data) } }); registerTemplateEngine("hogan", { compile: function(html) { return Hogan.compile(html) }, render: function(template, data) { return template.render(data) } }); registerTemplateEngine("underscore", { compile: function(html) { return _.template(html) }, render: function(template, data) { return template(data) } }); registerTemplateEngine("handlebars", { compile: function(html) { return Handlebars.compile(html) }, render: function(template, data) { return template(data) } }); registerTemplateEngine("doT", { compile: function(html) { return doT.template(html) }, render: function(template, data) { return template(data) } }) })(jQuery, DevExpress); /*! Module core, file ui.collectionContainerWidget.js */ (function($, DX, undefined) { var ui = DX.ui, events = ui.events; var CollectionContainerWidget = ui.Widget.inherit({ _setDefaultOptions: function() { this.callBase(); this.option({ items: [], itemTemplate: "item", itemRender: null, itemRenderedAction: null, itemClickAction: null, itemHoldAction: null, itemHoldTimeout: 750, noDataText: Globalize.localize("dxCollectionContainerWidget-noDataText"), dataSource: null, selectedIndex: -1, itemSelectAction: null, itemTemplateProperty: "template" }) }, _init: function() { this.callBase(); this._cleanRenderedItems(); this._refreshDataSource() }, _dataSourceOptions: function() { var options = { paginate: false, _preferSync: false }; if ($.isArray(this.option("dataSource"))) options._preferSync = true; return options }, _cleanRenderedItems: function() { this._renderedItemsCount = 0 }, _fireSelectItemEvent: function(index, prevIndex) { if (this._selectionEnabled()) { this._updateSelectedIndex(index, prevIndex); this._handleItemEvent(this._selectedItemElement(index), "itemSelectAction", { selectedIndex: index, previousIndex: prevIndex }, {excludeValidators: ["gesture", "disabled"]}) } }, _optionChanged: function(name, value, prevValue) { switch (name) { case"items": case"itemTemplateProperty": if (this._selectionEnabled()) { var itemsCount = value && value.length || 0, maxIndex = Math.max(itemsCount - 1, 0); if (maxIndex < this.option("selectedIndex")) this.option("selectedIndex", 0) } this._cleanRenderedItems(); this._invalidate(); break; case"dataSource": this._refreshDataSource(); if (!this._dataSource) this.option("items", []); this._renderEmptyMessage(); break; case"noDataText": this._renderEmptyMessage(); break; case"itemTemplate": this._invalidate(); break; case"itemRender": this._itemRender = null; this._invalidate(); break; case"itemRenderedAction": this._createItemRenderAction(); break; case"itemClickAction": break; case"itemHoldAction": case"itemHoldTimeout": this._attachHoldEvent(); break; case"selectedIndex": this._fireSelectItemEvent(value, prevValue); break; case"itemSelectAction": break; default: this.callBase(name, value, prevValue) } }, _expectNextPageLoading: function() { this._startIndexForAppendedItems = 0 }, _expectLastItemLoading: function() { this._startIndexForAppendedItems = -1 }, _forgetNextPageLoading: function() { this._startIndexForAppendedItems = null }, _handleDataSourceChanged: function(newItems) { var items = this.option("items"); if (this._initialized && items && this._shouldAppendItems()) { this._renderedItemsCount = items.length; if (!this._dataSource.isLastPage() || this._startIndexForAppendedItems !== -1) this.option().items = items.concat(newItems.slice(this._startIndexForAppendedItems)); this._renderContent(); this._forgetNextPageLoading() } else this.option("items", newItems) }, _handleDataSourceLoadError: function() { this._forgetNextPageLoading() }, _shouldAppendItems: function() { return this._startIndexForAppendedItems != null && this._allowDinamicItemsAppend() }, _allowDinamicItemsAppend: function() { return false }, _clean: function() { this._itemContainer().empty() }, _refresh: function() { this._cleanRenderedItems(); this.callBase.apply(this, arguments) }, _itemContainer: function() { return this._element() }, _itemClass: DX.abstract, _itemSelector: function() { return "." + this._itemClass() }, _itemDataKey: DX.abstract, _itemElements: function() { return this._itemContainer().find(this._itemSelector()) }, _render: function() { this.callBase(); this._attachClickEvent(); this._attachHoldEvent(); if (this._selectionEnabled()) { this._renderSelectedIndex(this.option("selectedIndex")); this._attachSelectedEvent() } }, _selectionEnabled: function() { return this._renderSelectedIndex !== DX.abstract }, _selectionByClickEnabled: function() { return true }, _renderSelectedIndex: DX.abstract, _attachSelectedEvent: function() { if (!this._selectionByClickEnabled()) return; var itemSelector = this._itemSelector(), itemSelectHandler = this._createAction($.proxy(function(e) { this._handleItemSelect(e.jQueryEvent) }, this), {validatingTargetName: "itemElement"}), eventName = events.addNamespace("dxclick", this.NAME); this._element().off(eventName, itemSelector).on(eventName, itemSelector, $.proxy(function(e) { var $itemElement = $(e.target).closest(itemSelector); itemSelectHandler({ itemElement: $itemElement, jQueryEvent: e }); this._handleItemClick(e) }, this)) }, _handleItemSelect: function(e) { if (events.needSkipEvent(e)) return; var items = this.option("items"), selectedItem = $(e.currentTarget).data(this._itemDataKey()), selectedItemIndex = $.inArray(selectedItem, items); this.option("selectedIndex", selectedItemIndex) }, _updateSelectedIndex: function() { this._renderSelectedIndex.apply(this, arguments) }, _selectedItemElement: function(index) { return this._itemElements().eq(index) }, _attachClickEvent: function() { if (this._selectionEnabled() && this._selectionByClickEnabled()) return; var itemSelector = this._itemSelector(), eventName = events.addNamespace("dxclick", this.NAME); this._itemContainer().off(eventName, itemSelector).on(eventName, itemSelector, $.proxy(this._handleItemClick, this)) }, _handleItemClick: function(e) { this._handleItemJQueryEvent(e, "itemClickAction") }, _attachHoldEvent: function() { var $itemContainer = this._itemContainer(), itemSelector = this._itemSelector(), eventName = events.addNamespace("dxhold", this.NAME); $itemContainer.off(eventName, itemSelector); if (this._shouldAttachHoldEvent()) $itemContainer.on(eventName, itemSelector, {timeout: this.option("itemHoldTimeout")}, $.proxy(this._handleItemHold, this)) }, _shouldAttachHoldEvent: function() { return this.option("itemHoldAction") }, _handleItemHold: function(e) { this._handleItemJQueryEvent(e, "itemHoldAction") }, _renderContentImpl: function() { var items = this.option("items") || []; if (this._renderedItemsCount) this._renderItems(items.slice(this._renderedItemsCount)); else this._renderItems(items) }, _renderItems: function(items) { if (items.length) $.each(items, $.proxy(this._renderItem, this)); this._renderEmptyMessage() }, _renderItem: function(index, itemData, container) { container = container || this._itemContainer(); var itemRenderer = this._getItemRenderer(), itemTemplateName = this._getItemTemplateName(itemData), itemTemplate = this._getTemplate(itemTemplateName, index, itemData), itemElement, renderArgs = { index: index, item: itemData, container: container }; if (itemRenderer) itemElement = this._createItemByRenderer(itemRenderer, renderArgs); else if (itemTemplate) itemElement = this._createItemByTemplate(itemTemplate, renderArgs); else itemElement = this._createItemByRenderer(this._itemRenderDefault, renderArgs); itemElement.addClass(this._itemClass()).data(this._itemDataKey(), itemData); var postprocessRenderArgs = { itemElement: itemElement, itemData: itemData, itemIndex: index }; this._postprocessRenderItem(postprocessRenderArgs); this._getItemRenderAction()({ itemElement: itemElement, itemData: itemData }); return itemElement }, _createItemRenderAction: function() { return this._itemRenderAction = this._createActionByOption("itemRenderedAction", { element: this._element(), excludeValidators: ["gesture", "designMode", "disabled"] }) }, _getItemRenderAction: function() { return this._itemRenderAction || this._createItemRenderAction() }, _getItemRenderer: function() { this._itemRender = this._itemRender || this.option("itemRender"); return this._itemRender }, _createItemByRenderer: function(itemRenderer, renderArgs) { var itemElement = $("
").appendTo(renderArgs.container); var rendererResult = itemRenderer.call(this, renderArgs.item, renderArgs.index, itemElement); if (rendererResult != null && itemElement[0] !== rendererResult[0]) itemElement.append(rendererResult); return itemElement }, _getItemTemplateName: function(itemData) { var templateProperty = this.option("itemTemplateProperty"); return itemData && itemData[templateProperty] || this.option("itemTemplate") }, _createItemByTemplate: function(itemTemplate, renderArgs) { return itemTemplate.render(renderArgs.container, renderArgs.item, renderArgs.index, "ignoreTarget") }, _itemRenderDefault: function(item, index, itemElement) { if ($.isPlainObject(item)) { if (item.visible !== undefined && !item.visible) itemElement.hide(); if (item.disabled) itemElement.addClass("dx-state-disabled"); if (item.text) itemElement.text(item.text); if (item.html) itemElement.html(item.html) } else itemElement.html(String(item)) }, _postprocessRenderItem: $.noop, _renderEmptyMessage: function() { if (!this._selectionEnabled()) { var noDataText = this.option("noDataText"), items = this.option("items"), dataSourceLoading = this._dataSource && this._dataSource.isLoading(), hideNoData = !noDataText || items && items.length || dataSourceLoading; if (hideNoData && this._$nodata) { this._$nodata.remove(); this._$nodata = null } if (!hideNoData) { this._$nodata = this._$nodata || $("
").addClass("dx-empty-message"); this._$nodata.appendTo(this._itemContainer()).text(noDataText) } } }, _handleItemJQueryEvent: function(jQueryEvent, handlerOptionName, actionArgs, actionConfig) { this._handleItemEvent(jQueryEvent.target, handlerOptionName, $.extend(actionArgs, {jQueryEvent: jQueryEvent}), actionConfig) }, _handleItemEvent: function(initiator, handlerOptionName, actionArgs, actionConfig) { var action = this._createActionByOption(handlerOptionName, $.extend({validatingTargetName: "itemElement"}, actionConfig)); return this._handleItemEventImpl(initiator, action, actionArgs) }, _handleItemEventByHandler: function(initiator, handler, actionArgs, actionConfig) { var action = this._createAction(handler, $.extend({validatingTargetName: "itemElement"}, actionConfig)); return this._handleItemEventImpl(initiator, action, actionArgs) }, _handleItemEventImpl: function(initiator, action, actionArgs) { var $itemElement = this._closestItemElement($(initiator)); actionArgs = $.extend({ itemElement: $itemElement, itemData: this._getItemData($itemElement) }, actionArgs); return action(actionArgs) }, _closestItemElement: function($element) { return $($element).closest(this._itemSelector()) }, _getItemData: function($itemElement) { return $itemElement.data(this._itemDataKey()) }, itemElements: function() { return this._itemElements() }, itemsContainer: function() { return this._itemContainer() } }).include(ui.DataHelperMixin); ui.CollectionContainerWidget = CollectionContainerWidget })(jQuery, DevExpress); /*! Module core, file ui.tooltip.js */ (function($, DX, undefined) { var $tooltip = null; var createTooltip = function(options) { options = $.extend({position: "top"}, options); var content = options.content; delete options.content; return $("
").html(content).appendTo(DX.overlayTargetContainer()).dxTooltip(options) }; var removeTooltip = function() { if (!$tooltip) return; $tooltip.remove(); $tooltip = null }; var tooltip = { show: function(options) { removeTooltip(); $tooltip = createTooltip(options); return $tooltip.dxTooltip("show") }, hide: function() { if (!$tooltip) return $.when(); return $tooltip.dxTooltip("hide").done(removeTooltip).promise() } }; DX.ui.tooltip = tooltip })(jQuery, DevExpress) } if (!DevExpress.MOD_VIZ_CORE) { if (!window.DevExpress) throw Error('Required module is not referenced: core'); /*! Module viz-core, file namespaces.js */ (function(DevExpress) { DevExpress.viz = {} })(DevExpress); /*! Module viz-core, file namespaces.js */ (function(DevExpress) { DevExpress.viz.core = {} })(DevExpress); /*! Module viz-core, file errorsWarnings.js */ (function(DevExpress) { DevExpress.viz.core.errorsWarnings = { E2001: "Invalid data source", E2002: "Axis type and data type are incompatible", E2003: "\"{0}\" data source field contains data of unsupported type", E2004: "\"{0}\" data source field is inconsistent", E2101: "Unknown series type was specified: {0}", E2102: "Ambiguity occurred between two value axes with the same name", E2103: "\"{0}\" option must be a function", E2104: "Invalid logarithm base", E2105: "Invalid value of a \"{0}\"", E2106: "Invalid visible range", E2201: "Invalid type of data source field", E2202: "Invalid scale {0} value", E2203: "The \"{0}\" field of the \"selectedRange\" configuration object is not valid", W2001: "{0} cannot be drawn because its container is invisible", W2002: "The {0} data field is absent", W2003: "Tick interval is too small", W2101: "\"{0}\" pane does not exist; \"{1}\" pane is used instead", W2102: "Value axis with the \"{0}\" name was created automatically", W2103: "Chart title was hidden due to container size", W2104: "Legend was hidden due to container size", W2105: "Title of \"{0}\" axis was hidden due to container size", W2106: "Labels of \"{0}\" axis were hidden due to container size", W2301: "Invalid value range" } })(DevExpress); /*! Module viz-core, file tickProvider.js */ (function($, DX, undefined) { var utils = DX.utils, math = Math, mathCeil = math.ceil, mathFloor = math.floor, mathAbs = math.abs, mathRound = math.round, core = DX.viz.core; var TICKS_COUNT_LIMIT = 2000; core.outOfScreen = { x: -1000, y: -1000 }; core.tickIntervalCalculator = { _defaultNumberMultipliers: [1, 2, 3, 5], _defaultGridSpacingFactor: 30, _getCommonTickInterval: function(deltaCoef, numberMultipliers) { var factor, result = 0, hasResult = false, i; for (factor = 1; !hasResult; factor *= 10) for (i = 0; i < numberMultipliers.length; i++) { result = numberMultipliers[i] * factor; if (deltaCoef <= result) { hasResult = true; break } } return result }, _getNumericTickInterval: function(deltaCoef, numberMultipliers) { var factor, result = 0, newResult, hasResult = false, i; if (deltaCoef > 1.0) result = this._getCommonTickInterval(deltaCoef, numberMultipliers); else if (deltaCoef > 0) { result = 1; for (factor = 0.1; !hasResult; factor /= 10) for (i = numberMultipliers.length - 1; i >= 0; i--) { newResult = numberMultipliers[i] * factor; if (deltaCoef > newResult) { hasResult = true; break } result = newResult } } return utils.adjustValue(result) }, _getLogarithmicTickInterval: function(deltaCoef, numberMultipliers) { var result = 0; if (deltaCoef !== 0) result = this._getCommonTickInterval(deltaCoef, numberMultipliers); return utils.adjustValue(result) }, _getDateTimeTickInterval: function(deltaCoef, numberMultipliers) { var dateTimeMultipliers = { millisecond: [1, 2, 5, 10, 25, 100, 250, 300, 500], second: [1, 2, 3, 5, 10, 15, 20, 30], minute: [1, 2, 3, 5, 10, 15, 20, 30], hour: [1, 2, 3, 4, 6, 8, 12], day: [1, 2, 3, 5, 7, 10, 14], month: [1, 2, 3, 6] }, result = {}, factor, key, specificMultipliers, yearsCount, i; if (deltaCoef > 0 && deltaCoef < 1.0) return {milliseconds: 1}; else if (deltaCoef === 0) return 0; for (key in dateTimeMultipliers) if (dateTimeMultipliers.hasOwnProperty(key)) { specificMultipliers = dateTimeMultipliers[key]; for (i = 0; i < specificMultipliers.length; i++) if (deltaCoef <= utils.convertDateUnitToMilliseconds(key, specificMultipliers[i])) { result[key + 's'] = specificMultipliers[i]; return result } } for (factor = 1; ; factor *= 10) for (i = 0; i < numberMultipliers.length; i++) { yearsCount = factor * numberMultipliers[i]; if (deltaCoef <= utils.convertDateUnitToMilliseconds('year', yearsCount)) return {years: yearsCount} } return null }, getTickInterval: function(options) { var that = this, gridSpacingFactor = options.gridSpacingFactor || that._defaultGridSpacingFactor, numberMultipliers = options.numberMultipliers || that._defaultNumberMultipliers, businessDelta = options.businessDelta, screenDelta = options.screenDelta, deltaCoef = screenDelta > 0 && gridSpacingFactor < screenDelta ? gridSpacingFactor * businessDelta / screenDelta : 0; that._testNumberMultipliers = numberMultipliers; if (options.axisType === 'logarithmic') return that._getLogarithmicTickInterval(deltaCoef, numberMultipliers); else switch (options.dataType) { case'numeric': return that._getNumericTickInterval(deltaCoef, numberMultipliers); break; case'datetime': return that._getDateTimeTickInterval(deltaCoef, numberMultipliers); break } return null } }; core.minorTickIntervalCalculator = { _defaultNumberMultipliers: [2, 4, 5, 8, 10], _defaultGridSpacingFactor: 15, _getDateTimeTickInterval: function(businessDelta, deltaCoef, numberMultipliers) { var result, i; for (i = numberMultipliers.length - 1; i >= 0; i--) { this.testResultNumberMultiplier = numberMultipliers[i]; result = mathFloor(businessDelta / numberMultipliers[i]); if (deltaCoef <= result) return utils.convertMillisecondsToDateUnits(result) } return 0 }, _getCommonTickInterval: function(businessDelta, deltaCoef, numberMultipliers) { var result, i; for (i = numberMultipliers.length - 1; i >= 0; i--) { this.testResultNumberMultiplier = numberMultipliers[i]; result = businessDelta / numberMultipliers[i]; if (deltaCoef <= result) return utils.adjustValue(result) } return 0 }, getTickInterval: function(options) { var that = this, gridSpacingFactor = !utils.isDefined(options.gridSpacingFactor) ? that._defaultGridSpacingFactor : options.gridSpacingFactor, numberMultipliers = options.numberMultipliers || that._defaultNumberMultipliers, businessDelta = options.businessDelta, deltaCoef = gridSpacingFactor * businessDelta / options.screenDelta; if (options.axisType === 'logarithmic') return that._getCommonTickInterval(businessDelta, deltaCoef, numberMultipliers); else switch (options.dataType) { case'numeric': return that._getCommonTickInterval(businessDelta, deltaCoef, numberMultipliers); case'datetime': return that._getDateTimeTickInterval(businessDelta, deltaCoef, numberMultipliers) } return 0 } }; core.tickProvider = { _appendFakeSVGElement: function(value, text, options) { var textOptions = $.extend({}, options.textOptions, {rotate: 0}); return options.renderer.createText(text, core.outOfScreen.x + (options.translator.translate(value) || 0), core.outOfScreen.y, textOptions).append() }, _getDistanceByAngle: function(elementHeight, rotationAngle) { return elementHeight / mathAbs(math.sin(rotationAngle * (math.PI / 180))) }, _areDisplayValuesValid: function(value1, value2, options) { var that = this, getText = that._getTextFunc(options), rotationAngle = options.textOptions && utils.isNumber(options.textOptions.rotate) ? options.textOptions.rotate : 0, svgElement1 = that._appendFakeSVGElement(value1, getText(value1), options), svgElement2 = that._appendFakeSVGElement(value2, getText(value2), options), bBox1 = svgElement1.getBBox(), bBox2 = svgElement2.getBBox(), result, translator = options.translator; if (rotationAngle !== 0) result = that._getDistanceByAngle(bBox1.height, rotationAngle) <= mathAbs(bBox2.x - bBox1.x); else if (options.isHorizontal) result = !translator.getBusinessRange().invert ? bBox1.x + bBox1.width < bBox2.x : bBox2.x + bBox2.width < bBox1.x; else result = mathAbs(translator.translate(value1) - translator.translate(value2)) > bBox1.height; svgElement1.remove(); svgElement2.remove(); return result }, _removeInvalidDatesWithUnitBegining: function(dates, options) { if (dates.length <= 1 || !options.setTicksAtUnitBeginning || !utils.isDate(options.min)) return; if (!this._areDisplayValuesValid(dates[0], dates[1], options)) dates.splice(1, 1) }, _getValueSize: function(values, options) { var that = this, value, rotationAngle = options.textOptions ? options.textOptions.rotate : 0, svgElement, bBox, result, getText = that._getTextFunc(options), i; if (values.length === 0) return 0; options.isRotate = utils.isNumber(rotationAngle) && rotationAngle !== 0; if (options.isRotate || !options.isHorizontal) value = getText(values[0]); else { value = []; for (i = 0; i < values.length; i++) value.push(getText(values[i])); value = value.join('\n') } svgElement = that._appendFakeSVGElement(value, value, options); bBox = svgElement.getBBox(); if (options.isRotate) result = that._getDistanceByAngle(bBox.height, rotationAngle); else result = options.isHorizontal ? bBox.width : bBox.height; svgElement.remove(); return mathCeil(result) }, _adjustNumericTickValue: function(value, interval, min) { return utils.isExponential(value) ? utils.adjustValue(value) : utils.applyPrecisionByMinDelta(min, interval, value) }, _generateStartTick: function(tickInterval, options) { var that = this, milliseconds = 0, boundedRule = options.min - options.max < 0, startTick = options.min, isDate = utils.isDate(options.min), currentTickInterval = isDate ? utils.convertDateTickIntervalToMilliseconds(tickInterval) : tickInterval, nextTick; if (options.axisType === 'logarithmic') startTick = utils.raiseTo(mathFloor(utils.adjustValue(utils.getLog(options.min, options.base)) / currentTickInterval * currentTickInterval), options.base); else { startTick = mathFloor(options.min / currentTickInterval) * currentTickInterval; startTick = isDate ? new Date(startTick) : that._adjustNumericTickValue(startTick, currentTickInterval, options.min) } while (boundedRule === startTick - options.min < 0 && startTick !== options.min) { nextTick = that._nextTick(startTick, tickInterval, options); if (nextTick !== startTick) startTick = nextTick; else return nextTick } return startTick }, _nextTick: function(tick, tickInterval, options) { var nextTick, lgPower, that = this; if (options.axisType === 'logarithmic') { lgPower = utils.addInterval(utils.adjustValue(utils.getLog(tick, options.base)), tickInterval, options.min > options.max); nextTick = utils.raiseTo(lgPower, options.base); nextTick = that._adjustNumericTickValue(nextTick, tickInterval, math.min(options.min, options.max)) } else { nextTick = utils.addInterval(tick, tickInterval, options.min > options.max); if (options.dataType === 'numeric') nextTick = that._adjustNumericTickValue(nextTick, tickInterval, options.min); if (options.dataType === 'datetime' && options.setTicksAtUnitBeginning) utils.correctDateWithUnitBeginning(nextTick, tickInterval) } return nextTick }, _addMinorTicks: function(majorTick1, majorTick2, ticksInfo, options, isReverse) { var that = this, i, dataType = options.dataType, businessDelta, minorTicks = [], interval = 0, minorTickIntervalsCount = options.minorTickCount + 1, intervalsCount, tickInterval; options.min = majorTick1; options.max = majorTick2; if (!utils.isDefined(options.tickInterval)) { options.businessDelta = businessDelta = mathAbs(options.max - options.min); options.screenDelta = businessDelta * options.deltaCoef; if (utils.isDefined(options.minorTickCount)) { if (!ticksInfo.majorTicks.autoArrangementStep || ticksInfo.majorTicks.autoArrangementStep <= 1) { intervalsCount = options.minorTickCount + 1; interval = dataType === 'datetime' ? utils.convertDateTickIntervalToMilliseconds(ticksInfo.majorTickInterval) : ticksInfo.majorTickInterval; minorTickIntervalsCount = mathRound(businessDelta / interval * intervalsCount) || 1 } tickInterval = dataType === 'datetime' ? utils.convertMillisecondsToDateUnits(businessDelta / minorTickIntervalsCount) : businessDelta / minorTickIntervalsCount; if ($.isNumeric(tickInterval)) tickInterval = utils.adjustValue(tickInterval) } else if (utils.isDate(majorTick1)) tickInterval = core.minorTickIntervalCalculator.getTickInterval(options) } options = $.extend(true, {}, options, {tickInterval: tickInterval}); minorTicks = that.getTicks(options); if (isReverse) minorTicks.reverse(); if (minorTicks.length > 0) if (mathCeil(mathAbs(majorTick2 - minorTicks[minorTicks.length - 1]) * options.deltaCoef) < 2) minorTicks.pop(); for (i = 0; i < minorTicks.length; i++) { ticksInfo.minorTicks.push(minorTicks[i]); ticksInfo.fullTicks.push(minorTicks[i]) } }, _addLeftBoudedTicks: function(ticksInfo, min, minorTicksOptions) { if (utils.isDefined(min) && ticksInfo.majorTicks[0].valueOf() !== min.valueOf()) { minorTicksOptions.addMinMax.max = true; this._addMinorTicks(ticksInfo.majorTicks[0], min, ticksInfo, minorTicksOptions, true); minorTicksOptions.addMinMax.max = false; if (minorTicksOptions.showCustomBoundaryTicks) { if (ticksInfo.minorTicks.length > 0 && ticksInfo.minorTicks[0].valueOf() === min.valueOf()) ticksInfo.minorTicks.shift(min); ticksInfo.customBoundaryTicks.push(min); ticksInfo.fullTicks.unshift(min) } } }, _addRightBoudedTicks: function(ticksInfo, max, minorTicksOptions) { var lastMajorTick = ticksInfo.majorTicks[ticksInfo.majorTicks.length - 1]; ticksInfo.fullTicks.push(lastMajorTick); if (utils.isDefined(max) && lastMajorTick.valueOf() !== max.valueOf()) { minorTicksOptions.addMinMax.min = false; minorTicksOptions.addMinMax.max = true; this._addMinorTicks(lastMajorTick, max, ticksInfo, minorTicksOptions); if (minorTicksOptions.showCustomBoundaryTicks) { if (ticksInfo.minorTicks.length > 0 && ticksInfo.minorTicks[ticksInfo.minorTicks.length - 1].valueOf() === max.valueOf()) ticksInfo.minorTicks.pop(max); ticksInfo.customBoundaryTicks.push(max); ticksInfo.fullTicks.push(max) } } }, _correctBoundedTicks: function(min, max, ticks, addMinMax) { addMinMax = $.extend({}, { min: true, max: true }, addMinMax); if (ticks.length > 0) { if (!addMinMax.min && ticks[0].valueOf() === min.valueOf()) ticks.shift(); if (!addMinMax.max || ticks[ticks.length - 1].valueOf() !== max.valueOf()) ticks.pop() } }, _initializeMinorTicksOptions: function(min, max, screenDelta, ticksInfo, options) { var that = this, businessDelta, hasMinorsCount = utils.isDefined(options.minorTickCount); $.extend(true, options, { addMinMax: { min: false, max: false }, deltaCoef: that._getDeltaCoef(screenDelta, max, min, options.axisType, options.base) }, options); options.numberMultipliers = hasMinorsCount ? [options.minorTickCount + 1] : options.numberMultipliers; options.gridSpacingFactor = hasMinorsCount ? 0 : options.gridSpacingFactor; if (!hasMinorsCount && ticksInfo.majorTicks.length > 1) { options.businessDelta = businessDelta = that._getBusinessDelta(options.axisType, ticksInfo.majorTicks[0], ticksInfo.majorTicks[1], options.base); if (that.needTickIntervalCalculation(businessDelta, ticksInfo.minorTickInterval, options.incidentOccured)) { options.screenDelta = businessDelta * options.deltaCoef; ticksInfo.minorTickInterval = core.minorTickIntervalCalculator.getTickInterval(options); if (utils.isNumber(min)) options.tickInterval = ticksInfo.minorTickInterval; else options.tickInterval = undefined } } }, _getDataType: function(value) { return utils.isDate(value) ? 'datetime' : 'numeric' }, _getBusinessDelta: function(type, min, max, base) { return type === 'logarithmic' ? mathRound(mathAbs(utils.getLog(min, base) - utils.getLog(max, base))) : mathAbs(min - max) }, _getDeltaCoef: function(screenDelta, max, min, type, base) { return screenDelta / this._getBusinessDelta(type, min, max, base) }, _initializeMajorTicksOptions: function(min, max, screenDelta, ticksInfo, options) { var businessDelta; options.screenDelta = screenDelta; $.extend(true, options, { min: min, max: max, screenDelta: screenDelta, isHorizontal: true }); if (utils.isDefined(min) && utils.isDefined(max)) { options.businessDelta = businessDelta = this._getBusinessDelta(options.axisType, min, max, options.base); if (this.needTickIntervalCalculation(businessDelta, ticksInfo.majorTickInterval, options.incidentOccured)) { options.isStartTickGenerated = true; ticksInfo.majorTickInterval = core.tickIntervalCalculator.getTickInterval(options); options.tickInterval = ticksInfo.majorTickInterval } } }, _getTextFunc: function(options) { return options.getText || function(value) { return value.toString() } }, _generateTicks: function(options) { var that = this, ticks = [], tick, boundedRule = options.max - options.min > 0, leftBound, rightBound, tickInterval, isStartTickGenerated = options.isStartTickGenerated, businessDelta, useTicksAutoArrangement = options.useTicksAutoArrangement; options.dataType = options.dataType || that._getDataType(options.min); options.businessDelta = businessDelta = that._getBusinessDelta(options.axisType, options.min, options.max, options.base); if (!utils.isDefined(options.min) || !utils.isDefined(options.max) || isNaN(options.min) || isNaN(options.max)) { ticks = options.isHorizontal ? ['canvas_position_left', 'canvas_position_center', 'canvas_position_right'] : ['canvas_position_bottom', 'canvas_position_middle', 'canvas_position_top']; useTicksAutoArrangement = false; ticks.hideLabels = true } else { tickInterval = $.isNumeric(options.min) && $.isNumeric(options.max) && !$.isNumeric(options.tickInterval) ? undefined : options.tickInterval; if (this.needTickIntervalCalculation(businessDelta, tickInterval, options.incidentOccured)) { isStartTickGenerated = utils.isDefined(isStartTickGenerated) ? isStartTickGenerated : true; tickInterval = core.tickIntervalCalculator.getTickInterval(options) } ticks.tickInterval = tickInterval; that.isTestStartTickGenerated = isStartTickGenerated; that.isTestTickInterval = tickInterval; that.testGridSpacingFactor = options.gridSpacingFactor; if (tickInterval && tickInterval.valueOf() !== 0 && options.min.valueOf() !== options.max.valueOf()) { tick = isStartTickGenerated ? that._generateStartTick(tickInterval, options) : options.min; do { ticks.push(tick); tick = that._nextTick(tick, tickInterval, options); if (ticks[ticks.length - 1].valueOf() === tick.valueOf()) break; leftBound = tick - options.min > 0; rightBound = options.max - tick > 0 } while (boundedRule === leftBound && boundedRule === rightBound); ticks.push(tick); that._correctBoundedTicks(options.min, options.max, ticks, options.addMinMax) } if (options.min.valueOf() === options.max.valueOf()) { tick = options.min; ticks.push(tick) } } return ticks }, _getAutoArrangementStep: function(ticks, options) { var that = this, requiredValuesCount, addedSpacing = options.isHorizontal ? options.textSpacing : 0; if (options.getCustomAutoArrangementStep) return options.getCustomAutoArrangementStep(ticks, options); if (options.maxDisplayValueSize > 0) { requiredValuesCount = mathFloor((options.screenDelta + options.textSpacing) / (options.maxDisplayValueSize + addedSpacing)); return mathCeil((options.ticksCount || ticks.length) / requiredValuesCount) } return 1 }, _getAutoArrangementTicks: function(ticks, options, step) { var that = this, resultTicks = ticks, i; if (step > 1) { resultTicks = []; for (i = 0; i < ticks.length; i += step) resultTicks.push(ticks[i]); resultTicks.tickInterval = ticks.tickInterval * step } return resultTicks }, isOverlappedTicks: function(ticks, options) { options.maxDisplayValueSize = this._getValueSize(ticks, options); return this._getAutoArrangementStep(ticks, options) > 1 }, getCorrectedTicks: function(ticks, ticksOptions) { var step = Math.ceil(core.tickIntervalCalculator.getTickInterval({ screenDelta: ticksOptions.screenDelta * 4, businessDelta: ticks.length, gridSpacingFactor: ticksOptions.gridSpacingFactor, numberMultipliers: ticksOptions.numberMultipliers, dataType: "numeric" })) || ticks.length; return this._getAutoArrangementTicks(ticks, ticksOptions, step) }, needTickIntervalCalculation: function(businessDelta, tickInterval, incidentOccured) { var date; if (utils.isDefined(tickInterval)) { if (!utils.isNumber(tickInterval)) { date = new Date; tickInterval = utils.addInterval(date, tickInterval) - date; if (!tickInterval) return true } if (utils.isNumber(tickInterval)) if (tickInterval > 0 && businessDelta / tickInterval > TICKS_COUNT_LIMIT) { if (incidentOccured) incidentOccured('W2003') } else return false } return true }, getTickIntervals: function(min, max, screenDelta, majorTicksOptions, minorTicksOptions, options) { var that = this, i, options = options || {}, ticksInfo = { majorTickInterval: majorTicksOptions.tickInterval, minorTickInterval: minorTicksOptions.tickInterval, majorTicks: [] }; majorTicksOptions.base = minorTicksOptions.base = options.base; majorTicksOptions.axisType = minorTicksOptions.axisType = options.axisType; majorTicksOptions.dataType = minorTicksOptions.dataType = options.dataType; that._initializeMajorTicksOptions(min, max, screenDelta, ticksInfo, majorTicksOptions); if (utils.isDefined(min) && utils.isDefined(max)) { ticksInfo.majorTicks.push(min); ticksInfo.majorTicks.push(that._nextTick(min, ticksInfo.majorTickInterval, { min: min, max: max, setTicksAtUnitBeginning: majorTicksOptions.setTicksAtUnitBeginning, dataType: options.dataType, axisType: options.axisType, base: options.base })); that._initializeMinorTicksOptions(min, max, screenDelta, ticksInfo, minorTicksOptions) } return ticksInfo }, getFullTicks: function(min, max, screenDelta, majorTicksOptions, minorTicksOptions, options) { var that = this, i, options = options || {}, ticksInfo = { customBoundaryTicks: [], fullTicks: [], majorTickInterval: majorTicksOptions.tickInterval, majorTicks: [], minorTickInterval: minorTicksOptions.tickInterval, minorTicks: [] }; majorTicksOptions.base = minorTicksOptions.base = options.base; majorTicksOptions.axisType = minorTicksOptions.axisType = options.axisType; majorTicksOptions.dataType = minorTicksOptions.dataType = options.dataType || that._getDataType(min); that._initializeMajorTicksOptions(min, max, screenDelta, ticksInfo, majorTicksOptions); ticksInfo.majorTicks = that.getTicks(majorTicksOptions); if (utils.isDefined(min) && utils.isDefined(max) && ticksInfo.majorTicks.length > 0) { if (ticksInfo.majorTicks.autoArrangementStep && ticksInfo.majorTicks.autoArrangementStep > 1 && !utils.isDefined(minorTicksOptions.tickInterval) && !utils.isDefined(minorTicksOptions.minorTickCount)) minorTicksOptions.tickInterval = ticksInfo.minorTickInterval = majorTicksOptions.tickInterval; that._initializeMinorTicksOptions(min, max, screenDelta, ticksInfo, minorTicksOptions); that._addLeftBoudedTicks(ticksInfo, min, minorTicksOptions); for (i = 0; i < ticksInfo.majorTicks.length - 1; i++) { ticksInfo.fullTicks.push(ticksInfo.majorTicks[i]); that._addMinorTicks(ticksInfo.majorTicks[i], ticksInfo.majorTicks[i + 1], ticksInfo, minorTicksOptions) } that._addRightBoudedTicks(ticksInfo, max, minorTicksOptions) } return ticksInfo }, getTicks: function(options) { var that = this, step, maxDisplayValue, ticks = options.customTicks ? options.customTicks : that._generateTicks(options); if (options.useTicksAutoArrangement) { options.maxDisplayValueSize = that._getValueSize(ticks, options); step = that._getAutoArrangementStep(ticks, options); if (step > 1) { if (utils.isDefined(options.tickInterval) || utils.isDefined(options.customTicks)) { utils.isDefined(options.customTicks) && (ticks.tickInterval = options.tickInterval); ticks = that._getAutoArrangementTicks(ticks, options, step) } else ticks = that._generateTicks($.extend({}, options, {gridSpacingFactor: options.maxDisplayValueSize})); ticks.autoArrangementStep = step } that._removeInvalidDatesWithUnitBegining(ticks, options) } return ticks } } })(jQuery, DevExpress); /*! Module viz-core, file numericTranslator.js */ (function($, DX, undefined) { var utils = DX.utils, isDefined = utils.isDefined, getPower = utils.getPower, round = Math.round; DX.viz.core.numericTranslatorFunctions = { translate: function(bp) { var that = this, canvasOptions = that._canvasOptions, doubleError = canvasOptions.rangeDoubleError, specialValue = that.translateSpecialCase(bp); if (isDefined(specialValue)) return specialValue; if (isNaN(bp) || bp.valueOf() + doubleError < canvasOptions.rangeMin || bp.valueOf() - doubleError > canvasOptions.rangeMax) return null; return round(that._calculateProjection((bp - canvasOptions.rangeMinVisible) * canvasOptions.ratioOfCanvasRange)) }, untranslate: function(pos) { var canvasOptions = this._canvasOptions, startPoint = canvasOptions.startPoint; if (pos < startPoint || pos > canvasOptions.endPoint) return null; return this._calculateUnProjection((pos - startPoint) / canvasOptions.ratioOfCanvasRange) }, getInterval: function() { return round(this._canvasOptions.ratioOfCanvasRange * (this._businessRange.interval || Math.abs(this._canvasOptions.rangeMax - this._canvasOptions.rangeMin))) } } })(jQuery, DevExpress); /*! Module viz-core, file datetimeTranslator.js */ (function($, DX, undefined) { var core = DX.viz.core, numericTranslator = core.numericTranslatorFunctions; core.datetimeTranslatorFunctions = { translate: numericTranslator.translate, untranslate: function(pos) { var result = numericTranslator.untranslate.call(this, pos); return result === null ? result : new Date(result) }, getInterval: numericTranslator.getInterval } })(jQuery, DevExpress); /*! Module viz-core, file categoryTranslator.js */ (function($, DX, undefined) { var isDefined = DX.utils.isDefined, round = Math.round; function doubleRound(value) { return round(round(value * 10) / 10) } DX.viz.core.categoryTranslatorFunctions = { translate: function(category) { var that = this, canvasOptions = that._canvasOptions, categoryRecord = that._categoriesToPoints[category], stickDelta, specialValue = that.translateSpecialCase(category); if (isDefined(specialValue)) return specialValue; if (!categoryRecord) return 0; stickDelta = that._businessRange.stick ? categoryRecord.index : categoryRecord.index + 0.5; return round(canvasOptions.startPoint + canvasOptions.interval * stickDelta) }, untranslate: function(pos) { var that = this, canvasOptions = that._canvasOptions, startPoint = canvasOptions.startPoint, categoriesLength = that._categories.length, result = 0; if (pos < startPoint || pos > canvasOptions.endPoint) return null; result = doubleRound((pos - startPoint) / canvasOptions.interval + (that._businessRange.stick ? 0.5 : 0) - 0.5); if (categoriesLength === result) result--; if (canvasOptions.invert) result = categoriesLength - result - 1; return that._categories[result] }, getInterval: function() { return this._canvasOptions.interval } } })(jQuery, DevExpress); /*! Module viz-core, file logarithmicTranslator.js */ (function($, DX, undefined) { var core = DX.viz.core, numericTranslator = core.numericTranslatorFunctions, utils = DX.utils, raiseTo = utils.raiseTo, getLog = utils.getLog; core.logarithmicTranslatorFunctions = { translate: function(bp) { var that = this, specialValue = that.translateSpecialCase(bp); if (utils.isDefined(specialValue)) return specialValue; return numericTranslator.translate.call(that, getLog(bp, that._businessRange.base)) }, untranslate: function(pos) { var result = numericTranslator.untranslate.call(this, pos); return result === null ? result : raiseTo(result, this._businessRange.base) }, getInterval: numericTranslator.getInterval } })(jQuery, DevExpress); /*! Module viz-core, file translator1D.js */ (function(DX, undefined) { var _Number = Number; function Translator1D() { this.setDomain(arguments[0], arguments[1]).setCodomain(arguments[2], arguments[3]) } Translator1D.prototype = { constructor: Translator1D, setDomain: function(domain1, domain2) { var that = this; that._domain1 = _Number(domain1); that._domain2 = _Number(domain2); that._domainDelta = that._domain2 - that._domain1; return that }, setCodomain: function(codomain1, codomain2) { var that = this; that._codomain1 = _Number(codomain1); that._codomain2 = _Number(codomain2); that._codomainDelta = that._codomain2 - that._codomain1; return that }, getDomain: function() { return [this._domain1, this._domain2] }, getCodomain: function() { return [this._codomain1, this._codomain2] }, getDomainStart: function() { return this._domain1 }, getDomainEnd: function() { return this._domain2 }, getCodomainStart: function() { return this._codomain1 }, getCodomainEnd: function() { return this._codomain2 }, getDomainRange: function() { return this._domainDelta }, getCodomainRange: function() { return this._codomainDelta }, translate: function(value) { var ratio = (_Number(value) - this._domain1) / this._domainDelta; return 0 <= ratio && ratio <= 1 ? this._codomain1 + ratio * this._codomainDelta : NaN }, adjust: function(value) { var ratio = (_Number(value) - this._domain1) / this._domainDelta, result = NaN; if (ratio < 0) result = this._domain1; else if (ratio > 1) result = this._domain2; else if (0 <= ratio && ratio <= 1) result = _Number(value); return result } }; DX.viz.core.Translator1D = Translator1D })(DevExpress); /*! Module viz-core, file translator2D.js */ (function($, DX, undefined) { var core = DX.viz.core, utils = DX.utils, getLog = utils.getLog, getPower = utils.getPower, raiseTo = utils.raiseTo, isDefined = utils.isDefined, CANVAS_PROP = ["width", "height", "left", "top", "bottom", "right"], NUMBER_EQUALITY_CORRECTION = 1, DATETIME_EQUALITY_CORRECTION = 60000; var validateCanvas = function(canvas) { $.each(CANVAS_PROP, function(_, prop) { canvas[prop] = parseInt(canvas[prop]) || 0 }); return canvas }; var raiseToFlooredLog = function(value, base, correction) { return raiseTo(Math.floor(getLog(value, base)) + (correction || 0), base) }; var makeCategoriesToPoints = function(categories, invert) { var categoriesToPoints = {}, category, length = categories.length, i; for (i = 0; i < length; i++) { category = categories[i]; categoriesToPoints[category] = { name: category, index: invert ? length - 1 - i : i } } return categoriesToPoints }; var validateBusinessRange = function(businessRange) { function validate(valueSelector, baseValueSeletor) { if (!isDefined(businessRange[valueSelector]) && isDefined(businessRange[baseValueSeletor])) businessRange[valueSelector] = businessRange[baseValueSeletor] } validate("minVisible", "min"); validate("maxVisible", "max"); return businessRange }; core.Translator2D = function(businessRange, canvas, options) { var that = this; that._options = $.extend(that._options || {}, options); that._canvas = validateCanvas(canvas); that.updateBusinessRange(businessRange) }; $.extend(core.Translator2D.prototype, { reinit: function() { var that = this, range = that._businessRange, categories = range.categories || [], script = {}, canvasOptions = that._prepareCanvasOptions(), interval, correctedCategoriesCount; switch (range.axisType) { case"logarithmic": script = core.logarithmicTranslatorFunctions; break; case"discrete": script = core.categoryTranslatorFunctions; that._categories = categories; correctedCategoriesCount = categories.length - (range.stick ? 1 : 0); if (correctedCategoriesCount > 0) interval = canvasOptions.canvasLength / correctedCategoriesCount; else interval = canvasOptions.canvasLength; canvasOptions.interval = interval; that._categoriesToPoints = makeCategoriesToPoints(categories, canvasOptions.invert); break; default: if (range.dataType === "datetime") script = core.datetimeTranslatorFunctions; else script = core.numericTranslatorFunctions } that.translate = script.translate; that.untranslate = script.untranslate; that.getInterval = script.getInterval }, _getCanvasBounds: function(range) { var min = range.min, max = range.max, minVisible = range.minVisible, maxVisible = range.maxVisible, newMin, newMax, base = range.base, isDateTime = utils.isDate(max) || utils.isDate(min), correction = isDateTime ? DATETIME_EQUALITY_CORRECTION : NUMBER_EQUALITY_CORRECTION; if (isDefined(min) && isDefined(max) && min.valueOf() === max.valueOf()) { newMin = min.valueOf() - correction; newMax = max.valueOf() + correction; if (isDateTime) { min = new Date(newMin); max = new Date(newMax) } else { min = min !== 0 ? newMin : 0; max = newMax } } if (isDefined(minVisible) && isDefined(maxVisible) && minVisible.valueOf() === maxVisible.valueOf()) { newMin = minVisible.valueOf() - correction; newMax = maxVisible.valueOf() + correction; if (isDateTime) { minVisible = newMin < min.valueOf() ? min : new Date(newMin); maxVisible = newMax > max.valueOf() ? max : new Date(newMax) } else { if (minVisible !== 0) minVisible = newMin < min ? min : newMin; maxVisible = newMax > max ? max : newMax } } if (range.axisType === 'logarithmic') { maxVisible = getLog(maxVisible, base); minVisible = getLog(minVisible, base); min = getLog(min, base); max = getLog(max, base) } return { base: base, rangeMin: min, rangeMax: max, rangeMinVisible: minVisible, rangeMaxVisible: maxVisible } }, _prepareCanvasOptions: function() { var that = this, rangeMin, rangeMax, rangeMinVisible, rangeMaxVisible, businessRange = that._businessRange, canvasOptions = that._canvasOptions = that._getCanvasBounds(businessRange), length; if (that._options.direction === "horizontal") { canvasOptions.startPoint = that._canvas.left; length = that._canvas.width; canvasOptions.endPoint = that._canvas.width - that._canvas.right; canvasOptions.invert = businessRange.invert } else { canvasOptions.startPoint = that._canvas.top; length = that._canvas.height; canvasOptions.endPoint = that._canvas.height - that._canvas.bottom; canvasOptions.invert = !businessRange.invert } that.canvasLength = canvasOptions.canvasLength = canvasOptions.endPoint - canvasOptions.startPoint; canvasOptions.rangeDoubleError = Math.pow(10, getPower(canvasOptions.rangeMax - canvasOptions.rangeMin) - getPower(length) - 2); canvasOptions.ratioOfCanvasRange = canvasOptions.canvasLength / (canvasOptions.rangeMaxVisible - canvasOptions.rangeMinVisible); return canvasOptions }, updateBusinessRange: function(businessRange) { this._businessRange = validateBusinessRange(businessRange); this.reinit() }, getBusinessRange: function() { return this._businessRange }, getCanvasVisibleArea: function() { return { min: this._canvasOptions.startPoint, max: this._canvasOptions.endPoint } }, translateSpecialCase: function(value) { var that = this, canvasOptions = that._canvasOptions, startPoint = canvasOptions.startPoint, endPoint = canvasOptions.endPoint, range = that._businessRange, minVisible = range.minVisible, maxVisible = range.maxVisible, invert, result = null; switch (value) { case"canvas_position_default": if (minVisible <= 0 && maxVisible >= 0) result = that.translate(0); else { invert = range.invert ^ (minVisible <= 0 && maxVisible <= 0); if (that._options.direction === "horizontal") result = invert ? endPoint : startPoint; else result = invert ? startPoint : endPoint } break; case"canvas_position_left": case"canvas_position_top": result = startPoint; break; case"canvas_position_center": case"canvas_position_middle": result = startPoint + canvasOptions.canvasLength / 2; break; case"canvas_position_right": case"canvas_position_bottom": result = endPoint; break; case"canvas_position_start": result = range.invert ? endPoint : startPoint; break; case"canvas_position_end": result = range.invert ? startPoint : endPoint; break } return result }, _calculateProjection: function(distance) { var canvasOptions = this._canvasOptions; return canvasOptions.invert ? canvasOptions.endPoint - distance : canvasOptions.startPoint + distance }, _calculateUnProjection: function(distance) { var canvasOptions = this._canvasOptions; return canvasOptions.invert ? canvasOptions.rangeMaxVisible.valueOf() - distance : canvasOptions.rangeMinVisible.valueOf() + distance } }) })(jQuery, DevExpress); /*! Module viz-core, file rectangle.js */ (function(DX, undefined) { var isFinite = window.isFinite; DX.viz.core.Rectangle = DX.Class.inherit({ ctor: function(options) { var that = this; options = options || {}; that.left = Number(options.left) || 0; that.right = Number(options.right) || 0; that.top = Number(options.top) || 0; that.bottom = Number(options.bottom) || 0 }, width: function() { return this.right - this.left }, height: function() { return this.bottom - this.top }, horizontalMiddle: function() { return (this.left + this.right) / 2 }, verticalMiddle: function() { return (this.top + this.bottom) / 2 }, raw: function() { var that = this; return { left: that.left, top: that.top, right: that.right, bottom: that.bottom } }, clone: function() { return new this.constructor(this.raw()) }, move: function(dx, dy) { var result = this.clone(); if (isFinite(dx) && isFinite(dy)) { result.left += Number(dx); result.right += Number(dx); result.top += Number(dy); result.bottom += Number(dy) } return result }, inflate: function(dx, dy) { var result = this.clone(); if (isFinite(dx) && isFinite(dy)) { result.left -= Number(dx); result.right += Number(dx); result.top -= Number(dy); result.bottom += Number(dy) } return result }, scale: function(factor) { var that = this; if (factor > 0) return that.inflate(that.width() * (factor - 1) / 2, that.height() * (factor - 1) / 2); return that.clone() } }) })(DevExpress); /*! Module viz-core, file themes.js */ (function($, DX, undefined) { var viz = DX.viz, core = viz.core; var currentThemeId = 0; var findThemeId = function(themeName) { var themeId, themes = viz.themes; for (themeId = 0; themeId < themes.length; themeId++) if (themes[themeId].name === themeName) return themeId; return -1 }; core.findTheme = function(themeName) { var themeId = findThemeId(themeName), themes = viz.themes; if (themeId < 0) themeId = currentThemeId; return themes[themeId] }; core.currentTheme = function(themeName, colorScheme, version) { var themeId = -1, themes = viz.themes; if (themeName === undefined) return themes[currentThemeId].name; else { if (version && colorScheme) themeId = findThemeId(themeName + ':' + version + '-' + colorScheme); if (themeId < 0 && version) themeId = findThemeId(themeName + ':' + version); if (colorScheme && themeId < 0) themeId = findThemeId(themeName + '-' + colorScheme); if (themeId < 0) themeId = findThemeId(themeName); currentThemeId = themeId >= 0 ? themeId : 0 } }; core.registerTheme = function(theme, basedOnThemeName) { var baseTheme, extendedTheme, themes = viz.themes; if (!theme || !theme.name || !core.findTheme(theme.name)) return; baseTheme = core.findTheme(basedOnThemeName); if (baseTheme) { extendedTheme = $.extend(true, {}, baseTheme, theme); themes.push(extendedTheme) } else themes.push(theme) } })(jQuery, DevExpress); /*! Module viz-core, file palette.js */ (function(DX, $, undefined) { var _String = window.String, _Color = DX.Color, _isArray = DX.utils.isArray, _isString = DX.utils.isString, _extend = $.extend; var palettes = { 'default': { simpleSet: ['#5f8b95', '#ba4d51', '#af8a53', '#955f71', '#859666', '#7e688c'], indicatingSet: ['#a3b97c', '#e1b676', '#ec7f83'], gradientSet: ['#5f8b95', '#ba4d51'] }, 'harmony light': { simpleSet: ['#fcb65e', '#679ec5', '#ad79ce', '#7abd5c', '#e18e92', '#b6d623', '#b7abea', '#85dbd5'], indicatingSet: ['#b6d623', '#fcb65e', '#e18e92'], gradientSet: ['#7abd5c', '#fcb65e'] }, 'soft pastel': { simpleSet: ['#60a69f', '#78b6d9', '#6682bb', '#a37182', '#eeba69', '#90ba58', '#456c68', '#7565a4'], indicatingSet: ['#90ba58', '#eeba69', '#a37182'], gradientSet: ['#78b6d9', '#eeba69'] }, pastel: { simpleSet: ['#bb7862', '#70b3a1', '#bb626a', '#057d85', '#ab394b', '#dac599', '#153459', '#b1d2c6'], indicatingSet: ['#70b3a1', '#dac599', '#bb626a'], gradientSet: ['#bb7862', '#70b3a1'] }, bright: { simpleSet: ['#70c92f', '#f8ca00', '#bd1550', '#e97f02', '#9d419c', '#7e4452', '#9ab57e', '#36a3a6'], indicatingSet: ['#70c92f', '#f8ca00', '#bd1550'], gradientSet: ['#e97f02', '#f8ca00'] }, soft: { simpleSet: ['#cbc87b', '#9ab57e', '#e55253', '#7e4452', '#e8c267', '#565077', '#6babac', '#ad6082'], indicatingSet: ['#9ab57e', '#e8c267', '#e55253'], gradientSet: ['#9ab57e', '#e8c267'] }, ocean: { simpleSet: ['#75c099', '#acc371', '#378a8a', '#5fa26a', '#064970', '#38c5d2', '#00a7c6', '#6f84bb'], indicatingSet: ['#c8e394', '#7bc59d', '#397c8b'], gradientSet: ['#acc371', '#38c5d2'] }, vintage: { simpleSet: ['#dea484', '#efc59c', '#cb715e', '#eb9692', '#a85c4c', '#f2c0b5', '#c96374', '#dd956c'], indicatingSet: ['#ffe5c6', '#f4bb9d', '#e57660'], gradientSet: ['#efc59c', '#cb715e'] }, violet: { simpleSet: ['#d1a1d1', '#eeacc5', '#7b5685', '#7e7cad', '#a13d73', '#5b41ab', '#e287e2', '#689cc1'], indicatingSet: ['#d8e2f6', '#d0b2da', '#d56a8a'], gradientSet: ['#eeacc5', '#7b5685'] } }; var currentPaletteName = 'default'; function currentPalette(name) { if (name === undefined) return currentPaletteName; else { name = String(name).toLowerCase(); currentPaletteName = name in palettes ? name : 'default' } } function getPalette(palette, parameters) { var result; if (_isArray(palette)) result = palette; else { parameters = parameters || {}; var type = parameters.type || 'simpleSet'; if (_isString(palette)) { var name = palette.toLowerCase(), baseContainer = palettes[name], themedContainer = parameters.theme && palettes[name + '_' + _String(parameters.theme).toLowerCase()]; result = themedContainer && themedContainer[type] || baseContainer && baseContainer[type] } if (!result) result = palettes[currentPaletteName][type] } return result ? result.slice(0) : null } function registerPalette(name, palette, theme) { var item = {}; if (_isArray(palette)) item.simpleSet = palette.slice(0); else if (palette) { item.simpleSet = _isArray(palette.simpleSet) ? palette.simpleSet.slice(0) : undefined; item.indicatingSet = _isArray(palette.indicatingSet) ? palette.indicatingSet.slice(0) : undefined; item.gradientSet = _isArray(palette.gradientSet) ? palette.gradientSet.slice(0) : undefined } if (item.simpleSet || item.indicatingSet || item.gradientSet) { var paletteName = _String(name).toLowerCase(); if (theme) paletteName = paletteName + '_' + _String(theme).toLowerCase(); _extend(palettes[paletteName] = palettes[paletteName] || {}, item) } } function RingBuf(buf) { var ind = 0; this.next = function() { var res = buf[ind++]; if (ind == buf.length) this.reset(); return res }; this.reset = function() { ind = 0 } } function Palette(palette, parameters) { parameters = parameters || {}; this._originalPalette = getPalette(palette, parameters); var stepHighlight = parameters ? parameters.stepHighlight || 0 : 0; this._paletteSteps = new RingBuf([0, stepHighlight, -stepHighlight]); this._resetPalette() } _extend(Palette.prototype, { dispose: function() { this._originalPalette = this._palette = this._paletteSteps = null; return this }, getNextColor: function() { var that = this; if (that._currentColor >= that._palette.length) that._resetPalette(); return that._palette[that._currentColor++] }, _resetPalette: function() { var that = this; that._currentColor = 0; var step = that._paletteSteps.next(), originalPalette = that._originalPalette; if (step) { var palette = that._palette = [], i = 0, ii = originalPalette.length; for (; i < ii; ++i) palette[i] = getNewColor(originalPalette[i], step) } else that._palette = originalPalette.slice(0) }, reset: function() { this._paletteSteps.reset(); this._resetPalette(); return this } }); function getNewColor(currentColor, step) { var newColor = new _Color(currentColor).alter(step), lightness = getLightness(newColor); if (lightness > 200 || lightness < 55) newColor = new _Color(currentColor).alter(-step / 2); return newColor.toHex() } function getLightness(color) { return color.r * 0.3 + color.g * 0.59 + color.b * 0.11 } function GradientPalette(source, size) { var palette = getPalette(source, {type: 'gradientSet'}); palette = size > 0 ? createGradientColors(palette[0], palette[1], size) : []; this.getColor = function(index) { return palette[index] || null }; this._DEBUG_source = source; this._DEBUG_size = size } function createGradientColors(start, end, count) { var startColor = new _Color(start), endColor = new _Color(end); if (count === 1) return [startColor.blend(endColor, 0.5).toHex()]; else { var list = [], step = 1 / (count - 1), i, ii = count; list.push(0); for (i = 1; i < ii - 1; ++i) list.push(step * i); list.push(1); for (i = 0; i < ii; ++i) list[i] = startColor.blend(endColor, list[i]).toHex(); return list } } _extend(DX.viz.core, { registerPalette: registerPalette, getPalette: getPalette, Palette: Palette, GradientPalette: GradientPalette, currentPalette: currentPalette }); DX.viz.core._DEBUG_palettes = palettes })(DevExpress, jQuery); /*! Module viz-core, file baseThemeManager.js */ (function(DX, $, undefined) { var _isString = DX.utils.isString, _findTheme = DX.viz.core.findTheme, _extend = $.extend, _each = $.each; DX.viz.core.BaseThemeManager = DX.Class.inherit({ dispose: function() { this._theme = this._font = null; return this }, setTheme: function(theme) { theme = theme || {}; var that = this, themeObj = _findTheme(_isString(theme) ? theme : theme.name); that._themeName = themeObj.name; that._font = _extend({}, themeObj.font, theme.font); that._themeSection && _each(that._themeSection.split('.'), function(_, path) { themeObj = _extend(true, {}, themeObj[path], that._IE8 ? themeObj[path + 'IE8'] : {}) }); that._theme = _extend(true, {}, themeObj, _isString(theme) ? {} : theme); that._initializeTheme(); return that }, theme: function() { return this._theme }, themeName: function() { return this._themeName }, _initializeTheme: function(){}, _initializeFont: function(font) { _extend(font, this._font, _extend({}, font)) } }) })(DevExpress, jQuery); /*! Module viz-core, file textCloud.js */ (function(DX, undefined) { var min = Math.min; DX.viz.core.TextCloud = DX.Class.inherit(function() { var DEFAULT_OPTIONS = { horMargin: 8, verMargin: 4, tailLength: 10 }; var COEFFICIENTS_MAP = {}; COEFFICIENTS_MAP['right-bottom'] = COEFFICIENTS_MAP['rb'] = [0, -1, -1, 0, 0, 1, 1, 0]; COEFFICIENTS_MAP['bottom-right'] = COEFFICIENTS_MAP['br'] = [-1, 0, 0, -1, 1, 0, 0, 1]; COEFFICIENTS_MAP['left-bottom'] = COEFFICIENTS_MAP['lb'] = [0, -1, 1, 0, 0, 1, -1, 0]; COEFFICIENTS_MAP['bottom-left'] = COEFFICIENTS_MAP['bl'] = [1, 0, 0, -1, -1, 0, 0, 1]; COEFFICIENTS_MAP['left-top'] = COEFFICIENTS_MAP['lt'] = [0, 1, 1, 0, 0, -1, -1, 0]; COEFFICIENTS_MAP['top-left'] = COEFFICIENTS_MAP['tl'] = [1, 0, 0, 1, -1, 0, 0, -1]; COEFFICIENTS_MAP['right-top'] = COEFFICIENTS_MAP['rt'] = [0, 1, -1, 0, 0, -1, 1, 0]; COEFFICIENTS_MAP['top-right'] = COEFFICIENTS_MAP['tr'] = [-1, 0, 0, 1, 1, 0, 0, -1]; return { setup: function(options) { var that = this, ops = $.extend({}, DEFAULT_OPTIONS, options), x = ops.x, y = ops.y, type = COEFFICIENTS_MAP[ops.type], cloudWidth = ops.textWidth + 2 * ops.horMargin, cloudHeight = ops.textHeight + 2 * ops.verMargin, tailWidth = ops.tailLength, tailHeight = tailWidth, cx = x, cy = y; if (type[0] & 1) tailHeight = min(tailHeight, cloudHeight / 3); else tailWidth = min(tailWidth, cloudWidth / 3); that._points = [x, y, x += type[0] * (cloudWidth + tailWidth), y += type[1] * (cloudHeight + tailHeight), x += type[2] * cloudWidth, y += type[3] * cloudHeight, x += type[4] * cloudWidth, y += type[5] * cloudHeight, x += type[6] * (cloudWidth - tailWidth), y += type[7] * (cloudHeight - tailHeight)]; that._cx = cx + type[0] * tailWidth + (type[0] + type[2]) * cloudWidth / 2; that._cy = cy + type[1] * tailHeight + (type[1] + type[3]) * cloudHeight / 2; that._cloudWidth = cloudWidth; that._cloudHeight = cloudHeight; that._tailLength = ops.tailLength; return that }, points: function() { return this._points.slice(0) }, cx: function() { return this._cx }, cy: function() { return this._cy }, width: function() { return this._cloudWidth }, height: function() { return this._cloudHeight }, tailLength: function() { return this._tailLength } } }()) })(DevExpress); /*! Module viz-core, file parseUtils.js */ (function($, DX) { var viz = DX.viz, core = viz.core, Class = DX.Class, isDefined = DX.utils.isDefined; var parseUtils = Class.inherit({ ctor: function(options) { options = options || {}; this._incidentOccured = $.isFunction(options.incidentOccured) ? options.incidentOccured : $.noop }, correctValueType: function(type) { return type === 'numeric' || type === 'datetime' || type === 'string' ? type : '' }, _parsers: { string: function(val) { return isDefined(val) ? '' + val : val }, numeric: function(val) { if (!isDefined(val)) return val; var parsedVal = Number(val); if (isNaN(parsedVal)) parsedVal = undefined; return parsedVal }, datetime: function(val) { if (!isDefined(val)) return val; var parsedVal, numVal = Number(val); if (!isNaN(numVal)) parsedVal = new Date(numVal); else parsedVal = new Date(val); if (isNaN(Number(parsedVal))) parsedVal = undefined; return parsedVal } }, getParser: function(valueType, entity) { var that = this, parser, message = 'valueType is unknown.'; if (entity) message = 'The type specified as the "valueType" field of the ' + entity + ' configuration object is unknown.'; valueType = that.correctValueType(valueType); parser = that._parsers[valueType]; if (!parser) this._incidentOccured.call(null, message); return parser || $.noop } }); core.ParseUtils = parseUtils })(jQuery, DevExpress); /*! Module viz-core, file utils.js */ (function($, DX) { var core = DX.viz.core, math = Math; core.utils = {decreaseGaps: function(object, keys, decrease) { var arrayGaps, eachDecrease, middleValue; do { arrayGaps = $.map(keys, function(key) { return object[key] ? object[key] : null }); middleValue = math.ceil(decrease / arrayGaps.length); arrayGaps.push(middleValue); eachDecrease = math.min.apply(null, arrayGaps); $.each(keys, function(_, key) { if (object[key]) { object[key] -= eachDecrease; decrease -= eachDecrease } }) } while (decrease > 0 && arrayGaps.length > 1); return decrease }} })(jQuery, DevExpress); /*! Module viz-core, file loadIndicator.js */ (function($, DX) { var viz = DX.viz, core = viz.core, ANIMATION_SETTINGS = { easing: 'linear', duration: 150 }, INVISIBLE_POINT = { x: -10000, y: -10000 }; var applySettings = function(element, settings, animate, complete) { var prevAnimation = element.animation; if (prevAnimation) { prevAnimation.options.complete = null; prevAnimation.stop() } if (animate) element.animate(settings, {complete: complete}); else { element.applySettings(settings); complete && complete() } }; core.LoadIndicator = DX.Class.inherit({ ctor: function(options, widgetContainer) { var that = this; that._$widgetContainer = $(widgetContainer); that._$container = $('
', {css: { position: 'relative', height: 0, padding: 0, margin: 0, border: 0 }}).appendTo(that._$widgetContainer); that._updateContainer(); that.applyOptions(options); that._endLoadingCompleteHandler = function() { that._endLoad = false; that._externalComplete && that._externalComplete(); that._externalComplete = null; that._onCompleteAction && that[that._onCompleteAction](); that._onCompleteAction = null }; that._$container.hide() }, _updateRenderer: function(width, height, top) { if (this._renderer) this._renderer.recreateCanvas(width, height); else if (this._$container.get(0)) { this._renderer = new viz.renderers.Renderer({ width: width, height: height, animation: ANIMATION_SETTINGS }); this._renderer.draw(this._$container[0]) } this._renderer && this._renderer.getRoot().applySettings({style: { position: 'absolute', top: top, left: 0 }}); return this._renderer }, applyOptions: function(options, width, height) { var pane = this._pane; if (pane && options) { pane.rect.applySettings({fill: options.backgroundColor}); pane.text.applySettings({ font: options.font, text: options.text }) } if (this.isShown && (width || height)) this._updateContainer(width, height) }, _draw: function() { var pane, renderer = this._renderer; if (renderer) { pane = this._pane = {}; pane.rect = renderer.createRect(0, 0, 0, 0, 0, {opacity: 0}).append(); pane.text = renderer.createText('', 0, 0, { align: 'center', translateX: INVISIBLE_POINT.x, translateY: INVISIBLE_POINT.y }).append() } }, _updateContainer: function(width, height) { var that = this, $widgetContainer = that._$widgetContainer, canvasTop; width = width || $widgetContainer.width(); height = height || $widgetContainer.height(); if ($widgetContainer.get(0)) canvasTop = $widgetContainer.offset().top - that._$container.offset().top; else canvasTop = -height; that._updateRenderer(width, height, canvasTop); if (!that._pane) that._draw(); else { that._pane.rect.applySettings({ width: width, height: height }); that._pane.text.move(width / 2, height / 2) } }, dispose: function() { this._$widgetContainer = null; this._$container.remove().detach(); this._$container = null; this._renderer.dispose(); this._renderer = null; this._pane = null }, toForeground: function() { this._$container.appendTo(this._$widgetContainer) }, show: function(width, height) { if (this._endLoad) { this._onCompleteAction = 'show'; return } this._$container.show(); this._updateContainer(width, height); applySettings(this._pane.rect, {opacity: 0.85}, true); this.isShown = true }, endLoading: function(complete, disableAnimation) { this._externalComplete = complete; if (this._endLoad) return; if (this.isShown) { this._endLoad = true; applySettings(this._pane.rect, {opacity: 1}, !disableAnimation, this._endLoadingCompleteHandler) } else complete && complete() }, hide: function() { var that = this; if (this._endLoad) { this._onCompleteAction = 'hide'; return } if (this.isShown) { this._pane.text.move(INVISIBLE_POINT.x, INVISIBLE_POINT.y); applySettings(that._pane.rect, {opacity: 0}, true, function() { that._$container.hide() }); this.isShown = false } } }) })(jQuery, DevExpress); /*! Module viz-core, file tooltip.js */ (function($, DX, undefined) { var ARROW_WIDTH = 20, MAX_SHADOW_SIZE = 10, formatHelper = DX.formatHelper, X_INTERVAL = 15, _max = Math.max, _round = Math.round, _isFunction = DX.utils.isFunction, _isDefined = DX.utils.isDefined, _extend = $.extend, FORMAT_PRECISION = { argument: ['argumentFormat', 'argumentPrecision'], percent: ['percent', 'percentPrecision'], value: ['format', 'precision'] }, VISIBLE = {visibility: 'visible'}, HIDDEN = {visibility: 'hidden'}, LEFT = 'left', RIGHT = 'right'; DX.viz.core.Tooltip = DX.Class.inherit({ ctor: function(options, group, renderer) { this._state = {}; this._options = {}; this._renderer = renderer; this._group = group; this._cloud = renderer.createArea(); this._textGroup = renderer.createGroup(); if (!$.isEmptyObject(options)) this.update(options); this._createTextContent() }, dispose: function() { this._shadow.dispose(); this._shadow = null; this._cloud = null; this._text = null; this._group = null; this._options = null; this._renderer = null; this._tooltipTextArray = null; this._textGroup = null; return this }, update: function(options) { options = options || {}; var that = this, group = that._group, shadowOptions = options.shadow || {}, shadow = that._shadow = that._shadow || that._renderer.createFilter('shadow').applySettings({ width: '200%', height: '200%', color: shadowOptions.color, opacity: shadowOptions.opacity, dx: shadowOptions.offsetX, dy: shadowOptions.offsetY, blur: shadowOptions.blur, x: '-50%', y: '-50%' }), borderSettings = options.border, shapeSettings = _extend({ opacity: options.opacity, filter: shadow.append().ref }, borderSettings && borderSettings.visible ? { strokeWidth: borderSettings.width, stroke: borderSettings.color, strokeOpacity: borderSettings.opacity, dashStyle: borderSettings.dashStyle } : { strokeWidth: null, stroke: null }), textSettings = _extend({}, { align: 'center', font: options.font }, options.text); that._options = options; that.setSize(options.canvasWidth, options.canvasHeight); that._customizeTooltip = _isFunction(options.customizeTooltip) ? options.customizeTooltip : null; if (!that._customizeTooltip && _isFunction(options.customizeText)) that._customizeTooltip = function() { return {text: options.customizeText.apply(this, arguments)} }; that._cloud.applySettings(shapeSettings).append(group); that._text && options.font && that._text.applySettings({font: {size: options.font.size}}); that._textGroup.applySettings(textSettings).append(group); that.hide(); return that }, formatValue: function(value, specialFormat) { var formatObj = FORMAT_PRECISION[specialFormat || 'value'], format = formatObj[0] in this._options ? this._options[formatObj[0]] : specialFormat; return formatHelper.format(value, format, this._options[formatObj[1]] || 0) }, prepare: function(formatObject, params, defaultTextValueField) { this._state = this._state || {}; defaultTextValueField = defaultTextValueField || 'valueText'; var defaultText = formatObject[defaultTextValueField] || ''; _extend(this._state, params); if (this._customizeTooltip) { var customize = this._customizeTooltip.call(formatObject, formatObject); customize = $.isPlainObject(customize) ? customize : {}; if ('text' in customize) this._state.text = _isDefined(customize.text) ? String(customize.text) : ''; else { if ($.isArray(defaultText)) { this._options._justify = true; this._createTextContent(); defaultText = defaultText.join('
') } this._state.text = defaultText } this._state.color = customize.color || this._options.color } else { this._state.text = defaultText; this._state.color = this._options.color } if (this._options._justify) this._state.text = this._state.text.split('
'); if (this._state.visibility == VISIBLE && !!this._state.text) this.show(); return !!this._state.text }, enabled: function() { return !!this._options.enabled }, formatColorTooltip: function(that) { return that._customizeTooltip && that._customizeTooltip.call(this, this) }, _getData: function() { var that = this, x = that._state.x, y = that._state.y, xt = x, yt = y, align = 'center', points = [], bbox = that._state.textBBox, options = that._options, paddingLeftRight = options.paddingLeftRight, paddingTopBottom = options.paddingTopBottom, arrowLength = options.arrowLength > 0 ? options.arrowLength : 0, horPosition = options.cloudHorizontalPosition, verPosition = options.cloudVerticalPosition, isHorPositionDefined = horPosition !== undefined && horPosition !== null, isVerPositionDefined = verPosition !== undefined && verPosition !== null, cloudWidth = bbox.width + paddingLeftRight * 2, cloudHeight = bbox.height + paddingTopBottom * 2, updatedText; updatedText = that._checkWidthText(cloudWidth, cloudHeight); if (updatedText) { that._state.textBBox = bbox = updatedText.bbox; cloudWidth = updatedText.cloudWidth; cloudHeight = updatedText.cloudHeight; paddingLeftRight = updatedText.paddingLeftRight; paddingTopBottom = updatedText.paddingTopBottom } if (isHorPositionDefined ? horPosition === RIGHT : cloudWidth / 2 > x) { points = that._setArrowLeft(cloudWidth, cloudHeight, arrowLength, x, y); align = LEFT; xt += paddingLeftRight } else if (isHorPositionDefined ? horPosition === LEFT : x + cloudWidth / 2 > that._canvasWidth) { points = that._setArrowRight(cloudWidth, cloudHeight, arrowLength, x, y); align = RIGHT; xt -= paddingLeftRight } else points = that._setArrowCenter(cloudWidth, cloudHeight, arrowLength, x, y); if (isVerPositionDefined ? verPosition === 'top' : cloudHeight + arrowLength < y) { yt -= arrowLength + cloudHeight / 2 - bbox.height / 2 + that._state.offset; that.tooltipInverted = false } else { yt += arrowLength + cloudHeight / 2 + bbox.height / 2 + that._state.offset; that.tooltipInverted = true } yt = that._correctYTextContent(yt); return { points: points, text: { x: xt, y: yt, align: align } } }, _updateTextContent: function() { if (this._options._justify) { this._textGroup.clear(); this._calculateTextContent(); this._locateTextContent(0, 0, 'center') } else this._text.updateText(this._state.text); this._state.textBBox = this._textGroup.getBBox() }, _correctYTextContent: function(y) { var bbox; if (this._options._justify) { this._locateTextContent(0, y, 'center'); bbox = this._textGroup.getBBox() } else { this._text.applySettings({y: y}); bbox = this._text.getBBox() } return y - (bbox.y + bbox.height - y) }, _adjustTextContent: function(data) { if (this._options._justify) this._locateTextContent(data.text.x, data.text.y, data.text.align); else this._text.applySettings({ x: data.text.x, y: data.text.y, align: data.text.align }) }, _updateTooltip: function() { var that = this, box, data, scale; data = that._getData(); that._cloud.applySettings({ points: data.points, fill: that._state.color, 'class': that._state.className }); that._adjustTextContent(data); box = that._group.getBBox(); if (box.y + box.height > that._canvasHeight) { scale = (that._canvasHeight - box.y) / box.height; that._group.applySettings({ scale: scale, translateX: that._state.x * (1 - scale), translateY: that._state.y * (1 - scale) }) } else that._group.applySettings({ scale: 1, translateX: 0, translateY: 0 }) }, _createTextContent: function() { var that = this, options = that._options, fontSize; that._textGroup.clear(); that._text = null; if (!options._justify) { fontSize = options.font && options.font.size; that._text = that._renderer.createText(undefined, 0, 0, {font: {size: fontSize}}).append(that._textGroup) } }, _getTextContentParams: function() { var that = this, i, text, textBBox, textArray = that._state.text, textArrayLength = textArray.length, textParams = { width: [], height: [] }; that._tooltipTextArray = []; for (i = 0; i < textArrayLength; i++) { text = that._renderer.createText(textArray[i], 0, 0, {}).append(this._textGroup); that._tooltipTextArray.push(text); textBBox = text.getBBox(); textParams.width.push(textBBox.width) } that._lineHeight = -2 * textBBox.y - textBBox.height; return textParams }, _locateTextContent: function(x, y, alignment) { var that = this, tooltipTextArray = that._tooltipTextArray, textWidth = that._textContentWidth, lineSpacing = that._options.lineSpacing, yDelta = (lineSpacing > 0 ? lineSpacing : 0) + that._lineHeight, leftXCoord, rightXCoord, i, rtl = that._options._rtl; if (alignment === LEFT) leftXCoord = x; else if (alignment === RIGHT) leftXCoord = x - textWidth; else leftXCoord = _round(x - textWidth / 2); rightXCoord = leftXCoord + textWidth; for (i = tooltipTextArray.length - 1; i >= 0; i -= 2) { tooltipTextArray[i].applySettings({ x: !rtl ? rightXCoord : leftXCoord, y: y, align: !rtl ? RIGHT : LEFT }); if (tooltipTextArray[i - 1]) tooltipTextArray[i - 1].applySettings({ x: !rtl ? leftXCoord : rightXCoord, y: y, align: !rtl ? LEFT : RIGHT }); y -= yDelta } }, _calculateTextContent: function() { var that = this, textArray = that._state.text, textArrayLength = textArray.length, textParams, width, stringWidthArray = [], i; textParams = that._getTextContentParams(); for (i = 0; i < textArrayLength; i += 2) { if (textParams.width[i + 1]) width = textParams.width[i] + X_INTERVAL + textParams.width[i + 1]; else width = textParams.width[i]; stringWidthArray.push(width) } that._textContentWidth = _max.apply(null, stringWidthArray) }, setSize: function(width, height) { this._canvasWidth = _isDefined(width) ? width : this._canvasWidth; this._canvasHeight = _isDefined(height) ? height : this._canvasHeight; return this }, getBBox: function() { var that = this, options = that._options, paddingLeftRight = options.paddingLeftRight || 0, paddingTopBottom = options.paddingTopBottom || 0, borderWidth = options.border.visible && options.border.width || 0, tooltipBBox = that._textGroup.getBBox(); return tooltipBBox.isEmpty ? tooltipBBox : { x: tooltipBBox.x - paddingLeftRight - borderWidth / 2 - MAX_SHADOW_SIZE, y: tooltipBBox.y - paddingTopBottom - borderWidth / 2 - MAX_SHADOW_SIZE, height: tooltipBBox.height + 2 * paddingTopBottom + borderWidth + MAX_SHADOW_SIZE * 2, width: tooltipBBox.width + 2 * paddingLeftRight + borderWidth + MAX_SHADOW_SIZE * 2, isEmpty: false } }, show: function() { this._state.visibility = VISIBLE; this._updateTextContent(); this.move(this._state.x, this._state.y, this._state.offset); this._cloud.applySettings(VISIBLE); this._textGroup.applySettings(VISIBLE); return this }, hide: function() { this._state.visibility = HIDDEN; this._cloud.applySettings(HIDDEN); this._textGroup.applySettings(HIDDEN); return this }, move: function(x, y, offset) { this._state.x = _isDefined(x) ? x : this._state.x || 0; this._state.y = _isDefined(y) ? y : this._state.y || 0; this._state.offset = _isDefined(offset) ? offset : this._state.offset || 0; this._updateTooltip(); return this }, _setArrowCenter: function(cloudWidth, cloudHeight, arrowLength, x, y) { var that = this, position = that._options.cloudVerticalPosition, isPosDefined = position !== undefined && position !== null, verticalInvert = !(isPosDefined ? position === 'top' : cloudHeight + arrowLength < y), x0 = x, y0 = verticalInvert ? y + that._state.offset : y - that._state.offset, x1 = x0 + ARROW_WIDTH / 2, y1 = verticalInvert ? y0 + arrowLength : y0 - arrowLength, x2 = x1 + cloudWidth / 2 - ARROW_WIDTH / 2, y2 = y1, x3 = x2, y3 = verticalInvert ? y2 + cloudHeight : y2 - cloudHeight, x4 = x3 - cloudWidth, y4 = y3, x5 = x4, y5 = verticalInvert ? y4 - cloudHeight : y4 + cloudHeight, x6 = x5 + cloudWidth / 2 - ARROW_WIDTH / 2, y6 = y5; return [x0, y0, x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, x6, y6] }, _setArrowLeft: function(cloudWidth, cloudHeight, arrowLength, x, y) { var that = this, position = that._options.cloudVerticalPosition, isPosDefined = position !== undefined && position !== null, verticalInvert = !(isPosDefined ? position === 'top' : cloudHeight + arrowLength < y), x0 = x, y0 = verticalInvert ? y + that._state.offset : y - that._state.offset, x1 = x0 + ARROW_WIDTH, y1 = verticalInvert ? y0 + arrowLength : y0 - arrowLength, x2 = x1 + cloudWidth - ARROW_WIDTH, y2 = y1, x3 = x2, y3 = verticalInvert ? y2 + cloudHeight : y2 - cloudHeight, x4 = x3 - cloudWidth, y4 = y3, x5 = x4, y5 = verticalInvert ? y4 - cloudHeight - arrowLength : y4 + cloudHeight + arrowLength; return [x0, y0, x1, y1, x2, y2, x3, y3, x4, y4, x5, y5] }, _setArrowRight: function(cloudWidth, cloudHeight, arrowLength, x, y) { var that = this, position = that._options.cloudVerticalPosition, isPosDefined = position !== undefined && position !== null, verticalInvert = !(isPosDefined ? position === 'top' : cloudHeight + arrowLength < y), x0 = x, y0 = verticalInvert ? y + that._state.offset : y - that._state.offset, x1 = x0, y1 = verticalInvert ? y0 + arrowLength + cloudHeight : y0 - arrowLength - cloudHeight, x2 = x1 - cloudWidth, y2 = y1, x3 = x2, y3 = verticalInvert ? y2 - cloudHeight : y2 + cloudHeight, x4 = x3 + cloudWidth - ARROW_WIDTH, y4 = y3, x5 = x4 + ARROW_WIDTH, y5 = verticalInvert ? y4 - arrowLength : y4 + arrowLength; return [x0, y0, x1, y1, x2, y2, x3, y3, x4, y4, x5, y5] }, _checkWidthText: function(cloudWidth, cloudHeight) { if (this._options._justify) return; var x = this._state.x, text = this._state.text, index, paddingLeftRight = this._options.paddingLeftRight, paddingTopBottom = this._options.paddingTopBottom, textLength, maxTooltipWidth, remainLength, newIndex, bbox = this._state.textBBox; if (cloudWidth < x || x + cloudWidth < this._canvasWidth || cloudWidth / 2 < x && x + cloudWidth / 2 < this._canvasWidth) return false; if (text.indexOf("
") === -1 && text.indexOf(" ") !== -1) { maxTooltipWidth = _max(x, this._canvasWidth - x, 2 * Math.min(x, this._canvasWidth - x)); textLength = text.length * maxTooltipWidth / bbox.width; index = text.substr(0, ~~textLength).lastIndexOf(" "); if (index === -1) index = text.substr(0).indexOf(" "); remainLength = text.substr(index + 1).length; this._state.text = text.substr(0, index) + "
"; while (textLength <= remainLength) { newIndex = text.substr(index + 1, ~~textLength).lastIndexOf(" "); if (newIndex === -1) newIndex = text.substr(index + 1).indexOf(" "); if (newIndex !== -1) { this._state.text += text.substr(index + 1, newIndex) + "
"; remainLength = text.substr(index + 1 + newIndex).length; index += newIndex + 1 } else break } this._state.text += text.substr(index + 1); this._text.updateText(this._state.text); bbox = this._text.getBBox(); cloudWidth = bbox.width + paddingLeftRight * 2; cloudHeight = bbox.height + paddingTopBottom * 2 } if (cloudWidth > x && x + cloudWidth > this._canvasWidth && (cloudWidth / 2 > x || x + cloudWidth / 2 > this._canvasWidth)) { paddingLeftRight = 5; paddingTopBottom = 5; cloudWidth = bbox.width + 2 * paddingLeftRight; cloudHeight = bbox.height + 2 * paddingTopBottom } return { bbox: bbox, cloudWidth: cloudWidth, cloudHeight: cloudHeight, paddingTopBottom: paddingTopBottom, paddingLeftRight: paddingLeftRight } } }) })(jQuery, DevExpress); /*! Module viz-core, file legend.js */ (function(DX, $, undefined) { var DEFAULT_MARGIN = 10, _math = Math, _round = _math.round, _ceil = _math.ceil, _floor = _math.floor, CENTER = 'center', RIGHT = 'right', LEFT = 'left', TOP = 'top', BOTTOM = 'bottom', HORIZONTAL = 'horizontal', VERTICAL = 'vertical', INSIDE = 'inside', OUTSIDE = 'outside', NONE = 'none', decreaseGaps = DevExpress.viz.core.utils.decreaseGaps, DEFAULT_MARKER_HATCHING_WIDTH = 2, DEFAULT_MARKER_HATCHING_STEP = 5; function getPatternId(renderer, states, action, color) { if (!states) return; var direction = states[action].hatching.direction, hatching, colorFromAction = states[action].fill; color = colorFromAction === NONE ? color : colorFromAction; direction = !direction || direction === NONE ? RIGHT : direction; hatching = $.extend({}, states[action].hatching, { direction: direction, step: DEFAULT_MARKER_HATCHING_STEP, width: DEFAULT_MARKER_HATCHING_WIDTH }); return renderer.createPattern(color, hatching).append().id } function getMaxBBox(groups) { var maxWidth = 0, maxHeight = 0, bbox; $.each(groups, function(_, group) { bbox = group.getBBox(); if (bbox.width > maxWidth) maxWidth = bbox.width; if (bbox.height > maxHeight) maxHeight = bbox.height }); return { width: maxWidth, height: maxHeight } } DX.viz.core.Legend = DX.Class.inherit({ ctor: function(data, options, renderer, group) { var that = this; that._renderer = renderer; that._legendGroup = group; that._markersPatternsIds = []; that._data = data; that._init(options) }, _init: function(options) { if (!options) return; var debug = DX.utils.debug; debug.assertParam(options.visible, 'Visibility was not passed'); debug.assertParam(options.markerSize, 'markerSize was not passed'); debug.assertParam(options.font.color, 'fontColor was not passed'); debug.assertParam(options.font.family, 'fontFamily was not passed'); debug.assertParam(options.font.size, 'fontSize was not passed'); debug.assertParam(options.paddingLeftRight, 'paddingLeftRight was not passed'); debug.assertParam(options.paddingTopBottom, 'paddingTopBottom was not passed'); debug.assertParam(options.columnItemSpacing, 'columnItemSpacing was not passed'); debug.assertParam(options.rowItemSpacing, 'rowItemSpacing was not passed'); debug.assertParam(options.equalColumnWidth, 'equalColumnWidth was not passed'); var that = this, i; that._parseMargins(options); that._parseAlignments(options); options.orientation = (options.orientation || '').toLowerCase(); if (options.orientation !== VERTICAL && options.orientation !== HORIZONTAL) { if (options.horizontalAlignment === CENTER) options.orientation = HORIZONTAL; if (options.horizontalAlignment === RIGHT || options.horizontalAlignment === LEFT) options.orientation = VERTICAL } if (!options.itemTextPosition) options.itemTextPosition = options.orientation === HORIZONTAL ? BOTTOM : RIGHT; else options.itemTextPosition = options.itemTextPosition; options.position = (options.position || '').toLowerCase(); if (options.position !== OUTSIDE && options.position !== INSIDE) options.position = OUTSIDE; options.hoverMode = (options.hoverMode || '').toLowerCase(); options.customizeText = $.isFunction(options.customizeText) ? options.customizeText : function() { return this.seriesName }; that._options = options; !that._trackerGroup && (that._trackerGroup = that._renderer.createGroup({ 'class': 'dxc-legend-trackers', stroke: NONE, fill: 'grey', opacity: 0.0001 })); that.__initialized = true }, _parseMargins: function(options) { if (options.margin >= 0) { options.margin = Number(options.margin); options.margin = { top: options.margin, bottom: options.margin, left: options.margin, right: options.margin } } else options.margin = { top: options.margin.top >= 0 ? Number(options.margin.top) : DEFAULT_MARGIN, bottom: options.margin.bottom >= 0 ? Number(options.margin.bottom) : DEFAULT_MARGIN, left: options.margin.left >= 0 ? Number(options.margin.left) : DEFAULT_MARGIN, right: options.margin.right >= 0 ? Number(options.margin.right) : DEFAULT_MARGIN } }, _parseAlignments: function(options) { options.horizontalAlignment = (options.horizontalAlignment || '').toLowerCase(); if (options.horizontalAlignment !== CENTER && options.horizontalAlignment !== RIGHT && options.horizontalAlignment !== LEFT) options.horizontalAlignment = RIGHT; options.verticalAlignment = (options.verticalAlignment || '').toLowerCase(); if (options.verticalAlignment !== TOP && options.verticalAlignment !== BOTTOM) { if (options.horizontalAlignment === CENTER) options.verticalAlignment = BOTTOM; if (options.horizontalAlignment === RIGHT || options.horizontalAlignment === LEFT) options.verticalAlignment = TOP } }, update: function(data, options) { this._data = data; this.boundingRect = { width: 0, height: 0, x: 0, y: 0 }; this._init(options); return this }, setSize: function(size) { this._size = size; return this }, draw: function() { if (!this._options) return this; var that = this, renderer = that._renderer, options = that._options, items = that._data, itemsLength = items.length, seriesGroups = [], i, label, marker, singleSeriesGroup, trackers = [], insideLegendGroup, markersId = new Array(itemsLength), passedId, border = options.border, borderVisible = border.visible && border.width && border.color && border.color !== NONE, markers = new Array(itemsLength); if (!(options.visible && items && itemsLength)) { that._disposeTrackers(); return that } that._cleanLegendGroups(); insideLegendGroup = that._insideLegendGroup = renderer.createGroup().append(that._legendGroup); that._createBackground(borderVisible); for (i = 0; i < itemsLength; i++) { singleSeriesGroup = renderer.createGroup({'class': 'dxc-item'}).append(insideLegendGroup); marker = that._createMarker(items[i], singleSeriesGroup, i); passedId = items[i].id; label = that._createLabel(items[i], passedId, singleSeriesGroup); markersId[i] = passedId; that._locateLabelAndMarker(label, marker); markers[i] = marker; trackers.push({ rect: renderer.createRect(0, 0, 0, 0, 0, { stroke: NONE, fill: 'grey', opacity: 0.0001, inh: true }), id: passedId }); seriesGroups.push(singleSeriesGroup) } that._seriesGroups = seriesGroups; that._trackers = trackers; that.drawTrackers(); that._markers = markers; that._markersId = markersId; that._locateElements(options); return that }, _locateElements: function(options) { var that = this, border = options.border, borderVisible = border.visible && border.width && border.color && border.color !== NONE; that._moveInInitialValues(); that._locateRowsColumns(that._seriesGroups, that._trackers, that._data.length, that._background, options); if (that._background) that._adjustBackgroundSettings(that._background, borderVisible, options); that._setBoundingRect(options) }, _moveInInitialValues: function() { var that = this; that._legendGroup && that._legendGroup.move(0, 0); that._trackerGroup && that._trackerGroup.move(0, 0); that._background && that._background.applySettings({ x: 0, y: 0, width: 0, height: 0 }) }, _applyMarkerOptions: function(marker, options) { if (marker) marker.applySettings(options) }, applySelected: function(id) { var index = this._getIndexById(id); if (index !== null) this._applyMarkerOptions(this._markers[index], {fill: this._markersPatternsIds[index].selectedPatternId}); return this }, applyHover: function(id) { var index = this._getIndexById(id); if (index !== null) this._applyMarkerOptions(this._markers[index], {fill: this._markersPatternsIds[index].hoverPatternId}); return this }, resetItem: function(id) { var index = this._getIndexById(id); if (index !== null) this._applyMarkerOptions(this._markers[index], {fill: this._data[index].color || this._data[index].states.normal.fill}) }, _getIndexById: function(id) { var i, markersId = this._markersId, markersIdLen = markersId.length; for (i = 0; i < markersIdLen; i++) if (markersId[i] === id) return i; return null }, drawTrackers: function() { if (!this._options.visible || !this._insideLegendGroup) return; var that = this, trackerGroup = that._trackerGroup.append(that._legendGroup); $.each(that._trackers || [], function(i, tracker) { var trackerRect = tracker.rect; trackerRect.data({ itemIndex: tracker.id, mode: that._options.hoverMode }); trackerRect.append(trackerGroup) }); return that }, _disposeTrackers: function() { var that = this; $.each(that._trackers || [], function(_, tracker) { tracker.rect.removeData() }); that._trackers = null }, _createMarker: function(data, group, markerIndex) { var that = this, renderer = that._renderer, markersPatternsIds = that._markersPatternsIds, size = that._options.markerSize, states = data.states, marker; marker = renderer.createRect(0, 0, size, size, 0, {fill: data.color}).append(group); markersPatternsIds[markerIndex] = { hoverPatternId: getPatternId(renderer, states, 'hover', data.color), selectedPatternId: getPatternId(renderer, states, 'selection', data.color) }; return marker }, _createLabel: function(data, index, group) { var that = this, options = that._options, position = options.itemTextPosition, align = position === TOP || position === BOTTOM ? CENTER : LEFT, text, label, labelFormatObject = { seriesName: data.text, seriesNumber: index, seriesColor: data.color }; text = that._formatLabel.call(labelFormatObject, options); label = that._renderer.createText(text, 0, 0, { font: options.font, align: align }).append(group); return label }, _cleanLegendGroups: function() { var that = this, trackerGroup = that._trackerGroup, legendGroup = that._legendGroup; if (legendGroup) { legendGroup.clear(); that._insideLegendGroup && that._insideLegendGroup.dispose(); that._insideLegendGroup = null } if (trackerGroup) trackerGroup.clear() }, _createBackground: function(borderVisible) { var that = this, options = that._options, isInside = options.position === INSIDE, color = options.backgroundColor, fill = color || (isInside ? options.containerBackgroundColor : NONE); if (isInside || color || borderVisible) that._background = that._renderer.createRect(0, 0, 0, 0, 0, { fill: fill, 'class': 'dxc-border' }).append(that._insideLegendGroup) }, _formatLabel: function(options) { return options.customizeText.call(this, this) }, _locateLabelAndMarker: function(label, marker) { var that = this, defaultXMargin = 7, defaultTopMargin = 4, defaultBottomMargin = 2, labelX = 0, labelY = 0, markerX, markerY, labelBox = label.getBBox(), markerWidth = that._options.markerSize, markerHeight = markerWidth, approximateLabelY = markerHeight / 2 - (labelBox.y + labelBox.height / 2), approximateLabelX = markerWidth / 2 - (labelBox.x + labelBox.width / 2); switch (that._options.itemTextPosition) { case LEFT: labelY = _round(approximateLabelY); markerX = labelBox.width + defaultXMargin; break; case RIGHT: labelX = markerWidth + defaultXMargin; labelY = _round(approximateLabelY); break; case TOP: labelX = _round(approximateLabelX); markerY = defaultTopMargin; break; case BOTTOM: labelX = _round(approximateLabelX); labelY = markerHeight + defaultBottomMargin - labelBox.y; break } label.applySettings({ x: labelX, y: labelY }); marker.applySettings({ x: markerX, y: markerY }) }, _locateRowsColumns: function(groups, trackers, count, background, options) { var that = this, itemTextPosition = options.itemTextPosition, size = that._size, legendBox, rowsColumns = that._getRowsColumns(count), rows = rowsColumns.rows, columns = rowsColumns.columns, margin = options.margin, paddingLeftRight = background ? options.paddingLeftRight : 0, paddingTopBottom = background ? options.paddingTopBottom : 0, placeholderWidth = size.width - margin.left - margin.right - 2 * paddingLeftRight, placeholderHeight = size.height - margin.top - margin.bottom - 2 * paddingTopBottom, rowsColumnsData, condition, maxBBox = getMaxBBox(groups); var moveRowsColumns = function(rows, columns) { rowsColumnsData = that._getDataRowsColumns(groups, columns, rows); that._moveItems(rowsColumnsData, groups, itemTextPosition, trackers, options) }; moveRowsColumns(rows, columns); legendBox = that._insideLegendGroup ? that._insideLegendGroup.getBBox() : {}; if (rowsColumns.autoEdit) if (rows === 1) { if (legendBox.width > placeholderWidth && columns > 1) { columns = _floor(placeholderWidth / (maxBBox.width + options.columnItemSpacing)) || 1; columns = validate(columns, count); rows = _ceil(count / columns); moveRowsColumns(rows, columns) } } else if (columns === 1) if (legendBox.height > placeholderHeight && rows > 1) { rows = _floor(placeholderHeight / (maxBBox.height + options.rowItemSpacing)) || 1; rows = validate(rows, count); columns = _ceil(count / rows); moveRowsColumns(rows, columns) } that._rowsCountDrawed = rows; that._columnsCountDrawed = columns; function validate(rowsOrColumns, count) { if (rowsOrColumns > count || rowsOrColumns < 1) rowsOrColumns = count; return rowsOrColumns } }, _moveItems: function(data, seriesGroups, horizontalTextPosition, trackers, options) { var that = this, i, j, rows, cols, number, group, box, xShift = 0, yShift = 0, widthColumn, xPadding = options.columnItemSpacing, yPadding = options.rowItemSpacing, equalColumnWidth = options.equalColumnWidth, renderer = that._renderer, maxWidthPerColumn = [], maxWidthColumn = 0, maxHeightRow = 0; rows = data.rows; cols = data.cols; maxHeightRow = data.maxHeightRow; maxWidthColumn = data.maxWidthColumn; maxWidthPerColumn = data.maxWidthPerColumn; for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { if (rows < cols) number = i * cols + j; else number = i + j * rows; group = seriesGroups[number]; if (!group) break; box = group.getBBox(); widthColumn = !equalColumnWidth ? maxWidthPerColumn[j] : maxWidthColumn; if (horizontalTextPosition === RIGHT) { group.move(xShift - box.x, yShift); trackers[number].rect.applySettings({ x: xShift - xPadding / 2, y: yShift + box.y - yPadding / 2, height: maxHeightRow + yPadding, width: widthColumn + xPadding }) } else if (horizontalTextPosition === LEFT) { group.move(box.x + widthColumn - box.width + xShift - xPadding / 2, yShift); trackers[number].rect.applySettings({ x: box.x + widthColumn - box.width + xShift - xPadding / 2, y: yShift + box.y - yPadding / 2, height: maxHeightRow + yPadding, width: widthColumn + xPadding }) } else { group.move(xShift - box.x - box.width / 2 + widthColumn / 2, yShift); trackers[number].rect.applySettings({ x: xShift - xPadding / 2, y: yShift + box.y - yPadding / 2, height: maxHeightRow + yPadding, width: widthColumn + xPadding }) } xShift = xShift + widthColumn + xPadding } yShift = yShift + maxHeightRow + yPadding; xShift = 0 } }, _getDataRowsColumns: function(seriesGroups, cols, rows) { var that = this, i, j, options = that._options, equalColumnWidth = options.equalColumnWidth, series = that.series || {}, maxWidthPerColumn = [], maxWidthColumn = 0, maxHeightRow = 0, group, box; for (i = 0; i < cols; i++) maxWidthPerColumn[i] = 0; for (i = 0; i < rows; i++) for (j = 0; j < cols; j++) { if (rows < cols) group = seriesGroups[i * cols + j]; else group = seriesGroups[i + j * rows]; if (!group) break; box = group.getBBox(); if (maxHeightRow < box.height) maxHeightRow = box.height; if (!equalColumnWidth) { if (maxWidthPerColumn[j] < box.width) maxWidthPerColumn[j] = box.width } else if (maxWidthColumn < box.width) maxWidthColumn = box.width } return { rows: rows, cols: cols, maxWidthPerColumn: maxWidthPerColumn, maxWidthColumn: maxWidthColumn, maxHeightRow: maxHeightRow } }, _getRowsColumns: function(count) { var that = this, options = that._options, isHorizontal = options.orientation === HORIZONTAL, rows = options.rowCount, onRows = _ceil(count / rows), columns = options.columnCount, onColumns = _ceil(count / columns), autoEdit; if (columns && !rows) rows = onColumns; else if (!columns && rows) columns = onRows; else if (columns && rows) { if (isHorizontal && columns < onRows) columns = onRows; else if (!isHorizontal && rows < onColumns) rows = onColumns } else { autoEdit = true; if (isHorizontal) { rows = 1; columns = count } else { columns = 1; rows = count } } return { rows: rows, columns: columns, autoEdit: autoEdit } }, _adjustBackgroundSettings: function(background, borderVisible, options) { var that = this, border = options.border, legendBox = that._insideLegendGroup.getBBox(), backgroundSettings = { x: _round(legendBox.x - options.paddingLeftRight), y: _round(legendBox.y - options.paddingTopBottom), width: _round(legendBox.width) + 2 * options.paddingLeftRight, height: _round(legendBox.height) + 2 * options.paddingTopBottom, opacity: options.backgroundOpacity }; if (borderVisible) { backgroundSettings.strokeWidth = border.width; backgroundSettings.stroke = border.color; backgroundSettings.strokeOpacity = border.opacity; backgroundSettings.dashStyle = border.dashStyle; backgroundSettings.rx = border.cornerRadius || 0; backgroundSettings.ry = border.cornerRadius || 0 } background.applySettings(backgroundSettings) }, _setBoundingRect: function(options) { var that = this, box, margin = options.margin; if (!that._insideLegendGroup) return; box = that._insideLegendGroup.getBBox(); box.height += margin.top + margin.bottom; box.width += margin.left + margin.right; box.x -= margin.left; box.y -= margin.top; that.boundingRect = box }, changeSize: function(size) { var that = this, options = $.extend(true, {}, that._options), margin = options.margin; if (size.height >= 0) { size.height = decreaseGaps(margin, ["top", "bottom"], size.height); if (options.border.visible) size.height = 2 * decreaseGaps(options, ["paddingTopBottom"], size.height / 2); if (that._rowsCountDrawed - 1) size.height = (that._rowsCountDrawed - 1) * decreaseGaps(options, ["rowItemSpacing"], size.height / (that._rowsCountDrawed - 1)) } if (size.width >= 0) { size.width = decreaseGaps(margin, ["left", "right"], size.width); if (options.border.visible) size.width = 2 * decreaseGaps(options, ["paddingLeftRight"], size.width / 2); if (that._columnsCountDrawed - 1) size.width = (that._columnsCountDrawed - 1) * decreaseGaps(options, ["columnItemSpacing"], size.width / (that._columnsCountDrawed - 1)) } if (that._insideLegendGroup) if (size.height > 0 || size.width > 0) { that._options._incidentOccured("W2104"); that._insideLegendGroup.remove(); that._insideLegendGroup = null; that._trackerGroup && that._trackerGroup.clear() } else that._locateElements(options) }, getTrackerGroup: function() { return this._trackerGroup }, getActionCallback: function(point) { var that = this; if (that._options.visible) return function(act) { var pointType = point.type, isSeries = pointType ? true : false, seriesType = pointType || point.series.type; if (isSeries || seriesType === 'pie' || seriesType === 'doughnut' || seriesType === 'donut') that[act] && that[act](point.index) }; else return $.noop }, getLayoutOptions: function() { var options = this._options, boundingRect = this._insideLegendGroup ? this.boundingRect : { width: 0, height: 0, x: 0, y: 0 }; if (options) { boundingRect.verticalAlignment = options.verticalAlignment; boundingRect.horizontalAlignment = options.horizontalAlignment; if (options.orientation === 'horizontal') boundingRect.cutLayoutSide = options.verticalAlignment; else boundingRect.cutLayoutSide = options.horizontalAlignment === 'center' ? options.verticalAlignment : options.horizontalAlignment; return boundingRect } return null }, shift: function(x, y) { var that = this, settings = {}, box = that.getLayoutOptions(); settings.translateX = x - box.x; settings.translateY = y - box.y; that._insideLegendGroup && that._insideLegendGroup.applySettings(settings); that._trackerGroup && that._trackerGroup.applySettings(settings) }, getPosition: function() { return this._options.position }, dispose: function() { var that = this; that._disposeTrackers(); that._legendGroup = null; that._trackerGroup = null; that._insideLegendGroup = null; that._renderer = null; that._options = null; that._data = null; return that } }) })(DevExpress, jQuery); /*! Module viz-core, file range.js */ (function($, DX, undefined) { var core = DX.viz.core, utils = DX.utils, isDefinedUtils = utils.isDefined, isDateUtils = utils.isDate, getLogUtils = utils.getLog, raiseToUtils = utils.raiseTo; var NUMBER_EQUALITY_CORRECTION = 1, DATETIME_EQUALITY_CORRECTION = 60000; var minSelector = 'min', maxSelector = 'max', minVisibleSelector = 'minVisible', maxVisibleSelector = 'maxVisible', minValueMarginSelector = 'minValueMargin', maxValueMarginSelector = 'maxValueMargin', categoriesSelector = 'categories', keepValueMarginsSelector = 'keepValueMargins', baseSelector = 'base', axisTypeSelector = 'axisType'; var raiseToFlooredLog = function(value, base, correction) { return raiseToUtils(Math.floor(getLogUtils(value, base)) + (correction || 0), base) }; var otherLessThan = function(thisValue, otherValue) { return otherValue < thisValue }; var otherGreaterThan = function(thisValue, otherValue) { return otherValue > thisValue }; var compareAndReplace = function(thisValue, otherValue, setValue, compare) { var otherValueDefined = isDefinedUtils(otherValue); if (isDefinedUtils(thisValue)) { if (otherValueDefined && compare(thisValue, otherValue)) setValue(otherValue) } else if (otherValueDefined) setValue(otherValue) }; var applyMargin = function(value, margin, rangeLength, coef, isDateTime) { value = value.valueOf() + coef * rangeLength * margin; return isDateTime ? new Date(value) : value }; DX.viz.core.__NUMBER_EQUALITY_CORRECTION = NUMBER_EQUALITY_CORRECTION; DX.viz.core.__DATETIME_EQUALITY_CORRECTION = DATETIME_EQUALITY_CORRECTION; core.Range = function(range) { range && $.extend(this, range) }; $.extend(core.Range.prototype, { dispose: function() { this[categoriesSelector] = null }, addRange: function(otherRange) { var that = this, categories = that[categoriesSelector], categoriesValues, otherCategories = otherRange[categoriesSelector], i, j, length, found; var setIndentByPriority = function(prefix) { var prioritySelector = prefix + 'Priority', priorityRelation = (that[prioritySelector] || 0) - (otherRange[prioritySelector] || 0); if ((that[prefix] || 0) < otherRange[prefix] && priorityRelation === 0 || priorityRelation < 0) { that[prefix] = otherRange[prefix]; that[prioritySelector] = otherRange[prioritySelector] } }; var compareAndReplaceByField = function(field, compare) { compareAndReplace(that[field], otherRange[field], function(value) { that[field] = value }, compare) }; var controlValuesByVisibleBounds = function(valueField, visibleValueField, compare) { compareAndReplace(that[valueField], that[visibleValueField], function(value) { isDefinedUtils(that[valueField]) && (that[valueField] = value) }, compare) }; var checkField = function(field) { that[field] = that[field] || otherRange[field] }; if (utils.isDefined(otherRange["stick"])) that["stick"] = otherRange["stick"]; checkField('invert'); checkField(axisTypeSelector); checkField('dataType'); checkField(keepValueMarginsSelector); if (that[axisTypeSelector] === 'logarithmic') checkField(baseSelector); else that[baseSelector] = undefined; compareAndReplaceByField(minSelector, otherLessThan); compareAndReplaceByField(maxSelector, otherGreaterThan); compareAndReplaceByField(minVisibleSelector, otherLessThan); compareAndReplaceByField(maxVisibleSelector, otherGreaterThan); compareAndReplaceByField('interval', otherLessThan); setIndentByPriority(minValueMarginSelector); setIndentByPriority(maxValueMarginSelector); controlValuesByVisibleBounds(minSelector, minVisibleSelector, otherLessThan); controlValuesByVisibleBounds(minSelector, maxVisibleSelector, otherLessThan); controlValuesByVisibleBounds(maxSelector, maxVisibleSelector, otherGreaterThan); controlValuesByVisibleBounds(maxSelector, minVisibleSelector, otherGreaterThan); if (categories === undefined) that[categoriesSelector] = otherCategories; else { length = categories.length; if (otherCategories && otherCategories.length) for (i = 0; i < otherCategories.length; i++) { for (j = 0, found = false; j < length; j++) if (categories[j].valueOf() === otherCategories[i].valueOf()) { found = true; break } !found && categories.push(otherCategories[i]) } } return this }, isDefined: function() { return isDefinedUtils(this[minSelector]) && isDefinedUtils(this[maxSelector]) || isDefinedUtils(this[categoriesSelector]) }, setStubData: function(dataType) { var that = this, year = (new Date).getYear() - 1, isDate = dataType === 'datetime', isCategories = that.axisType === 'discrete'; if (isCategories) that.categories = ['0', '1', '2']; else { that[minSelector] = isDate ? new Date(year, 0, 1) : 0; that[maxSelector] = isDate ? new Date(year, 11, 31) : 10 } that.stubData = true; return that }, applyValueMargins: function() { var that = this, base = that[baseSelector], isDateTime = isDateUtils(that[maxSelector]) || isDateUtils(that[minSelector]); var applyMarginWithZeroCorrection = function(min, max, rangeLength) { var minValue = that[min], maxValue = that[max], minMargin = that[minValueMarginSelector], maxMargin = that[maxValueMarginSelector], minCorrected = false, maxCorrected = false; if (rangeLength && !isDateTime && !that[keepValueMarginsSelector]) { if (minValue <= 0 && maxValue <= 0 && maxMargin > maxValue / (minValue - maxValue)) { that[max] = 0; maxCorrected = true } if (minValue >= 0 && maxValue >= 0 && minMargin > minValue / (maxValue - minValue)) { that[min] = 0; minCorrected = true } } if (isDefinedUtils(maxValue) && !maxCorrected && maxMargin) that[max] = applyMargin(maxValue, maxMargin, rangeLength, 1, isDateTime); if (isDefinedUtils(minValue) && !minCorrected && minMargin) that[min] = applyMargin(minValue, minMargin, rangeLength, -1, isDateTime) }; var correctValueByBoundaries = function(visibleSelector, valueSelector) { that[visibleSelector] = isDefinedUtils(that[visibleSelector]) ? that[visibleSelector] : that[valueSelector] }; var processLogarithmicMinValue = function(valueField) { if (isDefinedUtils(that[valueField])) { var intermediateValue = raiseToFlooredLog(that[valueField], base); if (getLogUtils(that[valueField] / intermediateValue, base) < 0.1 && that.alwaysCorrectMin && !that[keepValueMarginsSelector]) that[valueField] = raiseToFlooredLog(that[valueField], base, -1); else if (that.alwaysCorrectMin && !that[keepValueMarginsSelector]) that[valueField] = intermediateValue; else if (getLogUtils(that[valueField] / intermediateValue, base) < 0.5) that[valueField] = intermediateValue } }; var processLogarithmicMaxValue = function(valueField) { if (isDefinedUtils(that[valueField])) { var intermediateValue = raiseToFlooredLog(that[valueField], base); if (getLogUtils(that[valueField] / intermediateValue, base) > 0.5) that[valueField] = raiseToUtils(Math.ceil(getLogUtils(that[valueField], base)), base) } }; var correctLogVisibleValue = function(visibleValueSelector, valueSelector, compare) { if (!isDefinedUtils(that[visibleValueSelector]) || compare) that[visibleValueSelector] = that[valueSelector] }; if (that[axisTypeSelector] === 'logarithmic' && that[minSelector] !== that[maxSelector]) { processLogarithmicMinValue(minSelector); processLogarithmicMaxValue(maxSelector); if (that.isValueRange && that[minVisibleSelector] !== that[maxVisibleSelector]) { processLogarithmicMinValue(minVisibleSelector); processLogarithmicMaxValue(maxVisibleSelector) } correctLogVisibleValue(minVisibleSelector, minSelector, that[minVisibleSelector] < that[minSelector]); correctLogVisibleValue(maxVisibleSelector, maxSelector, that[maxVisibleSelector] > that[maxSelector]) } else { correctValueByBoundaries(minVisibleSelector, minSelector); correctValueByBoundaries(maxVisibleSelector, maxSelector); applyMarginWithZeroCorrection(minSelector, maxSelector, that[maxSelector] - that[minSelector]); applyMarginWithZeroCorrection(minVisibleSelector, maxVisibleSelector, that[maxVisibleSelector] - that[minVisibleSelector]) } return this }, correctValueZeroLevel: function() { var that = this; if (isDateUtils(that[maxSelector]) || isDateUtils(that[minSelector])) return that; function setZeroLevel(min, max) { that[min] < 0 && that[max] < 0 && (that[max] = 0); that[min] > 0 && that[max] > 0 && (that[min] = 0) } setZeroLevel(minSelector, maxSelector); setZeroLevel(minVisibleSelector, maxVisibleSelector); return that } }) })(jQuery, DevExpress); /*! Module viz-core, file seriesConsts.js */ (function(DX) { DX.viz.core.series = DX.viz.core.series || {}; DX.viz.core.series.helpers = DX.viz.core.series.helpers || {}; DX.viz.core.series.helpers.consts = { events: { mouseover: "mouseover", mouseout: "mouseout", mousemove: "mousemove", touchstart: "touchstart", touchmove: "touchmove", touchend: "touchend", mousedown: "mousedown", mouseup: "mouseup", click: "click", selectSeries: "selectseries", deselectSeries: "deselectseries", selectPoint: "selectpoint", deselectPoint: "deselectpoint", showPointTooltip: "showpointtooltip", hidePointTooltip: "hidepointtooltip" }, states: { hover: "hover", normal: "normal", selected: "selected", normalMark: 0, hoverMark: 1, selectedMark: 2 }, animations: { showDuration: {duration: 400}, hideGroup: {opacity: 0.0001}, showGroup: {opacity: 1} } } })(DevExpress); /*! Module viz-core, file seriesFamily.js */ (function($, DX, undefined) { var utils = DX.utils, _round = Math.round, _abs = Math.abs, _pow = Math.pow; DX.viz.core.series.helpers.SeriesFamily = DX.Class.inherit(function() { var ctor = function(options) { var debug = DX.utils.debug; debug.assert(options.type, "type was not passed or empty"); var that = this, stubFunction = $.noop; $.extend(that, options); that.type = that.type.toLowerCase(); that.series = []; switch (that.type) { case"bar": that.adjustSeriesDimensions = adjustBarSeriesDimensions; that.adjustSeriesValues = stubFunction; that.updateSeriesValues = updateBarSeriesValues; break; case"rangebar": that.adjustSeriesDimensions = adjustBarSeriesDimensions; that.adjustSeriesValues = stubFunction; that.updateSeriesValues = stubFunction; break; case"fullstackedbar": that.fullStacked = true; that.adjustSeriesDimensions = adjustStackedBarSeriesDimensions; that.adjustSeriesValues = adjustStackedSeriesValues; that.updateSeriesValues = updateStackedSeriesValues; break; case"stackedbar": that.adjustSeriesDimensions = adjustStackedBarSeriesDimensions; that.adjustSeriesValues = adjustStackedSeriesValues; that.updateSeriesValues = updateStackedSeriesValues; break; case"fullstackedarea": case"fullstackedline": that.fullStacked = true; that.adjustSeriesDimensions = stubFunction; that.adjustSeriesValues = adjustStackedSeriesValues; that.updateSeriesValues = stubFunction; break; case"stackedarea": case"stackedline": that.adjustSeriesDimensions = stubFunction; that.adjustSeriesValues = adjustStackedSeriesValues; that.updateSeriesValues = stubFunction; break; case"candlestick": case"stock": that.adjustSeriesDimensions = adjustCandlestickSeriesDimensions; that.adjustSeriesValues = stubFunction; that.updateSeriesValues = stubFunction; break; case"bubble": that.adjustSeriesDimensions = adjustBubbleSeriesDimensions; that.adjustSeriesValues = stubFunction; that.updateSeriesValues = stubFunction; break; default: that.adjustSeriesDimensions = stubFunction; that.adjustSeriesValues = stubFunction; that.updateSeriesValues = stubFunction; break } }; var dispose = function() { this.series = null; this.translators = null }; var add = function(series) { var that = this, singleSeries, i; if (!$.isArray(series)) series = [series]; for (i = 0; i < series.length; i++) { singleSeries = series[i]; if (singleSeries.type.toLowerCase() === that.type) that.series.push(singleSeries) } }; var adjustBarSeriesDimensionsCore = function(series, interval, stackCount, equalBarWidth, seriesStackIndexCallback) { var spacing, width, maxWidth, middleIndex, stackIndex, i, point, points, seriesOffset, stackName, argumentsKeeper = {}, stackKeepers = {}, stacksWithArgument, count; if (equalBarWidth) { width = equalBarWidth.width && equalBarWidth.width < 0 ? 0 : equalBarWidth.width; spacing = equalBarWidth.spacing && equalBarWidth.spacing < 0 ? 0 : equalBarWidth.spacing; if (width && !spacing) if (stackCount > 1) { spacing = _round((interval * 0.7 - width * stackCount) / (stackCount - 1)); if (spacing < 1) spacing = 1 } else spacing = 0; else if (spacing && !width) { width = _round((interval * 0.7 - spacing * (stackCount - 1)) / stackCount); if (width < 2) width = 2 } else if (!spacing && !width) { if (stackCount > 1) { spacing = _round(interval * 0.7 / stackCount * 0.2); if (spacing < 1) spacing = 1 } else spacing = 0; width = _round((interval * 0.7 - spacing * (stackCount - 1)) / stackCount); if (width < 2) width = 2 } if (width * stackCount + spacing * (stackCount - 1) > interval) { spacing = _round((interval * 0.7 - width * stackCount) / (stackCount - 1)); if (spacing < 1) { spacing = 1; maxWidth = _round((interval * 0.7 - spacing * (stackCount - 1)) / stackCount) } } middleIndex = stackCount / 2; for (i = 0; i < series.length; i++) { stackIndex = seriesStackIndexCallback(i); points = series[i].getPoints(); seriesOffset = (stackIndex - middleIndex + 0.5) * (maxWidth || width) - (middleIndex - stackIndex - 0.5) * spacing; $.each(points, function(_, point) { point.correctCoordinates({ width: width, offset: seriesOffset }) }) } } else { $.each(series, function(i, singleSeries) { stackName = singleSeries.getStackName && singleSeries.getStackName(); stackName = stackName || i.toString(); if (!stackKeepers[stackName]) stackKeepers[stackName] = []; stackKeepers[stackName].push(singleSeries) }); $.each(series, function(i, singleSeries) { $.each(singleSeries.getPoints(), function(_, point) { var argument = point.argument; if (!argumentsKeeper.hasOwnProperty(argument)) argumentsKeeper[argument.valueOf()] = 1 }) }); for (var argument in argumentsKeeper) { if (!argumentsKeeper.hasOwnProperty(argument)) continue; stacksWithArgument = []; $.each(stackKeepers, function(stackName, seriesInStack) { $.each(seriesInStack, function(i, singleSeries) { point = singleSeries.getPointByArg(argument); if (point && point.value) { stacksWithArgument.push(stackName); return false } }) }); count = stacksWithArgument.length; spacing = _round(interval * 0.7 / count * 0.2); if (spacing < 1) spacing = 1; width = _round((interval * 0.7 - spacing * (count - 1)) / count); if (width < 2) width = 2; middleIndex = count / 2; $.each(stackKeepers, function(stackName, seriesInStack) { stackIndex = $.inArray(stackName, stacksWithArgument); if (stackIndex === -1) return; seriesOffset = (stackIndex - middleIndex + 0.5) * width - (middleIndex - stackIndex - 0.5) * spacing; $.each(seriesInStack, function(i, singleSeries) { var point = singleSeries.getPointByArg(argument); if (point && point.value) point.correctCoordinates({ width: width, offset: seriesOffset }) }) }) } } }; var getVisibleSeries = function(that) { return $.map(that.series, function(s) { return s.isVisible() ? s : null }) }; var adjustBarSeriesDimensions = function(translators) { var debug = DX.utils.debug; debug.assert(translators, "translator was not passed or empty"); var that = this, equalBarWidth = that.equalBarWidth, series = getVisibleSeries(that); adjustBarSeriesDimensionsCore(series, getInterval(that, translators), series.length, equalBarWidth, function(seriesIndex) { return seriesIndex }) }; var adjustStackedBarSeriesDimensions = function(translators) { var debug = DX.utils.debug; debug.assert(translators, "translators was not passed or empty"); var that = this, interval, series = getVisibleSeries(that), stackIndexes = {}, stackCount = 0, equalBarWidth = that.equalBarWidth; $.each(series, function() { var stackName = this.getStackName(); if (!stackIndexes.hasOwnProperty(stackName)) stackIndexes[stackName] = stackCount++ }); adjustBarSeriesDimensionsCore(series, getInterval(that, translators), stackCount, equalBarWidth, function(seriesIndex) { return stackIndexes[series[seriesIndex].getStackName()] }) }; var adjustStackedSeriesValues = function() { var that = this, series = getVisibleSeries(that), stackKeepers = { positive: {}, negative: {} }; $.each(series, function(_, singleSeries) { var points = singleSeries.getPoints(); $.each(points, function(index, point) { var value = point.initialValue, argument = point.argument, stackName = singleSeries.getStackName ? singleSeries.getStackName() : "default", valueType = value >= 0 ? "positive" : "negative", currentStack; stackKeepers[valueType][stackName] = stackKeepers[valueType][stackName] || {}; currentStack = stackKeepers[valueType][stackName]; if (currentStack[argument.valueOf()]) { points[index].correctValue(currentStack[argument.valueOf()]); currentStack[argument.valueOf()] += value } else { currentStack[argument.valueOf()] = value; points[index].resetCorrection() } }) }); setPercentStackedValues(series, stackKeepers, that.fullStacked) }; var setPercentStackedValues = function(series, stackKeepers, fullStacked) { $.each(series, function(_, singleSeries) { var points = singleSeries.getPoints(); $.each(points, function(index, point) { var value = point.value, stackName = singleSeries.getStackName ? singleSeries.getStackName() : "default", valueType = value >= 0 ? "positive" : "negative", currentStack; stackKeepers[valueType][stackName] = stackKeepers[valueType][stackName] || {}; currentStack = stackKeepers[valueType][stackName]; points[index].setPercentValue(currentStack[point.argument.valueOf()], fullStacked) }) }) }; var getMinShownBusinessValue = function(that, translators, minBarSize) { var rotated = that.rotated, valTranslator = rotated ? translators.x : translators.y, canvas = valTranslator.getCanvasVisibleArea(); if (minBarSize) return _abs(valTranslator.untranslate(canvas.min) - valTranslator.untranslate(canvas.min + minBarSize)) }; var updateStackedSeriesValues = function(translators) { var that = this, series = getVisibleSeries(that), stackKeepers = { positive: {}, negative: {} }; $.each(series, function(_, singleSeries) { var points = singleSeries.getPoints(), minBarSize = singleSeries.getOptions().minBarSize; $.each(points, function(index, point) { var value = point.value, minValue = point.minValue, argument = point.argument, updateValue, pointSize, minShownBusinessValue, stackName = singleSeries.getStackName ? singleSeries.getStackName() : "default", valueType = value >= 0 ? "positive" : "negative", currentStack; minShownBusinessValue = getMinShownBusinessValue(that, translators, minBarSize); currentStack = stackKeepers[valueType][stackName] = stackKeepers[valueType][stackName] || {}; if (currentStack[argument.valueOf()]) { minValue = utils.isNumber(minValue) ? minValue : 0, pointSize = _abs(minValue - value); if (minShownBusinessValue && pointSize < minShownBusinessValue) updateValue = minShownBusinessValue; else updateValue = value - minValue; points[index].minValue = currentStack[argument.valueOf()]; points[index].value = currentStack[argument.valueOf()] + updateValue; currentStack[argument.valueOf()] += updateValue } else { pointSize = value; if (minShownBusinessValue && pointSize < minShownBusinessValue) updateValue = minShownBusinessValue; else updateValue = value; points[index].value = updateValue; currentStack[argument.valueOf()] = updateValue } }) }); if (that.fullStacked) updateFullStackedSeriesValues(series, stackKeepers) }; var updateFullStackedSeriesValues = function(series, stackKeepers) { $.each(series, function(_, singleSeries) { var stackName = singleSeries.getStackName ? singleSeries.getStackName() : "default", points = singleSeries.getPoints(); $.each(points, function(index, point) { var value = point.value, argument = point.argument, valueType = value >= 0 ? "positive" : "negative", currentStack; stackKeepers[valueType][stackName] = stackKeepers[valueType][stackName] || {}; currentStack = stackKeepers[valueType][stackName]; points[index].value = points[index].value / currentStack[argument.valueOf()] || 0; if (DX.utils.isNumber(points[index].minValue)) points[index].minValue = points[index].minValue / currentStack[argument.valueOf()] || 0 }) }) }; var updateBarSeriesValues = function(translators) { var that = this; $.each(that.series, function(_, singleSeries) { var points = singleSeries.getPoints(), minBarSize = singleSeries.getOptions().minBarSize; $.each(points, function(index, point) { var value = point.value, updateValue, pointSize, minShownBusinessValue; minShownBusinessValue = getMinShownBusinessValue(that, translators, minBarSize); pointSize = _abs(value); if (minShownBusinessValue && pointSize < minShownBusinessValue) updateValue = value >= 0 ? minShownBusinessValue : -minShownBusinessValue; else updateValue = value; points[index].value = updateValue }) }) }; var adjustCandlestickSeriesDimensions = function(translators) { var debug = DX.utils.debug; debug.assert(translators, "translator was not passed or empty"); var that = this, series = getVisibleSeries(that); adjustBarSeriesDimensionsCore(series, getInterval(that, translators), series.length, true, function(seriesIndex) { return seriesIndex }) }; var getInterval = function(that, translators) { var argTranslator = !that.rotated ? translators.x : translators.y; return that.interval = argTranslator.getInterval() }; var adjustBubbleSeriesDimensions = function(translators) { var debug = DX.utils.debug; debug.assert(translators, "translator was not passed or empty"); var that = this, series = getVisibleSeries(that), points, i, visibleAreaX = translators.x.getCanvasVisibleArea(), visibleAreaY = translators.y.getCanvasVisibleArea(), min = Math.min(visibleAreaX.max - visibleAreaX.min, visibleAreaY.max - visibleAreaY.min), minBubbleArea = _pow(that.minBubbleSize, 2), maxBubbleArea = _pow(min * that.maxBubbleSize, 2), equalBubbleSize = (min * that.maxBubbleSize + that.minBubbleSize) / 2, minPointSize = Infinity, maxPointSize = 0, pointSize, bubbleArea, sizeProportion, sizeDispersion, areaDispersion; for (i = 0; i < series.length; i++) { points = series[i].getPoints(); $.each(points, function(_, point) { maxPointSize = maxPointSize > point.size ? maxPointSize : point.size; minPointSize = minPointSize < point.size ? minPointSize : point.size }) } sizeDispersion = maxPointSize - minPointSize; areaDispersion = _abs(maxBubbleArea - minBubbleArea); minPointSize = minPointSize < 0 ? 0 : minPointSize; for (i = 0; i < series.length; i++) { points = series[i].getPoints(); $.each(points, function(_, point) { if (maxPointSize === minPointSize) pointSize = _round(equalBubbleSize); else { sizeProportion = _abs(point.size - minPointSize) / sizeDispersion; bubbleArea = areaDispersion * sizeProportion + minBubbleArea; pointSize = _round(Math.sqrt(bubbleArea)) } point.correctCoordinates(pointSize) }) } }; return { ctor: ctor, dispose: dispose, add: add } }()) })(jQuery, DevExpress); /*! Module viz-core, file baseSeries.js */ (function($, DX) { var viz = DX.viz, utils = DX.utils, _isDefined = utils.isDefined, _each = $.each, _extend = $.extend, _isEmptyObject = $.isEmptyObject, _Event = $.Event, _noop = $.noop, SELECTED_STATE = 2, HOVER_STATE = 1, NONE_MODE = "none", INCLUDE_POINTS = "includepoints", EXLUDE_POINTS = "excludepoints", ALL_SERIES_POINTS_MODE = "allseriespoints", APPLY_SELECTED = "applySelected", APPLY_HOVER = "applyHover", getEmptyBusinessRange = function() { return { arg: {}, val: {} } }; viz.core.series.mixins = { chart: {}, pieChart: {} }; viz.core.series.Series = DX.Class.inherit({ ctor: function(renderer, options) { this.fullState = 0; this._renderer = renderer; this._group = renderer.createGroup({"class": "dxc-series"}); this.updateOptions(options) }, update: function(data, options) { this.updateOptions(options); this.updateData(data) }, _createLegendState: function(styleOptions, defaultColor) { return { fill: styleOptions.color || defaultColor, hatching: styleOptions.hatching } }, getLegendStyles: function() { return this._styles.legendStyles }, _createStyles: function(options) { var mainSeriesColor = options.mainSeriesColor, specialMainColor = this._getSpecialColor(mainSeriesColor); this._styles = { normal: this._parseStyle(options, mainSeriesColor, mainSeriesColor), hover: this._parseStyle(options.hoverStyle || {}, specialMainColor, mainSeriesColor), selection: this._parseStyle(options.selectionStyle || {}, specialMainColor, mainSeriesColor), legendStyles: { normal: this._createLegendState(options, mainSeriesColor), hover: this._createLegendState(options.hoverStyle || {}, specialMainColor), selection: this._createLegendState(options.selectionStyle || {}, specialMainColor) } } }, setAdjustSeriesLabels: function(adjustSeriesLabels) { _each(this._points || [], function(_, point) { point.setAdjustSeriesLabels(adjustSeriesLabels) }) }, setClippingParams: function(id, forceClipping) { this._paneClipRectID = id; this._forceClipping = forceClipping }, getTagField: function() { return this._options.tagField || "tag" }, getValueFields: _noop, getArgumentField: _noop, getPoints: function() { return this._points }, _createPoint: function(data, pointsArray, index) { data.index = index; if (this._checkData(data)) { var point = pointsArray[index], options = this._customizePoint(data) || this._getCreatingPointOptions(); if (point) point.update(data, options); else { point = viz.core.CoreFactory.createPoint(data, options); pointsArray.push(point) } this.pointsByArgument[point.argument.valueOf()] = this.pointsByArgument[point.argument.valueOf()] || point; return true } }, getRangeData: function(zoomArgs, calcIntervalFunction) { return this._visible ? _extend(true, {}, this._getRangeData(zoomArgs, calcIntervalFunction)) : getEmptyBusinessRange() }, _deleteElementsGroup: function() { if (this._elementsGroup) { this._elementsGroup.detach(); this._elementsGroup = null } }, _deleteBordersGroup: function() { if (this._bordersGroup) { this._bordersGroup.detach(); this._bordersGroup = null } }, _saveOldAnimationMethods: function() { this._oldClearingAnimation = this._clearingAnimation; this._oldUpdateElement = this._updateElement }, _deleteOldAnimationMethods: function() { this._oldClearingAnimation = null; this._oldUpdateElement = null }, updateOptions: function(newOptions) { var that = this, widgetType = newOptions.widgetType, oldType = that.type, newType = newOptions.type; that.type = newType && newType.toString().toLowerCase(); if (!that._checkType(widgetType)) { that.dispose(); that.isUpdated = false; return } if (oldType !== that.type) { that._firstDrawing = true; that._saveOldAnimationMethods(); that._resetType(oldType, widgetType); that._setType(that.type, widgetType) } that._options = newOptions; that._pointOptions = null; that._deletePatterns(); that._patterns = []; that.name = newOptions.name; that.pane = newOptions.pane; that.axis = newOptions.axis; that.tag = newOptions.tag; that._createStyles(newOptions); that._updateOptions(newOptions); that._visible = newOptions.visible; that.isUpdated = true }, _disposePoints: function(points) { $.each(points || [], function(_, p) { p.dispose() }) }, _correctPointsLength: function(length, points) { this._disposePoints(this._oldPoints); this._oldPoints = points.splice(length, points.length) }, _getTicksForAggregation: function(min, max, screenDelta, pointSize) { return viz.core.tickProvider.getTicks({ min: min, max: max, screenDelta: screenDelta, gridSpacingFactor: pointSize }) }, updateDataType: function(settings) { var that = this; that.argumentType = settings.argumentType; that.valueType = settings.valueType; that.argumentAxisType = settings.argumentAxisType; that.valueAxisType = settings.valueAxisType }, getValueCategories: function() { return this._options.valueCategories || [] }, getOptions: function() { return this._options }, getArgumentCategories: function() { return this._options.argumentCategories || [] }, updateData: function(data) { var that = this, points, lastPointIndex = 0, options = that._options, pointData; that.pointsByArgument = {}; points = that._originalPoints || []; that._rangeData = getEmptyBusinessRange(); if (data && data.length) that._canRenderCompleteHandle = true; that._beginUpdateData(); _each(data, function(index, dataItem) { pointData = that._getPointData(dataItem, options); if (that._createPoint(pointData, points, lastPointIndex)) { that._processRange(points[lastPointIndex], lastPointIndex > 0 ? points[lastPointIndex - 1] : null); lastPointIndex++ } }); that._points = that._originalPoints = points; that._correctPointsLength(lastPointIndex, points); that._endUpdateData() }, getTeamplatedFields: function() { var that = this, fields = that.getValueFields(), teampleteFields = []; fields.push(that.getTagField()); _each(fields, function(_, field) { var fieldsObject = {}; fieldsObject.teamplateField = field + that.name; fieldsObject.originalField = field; teampleteFields.push(fieldsObject) }); return teampleteFields }, resamplePoints: function(translators, min, max) { var that = this, originalPoints = that.getAllPoints(), argTranslator = that._options.rotated ? translators.y : translators.x, minI, maxI, sizePoint, ticks; if (originalPoints.length) { _each(originalPoints, function(i, point) { minI = point.argument - min <= 0 ? i : minI; if (!maxI) maxI = point.argument - max > 0 ? i : null }); minI = minI ? minI : 1; maxI = utils.isDefined(maxI) ? maxI : originalPoints.length - 1; min = originalPoints[minI - 1].argument; max = originalPoints[maxI].argument; sizePoint = that._getPointSize(); if (that.argumentAxisType !== "discrete" && that.valueAxisType !== "discrete") ticks = that._getTicksForAggregation(min, max, argTranslator.canvasLength, sizePoint); else ticks = argTranslator.canvasLength / sizePoint; that._points = that._resample(ticks, ticks.tickInterval) } }, _removeOldSegments: function(startIndex) { var that = this; _each(that._graphics.splice(startIndex, that._graphics.length) || [], function(_, elem) { that._removeElement(elem) }); if (that._trackers) _each(that._trackers.splice(startIndex, that._trackers.length) || [], function(_, elem) { elem.remove() }) }, draw: function(translators, animationEnabled, hideLayoutLabels, legendCallback) { var that = this; if (that._oldClearingAnimation && animationEnabled && that._firstDrawing) { var drawComplete = function() { that._draw(translators, true, hideLayoutLabels) }; that._oldClearingAnimation(translators, drawComplete) } else that._draw(translators, animationEnabled, hideLayoutLabels, legendCallback) }, _clearSeries: function() { this._deleteElementsGroup(); this._deleteBordersGroup(); this._deleteTrackers(); this._graphics = []; this._trackers = [] }, _draw: function(translators, animationEnabled, hideLayoutLabels, legendCallback) { var that = this, points = that._points || [], segment = [], segmentCount = 0, firstDrawing = that._firstDrawing, markersGroup, labelsGroup; that._graphics = that._graphics || [], that._graphics = that._graphics || []; that._prepareSeriesToDrawing(); if (!that._visible) { animationEnabled = false; this._group.detach(); return } else that._group.append(that._options.seriesGroup); that.translators = translators; that._createGroups(animationEnabled, undefined, firstDrawing); that._segments = []; markersGroup = that._markersGroup; labelsGroup = that._labelsGroup; that._drawedPoints = []; that._firstDrawing = points.length ? false : true; _each(this._patterns || [], function(_, pattern) { pattern.append() }); _each(points, function(i, p) { p.translate(translators); if (p.hasValue()) { that._drawPoint(p, markersGroup, labelsGroup, animationEnabled, firstDrawing); segment.push(p) } else if (segment.length) { that._drawSegment(segment, animationEnabled, segmentCount++); segment = [] } }); segment.length && that._drawSegment(segment, animationEnabled, segmentCount++); that._removeOldSegments(segmentCount); that._defaultSegments = that._generateDefaultSegments(); that._adjustLabels(firstDrawing); hideLayoutLabels && that.hideLabels(); animationEnabled && that._animate(firstDrawing); if (that.isSelected()) that._changeStyle(legendCallback, APPLY_SELECTED); else if (this.isHovered()) this._changeStyle(legendCallback, APPLY_HOVER) }, drawTrackers: function() { var that = this, trackers = that._trackers = that._trackers || [], trackersGroup = that._trackersGroup = that._trackersGroup || that._renderer.createGroup(), markerTrackerGroup = that._markerTrackerGroup = that._markerTrackerGroup || that._renderer.createGroup(); if (!that.isVisible()) { trackersGroup.detach(); markerTrackerGroup.detach(); return } else { trackersGroup.append(that._options.trackersGroup); markerTrackerGroup.append(that._options.markerTrackerGroup) } _each(that._segments || [], function(i, segment) { if (!trackers[i]) { trackers[i] = that._drawTrackerElement(segment).append(trackersGroup); trackers[i].data({series: that}) } else that._updateTrackerElement(segment, trackers[i]) }); _each(that.getVisiblePoints(), function(_, p) { p.drawTracker(that._renderer, markerTrackerGroup) }); that._applyTrackersClippings() }, _checkType: function(widgetType) { return !!viz.core.series.mixins[widgetType][this.type] }, _resetType: function(seriesType, widgetType) { var that = this; if (seriesType) _each(viz.core.series.mixins[widgetType][seriesType], function(methodName) { delete that[methodName] }) }, _setType: function(seriesType, widgetType) { var that = this; _each(viz.core.series.mixins[widgetType][seriesType], function(methodName, method) { that[methodName] = method }) }, _setSelectedState: function(state, mode, legendCallback) { this.lastSelectionMode = mode = (mode || this._options.selectionMode).toLowerCase(); if (state && !this.isSelected()) { this.fullState = this.fullState | SELECTED_STATE; this._changeStyle(legendCallback, APPLY_SELECTED) } else if (!state && this.isSelected()) { this.fullState = this.fullState & ~SELECTED_STATE; if (this.isHovered()) this._changeStyle(legendCallback, APPLY_HOVER); else this._changeStyle(legendCallback, "resetItem") } }, _setHoverState: function(state, mode, legendCallback) { this.lastHoverMode = mode = (mode || this._options.hoverMode).toLowerCase(); if (state && !this.isHovered()) { this.fullState = this.fullState | HOVER_STATE; !this.isSelected() && this._changeStyle(legendCallback, APPLY_HOVER) } else if (!state && this.isHovered()) { this.fullState = this.fullState & ~HOVER_STATE; !this.isSelected() && this._changeStyle(legendCallback, "resetItem") } }, setHoverState: function(mode, legendCallback) { this._setHoverState(true, mode, legendCallback) }, releaseHoverState: function(mode, legendCallback) { this._setHoverState(false, mode, legendCallback) }, setSelectedState: function(mode, legendCallback) { this._setSelectedState(true, mode, legendCallback) }, releaseSelectedState: function(mode, legendCallback) { this._setSelectedState(false, mode, legendCallback) }, isFullStackedSeries: function() { return this.type.indexOf("fullstacked") === 0 }, isStackedSeries: function() { return this.type.indexOf("stacked") === 0 }, isFinancialSeries: function() { return this.type === "stock" || this.type === "candlestick" }, _changeStyle: function(legendCallBack, legendAction) { var style = this._calcStyle(), pointStyle; if (style.mode === NONE_MODE) return; legendCallBack && legendCallBack(legendAction); if (style.mode === INCLUDE_POINTS || style.mode === ALL_SERIES_POINTS_MODE) { pointStyle = style.pointStyle; _each(this._points || [], function(_, p) { !p.isSelected() && p.applyStyle(pointStyle) }) } this._applyStyle(style.series) }, _calcStyle: function() { var styles = this._styles, isHoverIncludeModeAndSeriesExcludeMode = false, result; switch (this.fullState & 3) { case 0: result = { pointStyle: "normal", mode: INCLUDE_POINTS, series: styles.normal }; break; case 1: result = { pointStyle: "hover", mode: this.lastHoverMode, series: styles.hover }; break; case 2: result = { pointStyle: "selection", mode: this.lastSelectionMode, series: styles.selection }; break; case 3: isHoverIncludeModeAndSeriesExcludeMode = this.lastSelectionMode === EXLUDE_POINTS && (this.lastHoverMode === INCLUDE_POINTS || this.lastHoverMode === ALL_SERIES_POINTS_MODE); result = { pointStyle: isHoverIncludeModeAndSeriesExcludeMode ? "normal" : "selection", mode: isHoverIncludeModeAndSeriesExcludeMode ? INCLUDE_POINTS : this.lastSelectionMode, series: styles.selection } } return result }, _getMainAxisName: function() { return this._options.rotated ? "X" : "Y" }, areLabelsVisible: function() { return !_isDefined(this._options.maxLabelCount) || this._points.length <= this._options.maxLabelCount }, getLabelVisibility: function() { return this.areLabelsVisible() && this._options.label && this._options.label.visible }, _customizePoint: function(pointData) { var that = this, options = that._options, customizePoint = that._options.customizePoint, customizeObject, pointOptions, customLabelOptions, customOptions, customizeLabel = that._options.customizeLabel, useLabelCustomOptions, usePointCustomOptions; if (customizeLabel && customizeLabel.call) { customizeObject = _extend({ seriesName: that.name, series: that }, pointData); customLabelOptions = customizeLabel.call(customizeObject, customizeObject); useLabelCustomOptions = customLabelOptions && !_isEmptyObject(customLabelOptions); customLabelOptions = useLabelCustomOptions ? _extend(true, {}, options.label, customLabelOptions) : null } if (customizePoint && customizePoint.call) { customizeObject = customizeObject || _extend({ seriesName: that.name, series: that }, pointData); customOptions = customizePoint.call(customizeObject, customizeObject); usePointCustomOptions = customOptions && !_isEmptyObject(customOptions) } if (useLabelCustomOptions || usePointCustomOptions) { pointOptions = that._parsePointOptions(that._preparePointOptions(customOptions), customLabelOptions || options.label); pointOptions.styles.useLabelCustomOptions = useLabelCustomOptions; pointOptions.styles.usePointCustomOptions = usePointCustomOptions } return pointOptions }, _getLabelOptions: function(labelOptions, defaultColor) { var opt = labelOptions || {}, labelFont = opt.font || {}, labelBorder = opt.border || {}, labelConnector = opt.connector || {}, labelAttributes = { align: opt.alignment, font: { color: opt.backgroundColor === "none" && labelFont.color.toLowerCase() === "#ffffff" && opt.position !== "inside" ? defaultColor : labelFont.color, family: labelFont.family, weight: labelFont.weight, size: labelFont.size, opacity: labelFont.opacity }, style: opt.style }, backgroundAttr = { fill: opt.backgroundColor || defaultColor, strokeWidth: labelBorder.visible ? labelBorder.width || 0 : 0, stroke: labelBorder.visible && labelBorder.width ? labelBorder.color : "none", dashStyle: labelBorder.dashStyle }, connectorAttr = { stroke: labelConnector.visible && labelConnector.width ? labelConnector.color || defaultColor : "none", strokeWidth: labelConnector.visible ? labelConnector.width || 0 : 0 }; return { format: opt.format, argumentFormat: opt.argumentFormat, precision: opt.precision, argumentPrecision: opt.argumentPrecision, percentPrecision: opt.percentPrecision, customizeText: $.isFunction(opt.customizeText) ? opt.customizeText : undefined, attributes: labelAttributes, visible: labelFont.size !== 0 ? opt.visible : false, showForZeroValues: opt.showForZeroValues, horizontalOffset: opt.horizontalOffset, verticalOffset: opt.verticalOffset, radialOffset: opt.radialOffset, background: backgroundAttr, position: opt.position, connector: connectorAttr, rotationAngle: opt.rotationAngle, resolveLabelsOverlapping: this._options.resolveLabelsOverlapping } }, show: function() { if (!this._visible) { this._visible = true; this.hidePointTooltip(); this._options.visibilityChanged() } }, hide: function() { if (this._visible) { this._visible = false; this.hidePointTooltip(); this._options.visibilityChanged() } }, hideLabels: function() { _each(this._points, function(_, point) { point._label.hide() }) }, _parsePointOptions: function(pointOptions, labelOptions) { var options = this._options, styles = this._createPointStyles(pointOptions), parsedOptions; parsedOptions = _extend(true, {}, pointOptions, { type: options.type, tag: this.tag, rotated: options.rotated, series: this, styles: styles, visibilityChanged: options.visibilityChanged }); parsedOptions.label = this._getLabelOptions(labelOptions, styles.normal.fill); return parsedOptions }, _resample: function(ticks, ticksInterval) { var that = this, fusPoints = [], arrayFusPoints, nowIndexTicks = 0, lastPointIndex = 0, originalPoints = that.getAllPoints(); if (that.argumentAxisType === "discrete" || that.valueAxisType === "discrete") { ticksInterval = originalPoints.length / ticks; arrayFusPoints = $.map(originalPoints, function(point, index) { if (Math.floor(nowIndexTicks) <= index) { nowIndexTicks += ticksInterval; return point } point.setInvisibility(); return null }); return arrayFusPoints } that._aggregatedPoints = that._aggregatedPoints || []; _each(originalPoints, function(_, point) { switch (that._isInInterval(point.argument, ticks, nowIndexTicks, ticksInterval)) { case true: fusPoints.push(point); break; case"nextInterval": var pointData = that._fusionPoints(fusPoints, ticks[nowIndexTicks], nowIndexTicks); while (that._isInInterval(point.argument, ticks, nowIndexTicks, ticksInterval) === "nextInterval") nowIndexTicks++; fusPoints = []; that._isInInterval(point.argument, ticks, nowIndexTicks, ticksInterval) === true && fusPoints.push(point); if (that._createPoint(pointData, that._aggregatedPoints, lastPointIndex)) lastPointIndex++ } }); if (fusPoints.length) { var pointData = that._fusionPoints(fusPoints, ticks[nowIndexTicks], nowIndexTicks); if (that._createPoint(pointData, that._aggregatedPoints, lastPointIndex)) lastPointIndex++ } that._correctPointsLength(lastPointIndex, that._aggregatedPoints); that._endUpdateData(); return that._aggregatedPoints }, _isInInterval: function(argument, ticks, nowIndexTicks, ticksInterval) { var minTick = ticks[nowIndexTicks], maxTick = ticks[nowIndexTicks + 1], sumMinTickTicksInterval; ticksInterval = $.isNumeric(ticksInterval) ? ticksInterval : utils.convertDateTickIntervalToMilliseconds(ticksInterval); sumMinTickTicksInterval = utils.isDate(minTick) ? new Date(minTick.getTime() + ticksInterval) : minTick + ticksInterval; if (argument >= minTick && argument < sumMinTickTicksInterval) return true; if (argument < minTick || maxTick === undefined) return false; return "nextInterval" }, canRenderCompleteHandle: function() { var result = this._canRenderCompleteHandle; delete this._canRenderCompleteHandle; return !!result }, isHovered: function() { return !!(this.fullState & 1) }, isSelected: function() { return !!(this.fullState & 2) }, isVisible: function() { return this._visible }, getAllPoints: function() { return (this._originalPoints || []).slice() }, getPointByPos: function(pos) { return (this._points || [])[pos] }, getVisiblePoints: function() { return (this._drawedPoints || []).slice() }, setPointHoverState: function(point, legendCallback) { point.fullState = point.fullState | HOVER_STATE; if (!(this.isSelected() && (this.lastSelectionMode === ALL_SERIES_POINTS_MODE || this.lastSelectionMode === INCLUDE_POINTS)) && !point.isSelected()) { point.applyStyle("hover"); legendCallback && legendCallback("applyHover") } }, releasePointHoverState: function(point, legendCallback) { point.fullState = point.fullState & ~HOVER_STATE; if (!(this.isSelected() && (this.lastSelectionMode === ALL_SERIES_POINTS_MODE || this.lastSelectionMode === INCLUDE_POINTS)) && !point.isSelected()) if (!(this.isHovered() && (this.lastHoverMode === ALL_SERIES_POINTS_MODE || this.lastHoverMode === INCLUDE_POINTS))) { point.applyStyle("normal"); legendCallback && legendCallback("resetItem") } }, setPointSelectedState: function(point, legendCallback) { point.fullState = point.fullState | SELECTED_STATE; point.applyStyle("selection"); legendCallback && legendCallback("applySelected") }, releasePointSelectedState: function(point, legendCallback) { point.fullState = point.fullState & ~SELECTED_STATE; if (this.isHovered() && (this.lastHoverMode === ALL_SERIES_POINTS_MODE || this.lastHoverMode === INCLUDE_POINTS) || point.isHovered()) { point.applyStyle("hover"); legendCallback && legendCallback("applyHover") } else if (this.isSelected() && (this.lastSelectionMode === ALL_SERIES_POINTS_MODE || this.lastSelectionMode === INCLUDE_POINTS)) { point.applyStyle("selection"); legendCallback && legendCallback("applySelected") } else { point.applyStyle("normal"); legendCallback && legendCallback("resetItem") } }, selectPoint: function(point) { this._options.seriesGroup && this._options.seriesGroup.trigger(new _Event("selectpoint"), point) }, deselectPoint: function(point) { this._options.seriesGroup && this._options.seriesGroup.trigger(new _Event("deselectpoint"), point) }, showPointTooltip: function(point) { this._options.seriesGroup && this._options.seriesGroup.trigger(new _Event("showpointtooltip"), point) }, hidePointTooltip: function(point) { this._options.seriesGroup && this._options.seriesGroup.trigger(new _Event("hidepointtooltip"), point) }, select: function() { this._options.seriesGroup && this._options.seriesGroup.trigger(new _Event("selectseries", {target: this}), this._options.selectionMode); this._group.toForeground(); this._trackersGroup && this._trackersGroup.toBackground() }, clearSelection: function clearSelection() { this._options.seriesGroup && this._options.seriesGroup.trigger(new _Event("deselectseries", {target: this}), this._options.selectionMode) }, getPointByArg: function(arg) { return this.pointsByArgument[arg.valueOf()] || null }, _deletePoints: function() { this._disposePoints(this._originalPoints); this._disposePoints(this._aggregatedPoints); this._disposePoints(this._oldPoints); this._points = null; this._oldPoints = null; this._aggregatedPoints = null; this._originalPoints = null; this._drawedPoint = null }, _deletePatterns: function() { _each(this._patterns || [], function(_, pattern) { pattern && pattern.dispose() }); this._patterns = null }, _deleteTrackers: function() { var that = this; _each(that._trackers || [], function(_, tracker) { tracker.remove() }); that._trackersGroup && that._trackersGroup.detach(); that._markerTrackerGroup && that._markerTrackerGroup.detach(); that._trackers = that._trackersGroup = that._markerTrackerGroup = null }, dispose: function() { this._deletePoints(); this._group.detach(); this._labelsGroup && this._labelsGroup.detach(); this._deletePatterns(); this._deleteTrackers(); this._group = null; this._markersGroup = null; this._elementsGroup = null; this._bordersGroup = null; this._labelsGroup = null; this._graphics = null; this._rangeData = null; this._renderer = null; this.translators = null; this._styles = null; this._options = null; this._pointOptions = null; this._drawedPoints = null; this._aggregatedPoints = null; this.pointsByArgument = null; this._segments = null }, correctPosition: _noop, getColor: function() { return this.getLegendStyles().normal.fill }, getStackName: function() { return this.type === "stackedbar" || this.type === "fullstackedbar" ? this._stackName : null } }) })(jQuery, DevExpress); /*! Module viz-core, file rangeDataCalculator.js */ (function($, DX) { var _math = Math, _abs = _math.abs, _min = _math.min, _each = $.each, _isEmptyObject = $.isEmptyObject, _isDefined = DevExpress.utils.isDefined, FULLSTACKED_SERIES_VALUE_MARGIN_PRIORITY = 15, BAR_ZERO_VALUE_MARGIN_PRIORITY = 20, SERIES_VALUE_MARGIN_PRIORITY = 20, SERIES_LABEL_VALUE_MARGIN = 0.3, CATEGORIES_SELECTOR = "categories", INTERVAL_SELECTOR = "interval", MIN_VALUE_MARGIN_SELECTOR = "minValueMargin", MAX_VALUE_MARGIN_SELECTOR = "maxValueMargin", MIN = "min", MAX = "max", MIN_VISIBLE = "minVisible", MAX_VISIBLE = "maxVisible"; DevExpress.viz.core.series.helpers.rangeDataCalculator = function() { var _truncateValue = function(data, minField, maxField, value) { var min = data[minField], max = data[maxField]; data[minField] = value < min || !_isDefined(min) ? value : data[minField]; data[maxField] = value > max || !_isDefined(max) ? value : data[maxField] }; var _processTwoValues = function(series, point, prevPoint, highValueName, lowValueName) { var val = point[highValueName], minVal = point[lowValueName], arg = point.argument, prevVal = prevPoint && prevPoint[highValueName], prevMinVal = prevPoint && prevPoint[lowValueName], prevArg = prevPoint && prevPoint.argument; point.hasValue() && _processRangeValue(series, val, minVal, prevVal, prevMinVal); _processValue(series, "arg", arg, prevArg) }; var _processValue = function(series, type, value, prevValue, calcInterval) { var axis = type === "arg" ? "argument" : "value", data = series._rangeData[type], minInterval = data[INTERVAL_SELECTOR], interval; if (series[axis + "AxisType"] === "discrete") { data[CATEGORIES_SELECTOR] = data[CATEGORIES_SELECTOR] || []; data[CATEGORIES_SELECTOR].push(value) } else { _truncateValue(data, "min", "max", value); if (type === "arg") { interval = (_isDefined(prevValue) ? _abs(calcInterval ? calcInterval(value, prevValue) : value - prevValue) : interval) || minInterval; data[INTERVAL_SELECTOR] = _isDefined(interval) && (interval < minInterval || !_isDefined(minInterval)) ? interval : minInterval } } }; var _addToVisibleRange = function(series, value) { var data = series._rangeData.val, isDiscrete = series.valueAxisType === "discrete"; if (isDiscrete) { data.visibleCategories = data.visibleCategories || []; data.visibleCategories.push(value) } else { if (value < data.minVisible || !_isDefined(data.minVisible)) data.minVisible = value; if (value > data.maxVisible || !_isDefined(data.maxVisible)) data.maxVisible = value } }; var _processRangeValue = function(series, val, minVal, prevVal, prevMinVal) { var data = series._rangeData.val, interval, currentInterval = data[INTERVAL_SELECTOR]; if (series.valueAxisType === "discrete") { data.categories = data.categories || []; data.categories.push(val, minVal) } else { _truncateValue(data, MIN, MAX, val); _truncateValue(data, MIN, MAX, minVal) } }; var _unique = function(array) { var values = {}; return $.map(array, function(item) { var result = !values[item] ? item : null; values[item] = true; return result }) }; var _processZoomArgument = function(series, zoomArgs) { var data = series._rangeData.arg, minArg, maxArg; minArg = zoomArgs.minArg < zoomArgs.maxArg ? zoomArgs.minArg : zoomArgs.maxArg; maxArg = zoomArgs.maxArg > zoomArgs.minArg ? zoomArgs.maxArg : zoomArgs.minArg; data.min = minArg < data.min ? minArg : data.min; data.max = maxArg > data.max ? maxArg : data.max; data.minVisible = minArg; data.maxVisible = maxArg }; var _correctZoomValue = function(series, zoomArgs) { var minVal, maxVal; if (_isDefined(zoomArgs.minVal) && _isDefined(zoomArgs.maxVal)) { minVal = zoomArgs.minVal < zoomArgs.maxVal ? zoomArgs.minVal : zoomArgs.maxVal; maxVal = zoomArgs.maxVal > zoomArgs.minVal ? zoomArgs.maxVal : zoomArgs.minVal } if (_isDefined(zoomArgs.minVal)) { series._rangeData.val.min = minVal < series._rangeData.val.min ? minVal : series._rangeData.val.min; series._rangeData.val.minVisible = minVal } if (_isDefined(zoomArgs.maxVal)) { series._rangeData.val.max = maxVal > series._rangeData.val.max ? maxVal : series._rangeData.val.max; series._rangeData.val.maxVisible = maxVal } }; var _processZoomValue = function(series, zoomArgs) { var adjustOnZoom = zoomArgs.adjustOnZoom, points = series._points || [], lastVisibleIndex, prevPointAdded = false; _each(points, function(index, point) { var arg = point.argument, prevPoint = index > 0 ? points[index - 1] : null; if (adjustOnZoom && arg >= series._rangeData.arg.minVisible && arg <= series._rangeData.arg.maxVisible) { if (!prevPointAdded) { prevPoint && prevPoint.hasValue() && _addToVisibleRange(series, prevPoint.value); prevPointAdded = true } point.hasValue() && _addToVisibleRange(series, point.value); lastVisibleIndex = index } }); if (_isDefined(lastVisibleIndex) && lastVisibleIndex < points.length - 1 && points[lastVisibleIndex + 1].hasValue()) _addToVisibleRange(series, points[lastVisibleIndex + 1].value); _correctZoomValue(series, zoomArgs) }; var _processZoomRangeValue = function(series, zoomArgs, maxValueName, minValueName) { var adjustOnZoom = zoomArgs.adjustOnZoom, points = series._points || [], lastVisibleIndex, prevPointAdded = false; _each(points, function(index, point) { var arg = point.argument, prevPoint = index > 0 ? points[index - 1] : null; if (adjustOnZoom && arg >= series._rangeData.arg.minVisible && arg <= series._rangeData.arg.maxVisible) { if (!prevPointAdded) { if (prevPoint && prevPoint.hasValue()) { _addToVisibleRange(series, prevPoint[maxValueName]); _addToVisibleRange(series, prevPoint[minValueName]) } prevPointAdded = true } if (point.hasValue()) { _addToVisibleRange(series, point[maxValueName]); _addToVisibleRange(series, point[minValueName]) } lastVisibleIndex = index } }); if (_isDefined(lastVisibleIndex) && lastVisibleIndex < points.length - 1 && points[lastVisibleIndex + 1].hasValue()) _addToVisibleRange(series, points[lastVisibleIndex + 1].value); _correctZoomValue(series, zoomArgs) }; var _processNewInterval = function(series, calcInterval) { var data = series._rangeData, points = series._points || [], isArgumentAxisDiscrete = series.argumentAxisType === "discrete"; delete data.arg.interval; _each(points, function(index, point) { var arg = point.argument, prevPoint = index > 0 ? points[index - 1] : null, prevArg = prevPoint && prevPoint.argument; !isArgumentAxisDiscrete && _processValue(series, "arg", arg, prevArg, calcInterval) }) }; var _fillRangeData = function(series) { var data = series._rangeData, mainAxis = series._getMainAxisName(), axis = mainAxis === "X" ? "Y" : "X"; data.arg.categories && (data.arg.categories = _unique(data.arg.categories)); data.val.categories && (data.val.categories = _unique(data.val.categories)); data.arg.visibleCategories && (data.arg.visibleCategories = _unique(data.arg.visibleCategories)); data.val.visibleCategories && (data.val.visibleCategories = _unique(data.val.visibleCategories)); data.arg.axisType = series.argumentAxisType; data.arg.dataType = series.argumentType; data.val.axisType = series.valueAxisType; data.val.dataType = series.valueType; data.val.isValueRange = true }; var _setPadding = function(range, prefix, val, priority) { range[prefix] = val; range[prefix + "Priority"] = priority }; var _setZeroPadding = function(range, val, prefix) { val === 0 && _setPadding(range, prefix, 0, BAR_ZERO_VALUE_MARGIN_PRIORITY) }; var _calculateRangeMinValue = function(series, zoomArgs) { var data = series._rangeData.val, minVisible = data[MIN_VISIBLE], maxVisible = data[MAX_VISIBLE]; zoomArgs = zoomArgs || {}; if (data) { data.alwaysCorrectMin = true; series._rangeData.arg.keepValueMargins = true; if (series.valueAxisType !== "logarithmic" && series.valueType !== "datetime" && series.getOptions().showZero !== false) { data[MIN_VISIBLE] = minVisible > (zoomArgs.minVal || 0) ? zoomArgs.minVal || 0 : minVisible; data[MAX_VISIBLE] = maxVisible < (zoomArgs.maxVal || 0) ? zoomArgs.maxVal || 0 : maxVisible; data[MIN] = data[MIN] > 0 ? 0 : data[MIN]; _setZeroPadding(data, data[MIN], MIN_VALUE_MARGIN_SELECTOR); data[MAX] = data[MAX] < 0 ? 0 : data[MAX]; if (data[MAX] === 0 || data[MAX] > 0 && data[MIN] < 0) { data[MIN_VALUE_MARGIN_SELECTOR] = data[MAX_VALUE_MARGIN_SELECTOR]; data[MIN_VALUE_MARGIN_SELECTOR + "Priority"] = data[MAX_VALUE_MARGIN_SELECTOR + "Priority"] } _setZeroPadding(data, data[MAX], MAX_VALUE_MARGIN_SELECTOR) } } }; var _processFullStackedRange = function(series) { var data = series._rangeData.val, isRangeEmpty = _isEmptyObject(data); _setPadding(data, "minValueMargin", 0, FULLSTACKED_SERIES_VALUE_MARGIN_PRIORITY); _setPadding(data, "maxValueMargin", 0, FULLSTACKED_SERIES_VALUE_MARGIN_PRIORITY); !isRangeEmpty && (data.min = 0) }; var _processRange = function(series, point, prevPoint) { var val = point.value, arg = point.argument, prevVal = prevPoint && prevPoint.value, prevArg = prevPoint && prevPoint.argument; point.hasValue() && _processValue(series, "val", val, prevVal); _processValue(series, "arg", arg, prevArg) }; var _addLabelPaddings = function(series) { var labelOptions = series.getOptions().label; if (series.areLabelsVisible() && labelOptions && labelOptions.visible && labelOptions.position !== "inside") _setPadding(series._rangeData.val, "maxValueMargin", SERIES_LABEL_VALUE_MARGIN, SERIES_VALUE_MARGIN_PRIORITY) }; var _addRangeSeriesLabelPaddings = function(series) { var data = series._rangeData.val; if (series.areLabelsVisible() && series._options.label.visible && series._options.label.position !== "inside") { _setPadding(data, "maxValueMargin", SERIES_LABEL_VALUE_MARGIN, SERIES_VALUE_MARGIN_PRIORITY); _setPadding(data, "minValueMargin", SERIES_LABEL_VALUE_MARGIN, SERIES_VALUE_MARGIN_PRIORITY) } }; var _calculateRangeData = function(series, zoomArgs, calcIntervalFunction) { var valueData = series._rangeData.val; if (series.argumentAxisType !== "discrete" && zoomArgs && _isDefined(zoomArgs.minArg) && _isDefined(zoomArgs.maxArg)) { valueData[MIN_VISIBLE] = zoomArgs.minVal; valueData[MAX_VISIBLE] = zoomArgs.maxVal; _processZoomArgument(series, zoomArgs); _processZoomValue(series, zoomArgs) } else if (!zoomArgs && calcIntervalFunction) _processNewInterval(series, calcIntervalFunction); _fillRangeData(series) }; var _calculateTwoValuesRangeData = function(series, zoomArgs, calcIntervalFunction, maxValueName, minValueName) { var valueData = series._rangeData.val; if (series.argumentAxisType !== "discrete" && zoomArgs && _isDefined(zoomArgs.minArg) && _isDefined(zoomArgs.maxArg)) { valueData[MIN_VISIBLE] = zoomArgs.minVal; valueData[MAX_VISIBLE] = zoomArgs.maxVal; _processZoomArgument(series, zoomArgs); _processZoomRangeValue(series, zoomArgs, maxValueName, minValueName) } else if (!zoomArgs && calcIntervalFunction) _processNewInterval(series); _fillRangeData(series) }; return { processRange: _processRange, calculateRangeData: _calculateRangeData, calculateTwoValuesRangeData: _calculateTwoValuesRangeData, addLabelPaddings: _addLabelPaddings, addRangeSeriesLabelPaddings: _addRangeSeriesLabelPaddings, processFullStackedRange: _processFullStackedRange, calculateRangeMinValue: _calculateRangeMinValue, processTwoValues: _processTwoValues } } })(jQuery, DevExpress); /*! Module viz-core, file scatterSeries.js */ (function($, DX) { var viz = DX.viz, series = viz.core.series, rangeCalculator = series.helpers.rangeDataCalculator(), _each = $.each, _extend = $.extend, _map = $.map, _noop = $.noop, _isDefined = DX.utils.isDefined, _floor = Math.floor, DEFAULT_SYMBOL_POINT_SIZE = 2, DEFAULT_TRACKER_WIDTH = 20, DEFAULT_DURATION = 400; series.mixins.chart.scatter = { _defaultDuration: DEFAULT_DURATION, _defaultTrackerWidth: DEFAULT_TRACKER_WIDTH, _applyStyle: _noop, _adjustLabels: _noop, _updateOptions: _noop, _parseStyle: _noop, _prepareSegment: _noop, _drawSegment: _noop, _generateDefaultSegments: _noop, _prepareSeriesToDrawing: function() { this._deleteOldAnimationMethods(); this._firstDrawing && this._clearSeries(); this._disposePoints(this._oldPoints); this._oldPoints = null }, _applyTrackersClippings: function() { this._markerTrackerGroup.applySettings({clipId: this._forceClipping ? this._paneClipRectID : null}) }, updateTeamplateFieldNames: function() { var that = this, options = that._options; options.valueField = that.getValueFields()[0] + that.name; options.tagField = that.getTagField() + that.name }, _applyElementsClipRect: function(settings) { settings.clipId = this._paneClipRectID }, _applyMarkerClipRect: function(settings) { settings.clipId = this._forceClipping ? this._paneClipRectID : null }, _createGroup: function(groupName, parent, target, settings) { var group = parent[groupName]; if (!group) parent[groupName] = group = this._renderer.createGroup(settings); else group.applySettings(settings); group.append(target) }, _applyClearingSettings: function(settings) { settings.opacity = null; settings.scale = null; if (this._options.rotated) settings.translateX = null; else settings.translateY = null }, _createMarkerGroup: function() { var settings = this._getPointOptions().styles.normal; settings["class"] = "dxc-markers"; settings.opacity = 1; this._applyMarkerClipRect(settings); this._createGroup("_markersGroup", this, this._group, settings) }, _createLabelGroup: function() { var settings = { "class": "dxc-labels", visibility: this.getLabelVisibility() ? "visible" : "hidden" }; this._applyElementsClipRect(settings); this._applyClearingSettings(settings); this._createGroup("_labelsGroup", this, this._options.labelsGroup, settings) }, _createGroups: function(animationEnabled) { this._createMarkerGroup(); this._createLabelGroup(); animationEnabled && this._labelsGroup && this._labelsGroup.applySettings({opacity: 0.001}) }, _getCreatingPointOptions: function() { if (!this._predefinedPointOptions) { var defaultPointOptions = this._getPointOptions(), r = defaultPointOptions.styles && defaultPointOptions.styles.normal && defaultPointOptions.styles.normal.r, strokeWidth = defaultPointOptions.styles && defaultPointOptions.styles.normal && defaultPointOptions.styles.normal.strokeWidth, creatingPointOptions = _extend(true, {}, defaultPointOptions); creatingPointOptions.styles = creatingPointOptions.styles || {}; creatingPointOptions.styles.normal = { r: r, strokeWidth: strokeWidth }; this._predefinedPointOptions = creatingPointOptions } return this._predefinedPointOptions }, _getSpecialColor: function(mainSeriesColor) { return mainSeriesColor }, _getPointOptions: function() { return this._pointOptions || (this._pointOptions = this._parsePointOptions(this._preparePointOptions(), this._options.label)) }, _preparePointOptions: function(customOptions) { return customOptions ? _extend(true, {}, this._options.point, customOptions) : this._options.point }, _parsePointStyle: function(style, defaultColor, defaultBorderColor) { var border = style.border || {}; return { fill: style.color || defaultColor, stroke: border.color || defaultBorderColor, strokeWidth: border.visible ? border.width : 0, r: style.size / 2 + (border.visible && style.size !== 0 ? ~~(border.width / 2) || 0 : 0) } }, _createPointStyles: function(pointOptions) { var mainPointColor = pointOptions.color || this._options.mainSeriesColor, containerColor = this._options.containerBackgroundColor, normalStyle = this._parsePointStyle(pointOptions, mainPointColor, mainPointColor); normalStyle.visibility = pointOptions.visible ? "visible" : "hidden"; return { normal: normalStyle, hover: this._parsePointStyle(pointOptions.hoverStyle, containerColor, mainPointColor), selection: this._parsePointStyle(pointOptions.selectionStyle, containerColor, mainPointColor) } }, _checkData: function(data) { return _isDefined(data.argument) && data.value !== undefined }, _processRange: function(point, prevPoint) { rangeCalculator.processRange(this, point, prevPoint) }, _getRangeData: function(zoomArgs, calcIntervalFunction) { rangeCalculator.calculateRangeData(this, zoomArgs, calcIntervalFunction); rangeCalculator.addLabelPaddings(this); return this._rangeData }, _getPointData: function(data, options) { var argumentField = options.argumentField || "arg", valueField = options.valueField || "val", tagField = options.tagField || "tag"; return { value: data[valueField], argument: data[argumentField], tag: data[tagField] } }, _drawPoint: function(point, markersGroup, labelsGroup, animationEnabled, firstDrawing) { if (point.isInVisibleArea()) { point.clearVisibility(); point.draw(this._renderer, markersGroup, labelsGroup, animationEnabled, firstDrawing); this._drawedPoints.push(point) } else point.setInvisibility() }, _clearingAnimation: function(translators, drawComplete) { var that = this, params = {opacity: 0.001}, options = { duration: that._defaultDuration, partitionDuration: 0.5 }; that._labelsGroup && that._labelsGroup.animate(params, options, function() { that._markersGroup && that._markersGroup.animate(params, options, drawComplete) }) }, _animate: function(complete) { var that = this, lastPointIndex = that._drawedPoints.length - 1, labelAnimFunc = function() { that._labelsGroup && that._labelsGroup.animate({opacity: 1}, {duration: that._defaultDuration}) }, settings; _each(that._drawedPoints || [], function(i, p) { settings = {translate: { x: p.x, y: p.y }}; p.animate(i === lastPointIndex ? labelAnimFunc : undefined, settings) }) }, _getPointSize: function() { return this._options.point.visible ? this._options.point.size : DEFAULT_SYMBOL_POINT_SIZE }, _calcMedianValue: function(fusionPoints, valueField) { var result, allValue; allValue = _map(fusionPoints, function(point) { return point[valueField] }); allValue.sort(function(a, b) { return a - b }); result = allValue[_floor(allValue.length / 2)]; return _isDefined(result) ? result : null }, _fusionPoints: function(fusionPoints, tick, index) { var result = this._calcMedianValue(fusionPoints, "value"); return { value: result, argument: tick, tag: null, index: index, seriesName: this.name } }, _endUpdateData: function() { delete this._predefinedPointOptions }, getArgumentField: function() { return this._options.argumentField || "arg" }, getValueFields: function() { return [this._options.valueField || "val"] }, _beginUpdateData: $.noop } })(jQuery, DevExpress); /*! Module viz-core, file lineSeries.js */ (function($, DX) { var viz = DX.viz, series = viz.core.series.mixins.chart, utils = DX.utils, scatterSeries = series.scatter, _extend = $.extend, _map = $.map, _each = $.each; series.line = _extend({}, scatterSeries, { _createElementsGroup: function(elementsStyle) { var settings = _extend({"class": "dxc-elements"}, elementsStyle); this._applyElementsClipRect(settings); this._createGroup("_elementsGroup", this, this._group, settings) }, _createBordersGroup: function(borderStyle) { var settings = _extend({"class": "dxc-borders"}, borderStyle); this._applyElementsClipRect(settings); this._createGroup("_bordersGroup", this, this._group, settings) }, _applyTrackersClippings: function() { scatterSeries._applyTrackersClippings.call(this); this._trackersGroup.applySettings({clipId: this._paneClipRectID}) }, _createGroups: function(animationEnabled, style) { var style = style || this._styles.normal; this._createElementsGroup(style.elements); this._areBordersVisible() && this._createBordersGroup(style.border); scatterSeries._createGroups.call(this, animationEnabled, {}); animationEnabled && this._markersGroup && this._markersGroup.applySettings({opacity: 0.001}) }, _areBordersVisible: function() { return false }, _getDefaultSegment: function(segment) { return {line: _map(segment.line || [], function(pt) { return pt.getDefaultCoords() })} }, _prepareSegment: function(points) { return {line: points} }, _parseLineOptions: function(options, defaultColor) { return { stroke: options.color || defaultColor, strokeWidth: options.width, dashStyle: options.dashStyle || 'solid' } }, _parseStyle: function(options, defaultColor) { return {elements: this._parseLineOptions(options, defaultColor)} }, _applyStyle: function(style) { this._elementsGroup && this._elementsGroup.applySettings(style.elements); _each(this._graphics || [], function(_, graphic) { graphic.line && graphic.line.applySettings({strokeWidth: style.elements.strokeWidth}) }) }, _drawElement: function(segment, group) { return {line: this._createMainElement(segment.line, {strokeWidth: this._styles.normal.elements.strokeWidth}).append(group)} }, _removeElement: function(element) { element.line.remove() }, _generateDefaultSegments: function() { var that = this, segments = []; _each(that._segments || [], function(_, segment) { segments.push(that._getDefaultSegment(segment)) }); return segments }, _updateElement: function(element, segment, animate, animateParams, complete) { var params = {points: segment.line}; animate ? element.line.animate(params, animateParams, complete) : element.line.applySettings(params) }, _clearingAnimation: function(translator, drawComplete) { var that = this, lastIndex = that._graphics.length - 1, settings = {opacity: 0.001}, options = { duration: that._defaultDuration, partitionDuration: 0.5 }; that._labelsGroup && that._labelsGroup.animate(settings, options, function() { that._markersGroup && that._markersGroup.animate(settings, options, function() { _each(that._defaultSegments || [], function(i, segment) { that._oldUpdateElement(that._graphics[i], segment, true, {partitionDuration: 0.5}, i === lastIndex ? drawComplete : undefined) }) }) }) }, _animate: function() { var that = this, lastIndex = that._graphics.length - 1; _each(that._graphics || [], function(i, elem) { that._updateElement(elem, that._segments[i], true, {complete: i === lastIndex ? function() { that._labelsGroup && that._labelsGroup.animate({opacity: 1}, {duration: that._defaultDuration}); that._markersGroup && that._markersGroup.animate({opacity: 1}, {duration: that._defaultDuration}) } : undefined}) }) }, _drawPoint: function(point, group, labelsGroup) { scatterSeries._drawPoint.call(this, point, group, labelsGroup) }, _createMainElement: function(points, settings) { return this._renderer.createPath(points, settings) }, _drawSegment: function(points, animationEnabled, segmentCount) { var segment = this._prepareSegment(points, this._options.rotated); this._segments.push(segment); if (!this._graphics[segmentCount]) this._graphics[segmentCount] = this._drawElement(animationEnabled ? this._getDefaultSegment(segment) : segment, this._elementsGroup); else if (!animationEnabled) this._updateElement(this._graphics[segmentCount], segment) }, _getTrackerSettings: function() { return { strokeWidth: this._styles.normal.elements.strokeWidth > this._defaultTrackerWidth ? this._styles.normal.elements.strokeWidth : this._defaultTrackerWidth, fill: "none" } }, _getMainPointsFromSegment: function(segment) { return segment.line }, _drawTrackerElement: function(segment) { return this._createMainElement(this._getMainPointsFromSegment(segment), this._getTrackerSettings(segment)) }, _updateTrackerElement: function(segment, element) { var settings = this._getTrackerSettings(segment); settings.points = this._getMainPointsFromSegment(segment); element.applySettings(settings) } }); series.stepline = _extend({}, series.line, { _calculateStepLinePoints: function(points) { var segment = []; _each(points, function(i, pt) { var stepY; if (!i) { segment.push(pt); return } stepY = segment[segment.length - 1].y; if (stepY !== pt.y) { var point = utils.clone(pt); point.y = stepY; segment.push(point) } segment.push(pt) }); return segment }, _prepareSegment: function(points) { return series.line._prepareSegment(this._calculateStepLinePoints(points)) } }); series.stackedline = _extend({}, series.line, {}); series.fullstackedline = _extend({}, series.line, {_getRangeData: function(zoomArgs, calcIntervalFunction) { var rangeCalculator = viz.core.series.helpers.rangeDataCalculator(); rangeCalculator.calculateRangeData(this, zoomArgs, calcIntervalFunction); rangeCalculator.addLabelPaddings(this); rangeCalculator.processFullStackedRange(this); return this._rangeData }}); series.spline = _extend({}, series.line, { _calculateBezierPoints: function(src, rotated) { var bezierPoints = [], pointsCopy = src; var checkExtr = function(otherPointCoord, pointCoord, controlCoord) { return otherPointCoord > pointCoord && controlCoord > otherPointCoord || otherPointCoord < pointCoord && controlCoord < otherPointCoord ? otherPointCoord : controlCoord }; var clonePoint = function(point, newX, newY) { var p = utils.clone(point); p.x = newX; p.y = newY; return p }; if (pointsCopy.length !== 1) _each(pointsCopy, function(i, curPoint) { var leftControlX, leftControlY, rightControlX, rightControlY, prevPoint, nextPoint, xCur, yCur, x1, x2, y1, y2, delta, lambda = 0.5, curIsExtremum, leftPoint, rightPoint, a, b, c, xc, yc, shift; if (!i) { bezierPoints.push(curPoint); bezierPoints.push(curPoint); return } prevPoint = pointsCopy[i - 1]; if (i < pointsCopy.length - 1) { nextPoint = pointsCopy[i + 1]; xCur = curPoint.x; yCur = curPoint.y; x1 = prevPoint.x; x2 = nextPoint.x; y1 = prevPoint.y; y2 = nextPoint.y; curIsExtremum = !!(!rotated && (yCur <= prevPoint.y && yCur <= nextPoint.y || yCur >= prevPoint.y && yCur >= nextPoint.y) || rotated && (xCur <= prevPoint.x && xCur <= nextPoint.x || xCur >= prevPoint.x && xCur >= nextPoint.x)); if (curIsExtremum) if (!rotated) { rightControlY = leftControlY = yCur; rightControlX = (xCur + nextPoint.x) / 2; leftControlX = (xCur + prevPoint.x) / 2 } else { rightControlX = leftControlX = xCur; rightControlY = (yCur + nextPoint.y) / 2; leftControlY = (yCur + prevPoint.y) / 2 } else { a = y2 - y1; b = x1 - x2; c = y1 * x2 - x1 * y2; if (!rotated) { xc = xCur; yc = -1 * (a * xc + c) / b; shift = yc - yCur || 0; y1 -= shift; y2 -= shift } else { yc = yCur; xc = -1 * (b * yc + c) / a; shift = xc - xCur || 0; x1 -= shift; x2 -= shift } rightControlX = (xCur + lambda * x2) / (1 + lambda); rightControlY = (yCur + lambda * y2) / (1 + lambda); leftControlX = (xCur + lambda * x1) / (1 + lambda); leftControlY = (yCur + lambda * y1) / (1 + lambda) } if (!rotated) { leftControlY = checkExtr(prevPoint.y, yCur, leftControlY); rightControlY = checkExtr(nextPoint.y, yCur, rightControlY) } else { leftControlX = checkExtr(prevPoint.x, xCur, leftControlX); rightControlX = checkExtr(nextPoint.x, xCur, rightControlX) } leftPoint = clonePoint(curPoint, leftControlX, leftControlY); rightPoint = clonePoint(curPoint, rightControlX, rightControlY); bezierPoints.push(leftPoint, curPoint, rightPoint) } else { bezierPoints.push(curPoint, curPoint); return } }); else bezierPoints.push(pointsCopy[0]); return bezierPoints }, _prepareSegment: function(points, rotated) { return series.line._prepareSegment(this._calculateBezierPoints(points, rotated)) }, _createMainElement: function(points, settings) { return this._renderer.createBezierPath(points, settings) } }) })(jQuery, DevExpress); /*! Module viz-core, file areaSeries.js */ (function($, DX) { var viz = DX.viz, utils = DX.utils, series = viz.core.series.mixins.chart, lineSeries = series.line, _map = $.map, _extend = $.extend, HOVER_COLOR_HIGHLIGHTING = 20; series.area = _extend({}, lineSeries, { _createBorderElement: lineSeries._createMainElement, _processSinglePointsAreaSegment: function(points, rotated) { if (points.length == 1) { var p = points[0], p1 = utils.clone(p), coord = rotated ? "y" : "x"; p1[coord] += 1; return [p, p1] } return points }, _prepareSegment: function(points, rotated) { var processedPoints = this._processSinglePointsAreaSegment(points, rotated); return { line: processedPoints, area: _map(processedPoints, function(pt) { return pt.getCoords() }).concat(_map(processedPoints.slice().reverse(), function(pt) { return pt.getCoords(true) })), singlePointSegment: processedPoints !== points } }, _getSpecialColor: function(color) { return this._options._IE8 ? new DX.Color(color).highlight(HOVER_COLOR_HIGHLIGHTING) : color }, _getRangeData: function(zoomArgs, calcIntervalFunction) { var rangeCalculator = viz.core.series.helpers.rangeDataCalculator(); rangeCalculator.calculateRangeData(this, zoomArgs, calcIntervalFunction); rangeCalculator.addLabelPaddings(this); rangeCalculator.calculateRangeMinValue(this, zoomArgs); return this._rangeData }, _getDefaultSegment: function(segment) { var defaultSegment = lineSeries._getDefaultSegment(segment); defaultSegment.area = defaultSegment.line.concat(defaultSegment.line.slice().reverse()); return defaultSegment }, _updateElement: function(element, segment, animate, animateParams, complete) { var lineParams = {points: segment.line}, areaParams = {points: segment.area}, borderElement = element.line; if (animate) { borderElement && borderElement.animate(lineParams, animateParams); element.area.animate(areaParams, animateParams, complete) } else { borderElement && borderElement.applySettings(lineParams); element.area.applySettings(areaParams) } }, _removeElement: function(element) { element.line && element.line.remove(); element.area.remove() }, _drawElement: function(segment, group) { return { line: this._bordersGroup && this._createBorderElement(segment.line, {strokeWidth: this._styles.normal.border.strokeWidth}).append(this._bordersGroup), area: this._createMainElement(segment.area).append(this._elementsGroup) } }, _applyStyle: function(style) { this._elementsGroup && this._elementsGroup.applySettings(style.elements); this._bordersGroup && this._bordersGroup.applySettings(style.border); $.each(this._graphics || [], function(_, graphic) { graphic.line && graphic.line.applySettings({strokeWidth: style.border.strokeWidth}) }) }, _createPattern: function(color, hatching) { if (hatching && utils.isObject(hatching)) { var pattern = this._renderer.createPattern(color, hatching); this._patterns.push(pattern); return pattern.id } return color }, _parseStyle: function(options, defaultColor, defaultBorderColor) { var borderOptions = options.border || {}, borderStyle = lineSeries._parseLineOptions(borderOptions, defaultBorderColor); borderStyle.strokeWidth = borderOptions.visible ? borderStyle.strokeWidth : 0; return { border: borderStyle, elements: { stroke: "none", fill: this._createPattern(options.color || defaultColor, options.hatching), opacity: options.opacity } } }, _areBordersVisible: function() { var options = this._options; return options.border.visible || options.hoverStyle.border.visible || options.selectionStyle.border.visible }, _createMainElement: function(points, settings) { return this._renderer.createArea(points, settings) }, _getTrackerSettings: function(segment) { return {strokeWidth: segment.singlePointSegment ? this._defaultTrackerWidth : 0} }, _getMainPointsFromSegment: function(segment) { return segment.area } }); series.steparea = _extend({}, series.area, {_prepareSegment: function(points, rotated) { points = series.area._processSinglePointsAreaSegment(points, rotated); return series.area._prepareSegment.call(this, series.stepline._calculateStepLinePoints(points)) }}); series.splinearea = _extend({}, series.area, { _areaPointsToSplineAreaPoints: function(areaPoints) { var lastFwPoint = areaPoints[areaPoints.length / 2 - 1], firstBwPoint = areaPoints[areaPoints.length / 2]; areaPoints.splice(areaPoints.length / 2, 0, { x: lastFwPoint.x, y: lastFwPoint.y }, { x: firstBwPoint.x, y: firstBwPoint.y }); if (lastFwPoint.defaultCoords) areaPoints[areaPoints.length / 2].defaultCoords = true; if (firstBwPoint.defaultCoords) areaPoints[areaPoints.length / 2 - 1].defaultCoords = true }, _prepareSegment: function(points, rotated) { var areaSeries = series.area, processedPoints = areaSeries._processSinglePointsAreaSegment(points, rotated), areaSegment = areaSeries._prepareSegment.call(this, series.spline._calculateBezierPoints(processedPoints, rotated)); this._areaPointsToSplineAreaPoints(areaSegment.area); areaSegment.singlePointSegment = processedPoints !== points; return areaSegment }, _getDefaultSegment: function(segment) { var areaDefaultSegment = series.area._getDefaultSegment(segment); this._areaPointsToSplineAreaPoints(areaDefaultSegment.area); return areaDefaultSegment }, _createMainElement: function(points, settings) { return this._renderer.createBezierArea(points, settings) }, _createBorderElement: series.spline._createMainElement }) })(jQuery, DevExpress); /*! Module viz-core, file barSeries.js */ (function($, DX) { var viz = DX.viz, series = viz.core.series.mixins.chart, scatterSeries = series.scatter, areaSeries = series.area, _extend = $.extend, _each = $.each, DEFAULT_BAR_POINT_SIZE = 3; series.bar = _extend({}, scatterSeries, { _getSpecialColor: areaSeries._getSpecialColor, _createPattern: areaSeries._createPattern, _updateOptions: function(options) { this._stackName = "axis_" + (options.axis || "default") + "_stack_" + (options.stack || "default") }, _getRangeData: function(zoomArgs, calcIntervalFunction) { var rangeData = areaSeries._getRangeData.apply(this, arguments); rangeData.arg.stick = false; return rangeData }, _parsePointStyle: function(style, defaultColor, defaultBorderColor) { var color = this._createPattern(style.color || defaultColor, style.hatching), base = scatterSeries._parsePointStyle.call(this, style, color, defaultBorderColor); base.fill = color; base.dashStyle = style.border && style.border.dashStyle || "solid"; delete base.r; return base }, _applyMarkerClipRect: function(settings) { settings.clipId = null }, _applyTrackersClippings: function() { this._markerTrackerGroup.applySettings({clipId: this._paneClipRectID}) }, _clearingAnimation: function(translators, drawComplete) { var that = this, settings; if (that._options.rotated) settings = { scale: { x: 0.001, y: 1 }, translate: {x: translators.x.translate("canvas_position_default")} }; else settings = { scale: { x: 1, y: 0.001 }, translate: {y: translators.y.translate("canvas_position_default")} }; that._labelsGroup && that._labelsGroup.animate({opacity: 0.001}, { duration: that._defaultDuration, partitionDuration: 0.5 }, function() { that._markersGroup.animate(settings, {partitionDuration: 0.5}, function() { that._markersGroup.applySettings({ scale: null, translateX: 0, translateY: 0 }); drawComplete() }) }) }, _createGroups: function(animationEnabled, style, firstDrawing) { var settings = {}; scatterSeries._createGroups.apply(this, arguments); if (animationEnabled && firstDrawing) if (!this._options.rotated) settings = { scale: { x: 1, y: 0.001 }, translateY: this.translators.y.translate("canvas_position_default") }; else settings = { scale: { x: 0.001, y: 1 }, translateX: this.translators.x.translate("canvas_position_default") }; else if (!animationEnabled) settings = { scale: { x: 1, y: 1 }, translateX: 0, translateY: 0 }; this._markersGroup.applySettings(settings) }, _drawPoint: function(point, markersGroup, labelsGroup, animationEnabled, firstDrawing) { scatterSeries._drawPoint.call(this, point, markersGroup, labelsGroup, animationEnabled && !firstDrawing) }, _getMainColor: function() { return this._options.mainSeriesColor }, _createPointStyles: function(pointOptions) { var mainColor = pointOptions.color || this._getMainColor(), specialMainColor = this._getSpecialColor(mainColor); return { normal: this._parsePointStyle(pointOptions, mainColor, mainColor), hover: this._parsePointStyle(pointOptions.hoverStyle || {}, specialMainColor, mainColor), selection: this._parsePointStyle(pointOptions.selectionStyle || {}, specialMainColor, mainColor) } }, _preparePointOptions: function(customOptions) { return customOptions ? _extend(true, {}, this._options, customOptions) : this._options }, _animate: function(firstDrawing) { var that = this, labelAnimFunc = function() { that._labelsGroup && that._labelsGroup.animate({opacity: 1}, {duration: that._defaultDuration}) }, lastPointIndex; that._markersGroup.animate({ scale: { x: 1, y: 1 }, translate: { y: 0, x: 0 } }, undefined, labelAnimFunc); if (!firstDrawing) { lastPointIndex = that._drawedPoints.length - 1; _each(this._drawedPoints || [], function(i, point) { point.animate(i === lastPointIndex ? labelAnimFunc : undefined, { x: point.x, y: point.y, height: point.height, width: point.width }) }) } }, _getPointSize: function() { return DEFAULT_BAR_POINT_SIZE } }) })(jQuery, DevExpress); /*! Module viz-core, file rangeSeries.js */ (function($, DX) { var viz = DX.viz, series = viz.core.series.mixins.chart, _extend = $.extend, _isDefined = DX.utils.isDefined, _map = $.map, rangeCalculator = viz.core.series.helpers.rangeDataCalculator(), areaSeries = series.area; var baseRangeSeries = { _checkData: function(data) { return _isDefined(data.argument) && data.value !== undefined && data.minValue !== undefined }, updateTeamplateFieldNames: function() { var that = this, options = that._options, valueFields = that.getValueFields(), name = that.name; options.rangeValue1Field = valueFields[0] + name; options.rangeValue2Field = valueFields[1] + name; options.tagField = that.getTagField() + name }, _processRange: function(point, prevPoint) { rangeCalculator.processTwoValues(this, point, prevPoint, "value", "minValue") }, _getRangeData: function(zoomArgs, calcIntervalFunction) { rangeCalculator.calculateTwoValuesRangeData(this, zoomArgs, calcIntervalFunction, "value", "minValue"); rangeCalculator.addRangeSeriesLabelPaddings(this); return this._rangeData }, _getPointData: function(data, options) { var argumentField = options.argumentField || "arg", tagField = options.tagField || "tag", rangeValue1Field = options.rangeValue1Field || "val1", rangeValue2Field = options.rangeValue2Field || "val2"; return { tag: data[tagField], minValue: data[rangeValue1Field], value: data[rangeValue2Field], argument: data[argumentField] } }, _fusionPoints: function(fusionPoints, tick, index) { var scatterSeries = series.scatter, value = scatterSeries._calcMedianValue.call(this, fusionPoints, "value"), minValue = scatterSeries._calcMedianValue.call(this, fusionPoints, "minValue"), pointData; if (value === null || minValue === null) value = minValue = null; pointData = { minValue: minValue, value: value, argument: tick, tag: null }; return pointData }, getValueFields: function() { return [this._options.rangeValue1Field || "val1", this._options.rangeValue2Field || "val2"] } }; series.rangebar = _extend({}, series.bar, baseRangeSeries); series.rangearea = _extend({}, areaSeries, { _drawPoint: function(point, markersGroup, labelsGroup, animationEnabled) { if (point.isInVisibleArea()) { point.clearVisibility(); point.draw(this._renderer, markersGroup, labelsGroup, animationEnabled); this._drawedPoints.push(point); if (!point.visibleTopMarker) point.hideMarker("top"); if (!point.visibleBottomMarker) point.hideMarker("bottom") } else point.setInvisibility() }, _prepareSegment: function(points, rotated) { var processedPoints = this._processSinglePointsAreaSegment(points, rotated), processedMinPointsCoords = $.map(processedPoints, function(pt) { return pt.getCoords(true) }); return { line: processedPoints, bottomLine: processedMinPointsCoords, area: $.map(processedPoints, function(pt) { return pt.getCoords() }).concat(processedMinPointsCoords.slice().reverse()), singlePointSegment: processedPoints !== points } }, _getDefaultSegment: function(segment) { var defaultSegment = areaSeries._getDefaultSegment.call(this, segment); defaultSegment.bottomLine = defaultSegment.line; return defaultSegment }, _removeElement: function(element) { areaSeries._removeElement.call(this, element); element.bottomLine && element.bottomLine.remove() }, _drawElement: function(segment, group) { var drawnElement = areaSeries._drawElement.call(this, segment, group); drawnElement.bottomLine = this._bordersGroup && this._createBorderElement(segment.bottomLine, {strokeWidth: this._styles.normal.border.strokeWidth}).append(this._bordersGroup); return drawnElement }, _applyStyle: function(style) { this._elementsGroup && this._elementsGroup.applySettings(style.elements); this._bordersGroup && this._bordersGroup.applySettings(style.border); $.each(this._graphics || [], function(_, graphic) { graphic.line && graphic.line.applySettings({strokeWidth: style.border.strokeWidth}); graphic.bottomLine && graphic.bottomLine.applySettings({strokeWidth: style.border.strokeWidth}) }) }, _updateElement: function(element, segment, animate, animateParams, complete) { areaSeries._updateElement.call(this, element, segment, animate, animateParams, complete); var bottomLineParams = {points: segment.bottomLine}, bottomBorderElement = element.bottomLine; if (bottomBorderElement) animate ? bottomBorderElement.animate(bottomLineParams, animateParams) : bottomBorderElement.applySettings(bottomLineParams) } }, baseRangeSeries) })(jQuery, DevExpress); /*! Module viz-core, file bubbleSeries.js */ (function($, DX) { var viz = DX.viz, series = viz.core.series.mixins.chart, scatterSeries = series.scatter, barSeries = series.bar, _isDefined = DX.utils.isDefined, _extend = $.extend, _each = $.each; series.bubble = _extend({}, scatterSeries, { _applyTrackersClippings: barSeries._applyTrackersClippings, _getMainColor: barSeries._getMainColor, _createPointStyles: barSeries._createPointStyles, _createPattern: barSeries._createPattern, _preparePointOptions: barSeries._preparePointOptions, _getSpecialColor: barSeries._getSpecialColor, _applyMarkerClipRect: series.line._applyElementsClipRect, _parsePointStyle: function(style, defaultColor, defaultBorderColor) { var base = barSeries._parsePointStyle.call(this, style, defaultColor, defaultBorderColor); base.opacity = style.opacity; return base }, _createMarkerGroup: function() { var markersSettings = this._getPointOptions().styles.normal, groupSettings; markersSettings["class"] = "dxc-markers"; this._applyMarkerClipRect(markersSettings); groupSettings = _extend({}, markersSettings); delete groupSettings.opacity; this._createGroup("_markersGroup", this, this._group, groupSettings) }, _getCreatingPointOptions: function() { if (!this._predefinedPointOptions) { var styles, defaultPointOptions = this._getPointOptions(), strokeWidth = defaultPointOptions.styles && defaultPointOptions.styles.normal && defaultPointOptions.styles.normal.strokeWidth, r = defaultPointOptions.styles && defaultPointOptions.styles.normal && defaultPointOptions.styles.normal.r, opacity = defaultPointOptions.styles && defaultPointOptions.styles.normal && defaultPointOptions.styles.normal.opacity, creatingPointOptions = _extend(true, {}, defaultPointOptions); creatingPointOptions.styles = styles = creatingPointOptions.styles || {}; styles.normal = { strokeWidth: strokeWidth, r: r, opacity: opacity }; this._predefinedPointOptions = creatingPointOptions } return this._predefinedPointOptions }, _checkData: function(data) { return _isDefined(data.argument) && _isDefined(data.size) && data.value !== undefined }, _getPointData: function(data, options) { var pointData = scatterSeries._getPointData.call(this, data, options), sizeField = options.sizeField || "size"; pointData.size = data[sizeField]; return pointData }, _fusionPoints: function(fusionPoints, tick, index) { var medianValue = scatterSeries._calcMedianValue.call(this, fusionPoints, "value"), medianSize = scatterSeries._calcMedianValue.call(this, fusionPoints, "size"); return { size: medianSize, value: medianValue, argument: tick, tag: null } }, getValueFields: function() { return [this._options.valueField || "val", this._options.sizeField || "size"] }, updateTeamplateFieldNames: function() { var that = this, options = that._options, valueFields = that.getValueFields(), name = that.name; options.valueField = valueFields[0] + name; options.sizeField = valueFields[1] + name; options.tagField = that.getTagField() + name }, _clearingAnimation: function(translators, drawComplete) { var that = this, settings = {r: 0}, partitionDuration = 0.5, lastPointIndex = that._drawedPoints.length - 1; that._labelsGroup && that._labelsGroup.animate({opacity: 0.001}, { duration: that._defaultDuration, partitionDuration: partitionDuration }, function() { _each(that._drawedPoints || [], function(i, p) { p.animate(i === lastPointIndex ? drawComplete : undefined, settings, partitionDuration) }) }) }, _animate: function(firstDrawing) { var that = this, lastPointIndex = that._drawedPoints.length - 1, labelAnimFunc = function() { that._labelsGroup && that._labelsGroup.animate({opacity: 1}, {duration: that._defaultDuration}) }; _each(that._drawedPoints || [], function(i, p) { p.animate(i === lastPointIndex ? labelAnimFunc : undefined, { r: p.bubbleSize, translate: { x: p.x, y: p.y } }) }) } }) })(jQuery, DevExpress); /*! Module viz-core, file pieSeries.js */ (function($, DX) { var viz = DX.viz, mixins = viz.core.series.mixins, pieSeries = mixins.pieChart, utils = DX.utils, scatterSeries = mixins.chart.scatter, barSeries = mixins.chart.bar, _extend = $.extend, _each = $.each, _noop = $.noop, _map = $.map, _isFinite = isFinite, _max = Math.max; pieSeries.pie = _extend({}, barSeries, { _createLabelGroup: scatterSeries._createLabelGroup, _createGroups: scatterSeries._createGroups, _drawPoint: function(point) { scatterSeries._drawPoint.apply(this, arguments); !point.isVisible() && point.setInvisibility() }, _applyTrackersClippings: _noop, _processRange: _noop, _applyElementsClipRect: _noop, _updateDataType: _noop, getColor: _noop, _prepareSeriesToDrawing: _noop, _endUpdateData: scatterSeries._prepareSeriesToDrawing, resetLabelEllipsis: function() { _each(this._points || [], function(_, point) { point._label.setLabelEllipsis = false }) }, _adjustLabels: function(firstDrawing) { var that = this, options = that._options, canvas = that.canvas, points = that._points || [], labelsBBoxes = [], labelsSpaces = [], labelSpace = 0, maxLabelLength, paneSpaceHeight, paneSpaceWidth, min; if (options.label.position !== "inside") { _each(points, function(_, point) { if (point._label.hasText()) labelsBBoxes.push(point._label.getTextCoords().width) }); if (labelsBBoxes.length) { maxLabelLength = _max.apply(null, labelsBBoxes); _each(points, function(_, point) { if (point._label.hasText()) { point._label.updatePosition(maxLabelLength); point._label.setLabelEllipsis = true } }); that._firstDrawing = !that.redraw && firstDrawing; that.redraw = true } } else _each(points, function(i, point) { if (point._label.hasText()) { point._label.setLabelEllipsis = true; point._label.updatePosition() } }) }, _getCreatingPointOptions: function() { return this._getPointOptions() }, _updateOptions: function(options) { this.labelSpace = 0; this.innerRadius = this.type === "pie" ? 0 : options.innerRadius; this.redraw = false }, _checkData: function(data) { var base = barSeries._checkData(data); return this._options.paintNullPoints ? base : base && data.value !== null }, _createMarkerGroup: function() { if (!this._markersGroup) this._markersGroup = this._renderer.createGroup({"class": "dxc-markers"}).append(this._group) }, _getMainColor: function() { return this._options.mainSeriesColor() }, _getPointOptions: function() { return this._parsePointOptions(this._preparePointOptions(), this._options.label) }, _getRangeData: function() { return this._rangeData }, _getArrangeTotal: function(points) { var total = 0; _each(points, function(_, point) { if (point.isVisible()) total += point.initialValue }); return total }, _createPointStyles: function(pointOptions) { var mainColor = pointOptions.color || this._getMainColor(), specialMainColor = this._getSpecialColor(mainColor); return { normal: this._parsePointStyle(pointOptions, mainColor, mainColor), hover: this._parsePointStyle(pointOptions.hoverStyle, specialMainColor, mainColor), selection: this._parsePointStyle(pointOptions.selectionStyle, specialMainColor, mainColor), legendStyles: { normal: this._createLegendState(pointOptions, mainColor), hover: this._createLegendState(pointOptions.hoverStyle, specialMainColor), selection: this._createLegendState(pointOptions.selectionStyle, specialMainColor) } } }, _getArrangeMinShownValue: function(points, total) { var minSegmentSize = this._options.minSegmentSize, totalMinSegmentSize = 0, totalNotMinValues = 0; total = total || points.length; _each(points, function(_, point) { if (point.isVisible()) if (point.initialValue < minSegmentSize * total / 360) totalMinSegmentSize += minSegmentSize; else totalNotMinValues += point.initialValue }); return totalMinSegmentSize < 360 ? minSegmentSize * totalNotMinValues / (360 - totalMinSegmentSize) : 0 }, _applyArrangeCorrection: function(points, minShownValue, total) { var options = this._options, isClockWise = options.segmentsDirection !== "anticlockwise", shiftedAngle = _isFinite(options.startAngle) ? utils.normalizeAngle(options.startAngle) : 0, minSegmentSize = options.minSegmentSize, percent, correction = 0, zeroTotalCorrection = 0; if (total === 0) { total = points.length; zeroTotalCorrection = 1 } _each(isClockWise ? points : points.concat([]).reverse(), function(_, point) { var val = point.isVisible() ? zeroTotalCorrection || point.initialValue : 0, updatedZeroValue; if (minSegmentSize && point.isVisible() && val < minShownValue) updatedZeroValue = minShownValue; percent = val / total; point.correctValue(correction, percent, zeroTotalCorrection + (updatedZeroValue || 0)); point.shiftedAngle = shiftedAngle; correction = correction + (updatedZeroValue || val) }); this._rangeData = {val: { min: 0, max: correction }} }, arrangePoints: function() { var that = this, minSegmentSize = that._options.minSegmentSize, minShownValue, pointIndex = 0, total, points = that._originalPoints = that._points = _map(that._originalPoints || [], function(point) { if (point.value === null || point.value < 0 || point.value === 0 && !minSegmentSize) { point.dispose(); return null } else { point.index = pointIndex++; return point } }); total = that._getArrangeTotal(points); if (minSegmentSize) minShownValue = this._getArrangeMinShownValue(points, total); that._applyArrangeCorrection(points, minShownValue, total) }, correctPosition: function(correction) { var debug = DX.utils.debug; debug.assert(correction, "correction was not passed"); debug.assertParam(correction.centerX, "correction.centerX was not passed"); debug.assertParam(correction.centerY, "correction.centerY was not passed"); debug.assertParam(correction.radiusInner, "correction.radiusInner was not passed"); debug.assertParam(correction.radiusOuter, "correction.radiusOuter was not passed"); _each(this._points, function(_, point) { point.correctPosition(correction) }) }, _animate: function(firstDrawing) { var that = this, index = 0, timeThreshold = 0.2, points = that._points, pointsCount = points && points.length, duration = 1 / (timeThreshold * (pointsCount - 1) + 1), animateP = function() { points[index] && points[index++].animate(index === pointsCount ? completeFunc : undefined, duration, stepFunc) }, stepFunc = function(_, progress) { if (progress >= timeThreshold) { this.step = null; animateP() } }, completeFunc = function() { that._labelsGroup && that._labelsGroup.animate({opacity: 1}, {duration: 400}) }; if (firstDrawing) animateP(); else $.each(points, function(i, p) { p.animate(i == pointsCount - 1 ? completeFunc : undefined) }) }, getVisiblePoints: function() { return _map(this._points, function(p) { return p.isVisible() ? p : null }) }, _beginUpdateData: function() { this._deletePatterns(); this._patterns = [] } }); pieSeries.doughnut = pieSeries.donut = pieSeries.pie })(jQuery, DevExpress); /*! Module viz-core, file financialSeries.js */ (function($, DX) { var viz = DX.viz, series = viz.core.series.mixins.chart, scatterSeries = series.scatter, barSeries = series.bar, rangeCalculator = viz.core.series.helpers.rangeDataCalculator(), _isDefined = DX.utils.isDefined, _extend = $.extend, _each = $.each, _noop = $.noop, DEFAULT_FINANCIAL_POINT_SIZE = 10; series.stock = _extend({}, scatterSeries, { _animate: _noop, _applyMarkerClipRect: series.line._applyElementsClipRect, _applyTrackersClippings: barSeries._applyTrackersClippings, _createPattern: barSeries._createPattern, _preparePointOptions: barSeries._preparePointOptions, _createMarkerGroup: function() { var that = this, markersGroup, styles = that._getPointOptions().styles, defaultStyle = styles.normal, defaultPositiveStyle = styles.positive.normal, reductionStyle = styles.reduction.normal, reductionPositiveStyle = styles.reductionPositive.normal, markerSettings = {"class": "dxc-markers"}; that._applyMarkerClipRect(markerSettings); defaultStyle["class"] = "default-markers"; defaultPositiveStyle["class"] = "default-positive-markers"; reductionStyle["class"] = "reduction-markers"; reductionPositiveStyle["class"] = "reduction-positive-markers"; that._createGroup("_markersGroup", that, that._group, markerSettings); markersGroup = that._markersGroup; that._createGroup("defaultMarkersGroup", markersGroup, markersGroup, defaultStyle); that._createGroup("reductionMarkersGroup", markersGroup, markersGroup, reductionStyle); that._createGroup("defaultPositiveMarkersGroup", markersGroup, markersGroup, defaultPositiveStyle); that._createGroup("reductionPositiveMarkersGroup", markersGroup, markersGroup, reductionPositiveStyle) }, _createGroups: function() { scatterSeries._createGroups.call(this, false) }, _clearingAnimation: function(translators, drawComplete) { drawComplete() }, _getCreatingPointOptions: function() { if (!this._predefinedPointOptions) { var styles, defaultPointOptions = this._getPointOptions(), strokeWidth = defaultPointOptions.styles && defaultPointOptions.styles.normal && defaultPointOptions.styles.normal.strokeWidth, creatingPointOptions = _extend(true, {}, defaultPointOptions); creatingPointOptions.styles = styles = creatingPointOptions.styles || {}; styles.normal = styles.positive.normal = styles.reduction.normal = styles.reductionPositive.normal = {strokeWidth: strokeWidth}; this._predefinedPointOptions = creatingPointOptions } return this._predefinedPointOptions }, _checkData: function(data) { return _isDefined(data.argument) && data.highValue !== undefined && data.lowValue !== undefined && data.openValue !== undefined && data.closeValue !== undefined }, _processRange: function(point, prevPoint) { rangeCalculator.processTwoValues(this, point, prevPoint, "highValue", "lowValue") }, _getRangeData: function(zoomArgs, calcIntervalFunction) { rangeCalculator.calculateTwoValuesRangeData(this, zoomArgs, calcIntervalFunction, "highValue", "lowValue"); rangeCalculator.addRangeSeriesLabelPaddings(this); return this._rangeData }, _getPointData: function(data, options) { var that = this, level, argumentField = options.argumentField || "date", tagField = options.tagField || "tag", openValueField = options.openValueField || "open", closeValueField = options.closeValueField || "close", highValueField = options.highValueField || "high", lowValueField = options.lowValueField || "low", reductionValue; that.level = options.reduction.level; switch ((that.level || "").toLowerCase()) { case"open": level = openValueField; break; case"high": level = highValueField; break; case"low": level = lowValueField; break; default: level = closeValueField; that.level = "close"; break } reductionValue = data[level]; return { argument: data[argumentField], highValue: data[highValueField], lowValue: data[lowValueField], closeValue: data[closeValueField], openValue: data[openValueField], reductionValue: reductionValue, tag: data[tagField], isReduction: this._checkReduction(reductionValue) } }, _parsePointStyle: function(style, defaultColor, innerColor) { return { stroke: style.color || defaultColor, strokeWidth: style.width, fill: style.color || innerColor } }, updateTeamplateFieldNames: function() { var that = this, options = that._options, valueFields = that.getValueFields(), name = that.name; options.openValueField = valueFields[0] + name; options.highValueField = valueFields[1] + name; options.lowValueField = valueFields[2] + name; options.closeValueField = valueFields[3] + name; options.tagField = that.getTagField() + name }, _getDefaultStyle: function(options) { var mainPointColor = options.color || this._options.mainSeriesColor; return { normal: this._parsePointStyle(options, mainPointColor, mainPointColor), hover: this._parsePointStyle(options.hoverStyle, mainPointColor, mainPointColor), selection: this._parsePointStyle(options.selectionStyle, mainPointColor, mainPointColor) } }, _getReductionStyle: function(options) { var reductionColor = options.reduction.color, normalStyle = this._parsePointStyle({ color: reductionColor, width: options.width, hatching: options.hatching }, reductionColor, reductionColor); return { normal: normalStyle, hover: this._parsePointStyle(options.hoverStyle, reductionColor, reductionColor), selection: this._parsePointStyle(options.selectionStyle, reductionColor, reductionColor) } }, _createPointStyles: function(pointOptions) { var that = this, innerColor = that._options.innerColor, styles = that._getDefaultStyle(pointOptions), positiveStyle, reductionStyle, reductionPositiveStyle; positiveStyle = _extend(true, {}, styles); reductionStyle = that._getReductionStyle(pointOptions); reductionPositiveStyle = _extend(true, {}, reductionStyle); positiveStyle.normal.fill = positiveStyle.hover.fill = positiveStyle.selection.fill = innerColor; reductionPositiveStyle.normal.fill = reductionPositiveStyle.hover.fill = reductionPositiveStyle.selection.fill = innerColor; styles.positive = positiveStyle; styles.reduction = reductionStyle; styles.reductionPositive = reductionPositiveStyle; return styles }, _endUpdateData: function() { delete this.prevLevelValue; delete this._predefinedPointOptions }, _checkReduction: function(value) { var result = false; if (value != null) { if (_isDefined(this.prevLevelValue)) result = value < this.prevLevelValue; this.prevLevelValue = value } return result }, _fusionPoints: function(fusionPoints, tick, nowIndexTicks) { var fusedPointData = {}, reductionLevel, highValue = -Infinity, lowValue = +Infinity, openValue, closeValue; if (!fusionPoints.length) return {}; _each(fusionPoints, function(_, point) { if (!point.hasValue()) return; highValue = Math.max(highValue, point.highValue); lowValue = Math.min(lowValue, point.lowValue); openValue = openValue !== undefined ? openValue : point.openValue; closeValue = point.closeValue !== undefined ? point.closeValue : closeValue }); fusedPointData.argument = tick; fusedPointData.openValue = openValue; fusedPointData.closeValue = closeValue; fusedPointData.highValue = highValue; fusedPointData.lowValue = lowValue; fusedPointData.tag = null; switch ((this.level || "").toLowerCase()) { case"open": reductionLevel = openValue; break; case"high": reductionLevel = highValue; break; case"low": reductionLevel = lowValue; break; default: reductionLevel = closeValue; break } fusedPointData.reductionValue = reductionLevel; fusedPointData.isReduction = this._checkReduction(reductionLevel); return fusedPointData }, _getPointSize: function() { return DEFAULT_FINANCIAL_POINT_SIZE }, getValueFields: function() { var options = this._options; return [options.openValueField || "open", options.highValueField || "high", options.lowValueField || "low", options.closeValueField || "close"] }, getArgumentField: function() { return this._options.argumentField || "date" } }); series.candlestick = _extend({}, series.stock, {_parsePointStyle: function(style, defaultColor, innerColor) { var color = this._createPattern(style.color || innerColor, style.hatching), base = series.stock._parsePointStyle.call(this, style, defaultColor, color); base.fill = color; return base }}) })(jQuery, DevExpress); /*! Module viz-core, file stackedSeries.js */ (function($, DX) { var viz = DX.viz, series = viz.core.series.mixins.chart, areaSeries = series.area, barSeries = series.bar, lineSeries = series.line, rangeCalculator = viz.core.series.helpers.rangeDataCalculator(), _extend = $.extend, _noop = $.noop, baseStackedSeries = { _processRange: _noop, _processStackedRange: function() { var that = this, prevPoint; $.each(that.getAllPoints(), function(i, p) { rangeCalculator.processRange(that, p, prevPoint); prevPoint = p }) }, _getRangeData: function() { this._processStackedRange(); return areaSeries._getRangeData.apply(this, arguments) } }, baseFullStackedSeries = _extend({}, baseStackedSeries, { _getRangeData: function(zoomArgs, calcIntervalFunction) { this._processStackedRange(); rangeCalculator.calculateRangeData(this, zoomArgs, calcIntervalFunction); rangeCalculator.addLabelPaddings(this); rangeCalculator.processFullStackedRange(this); rangeCalculator.calculateRangeMinValue(this, zoomArgs); return this._rangeData }, isFullStackedSeries: function() { return true } }); series.stackedline = _extend({}, lineSeries, baseStackedSeries, {_getRangeData: function() { this._processStackedRange(); return lineSeries._getRangeData.apply(this, arguments) }}); series.fullstackedline = _extend({}, lineSeries, baseFullStackedSeries, {_getRangeData: function(zoomArgs, calcIntervalFunction) { this._processStackedRange(); var rangeCalculator = viz.core.series.helpers.rangeDataCalculator(); rangeCalculator.calculateRangeData(this, zoomArgs, calcIntervalFunction); rangeCalculator.addLabelPaddings(this); rangeCalculator.processFullStackedRange(this); return this._rangeData }}); series.stackedbar = _extend({}, barSeries, baseStackedSeries, {_getRangeData: function() { this._processStackedRange(); return barSeries._getRangeData.apply(this, arguments) }}); series.fullstackedbar = _extend({}, barSeries, baseFullStackedSeries, {_getRangeData: function(zoomArgs, calcIntervalFunction) { var rangeData = baseFullStackedSeries._getRangeData.apply(this, arguments); rangeData.arg.stick = false; return rangeData }}); series.stackedarea = _extend({}, areaSeries, baseStackedSeries); series.fullstackedarea = _extend({}, areaSeries, baseFullStackedSeries) })(jQuery, DevExpress); /*! Module viz-core, file basePoint.js */ (function($, DX) { var viz = DX.viz, statesConsts = viz.core.series.helpers.consts.states, _each = $.each, _extend = $.extend, _isDefined = DX.utils.isDefined, _noop = $.noop, pointTypes = { scatter: "symbolPoint", line: "symbolPoint", spline: "symbolPoint", stepline: "symbolPoint", stackedline: "symbolPoint", fullstackedline: "symbolPoint", area: "symbolPoint", splinearea: "symbolPoint", steparea: "symbolPoint", stackedarea: "symbolPoint", fullstackedarea: "symbolPoint", rangearea: "rangeSymbolPoint", bar: "barPoint", stackedbar: "barPoint", fullstackedbar: "barPoint", rangebar: "rangeBarPoint", bubble: "bubblePoint", pie: "piePoint", doughnut: "piePoint", donut: "piePoint", stock: "stockPoint", candlestick: "candlestickPoint" }; viz.core.series.points = {}; viz.core.series.points.Point = DX.Class.inherit({ ctor: function(dataItem, options) { this.update(dataItem, options); this._emptySettings = { fill: null, stroke: null, dashStyle: null } }, getColor: function() { return this._styles.normal.fill || this.series.getColor() }, _getStyle: function() { var styles = this._styles, style; if (this.isSelected()) style = styles.selection; else if (this.isHovered()) style = styles.hover; else { this.fullState = statesConsts.normalMark; style = styles.normal } return style }, update: function(dataItem, options) { this.updateOptions(options); this.updateData(dataItem) }, updateData: function(dataItem) { this._updateData(dataItem); if (!this.hasValue()) this.setInvisibility(); else { this._updateLabelData(); this._fillStyle() } }, deleteMarker: function() { this.graphic && this.graphic.detach(); this.graphic = null }, deleteTrackerMarker: function() { this.trackerGraphic && this.trackerGraphic.remove(); this.trackerGraphic = null }, draw: function(renderer, markersGroup, labelsGroup, animationEnabled, firstDrawing) { if (this._needDeletingOnDraw) { this.deleteMarker(); this.deleteTrackerMarker(); this._needDeletingOnDraw = false } if (this._needClearingOnDraw) { this.clearMarker(); this._needClearingOnDraw = false } if (!this._hasGraphic()) this._options.visible && this._drawMarker(renderer, markersGroup, animationEnabled, firstDrawing); else this._updateMarker(animationEnabled, undefined, markersGroup); this._drawLabel(renderer, labelsGroup) }, applyStyle: function(style) { if (this.graphic) { if (style === "normal") this.clearMarker(); else this.graphic.toForeground(); this._updateMarker(true, this._styles[style]) } }, setHoverState: function() { this.series.setPointHoverState(this) }, releaseHoverState: function(callback) { this.series.releasePointHoverState(this, callback); if (this.graphic) !this.isSelected() && this.graphic.toBackground() }, setSelectedState: function() { this.series.setPointSelectedState(this) }, releaseSelectedState: function() { this.series.releasePointSelectedState(this) }, select: function() { this.series.selectPoint(this) }, clearSelection: function() { this.series.deselectPoint(this) }, showTooltip: function() { this.series.showPointTooltip(this) }, hideTooltip: function() { this.series.hidePointTooltip(this) }, _checkLabelsChanging: function(oldType, newType) { if (oldType) { var isNewRange = ~newType.indexOf("range"), isOldRange = ~oldType.indexOf("range"); return isOldRange && !isNewRange || !isOldRange && isNewRange } else return false }, updateOptions: function(newOptions) { if (!_isDefined(newOptions)) return; var that = this, oldOptions = that._options, oldType = oldOptions && oldOptions.type, newType = newOptions.type; if (pointTypes[oldType] !== pointTypes[newType]) { that._needDeletingOnDraw = true; that._needClearingOnDraw = false; that._checkLabelsChanging(oldType, newType) && that.deleteLabel(); that._resetType(oldType); that._setType(newType) } else { that._needDeletingOnDraw = that._checkSymbol(oldOptions, newOptions); that._needClearingOnDraw = that._checkCustomize(oldOptions, newOptions) } that.series = newOptions.series; that._options = newOptions; that._fillStyle(); that._updateLabelOptions(pointTypes[newType]) }, translate: function(translators) { this.translators = translators || this.translators; this.translators && this.hasValue() && this._translate(this.translators) }, drawTracker: function(renderer, group) { if (!this.trackerGraphic) this._drawTrackerMarker(renderer, group); else this._updateTracker() }, _checkCustomize: function(oldOptions, newOptions) { return oldOptions.styles.usePointCustomOptions && !newOptions.styles.usePointCustomOptions }, _getCustomLabelVisibility: function() { if (this._styles.useLabelCustomOptions) return this._options.label.visible ? "visible" : "hidden" }, _getGraphicSettings: function() { return { x: this.graphic.settings.x || 0, y: this.graphic.settings.y || 0, height: this.graphic.settings.height || 0, width: this.graphic.settings.width || 0 } }, _resetType: function(type) { var that = this; if (type) _each(viz.core.series.points.mixins[pointTypes[type]], function(methodName) { delete that[methodName] }) }, _setType: function(type) { var that = this; _each(viz.core.series.points.mixins[pointTypes[type]], function(methodName, method) { that[methodName] = method }) }, _prepareStatesOptions: function() { var that = this; if (that._options.states && that._options.states.normal) that._populatePointShape(that._options.states.normal.r) }, isInVisibleArea: function() { return this.inVisibleArea }, isSelected: function() { return !!(this.fullState & statesConsts.selectedMark) }, isHovered: function() { return !!(this.fullState & statesConsts.hoverMark) }, getOptions: function() { return this._options }, animate: function(complete, settings, partitionDuration) { if (!this.graphic) { complete && complete(); return } this.graphic.animate(settings, {partitionDuration: partitionDuration}, complete) }, getCoords: function(min) { if (!min) return { x: this.x, y: this.y }; if (!this._options.rotated) return { x: this.x, y: this.minY }; return { x: this.minX, y: this.y } }, getDefaultCoords: function() { return !this._options.rotated ? { x: this.x, y: this.defaultY } : { x: this.defaultX, y: this.y } }, _calculateVisibility: function(x, y, width, height) { var that = this, visibleAreaX, visibleAreaY, rotated = that._options.rotated; if (that.translators) { visibleAreaX = that.translators.x.getCanvasVisibleArea(); visibleAreaY = that.translators.y.getCanvasVisibleArea(); if (visibleAreaX.min > x + (width || 0) || visibleAreaX.max < x || visibleAreaY.min > y + (height || 0) || visibleAreaY.max < y || rotated && _isDefined(width) && width !== 0 && (visibleAreaX.min === x + width || visibleAreaX.max === x) || !rotated && _isDefined(height) && height !== 0 && (visibleAreaY.min === y + height || visibleAreaY.max === y)) that.inVisibleArea = false; else that.inVisibleArea = true } }, correctPosition: _noop, hasValue: function() { return this.value !== null && this.minValue !== null }, _populatePointShape: _noop, _checkSymbol: _noop, hide: _noop, show: _noop, hideMarker: _noop, setInvisibility: _noop, clearVisibility: _noop, isVisible: _noop, resetCorrection: _noop, correctValue: _noop, setPercentValue: _noop, correctCoordinates: _noop, dispose: function() { this.deleteMarker(); this.deleteTrackerMarker(); this.deleteLabel(); this._options = null; this._styles = null; this.series = null; this.translators = null }, getTooltipFormatObject: function(tooltip) { var that = this, tooltipFormatObject = that._getFormatObject(tooltip), sharedTooltipValuesArray = [], tooltipStackPointsFormatObject = []; if (that.stackPoints) { _each(that.stackPoints, function(_, point) { if (!point.isVisible()) return; var formatObject = point._getFormatObject(tooltip); tooltipStackPointsFormatObject.push(point._getFormatObject(tooltip)); sharedTooltipValuesArray.push(formatObject.seriesName + ": " + formatObject.valueText) }); _extend(tooltipFormatObject, { points: tooltipStackPointsFormatObject, valueText: sharedTooltipValuesArray.join("\n"), stackName: that.stackPoints.stackName }) } return tooltipFormatObject } }) })(jQuery, DevExpress); /*! Module viz-core, file label.js */ (function($, DX) { var _isDefined = DX.utils.isDefined, _extend = $.extend, _math = Math, _round = _math.round, _floor = _math.floor, _isEmptyObject = $.isEmptyObject, _noop = $.noop, LABEL_BACKGROUND_PADDING_X = 8, LABEL_BACKGROUND_PADDING_Y = 4, LABEL_OFFSET = 10, setPositionFuncCollection = { symbolPoint: "_setPositionForSymbol", barPoint: "_setPositionForBar", bubblePoint: "_setPositionForBubble", rangeSymbolPoint: "_setPositionForSymbol", rangeBarPoint: "_setPositionForBar", stockPoint: "_setPositionForFinancial", candlestickPoint: "_setPositionForFinancial" }, checkPositionFuncCollection = { symbolPoint: "_checkPositionForSymbol", barPoint: "_checkPositionForBar", bubblePoint: "_checkPositionForSymbol", rangeSymbolPoint: "_checkPositionForSymbol", rangeBarPoint: "_checkPositionForBar", stockPoint: "_checkPositionForBar", candlestickPoint: "_checkPositionForBar" }; DX.viz.core.series.points.Label = DX.Class.inherit({ ctor: function(data, options) { this._offset = LABEL_OFFSET; this.updateData(data); this.setOptions(options) }, clearVisibility: function() { if (this._group && this._group.settings.visibility) this._group.applySettings({visibility: null}) }, hide: function() { if (this._group && this._group.settings.visibility !== "hidden") this._group.applySettings({visibility: "hidden"}) }, updateData: function(data) { if (_isDefined(data)) { this._data = data.formatObject; this._initialValue = data.initialValue } }, updateOptions: function(options) { this.setOptions(_extend(true, {}, {options: this._options}, options)) }, setOptions: function(newOptions) { var that = this, oldOptions = that._options, newOptions = newOptions || {}, pointType = newOptions.type || "symbolPoint"; that._options = newOptions.options; that._rotated = newOptions.rotated; that._isFullStacked = newOptions.isFullStacked; that._isRange = newOptions.isRange; that._setPosition = that[setPositionFuncCollection[pointType]]; that._checkPosition = that[checkPositionFuncCollection[pointType]]; if (oldOptions) { that._isBackgroundChanged(oldOptions.background, that._options.background) && that._deleteBackground(); that._isConnectorChanged(oldOptions.connector, that._options.connector) && that._deleteConnector() } }, setDataField: function(fieldName, fieldValue) { this._data = this._data || {}; this._data[fieldName] = fieldValue }, getData: function() { return this._data }, setCoords: function(coords, graphicBbox, location, visibleArea) { this._coords = coords; this._graphicBbox = graphicBbox; this._visibleArea = visibleArea; this._location = location }, hasText: function() { return !!this._text }, getTextCoords: function() { return this._text && this._text.getBBox() }, getCoords: function() { var coords = {}, insideGroup = this._insideGroup; if (insideGroup) { coords = insideGroup.getBBox(); coords.x = insideGroup.settings.translateX || 0; coords.y = insideGroup.settings.translateY || 0 } return coords }, updatePosition: function(x, y) { var settings = {}, insideGroup = this._insideGroup; insideGroup.applySettings({ translateX: x, translateY: y }); this._connector && this._drawConnector() }, _deleteElements: function() { this._deleteConnector(); this._deleteBackground(); this._deleteText(); this._deleteGroups() }, dispose: function() { this._data = null; this._options = null; this._positioningFunction = null; this._graphicBbox = null; this._visibleArea = null; this._coords = null; this._deleteElements() }, _deleteText: function() { this._text && this._text.detach(); this._text = null }, _deleteGroups: function() { this._insideGroup = null; this._group && this._group.detach(); this._group = null }, _drawGroups: function(renderer, group) { if (!this._group) this._group = renderer.createGroup().append(group); if (!this._insideGroup) this._insideGroup = renderer.createGroup().append(this._group) }, _drawText: function(renderer, text) { if (!this._text) this._text = renderer.createText(text, 0, 0, this._options.attributes).append(this._insideGroup); else this._text.applySettings({text: text}, this._options.attributes) }, _drawBackground: function(renderer) { var that = this, options = that._options, background = options.background || {}, settings; if (that._checkBackground(background)) { settings = _extend(that._getBackgroundSettings(), background); if (!that._background) that._background = renderer.createRect(settings.x, settings.y, settings.width, settings.height, 0, background).append(that._insideGroup); else that._background.applySettings(settings); that._background.toBackground() } }, _drawConnector: function(renderer) { var that = this, connector = that._options.connector || {}, points; if (that._checkConnector(connector)) { points = that._getConnectorPoints() || []; if (!that._connector) that._connector = renderer.createPath(points, connector).append(that._group); else that._connector.applySettings(_extend({points: points}, connector)); that._connector.toBackground() } }, _setVisibility: function(visibility) { this._group && this._group.applySettings({visibility: visibility}) }, draw: function(renderer, group, visibility) { var that = this, options = that._options, background = options.background, text = that._format(); if (_isDefined(text) && text !== "") { that._drawGroups(renderer, group); that._setVisibility(visibility); that._drawText(renderer, text); that._drawBackground(renderer); that._rotateLabel(); that._setPosition(); that._drawConnector(renderer) } else that._setVisibility("hidden") }, _deleteBackground: function() { this._background && this._background.detach(); this._background = null }, _isBackgroundChanged: function(oldBackground, newBackground) { return this._checkBackground(oldBackground || {}) !== this._checkBackground(newBackground || {}) }, _checkBackground: function(background) { var hasColor = background.fill && background.fill !== "none", hasBorder = background.strokeWidth && background.stroke && background.stroke !== "none"; return hasColor || hasBorder }, _getBackgroundSettings: function() { var bbox = this._text.getBBox(); return { x: bbox.x - LABEL_BACKGROUND_PADDING_X, y: bbox.y - LABEL_BACKGROUND_PADDING_Y, width: bbox.width + 2 * LABEL_BACKGROUND_PADDING_X, height: bbox.height + 2 * LABEL_BACKGROUND_PADDING_Y } }, _deleteConnector: function() { this._connector && this._connector.detach(); this._connector = null }, _isConnectorChanged: function(oldConnector, newConnector) { return this._checkConnector(oldConnector || {}) !== this._checkConnector(newConnector || {}) }, _checkConnector: function(connector) { return connector && connector.strokeWidth }, _getConnectorPoints: function() { var that = this, rotated = that._rotated, labelBbox = that._insideGroup.getBBox(), graphicBbox = that._graphicBbox, centerLabelY, centerLabelX, rightLabelCoord, bottomLabelCoord, x1, x2, y1, y2; labelBbox.x += that._insideGroup.settings.translateX || 0; labelBbox.y += that._insideGroup.settings.translateY || 0; centerLabelY = that._background ? labelBbox.y + labelBbox.height / 2 : null; centerLabelX = that._background ? labelBbox.x + labelBbox.width / 2 : null, rightLabelCoord = labelBbox.x + labelBbox.width; bottomLabelCoord = labelBbox.y + labelBbox.height; x1 = _floor(labelBbox.x + labelBbox.width / 2); x2 = _floor(graphicBbox.x + graphicBbox.width / 2); if (bottomLabelCoord < graphicBbox.y) { y1 = centerLabelY || bottomLabelCoord; y2 = graphicBbox.y } else if (labelBbox.y > graphicBbox.y + graphicBbox.height) { y1 = centerLabelY || labelBbox.y; y2 = graphicBbox.y + graphicBbox.height } else { if (labelBbox.x > graphicBbox.x + graphicBbox.width) { x1 = centerLabelX || labelBbox.x; x2 = graphicBbox.x + graphicBbox.width } else if (rightLabelCoord < graphicBbox.x) { x1 = centerLabelX || rightLabelCoord; x2 = graphicBbox.x } else return; y1 = _floor(labelBbox.y + labelBbox.height / 2); y2 = _floor(graphicBbox.y + graphicBbox.height / 2) } return [{ x: x1, y: y1 }, { x: x2, y: y2 }] }, _rotateLabel: function() { var bbox = this._insideGroup.getBBox(); this._insideGroup.rotate(this._options.rotationAngle) }, _format: function() { var that = this, data = that._data, options = that._options, formatHelper = DX.formatHelper; data.valueText = formatHelper.format(data.value, options.format, options.precision); data.argumentText = formatHelper.format(data.argument, options.argumentFormat, options.argumentPrecision); if (data.percent !== undefined) data.percentText = formatHelper.format(data.percent, "percent", options.percentPrecision); if (data.total !== undefined) data.totalText = formatHelper.format(data.total, options.format, options.precision); if (data.openValue !== undefined) data.openValueText = formatHelper.format(data.openValue, options.format, options.precision); if (data.closeValue !== undefined) data.closeValueText = formatHelper.format(data.closeValue, options.format, options.precision); if (data.lowValue !== undefined) data.lowValueText = formatHelper.format(data.lowValue, options.format, options.precision); if (data.highValue !== undefined) data.highValueText = formatHelper.format(data.highValue, options.format, options.precision); if (data.reductionValue !== undefined) data.reductionValueText = formatHelper.format(data.reductionValue, options.format, options.precision); return options.customizeText ? options.customizeText.call(data, data) : data.valueText }, _getOutsideLabelCoords: function(labelBbox) { var graphicBbox = this._graphicBbox, x = 0, y = 0, isTop = this._location === "top"; if (!this._rotated) { x += graphicBbox.width / 2 + graphicBbox.x; if (isTop) y += graphicBbox.y - labelBbox.y - labelBbox.height - this._offset; else y += graphicBbox.y + graphicBbox.height - labelBbox.y + this._offset } else { y += graphicBbox.y - labelBbox.y - labelBbox.height / 2 + graphicBbox.height / 2; if (isTop) x += graphicBbox.x + graphicBbox.width - labelBbox.x + this._offset; else x += graphicBbox.x - labelBbox.x - labelBbox.width - this._offset } return { x: x, y: y } }, _getInsideLabelCoords: function(labelBbox) { var graphicBbox = this._graphicBbox, isTop = this._location === "top", x = 0, y = 0; if (!this._isRange) if (!this._rotated) { x += graphicBbox.width / 2 + graphicBbox.x; y += graphicBbox.y - labelBbox.y - labelBbox.height / 2 + graphicBbox.height / 2 } else { y += graphicBbox.y - labelBbox.y - labelBbox.height / 2 + graphicBbox.height / 2; x += graphicBbox.x - labelBbox.x - labelBbox.width / 2 + graphicBbox.width / 2 } else if (!this._rotated) { x += graphicBbox.width / 2 + graphicBbox.x; if (isTop) y += graphicBbox.y - labelBbox.y - labelBbox.height + this._offset + labelBbox.height; else y += graphicBbox.y + graphicBbox.height - labelBbox.y - this._offset - labelBbox.height } else { y += graphicBbox.y - labelBbox.y - labelBbox.height / 2 + graphicBbox.height / 2; if (isTop) x += graphicBbox.x + graphicBbox.width - labelBbox.x - labelBbox.width - this._offset; else x += graphicBbox.x - labelBbox.x + this._offset } return { x: x, y: y } }, _getFullstackedLabelCoords: function(labelBbox) { var x = 0, y = 0, graphicBbox = this._graphicBbox; if (!this._rotated) { x += graphicBbox.width / 2 + graphicBbox.x; y += this._coords.defaultY - labelBbox.y - labelBbox.height - this._offset } else { y += graphicBbox.y - labelBbox.y - labelBbox.height / 2 + graphicBbox.height / 2; x += this._coords.defaultX - labelBbox.x + this._offset } return { x: x, y: y } }, _setPositionForSymbol: function() { var that = this, offset = that._offset, labelBBox = that._insideGroup.getBBox(), graphicBbox = that._graphicBbox, isTop = that._location === "top", correctionY = 0, correctionX = 0, x = 0, y = 0; if (!that._rotated) { correctionX = that._coords.x; correctionY = isTop ? -labelBBox.y - labelBBox.height - offset : graphicBbox.height - labelBBox.y + offset; correctionY += graphicBbox.y } else { correctionY = graphicBbox.y - labelBBox.y - labelBBox.height / 2 + graphicBbox.height / 2; correctionX = isTop ? graphicBbox.width - labelBBox.x + offset : -labelBBox.x - labelBBox.width - offset; correctionX += graphicBbox.x } x += correctionX + that._options.horizontalOffset; y += correctionY + that._options.verticalOffset; that._checkPosition({ x: labelBBox.x + x, y: labelBBox.y + y, height: labelBBox.height, width: labelBBox.width }, x, y) }, _checkPositionForSymbol: function(labelBbox, x, y) { var that = this, graphicBbox = that._graphicBbox, visibleArea = that._visibleArea, offset = that._offset; if (!that._rotated) { if (visibleArea.minX <= graphicBbox.x + graphicBbox.width && visibleArea.maxX >= graphicBbox.x) { if (visibleArea.minX > labelBbox.x && that.adjustSeriesLabels) x += visibleArea.minX - labelBbox.x; if (visibleArea.maxX < labelBbox.x + labelBbox.width && that.adjustSeriesLabels) x -= labelBbox.x + labelBbox.width - visibleArea.maxX; if (visibleArea.minY > labelBbox.y) y += graphicBbox.y + graphicBbox.height - labelBbox.y + offset; if (visibleArea.maxY < labelBbox.y + labelBbox.height) y -= labelBbox.y + labelBbox.height - graphicBbox.y + offset } } else if (visibleArea.minY <= graphicBbox.y + graphicBbox.height && visibleArea.maxY >= graphicBbox.y) { if (visibleArea.minX > labelBbox.x) x += graphicBbox.x + graphicBbox.width - labelBbox.x + offset; if (visibleArea.maxX < labelBbox.x + labelBbox.width) x -= labelBbox.x + labelBbox.width - graphicBbox.x + offset; if (visibleArea.minY > graphicBbox.y && that.adjustSeriesLabels) y += visibleArea.minY - labelBbox.y; if (visibleArea.maxY < labelBbox.y + labelBbox.height && that.adjustSeriesLabels) y -= labelBbox.y + labelBbox.height - visibleArea.maxY } that._insideGroup.applySettings({ translateX: _round(x), translateY: _round(y) }) }, _setPositionForBar: function() { var that = this, offset = that._offset, labelPosition = that._options.position, labelBbox = that._insideGroup.getBBox(), coords; if (that._initialValue === 0 && that._isFullStacked) coords = that._getFullstackedLabelCoords(labelBbox); else if (labelPosition === "inside") coords = that._getInsideLabelCoords(labelBbox); else coords = that._getOutsideLabelCoords(labelBbox); coords.x += that._options.horizontalOffset; coords.y += that._options.verticalOffset; that._checkPosition({ x: labelBbox.x + coords.x, y: labelBbox.y + coords.y, height: labelBbox.height, width: labelBbox.width }, coords.x, coords.y) }, _checkPositionForBar: function(labelBbox, x, y) { var that = this, graphicBbox = that._graphicBbox, visibleArea = that._visibleArea; if (visibleArea.minX <= graphicBbox.x + graphicBbox.width && visibleArea.maxX >= graphicBbox.x && visibleArea.minY <= graphicBbox.y + graphicBbox.height && visibleArea.maxY >= graphicBbox.y) if (!that._rotated) { if (visibleArea.minX > labelBbox.x && that.adjustSeriesLabels) x += visibleArea.minX - labelBbox.x; if (visibleArea.maxX < labelBbox.x + labelBbox.width && that.adjustSeriesLabels) x -= labelBbox.x + labelBbox.width - visibleArea.maxX; if (visibleArea.minY > labelBbox.y) y += visibleArea.minY - labelBbox.y; if (visibleArea.maxY < labelBbox.y + labelBbox.height) y -= labelBbox.y + labelBbox.height - visibleArea.maxY } else { if (visibleArea.minX > labelBbox.x) x += visibleArea.minX - labelBbox.x; if (visibleArea.maxX < labelBbox.x + labelBbox.width) x -= labelBbox.x + labelBbox.width - visibleArea.maxX; if (visibleArea.minY > labelBbox.y && that.adjustSeriesLabels) y += visibleArea.minY - labelBbox.y; if (visibleArea.maxY < labelBbox.y + labelBbox.height && that.adjustSeriesLabels) y -= labelBbox.y + labelBbox.height - visibleArea.maxY } if (that._options.resolveLabelsOverlapping && that._options.position === "inside") if (that._rotated) { if (labelBbox.width > graphicBbox.width || labelBbox.height > graphicBbox.height) { that.hide(); return } } else if (labelBbox.height > graphicBbox.height || labelBbox.width > graphicBbox.width) { that.hide(); return } that._insideGroup.applySettings({ translateX: _round(x), translateY: _round(y) }) }, _setPositionForBubble: function() { var that = this, labelBbox = that._insideGroup.getBBox(), graphicBbox = that._graphicBbox, x = 0, y = 0; if (that._options.position === "inside") { x = that._coords.x; y += graphicBbox.y + graphicBbox.height / 2 - labelBbox.y - labelBbox.height / 2; x += that._options.horizontalOffset; y += that._options.verticalOffset; that._checkPosition({ x: labelBbox.x + x, y: labelBbox.y + y, height: labelBbox.height, width: labelBbox.width }, x, y) } else that._setPositionForSymbol() }, _setPositionForFinancial: function() { var that = this, offset = that._offset, labelBbox = that._insideGroup.getBBox(), coords; coords = that._getOutsideLabelCoords(labelBbox); coords.x += that._options.horizontalOffset; coords.y += that._options.verticalOffset; that._checkPosition({ x: labelBbox.x + coords.x, y: labelBbox.y + coords.y, height: labelBbox.height, width: labelBbox.width }, coords.x, coords.y) } }) })(jQuery, DevExpress); /*! Module viz-core, file pieLabel.js */ (function($, DX) { var getCosAndSin = DX.utils.getCosAndSin, _extend = $.extend, _math = Math, _round = _math.round, _max = _math.max, _inArray = $.inArray, _isDefined = DX.utils.isDefined, INDENT_FROM_PIE = 30, CONNECTOR_LENGTH = 20; DX.viz.core.series.points.PieLabel = DX.viz.core.series.points.Label.inherit({ ctor: function(data, options) { this.setLabelEllipsis = false; this.indentFromPie = INDENT_FROM_PIE; this.updateData(data); this.setOptions(options) }, updateData: function(data) { if (_isDefined(data)) this._data = data.formatObject }, setOptions: function(newOptions) { var that = this, oldOptions = that._options, newOptions = newOptions || {}; that._options = newOptions.options; that._borderWidth = newOptions.borderWidth; if (oldOptions) { that._isBackgroundChanged(oldOptions.background, that._options.background) && that._deleteBackground(); that._isConnectorChanged(oldOptions.connector, that._options.connector) && that._deleteConnector() } }, setCoords: function(coords, canvas) { this._middleAngle = coords.middleAngle; this._radiusOuter = coords.radiusOuter; this._centerX = coords.centerX; this._centerY = coords.centerY; this._canvas = canvas }, updatePosition: function(maxLabelLength) { this._setPosition(maxLabelLength); this._checkEllipsis(); this._drawBackground(); this._rotateLabel(); this._checkPosition(); this._connector && this._drawConnector() }, dispose: function() { this._data = null; this._options = null; this._canvas = null; this._deleteElements() }, draw: function(renderer, group, visibility) { var that = this, options = that._options, background = options.background, text = that._format(); if (_isDefined(text) && text !== "") { that._drawGroups(renderer, group); that._setVisibility(visibility); that._drawText(renderer, text); that._setPosition(); that._checkEllipsis(); that._drawBackground(renderer); that._rotateLabel(); that._checkPosition(); that._drawConnector(renderer) } else that._setVisibility("hidden") }, _getOutsideGroupLabelPosition: function() { this._deleteConnector(); return this._group && this._group.getBBox() }, _setPosition: function(maxLabelLength) { var that = this, bbox = that._text.getBBox(), options = that._options, angleFunctions = getCosAndSin(that._middleAngle), align = "center", rad = that._radiusOuter + options.radialOffset, canvas = that._canvas, rightBorderX = canvas.width - canvas.right, leftBorderX = canvas.left, x, y; if (options.position === 'inside') { rad -= that.indentFromPie; x = that._centerX + rad * angleFunctions.cos } else if (options.position === 'columns') { rad += CONNECTOR_LENGTH; if (angleFunctions.cos >= 0) { align = "right"; x = maxLabelLength ? that._centerX + rad + maxLabelLength : rightBorderX; x = x > rightBorderX ? rightBorderX : x } else if (angleFunctions.cos < 0) { align = "left"; x = maxLabelLength ? that._centerX - rad - maxLabelLength : leftBorderX; x = x < leftBorderX ? leftBorderX : x } } else { rad += that.indentFromPie; if (angleFunctions.cos > 0.1) align = "left"; else if (angleFunctions.cos < -0.1) align = "right"; x = that._centerX + rad * angleFunctions.cos } y = _round(that._text.settings.y + that._centerY - rad * angleFunctions.sin - bbox.y - bbox.height / 2); that._text.applySettings({ x: x, y: y, align: align }) }, _getConnectorPoints: function() { var that = this, options = that._options, position = options.position, angleFunctions, rad = that._radiusOuter, box, x, y, points = []; if (position !== "inside") { angleFunctions = getCosAndSin(_round(that._middleAngle)); points.push({ x: _round(that._centerX + (rad - that._borderWidth) * angleFunctions.cos), y: _round(that._centerY - (rad - that._borderWidth) * angleFunctions.sin) }); x = _round(that._centerX + (rad + options.radialOffset + CONNECTOR_LENGTH) * angleFunctions.cos); if (position === "columns") { box = that._insideGroup.getBBox(); box.x = box.x + (that._insideGroup.settings.translateX || 0); box.y = box.y + (that._insideGroup.settings.translateY || 0); y = box.y + box.height / 2; points.push({ x: x, y: y }); if (that._background) x = box.x + box.width / 2; else if (angleFunctions.cos < 0) x = box.x + box.width; else if (angleFunctions.cos > 0) x = box.x; points.push({ x: x, y: y }) } else { y = _round(that._centerY - (rad + options.radialOffset + CONNECTOR_LENGTH) * angleFunctions.sin); points.push({ x: x, y: y }) } } return points }, _rotateLabel: function() { var that = this, options = that._options, shift = that._radiusOuter + options.radialOffset * 2 + CONNECTOR_LENGTH, angleFunctions = getCosAndSin(that._middleAngle), x, y, box = that._insideGroup.getBBox(); if (options.position === "inside" || options.position === "columns") { x = box.x + box.width / 2; y = box.y + box.height / 2 } else { x = that._centerX + shift * angleFunctions.cos; y = that._centerY - shift * angleFunctions.sin } that._insideGroup.applySettings({ x: x, y: y, rotate: options.rotationAngle }) }, _checkEllipsis: function() { var that = this, i, LABEL_OFFSET = 10, labelBox, text, textLength = 0, linesLength = [], numLastSpan = [], maxLength, numSpan, index, x, y, width, rotationAngleFunction = getCosAndSin(that._options.rotationAngle), canvas = that._canvas, labelOptions = that._options, angleFunctions = getCosAndSin(that._middleAngle), borderX = that._centerX + (that._radiusOuter + CONNECTOR_LENGTH) * angleFunctions.cos; if (!that._text.tspans || !that.setLabelEllipsis) return; labelBox = that._text.getBBox(); x = labelBox.x + labelBox.width < that._centerX ? labelBox.x + labelBox.width : labelBox.x; y = labelBox.y + labelBox.height / 2; width = labelBox.x + labelBox.width < that._centerX ? -labelBox.width : labelBox.width; if (y + width * rotationAngleFunction.sin > canvas.height - canvas.bottom + LABEL_OFFSET || y + width * rotationAngleFunction.sin < canvas.top - LABEL_OFFSET || x + width * rotationAngleFunction.cos < canvas.left - LABEL_OFFSET || x + width * rotationAngleFunction.cos > canvas.width - canvas.right + LABEL_OFFSET || labelOptions.position === "columns" && (angleFunctions.cos < 0 && borderX < x || angleFunctions.cos > 0 && borderX > x)) for (i = 0; i < that._text.tspans.length; i++) { textLength += that._text.tspans[i].element.getNumberOfChars(); if (!that._text.tspans[i + 1] || that._text.tspans[i + 1].settings.dy > 0) { linesLength.push(textLength); numLastSpan.push(i); textLength = 0 } } while (y + width * rotationAngleFunction.sin > canvas.height - canvas.bottom + LABEL_OFFSET || y + width * rotationAngleFunction.sin < canvas.top - LABEL_OFFSET || x + width * rotationAngleFunction.cos < canvas.left - LABEL_OFFSET || x + width * rotationAngleFunction.cos > canvas.width - canvas.right + LABEL_OFFSET || labelOptions.position === "columns" && (angleFunctions.cos < 0 && borderX < x || angleFunctions.cos > 0 && borderX > x)) { maxLength = _max.apply(null, linesLength); if (maxLength === 0) break; index = _inArray(maxLength, linesLength); numSpan = numLastSpan[index]; if (that._text.tspans[numSpan].element.textContent === "...") { if (that._text.tspans[numSpan].settings.dy > 0 || !that._text.tspans[numSpan - 1]) linesLength[index] = 0; else if (that._text.tspans[numSpan - 1]) { that._text.tspans[numSpan].element.textContent = ""; numLastSpan[index] -= 1; that._text.tspans[numSpan - 1].element.textContent += "..." } } else { text = that._text.tspans[numSpan].element.textContent; text = text.substr(0, text.length - 1 - 3) + "..."; that._text.tspans[numSpan].element.textContent = text; linesLength[index] -= 1 } labelBox = that._text.getBBox(); x = labelBox.x + labelBox.width < that._centerX ? labelBox.x + labelBox.width : labelBox.x; y = labelBox.y + labelBox.height / 2; width = labelBox.x + labelBox.width < that._centerX ? -labelBox.width : labelBox.width } }, _checkPosition: function() { var that = this, group = that._insideGroup, box = group.getBBox(), canvas = that._canvas, x = 0, y = 0; if (box.y + box.height > canvas.height - canvas.bottom) y = canvas.height - box.y - box.height - canvas.bottom; else if (box.y < canvas.top) y = canvas.top - box.y; if (box.x + box.width > canvas.width - canvas.right) x = canvas.width - canvas.right - box.x - box.width; else if (box.x < canvas.left) x = canvas.left - box.x; group.applySettings({ translateX: x, translateY: y }) }, setPosition: function(position) { this._options.position = position }, getPosition: function() { return this._options.position } }) })(jQuery, DevExpress); /*! Module viz-core, file symbolPoint.js */ (function($, DX) { var viz = DevExpress.viz, core = viz.core, series = core.series, _extend = $.extend, _each = $.each, _isNumber = DX.utils.isNumber, _isDefined = DX.utils.isDefined, _isEmptyObject = $.isEmptyObject, _math = Math, _round = _math.round, _floor = _math.floor, _ceil = _math.ceil, DEFAULT_IMAGE_WIDTH = 20, DEFAULT_IMAGE_HEIGHT = 20, CANVAS_POSITION_DEFAULT = "canvas_position_default"; series.points.mixins = series.points.mixins || {}; series.points.mixins.symbolPoint = { deleteLabel: function() { this._label.dispose(); this._label = null }, _hasGraphic: function() { return this.graphic }, _clearTrackerVisibility: function() { if (this.trackerGraphic && this.trackerGraphic.settings.visibility) this.trackerGraphic.applySettings({visibility: null}) }, clearVisibility: function() { if (this.graphic && this.graphic.settings.visibility) this.graphic.applySettings({visibility: null}); this._clearTrackerVisibility(); this._label.clearVisibility() }, isVisible: function() { return this.inVisibleArea && this.series.isVisible() }, _setTrackerInvisibility: function() { if (this.trackerGraphic && this.trackerGraphic.settings.visibility !== "hidden") this.trackerGraphic.applySettings({visibility: "hidden"}) }, setInvisibility: function() { if (this.graphic && this.graphic.settings.visibility !== "hidden") this.graphic.applySettings({visibility: "hidden"}); this._setTrackerInvisibility(); this._label.hide() }, clearMarker: function() { this.graphic && this.graphic.applySettings(this._emptySettings) }, setAdjustSeriesLabels: function(adjustSeriesLabels) { this._label.adjustSeriesLabels = adjustSeriesLabels }, _getLabelOptions: function(type) { var options = this._options; return { options: options.label, rotated: options.rotated, type: type, isFullStacked: options.series.isFullStackedSeries(), isRange: options.type.indexOf("range") !== -1 } }, _createLabel: function() { this._label = core.CoreFactory.createLabel(this._options.type) }, _updateLabelData: function() { this._label.updateData({ formatObject: this._getLabelFormatObject(), initialValue: this.initialValue }) }, _updateLabelOptions: function(type) { !this._label && this._createLabel(); this._label.setOptions(this._getLabelOptions(type)) }, _checkImage: function(image) { return _isDefined(image) && (typeof image === "string" || _isDefined(image.url)) }, _fillStyle: function() { this._styles = this._options.styles }, _checkSymbol: function(oldOptions, newOptions) { var oldSymbol = oldOptions.symbol, newSymbol = newOptions.symbol, symbolChanged = oldSymbol === "circle" && newSymbol !== "circle" || oldSymbol !== "circle" && newSymbol === "circle", imageChanged = this._checkImage(oldOptions.image) !== this._checkImage(newOptions.image); if (symbolChanged || imageChanged) return true; return false }, _getSquareMarkerCoords: function(radius) { return [{ x: -radius, y: -radius }, { x: radius, y: -radius }, { x: radius, y: radius }, { x: -radius, y: radius }, { x: -radius, y: -radius }] }, _getPolygonMarkerCoords: function(radius) { var r = _ceil(radius); return [{ x: -r, y: 0 }, { x: 0, y: -r }, { x: r, y: 0 }, { x: 0, y: r }, { x: -r, y: 0 }] }, _getTriangleMarkerCoords: function(radius) { return [{ x: -radius, y: -radius }, { x: radius, y: -radius }, { x: 0, y: radius }, { x: -radius, y: -radius }] }, _getCrossMarkerCoords: function(radius) { var r = _ceil(radius), floorHalfRadius = _floor(r / 2), ceilHalfRadius = _ceil(r / 2); return [{ x: -r, y: -floorHalfRadius }, { x: -floorHalfRadius, y: -r }, { x: 0, y: -ceilHalfRadius }, { x: floorHalfRadius, y: -r }, { x: r, y: -floorHalfRadius }, { x: ceilHalfRadius, y: 0 }, { x: r, y: floorHalfRadius }, { x: floorHalfRadius, y: r }, { x: 0, y: ceilHalfRadius }, { x: -floorHalfRadius, y: r }, { x: -r, y: floorHalfRadius }, { x: -ceilHalfRadius, y: 0 }] }, _populatePointShape: function(symbol, radius) { switch (symbol) { case"square": return this._getSquareMarkerCoords(radius); case"polygon": return this._getPolygonMarkerCoords(radius); case"triangle": return this._getTriangleMarkerCoords(radius); case"cross": return this._getCrossMarkerCoords(radius) } }, correctValue: function(correction) { if (this.hasValue()) { this.value = this.initialValue + correction; this.minValue = correction; this.translate() } }, resetCorrection: function() { this.value = this.initialValue; this.minValue = CANVAS_POSITION_DEFAULT }, _getTranslates: function(animationEnabled) { var translateX, translateY; translateX = this.x; translateY = this.y; if (animationEnabled) if (this._options.rotated) translateX = this.defaultX; else translateY = this.defaultY; return { x: translateX, y: translateY } }, _createImageMarker: function(renderer, settings, options) { var url, width, height, offsetY, attr = { location: "center", translateX: settings.attr.translateX, translateY: settings.attr.translateY, visibility: settings.attr.visibility }; url = options.url ? options.url.toString() : options.toString(); width = options.width || DEFAULT_IMAGE_WIDTH; height = options.height || DEFAULT_IMAGE_HEIGHT; return renderer.createImage(-_round(width * 0.5), -_round(height * 0.5), width, height, url, attr) }, _createSymbolMarker: function(renderer, pointSettings, animationEnabled) { var marker, options = this._options; switch (options.symbol) { case"circle": marker = renderer.createCircle(0, 0, pointSettings.r, pointSettings.attr); break; case"square": case"polygon": case"triangle": case"cross": marker = renderer.createArea(pointSettings.points, pointSettings.attr); break } return marker }, _createMarker: function(renderer, group, image, settings, animationEnabled) { var marker = this._checkImage(image) ? this._createImageMarker(renderer, settings, image) : this._createSymbolMarker(renderer, settings, animationEnabled); marker && marker.append(group); return marker }, _getSymbolBbox: function(x, y, r) { var bbox = {}; bbox.x = x - r; bbox.y = y - r; bbox.width = bbox.height = r * 2; return bbox }, _getImageBbox: function(x, y) { var bbox = {}, image = this._options.image, width = image.width || DEFAULT_IMAGE_WIDTH, height = image.height || DEFAULT_IMAGE_HEIGHT; bbox.x = x - _round(width / 2); bbox.y = y - _round(height / 2); bbox.width = width; bbox.height = height; return bbox }, _getGraphicBbox: function() { var options = this._options, x = this.x, y = this.y, bbox; if (options.visible) bbox = this._checkImage(options.image) ? this._getImageBbox(x, y) : this._getSymbolBbox(x, y, options.styles.normal.r); else bbox = { x: x, y: y, width: 0, height: 0 }; return bbox }, _drawLabel: function(renderer, group) { var that = this, customVisibility = that._getCustomLabelVisibility(), visibleArea, translators = that.translators; if ((that._options.series.getLabelVisibility() || customVisibility) && that.hasValue()) { if (translators) visibleArea = { minX: translators.x.getCanvasVisibleArea().min, maxX: translators.x.getCanvasVisibleArea().max, minY: translators.y.getCanvasVisibleArea().min, maxY: translators.y.getCanvasVisibleArea().max }; that._label.setCoords({ x: that.x, y: that.y }, that._getGraphicBbox(), that._getLabelPosition(), visibleArea); that._label.draw(renderer, group, customVisibility) } else that._label.hide() }, _drawMarker: function(renderer, group, animationEnabled) { var that = this, options = that._options, translates = that._getTranslates(animationEnabled), marker, style = that._getStyle(), pointAttributes = _extend({ translateX: translates.x, translateY: translates.y }, style), pointSettings = { attr: pointAttributes, points: that._populatePointShape(options.symbol, style.r), r: style.r }; marker = that._createMarker(renderer, group, options.image, pointSettings, animationEnabled); that.graphic = marker }, _drawTrackerMarker: function(renderer, group) { var radius = this._options.trackerR || this.storeTrackerR(); this.trackerGraphic = renderer.createCircle(this.x, this.y, radius).append(group); this.trackerGraphic.data({point: this}) }, getTooltipCoords: function() { var coords; if (this.graphic) coords = { x: this.x, y: this.y, offset: this.graphic.getBBox().height / 2 }; else coords = { x: this.x, y: this.y, offset: 0 }; return coords }, hasValue: function() { return this.value !== null && this.minValue !== null }, setPercentValue: function(total) { var valuePercent = this.value / total || 0, percent = valuePercent, minValuePercent = this.minValue / total || 0; percent -= _isNumber(this.minValue) ? minValuePercent : 0; this._label.setDataField("percent", percent); this._label.setDataField("total", total); if (this._options.series.isFullStackedSeries() && this.hasValue()) { this.value = valuePercent; this.minValue = !minValuePercent ? this.minValue : minValuePercent; this.translate() } }, storeTrackerR: function() { var navigator = window.navigator, r = this._options.styles.normal.r, minTrackerSize; navigator = this.__debug_navigator || navigator; this.__debug_browserNavigator = navigator; minTrackerSize = "ontouchstart" in window || navigator.msPointerEnabled && navigator.msMaxTouchPoints || navigator.pointerEnabled && navigator.maxTouchPoints ? 20 : 6; this._options.trackerR = r < minTrackerSize ? minTrackerSize : r; return this._options.trackerR }, _translate: function(translators) { var that = this, mainAxis = that._options.rotated ? "x" : "y", upperMainAxis = mainAxis.toUpperCase(), mainTranslator = translators[mainAxis], axis = that._options.rotated ? "y" : "x"; that[mainAxis] = mainTranslator.translate(that.value); that[axis] = translators[axis].translate(that.argument); that["min" + upperMainAxis] = mainTranslator.translate(that.minValue); that["default" + upperMainAxis] = mainTranslator.translate(CANVAS_POSITION_DEFAULT); that._calculateVisibility(that.x, that.y); that._prepareStatesOptions() }, _changeData: function(data) { this.value = this.initialValue = this.originalValue = data.value; this.argument = this.initialArgument = this.originalArgument = data.argument; this.minValue = this.initialMinValue = this.originalMinValue = _isDefined(data.minValue) ? data.minValue : CANVAS_POSITION_DEFAULT; this.tag = data.tag; this.index = data.index }, _updateData: function(data) { if (this.argument !== data.argument || this.value !== data.value || this.tag !== data.tag) this._changeData(data) }, _getImageSettings: function(image) { return { href: image.url || image.toString(), width: image.width || DEFAULT_IMAGE_WIDTH, height: image.height || DEFAULT_IMAGE_HEIGHT } }, _updateMarker: function(animationEnabled, style) { var that = this, options = that._options, style = style || this._getStyle(), settings, image = options.image; if (that._checkImage(image)) settings = _extend({}, {visibility: style.visibility}, that._getImageSettings(image)); else settings = _extend({}, style, {points: that._populatePointShape(options.symbol, style.r)}); if (!animationEnabled) { settings.translateX = that.x; settings.translateY = that.y } that.graphic.applySettings(settings) }, _updateTracker: function() { this.trackerGraphic.applySettings({ cx: this.x, cy: this.y, r: this.storeTrackerR() }) }, _getLabelFormatObject: function() { return { argument: this.initialArgument, value: this.initialValue, originalArgument: this.originalArgument, originalValue: this.originalValue, seriesName: this._options.series.name, point: this } }, _getLabelPosition: function() { if (this._options.series.isFullStackedSeries() || this.initialValue > 0) return "top"; else return "bottom" }, _getFormatObject: function(tooltip) { var labelFormatObject = this._label.getData(), valueObject = { argumentText: tooltip.formatValue(this.initialArgument, "argument"), valueText: tooltip.formatValue(this.initialValue) }, percentObject = _isDefined(labelFormatObject.percent) ? {percentText: tooltip.formatValue(labelFormatObject.percent, "percent")} : {}, totalObject = _isDefined(labelFormatObject.total) ? {totalText: tooltip.formatValue(labelFormatObject.total)} : {}; return _extend({}, labelFormatObject, valueObject, percentObject, totalObject) } } })(jQuery, DevExpress); /*! Module viz-core, file barPoint.js */ (function($, DX) { var viz = DevExpress.viz, points = viz.core.series.points.mixins, _extend = $.extend, _math = Math, _round = _math.round, _abs = _math.abs, _min = _math.min, CANVAS_POSITION_DEFAULT = "canvas_position_default", DEFAULT_BAR_TRACKER_SIZE = 9, CORRECTING_BAR_TRACKER_VALUE = 4; points.barPoint = _extend({}, points.symbolPoint, { correctCoordinates: function(correctOptions) { var correction = correctOptions.offset - _round(correctOptions.width / 2), rotated = this._options.rotated, valueSelector = rotated ? "height" : "width", correctionSelector = (rotated ? "y" : "x") + "Correction"; this[valueSelector] = correctOptions.width; this[correctionSelector] = correction }, _getGraphicBbox: function() { var bbox = {}; bbox.x = this.x; bbox.y = this.y; bbox.width = this.width; bbox.height = this.height; return bbox }, _getLabelPosition: function() { var position, invertX = this.translators.x.getBusinessRange().invert, invertY = this.translators.y.getBusinessRange().invert, isDiscreteValue = this.series.valueAxisType === "discrete", isFullStacked = this.series.isFullStackedSeries(), notVerticalInverted = !isDiscreteValue && (this.initialValue >= 0 && !invertY || this.initialValue < 0 && invertY) || isDiscreteValue && !invertY || isFullStacked, notHorizontalInverted = !isDiscreteValue && (this.initialValue >= 0 && !invertX || this.initialValue < 0 && invertX) || isDiscreteValue && !invertX || isFullStacked; if (!this._options.rotated) position = notVerticalInverted ? "top" : "bottom"; else position = notHorizontalInverted ? "top" : "bottom"; return position }, _drawLabel: function(renderer, group) { var that = this, options = that._options, coords, commonVisibility = options.series.getLabelVisibility(), customVisibility = that._getCustomLabelVisibility(), visibleArea, translators = that.translators; if (that.hasValue() && (options.label.showForZeroValues || that.initialValue) && (customVisibility || commonVisibility)) { coords = { x: that.x, y: that.y, defaultX: that.defaultX, defaultY: that.defaultY }; if (translators) visibleArea = { minX: translators.x.getCanvasVisibleArea().min, maxX: translators.x.getCanvasVisibleArea().max, minY: translators.y.getCanvasVisibleArea().min, maxY: translators.y.getCanvasVisibleArea().max }; that._label.setCoords(coords, that._getGraphicBbox(), that._getLabelPosition(), visibleArea); that._label.draw(renderer, group, customVisibility) } else that._label.hide() }, _drawMarker: function(renderer, group, animationEnabled) { var style = this._getStyle(), x = this.x, y = this.y, width = this.width, height = this.height; if (animationEnabled) if (this._options.rotated) { width = 0; x = this.defaultX } else { height = 0; y = this.defaultY } this.graphic = renderer.createRect(x, y, width, height, this._options.cornerRadius, style).append(group) }, _getSettingsForTracker: function() { var that = this, y = that.y, height = that.height, x = that.x, width = that.width; if (that._options.rotated) { if (width === 1) { width = DEFAULT_BAR_TRACKER_SIZE; x -= CORRECTING_BAR_TRACKER_VALUE } } else if (height === 1) { height = DEFAULT_BAR_TRACKER_SIZE; y -= CORRECTING_BAR_TRACKER_VALUE } return { x: x, y: y, width: width, height: height } }, _drawTrackerMarker: function(renderer, group) { var settings = this._getSettingsForTracker(); this.trackerGraphic = renderer.createRect(settings.x, settings.y, settings.width, settings.height, this._options.cornerRadius).append(group); this.trackerGraphic.data({point: this}) }, getGraphicSettings: function() { return { x: this.graphic.settings.x || 0, y: this.graphic.settings.y || 0, height: this.graphic.settings.height || 0, width: this.graphic.settings.width || 0 } }, getTooltipCoords: function() { var x = this.x + this.width / 2, y = this.y + this.height / 2; return { x: x, y: y, offset: 0 } }, _truncateCoord: function(coord, minBounce, maxBounce) { if (coord < minBounce) return minBounce; if (coord > maxBounce) return maxBounce; return coord }, _translate: function(translators) { var that = this, rotated = that._options.rotated, valAxis = rotated ? "x" : "y", argAxis = rotated ? "y" : "x", valIntervalName = rotated ? "width" : "height", argIntervalName = rotated ? "height" : "width", argTranslator = translators[argAxis], valTranslator = translators[valAxis], argVisibleArea = argTranslator.getCanvasVisibleArea(), valVisibleArea = valTranslator.getCanvasVisibleArea(), arg, minArg, val, minVal; arg = minArg = argTranslator.translate(that.argument) + (that[argAxis + "Correction"] || 0); val = valTranslator.translate(that.value); minVal = valTranslator.translate(that.minValue); that[valIntervalName] = _abs(val - minVal); that._calculateVisibility(rotated ? _min(val, minVal) : _min(arg, minArg), rotated ? _min(arg, minArg) : _min(val, minVal), that.width, that.height); val = that._truncateCoord(val, valVisibleArea.min, valVisibleArea.max); minVal = that._truncateCoord(minVal, valVisibleArea.min, valVisibleArea.max); that[argAxis] = arg; that["min" + argAxis.toUpperCase()] = minArg; that[valIntervalName] = _abs(val - minVal); that[valAxis] = _min(val, minVal) + (that[valAxis + "Correction"] || 0); that["min" + valAxis.toUpperCase()] = minVal + (that[valAxis + "Correction"] || 0); that["default" + valAxis.toUpperCase()] = valTranslator.translate(CANVAS_POSITION_DEFAULT); if (that.inVisibleArea) { if (that[argAxis] < argVisibleArea.min) { that[argIntervalName] = that[argIntervalName] - (argVisibleArea.min - that[argAxis]); that[argAxis] = argVisibleArea.min; that["min" + argAxis.toUpperCase()] = argVisibleArea.min } if (that[argAxis] + that[argIntervalName] > argVisibleArea.max) that[argIntervalName] = argVisibleArea.max - that[argAxis] } }, _updateMarker: function(animationEnabled, style) { var style = style || this._getStyle(), attributes = _extend({}, style); if (!animationEnabled) { attributes.x = this.x; attributes.y = this.y; attributes.width = this.width; attributes.height = this.height } else attributes.sharpEdges = false; this.graphic.applySettings(attributes) }, _updateTracker: function() { this.trackerGraphic.applySettings(this._getSettingsForTracker()) } }) })(jQuery, DevExpress); /*! Module viz-core, file bubblePoint.js */ (function($, DX) { var viz = DX.viz, points = viz.core.series.points.mixins, _extend = $.extend, MIN_BUBBLE_HEIGHT = 20; points.bubblePoint = _extend({}, points.symbolPoint, { correctCoordinates: function(diameter) { this.bubbleSize = diameter / 2 }, _drawMarker: function(renderer, group, animationEnabled) { var style = this._getStyle(), attr = _extend({ translateX: this.x, translateY: this.y }, style), marker = renderer.createCircle(0, 0, animationEnabled ? 0 : this.bubbleSize, attr).append(group); this.graphic = marker }, _drawTrackerMarker: function(renderer, group) { this.trackerGraphic = renderer.createCircle(this.x, this.y, this.bubbleSize).append(group); this.trackerGraphic.data({point: this}) }, getTooltipCoords: function() { if (this.graphic) { var height = this.graphic.getBBox().height; return { x: this.x, y: this.y, offset: height < MIN_BUBBLE_HEIGHT ? height / 2 : 0 } } }, _getLabelFormatObject: function() { var symbolMethods = points.symbolPoint, formatObject = symbolMethods._getLabelFormatObject.call(this); formatObject.size = this.initialSize; return formatObject }, _updateData: function(data) { var symbolMethods = points.symbolPoint; if (this.argument !== data.argument || this.value !== data.value || this.size !== data.size || this.tag !== data.tag) { symbolMethods._changeData.call(this, data); this.size = this.initialSize = data.size } }, _getGraphicBbox: function() { return this._getSymbolBbox(this.x, this.y, this.bubbleSize) }, _updateMarker: function(animationEnabled, style) { var style = style || this._getStyle(); if (!animationEnabled) style = $.extend({ r: this.bubbleSize, translateX: this.x, translateY: this.y }, style); this.graphic.applySettings(style) }, _updateTracker: function() { this.trackerGraphic.applySettings({ cx: this.x, cy: this.y, r: this.bubbleSize }) }, _getFormatObject: function(tooltip) { var symbolMethods = points.symbolPoint, formatObject = symbolMethods._getFormatObject.call(this, tooltip); formatObject.sizeText = tooltip.formatValue(this.initialSize); return formatObject } }) })(jQuery, DevExpress); /*! Module viz-core, file piePoint.js */ (function($, DX) { var viz = DevExpress.viz, points = viz.core.series.points.mixins, _extend = $.extend, _round = Math.round, _getCosAndSin = DX.utils.getCosAndSin; points.piePoint = _extend({}, points.symbolPoint, { _populatePointShape: function(target, deltaRadius) { var angleFunctions = _getCosAndSin(point.middleAngle); target.x = point.centerX - ~~(deltaRadius * angleFunctions.cos); target.y = point.centerY + ~~(deltaRadius * angleFunctions.sin); target.outerRadius = this.radiusOuter + deltaRadius; target.innerRadius = this.radiusInner; target.startAngle = this.toAngle; target.endAngle = this.fromAngle }, _changeData: function(data) { var that = this; that.value = that.initialValue = that.originalValue = data.value; that.argument = that.initialArgument = that.originalArgument = data.argument; that.minValue = that.initialMinValue = that.originalMinValue = DevExpress.utils.isDefined(data.minValue) ? data.minValue : 0; that.tag = data.tag; that._visible = true; that.index = data.index }, animate: function(complete, duration, step) { this.graphic.animate({ x: this.centerX, y: this.centerY, outerRadius: this.radiusOuter, innerRadius: this.radiusInner, startAngle: this.toAngle, endAngle: this.fromAngle }, { partitionDuration: duration, step: step }, complete) }, correctPosition: function(correction) { this.radiusInner = correction.radiusInner; this.radiusOuter = correction.radiusOuter; this.centerX = correction.centerX; this.centerY = correction.centerY }, correctValue: function(correction, percent, base) { this.value = (base || this.initialValue) + correction; this.minValue = correction; this.percent = percent; this._label.setDataField("percent", percent) }, _getLabelOptions: function() { var options = this._options, series = options.series, seriesStyle = this._options.styles.normal, borderWidth = series._options.containerBackgroundColor === seriesStyle.stroke ? _round(seriesStyle.strokeWidth / 2) : _round(-seriesStyle.strokeWidth / 2); return { options: options.label, borderWidth: borderWidth } }, _updateLabelData: function() { this._label.updateData({formatObject: this._getLabelFormatObject()}) }, _updateLabelOptions: function() { !this._label && this._createLabel(); this._label.setOptions(this._getLabelOptions()) }, _drawLabel: function(renderer, group) { var commonVisibility = this._options.series.getLabelVisibility(), customVisibility = this._getCustomLabelVisibility(); if ((commonVisibility || customVisibility) && this.hasValue()) { this._label.setCoords({ middleAngle: this.middleAngle, radiusOuter: this.radiusOuter, centerX: this.centerX, centerY: this.centerY }, this._options.series.canvas); this._label.draw(renderer, group, customVisibility) } else this._label.hide() }, _drawMarker: function(renderer, group, animationEnabled, firstDrawing) { var styles = this._getStyle(), radiusOuter = this.radiusOuter, radiusInner = this.radiusInner, fromAngle = this.fromAngle, toAngle = this.toAngle; if (animationEnabled) { radiusInner = radiusOuter = 0; if (!firstDrawing) fromAngle = toAngle = this.shiftedAngle } this.graphic = renderer.createArc(this.centerX, this.centerY, radiusOuter, radiusInner, toAngle, fromAngle, styles).append(group) }, _drawTrackerMarker: function(renderer, group) { this.trackerGraphic = renderer.createArc(this.centerX, this.centerY, this.radiusOuter, this.radiusInner, this.toAngle, this.fromAngle).append(group); this.trackerGraphic.data({point: this}) }, getTooltipCoords: function() { var angleFunctions = _getCosAndSin(this.middleAngle); return { x: this.centerX + (this.radiusInner + (this.radiusOuter - this.radiusInner) / 2) * angleFunctions.cos, y: this.centerY - (this.radiusInner + (this.radiusOuter - this.radiusInner) / 2) * angleFunctions.sin, offset: 0 } }, _translate: function(translator) { var angle = this.shiftedAngle || 0; this.fromAngle = translator.translate(this.minValue) + angle; this.toAngle = translator.translate(this.value) + angle; this.middleAngle = translator.translate((this.value - this.minValue) / 2 + this.minValue) + angle; if (!this.isVisible()) this.middleAngle = this.toAngle = this.fromAngle = this.fromAngle || angle }, _updateMarker: function(animationEnabled, style) { style = style || this._getStyle(); if (!animationEnabled) style = _extend({ x: this.centerX, y: this.centerY, outerRadius: this.radiusOuter, innerRadius: this.radiusInner, startAngle: this.toAngle, endAngle: this.fromAngle }, style); this.graphic.applySettings(style) }, _updateTracker: function() { this.trackerGraphic.applySettings({ x: this.centerX, y: this.centerY, outerRadius: this.radiusOuter, innerRadius: this.radiusInner, startAngle: this.toAngle, endAngle: this.fromAngle }) }, getLegendStyles: function() { return this._styles.legendStyles }, isInVisibleArea: function() { return true }, hide: function() { if (this._visible) { this._visible = false; this.hideTooltip(); this._options.visibilityChanged(this) } }, show: function() { if (!this._visible) { this._visible = true; this._options.visibilityChanged(this) } }, setInvisibility: function() { this._setTrackerInvisibility(); this._label.hide() }, isVisible: function() { return this._visible }, _getFormatObject: function(tooltip) { var symbolMethods = points.symbolPoint, formatObject = symbolMethods._getFormatObject.call(this, tooltip); formatObject.percent = this.percent; formatObject.percentText = tooltip.formatValue(this.percent, "percent"); return formatObject }, getColor: function() { return this._styles.normal.fill } }) })(jQuery, DevExpress); /*! Module viz-core, file rangeSymbolPoint.js */ (function($, DX) { var viz = DevExpress.viz, points = viz.core.series.points.mixins, _extend = $.extend, _isDefined = DX.utils.isDefined, _math = Math, _abs = _math.abs, _min = _math.min, _max = _math.max, _round = _math.round, DEFAULT_IMAGE_WIDTH = 20, DEFAULT_IMAGE_HEIGHT = 20; points.rangeSymbolPoint = _extend({}, points.symbolPoint, { deleteLabel: function() { this._topLabel.dispose(); this._topLabel = null; this._bottomLabel.dispose(); this._bottomLabel = null }, hideMarker: function(type) { var marker = this.graphic && this.graphic[type + "Marker"], label = this["_" + type + "Label"]; if (marker && marker.settings.visibility !== "hidden") marker.applySettings({visibility: "hidden"}); label.hide() }, setInvisibility: function() { this.hideMarker("top"); this.hideMarker("bottom"); this._setTrackerInvisibility() }, clearVisibility: function() { var graphic = this.graphic; if (graphic) { if (graphic.topMarker && graphic.topMarker.settings.visibility) graphic.topMarker.applySettings({visibility: null}); if (graphic.bottomMarker && graphic.bottomMarker.settings.visibility) graphic.bottomMarker.applySettings({visibility: null}) } this._clearTrackerVisibility(); this._topLabel.clearVisibility(); this._bottomLabel.clearVisibility() }, clearMarker: function() { if (this.graphic) { this.graphic.topMarker && this.graphic.topMarker.applySettings(this._emptySettings); this.graphic.bottomMarker && this.graphic.bottomMarker.applySettings(this._emptySettings) } }, _getLabelPosition: function(markerType) { var position, rotated = this._options.rotated, invertY = this.translators.y.getBusinessRange().invert, invertX = this.translators.x.getBusinessRange().invert, isDiscreteValue = this._options.series._options.valueAxisType === "discrete", notInverted = isDiscreteValue && (!invertY && !rotated || invertX && rotated) || !isDiscreteValue && this.value > this.minValue && (!invertY && !rotated || !invertX && rotated); if (markerType === "top") position = notInverted ? "top" : "bottom"; else position = notInverted ? "bottom" : "top"; return position }, _getLabelMinFormatObject: function() { return { index: 0, argument: this.initialArgument, value: this.initialMinValue, seriesName: this._options.series.name, originalValue: this.originalMinValue, originalArgument: this.originalArgument, point: this } }, _updateLabelData: function() { var maxFormatObject = this._getLabelFormatObject(); maxFormatObject.index = 1; this._topLabel.updateData({ formatObject: maxFormatObject, initialValue: this.initialValue }); this._bottomLabel.updateData({ formatObject: this._getLabelMinFormatObject(), initialValue: this.initialMinValue }) }, _updateLabelOptions: function(type) { var options = this._getLabelOptions(type); (!this._topLabel || !this._bottomLabel) && this._createLabel(); this._topLabel.setOptions(options); this._bottomLabel.setOptions(options) }, setAdjustSeriesLabels: function(adjustSeriesLabels) { this._topLabel.adjustSeriesLabels = adjustSeriesLabels; this._bottomLabel.adjustSeriesLabels = adjustSeriesLabels }, _createLabel: function() { this._topLabel = viz.core.CoreFactory.createLabel(); this._bottomLabel = viz.core.CoreFactory.createLabel() }, _getLabelCoords: function(location) { var coords = {}, isTop = location === "top"; if (!this._options.rotated) { coords.x = this.x; coords.y = isTop ? _min(this.y, this.minY) : _max(this.y, this.minY) } else { coords.x = isTop ? _max(this.x, this.minX) : _min(this.x, this.minX); coords.y = this.y } return coords }, _getGraphicBbox: function(location) { var options = this._options, rotated = options.rotated, isTop = location === "top", images = this._getImage(options.image), image = isTop ? this._checkImage(images.top) : this._checkImage(images.bottom), bbox, x, y; if (!rotated) { x = this.x; y = isTop ? _min(this.y, this.minY) : _max(this.y, this.minY) } else { x = isTop ? _max(this.x, this.minX) : _min(this.x, this.minX); y = this.y } if (options.visible) bbox = image ? this._getImageBbox(x, y) : this._getSymbolBbox(x, y, options.styles.normal.r); else bbox = { x: x, y: y, width: 0, height: 0 }; return bbox }, _checkOverlay: function(bottomCoord, topCoord, topValue) { return bottomCoord < topCoord + topValue }, _getOverlayCorrections: function(type, topCoords, bottomCoords) { var isVertical = type === "vertical", coordSelector = isVertical ? "y" : "x", valueSelector = isVertical ? "height" : "width", visibleArea = this.translators[coordSelector].getCanvasVisibleArea(), minBound = visibleArea.min, maxBound = visibleArea.max, delta = _round((topCoords[coordSelector] + topCoords[valueSelector] - bottomCoords[coordSelector]) / 2), coord1 = topCoords[coordSelector] - delta, coord2 = bottomCoords[coordSelector] + delta; if (coord1 < minBound) { delta = minBound - topCoords[coordSelector]; coord1 += delta; coord2 += delta } else if (coord2 + bottomCoords[valueSelector] > maxBound) { delta = -(bottomCoords[coordSelector] + bottomCoords[valueSelector] - maxBound); coord1 += delta; coord2 += delta } return { coord1: coord1, coord2: coord2 } }, _checkLabelsOverlay: function(topLocation) { var that = this, topCoords = that._topLabel.getCoords(), bottomCoords = that._bottomLabel.getCoords(), corrections = {}; if (!that._options.rotated) { if (topLocation === "top") { if (this._checkOverlay(bottomCoords.y, topCoords.y, topCoords.height)) { corrections = this._getOverlayCorrections("vertical", topCoords, bottomCoords); that._topLabel.updatePosition(undefined, corrections.coord1); that._bottomLabel.updatePosition(undefined, corrections.coord2) } } else if (this._checkOverlay(topCoords.y, bottomCoords.y, bottomCoords.height)) { corrections = this._getOverlayCorrections("vertical", bottomCoords, topCoords); that._topLabel.updatePosition(undefined, corrections.coord2); that._bottomLabel.updatePosition(undefined, corrections.coord1) } } else if (topLocation === "top") { if (this._checkOverlay(topCoords.x, bottomCoords.x, bottomCoords.width)) { corrections = this._getOverlayCorrections("horizontal", bottomCoords, topCoords); that._topLabel.updatePosition(corrections.coord2); that._bottomLabel.updatePosition(corrections.coord1) } } else if (this._checkOverlay(bottomCoords.x, topCoords.x, topCoords.width)) { corrections = this._getOverlayCorrections("horizontal", topCoords, bottomCoords); that._topLabel.updatePosition(corrections.coord1); that._bottomLabel.updatePosition(corrections.coord2) } }, _drawLabel: function(renderer, group) { var topCoords, bottomCoords, rotated = this._options.rotated, topLocation = this._getLabelPosition("top"), bottomLocation = this._getLabelPosition("bottom"), isInside = this._options.label.position === "inside", topPosition = isInside ? bottomLocation : topLocation, bottomPosition = isInside ? topLocation : bottomLocation, translators = this.translators, visibleArea, customVisibility = this._getCustomLabelVisibility(), commonVisibility = this._options.series.getLabelVisibility(); if ((commonVisibility || customVisibility) && this.hasValue()) { if (translators) visibleArea = { minX: translators.x.getCanvasVisibleArea().min, maxX: translators.x.getCanvasVisibleArea().max, minY: translators.y.getCanvasVisibleArea().min, maxY: translators.y.getCanvasVisibleArea().max }; this._topLabel.setCoords(this._getLabelCoords(topLocation), this._getGraphicBbox(topLocation), topPosition, visibleArea); this._bottomLabel.setCoords(this._getLabelCoords(bottomLocation), this._getGraphicBbox(bottomLocation), bottomPosition, visibleArea); this.visibleTopMarker && this._topLabel.draw(renderer, group, customVisibility); this.visibleBottomMarker && this._bottomLabel.draw(renderer, group, customVisibility); this._checkLabelsOverlay(topLocation) } else { this._topLabel.hide(); this._bottomLabel.hide() } }, _getImage: function(imageOption) { var image = {}; if (_isDefined(imageOption)) if (typeof imageOption === "string") image.top = image.bottom = imageOption; else { image.top = { url: typeof imageOption.url === "string" ? imageOption.url : imageOption.url && imageOption.url.rangeMaxPoint, width: typeof imageOption.width === "number" ? imageOption.width : imageOption.width && imageOption.width.rangeMaxPoint, height: typeof imageOption.height === "number" ? imageOption.height : imageOption.height && imageOption.height.rangeMaxPoint }; image.bottom = { url: typeof imageOption.url === "string" ? imageOption.url : imageOption.url && imageOption.url.rangeMinPoint, width: typeof imageOption.width === "number" ? imageOption.width : imageOption.width && imageOption.width.rangeMinPoint, height: typeof imageOption.height === "number" ? imageOption.height : imageOption.height && imageOption.height.rangeMinPoint } } return image }, _checkSymbol: function(oldOptions, newOptions) { var oldSymbol = oldOptions.symbol, newSymbol = newOptions.symbol, symbolChanged = oldSymbol === "circle" && newSymbol !== "circle" || oldSymbol !== "circle" && newSymbol === "circle", oldImages = this._getImage(oldOptions.image), newImages = this._getImage(newOptions.image), topImageChanged = this._checkImage(oldImages.top) !== this._checkImage(newImages.top), bottomImageChanged = this._checkImage(oldImages.bottom) !== this._checkImage(newImages.bottom); return symbolChanged || topImageChanged || bottomImageChanged }, _getSettingsForTwoMarkers: function(style) { var that = this, options = that._options, settings = {}, x = options.rotated ? _min(that.x, that.minX) : that.x, y = options.rotated ? that.y : _min(that.y, that.minY), radius = style.r, points = that._populatePointShape(options.symbol, radius); settings.top = { r: radius, points: points, attr: _extend({ translateX: x + that.width, translateY: y }, style) }; settings.bottom = { r: radius, points: points, attr: _extend({ translateX: x, translateY: y + that.height }, style) }; return settings }, _hasGraphic: function() { return this.graphic && this.graphic.topMarker && this.graphic.bottomMarker }, _drawOneMarker: function(renderer, markerType, imageSettings, settings) { if (this.graphic[markerType]) this._updateOneMarker(markerType, settings); else this.graphic[markerType] = this._createMarker(renderer, this.graphic, imageSettings, settings) }, _drawMarker: function(renderer, group, animationEnabled, style) { var that = this, style = style || that._getStyle(), settings = that._getSettingsForTwoMarkers(style), image = that._getImage(that._options.image); if (that._checkImage(image.top)) settings.top = that._getImageSettings(settings.top, image.top); if (that._checkImage(image.bottom)) settings.bottom = that._getImageSettings(settings.bottom, image.bottom); that.graphic = that.graphic || renderer.createGroup().append(group); that.visibleTopMarker && that._drawOneMarker(renderer, 'topMarker', image.top, settings.top); that.visibleBottomMarker && that._drawOneMarker(renderer, 'bottomMarker', image.bottom, settings.bottom) }, _getSettingsForTracker: function(radius) { var that = this, options = that._options, x = options.rotated ? _min(that.x, that.minX) - radius : that.x - radius, y = options.rotated ? that.y - radius : _min(that.y, that.minY) - radius, width = that.width + 2 * radius, height = that.height + 2 * radius; return { translateX: x, translateY: y, width: width, height: height } }, _drawTrackerMarker: function(renderer, group) { var that = this, options = that._options, radius = options.trackerR || that.storeTrackerR(), settings = that._getSettingsForTracker(radius), attr = { translateX: settings.translateX, translateY: settings.translateY }; that.trackerGraphic = renderer.createRect(0, 0, settings.width, settings.height, 0, attr).append(group); that.trackerGraphic.data({point: that}) }, isInVisibleArea: function() { var that = this, minArgument = _min(that.minX, that.x) || that.x, maxArgument = _max(that.minX, that.x) || that.x, maxValue = _max(that.minY, that.y) || that.y, minValue = _min(that.minY, that.y) || that.y, notVisibleBothMarkersRight, notVisibleBothMarkersLeft, notVisibleBothMarkersBottom, notVisibleBothMarkersTop, visibleTopMarker = true, visibleBottomMarker = true, visibleRangeArea = true, visibleAreaX, visibleAreaY; if (that.translators) { visibleAreaX = that.translators.x.getCanvasVisibleArea(); visibleAreaY = that.translators.y.getCanvasVisibleArea(); notVisibleBothMarkersRight = visibleAreaX.max < minArgument && visibleAreaX.max < maxArgument; notVisibleBothMarkersLeft = visibleAreaX.min > minArgument && visibleAreaX.min > maxArgument; notVisibleBothMarkersTop = visibleAreaY.min > minValue && visibleAreaY.min > maxValue; notVisibleBothMarkersBottom = visibleAreaY.max < minValue && visibleAreaY.max < maxValue; if (notVisibleBothMarkersTop || notVisibleBothMarkersBottom || notVisibleBothMarkersRight || notVisibleBothMarkersLeft) visibleTopMarker = visibleBottomMarker = visibleRangeArea = false; else if (!that._options.rotated) { visibleTopMarker = visibleAreaY.min < minValue && visibleAreaY.max > minValue; visibleBottomMarker = visibleAreaY.min < maxValue && visibleAreaY.max > maxValue } else { visibleBottomMarker = visibleAreaX.min < minArgument && visibleAreaX.max > minArgument; visibleTopMarker = visibleAreaX.min < maxArgument && visibleAreaX.max > maxArgument } } that.visibleTopMarker = visibleTopMarker; that.visibleBottomMarker = visibleBottomMarker; that.visibleRangeArea = visibleRangeArea; return visibleRangeArea }, getTooltipCoords: function() { var that = this, x, y, min, max, minValue, visibleAreaX = that.translators.x.getCanvasVisibleArea(), visibleAreaY = that.translators.y.getCanvasVisibleArea(); if (!that._options.rotated) { minValue = _min(that.y, that.minY); x = that.x; min = visibleAreaY.min > minValue ? visibleAreaY.min : minValue; max = visibleAreaY.max < minValue + that.height ? visibleAreaY.max : minValue + that.height; y = min + (max - min) / 2 } else { minValue = _min(that.x, that.minX); y = that.y; min = visibleAreaX.min > minValue ? visibleAreaX.min : minValue; max = visibleAreaX.max < minValue + that.width ? visibleAreaX.max : minValue + that.width; x = min + (max - min) / 2 } return { x: x, y: y, offset: 0 } }, _translate: function(translators) { var symbolMethods = points.symbolPoint; this.minX = this.minY = translators.y.translate(this.minValue); symbolMethods._translate.call(this, translators); this.height = this._options.rotated ? 0 : _abs(this.minY - this.y); this.width = this._options.rotated ? _abs(this.x - this.minX) : 0 }, _updateData: function(data) { if (this.argument !== data.argument || this.value !== data.value || this.minValue !== data.minValue || this.tag !== data.tag) { this._changeData(data); this.minValue = this.initialMinValue = this.originalMinValue = data.minValue } }, _getImageSettings: function(settings, image) { var x = settings.attr.translateX, y = settings.attr.translateY; return { href: image.url || image.toString(), width: image.width || DEFAULT_IMAGE_WIDTH, height: image.height || DEFAULT_IMAGE_HEIGHT, attr: { translateX: x, translateY: y } } }, _updateOneMarker: function(markerType, settings) { this.graphic && this.graphic[markerType] && this.graphic[markerType].applySettings(_extend({}, settings, settings.attr)) }, _updateMarker: function(animationEnabled, style) { this._drawMarker(undefined, undefined, undefined, style) }, _updateTracker: function() { var radius = this.storeTrackerR(), settings = this._getSettingsForTracker(radius); this.trackerGraphic.applySettings(settings) }, _getFormatObject: function(tooltip) { var minValue = tooltip.formatValue(this.initialMinValue), value = tooltip.formatValue(this.initialValue); return { argument: this.initialArgument, argumentText: tooltip.formatValue(this.initialArgument, "argument"), valueText: minValue + " - " + value, rangeValue1Text: minValue, rangeValue2Text: value, rangeValue1: this.initialMinValue, rangeValue2: this.initialValue, seriesName: this.series.name, point: this, originalMinValue: this.originalMinValue, originalValue: this.originalValue, originalArgument: this.originalArgument } } }) })(jQuery, DevExpress); /*! Module viz-core, file rangeBarPoint.js */ (function($, DX) { var viz = DevExpress.viz, points = viz.core.series.points.mixins, _isDefined = DX.utils.isDefined, rangeSymbolPointMethods = points.rangeSymbolPoint, _extend = $.extend; points.rangeBarPoint = _extend({}, points.barPoint, { deleteLabel: rangeSymbolPointMethods.deleteLabel, _getFormatObject: rangeSymbolPointMethods._getFormatObject, setAdjustSeriesLabels: rangeSymbolPointMethods.setAdjustSeriesLabels, clearVisibility: function() { if (this.graphic && this.graphic.settings.visibility) this.graphic.applySettings({visibility: null}); this._topLabel.clearVisibility(); this._bottomLabel.clearVisibility() }, setInvisibility: function() { if (this.graphic && this.graphic.settings.visibility !== "hidden") this.graphic.applySettings({visibility: "hidden"}); this._topLabel.hide(); this._bottomLabel.hide() }, _translate: function(translator) { var barMethods = points.barPoint; barMethods._translate.call(this, translator); if (this._options.rotated) this.width = this.width || 1; else this.height = this.height || 1 }, _updateData: rangeSymbolPointMethods._updateData, _getLabelPosition: rangeSymbolPointMethods._getLabelPosition, _getLabelMinFormatObject: rangeSymbolPointMethods._getLabelMinFormatObject, _updateLabelData: rangeSymbolPointMethods._updateLabelData, _updateLabelOptions: rangeSymbolPointMethods._updateLabelOptions, _createLabel: rangeSymbolPointMethods._createLabel, _checkOverlay: rangeSymbolPointMethods._checkOverlay, _getOverlayCorrections: rangeSymbolPointMethods._getOverlayCorrections, _drawLabel: function(renderer, group) { var topCoords, bottomCoords, rotated = this._options.rotated, topLocation = this._getLabelPosition("top"), bottomLocation = this._getLabelPosition("bottom"), bbox = this._getGraphicBbox(), coords = { x: this.x, y: this.y, defaultX: this.defaultX, defaultY: this.defaultY }, translators = this.translators, visibleArea, customVisibility = this._getCustomLabelVisibility(), commonVisibility = this._options.series.getLabelVisibility(); if ((customVisibility || commonVisibility) && this.hasValue()) { if (translators) visibleArea = { minX: translators.x.getCanvasVisibleArea().min, maxX: translators.x.getCanvasVisibleArea().max, minY: translators.y.getCanvasVisibleArea().min, maxY: translators.y.getCanvasVisibleArea().max }; this._topLabel.setCoords(coords, bbox, topLocation, visibleArea); this._bottomLabel.setCoords(coords, bbox, bottomLocation, visibleArea); this._topLabel.draw(renderer, group, customVisibility); this._bottomLabel.draw(renderer, group, customVisibility); rangeSymbolPointMethods._checkLabelsOverlay.call(this, topLocation) } else { this._topLabel.hide(); this._bottomLabel.hide() } } }) })(jQuery, DevExpress); /*! Module viz-core, file candlestickPoint.js */ (function($, DX) { var viz = DevExpress.viz, points = viz.core.series.points.mixins, _isNumeric = $.isNumeric, _extend = $.extend, _math = Math, _abs = _math.abs, _min = _math.min, _max = _math.max, _round = _math.round, DEFAULT_FINANCIAL_TRACKER_MARGIN = 2; points.candlestickPoint = _extend({}, points.barPoint, { _getContinuousPoints: function(minValueName, maxValueName) { var that = this, x = that.x, createPoint = that._options.rotated ? function(x, y) { return { x: y, y: x } } : function(x, y) { return { x: x, y: y } }, width = that.width, min = that[minValueName], max = that[maxValueName], points; if (min === max) points = [createPoint(x, that.highY), createPoint(x, that.lowY), createPoint(x, that.closeY), createPoint(x - width / 2, that.closeY), createPoint(x + width / 2, that.closeY), createPoint(x, that.closeY)]; else points = [createPoint(x, that.highY), createPoint(x, max), createPoint(x + width / 2, max), createPoint(x + width / 2, min), createPoint(x, min), createPoint(x, that.lowY), createPoint(x, min), createPoint(x - width / 2, min), createPoint(x - width / 2, max), createPoint(x, max)]; return points }, _getCategoryPoints: function(y) { var that = this, x = that.x, createPoint = that._options.rotated ? function(x, y) { return { x: y, y: x } } : function(x, y) { return { x: x, y: y } }; return [createPoint(x, that.highY), createPoint(x, that.lowY), createPoint(x, y), createPoint(x - that.width / 2, y), createPoint(x + that.width / 2, y), createPoint(x, y)] }, _getPoints: function() { var that = this, points, minValueName, maxValueName, openValue = that.openValue, closeValue = that.closeValue; if (_isNumeric(openValue) && _isNumeric(closeValue)) { minValueName = openValue > closeValue ? "closeY" : "openY"; maxValueName = openValue > closeValue ? "openY" : "closeY"; points = that._getContinuousPoints(minValueName, maxValueName) } else if (openValue === closeValue) points = [{ x: that.x, y: that.highY }, { x: that.x, y: that.lowY }]; else points = that._getCategoryPoints(_isNumeric(openValue) ? that.openY : that.closeY); return points }, getColor: function() { return this._isReduction ? this._options.reduction.color : this._styles.normal.stroke || this.series.getColor() }, _drawMarkerInGroup: function(group, attributes, renderer) { this.graphic = renderer.createArea(this._getPoints(), attributes).append(group) }, _fillStyle: function() { var styles = this._options.styles; if (this._isReduction && this._isPositive) this._styles = styles.reductionPositive; else if (this._isReduction) this._styles = styles.reduction; else if (this._isPositive) this._styles = styles.positive; else this._styles = styles }, _getMinTrackerWidth: function() { return 1 + 2 * this._styles.normal.strokeWidth }, correctCoordinates: function(correctOptions) { var minWidth = this._getMinTrackerWidth(), maxWidth = 10; this.width = correctOptions.width < minWidth ? minWidth : correctOptions.width > maxWidth ? maxWidth : correctOptions.width; this.xCorrection = correctOptions.offset }, _getMarkerGroup: function(group) { var markerGroup; if (this._isReduction && this._isPositive) markerGroup = group.reductionPositiveMarkersGroup; else if (this._isReduction) markerGroup = group.reductionMarkersGroup; else if (this._isPositive) markerGroup = group.defaultPositiveMarkersGroup; else markerGroup = group.defaultMarkersGroup; return markerGroup }, _drawMarker: function(renderer, group) { var attributes = this._getStyle(), rotated = this._options.rotated, pointGroup = this._getMarkerGroup(group); this._drawMarkerInGroup(pointGroup, attributes, renderer) }, _getSettingsForTracker: function() { var that = this, highY = that.highY, lowY = that.lowY, rotated = that._options.rotated, x, y, width, height; if (highY === lowY) { highY = rotated ? highY + DEFAULT_FINANCIAL_TRACKER_MARGIN : highY - DEFAULT_FINANCIAL_TRACKER_MARGIN; lowY = rotated ? lowY - DEFAULT_FINANCIAL_TRACKER_MARGIN : lowY + DEFAULT_FINANCIAL_TRACKER_MARGIN } if (rotated) { x = _min(lowY, highY); y = that.x - that.width / 2; width = _abs(lowY - highY); height = that.width } else { x = that.x - that.width / 2; y = _min(lowY, highY); width = that.width; height = _abs(lowY - highY) } return { x: x, y: y, width: width, height: height } }, _drawTrackerMarker: function(renderer, group) { var settings = this._getSettingsForTracker(); this.trackerGraphic = renderer.createRect(settings.x, settings.y, settings.width, settings.height, 0).append(group); this.trackerGraphic.data({point: this}) }, _getGraphicBbox: function() { var bbox = {}, rotated = this._options.rotated; bbox.x = !rotated ? this.x - _round(this.width / 2) : this.lowY; bbox.y = !rotated ? this.highY : this.x - _round(this.width / 2); bbox.width = !rotated ? this.width : this.highY - this.lowY; bbox.height = !rotated ? this.lowY - this.highY : this.width; return bbox }, _drawLabel: function(renderer, group) { var coords, commonVisibility = this._options.series.getLabelVisibility(), customVisibility = this._getCustomLabelVisibility(), visibleArea, reductionColor = this._options.reduction.color, translators = this.translators; if (this.hasValue() && (commonVisibility || customVisibility)) { visibleArea = { minX: translators.x.getCanvasVisibleArea().min, maxX: translators.x.getCanvasVisibleArea().max, minY: translators.y.getCanvasVisibleArea().min, maxY: translators.y.getCanvasVisibleArea().max }; if (this._isReduction) this._label.updateOptions({options: { background: {fill: reductionColor}, connector: {stroke: reductionColor} }}); coords = this._options.rotated ? { x: this.highY, y: this.x } : { x: this.x, y: this.highY }; this._label.setCoords(coords, this._getGraphicBbox(), "top", visibleArea); this._label.draw(renderer, group, customVisibility) } }, getTooltipCoords: function() { var that = this; if (that.graphic) { var x, y, min, max, minValue = _min(that.lowY, that.highY), maxValue = _max(that.lowY, that.highY), visibleAreaX = that.translators.x.getCanvasVisibleArea(), visibleAreaY = that.translators.y.getCanvasVisibleArea(); if (!that._options.rotated) { min = _max(visibleAreaY.min, minValue); max = _min(visibleAreaY.max, maxValue); x = that.x; y = min + (max - min) / 2 } else { min = _max(visibleAreaX.min, minValue); max = _min(visibleAreaX.max, maxValue); y = that.x; x = min + (max - min) / 2 } return { x: x, y: y, offset: 0 } } }, hasValue: function() { return this.highValue !== null && this.lowValue !== null }, _translate: function(translator) { var that = this, rotated = that._options.rotated, argTranslator = rotated ? that.translators.y : that.translators.x, valTranslator = rotated ? that.translators.x : that.translators.y, centerValue, height; that.x = argTranslator.translate(that.argument) + (that.xCorrection || 0); that.openY = that.openValue !== null ? valTranslator.translate(that.openValue) : null; that.highY = valTranslator.translate(that.highValue); that.lowY = valTranslator.translate(that.lowValue); that.closeY = that.closeValue !== null ? valTranslator.translate(that.closeValue) : null; height = _abs(that.lowY - that.highY); centerValue = _min(that.lowY, that.highY) + _abs(that.lowY - that.highY) / 2; that._calculateVisibility(!rotated ? that.x : centerValue, !rotated ? centerValue : that.x) }, _updateData: function(data) { var that = this; if (that.argument !== data.argument || that.reductionValue !== data.reductionValue || that.highValue !== data.highValue || that.lowValue !== data.lowValue || that.openValue !== data.openValue || that.closeValue !== data.closeValue || that.tag !== data.tag) { that.value = that.initialValue = data.reductionValue; that.originalValue = data.value; that.argument = that.initialArgument = data.argument; that.originalArgument = data.argument; that.lowValue = data.lowValue; that.originalLowValue = data.lowValue; that.highValue = data.highValue; that.originalHighValue = data.highValue; that.openValue = data.openValue; that.originalOpenValue = data.openValue; that.closeValue = data.closeValue; that.originalCloseValue = data.closeValue; that.tag = data.tag; that.pointClassName = data.pointClassName; that._isPositive = data.openValue < data.closeValue; that._isReduction = data.isReduction } }, _updateMarker: function(animationEnabled, style, group) { var style = style || this._getStyle(); this.graphic.applySettings(_extend({points: this._getPoints()}, style)); group && this.graphic.append(this._getMarkerGroup(group)) }, _updateTracker: function() { this.trackerGraphic.applySettings(this._getSettingsForTracker()) }, _getLabelFormatObject: function() { return { openValue: this.openValue, highValue: this.highValue, lowValue: this.lowValue, closeValue: this.closeValue, reductionValue: this.initialValue, argument: this.initialArgument, value: this.initialValue, seriesName: this._options.series.name, originalOpenValue: this.originalOpenValue, originalCloseValue: this.originalCloseValue, originalLowValue: this.originalLowValue, originalHighValue: this.originalHighValue, originalArgument: this.originalArgument, point: this } }, _getFormatObject: function(tooltip) { var highValue = tooltip.formatValue(this.highValue), openValue = tooltip.formatValue(this.openValue), closeValue = tooltip.formatValue(this.closeValue), lowValue = tooltip.formatValue(this.lowValue), symbolMethods = points.symbolPoint, formatObject = symbolMethods._getFormatObject.call(this, tooltip); return _extend({}, formatObject, { valueText: "h: " + highValue + (openValue !== "" ? " o: " + openValue : "") + (closeValue !== "" ? " c: " + closeValue : "") + " l: " + lowValue, highValueText: highValue, openValueText: openValue, closeValueText: closeValue, lowValueText: lowValue }) } }) })(jQuery, DevExpress); /*! Module viz-core, file stockPoint.js */ (function($, DX) { var viz = DevExpress.viz, points = viz.core.series.points.mixins, _extend = $.extend, _isNumeric = $.isNumeric; points.stockPoint = _extend({}, points.candlestickPoint, { _getPoints: function() { var that = this, createPoint = that._options.rotated ? function(x, y) { return { x: y, y: x } } : function(x, y) { return { x: x, y: y } }, openYExist = _isNumeric(that.openY), closeYExist = _isNumeric(that.closeY), x = that.x, width = that.width, points = [createPoint(x, that.highY), openYExist && createPoint(x, that.openY), openYExist && createPoint(x - width / 2, that.openY), openYExist && createPoint(x, that.openY), closeYExist && createPoint(x, that.closeY), closeYExist && createPoint(x + width / 2, that.closeY), closeYExist && createPoint(x, that.closeY), createPoint(x, that.lowY)]; return points }, _drawMarkerInGroup: function(group, attributes, renderer) { this.graphic = renderer.createPath(this._getPoints(), attributes).append(group) }, _getMinTrackerWidth: function() { return 2 + this._styles.normal.strokeWidth } }) })(jQuery, DevExpress); /*! Module viz-core, file default.js */ (function($, DX, undefined) { DX.viz.themes = DX.viz.themes || []; var fontFamilyDefault = "'Segoe UI', 'Helvetica Neue', 'Trebuchet MS', Verdana", fontFamilyLight = "'Segoe UI Light', 'Helvetica Neue Light', 'Segoe UI', 'Helvetica Neue', 'Trebuchet MS', Verdana", baseChartTheme = { containerBackgroundColor: '#ffffff', animation: { enabled: true, duration: 1000, easing: 'easeOutCubic', maxPointCountSupported: 300 }, commonSeriesSettings: { border: { visible: false, width: 2 }, showInLegend: true, visible: true, hoverMode: 'excludePoints', selectionMode: 'includePoints', hoverStyle: { hatching: { direction: 'right', width: 2, step: 6, opacity: 0.75 }, border: { visible: false, width: 3 } }, selectionStyle: { hatching: { direction: 'right', width: 2, step: 6, opacity: 0.5 }, border: { visible: false, width: 3 } }, label: { visible: false, alignment: 'center', rotationAngle: 0, horizontalOffset: 0, verticalOffset: 0, radialOffset: 0, format: '', argumentFormat: '', precision: 0, argumentPrecision: 0, percentPrecision: 0, showForZeroValues: true, customizeText: undefined, maxLabelCount: undefined, position: 'outside', font: {color: '#ffffff'}, border: { visible: false, width: 1, color: '#d3d3d3', dashStyle: 'solid' }, connector: { visible: false, width: 1 } } }, redrawOnResize: true, margin: { left: 0, top: 0, right: 0, bottom: 0 }, seriesSelectionMode: 'single', pointSelectionMode: 'single', legend: { hoverMode: 'includePoints', verticalAlignment: 'top', horizontalAlignment: 'right', position: 'outside', visible: true, customizeText: undefined, itemTextPosition: undefined, margin: 10, equalColumnWidth: false, markerSize: 12, backgroundColor: undefined, backgroundOpacity: undefined, border: { visible: false, width: 1, color: '#d3d3d3', cornerRadius: 0, dashStyle: 'solid' }, paddingLeftRight: 20, paddingTopBottom: 15, columnCount: 0, rowCount: 0, columnItemSpacing: 20, rowItemSpacing: 8 }, tooltip: { enabled: false, border: { width: 1, color: '#d3d3d3', dashStyle: 'solid', visible: true }, font: { family: fontFamilyDefault, weight: 400, size: 12, color: '#232323' }, color: '#ffffff', arrowLength: 10, paddingLeftRight: 18, paddingTopBottom: 15, shared: false, format: '', argumentFormat: '', precision: 0, argumentPrecision: 0, percentPrecision: 0, customizeText: undefined, customizeTooltip: undefined, shadow: { opacity: 0.4, offsetX: 0, offsetY: 4, blur: 2, color: '#000000' } }, size: { width: undefined, height: undefined }, loadingIndicator: { font: {}, backgroundColor: '#ffffff', text: 'Loading...' }, dataPrepareSettings: { checkTypeForAllData: false, convertToAxisDataType: true, sortingMethod: true }, title: { font: { family: fontFamilyLight, weight: 200, color: '#232323', size: 28 }, margin: 10 }, adaptiveLayout: { width: 80, height: 80, keepLabels: true }, _rtl: {legend: {itemTextPosition: 'left'}} }, baseDarkChartTheme = { containerBackgroundColor: '#2b2b2b', commonSeriesSettings: {label: {border: {color: '#494949'}}}, legend: {border: {color: '#494949'}}, loadingIndicator: {backgroundColor: '#2b2b2b'}, title: {font: {color: '#929292'}}, tooltip: { color: '#2b2b2b', border: {color: '#494949'}, font: {color: '#929292'} } }; DX.viz.themes.push({ name: 'desktop', font: { color: '#767676', family: fontFamilyDefault, weight: 400, size: 12, cursor: 'default' }, chart: $.extend(true, {}, baseChartTheme, { commonSeriesSettings: { type: 'line', stack: 'default', point: { visible: true, symbol: 'circle', size: 12, border: { visible: false, width: 1 }, hoverMode: 'onlyPoint', selectionMode: 'onlyPoint', hoverStyle: { border: { visible: true, width: 4 }, size: 12 }, selectionStyle: { border: { visible: true, width: 4 }, size: 12 } }, scatter: {}, line: { width: 2, dashStyle: 'solid', hoverStyle: { width: 3, hatching: {direction: 'none'} }, selectionStyle: {width: 3} }, stackedline: { width: 2, dashStyle: 'solid', hoverStyle: { width: 3, hatching: {direction: 'none'} }, selectionStyle: {width: 3} }, fullstackedline: { width: 2, dashStyle: 'solid', hoverStyle: { width: 3, hatching: {direction: 'none'} }, selectionStyle: {width: 3} }, stepline: { width: 2, dashStyle: 'solid', hoverStyle: { width: 3, hatching: {direction: 'none'} }, selectionStyle: {width: 3} }, area: { point: {visible: false}, opacity: 0.5 }, stackedarea: { point: {visible: false}, opacity: 0.5 }, fullstackedarea: { point: {visible: false}, opacity: 0.5 }, steparea: { border: { visible: true, width: 2 }, point: {visible: false}, hoverStyle: {border: { visible: true, width: 3 }}, selectionStyle: {border: { visible: true, width: 3 }}, opacity: 0.5 }, spline: { width: 2, hoverStyle: { width: 3, hatching: {direction: 'none'} }, selectionStyle: {width: 3} }, splinearea: { point: {visible: false}, opacity: 0.5 }, bar: { cornerRadius: 0, point: { hoverStyle: {border: {visible: false}}, selectionStyle: {border: {visible: false}} } }, stackedbar: { cornerRadius: 0, point: { hoverStyle: {border: {visible: false}}, selectionStyle: {border: {visible: false}} }, label: {position: "inside"} }, fullstackedbar: { cornerRadius: 0, point: { hoverStyle: {border: {visible: false}}, selectionStyle: {border: {visible: false}} }, label: {position: "inside"} }, rangebar: { cornerRadius: 0, point: { hoverStyle: {border: {visible: false}}, selectionStyle: {border: {visible: false}} } }, rangearea: { point: {visible: false}, opacity: 0.5 }, rangesplinearea: { point: {visible: false}, opacity: 0.5 }, bubble: { opacity: 0.5, point: { hoverStyle: {border: {visible: false}}, selectionStyle: {border: {visible: false}} } }, candlestick: { width: 1, innerColor: '#ffffff', reduction: {color: '#ff0000'}, hoverStyle: { width: 3, hatching: {direction: 'none'} }, selectionStyle: {width: 3}, point: {border: {visible: true}} }, stock: { width: 1, reduction: {color: '#ff0000'}, hoverStyle: { width: 3, hatching: {direction: 'none'} }, selectionStyle: {width: 3}, point: {border: {visible: true}} } }, crosshair: { enabled: false, color: '#c6c6c6', width: 1, dashStyle: 'solid', verticalLine: {visible: true}, horizontalLine: {visible: true} }, commonAxisSettings: { tickInterval: undefined, setTicksAtUnitBeginning: true, valueMarginsEnabled: true, placeholderSize: null, logarithmBase: 10, discreteAxisDivisionMode: 'betweenLabels', visible: false, color: '#d3d3d3', width: 1, multipleAxesSpacing: 5, label: { visible: true, overlappingBehavior: { mode: 'auto', rotationAngle: 90, staggeringSpacing: 5 }, precision: 0, format: '', customizeText: undefined, indentFromAxis: 10 }, grid: { visible: false, color: '#d3d3d3', width: 1 }, tick: { visible: false, color: '#d3d3d3' }, title: { font: {size: 16}, margin: 10 }, stripStyle: { paddingLeftRight: 10, paddingTopBottom: 5 }, constantLineStyle: { paddingLeftRight: 10, paddingTopBottom: 10, width: 1, color: '#000000', dashStyle: 'solid', label: { visible: true, position: 'inside' } } }, horizontalAxis: { isHorizontal: true, position: 'bottom', axisDivisionFactor: 50, label: {alignment: "center"}, stripStyle: {label: { horizontalAlignment: 'center', verticalAlignment: 'top' }}, constantLineStyle: {label: { horizontalAlignment: 'right', verticalAlignment: 'top' }}, constantLines: {} }, verticalAxis: { isHorizontal: false, position: 'left', axisDivisionFactor: 30, label: { alignment: 'right', overlappingBehavior: {mode: 'enlargeTickInterval'} }, stripStyle: {label: { horizontalAlignment: 'left', verticalAlignment: 'center' }}, constantLineStyle: {label: { horizontalAlignment: 'left', verticalAlignment: 'top' }}, constantLines: {} }, argumentAxis: {}, valueAxis: {grid: {visible: true}}, commonPaneSettings: { backgroundColor: 'none', border: { color: '#d3d3d3', width: 1, visible: false, top: true, bottom: true, left: true, right: true, dashStyle: 'solid' } }, useAggregation: false, adjustOnZoom: true, rotated: false, synchronizeMultiAxes: true, equalBarWidth: true, minBubbleSize: 12, maxBubbleSize: 0.2 }), pie: $.extend(true, {}, baseChartTheme, { commonSeriesSettings: { type: 'pie', pie: { border: { visible: false, width: 2, color: '#ffffff' }, hoverStyle: { hatching: { direction: 'right', width: 4, step: 10, opacity: 0.75 }, border: { visible: false, width: 2 } }, selectionStyle: { hatching: { direction: 'right', width: 4, step: 10, opacity: 0.5 }, border: { visible: false, width: 2 } } }, doughnut: { innerRadius: 0.5, border: { visible: false, width: 2, color: '#ffffff' }, hoverStyle: { hatching: { direction: 'right', width: 4, step: 10, opacity: 0.75 }, border: { visible: false, width: 2 } }, selectionStyle: { hatching: { direction: 'right', width: 4, step: 10, opacity: 0.5 }, border: { visible: false, width: 2 } } }, donut: { innerRadius: 0.5, border: { visible: false, width: 2, color: '#ffffff' }, hoverStyle: { hatching: { direction: 'right', width: 4, step: 10, opacity: 0.75 }, border: { visible: false, width: 2 } }, selectionStyle: { hatching: { direction: 'right', width: 4, step: 10, opacity: 0.5 }, border: { visible: false, width: 2 } } } }, legend: {hoverMode: 'markPoint'}, adaptiveLayout: {keepLabels: false} }), pieIE8: {commonSeriesSettings: { pie: { hoverStyle: {border: { visible: true, color: '#ffffff' }}, selectionStyle: {border: { visible: true, color: '#ffffff' }} }, donut: { hoverStyle: {border: { visible: true, color: '#ffffff' }}, selectionStyle: {border: { visible: true, color: '#ffffff' }} }, doughnut: { hoverStyle: {border: { visible: true, color: '#ffffff' }}, selectionStyle: {border: { visible: true, color: '#ffffff' }} } }}, gauge: { containerBackgroundColor: '#ffffff', scale: { majorTick: { visible: true, length: 5, width: 2, showCalculatedTicks: true, useTicksAutoArrangement: true, color: '#ffffff' }, minorTick: { visible: false, length: 3, width: 1, showCalculatedTicks: true, color: '#ffffff' }, label: { visible: true, font: {} } }, rangeContainer: { offset: 0, width: 5, backgroundColor: '#808080' }, valueIndicator: { _default: {color: '#c2c2c2'}, rangebar: { space: 2, size: 10, color: '#cbc5cf', backgroundColor: 'none', text: { indent: 0, font: { size: 14, color: null } } }, twocolorneedle: {secondColor: '#e18e92'}, twocolorrectangle: {secondColor: '#e18e92'} }, subvalueIndicator: { _default: {color: '#8798a5'}, trianglemarker: { space: 2, length: 14, width: 13, color: '#8798a5' }, triangle: { space: 2, length: 14, width: 13, color: '#8798a5' }, textcloud: { arrowLength: 5, horizontalOffset: 6, verticalOffset: 3, color: '#679ec5', text: {font: { color: '#ffffff', size: 18 }} } }, valueIndicators: { _default: {color: '#c2c2c2'}, rangebar: { space: 2, size: 10, color: '#cbc5cf', backgroundColor: 'none', text: { indent: 0, font: { size: 14, color: null } } }, twocolorneedle: {secondColor: '#e18e92'}, trianglemarker: { space: 2, length: 14, width: 13, color: '#8798a5' }, textcloud: { arrowLength: 5, horizontalOffset: 6, verticalOffset: 3, color: '#679ec5', text: {font: { color: '#ffffff', size: 18 }} } }, title: { layout: { horizontalAlignment: 'center', verticalAlignment: 'top', overlay: 0 }, font: { size: 16, color: '#232323', family: fontFamilyDefault, weight: 400 } }, subtitle: {font: { size: 14, color: '#232323', family: fontFamilyDefault, weight: 400 }}, indicator: { hasPositiveMeaning: true, layout: { horizontalAlignment: 'center', verticalAlignment: 'bottom', overlay: 0 }, text: {font: {size: 18}} }, tooltip: { arrowLength: 10, paddingLeftRight: 18, paddingTopBottom: 15, enabled: false, border: { width: 1, color: '#d3d3d3', dashStyle: 'solid', visible: true }, color: '#ffffff', font: { color: '#232323', size: 12, family: fontFamilyDefault, weight: 400 }, shadow: { opacity: 0.4, offsetX: 0, offsetY: 4, blur: 2, color: '#000000' } }, loadingIndicator: { font: {}, backgroundColor: '#ffffff', text: 'Loading...' }, _circular: { scale: { orientation: 'outside', label: {indentFromTick: 10} }, rangeContainer: {orientation: 'outside'}, valueIndicator: { type: 'rectangleneedle', _default: { offset: 20, indentFromCenter: 0, width: 2, spindleSize: 14, spindleGapSize: 10 }, triangleneedle: {width: 4}, triangle: {width: 4}, twocolorneedle: { space: 2, secondFraction: 0.4 }, twocolorrectangle: { space: 2, secondFraction: 0.4 }, rangebar: {offset: 30} }, subvalueIndicator: { type: 'trianglemarker', trianglemarker: {offset: 6}, triangle: {offset: 6}, textcloud: {offset: -6} }, valueIndicators: { _type: 'rectangleneedle', _default: { offset: 20, indentFromCenter: 0, width: 2, spindleSize: 14, spindleGapSize: 10 }, triangleneedle: {width: 4}, twocolorneedle: { space: 2, secondFraction: 0.4 }, rangebar: {offset: 30}, trianglemarker: {offset: 6}, textcloud: {offset: -6} } }, _linear: { scale: { horizontalOrientation: 'right', verticalOrientation: 'bottom', label: {indentFromTick: -10} }, rangeContainer: { horizontalOrientation: 'right', verticalOrientation: 'bottom' }, valueIndicator: { type: 'rangebar', _default: { offset: 2.5, length: 15, width: 15 }, rectangle: {width: 10}, rangebar: { offset: 10, horizontalOrientation: 'right', verticalOrientation: 'bottom' } }, subvalueIndicator: { type: 'trianglemarker', _default: { offset: -1, horizontalOrientation: 'left', verticalOrientation: 'top' } }, valueIndicators: { _type: 'rectangle', _default: { offset: 2.5, length: 15, width: 15 }, rectangle: {width: 10}, rangebar: { offset: 10, horizontalOrientation: 'right', verticalOrientation: 'bottom' }, trianglemarker: { offset: -1, horizontalOrientation: 'left', verticalOrientation: 'top' }, textcloud: { offset: -1, horizontalOrientation: 'left', verticalOrientation: 'top' } } } }, barGauge: { backgroundColor: '#e0e0e0', relativeInnerRadius: 0.3, barSpacing: 4, label: { indent: 20, connectorWidth: 2, font: {size: 16} }, title: { layout: { horizontalAlignment: 'center', verticalAlignment: 'top', overlay: 0 }, font: { size: 16, color: '#232323', family: fontFamilyDefault, weight: 400 } }, subtitle: {font: { size: 14, color: '#232323', family: fontFamilyDefault, weight: 400 }}, indicator: { hasPositiveMeaning: true, layout: { horizontalAlignment: 'center', verticalAlignment: 'bottom', overlay: 0 }, text: {font: {size: 18}} }, tooltip: { arrowLength: 10, paddingLeftRight: 18, paddingTopBottom: 15, enabled: false, border: { width: 1, color: '#d3d3d3', dashStyle: 'solid', visible: true }, color: '#ffffff', font: { size: 12, color: '#232323', family: fontFamilyDefault, weight: 400 }, shadow: { opacity: 0.4, offsetX: 0, offsetY: 4, blur: 2, color: '#000000' } }, loadingIndicator: { font: {}, backgroundColor: '#ffffff', text: 'Loading...' } }, rangeSelector: { containerBackgroundColor: '#ffffff', scale: { label: { topIndent: 7, font: {size: 11} }, tick: { width: 1, color: '#000000', opacity: 0.1 }, marker: { separatorHeight: 33, topIndent: 10, textLeftIndent: 7, textTopIndent: 11 } }, loadingIndicator: { font: {}, backgroundColor: '#ffffff', text: 'Loading...' }, sliderMarker: { padding: 7, pointerSize: 6, color: '#9b9b9b', invalidRangeColor: '#ff0000', font: { color: '#ffffff', size: 11 } }, sliderHandle: { width: 1, color: '#000000', opacity: 0.2 }, shutter: { color: undefined, opacity: 0.75 }, background: {color: "#c0bae1"}, chart: { containerBackgroundColor: undefined, commonSeriesSettings: { label: baseChartTheme.commonSeriesSettings.label, border: { visible: false, width: 1 }, visible: true, type: 'area', hoverMode: 'none', hoverStyle: {border: {}}, selectionStyle: {border: {}}, point: { visible: false, symbol: 'circle', border: { visible: false, width: 1 }, size: 12, hoverStyle: {border: {}}, selectionStyle: {border: {}} }, line: {width: 2}, stepline: {width: 2}, scatter: {point: {visible: true}}, stackedline: {width: 2}, fullstackedline: {width: 2}, area: {opacity: 0.5}, stackedarea: {opacity: 0.5}, fullstackedarea: {opacity: 0.5}, spline: {width: 2}, splinearea: {opacity: 0.5}, steparea: { border: { visible: true, width: 2 }, opacity: 0.5 }, bubble: { opacity: 0.5, point: {visible: true} }, bar: { cornerRadius: 0, point: {visible: true} }, stackedbar: { cornerRadius: 0, point: {visible: true} }, fullstackedbar: { cornerRadius: 0, point: {visible: true} }, rangebar: { cornerRadius: 0, point: {visible: true} }, rangearea: {opacity: 0.5}, rangesplinearea: {opacity: 0.5}, candlestick: { width: 1, innerColor: '#ffffff', reduction: {color: '#ff0000'} }, stock: { width: 1, reduction: {color: '#ff0000'} } }, dataPrepareSettings: { checkTypeForAllData: false, convertToAxisDataType: true, sortingMethod: true }, useAggregation: false, equalBarWidth: true, minBubbleSize: 12, maxBubbleSize: 0.2, topIndent: 0.1, bottomIndent: 0, valueAxis: { min: undefined, max: undefined, inverted: false, logarithmBase: 10 } } }, map: { background: { borderWidth: 1, borderColor: '#cacaca', color: '#ffffff' }, area: { borderWidth: 1, borderColor: '#ffffff', color: '#d2d2d2', hoveredBorderColor: '#303030', selectedBorderWidth: 2, selectedBorderColor: '#303030' }, marker: { font: { color: '#2b2b2b', size: 12 }, _dot: { borderWidth: 2, borderColor: '#ffffff', color: '#ba4d51', size: 8, selectedStep: 2, backStep: 18, backColor: '#ffffff', backOpacity: 0.32, shadow: true }, _bubble: { minSize: 20, maxSize: 50, color: '#ba4d51', hoveredBorderWidth: 1, hoveredBorderColor: '#303030', selectedBorderWidth: 2, selectedBorderColor: '#303030' }, _pie: { size: 50, hoveredBorderWidth: 1, hoveredBorderColor: '#303030', selectedBorderWidth: 2, selectedBorderColor: '#303030' }, _image: {size: 20} }, controlBar: { borderColor: '#5d5d5d', borderWidth: 3, color: '#ffffff' }, tooltip: { borderWidth: 1, borderColor: '#d7d7d7', arrowLength: 10, paddingLeftRight: 18, paddingTopBottom: 15, border: { width: 1, color: '#d3d3d3', dashStyle: 'solid', visible: true }, color: '#ffffff', font: { color: '#232323', size: 12, family: fontFamilyDefault, weight: 400 }, shadow: { opacity: 0.4, offsetX: 0, offsetY: 4, blur: 2, color: '#000000' } }, legend: { verticalAlignment: 'bottom', horizontalAlignment: 'right', position: 'inside', visible: true, margin: 10, equalColumnWidth: false, markerSize: 12, backgroundColor: '#ffffff', backgroundOpacity: 0.65, border: { visible: true, width: 1, color: '#cacaca', cornerRadius: 0, dashStyle: 'solid' }, paddingLeftRight: 16, paddingTopBottom: 12, columnItemSpacing: 20, rowItemSpacing: 8, font: { color: '#2b2b2b', size: 12 } }, loadingIndicator: { backgroundColor: '#ffffff', font: {}, text: 'Loading...' }, _rtl: {legend: {itemTextPosition: 'left'}} }, sparkline: { lineColor: '#666666', lineWidth: 2, areaOpacity: 0.2, minColor: '#e8c267', maxColor: '#e55253', barPositiveColor: '#a9a9a9', barNegativeColor: '#d7d7d7', winColor: '#a9a9a9', lossColor: '#d7d7d7', firstLastColor: '#666666', pointSymbol: 'circle', pointColor: '#ffffff', pointSize: 4, tooltip: { enabled: true, allowContainerResizing: true, verticalAlignment: 'top', horizontalAlignment: 'center', format: '', paddingLeftRight: 18, paddingTopBottom: 15, arrowLength: 10, precision: 0, color: '#ffffff', border: { width: 1, color: '#d3d3d3', dashStyle: 'solid', visible: true }, font: { color: '#232323', family: fontFamilyDefault, size: 12, weight: 400 }, shadow: { opacity: 0.4, offsetX: 0, offsetY: 4, blur: 2, color: '#000000' } } }, bullet: { color: '#e8c267', targetColor: '#666666', targetWidth: 4, showTarget: true, showZeroLevel: true, tooltip: { enabled: true, allowContainerResizing: true, verticalAlignment: 'top', horizontalAlignment: 'center', format: '', precision: 0, paddingLeftRight: 18, paddingTopBottom: 15, arrowLength: 10, color: '#ffffff', border: { width: 1, color: '#d3d3d3', dashStyle: 'solid', visible: true }, font: { color: '#232323', family: fontFamilyDefault, size: 12, weight: 400 }, shadow: { opacity: 0.4, offsetX: 0, offsetY: 4, blur: 2, color: '#000000' } } } }); DX.viz.core.registerTheme({ name: 'desktop-dark', font: {color: '#808080'}, chart: $.extend(true, {}, baseDarkChartTheme, { commonSeriesSettings: {candlestick: {innerColor: '#2b2b2b'}}, crosshair: {color: '#515151'}, commonAxisSettings: { color: '#494949', grid: {color: '#494949'}, tick: {color: '#494949'}, constantLineStyle: {color: '#ffffff'} }, commonPaneSettings: {border: {color: '#494949'}} }), pie: $.extend(true, {}, baseDarkChartTheme), pieIE8: {commonSeriesSettings: { pie: { hoverStyle: {border: {color: '#2b2b2b'}}, selectionStyle: {border: {color: '#2b2b2b'}} }, donut: { hoverStyle: {border: {color: '#2b2b2b'}}, selectionStyle: {border: {color: '#2b2b2b'}} }, doughnut: { hoverStyle: {border: {color: '#2b2b2b'}}, selectionStyle: {border: {color: '#2b2b2b'}} } }}, gauge: { containerBackgroundColor: '#2b2b2b', scale: { majorTick: {color: '#303030'}, minorTick: {color: '#303030'} }, rangeContainer: {backgroundColor: '#b5b5b5'}, valueIndicator: { _default: {color: '#b5b5b5'}, rangebar: {color: '#84788b'}, twocolorneedle: {secondColor: '#ba544d'}, twocolorrectangle: {secondColor: '#ba544d'} }, subvalueIndicator: {_default: {color: '#b7918f'}}, valueIndicators: { _default: {color: '#b5b5b5'}, rangebar: {color: '#84788b'}, twocolorneedle: {secondColor: '#ba544d'}, trianglemarker: {color: '#b7918f'}, textcloud: {color: '#ba544d'} }, title: {font: {color: '#929292'}}, subtitle: {font: {color: '#929292'}}, loadingIndicator: {backgroundColor: '#2b2b2b'}, tooltip: { color: '#2b2b2b', border: {color: '#494949'}, font: {color: '#929292'} } }, barGauge: { title: {font: {color: '#929292'}}, subtitle: {font: {color: '#929292'}}, tooltip: { color: '#2b2b2b', border: {color: '#494949'}, font: {color: '#929292'} }, loadingIndicator: {backgroundColor: '#2b2b2b'} }, rangeSelector: { containerBackgroundColor: '#2b2b2b', scale: {tick: { color: '#ffffff', opacity: 0.05 }}, loadingIndicator: {backgroundColor: '#2b2b2b'}, sliderMarker: { color: '#b5b5b5', font: {color: '#303030'} }, sliderHandle: { color: '#ffffff', opacity: 0.35 }, shutter: { color: '#2b2b2b', opacity: 0.9 } }, map: { background: { borderColor: '#3f3f3f', color: '#303030' }, area: { borderColor: '#303030', color: '#686868', hoveredBorderColor: '#ffffff', selectedBorderColor: '#ffffff' }, marker: { font: {color: '#ffffff'}, _bubble: { hoveredBorderColor: '#ffffff', selectedBorderColor: '#ffffff' }, _pie: { hoveredBorderColor: '#ffffff', selectedBorderColor: '#ffffff' } }, controlBar: { borderColor: '#c7c7c7', color: '#303030' }, legend: { border: {color: '#3f3f3f'}, backgroundColor: '#303030', font: {color: '#ffffff'} }, tooltip: { color: '#2b2b2b', border: {color: '#494949'}, font: {color: '#929292'} }, loadingIndicator: {backgroundColor: '#2b2b2b'} }, sparkline: { lineColor: '#c7c7c7', firstLastColor: '#c7c7c7', barPositiveColor: '#b8b8b8', barNegativeColor: '#8e8e8e', winColor: '#b8b8b8', lossColor: '#8e8e8e', pointColor: '#303030', tooltip: { color: '#2b2b2b', border: {color: '#494949'}, font: {color: '#929292'} } }, bullet: { targetColor: '#8e8e8e', tooltip: { color: '#2b2b2b', border: {color: '#494949'}, font: {color: '#929292'} } } }, 'desktop') })(jQuery, DevExpress); /*! Module viz-core, file android.js */ (function($, DX, undefined) { var baseChartTheme = { containerBackgroundColor: '#050506', title: {font: {color: '#ffffff'}}, commonSeriesSettings: {label: {border: {color: '#4c4c4c'}}}, legend: { font: { color: '#ffffff', size: 11 }, border: {color: '#4c4c4c'} }, loadingIndicator: {backgroundColor: '#050506'}, tooltip: { color: '#050506', border: {color: '#4c4c4c'}, font: {color: '#ffffff'} } }, baseLightChartTheme = { containerBackgroundColor: '#e8e8e8', title: {font: {color: '#808080'}}, legend: {font: { color: '#000000', size: 11 }}, loadingIndicator: {backgroundColor: '#e8e8e8'}, tooltip: { color: '#e8e8e8', font: {color: '#808080'} } }; DX.viz.core.registerTheme({ name: 'android', chart: $.extend(true, {}, baseChartTheme, { commonSeriesSettings: {candlestick: {innerColor: '#050506'}}, commonAxisSettings: { color: '#4c4c4c', grid: {color: '#4c4c4c'}, tick: {color: '#4c4c4c'}, title: {font: {color: '#545455'}}, label: {font: { color: '#ffffff', size: 11 }} }, commonPaneSettings: {border: {color: '#4c4c4c'}} }), pie: $.extend(true, {}, baseChartTheme), pieIE8: {commonSeriesSettings: { pie: { hoverStyle: {border: {color: '#050506'}}, selectionStyle: {border: {color: '#050506'}} }, donut: { hoverStyle: {border: {color: '#050506'}}, selectionStyle: {border: {color: '#050506'}} }, doughnut: { hoverStyle: {border: {color: '#050506'}}, selectionStyle: {border: {color: '#050506'}} } }}, gauge: { containerBackgroundColor: '#050506', title: {font: {color: '#ffffff'}}, subtitle: {font: {color: '#ffffff'}}, loadingIndicator: {backgroundColor: '#050506'}, tooltip: { color: '#050506', border: {color: '#4c4c4c'}, font: {color: '#ffffff'} } }, barGauge: { title: {font: {color: '#ffffff'}}, subtitle: {font: {color: '#ffffff'}}, tooltip: { color: '#050506', border: {color: '#4c4c4c'}, font: {color: '#ffffff'} }, loadingIndicator: {backgroundColor: '#050506'} }, rangeSelector: { containerBackgroundColor: '#050506', loadingIndicator: {backgroundColor: '#050506'} }, map: { loadingIndicator: {backgroundColor: '#050506'}, tooltip: { color: '#050506', border: {color: '#4c4c4c'}, font: {color: '#ffffff'} } }, sparkline: {tooltip: { color: '#050506', border: {color: '#4c4c4c'}, font: {color: '#ffffff'} }}, bullet: {tooltip: { color: '#050506', border: {color: '#4c4c4c'}, font: {color: '#ffffff'} }} }, 'desktop-dark'); DX.viz.core.registerTheme({ name: 'android-holo-light', chart: $.extend(true, {}, baseLightChartTheme, { commonSeriesSettings: {candlestick: {innerColor: '#e8e8e8'}}, commonAxisSettings: { title: {font: {color: '#939393'}}, label: {font: { color: '#404040', size: 11 }} } }), pie: $.extend(true, {}, baseLightChartTheme), pieIE8: {commonSeriesSettings: { pie: { hoverStyle: {border: {color: '#e8e8e8'}}, selectionStyle: {border: {color: '#e8e8e8'}} }, donut: { hoverStyle: {border: {color: '#e8e8e8'}}, selectionStyle: {border: {color: '#e8e8e8'}} }, doughnut: { hoverStyle: {border: {color: '#e8e8e8'}}, selectionStyle: {border: {color: '#e8e8e8'}} } }}, gauge: { containerBackgroundColor: '#e8e8e8', title: {font: {color: '#808080'}}, subtitle: {font: {color: '#808080'}}, loadingIndicator: {backgroundColor: '#e8e8e8'}, tooltip: { color: '#e8e8e8', font: {color: '#808080'} } }, barGauge: { title: {font: {color: '#808080'}}, subtitle: {font: {color: '#808080'}}, tooltip: { color: '#e8e8e8', font: {color: '#808080'} }, loadingIndicator: {backgroundColor: '#e8e8e8'} }, rangeSelector: { containerBackgroundColor: '#e8e8e8', loadingIndicator: {backgroundColor: '#e8e8e8'} }, map: { loadingIndicator: {backgroundColor: '#e8e8e8'}, tooltip: { color: '#e8e8e8', font: {color: '#808080'} } }, sparkline: {tooltip: { color: '#e8e8e8', font: {color: '#808080'} }}, bullet: {tooltip: { color: '#e8e8e8', font: {color: '#808080'} }} }, 'desktop') })(jQuery, DevExpress); /*! Module viz-core, file ios.js */ (function($, DX, undefined) { var baseChartTheme = { containerBackgroundColor: '#cbd0da', title: {font: {color: '#808080'}}, commonSeriesSettings: {label: {border: {color: '#b0b3ba'}}}, legend: { font: { color: '#000000', size: 11 }, border: {color: '#b0b3ba'} }, loadingIndicator: {backgroundColor: '#cbd0da'}, tooltip: {font: {color: '#808080'}} }, baseIos7ChartTheme = { containerBackgroundColor: '#ffffff', title: {font: {color: '#808080'}}, commonSeriesSettings: {label: {border: {color: '#d3d3d3'}}}, legend: { font: { color: '#000000', size: 11 }, border: {color: '#d3d3d3'} }, loadingIndicator: {backgroundColor: '#ffffff'}, tooltip: {font: {color: '#808080'}} }; DX.viz.core.registerTheme({ name: 'ios', chart: $.extend(true, {}, baseChartTheme, { commonSeriesSettings: {candlestick: {innerColor: '#cbd0da'}}, commonAxisSettings: { color: '#b0b3ba', grid: {color: '#b0b3ba'}, tick: {color: '#b0b3ba'}, title: {font: {color: '#939393'}}, label: {font: { color: '#000000', size: 11 }} }, commonPaneSettings: {border: {color: '#b0b3ba'}} }), pie: $.extend(true, {}, baseChartTheme), pieIE8: {commonSeriesSettings: { pie: { hoverStyle: {border: {color: '#cbd0da'}}, selectionStyle: {border: {color: '#cbd0da'}} }, donut: { hoverStyle: {border: {color: '#cbd0da'}}, selectionStyle: {border: {color: '#cbd0da'}} }, doughnut: { hoverStyle: {border: {color: '#cbd0da'}}, selectionStyle: {border: {color: '#cbd0da'}} } }}, gauge: { title: {font: {color: '#808080'}}, subtitle: {font: {color: '#808080'}}, tooltip: {font: {color: '#808080'}} }, barGauge: { title: {font: {color: '#808080'}}, subtitle: {font: {color: '#808080'}}, tooltip: {font: {color: '#808080'}} }, map: {tooltip: {font: {color: '#808080'}}}, sparkline: {tooltip: {font: {color: '#808080'}}}, bullet: {tooltip: {font: {color: '#808080'}}} }, 'desktop'); DX.viz.core.registerTheme({ name: 'ios:7', chart: $.extend(true, {}, baseIos7ChartTheme, { commonAxisSettings: { color: '#d3d3d3', grid: {color: '#d3d3d3'}, tick: {color: '#d3d3d3'}, title: {font: {color: '#939393'}}, label: {font: { color: '#000000', size: 11 }} }, commonPaneSettings: {border: {color: '#d3d3d3'}} }), pie: $.extend(true, {}, baseIos7ChartTheme), gauge: { title: {font: {color: '#808080'}}, subtitle: {font: {color: '#808080'}}, tooltip: {font: {color: '#808080'}} }, barGauge: { title: {font: {color: '#808080'}}, subtitle: {font: {color: '#808080'}}, tooltip: {font: {color: '#808080'}} }, map: {tooltip: {font: {color: '#808080'}}}, sparkline: {tooltip: {font: {color: '#808080'}}}, bullet: {tooltip: {font: {color: '#808080'}}} }, 'desktop') })(jQuery, DevExpress); /*! Module viz-core, file win8.js */ (function($, DX) { var baseChartTheme = { containerBackgroundColor: '#000000', title: {font: {color: '#ffffff'}}, commonSeriesSettings: {label: {border: {color: '#454545'}}}, legend: { font: { color: '#ffffff', size: 11 }, border: {color: '#454545'} }, loadingIndicator: {backgroundColor: '#000000'}, tooltip: { color: '#000000', font: {color: '#ffffff'} } }, baseWhiteChartTheme = { title: {font: {color: '#808080'}}, legend: {font: { color: '#000000', size: 11 }}, tooltip: {font: {color: '#808080'}} }; DX.viz.core.registerTheme({ name: 'win8', chart: $.extend(true, {}, baseChartTheme, { commonSeriesSettings: {candlestick: {innerColor: '#000000'}}, commonAxisSettings: { color: '#454545', grid: {color: '#454545'}, tick: {color: '#454545'}, title: {font: {color: '#535353'}}, label: {font: { color: '#ffffff', size: 11 }} }, commonPaneSettings: {border: {color: '#454545'}} }), pie: $.extend(true, {}, baseChartTheme), pieIE8: {commonSeriesSettings: { pie: { hoverStyle: {border: {color: '#000000'}}, selectionStyle: {border: {color: '#000000'}} }, donut: { hoverStyle: {border: {color: '#000000'}}, selectionStyle: {border: {color: '#000000'}} }, doughnut: { hoverStyle: {border: {color: '#000000'}}, selectionStyle: {border: {color: '#000000'}} } }}, gauge: { containerBackgroundColor: '#000000', title: {font: {color: '#ffffff'}}, subtitle: {font: {color: '#ffffff'}}, loadingIndicator: {backgroundColor: '#000000'}, tooltip: { color: '#000000', font: {color: '#ffffff'} } }, barGauge: { title: {font: {color: '#ffffff'}}, subtitle: {font: {color: '#ffffff'}}, tooltip: { color: '#000000', font: {color: '#ffffff'} }, loadingIndicator: {backgroundColor: '#000000'} }, rangeSelector: { containerBackgroundColor: '#000000', loadingIndicator: {backgroundColor: '#000000'} }, map: { loadingIndicator: {backgroundColor: '#000000'}, tooltip: { color: '#000000', font: {color: '#ffffff'} } }, sparkline: {tooltip: { color: '#000000', font: {color: '#ffffff'} }}, bullet: {tooltip: { color: '#000000', font: {color: '#ffffff'} }} }, 'desktop-dark'); DX.viz.core.registerTheme({ name: 'win8-white', chart: $.extend(true, {}, baseWhiteChartTheme, {commonAxisSettings: { title: {font: {color: '#939393'}}, label: {font: { color: '#404040', size: 11 }} }}), pie: $.extend(true, {}, baseWhiteChartTheme), gauge: { title: {font: {color: '#808080'}}, subtitle: {font: {color: '#808080'}}, tooltip: {font: {color: '#808080'}} }, barGauge: { title: {font: {color: '#808080'}}, subtitle: {font: {color: '#808080'}}, tooltip: {font: {color: '#808080'}} }, map: {tooltip: {font: {color: '#808080'}}}, sparkline: {tooltip: {font: {color: '#808080'}}}, bullet: {tooltip: {font: {color: '#808080'}}} }, 'desktop') })(jQuery, DevExpress); /*! Module viz-core, file others.js */ (function($, DX) { DX.viz.core.registerTheme({name: 'generic'}, 'desktop'); DX.viz.core.registerTheme({name: 'generic-dark'}, 'desktop-dark'); DX.viz.core.registerTheme({name: 'tizen'}, 'desktop'); DX.viz.core.registerTheme({name: 'tizen-black'}, 'desktop-dark') })(jQuery, DevExpress); /*! Module viz-core, file namespaces.js */ (function(DevExpress) { DevExpress.viz.renderers = {} })(DevExpress); /*! Module viz-core, file svgRenderer.js */ (function($, DX) { var renderers = DX.viz.renderers, utils = DX.utils, Class = DX.Class, doc = document, MAX_PIXEL_COUNT = 10000000000; function createElement(name) { return doc.createElementNS('http://www.w3.org/2000/svg', name) } function getPatternUrl(id, pathModified) { return id !== null ? 'url(' + (pathModified ? window.location.href : '') + '#' + id + ')' : null } var BaseSvgElement = Class.inherit({ ctor: function baseSvgElementCtor(renderer, name, params) { this.renderer = renderer; this.element = this.createElement(name); this.$element = $(this.element); this.applySettings($.extend({}, this.defaultSettings(), params)); this.__passedParams = params }, defaultSettings: $.noop, createElement: function(nodeName) { this._nodeName = nodeName; return createElement(nodeName) }, dispose: function() { this.off(); this.remove(); this.renderer = null; this.element = null; this.settings = null; this.$element = null; this.transformation = null; this.__passedParams = null; this.__appliedSettings = null; this.__appliedStyle = null }, append: function(svgElement) { var toElement = svgElement || this.renderer.getRoot(); toElement.element.appendChild(this.element); return this }, insertBefore: function(target) { target.element.parentNode.insertBefore(this.element, target.element); return this }, toBackground: function() { this.element.parentNode && this.element.parentNode.insertBefore(this.element, this.element.parentNode.firstChild); return this }, toForeground: function() { this.element.parentNode && this.element.parentNode.appendChild(this.element); return this }, addClass: function(className) { var classAttribute = this.$element.attr('class'), classNameIndex, classNames; if (className) { if (classAttribute) { classNames = classAttribute.split(' '); classNameIndex = $.inArray(className, classNames); if (classNameIndex === -1) classAttribute += ' ' + className } else classAttribute = className; this.$element.attr('class', classAttribute) } return this.$element }, removeClass: function(className) { var classAttribute = this.$element.attr('class'), classNames, indexDeleteElement, resultClassNames = '', i; if (classAttribute && className) { classNames = classAttribute.split(' '); indexDeleteElement = $.inArray(className, classNames); if (indexDeleteElement !== -1) { for (i = 0; i < classNames.length; i++) if (i !== indexDeleteElement) resultClassNames += classNames[i] + ' '; this.$element.attr('class', resultClassNames.replace(/ $/, '')) } } return this.$element }, applySettings: function(settings) { var normalized; this.settings = $.extend(this.settings || {}, settings || {}); this.adjustSettings(); normalized = this._normalizeSettings(this.settings); this.applyStyle(this._style); this._applyAttributes(normalized); return this }, _applyAttributes: function(settings) { this.$element.attr(settings); this.__appliedSettings = settings }, adjustSettings: function(){}, applyStyle: function(style) { this.$element.css(style || {}); this.__appliedStyle = style || {}; return this }, trigger: function(event, data) { this.$element.trigger(event, data) }, on: function(events, data, handler) { this.$element.on.apply(this.$element, arguments); return this }, data: function(key, value) { this.$element.data(key, value); return this }, removeData: function() { this.$element.removeData(); return this }, off: function(events) { this.$element.off(events); return this }, getBBox: function() { var that = this, bBox, element = this.element, transformation = that.transformation, rotateAngle = transformation.rotateAngle || 0, rotateX = transformation.rotateX || 0, rotateY = transformation.rotateY || 0, mabs = Math.abs, mmin = Math.min; function bBox(el) { var ret = {}; try { if (!$.isFunction(el.getBBox)) throw{}; else ret = el.getBBox() } catch(e) { ret = { x: 0, y: 0, width: el.offsetWidth || 0, height: el.offsetHeight || 0 } } return ret } bBox = $.extend({}, bBox(element)); if (rotateAngle) { var cossin = utils.getCosAndSin(rotateAngle), sin = cossin.sin.toFixed(3), cos = cossin.cos.toFixed(3), ltx = bBox.x - rotateX, lty = bBox.y - rotateY, rtx = bBox.x + bBox.width - rotateX, rty = bBox.y - rotateY, lbx = bBox.x - rotateX, lby = bBox.y + bBox.height - rotateY, rbx = bBox.x + bBox.width - rotateX, rby = bBox.y + bBox.height - rotateY, w, h; w = mabs(bBox.height * sin) + mabs(bBox.width * cos); h = mabs(bBox.height * cos) + mabs(bBox.width * sin); bBox.x = mmin(ltx * cos - lty * sin + rotateX, rtx * cos - rty * sin + rotateX, lbx * cos - lby * sin + rotateX, rbx * cos - rby * sin + rotateX); bBox.y = mmin(ltx * sin + lty * cos + rotateY, rtx * sin + rty * cos + rotateY, lbx * sin + lby * cos + rotateY, rbx * sin + rby * cos + rotateY); bBox.width = w; bBox.height = h } return that._normalizeBBox(bBox) }, _normalizeBBox: function(bBox) { var ceil = Math.ceil, floor = Math.floor, $isNumeric = $.isNumeric, rxl = floor(bBox.x), ryt = floor(bBox.y), rxr = ceil(bBox.width + bBox.x), ryb = ceil(bBox.height + bBox.y), width, height; bBox.x = $isNumeric(rxl) && rxl < MAX_PIXEL_COUNT && rxl > -MAX_PIXEL_COUNT ? rxl : 0; bBox.y = $isNumeric(ryt) && ryt < MAX_PIXEL_COUNT && ryt > -MAX_PIXEL_COUNT ? ryt : 0; width = rxr - rxl; height = ryb - ryt; bBox.width = $isNumeric(width) && width < MAX_PIXEL_COUNT && width > -MAX_PIXEL_COUNT ? width : 0; bBox.height = $isNumeric(height) && height < MAX_PIXEL_COUNT && height > -MAX_PIXEL_COUNT ? height : 0; bBox.isEmpty = !bBox.x && !bBox.y && !bBox.width && !bBox.height; return bBox }, clear: function(selector) { selector ? this.$element.find(selector).remove() : this.$element.empty(); return this }, detach: function() { this.$element.detach(); return this }, animate: function(params, options, complete) { options = options || {}; var that = this, animationParams = {}; if (complete) $.extend(options, {complete: complete}); if (this.renderer.animOptions.enabled) { $.each(params, function(name, to) { switch (name) { case'scale': animationParams['transform'] = animationParams['transform'] || {}; var scale = that.transformation.scale || {}; animationParams['transform'].scale = { x: { from: utils.isDefined(scale.x) ? scale.x : 1, to: utils.isDefined(to.x) ? to.x : 1 }, y: { from: utils.isDefined(scale.y) ? scale.y : 1, to: utils.isDefined(to.y) ? to.y : 1 } }; break; case'rotate': animationParams['transform'] = animationParams['transform'] || {}; animationParams['transform'].rotate = { angle: { from: that.transformation.rotateAngle || 0, to: to.angle }, y: to.y || 0, x: to.x || 0 }; break; case'translate': animationParams['transform'] = animationParams['transform'] || {}; animationParams['transform'].translate = { x: { from: that.transformation.translateX || 0, to: to.x || 0 }, y: { from: that.transformation.translateY || 0, to: to.y || 0 } }; break; case'arc': case'points': animationParams[name] = to; break; default: animationParams[name] = { from: that.settings[name] || 0, to: to } } }); that.renderer.animateElement(that, animationParams, $.extend({}, this.renderer.animOptions, options)) } else { if (params.translate) { if ('x' in params.translate) params.translateX = params.translate.x; if ('y' in params.translate) params.translateY = params.translate.y; delete params.translate } if (options) { options.step && options.step.call(that, 1, 1); options.complete && options.complete.call(that) } this.applySettings(params) } }, stopAnimation: function(disableComplete) { var that = this; that.animation && that.animation.stop(true, disableComplete); return that }, move: function(x, y, animate, animOptions) { x = x || 0, y = y || 0; animOptions = animOptions || {}; if (!animate) this.applySettings({ translateX: x, translateY: y }); else this.animate({translate: { x: x, y: y }}, animOptions); return this }, rotate: function(angle, x, y, animate, animOptions) { angle = angle || 0; x = x || 0; y = y || 0; animOptions = animOptions || {}; if (!animate) this.applySettings({rotate: [angle, x, y]}); else this.animate({rotate: { angle: angle, x: x, y: y }}, animOptions) }, remove: function() { this.$element.remove() }, _normalizeSettings: function(settings) { var key, style, firstChar, styleName, prop, value, normalized = {}, fontSetting, rtl = this.renderer.rtl; for (key in settings) { prop = key, value = settings[prop]; if (prop === 'align') { prop = 'text-anchor'; value = { left: rtl ? 'end' : 'start', center: 'middle', right: rtl ? 'start' : 'end' }[value] } else if (prop === 'font') { style = this['_style'] = this['_style'] || {}; if (!$.isPlainObject(value)) continue; $.each(value, function(fontSetting) { switch (fontSetting) { case'color': styleName = 'fill'; break; case'opacity': styleName = 'fillOpacity'; break; case'cursor': styleName = fontSetting; break; default: firstChar = fontSetting.charAt(0); styleName = 'font' + fontSetting.replace(firstChar, firstChar.toUpperCase()) } style[styleName] = value[fontSetting] }); continue } else if (prop === 'dashStyle') { prop = 'stroke-dasharray'; value = (value || 'none').toLowerCase(); if (value === 'solid' || value === 'none') value = null; else { value = value.replace(/longdash/g, '8,3,').replace(/dash/g, '4,3,').replace(/dot/g, '1,3,').replace(/,$/, '').split(','); value = $.map(value, function(p) { return +p * (settings.strokeWidth || 1) }).join(',') } } else if (/^(linecap|linejoin)$/i.test(prop)) prop = 'stroke-' + prop; else if (/^(translateX|translateY|rotate|scale)$/i.test(prop)) { this['_' + prop] = value; continue } else if (prop === 'clipId') { prop = 'clip-path'; value = getPatternUrl(value, this.renderer.pathModified) } else if (prop === 'style') { this['_style'] = this['_style'] || {}; $.extend(true, this['_style'], value); continue } else if (prop === 'sharpEdges') continue; else if (prop === 'text') continue; else if (prop === 'segments') continue; else prop = DX.inflector.dasherize(prop); normalized[prop] = value } return this._applyTransformation(normalized) }, _applyTransformation: function(settings) { this.transformation = { translateX: this._translateX, translateY: this._translateY, rotateAngle: 0, rotateX: 0, rotateY: 0 }; var tr = this.transformation, rotate = this._rotate, scale = this._scale, transformations = []; if (utils.isDefined(tr.translateX) || utils.isDefined(tr.translateY)) transformations.push('translate(' + (tr.translateX || 0) + ',' + (tr.translateY || 0) + ')'); if (utils.isDefined(rotate)) { if (utils.isNumber(rotate)) { tr.rotateAngle = rotate; tr.rotateX = settings.x || 0; tr.rotateY = settings.y || 0 } else if ($.isArray(rotate)) { tr.rotateAngle = rotate[0] || 0; tr.rotateX = rotate[1] || 0; tr.rotateY = rotate[2] || 0 } else if (utils.isObject(rotate)) { tr.rotateAngle = rotate.angle || 0; tr.rotateX = rotate.x || 0; tr.rotateY = rotate.y || 0 } transformations.push('rotate(' + tr.rotateAngle + ',' + tr.rotateX + ',' + tr.rotateY + ')') } if (utils.isNumber(scale)) { var value = utils.isDefined(scale) ? scale : 1; transformations.push('scale(' + value + ',' + value + ')'); tr.scale = { x: value, y: value } } else if (utils.isObject(scale)) { var valueX = utils.isDefined(scale.x) ? scale.x : 1; var valueY = utils.isDefined(scale.y) ? scale.y : 1; transformations.push('scale(' + valueX + ',' + valueY + ')'); tr.scale = { x: valueX, y: valueY } } if (transformations.length) settings.transform = transformations.join(' '); return settings } }); var RootSvgElement = BaseSvgElement.inherit({ defaultSettings: function() { return { width: 0, height: 0, style: { '-webkit-tap-highlight-color': 'rgba(0, 0, 0, 0)', display: 'block', overflow: 'hidden' }, xmlns: 'http://www.w3.org/2000/svg', 'xmlns:xlink': 'http://www.w3.org/1999/xlink', version: '1.1', stroke: 'none', strokeWidth: 0, fill: 'none' } }, ctor: function(renderer, params) { this.callBase(renderer, 'svg', params) } }); var RectSvgBaseElement = { defaultSettings: function() { return { x: 0, y: 0, width: 0, height: 0 } }, adjustSettings: function() { if (!utils.isDefined(this.settings.sharpEdges) || this.settings.sharpEdges) { this.sharpEdges(); delete this.settings.sharpEdges } }, prepareSettings: function(settings) { var prevStrokeWidth = this.settings ? Number(this.settings.strokeWidth) || 0 : 0, newStrokeWidth, maxStrokeWidth, strokeWidthChanged = false; if (utils.isDefined(settings.width)) this._realWidth = Number(settings.width); if (utils.isDefined(settings.height)) this._realHeight = Number(settings.height); if (utils.isDefined(settings.x)) this._realX = Number(settings.x); if (utils.isDefined(settings.y)) this._realY = Number(settings.y); if (utils.isDefined(settings.strokeWidth)) this._realStrokeWidth = Number(settings.strokeWidth); this._realStrokeWidth = this._realStrokeWidth || this.defaultSettings().strokeWidth || 0; maxStrokeWidth = ~~((this._realWidth < this._realHeight ? this._realWidth : this._realHeight) / 2); newStrokeWidth = this._realStrokeWidth < maxStrokeWidth ? this._realStrokeWidth : maxStrokeWidth; if (newStrokeWidth !== prevStrokeWidth) { strokeWidthChanged = true; settings.sharpEdges = true; newStrokeWidth > 0 && (settings.strokeWidth = newStrokeWidth) } (utils.isDefined(settings.x) || strokeWidthChanged) && (settings.x = this._realX + newStrokeWidth / 2); (utils.isDefined(settings.y) || strokeWidthChanged) && (settings.y = this._realY + newStrokeWidth / 2); (utils.isDefined(settings.width) || strokeWidthChanged) && (settings.width = this._realWidth - newStrokeWidth); (utils.isDefined(settings.height) || strokeWidthChanged) && (settings.height = this._realHeight - newStrokeWidth) }, applySettings: function(settings) { var settings = $.extend(true, {}, settings); this.prepareSettings(settings); return this.callBase(settings) }, sharpEdges: function() { var strokeWidth = Math.round(this.settings.strokeWidth || 0), correction = strokeWidth % 2 / 2; this.settings.x = Math.floor(this.settings.x - correction || 0) + correction; this.settings.y = Math.floor(this.settings.y - correction || 0) + correction; this.settings.width = Math.floor(this.settings.width || 0); this.settings.height = Math.floor(this.settings.height || 0); this.settings.strokeWidth > 0 && (this.settings.strokeWidth = strokeWidth) } }; var ImageSvgElement = BaseSvgElement.inherit(RectSvgBaseElement).inherit({ ctor: function(renderer, params, href, location) { var locationToPreserveAspectRatioMap = { full: 'none', lefttop: 'xMinYMin', leftcenter: 'xMinYMid', leftbottom: 'xMinYMax', centertop: 'xMidYMin', center: 'xMidYMid', centerbottom: 'xMidYMax', righttop: 'xMaxYMin', rightcenter: 'xMaxYMid', rightbottom: 'xMaxYMax' }; this.href = utils.isDefined(href) ? href : ''; this.preserveAspectRatio = locationToPreserveAspectRatioMap[(location || '').toLowerCase()]; this.preserveAspectRatio = this.preserveAspectRatio || 'none'; this.callBase(renderer, 'image', params) }, adjustSettings: function() { this.callBase(); this.element.setAttributeNS('http://www.w3.org/1999/xlink', 'href', this.href); if (this.preserveAspectRatio) this.element.setAttribute('preserveAspectRatio', this.preserveAspectRatio) } }); var RectSvgElement = BaseSvgElement.inherit(RectSvgBaseElement).inherit({ defaultSettings: function() { return { x: 0, y: 0, width: 0, height: 0, rx: 0, ry: 0 } }, ctor: function(renderer, params) { this.callBase(renderer, 'rect', params) } }); var PathSvgElement = BaseSvgElement.inherit({ defaultSettings: function() { return {points: { x: 0, y: 0 }} }, getNodeName: function() { return 'path' }, getPathAttributeName: function() { return 'd' }, ctor: function(renderer, params) { this.callBase(renderer, this.getNodeName(), params) }, dispose: function() { this.segments = null; this.fromSegments = null; this.callBase() }, adjustSettings: function() { this.prepareSegments(this.settings) }, applySettings: function(settings) { var settings = settings || {}; if (this.settings && settings.strokeWidth && this.settings.strokeWidth !== settings.strokeWidth) settings.sharpEdges = true; return this.callBase(settings) }, prepareSegments: function(params) { if ('points' in params) { var points = params.points, firstElem = points[0], close = this.closePath || params.closePath, segments = [], i; if (utils.isObject(firstElem)) segments = $.map(points, function(pt, i) { if (!pt) return null; if (!i) return [['M', pt.x, pt.y]]; return [['L', pt.x, pt.y]] }); else if (utils.isNumber(firstElem)) for (i = 0; i < points.length; i += 2) { if (!i) { segments = [['M', points[i] || 0, points[i + 1] || 0]]; continue } segments.push(['L', points[i] || 0, points[i + 1] || 0]) } else segments = [['M', 0, 0]]; if (close) segments.push(['Z']); this.segments = segments; delete params.points; delete params.closePath; params.sharpEdges = true } if (params.sharpEdges) { this.sharpEdges(); this.combinePathParams(params); delete params.sharpEdges } }, customizeSegments: function(segments) { return segments }, combinePathParams: function(params) { var path; this.segments = this.customizeSegments(this.segments); if (this.segments) { path = $.map(this.segments, function(seg, i) { return seg.join(' ') }); path = path.join(' '); params[this.getPathAttributeName()] = path } }, _prepareDifferrentPath: function(from, to) { var end = {}, constsSeg; if (to.length > from.length) this._makeEqualPath(from, to); else { this.combinePathParams(end); this._makeEqualPath(to, from) } return end.d }, _prepareConstSegment: function(seg) { seg[0] = "L" }, _makeEqualPath: function(short, long) { var constSeg = short[short.length - 1].slice(); this._prepareConstSegment(constSeg); for (var i = short.length; i < long.length; i++) short[i] = constSeg }, animate: function(params, options, complete) { var that = this; if (!('points' in params) || !that.renderer.animOptions.enabled) return that.callBase(params, options, complete); var fromPath = that.segments, end; that.prepareSegments(params); delete params.d; if (fromPath.length === that.segments.length) params.points = { from: fromPath, to: that.segments }; else end = that._prepareDifferrentPath(fromPath, that.segments); params.points = { from: fromPath, to: that.segments, end: end }; that.callBase(params, options, complete) }, sharpEdges: function() { var that = this, segLength = that.segments.length, i = 0, curSeg, nextSeg, curX, curY, nextX, nextY, curXIdx, curYIdx, nextXIdx, nextYIdx, strokeWidth = Math.round(that.settings.strokeWidth || 0), correction = strokeWidth % 2 / 2; for (i; i < segLength - 1; i++) { curSeg = that.segments[i]; nextSeg = that.segments[i + 1]; if (nextSeg[0] === 'Z' && i) nextSeg = that.segments[0]; switch (curSeg[0]) { case'M': case'L': curXIdx = 1; curYIdx = 2; break; case'C': curXIdx = 5; curYIdx = 6; break; case'A': curXIdx = 6; curYIdx = 7; break; case'Z': continue } switch (nextSeg[0]) { case'M': case'L': nextXIdx = 1; nextYIdx = 2; break; case'C': nextXIdx = 5; nextYIdx = 6; break; case'A': nextXIdx = 6; nextYIdx = 7; break; case'Z': continue } curX = Math.floor(curSeg[curXIdx]); curY = Math.floor(curSeg[curYIdx]); nextX = nextSeg[nextXIdx] = Math.floor(nextSeg[nextXIdx]); nextY = nextSeg[nextYIdx] = Math.floor(nextSeg[nextYIdx]); curSeg[curXIdx] = i == 0 ? curX : curSeg[curXIdx]; curSeg[curYIdx] = i == 0 ? curY : curSeg[curYIdx]; if (curX == nextX) { curSeg[curXIdx] = curX + correction; nextSeg[nextXIdx] = nextX + correction } if (curY == nextY) { curSeg[curYIdx] = curY + correction; nextSeg[nextYIdx] = nextY + correction } } } }); var SegmentRectSvgElement = PathSvgElement.inherit(RectSvgBaseElement).inherit({ defaultSettings: function() { return $.extend(true, {}, this.callBase(), {segments: { top: true, bottom: true, left: true, right: true }}) }, prepareSegments: function() { var that = this, settings = that.settings, left = settings.x, right = left + settings.width, top = settings.y, bottom = top + settings.height, segments = [], segmentSequence, visiblyOpt = 0, prevSegmentVisibility = 0; var allSegment = { top: [['M', left, top], ['L', right, top]], right: [['M', right, top], ['L', right, bottom]], bottom: [['M', right, bottom], ['L', left, bottom]], left: [['M', left, bottom], ['L', left, top]] }; $.each(allSegment, function(seg, _) { var visibility = !!that.settings.segments[seg]; visiblyOpt = visiblyOpt * 2 + ~~visibility }); switch (visiblyOpt) { case(13): case(9): segmentSequence = ['left', 'top', 'right', 'bottom']; break; case(11): segmentSequence = ['bottom', 'left', 'top', 'right']; break; default: segmentSequence = ['top', 'right', 'bottom', 'left'] } $.each(segmentSequence, function(_, seg) { var segmentVisibility = !!that.settings.segments[seg]; if (segmentVisibility) $.each(allSegment[seg].slice(prevSegmentVisibility), function(_, segment) { segments.push(segment) }); prevSegmentVisibility = ~~segmentVisibility }); visiblyOpt == 15 && segments.push(['Z']); this.segments = segments.length ? segments : [['M', 0, 0], ['Z']]; this.combinePathParams(settings) }, adjustSettings: function() { this.callBase(); this.prepareSegments() }, applySettings: function(settings) { var segments = this.settings && this.settings.segments || this.defaultSettings().segments; settings.segments = $.extend(true, {}, segments || {}, settings.segments); return this.callBase(settings) } }); var baseAreaElement = { defaultSettings: function() { return {points: { x: 0, y: 0 }} }, ctor: function(renderer, params) { this.closePath = true; this.callBase(renderer, params) }, _tailIndex: 0, _makeEqualPath: function(short, long) { var i, tail, head, constsSeg1, constsSeg2, newTail = []; if ((short.length - 1) % 2 == 0 && (long.length - 1) % 2 == 0) { i = (short.length - 1) / 2 - 1; tail = short.slice(i + 1); head = short.slice(0, i + 1); constsSeg1 = head[head.length - 1]; constsSeg2 = tail[this._tailIndex]; this._prepareConstSegment(constsSeg1); for (var j = i; j < (long.length - 1) / 2 - 1; j++) { head.push(constsSeg1); newTail.push(constsSeg2) } head = this._concatAnimationSegment(head, newTail, tail); for (i = 0; i < head.length; i++) short[i] = head[i] } }, _concatAnimationSegment: function(head, newTail, tail) { return head.concat(newTail, tail) } }; var AreaSvgElement = PathSvgElement.inherit(baseAreaElement); var BezierSvgElement = PathSvgElement.inherit({ defaultSettings: function() { return {points: { x: 0, y: 0 }} }, _prepareConstSegment: function(seg) { var x = seg[seg.length - 2], y = seg[seg.length - 1]; seg[0] = "C"; seg[5] = seg[3] = seg[1] = x; seg[6] = seg[4] = seg[2] = y }, prepareSegments: function(params) { if (!('points' in params)) return; var points = params.points, firstElem = points[0], close = this.closePath || params.closePath, segments = [], seg = [], i, x, y; var cnt = 0; if (utils.isObject(firstElem)) { for (i = 0; i < points.length; i++) { x = points[i].x; y = points[i].y; if (!i) { segments = [['M', x, y]]; continue } if ((i - 1) % 3 == 0) { if (seg.length > 0) segments.push(seg); seg = ['C', x, y]; continue } seg.push(x); seg.push(y) } if (seg.length > 0) segments.push(seg) } else if (utils.isNumber(firstElem)) { for (i = 0; i < points.length; i += 2) { x = points[i]; y = points[i + 1]; if (!i) { segments = [['M', x, y || 0]]; continue } if ((i - 2) % 6 == 0) { if (seg.length > 0) segments.push(seg); seg = ['C', x, y || 0]; continue } seg.push(x); seg.push(y || 0) } if (seg.length > 0) segments.push(seg) } else segments = [['M', 0, 0]]; if (close) segments.push(['Z']); this.segments = segments; delete params.points; delete params.closePath; this.combinePathParams(params) } }); var BezierAreaSvgElement = BezierSvgElement.inherit(baseAreaElement).inherit({ _concatAnimationSegment: function(head, newTail, tail) { var point = tail.splice(0, 1); return head.concat(point.concat(newTail), tail) }, _tailIndex: 1 }); var ArcSvgElement = PathSvgElement.inherit({ defaultSettings: function() { return { x: 0, y: 0, linejoin: 'round' } }, createArcSegments: function(x, y, innerR, outerR, startAngle, endAngle, isCircle) { var longFlag = Math.floor(Math.abs(endAngle - startAngle) / Math.PI) % 2 ? '1' : '0', xOuterStart = x + outerR * Math.cos(startAngle), yOuterStart = y - outerR * Math.sin(startAngle), xOuterEnd = x + outerR * Math.cos(endAngle), yOuterEnd = y - outerR * Math.sin(endAngle), xInnerStart = x + innerR * Math.cos(endAngle), yInnerStart = y - innerR * Math.sin(endAngle), xInnerEnd = x + innerR * Math.cos(startAngle), yInnerEnd = y - innerR * Math.sin(startAngle); return [['M', xOuterStart, yOuterStart], ['A', outerR, outerR, 0, longFlag, 0, xOuterEnd, yOuterEnd], [isCircle ? 'M' : 'L', xInnerStart, yInnerStart], ['A', innerR, innerR, 0, longFlag, 1, xInnerEnd, yInnerEnd], ['Z']] }, prepareSegments: function(params) { if (!('x' in params) && !('y' in params) && !('outerRadius' in params) && !('innerRadius' in params) && !('startAngle' in params) && !('endAngle' in params)) return; var x = utils.isNumber(params.x) ? Number(params.x) : 0, y = utils.isNumber(params.y) ? Number(params.y) : 0, outerR = utils.isNumber(params.outerRadius) ? Number(params.outerRadius) : 0, innerR = utils.isNumber(params.innerRadius) ? Number(params.innerRadius) : 0, startAngle = utils.isNumber(params.startAngle) ? Number(params.startAngle) : 0, endAngle = utils.isNumber(params.endAngle) ? Number(params.endAngle) : 360, isCircle; this.segments = [['M', 0, 0], ['Z']]; if (outerR || innerR) { var tmp = Math.min(outerR, innerR); outerR = Math.max(outerR, innerR); innerR = tmp; if (Math.round(startAngle) != Math.round(endAngle)) { if (Math.abs(endAngle - startAngle) % 360 == 0) { startAngle = 0; endAngle = 360; isCircle = true; endAngle -= 0.0001 } if (startAngle > 360) startAngle = startAngle % 360; if (endAngle > 360) endAngle = endAngle % 360; if (startAngle > endAngle) startAngle -= 360; startAngle = startAngle * Math.PI / 180; endAngle = endAngle * Math.PI / 180; this.segments = this.createArcSegments(x, y, innerR, outerR, startAngle, endAngle, isCircle) } } this.x = params.x; this.y = params.y; this.outerRadius = params.outerRadius; this.innerRadius = params.innerRadius; this.startAngle = params.startAngle; this.endAngle = params.endAngle; delete params.x; delete params.y; delete params.outerRadius; delete params.innerRadius; delete params.startAngle; delete params.endAngle; this.combinePathParams(params) }, animate: function(params) { var _this = this; if ('x' in params && 'y' in params && 'outerRadius' in params && 'innerRadius' in params && 'startAngle' in params && 'endAngle' in params && this.renderer.animOptions.enabled) { var settings = this.settings; params.arc = { from: { x: this.x, y: this.y, outerRadius: this.outerRadius, innerRadius: this.innerRadius, startAngle: this.startAngle, endAngle: this.endAngle }, to: { x: params.x, y: params.y, outerRadius: params.outerRadius, innerRadius: params.innerRadius, startAngle: params.startAngle, endAngle: params.endAngle } }; delete params.d; delete params.x; delete params.y; delete params.outerRadius; delete params.innerRadius; delete params.startAngle; delete params.endAngle } this.callBase.apply(this, arguments) } }); var CircleSvgElement = BaseSvgElement.inherit({ defaultSettings: function() { return { cx: 0, cy: 0, r: 0 } }, ctor: function(renderer, params) { this.callBase(renderer, 'circle', params) } }); var TextSvgElement = BaseSvgElement.inherit({ defaultSettings: function() { return { x: 0, y: 0 } }, ctor: function(renderer, params) { this.tspans = []; this.callBase(renderer, 'text', params) }, dispose: function() { this.tspans = null; this.callBase() }, updateText: function(text) { if (!utils.isDefined(text)) text = ''; this.applySettings({text: text}) }, adjustSettings: function() { if (!('text' in this.settings)) { this.changeX(); return } this._createElementWithText(this.settings.text) }, changeX: function() { for (var i = 0; i < this.tspans.length; i++) if (this.tspans[i].settings.x != undefined) this.tspans[i].applySettings({x: this.settings.x}) }, _createElementWithText: function(text) { var div, i; this.clear(); text = text.toString().replace(/\r/g, ""); text = text.replace(/\n/g, "
"); div = doc.createElement("div"); div.innerHTML = text; div.params = {style: {}}; this._orderText(div) }, clear: function() { this.callBase(); this.tspans = [] }, _orderText: function(node) { var textArray = [], defaultFontSize = (this.settings.font ? this.settings.font.size : 12) || 12; var order = function(strCount, node, textArray) { var params = {style: {}}, textArray = textArray || []; node.params = node.params || {}; if (node.parentNode && node.nodeName != "#text") if (node.parentNode.params) for (var i in node.parentNode.params) node.params[i] = node.parentNode.params[i]; switch (node.tagName) { case"B" || "STRONG": node.params.fontWeight = "bold"; break; case"I" || "EM": node.params.fontStyle = "italic"; break; case"U": node.params.textDecoration = "underline"; break; case"BR": strCount++; break } if (node.style) { if (node.style.fontSize) node.params.fontSize = (parseInt(node.style.fontSize) || node.params.fontSize) + "px"; node.params.fill = node.style.color || node.params.fill; node.params.fontStyle = node.style.fontStyle || node.params.fontStyle; node.params.fontWeight = node.style.fontWeight || node.params.fontWeight; node.params.textDecoration = node.style.textDecoration || node.params.textDecoration } var childnum = node.childNodes.length; var count = 0; while (count != childnum) strCount = order(strCount, node.childNodes[count++], textArray); if (node.wholeText != undefined) { params.fill = node.parentNode.params.fill; params.text = node.wholeText; node.parentNode.params.fontSize && (params.style.fontSize = node.parentNode.params.fontSize); node.parentNode.params.fontStyle && (params.style.fontStyle = node.parentNode.params.fontStyle); node.parentNode.params.fontWeight && (params.style.fontWeight = node.parentNode.params.fontWeight); node.parentNode.params.textDecoration && (params.style.textDecoration = node.parentNode.params.textDecoration); textArray.push({ params: params, line: strCount }) } return strCount }; order(0, node, textArray); for (var txt = 0; txt < textArray.length; txt++) { if (txt != 0) if (textArray[txt].line != textArray[txt - 1].line) { textArray[txt].params.dy = textArray[txt].params.style.fontSize || defaultFontSize; textArray[txt].params.x = this.settings.x } else { textArray[txt].params.dy = 0; textArray[txt].params.dx = 0 } else { textArray[txt].params.x = this.settings.x; textArray[txt].params.dy = 0 } var tspan = new TspanSvgElement(this.renderer, textArray[txt].params); tspan.append(this); this.tspans.push(tspan) } } }); var TspanSvgElement = BaseSvgElement.inherit({ctor: function(renderer, params) { var text = params.text || ''; delete params.text; this.callBase(renderer, 'tspan', params); this.element.appendChild(doc.createTextNode(text)) }}); var GroupSvgElement = BaseSvgElement.inherit({ ctor: function(renderer, params) { this.callBase(renderer, 'g', params) }, update: $.noop }); var PatternSvgElement = BaseSvgElement.inherit({ ctor: function(renderer, params) { this.__patternParams = $.extend({}, params); var id = utils.getNextDefsSvgId(), color = params.color, hatching = params.hatching, opacity = hatching.opacity, width = hatching.width || 1, step = hatching.step || 6, direction = hatching.direction, options = { strokeWidth: width, stroke: color }; this.callBase(renderer, 'pattern', { id: id, width: step, height: step }); this.element.setAttribute('patternUnits', 'userSpaceOnUse'); this._rect = renderer.createRect(0, 0, step, step, 0, { fill: color, opacity: opacity }).append(this); this._path = renderer.createPath(0, options).append(this); if (direction === 'right') this._path.applySettings({d: "M " + step / 2 + " " + -step / 2 + " L " + -step / 2 + " " + step / 2 + "M 0 " + step + " L " + step + " 0 M " + step * 1.5 + " " + step / 2 + " L " + step / 2 + " " + step * 1.5}); else if (direction === 'left') this._path.applySettings({d: "M 0 0 L " + step + ' ' + step + " M " + -step / 2 + " " + step / 2 + " L " + step / 2 + " " + step * 1.5 + " M " + step / 2 + -step / 2 + " L " + step * 1.5 + " " + step / 2}); this.id = getPatternUrl(id, renderer.pathModified) }, append: function() { return this.callBase(this.renderer.getDefsSvg()) }, clear: function() { this.callBase(); this._path = null }, dispose: function() { this._path = null; this.callBase() } }); var ClipRectSvgElement = BaseSvgElement.inherit({ ctor: function(renderer, params) { this.__clipRectParams = $.extend({}, params); var x = params.x, y = params.y, w = params.w, h = params.h, id = utils.getNextDefsSvgId(); delete params.x; delete params.y; delete params.w; delete params.h; this.callBase(renderer, 'clipPath', {id: id}); this.id = id; this._rect = renderer.createRect(x, y, w, h, 0, params); this._rect.append(this) }, append: function() { return this.callBase(this.renderer.getDefsSvg()) }, updateRectangle: function(settings) { this._rect.applySettings(settings) }, dispose: function() { this._rect = null; this.callBase() } }); var BaseFilterSvgElement = BaseSvgElement.inherit({ ctor: function(renderer) { this.applySettings = $.noop; this.callBase(renderer, 'filter'); delete this.applySettings; this.ref = null; this._create() }, append: function() { return this.callBase(this.renderer.getDefsSvg()) }, dispose: function() { while (this.element.firstChild) this.element.removeChild(this.element.firstChild); this.callBase(); return this }, applySettings: function(settings) { settings = settings || {}; settings.id = utils.getNextDefsSvgId(); this.$element.attr({ id: settings.id, x: settings.x || null, y: settings.y || null, width: settings.width || null, height: settings.height || null }); this.ref = settings.id ? getPatternUrl(settings.id, this.renderer.pathModified) : null; this._update(settings); return this } }); function setAttributes(element, attr) { $.each(attr, function(name, value) { element.setAttribute(name, value) }) } var ShadowFilterSvgElement = BaseFilterSvgElement.inherit({ _create: function() { var that = this, gaussianBlur = that._gaussianBlur = createElement('feGaussianBlur'), offset = that._offset = createElement('feOffset'), flood = that._flood = createElement('feFlood'), composite = that._composite = createElement('feComposite'), finalComposite = createElement('feComposite'); setAttributes(gaussianBlur, { 'in': 'SourceGraphic', result: 'gaussianBlurResult' }); setAttributes(offset, { 'in': 'gaussianBlurResult', result: 'offsetResult' }); setAttributes(flood, {result: 'floodResult'}); setAttributes(composite, { 'in': 'floodResult', in2: 'offsetResult', operator: 'in', result: 'compositeResult' }); setAttributes(finalComposite, { 'in': 'SourceGraphic', in2: 'compositeResult', operator: 'over' }); that.element.appendChild(gaussianBlur); that.element.appendChild(offset); that.element.appendChild(flood); that.element.appendChild(composite); that.element.appendChild(finalComposite) }, _update: function(settings) { setAttributes(this._gaussianBlur, {stdDeviation: settings.blur || 0}); setAttributes(this._offset, { dx: settings.dx || 0, dy: settings.dy || 0 }); setAttributes(this._flood, { 'flood-color': settings.color, 'flood-opacity': settings.opacity }) } }); renderers.SvgRenderer = Class.inherit({ ctor: function(options) { var that = this; options = options || {}; that._setAnimationOptions(options.animation || {}); that.animationController = new renderers.AnimationController; that.pathModified = options.pathModified; that.rtl = !!options.rtl; that.cssClass = options.cssClass || ''; that.recreateCanvas(options.width, options.height) }, dispose: function() { var that = this; that.detachContainer(); that.svgRoot && (that.svgRoot.remove(), that.svgRoot = null); that.animationController.dispose(); that.animOptions = null; that.animationController = null }, _setAnimationOptions: function(options) { this.animOptions = { enabled: true, duration: 1000, easing: 'easeOutCubic' }; if ('enabled' in options) this.animOptions.enabled = options.enabled; if ('duration' in options) this.animOptions.duration = options.duration; if ('easing' in options) this.animOptions.easing = options.easing }, animationEnabled: function() { return !!this.animOptions.enabled }, updateAnimationOptions: function(newOptions) { this._setAnimationOptions($.extend(this.animOptions || {}, newOptions)) }, stopAllAnimations: function(lock) { lock ? this.animationController.lock() : this.animationController.stop() }, detachContainer: function() { var that = this; that.svgRoot && that.svgRoot.detach(); that.defsSvg && (that.defsSvg.remove(), that.defsSvg = null); that.drawn = null }, recreateCanvas: function(width, height, cssClass) { if (width >= 0 && height >= 0) { if (!this.svgRoot) { this.cssClass = cssClass || this.cssClass; this.svgRoot = new RootSvgElement(this, { width: width, height: height, 'class': this.cssClass, direction: this.rtl ? 'rtl' : 'ltr' }); this.animationController.element = this.svgRoot.element } else this.svgRoot.applySettings({ width: width, height: height }); this.defsSvg && this.defsSvg.clear("pattern") } }, resize: function(width, height) { var root = this.getRoot(); root && width > 0 && height > 0 && root.applySettings({ width: width, height: height }) }, getRoot: function() { return this.svgRoot }, isInitialized: function() { return !!this.svgRoot }, draw: function(container) { if (!container || this.drawn) return; container.appendChild(this.getRoot().element); this.drawn = true }, updateParams: function(params, options) { if (options && options.strokeWidth) params.strokeWidth = options.strokeWidth }, animateElement: function(element, params, options) { this.animationController.animateElement(element, params, options) }, createRect: function(x, y, w, h, r, options) { var params = { x: x, y: y, width: w, height: h, rx: r, ry: r }; if (options && !options.inh) $.extend(params, options); this.updateParams(params, options); return new RectSvgElement(this, params) }, createSegmentRect: function(x, y, w, h, r, segments, options) { var params = $.extend({}, options || {}, { x: x, y: y, width: w, height: h, rx: r, ry: r, segments: segments }); return new SegmentRectSvgElement(this, params) }, createClipRect: function(x, y, w, h) { var attr = { x: x, y: y, w: w, h: h, fill: 'none', stroke: 'none', strokeWidth: 0 }; return new ClipRectSvgElement(this, attr) }, createPattern: function(color, hatching) { hatching = hatching || {}; hatching.direction = (hatching.direction || '').toLowerCase(); if (hatching.direction !== 'right' && hatching.direction !== 'left') return { id: color, append: function() { return this }, clear: function(){}, dispose: function(){} }; return new PatternSvgElement(this, { hatching: hatching, color: color }) }, createImage: function(x, y, w, h, href, options) { var params = $.extend({}, options || {}, { x: x, y: y, width: w, height: h }); return new ImageSvgElement(this, params, href, params.location) }, createLine: function(x1, y1, x2, y2, options) { var params = {points: [x1, y1, x2, y2]}; if (options && !options.inh) $.extend(params, options); this.updateParams(params, options); return new PathSvgElement(this, params) }, createPath: function(points, options) { var params = {points: points}; if (options && !options.inh) $.extend(params, options); this.updateParams(params, options); return new PathSvgElement(this, params) }, createSimplePath: function(options) { return new BaseSvgElement(this, 'path', options) }, createBezierPath: function(points, options) { var params = {points: points}; if (options && !options.inh) $.extend(params, options); this.updateParams(params, options); return new BezierSvgElement(this, params) }, createArea: function(points, options) { var params = {points: points}; if (options && !options.inh) $.extend(params, options); this.updateParams(params, options); return new AreaSvgElement(this, params) }, createBezierArea: function(points, options) { var params = {points: points}; if (options && !options.inh) $.extend(params, options); this.updateParams(params, options); return new BezierAreaSvgElement(this, params) }, createCircle: function(x, y, r, options) { var params = { cx: x, cy: y, r: r }; if (options && !options.inh) $.extend(params, options); return new CircleSvgElement(this, params) }, createArc: function(x, y, outerRadius, innerRadius, startAngle, endAngle, options) { var params = { x: x, y: y, outerRadius: outerRadius, innerRadius: innerRadius, startAngle: startAngle, endAngle: endAngle }; if (options && !options.inh) $.extend(params, options); this.updateParams(params, options); return new ArcSvgElement(this, params) }, createText: function(text, x, y, options) { var params = { x: x, y: y, text: text }; if (options && !options.inh) $.extend(params, options); return new TextSvgElement(this, params) }, createGroup: function(options) { return new GroupSvgElement(this, options) }, createFilter: function(type) { var filterType = type === 'shadow' ? ShadowFilterSvgElement : null; if (filterType) return new filterType(this); return null }, getDefsSvg: function() { this.defsSvg = this.defsSvg || new BaseSvgElement(this, 'defs').append(); return this.defsSvg }, svg: function() { return this.svgRoot.$element.parent().html() } }); function buildPath(points) { var i = 0, ii = points.length, list = []; for (; i < ii; ) list.push('L', points[i++].toFixed(2), points[i++].toFixed(2)); if (ii) { list[0] = 'M'; list.push('Z'); list = list.join(' ') } else list = ''; return list } function processCircleSettings(x, y, size, borderWidth) { var correct = size + ~~borderWidth & 1; return { cx: correct ? x + 0.5 : x, cy: correct ? y + 0.5 : y, r: size / 2 } } renderers._svgBuildPath = buildPath; renderers._svgProcessCircleSettings = processCircleSettings; renderers._svgRendererInternals = { BaseSvgElement: BaseSvgElement, RootSvgElement: RootSvgElement, RectSvgElement: RectSvgElement, ImageSvgElement: ImageSvgElement, PathSvgElement: PathSvgElement, AreaSvgElement: AreaSvgElement, BezierSvgElement: BezierSvgElement, BezierAreaSvgElement: BezierAreaSvgElement, CircleSvgElement: CircleSvgElement, TextSvgElement: TextSvgElement, TspanSvgElement: TspanSvgElement, GroupSvgElement: GroupSvgElement, ArcSvgElement: ArcSvgElement, RectSvgBaseElement: RectSvgBaseElement, SegmentRectSvgElement: SegmentRectSvgElement, ClipRectSvgElement: ClipRectSvgElement, PatternSvgElement: PatternSvgElement, ShadowFilterSvgElement: ShadowFilterSvgElement } })(jQuery, DevExpress); /*! Module viz-core, file vmlRenderer.js */ (function($, DX) { var renderers = DX.viz.renderers, utils = DX.utils, doc = document, svgRendererInternals = renderers._svgRendererInternals, documentFragment = doc.createDocumentFragment(); function createVmlElement(nodeName) { var element = doc.createElement(nodeName); return documentFragment.appendChild(element) } var appendTimerID; var vmlElementsToAppend = []; var CSS_PROPERTIES = ['position', 'display', 'visibility', 'filter', 'margin', 'marginTop', 'marginLeft', 'marginRight', 'marginBottom', 'whiteSpace', 'clip', 'overflow']; var INHERITABLE_PROPERTIES = ['stroke', 'fill', 'opacity', 'strokeWidth', 'align', 'dashStyle']; var defaultVmlSettings = { x: 0, y: 0, width: 1, height: 1, position: 'absolute', behavior: 'url(#default#VML)', display: 'inline-block', xmlns: "urn:schemas-microsoft-com:vml" }; var CLIP_RECT_CLASS = "dx-vml-clip-rect"; var extendDefaultVmlOptions = function(customOptions, baseOptions) { return $.extend(true, baseOptions || {}, defaultVmlSettings, customOptions) }; var parseRotateParameter = function(rotate, defaultX, defaultY) { var rotateObject; if (utils.isDefined(rotate)) if (utils.isNumber(rotate)) rotateObject = { angle: rotate, x: defaultX || 0, y: defaultY || 0 }; else if ($.isArray(rotate)) rotateObject = { angle: rotate[0] || 0, x: rotate[1] || 0, y: rotate[2] || 0 }; else if (utils.isObject(rotate)) rotateObject = { angle: rotate.angle || 0, x: rotate.x || 0, y: rotate.y || 0 }; return rotateObject }; function adjustOpacity(value) { return value >= 0.002 ? value : value === null ? 1 : 0.002 } var applySubElementAttribute = function(vmlElement, params, name) { var element = vmlElement.element, subElement, value = params[name]; if (name === 'opacity' || name === 'fillOpacity') if (element.fill) element.fill.opacity = adjustOpacity(value); if (name === 'joinStyle') if (element.stroke) element.stroke.joinStyle = value; if (name === 'opacity' || name === 'strokeOpacity') if (element.stroke) element.stroke.opacity = value >= 0.002 ? value : value === null ? 1 : 0.002; if (name === 'dashstyle') if (element.stroke) element.stroke.dashstyle = value }; var getBoundingClientRect = function(element) { var i, resultRect, rect, tagName = element.tagName.toLowerCase(), points, value, halfStrokeWidth; if (element.className && element.className.indexOf(CLIP_RECT_CLASS) !== -1) return; if (tagName === 'div') { if (element.childNodes.length > 0) { resultRect = {}; for (i = 0; i < element.childNodes.length; i++) { rect = getBoundingClientRect(element.childNodes[i]); if (!rect) continue; resultRect.left = resultRect.left === undefined || rect.left < resultRect.left ? rect.left : resultRect.left; resultRect.top = resultRect.top === undefined || rect.top < resultRect.top ? rect.top : resultRect.top; resultRect.right = resultRect.right === undefined || rect.right > resultRect.right ? rect.right : resultRect.right; resultRect.bottom = resultRect.bottom === undefined || rect.bottom > resultRect.bottom ? rect.bottom : resultRect.bottom } } } else if (tagName === 'shape' || tagName === 'vml:shape') { points = (element.path.value || element.path).match(/[-0-9]+/g); resultRect = {}; rect = element.getBoundingClientRect(); for (i = 0; i < points.length; i++) { value = parseInt(points[i]); if (i % 2) { resultRect.top = resultRect.top === undefined || value < resultRect.top ? value : resultRect.top; resultRect.bottom = resultRect.bottom === undefined || value > resultRect.bottom ? value : resultRect.bottom } else { resultRect.left = resultRect.left === undefined || value < resultRect.left ? value : resultRect.left; resultRect.right = resultRect.right === undefined || value > resultRect.right ? value : resultRect.right } } resultRect.left = resultRect.left || 0; resultRect.top = resultRect.top || 0; resultRect.right = resultRect.right || 0; resultRect.bottom = resultRect.bottom || 0; if (rect.right - rect.left <= 1 && rect.top - rect.bottom <= 1) { resultRect.right = resultRect.right + rect.left; resultRect.bottom = resultRect.bottom + rect.top; resultRect.left = resultRect.left + rect.left; resultRect.top = resultRect.top + rect.top } else { resultRect.right = resultRect.right - resultRect.left + rect.left; resultRect.bottom = resultRect.bottom - resultRect.top + rect.top; resultRect.left = rect.left; resultRect.top = rect.top } halfStrokeWidth = Math.ceil(parseFloat(element.strokeweight) / 2); if (halfStrokeWidth && halfStrokeWidth > 1) { resultRect.left -= halfStrokeWidth; resultRect.top -= halfStrokeWidth; resultRect.right += halfStrokeWidth; resultRect.bottom += halfStrokeWidth } } else resultRect = element.getBoundingClientRect(); return resultRect }; var BaseVmlElement = { isVml: function() { return true }, dispose: function() { this.childElements = null; this._style = null; this._fullSettings = null; this.callBase() }, defaultSettings: function(customOptions) { return extendDefaultVmlOptions(customOptions, this.callBase ? this.callBase() : {}) }, createElement: function(nodeName) { this._nodeName = nodeName; this.childElements = []; this._fullSettings = {}; if (this.isVml()) { var result = createVmlElement('vml:' + nodeName); return result } else return doc.createElement(nodeName) }, append: function(element) { var toElement = element || this.renderer.getRoot(); if (toElement) { toElement.element.appendChild(this.element); toElement.childElements.push(this); if (this.parentElement) this.parentElement.childElements.splice($.inArray(this, this.parentElement.childElements), 1); this.parentElement = toElement } if (toElement === this.renderer.getRoot() || toElement._isAppended) this.appendComplete(); return this }, insertBefore: function(target) { var parent = target.parentElement; parent.element.insertBefore(this.element, target.element); this.parentElement = parent; parent.childElements.splice($.inArray(target, parent.childElements), 0, this); parent._isAppended && this.appendComplete(); return this }, remove: function() { this.callBase.apply(this, arguments); if (this.parentElement) { this.parentElement.childElements.splice($.inArray(this, this.parentElement.childElements), 1); this.parentElement = null } return this }, detach: function() { this.callBase.apply(this, arguments); this._delayAttributes(['opacity']); this._onDetach(); if (this.parentElement) { this.parentElement.childElements.splice($.inArray(this, this.parentElement.childElements), 1); this.parentElement = null } return this }, clear: function() { this.callBase.apply(this, arguments); $.each(this.childElements, function(_, element) { element._delayAttributes(['opacity']); element._onDetach(); element.parentElement = null }); this.childElements = []; return this }, applyStyle: function(style) { this.callBase(style); if (style.opacity) this.element.style.opacity = style.opacity; if (style.clip) try { this.element.style.clip = style.clip } catch(e) {} }, _fillAttributesFromParentAndCurrentStyle: function(attributes) { var element = this.element, parent = this.parentElement, i, settingToStyleMap = {strokeWidth: 'stroke-width'}, propertyName, styleName, settingsToApply = {}; if (parent) for (i = 0; i < INHERITABLE_PROPERTIES.length; i++) { propertyName = INHERITABLE_PROPERTIES[i]; if (!this.settings[propertyName] && parent._fullSettings[propertyName]) settingsToApply[propertyName] = parent._fullSettings[propertyName] } if (element.style && element.currentStyle) for (i = 0; i < INHERITABLE_PROPERTIES.length; i++) { propertyName = INHERITABLE_PROPERTIES[i]; styleName = settingToStyleMap[propertyName] || propertyName; if (element.currentStyle[styleName]) settingsToApply[propertyName] = element.currentStyle[styleName] } $.extend(this._fullSettings, this.settings, settingsToApply); if (this.isVml()) $.extend(attributes, this._normalizeSettings(settingsToApply)) }, _applyAttributes: function(params) { var name, value; if (params && params.arcsize !== undefined) { try { this.element.setAttribute('arcsize', params.arcsize) } catch(e) {} this.__appliedSettings = {arcsize: params.arcsize}; delete params.arcsize } if (params && params['class']) { this.element.className = params['class']; delete params['class'] } if (!this._isAppended) this._delayedAttributes = params; else { params = params || this._delayedAttributes; if (params) { this._fillAttributesFromParentAndCurrentStyle(params); if (this.isVml()) { for (name in params) { value = params[name]; if (name === 'opacity' || name === 'fillOpacity' || name === 'strokeOpacity' || name === 'dashstyle' || name === 'joinStyle') applySubElementAttribute(this, params, name); else this.element[name] = value } $.each(this.element.children, function(_, e) { e.style.behavior = 'url(#default#VML)'; e.style.display = 'inline-block'; e.xmlns = "urn:schemas-microsoft-com:vml" }) } this.__appliedSettings = this.isVml() ? params : {}; delete this._delayedAttributes } } }, _onDetach: function() { this._isAppended = false; $.each(this.childElements, function(_, child) { child._onDetach() }) }, appendComplete: function() { if (this.renderer.isElementAppendedToPage(this)) { this._isAppended = true; this._applyAttributes(); $.each(this.childElements, function(_, child) { child.appendComplete() }); if (this.parentElement instanceof GroupVmlElement && this.parentElement._clipRect && this.parentElement._clipRect !== this) if (this.parentElement._clipRect._isAppended) this.parentElement._clipRect.toForeground(); else this.parentElement._clipRect.append(this.parentElement) } else { vmlElementsToAppend.push(this); $(this.element).data('vmlNeedAppendComplete', true); if (appendTimerID === undefined) appendTimerID = setTimeout(function() { appendTimerID = undefined; var vmlElements = vmlElementsToAppend; vmlElementsToAppend = []; $.each(vmlElements, function() { if ($(this.element).data('vmlNeedAppendComplete') && !this._isAppended) this.appendComplete() }) }, 200) } }, _delayAttributes: function(attributes) { var attr, val, i, settings = this.settings || {}; attributes = attributes || []; this._delayedAttributes = this._delayedAttributes || {}; for (i = 0; i < attributes.length; i++) { attr = attributes[i]; val = settings[attr]; if (val) this._delayedAttributes[attr] = val } $.each(this.childElements || [], function(_, child) { child._delayAttributes(attributes) }) }, _normalizeSettings: function(settings) { var key, style = {}, normalized = {}, clipRect, pos, prop, value; for (key in settings) { prop = key; value = settings[prop]; if (prop === 'x' || prop === 'translateX') { pos = settings.x || 0; if (settings.translateX) pos += settings.translateX; style.left = pos + 'px' } else if (prop === 'y' || prop === 'translateY') { pos = settings.y || 0; if (settings.translateY) pos += settings.translateY; style.top = pos + 'px' } else if (prop === 'width') style.width = value + 'px'; else if (prop === "behavior") style[prop] = value; else if (prop === 'height') style.height = value + 'px'; else if (prop === 'align') continue; else if (prop === 'scale') continue; else if ($.inArray(prop, CSS_PROPERTIES) != -1) style[prop] = value !== null ? value : ''; else if (prop === 'font') { if (!$.isPlainObject(value)) continue; $.each(value, function(fontSetting) { var styleName, firstChar; switch (fontSetting) { case'color': styleName = "fill"; break; case'opacity': styleName = "opacity"; break; case'cursor': styleName = fontSetting; break; default: firstChar = fontSetting.charAt(0); styleName = 'font' + fontSetting.replace(firstChar, firstChar.toUpperCase()) } if (styleName) style[styleName] = value[fontSetting] }) } else if (prop === 'style') $.extend(true, style, value); else if (prop === 'rotate') this['_rotate'] = value; else if (prop === 'clipId') { clipRect = this.renderer.getClipRect(value, this); if (clipRect) { var width = clipRect.width, height = clipRect.height, x = clipRect.x, y = clipRect.y, clipWidth = width + x, clipHeight = height + y, canvasSize = this.renderer._getSize(); style.width = canvasSize.width; style.height = canvasSize.height; style.clip = "rect(" + y + "px, " + clipWidth + "px, " + clipHeight + "px, " + x + "px)" } } else if (prop === 'segments') continue; else if (prop === 'fill') { normalized.filled = value === 'none' ? 'f' : 't'; normalized.fillcolor = value === 'grey' ? '#808080' : value } else if (prop === 'opacity') normalized.opacity = value < 0.002 ? value : value; else if (prop === 'stroke') { normalized.stroked = value === 'none' ? 'f' : 't'; normalized.strokecolor = value } else if (prop === 'strokeWidth') normalized.strokeweight = value + 'px'; else if (prop === 'lineJoin') normalized.joinStyle = value; else if (prop === 'dashStyle') { value = (value || "").toLowerCase(); normalized.dashstyle = value } else normalized[prop] = value } this['_style'] = style; return normalized }, _getBBox: function() { var width, height, rect, parentRect, x = 0, y = 0, element = this.element, parent; try { rect = getBoundingClientRect(element); width = rect.right - rect.left; height = rect.bottom - rect.top; parent = this.element.parentNode || this.renderer.getRoot().element; parentRect = parent.getBoundingClientRect(); x = rect.left - parentRect.left; y = rect.top - parentRect.top; if (element.tagName.toLowerCase() === 'div') { x = x - (parseInt(element.style.left, 10) || 0); y = y - (parseInt(element.style.top, 10) || 0) } } catch(e) { width = element.offsetWidth || 0; height = element.offsetHeight || 0 } return { x: x, y: y, width: width, height: height, isEmpty: !x && !y && !width && !height } }, getBBox: function() { return this._getBBox() }, sharpEdges: function(){} }; var convertSvgPathCommandToVml = function(command) { switch (command) { case'M': return 'm'; case'L': return 'l'; case'Z': return 'x e' } return command }; var BasePathVmlElement = { defaultSettings: function() { return $.extend(this.callBase(), {coordsize: '1,1'}) }, getNodeName: function() { return 'shape' }, getPathAttributeName: function() { return 'path' }, customizeSegments: function(segments) { var result = segments; if (segments) result = $.map(segments, function(s, i) { var pos, segmentArray = [], command = convertSvgPathCommandToVml(s[0]); segmentArray.push(command); for (pos = 1; pos < s.length; pos++) segmentArray.push(Math.floor(s[pos])); return [segmentArray] }); return result } }; var RootVmlElement = svgRendererInternals.BaseSvgElement.inherit(BaseVmlElement).inherit({ isVml: function() { return false }, defaultSettings: function() { return { width: 0, height: 0, position: 'relative', display: 'inline-block', overflow: 'hidden', stroke: 'none', strokeWidth: 0, fill: 'none' } }, ctor: function(renderer, params) { this.callBase(renderer, 'div', params) } }); var ImageVmlElement = svgRendererInternals.BaseSvgElement.inherit(svgRendererInternals.RectSvgBaseElement).inherit(BaseVmlElement).inherit({ ctor: function(renderer, params) { this.callBase(renderer, 'image', params) }, defaultSettings: function() { return $.extend(this.callBase(), { strokeWidth: 0, fill: 'none', stroke: 'none' }) }, adjustSettings: function() { var defaultSettings = this.defaultSettings(); this.callBase(); if (this.settings.href) { this.settings.src = this.settings.href; delete this.settings.href } this.settings.fill = defaultSettings.fill; this.settings.stroke = defaultSettings.stroke; this.settings.strokeWidth = defaultSettings.strokeWidth } }); var RectVmlElement = svgRendererInternals.BaseSvgElement.inherit(svgRendererInternals.RectSvgBaseElement).inherit(BaseVmlElement).inherit({ defaultSettings: function() { return extendDefaultVmlOptions({ stroked: 'f', strokeWidth: 0, rx: 0, ry: 0 }) }, recreateElement: function(name) { this._nodeName = name; var parent = this.$element.parent()[0]; if (parent) { var $oldElement = this.$element; this.element = this.createElement(name); this.$element = $(this.element); this.$element.insertBefore($oldElement); $oldElement.remove() } else { this.element = this.createElement(name); this.$element = $(this.element) } this.applySettings() }, _adjustArcSize: function() { var settings = this.settings; var rx = settings.rx || 0, ry = settings.ry || 0, width = settings.width, height = settings.height, r, halfsize, arcsize; if (settings.rx !== undefined || settings.ry !== undefined) { r = Math.max(rx, ry); halfsize = Math.max(width, height) / 2; arcsize = r / halfsize; settings.arcsize = arcsize; if ($.isNumeric(arcsize) && arcsize != 0) this._nodeName !== 'roundrect' && this.recreateElement('roundrect'); else this._nodeName === 'roundrect' && this.recreateElement('rect'); delete settings.rx; delete settings.ry } }, _adjustRotation: function() { var settings = this.settings; var rotate = this.settings.rotate, rotateAngle, radianAngle, cos, sin, rotateX, rotateY, marginTop, marginLeft, cx, cy, rotateObject; rotateObject = parseRotateParameter(rotate, settings.x, settings.y); if (rotateObject) { rotateAngle = rotateObject.angle; rotateX = rotateObject.x; rotateY = rotateObject.y; radianAngle = rotateAngle * Math.PI / 180.0; cos = Math.cos(radianAngle); sin = Math.sin(radianAngle); cx = settings.x + (settings.translateX || 0) + settings.width / 2; cy = settings.y + (settings.translateY || 0) + settings.height / 2; marginLeft = (cx - rotateX) * cos - (cy - rotateY) * sin + rotateX - cx; marginTop = (cx - rotateX) * sin + (cy - rotateY) * cos + rotateY - cy; this.settings.marginLeft = Math.round(marginLeft) + 'px'; this.settings.marginTop = Math.round(marginTop) + 'px'; this.settings.rotation = rotateAngle } }, adjustSettings: function() { this.callBase(); this._adjustArcSize(); this._adjustRotation() }, ctor: function(renderer, params) { this.callBase(renderer, 'rect', params) } }); var PathVmlElement = svgRendererInternals.PathSvgElement.inherit(BaseVmlElement).inherit(BasePathVmlElement).inherit({prepareSegments: function(settings) { var that = this, rotate = settings.rotate, rotateAngle, rotateX, rotateY, oldSegments, radianAngle, cos, sin, x, y, rotatedX, rotatedY, rotateObject; this.callBase(settings); oldSegments = that.segments; rotateObject = parseRotateParameter(rotate, settings.x, settings.y); if (rotateObject) { rotateAngle = rotateObject.angle; rotateX = rotateObject.x; rotateY = rotateObject.y; if (that.segments) { radianAngle = rotateAngle * Math.PI / 180.0; cos = Math.cos(radianAngle); sin = Math.sin(radianAngle); that.segments = $.map(that.segments, function(s, i) { if (s.length === 3) { x = s[1], y = s[2]; rotatedX = (x - rotateX) * cos - (y - rotateY) * sin + rotateX; rotatedY = (x - rotateX) * sin + (y - rotateY) * cos + rotateY; return [[s[0], Math.floor(rotatedX), Math.floor(rotatedY)]] } else return [s] }); that.combinePathParams(settings); that.segments = oldSegments } } }}); var SimplePathVmlElement = svgRendererInternals.BaseSvgElement.inherit(BaseVmlElement).inherit({ ctor: function(renderer, options) { this.callBase(renderer, 'shape', options) }, defaultSettings: function() { return extendDefaultVmlOptions({coordsize: '1,1'}) }, adjustSettings: function() { var settings = this.settings; if (settings.d !== undefined) { settings.path = settings.d; delete settings.d } } }); var AreaVmlElement = PathVmlElement.inherit({ defaultSettings: function() { var baseOptions = this.callBase(); return extendDefaultVmlOptions({points: { x: 0, y: 0 }}, baseOptions) }, ctor: function(renderer, params) { this.closePath = true; this.callBase(renderer, params) } }); var SegmentRectVmlElement = svgRendererInternals.SegmentRectSvgElement.inherit(BaseVmlElement).inherit(BasePathVmlElement).inherit({ defaultSettings: function() { var settings = this.callBase(); settings.lineJoin = 'miter'; delete settings.fill; delete settings.stroke; delete settings.strokecolor; delete settings.stroked; return settings }, prepareSegments: function() { this.callBase(); this.segments = this.customizeSegments(this.segments); this.settings.x = 0; this.settings.y = 0; this.settings.width = 1; this.settings.height = 1 }, applySettings: function(settings) { var x = settings.x, y = settings.y, w = settings.width, h = settings.height; this.callBase(settings); this.settings.x = x; this.settings.y = y; this.settings.width = w; this.settings.height = h; return this } }); var BezierVmlElement = svgRendererInternals.BezierSvgElement.inherit(BaseVmlElement).inherit(BasePathVmlElement); var BezierAreaVmlElement = BezierVmlElement.inherit({ defaultSettings: function() { var baseOptions = this.callBase(); return extendDefaultVmlOptions({points: { x: 0, y: 0 }}, baseOptions) }, ctor: function(renderer, params) { this.closePath = true; this.callBase(renderer, params) } }); var ArcVmlElement = svgRendererInternals.ArcSvgElement.inherit(BaseVmlElement).inherit(BasePathVmlElement).inherit({createArcSegments: function(x, y, innerR, outerR, startAngle, endAngle, isCircle) { var xOuterStart = x + outerR * Math.cos(startAngle), yOuterStart = y - outerR * Math.sin(startAngle), xOuterEnd = x + outerR * Math.cos(endAngle), yOuterEnd = y - outerR * Math.sin(endAngle), xInnerStart = x + innerR * Math.cos(endAngle), yInnerStart = y - innerR * Math.sin(endAngle), xInnerEnd = x + innerR * Math.cos(startAngle), yInnerEnd = y - innerR * Math.sin(startAngle); return [['wr', x - innerR, y - innerR, x + innerR, y + innerR, xInnerStart, yInnerStart, xInnerEnd, yInnerEnd], [isCircle ? 'wr' : 'at', x - outerR, y - outerR, x + outerR, y + outerR, xOuterStart, yOuterStart, xOuterEnd, yOuterEnd], ['x e']] }}); var CircleVmlElement = svgRendererInternals.BaseSvgElement.inherit(BaseVmlElement).inherit({ defaultSettings: function() { return extendDefaultVmlOptions({ cx: 0, cy: 0, r: 0 }) }, applySettings: function(settings) { settings.cx = settings.cx || settings.x; settings.cy = settings.cy || settings.y; return this.callBase(settings) }, adjustSettings: function() { var r, cx, cy; if (this.settings.cx !== undefined || this.settings.cy !== undefined || this.settings.r !== undefined) { r = 'r' in this.settings ? this.settings.r : this.settings.width / 2; cx = 'cx' in this.settings ? this.settings.cx : this.settings.x + this.settings.width / 2; cy = 'cy' in this.settings ? this.settings.cy : this.settings.y + this.settings.width / 2; this.settings.x = cx - r; this.settings.y = cy - r; this.settings.width = this.settings.height = r * 2; delete this.settings.cx; delete this.settings.cy; delete this.settings.r } }, ctor: function(renderer, params) { this.callBase(renderer, 'oval', params) } }); var TextVmlElement = svgRendererInternals.BaseSvgElement.inherit(BaseVmlElement).inherit({ isVml: function() { return false }, defaultSettings: function() { return { x: 0, y: 0, position: 'absolute', whiteSpace: 'nowrap' } }, ctor: function(renderer, params) { this.callBase(renderer, 'span', params) }, adjustSettings: function() { var text, settings = this.settings; if (settings.font) { settings.fill = settings.fill || settings.font.color; settings.opacity = settings.opacity || settings.font.opacity } if ('text' in settings) { text = utils.isDefined(settings.text) ? settings.text : ''; text = text.toString().replace(/\r/g, ""); text = text.replace(/\n/g, "
"); $(this.element).html(text); delete settings.text } if (this.renderer.rtl) $(this.element).css('direction', 'rtl') }, updateText: function(text) { this.applySettings({text: utils.isDefined(text) ? text : ''}) }, _applyAttributes: function(settings) { this.callBase(settings); settings = this._fullSettings; var rotate = settings.rotate, rotateAngle = 0, rotateX, rotateY, cos = 1, sin = 0, osin = 0, ocos = 1, angle, otg, rad, y = settings.y + (settings.translateY || 0), x = settings.x + (settings.translateX || 0), align = settings.align, bBox = this.getBBox(), style = this._style || {}, marginLeft = 0, marginTop = 0, fontHeightOffset, alignMultiplier, rotateObject, textWidth, textHeight; if (this._oldRotate && !bBox.isEmpty) { rad = this._oldRotate.angle * Math.PI / 180.0; osin = Math.sin(rad); ocos = Math.cos(rad); if ((this._oldRotate.angle | 0) % 90 !== 0) if ((this._oldRotate.angle | 0) % 45 === 0) textWidth = bBox.width, textHeight = bBox.height; else { otg = Math.abs(Math.tan(rad)); var b = (bBox.width - bBox.height * otg) / (1 - otg * otg); var a = bBox.width - b; textHeight = Math.abs(a / osin); textWidth = Math.abs(b / ocos) } else { textHeight = Math.abs(bBox.height * ocos - bBox.width * osin); textWidth = Math.abs(bBox.width * ocos - bBox.height * osin) } } else textWidth = bBox.width, textHeight = bBox.height; this.__textWidth = textWidth; this.__textHeight = textHeight; if (textHeight || textWidth) { rotateObject = parseRotateParameter(rotate, x, y); this._oldRotate = rotateObject; if (rotateObject) { rotateAngle = rotateObject.angle; rotateX = rotateObject.x; rotateY = rotateObject.y; if (Math.abs(rotateAngle) > 360) rotateAngle = rotateAngle % 360; if (rotateAngle < 0) rotateAngle = rotateAngle + 360; if (rotateAngle) { rad = rotateAngle * Math.PI / 180.0; cos = Math.cos(rad); sin = Math.sin(rad); style.filter = 'progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand", M11 = ' + cos.toFixed(5) + ', M12 = ' + (-sin).toFixed(5) + ', M21 = ' + sin.toFixed(5) + ', M22 = ' + cos.toFixed(5) + ')' } else { style.filter = ''; this._oldRotate = null } marginLeft = (x - rotateX) * (cos - 1) - (y - rotateY) * sin; marginTop = (x - rotateX) * sin + (y - rotateY) * (cos - 1) } fontHeightOffset = textHeight * (0.55 + 0.45 / 2); if (rotateAngle < 90) { marginTop -= fontHeightOffset * cos; marginLeft -= (textHeight - fontHeightOffset) * sin } else if (rotateAngle < 180) { marginTop += (textHeight - fontHeightOffset) * cos; marginLeft += textWidth * cos - (textHeight - fontHeightOffset) * sin } else if (rotateAngle < 270) { marginTop += (textHeight - fontHeightOffset) * cos + textWidth * sin; marginLeft += textWidth * cos + fontHeightOffset * sin } else { marginTop += textWidth * sin - fontHeightOffset * cos; marginLeft += fontHeightOffset * sin } if (rotateAngle && this.renderer.rtl) marginLeft -= textWidth - (textHeight * Math.abs(sin) + textWidth * Math.abs(cos)); alignMultiplier = { center: 0.5, right: 1 }[align]; if (alignMultiplier) { marginLeft -= textWidth * alignMultiplier * cos; marginTop -= textWidth * alignMultiplier * sin } style.marginLeft = Math.round(marginLeft) + 'px'; style.marginTop = Math.round(marginTop) + 'px' } if (settings.fill && settings.fill !== 'none') style.color = settings.fill; if (settings.opacity) this.element.style.filter = 'alpha(opacity=' + settings.opacity * 100 + ')'; this.applyStyle(style) } }); var GroupVmlElement = svgRendererInternals.BaseSvgElement.inherit(BaseVmlElement).inherit({ isVml: function() { return false }, defaultSettings: function() { return { x: 0, y: 0, position: 'absolute' } }, ctor: function(renderer, params) { this.callBase(renderer, 'div', params) }, adjustSettings: function() { if (this.settings.clipId || this._clipRect) { var rect = this.renderer.getClipRect(this.settings.clipId, this); if (this._clipRect) if (rect) this._clipRect.applySettings({ x: rect.x, y: rect.y, width: rect.width, height: rect.height }); else { this._clipRect.remove(); this._clipRect = null } else this._clipRect = this.renderer.createRect(rect.x, rect.y, rect.width, rect.height, 0, { fill: "none", opacity: 0.002, "class": CLIP_RECT_CLASS }); if (this._clipRect) this.childElements.length && this._clipRect.append(this) } }, applySettings: function(settings) { var rotate; settings = settings || {}; rotate = settings.rotate; if (rotate) { if (utils.isNumber(rotate)) rotate = [rotate, settings.x || 0, settings.y || 0]; $.each(this.childElements, function(_, child) { child.applySettings({rotate: rotate}) }) } delete settings.rotate; delete settings.x; delete settings.y; this.callBase(settings); $.each(this.childElements || [], function(_, c) { c.applySettings({}) }); return this }, getBBox: function() { return this._getBBox() }, update: function() { if (this.settings.clipId) { var bbox = this.getBBox(); this.applyStyle({ left: bbox.x + (this.settings.translateX || 0), right: bbox.y + (this.settings.translateY || 0), width: bbox.width, height: bbox.height }) } } }); renderers.VmlRenderer = renderers.SvgRenderer.inherit({ ctor: function(options) { options = options || {}; options.animation = {enabled: false}; if (doc.namespaces && !doc.namespaces.vml) { doc.namespaces.add('vml', 'urn:schemas-microsoft-com:vml'); var cssText = 'vml\\:fill, vml\\:path, vml\\:shape, vml\\:stroke, vml\\:rect, vml\\:oval' + '{ behavior:url(#default#VML); display: inline-block; };'; try { doc.createStyleSheet().cssText = cssText } catch(e) { doc.styleSheets[0].cssText += cssText } } this._clipRects = {}; this.cssClass = options.cssClass || ''; this.callBase(options) }, dispose: function() { this.callBase(); this._clipRects = null; this._size = null }, updateAnimationOptions: $.noop, draw: function(container) { var root = this.getRoot(); this.callBase(container); if (root) root.appendComplete() }, recreateCanvas: function(width, height, cssClass) { if (width >= 0 && height >= 0) { this._size = { width: width, height: height }; if (!this.svgRoot) { this.cssClass = cssClass || this.cssClass; this.svgRoot = new RootVmlElement(this, { width: width, height: height, 'class': this.cssClass }) } else this.svgRoot.applySettings({ width: width, height: height }); this.defsSvg && this.defsSvg.clear() } }, _getSize: function() { return this._size || {} }, isElementAppendedToPage: function(element) { return $(element.element).closest(doc.documentElement).length }, createRect: function(x, y, w, h, r, options) { var params = $.extend(true, {}, options || {}, { x: x, y: y, width: w, height: h, rx: r, ry: r }); return new RectVmlElement(this, params) }, createSegmentRect: function(x, y, w, h, r, segments, options) { var params = $.extend({}, options || {}, { x: x, y: y, width: w, height: h, rx: r, ry: r, segments: segments }); return new SegmentRectVmlElement(this, params) }, createClipRect: function(x, y, width, height) { var clipId = utils.getNextDefsSvgId(), elements = [], clipRect = { id: clipId, x: x, y: y, width: width, height: height, addElement: function(element) { var hasElement = false; $.each(elements, function() { if (this === element) { hasElement = true; return false } }); if (!hasElement) elements.push(element) }, append: function() { return this }, remove: function(){}, dispose: function(){}, updateRectangle: function(settings) { if ('x' in settings) this.x = settings.x; if ('translateX' in settings) this.x += settings.translateX; if ('y' in settings) this.y = settings.y; if ('translateY' in settings) this.y += settings.translateY; if ('width' in settings) this.width = settings.width; if ('height' in settings) this.height = settings.height; $.each(elements, function() { this.applySettings({clipId: clipId}) }); return this } }; this._clipRects[clipId] = clipRect; return clipRect }, getClipRect: function(clipId, element) { var clipRect = this._clipRects[clipId]; if (clipRect && element) clipRect.addElement(element); return this._clipRects[clipId] }, createImage: function(x, y, w, h, href, options) { var params = $.extend(true, {}, options && !options.inh ? options : {}, { x: x, y: y, width: w, height: h, href: href }); return new ImageVmlElement(this, params) }, createLine: function(x1, y1, x2, y2, options) { var params = $.extend(true, {}, options && !options.inh ? options : {}, {points: [x1, y1, x2, y2]}); return new PathVmlElement(this, params) }, createPath: function(points, options) { var params = $.extend(true, {}, options && !options.inh ? options : {}, {points: points}); return new PathVmlElement(this, params) }, createSimplePath: function(options) { return new SimplePathVmlElement(this, options) }, createBezierPath: function(points, options) { var params = $.extend(true, {}, options && !options.inh ? options : {}, {points: points}); return new BezierVmlElement(this, params) }, createArea: function(points, options) { var params = $.extend(true, {}, options && !options.inh ? options : {}, {points: points}); return new AreaVmlElement(this, params) }, createBezierArea: function(points, options) { var params = $.extend(true, {}, options && !options.inh ? options : {}, {points: points}); return new BezierAreaVmlElement(this, params) }, createCircle: function(x, y, r, options) { var params = $.extend(true, {}, options && !options.inh ? options : {}, { cx: x, cy: y, r: r }); return new CircleVmlElement(this, params) }, createArc: function(x, y, outerRadius, innerRadius, startAngle, endAngle, options) { var params = $.extend(true, {}, options && !options.inh ? options : {}, { x: x, y: y, outerRadius: outerRadius, innerRadius: innerRadius, startAngle: startAngle, endAngle: endAngle }); return new ArcVmlElement(this, params) }, createText: function(text, x, y, options) { var params = $.extend(true, {}, options && !options.inh ? options : {}, { x: x, y: y, text: text }); return new TextVmlElement(this, params) }, createGroup: function(options) { return new GroupVmlElement(this, options) }, createPattern: function(color, hatching) { return { id: color, append: function() { return this }, clear: function(){}, dispose: function(){} } }, createFilter: function(type) { if (type === 'shadow') return { ref: null, append: function() { return this }, dispose: function() { return this }, applySettings: function() { return this } }; return null }, svg: function() { return '' } }); function buildPath(points) { var i = 0, ii = points.length, list = []; for (; i < ii; ) list.push('l', points[i++].toFixed(0), points[i++].toFixed(0)); if (ii) { list[0] = 'm'; list.push('x e'); list = list.join(' ') } else list = ''; return list } function processCircleSettings(x, y, size) { return { cx: x, cy: y, r: size / 2 } } renderers._vmlBuildPath = buildPath; renderers._vmlProcessCircleSettings = processCircleSettings; renderers.__vmlRendererInternals = { RootVmlElement: RootVmlElement, RectVmlElement: RectVmlElement, ImageVmlElement: ImageVmlElement, PathVmlElement: PathVmlElement, AreaVmlElement: AreaVmlElement, BezierVmlElement: BezierVmlElement, BezierAreaVmlElement: BezierAreaVmlElement, SimplePathVmlElement: SimplePathVmlElement, CircleVmlElement: CircleVmlElement, TextVmlElement: TextVmlElement, GroupVmlElement: GroupVmlElement, ArcVmlElement: ArcVmlElement, SegmentRectVmlElement: SegmentRectVmlElement } })(jQuery, DevExpress); /*! Module viz-core, file renderer.js */ (function($, DX) { var renderers = DX.viz.renderers, browser = DX.browser; function isSvg() { return !(browser.msie && browser.version < 9) || !!document.createElementNS && !!document.createElementNS('http://www.w3.org/2000/svg', "svg").createSVGRect } if (!isSvg()) { renderers.Renderer = renderers.VmlRenderer; renderers.buildPath = renderers._vmlBuildPath; renderers.processCircleSettings = renderers._vmlProcessCircleSettings } else { renderers.Renderer = renderers.SvgRenderer; renderers.buildPath = renderers._svgBuildPath; renderers.processCircleSettings = renderers._svgProcessCircleSettings } renderers.isSvg = isSvg })(jQuery, DevExpress); /*! Module viz-core, file animation.js */ (function(DX) { var renderers = DX.viz.renderers, Class = DX.Class, noop = function(){}, easingFunctions = { easeOutCubic: function(pos, start, end) { return pos === 1 ? end : (1 - Math.pow(1 - pos, 3)) * (end - start) + +start }, linear: function(pos, start, end) { return pos === 1 ? end : pos * (end - start) + +start } }; renderers.easingFunctions = easingFunctions; renderers.animationSvgStep = { points: function(elem, params, progress, easing, currentParams) { var from = params.from, to = params.to, path = [], i, j, seg, d; for (i = 0; i < from.length; i++) { seg = [from[i][0]]; if (from[i].length > 1) for (j = 1; j < from[i].length; j++) seg.push(easing(progress, from[i][j], to[i][j])); path[i] = seg.join(' ') } d = path.join(' '); currentParams.d = params.end && progress === 1 ? params.end : d; elem.element.setAttribute('d', d) }, arc: function(elem, params, progress, easing) { var from = params.from, to = params.to, current = {}; for (var i in from) current[i] = easing(progress, from[i], to[i]); elem.applySettings(current) }, transform: function(elem, params, progress, easing, currentParams) { var translate = params.translate, rotate = params.rotate, scale = params.scale, transformations = [], elemSettings = elem.settings; if (translate) { currentParams.translateX = easing(progress, translate.x.from, translate.x.to); currentParams.translateY = easing(progress, translate.y.from, translate.y.to); transformations.push('translate(' + currentParams.translateX + ',' + currentParams.translateY + ')') } else if (elemSettings.translateX || elemSettings.translateY) transformations.push('translate(' + (elemSettings.translateX || 0) + ',' + (elemSettings.translateY || 0) + ')'); if (rotate) { currentParams.rotate = { angle: easing(progress, rotate.angle.from, rotate.angle.to), x: rotate.x, y: rotate.y }; transformations.push('rotate(' + currentParams.rotate.angle + ',' + rotate.x + ',' + rotate.y + ')') } else if (elemSettings.rotate) transformations.push('rotate(' + elemSettings.rotate.angle + ',' + (elemSettings.rotate.x || 0) + ',' + (elemSettings.rotate.y || 0) + ')'); if (scale) { currentParams.scale = { x: easing(progress, scale.x.from, scale.x.to), y: easing(progress, scale.y.from, scale.y.to) }; transformations.push('scale(' + currentParams.scale.x + ',' + currentParams.scale.y + ')') } else if (elemSettings.scale) transformations.push('scale(' + elemSettings.scale.x + ',' + elemSettings.scale.y + ')'); elem.element.setAttribute('transform', transformations.join()) }, base: function(elem, params, progress, easing, currentParams, attributeName) { currentParams[attributeName] = easing(progress, params.from, params.to); elem.element.setAttribute(attributeName, currentParams[attributeName]) }, _: noop, complete: function(element, currentSettings) { element.applySettings(currentSettings) } }; var Animation = Class.inherit({ ctor: function(element, params, options) { var that = this; that._progress = 0; that.element = element; that.params = params; that.options = options; that.duration = options.partitionDuration ? options.duration * options.partitionDuration : options.duration; that._animateStep = options.animateStep || renderers.animationSvgStep; that._easing = easingFunctions[options.easing] || easingFunctions['easeOutCubic']; that._currentParams = {}; that.tick = that._start }, _calcProgress: function(now) { return Math.min(1, (now - this._startTime) / this.duration) }, _step: function(now) { var that = this, animateStep = that._animateStep, attrName; that._progress = that._calcProgress(now); for (attrName in that.params) { if (!that.params.hasOwnProperty(attrName)) continue; var anim = animateStep[attrName] || animateStep.base; anim(that.element, that.params[attrName], that._progress, that._easing, that._currentParams, attrName) } that.options.step && that.options.step(that._easing(that._progress, 0, 1), that._progress); if (that._progress === 1) return that.stop(); return true }, _start: function(now) { this._startTime = now; this.tick = this._step; return true }, _end: function(disableComplete) { var that = this; that.stop = noop; that.tick = noop; that._animateStep.complete && that._animateStep.complete(that.element, that._currentParams); that.options.complete && !disableComplete && that.options.complete() }, tick: function(now) { return true }, stop: function(breakAnimation, disableComplete) { var options = this.options; if (!breakAnimation && options.repeatCount && --options.repeatCount > 0) { this.tick = this._start; return true } else this._end(disableComplete) } }); renderers.AnimationController = Class.inherit(function() { var FPS = 1000 / 60, requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) { setTimeout(callback, FPS) }; return { ctor: function() { var that = this; that.requestAnimationFrame = requestAnimationFrame; that._animationCount = 0; that._timerId = null; that._animations = {} }, _loop: function() { var that = this, animations = that._animations, activeAnimation = 0, now = (new Date).getTime(), an; for (an in animations) { if (!animations.hasOwnProperty(an)) continue; if (!animations[an].tick(now)) delete animations[an]; activeAnimation++ } if (activeAnimation === 0) { that.stop(); return } that._timerId = that.requestAnimationFrame.call(null, function() { that._loop() }, that.element) }, addAnimation: function(animation) { var that = this; that._animations[that._animationCount++] = animation; if (!that._timerId) { clearTimeout(that._startDelay); that._startDelay = setTimeout(function() { that._timerId = 1; that._loop() }, 0) } }, animateElement: function(elem, params, options) { if (elem && params && options) { elem.animation && elem.animation.stop(true); this.addAnimation(elem.animation = new Animation(elem, params, options)) } }, dispose: function() { this.stop(); this.element = null }, stop: function() { this._animations = {}; this._animationCount = 0; clearTimeout(this._startDelay); this._timerId = null }, lock: function() { var animations = this._animations; for (var an in animations) animations.hasOwnProperty(an) && animations[an].stop(true, true); this.stop() } } }()); renderers.Animation = Animation; renderers.noop = noop })(DevExpress); /*! Module viz-core, file namespaces.js */ (function(DevExpress) { DevExpress.viz.charts = {series: {}} })(DevExpress); /*! Module viz-core, file chartsConsts.js */ (function(DX) { DX.viz.charts.consts = { dataTypes: { STRING: 'string', NUMERIC: 'numeric', DATETIME: 'datetime' }, axisTypes: { DISCRETE: 'discrete', CONTINUOUS: 'continuous', LOGARITHMIC: 'logarithmic' } } })(DevExpress); /*! Module viz-core, file dataValidator.js */ (function($, DX) { var viz = DX.viz, parseUtils = new viz.core.ParseUtils, chartConst = viz.charts.consts, dataTypes = chartConst.dataTypes, axisTypes = chartConst.axisTypes, utils = DX.utils, _each = $.each, _isDefined = utils.isDefined; var mergeSort = function(data, field) { function merge_sort(array, low, high, field) { if (low < high) { var mid = Math.floor((low + high) / 2); merge_sort(array, low, mid, field); merge_sort(array, mid + 1, high, field); merge(array, low, mid, high, field) } } var n = data.length; merge_sort(data, 0, n - 1, field); return data }; var merge = function(array, low, mid, high, field) { var newArray = new Array(high - low + 1), countL = low, countR = mid + 1, k, i = 0; while (countL <= mid && countR <= high) { if (array[countL][field] <= array[countR][field] || !_isDefined(array[countR][field])) { newArray[i] = array[countL]; countL++ } else { newArray[i] = array[countR]; countR++ } i++ } if (countL > mid) for (k = countR; k <= high; k++, i++) newArray[i] = array[k]; else for (k = countL; k <= mid; k++, i++) newArray[i] = array[k]; for (k = 0; k <= high - low; k++) array[k + low] = newArray[k]; return array }; viz.charts.DataValidator = DX.Class.inherit({ ctor: function(data, groups, incidentOccured, dataPrepareOptions) { var that = this; groups = groups || [[]]; if (!data) that._nullData = true; that.groups = groups; that.data = data || []; that._parsers = {}; that._errorShowList = {}; that._skipFields = {}; that.options = dataPrepareOptions || {}; that.incidentOccured = incidentOccured; that.userArgumentCategories = that.groups.length && that.groups[0].length && that.groups[0][0].getArgumentCategories(); if (!incidentOccured) that.incidentOccured = $.noop }, validate: function validate() { var that = this; that._data = that.data; if (!utils.isArray(that.data) || that._nullData) that._incorrectDataMessage(); that.groups.argumentType = null; that.groups.argumentAxisType = null; $.each(that.groups, function(_, group) { group.valueType = null; group.valueAxisType = null; $.each(group, function(_, series) { series.updateDataType({}) }) }); that._checkType(); that._checkAxisType(); if (that.options.convertToAxisDataType) { that._createParser(); that._parse() } that._groupData(); that._sort(); $.each(that._skipFields, function(field, fieldValue) { if (fieldValue === that._data.length) that.incidentOccured("W2002", [field]) }); return that._data }, _checkType: function _checkType() { var that = this, groupsWithUndefinedValueType = [], groupsWithUndefinedArgumentType = [], checkValueTypeOfGroup = function checkValueTypeOfGroup(group, cell) { $.each(group, function(_, series) { $.each(series.getValueFields(), function(_, field) { group.valueType = that._getType(cell[field], group.valueType) }) }); if (group.valueType) return true }, checkArgumentTypeOfGroup = function checkArgumentTypeOfGroup(group, cell) { $.each(group, function(_, series) { that.groups.argumentType = that._getType(cell[series.getArgumentField()], that.groups.argumentType) }); if (that.groups.argumentType) return true }; $.each(that.groups, function(_, group) { if (!group.length) return null; var options = group[0].getOptions(), valueTypeGroup = options.valueType, argumentTypeGroup = options.argumentType; group.valueType = valueTypeGroup; that.groups.argumentType = argumentTypeGroup; valueTypeGroup ? null : groupsWithUndefinedValueType.push(group); argumentTypeGroup ? null : groupsWithUndefinedArgumentType.push(group) }); if (groupsWithUndefinedValueType.length || groupsWithUndefinedArgumentType.length) $.each(that.data, function(_, cell) { var define = true; if (!utils.isObject(cell)) return; $.each(groupsWithUndefinedValueType, function(index, group) { define = define && checkValueTypeOfGroup(group, cell) }); $.each(groupsWithUndefinedArgumentType, function(index, group) { define = define && checkArgumentTypeOfGroup(group, cell) }); if (!that.options.checkTypeForAllData && define) return false }) }, _checkAxisType: function _checkAxisType() { var that = this; $.each(that.groups, function(_, group) { $.each(group, function(_, series) { var optionsSeries = {}, existingSeriesOptions = series.getOptions(); optionsSeries.argumentAxisType = that._correctAxisType(that.groups.argumentType, existingSeriesOptions.argumentAxisType, !!that.userArgumentCategories.length); optionsSeries.valueAxisType = that._correctAxisType(group.valueType, existingSeriesOptions.valueAxisType, !!series.getValueCategories().length); that.groups.argumentAxisType = that.groups.argumentAxisType || optionsSeries.argumentAxisType; group.valueAxisType = group.valueAxisType || optionsSeries.valueAxisType; optionsSeries.argumentType = that.groups.argumentType; optionsSeries.valueType = group.valueType; series.updateDataType(optionsSeries) }) }) }, _createParser: function _createParser() { var that = this; $.each(that.groups, function(index, group) { $.each(group, function(_, series) { that._parsers[series.getArgumentField()] = that._createParserUnit(that.groups.argumentType, that.groups.argumentAxisType === axisTypes.LOGARITHMIC ? that._filterForLogAxis : null); $.each(series.getValueFields(), function(_, field) { that._parsers[field] = that._createParserUnit(group.valueType, group.valueAxisType === axisTypes.LOGARITHMIC ? that._filterForLogAxis : null, series.getOptions().ignoreEmptyPoints) }); if (series.getTagField()) that._parsers[series.getTagField()] = null }) }) }, _parse: function _parse() { var that = this, parsedData = []; $.each(that.data, function(_, cell) { var parserObject = {}; if (!utils.isObject(cell)) { cell && that._incorrectDataMessage(); return } $.each(that._parsers, function(field, parser) { parserObject[field] = parser ? parser(cell[field], field) : cell[field]; parserObject['original' + field] = cell[field] }); parsedData.push(parserObject) }); this._data = parsedData }, _groupMinSlices: function(argumentField, valueField, smallValuesGrouping) { var that = this, smallValuesGrouping = smallValuesGrouping || {}, mode = smallValuesGrouping.mode, count = smallValuesGrouping.topCount, threshold = smallValuesGrouping.threshold, name = smallValuesGrouping.groupName || 'others', others = {}, data = that._data.slice(), index; var groupingValues = function(index) { if (!_isDefined(index) || index < 0) return; _each(data.slice(index), function(_, cell) { if (!_isDefined(cell[valueField])) return; others[valueField] += cell[valueField]; cell[valueField] = undefined; cell['original' + valueField] = undefined }) }; if (!mode || mode === 'none') return; others[argumentField] = name + ''; others[valueField] = 0; data.sort(function(a, b) { if (_isDefined(b[valueField]) && _isDefined(a[valueField])) return b[valueField] - a[valueField]; else if (!_isDefined(b[valueField]) && a[valueField]) return -1; else if (!_isDefined(a[valueField]) && b[valueField]) return 1 }); if (mode === 'smallValueThreshold') { _each(data, function(i, cell) { if (_isDefined(index) || !_isDefined(cell[valueField])) return; if (threshold > cell[valueField]) index = i }); groupingValues(index) } else if (mode === 'topN') groupingValues(count); others[valueField] && that._data.push(others) }, _groupData: function() { var that = this, groups = that.groups, isPie = groups.length && groups[0].length && (groups[0][0].type === 'pie' || groups[0][0].type === 'doughnut' || groups[0][0].type === 'donut'), argumentField, valueFields; if (!isPie) return; _each(groups, function(_, group) { _each(group, function(_, series) { argumentField = series.getArgumentField(); valueFields = series.getValueFields(); if (groups.argumentAxisType === axisTypes.DISCRETE) that._groupSameArguments(argumentField, valueFields); that._groupMinSlices(argumentField, valueFields[0], series.getOptions().smallValuesGrouping) }) }) }, _groupSameArguments: function(argumentField, valueFields) { var that = this, argument, dataOfArguments = {}, parsedData = that._data; _each(parsedData, function(i, cell) { if (!_isDefined(cell[argumentField]) || !_isDefined(cell[valueFields[0]])) return; argument = cell[argumentField]; if (_isDefined(dataOfArguments[argument])) { var data = parsedData[dataOfArguments[argument]]; _each(valueFields, function(_, field) { data[field] += cell[field]; cell[field] = undefined; cell['original' + field] = undefined }) } else dataOfArguments[argument] = i }) }, _getType: function _getType(unit, type) { if (type === dataTypes.STRING || utils.isString(unit)) return dataTypes.STRING; if (type === dataTypes.DATETIME || utils.isDate(unit)) return dataTypes.DATETIME; if (utils.isNumber(unit)) return dataTypes.NUMERIC; return type }, _correctAxisType: function _correctAxisType(type, axisType, hasCategories) { if (type === dataTypes.STRING && (axisType === axisTypes.CONTINUOUS || axisType === axisTypes.LOGARITHMIC)) this.incidentOccured("E2002"); if (axisType === axisTypes.LOGARITHMIC) return axisTypes.LOGARITHMIC; axisType = (hasCategories || axisType === axisTypes.DISCRETE || type === dataTypes.STRING) && axisTypes.DISCRETE; return axisType || axisTypes.CONTINUOUS }, _filterForLogAxis: function(val, field) { if (val <= 0) { this.incidentOccured("E2004", [field]); return null } return val }, _createParserUnit: function _createParserUnit(type, filter, ignoreEmptyPoints) { var that = this, parser = type ? parseUtils.getParser(type, undefined, true) : function(unit) { return unit }; return function(unit, field) { var parseUnit = parser(unit); if (filter) parseUnit = filter.call(that, parseUnit, field); parseUnit === null && ignoreEmptyPoints && (parseUnit = undefined); if (parseUnit === undefined) { that._addSkipFields(field); that._validUnit(unit, field, type) } return parseUnit } }, _validUnit: function _validUnit(unit, field, type) { if (!unit) return; if (!utils.isNumber(unit) && !utils.isDate(unit) && !utils.isString(unit)) { this.incidentOccured("E2003", [field]); return } this.incidentOccured("E2004", [field]) }, _sort: function _sort() { var that = this, groups = that.groups, hash = {}, argumentField = groups.length && groups[0].length && groups[0][0].getArgumentField(); if (utils.isFunction(that.options.sortingMethod)) that._data.sort(that.options.sortingMethod); else if (that.userArgumentCategories.length) { $.each(that.userArgumentCategories, function(index, value) { hash[value] = index }); that._data.sort(function sortCat(a, b) { a = a[argumentField]; b = b[argumentField]; return hash[a] - hash[b] }) } else if (that.options.sortingMethod === true && groups.argumentType !== dataTypes.STRING) mergeSort(that._data, argumentField) }, _addSkipFields: function _addSkipFields(field) { this._skipFields[field] = (this._skipFields[field] || 0) + 1 }, _incorrectDataMessage: function() { if (this._erorrDataSource !== true) { this._erorrDataSource = true; this.incidentOccured("E2001") } } }) })(jQuery, DevExpress); /*! Module viz-core, file themeManager.js */ (function($, DX, undefined) { var viz = DX.viz, Palette = viz.core.Palette, utils = DX.utils; var HOVER_COLOR_HIGHLIGHTING = 20, HIGHLIGHTING_STEP = 50; viz.charts.ThemeManager = viz.core.BaseThemeManager.inherit(function() { var ctor = function(options, themeGroupName) { var that = this; options = options || {}; that._userOptions = options; that._mergeAxisTitleOptions = []; themeGroupName && (that._themeSection = themeGroupName); that._IE8 = DX.browser.msie && DX.browser.version < 9; that.setTheme(options.theme); that.palette = new Palette(options.palette, { stepHighlight: HIGHLIGHTING_STEP, theme: that._themeName }) }; var dispose = function() { var that = this; that.palette.dispose(); that.palette = that._userOptions = that._mergedSettings = null; that.callBase() }; var initDefaultSeriesTheme = function(that) { var commonSeriesSettings = that._theme.commonSeriesSettings; commonSeriesSettings.point = commonSeriesSettings.point || {}; commonSeriesSettings.label = commonSeriesSettings.label || {}; that._initializeFont(commonSeriesSettings.label.font) }; var initAxisTheme = function(that) { var axisTheme = that._theme.commonAxisSettings; if (axisTheme) { axisTheme.label = axisTheme.label || {}; axisTheme.grid = axisTheme.grid || {}; axisTheme.ticks = axisTheme.ticks || {}; axisTheme.line = axisTheme.line || {}; axisTheme.title = axisTheme.title || {}; axisTheme.label.font = axisTheme.label.font || {}; that._initializeFont(axisTheme.label.font); axisTheme.title.font = axisTheme.title.font || {}; that._initializeFont(axisTheme.title.font) } }; var resetPalette = function() { this.palette.reset() }; var updatePalette = function(palette) { this.palette = new Palette(palette || this._theme.defaultPalette, { stepHighlight: HIGHLIGHTING_STEP, theme: this.themeName }) }; var processTitleOptions = function(options) { return utils.isString(options) ? {text: options} : options }; var processAxisOptions = function(axisOptions, name) { if (!axisOptions) return; axisOptions = $.extend(true, {}, axisOptions); axisOptions.title = processTitleOptions(axisOptions.title); if (axisOptions.type === 'logarithmic' && axisOptions.logarithmBase <= 0 || axisOptions.logarithmBase && !$.isNumeric(axisOptions.logarithmBase)) { axisOptions.logarithmBase = undefined; axisOptions.logarithmBaseError = true } if (axisOptions.label) { if (axisOptions.label.alignment) axisOptions.label['userAlignment'] = true; if (!axisOptions.label.overlappingBehavior) { if (axisOptions.label.staggered) axisOptions.label.overlappingBehavior = { mode: 'stagger', staggeringSpacing: axisOptions.label.staggeringSpacing }; if (axisOptions.label.rotationAngle) axisOptions.label.overlappingBehavior = { mode: 'rotate', rotationAngle: axisOptions.label.rotationAngle } } if (utils.isString(axisOptions.label.overlappingBehavior)) axisOptions.label.overlappingBehavior = {mode: axisOptions.label.overlappingBehavior}; if (!axisOptions.label.overlappingBehavior || !axisOptions.label.overlappingBehavior.mode) axisOptions.label.overlappingBehavior = axisOptions.label.overlappingBehavior || {} } return axisOptions }; var applyParticularAxisOptions = function(name, userOptions, rotated) { var theme = this._theme, position = !(rotated ^ name === "valueAxis") ? "horizontalAxis" : "verticalAxis", commonAxisSettings = processAxisOptions(this._userOptions["commonAxisSettings"], name); return $.extend(true, {}, theme.commonAxisSettings, theme[position], theme[name], commonAxisSettings, processAxisOptions(userOptions, name)) }; var mergeOptions = function(name, userOptions) { userOptions = userOptions || this._userOptions[name]; var theme = this._theme[name], result = this._mergedSettings[name]; if (result) return result; if ($.isPlainObject(theme) && $.isPlainObject(userOptions)) result = $.extend(true, {}, theme, userOptions); else result = utils.isDefined(userOptions) ? userOptions : theme; this._mergedSettings[name] = result; return result }; var applyParticularTheme = { base: mergeOptions, argumentAxis: applyParticularAxisOptions, valueAxisRangeSelector: function() { return mergeOptions.call(this, 'valueAxis') }, valueAxis: applyParticularAxisOptions, title: function(name) { var userOptions = processTitleOptions(this._userOptions[name]); return mergeOptions.call(this, name, userOptions) }, series: function(name, userOptions, isPie) { var theme = this._theme, userCommonSettings = this._userOptions.commonSeriesSettings || {}, themeCommonSettings = theme.commonSeriesSettings, type = ((userOptions.type || userCommonSettings.type || themeCommonSettings.type) + '').toLowerCase(), settings, palette = this.palette, isBar = ~type.indexOf('bar'), isBubble = ~type.indexOf('bubble'), mainSeriesColor, containerBackgroundColor = this.getOptions("containerBackgroundColor"); if (isBar || isBubble) { userOptions = $.extend(true, {}, userCommonSettings, userCommonSettings[type], userOptions); var seriesVisibility = userOptions.visible; userCommonSettings = {type: {}}; $.extend(true, userOptions, userOptions.point); userOptions.visible = seriesVisibility } settings = $.extend(true, {}, themeCommonSettings, themeCommonSettings[type], userCommonSettings, userCommonSettings[type], userOptions); settings.type = type; settings.containerBackgroundColor = containerBackgroundColor; if (!isPie) { settings.widgetType = 'chart'; mainSeriesColor = settings.color || palette.getNextColor() } else { settings.widgetType = 'pieChart'; mainSeriesColor = function() { return palette.getNextColor() } } settings.mainSeriesColor = mainSeriesColor; settings._IE8 = this._IE8; return settings }, pieSegment: function(name, seriesSettings, segmentSettings) { var settings = $.extend(true, {}, seriesSettings, segmentSettings); var mainColor = new DX.Color(settings.color || this.palette.getNextColor()); settings.color = mainColor.toHex(); settings.border.color = settings.border.color || mainColor.toHex(); settings.hoverStyle.color = settings.hoverStyle.color || this._IE8 && mainColor.highlight(HOVER_COLOR_HIGHLIGHTING) || mainColor.toHex(); settings.hoverStyle.border.color = settings.hoverStyle.border.color || mainColor.toHex(); settings.selectionStyle.color = settings.selectionStyle.color || this._IE8 && mainColor.highlight(HOVER_COLOR_HIGHLIGHTING) || mainColor.toHex(); settings.selectionStyle.border.color = settings.selectionStyle.border.color || mainColor.toHex(); return settings }, animation: function(name) { var userOptions = this._userOptions[name]; userOptions = $.isPlainObject(userOptions) ? userOptions : utils.isDefined(userOptions) ? {enabled: !!userOptions} : {}; return mergeOptions.call(this, name, userOptions) } }; return { _themeSection: 'chart', ctor: ctor, dispose: dispose, _initializeTheme: function() { var that = this, theme = this._theme; theme.legend = theme.legend || {}; theme.legend.font = theme.legend.font || {}; that._initializeFont(theme.legend.font); initDefaultSeriesTheme(that); initAxisTheme(that); theme.title = theme.title || {}; theme.title.font = theme.title.font || {}; that._initializeFont(theme.title.font); theme.tooltip = theme.tooltip || {}; theme.tooltip.font = theme.tooltip.font || {}; that._initializeFont(theme.tooltip.font); theme.loadingIndicator = theme.loadingIndicator || {}; theme.loadingIndicator.font = theme.loadingIndicator.font || {}; that._initializeFont(theme.loadingIndicator.font) }, resetPalette: resetPalette, getOptions: function(name) { return (applyParticularTheme[name] || applyParticularTheme["base"]).apply(this, arguments) }, setTheme: function(theme) { var that = this; that._mergedSettings = {}; that.callBase(theme); that.getOptions('rtlEnabled') && $.extend(true, that._theme, that._theme._rtl) }, resetOptions: function(name) { this._mergedSettings[name] = null }, update: function(options) { this._userOptions = options }, updatePalette: updatePalette } }()) })(jQuery, DevExpress); /*! Module viz-core, file factory.js */ (function($, DX) { var viz = DX.viz, charts = viz.charts, series = charts.series; charts.factory = function() { var createSeriesFamily = function(options) { return new series.SeriesFamily(options) }; var createAxis = function(renderer, options) { return new charts.Axis(renderer, options) }; var createThemeManager = function(options, groupName) { return new charts.ThemeManager(options, groupName) }; var createDataValidator = function(data, groups, incidentOccured, dataPrepareOptions) { return new charts.DataValidator(data, groups, incidentOccured, dataPrepareOptions) }; var createTracker = function(options) { return new charts.Tracker(options) }; var createTitle = function(renderer, canvas, options, group) { return new charts.ChartTitle(renderer, canvas, options, group) }; var createChartLayoutManager = function(options) { return new charts.LayoutManager(options) }; return { createSeriesFamily: createSeriesFamily, createAxis: createAxis, createThemeManager: createThemeManager, createDataValidator: createDataValidator, createTracker: createTracker, createChartLayoutManager: createChartLayoutManager, createTitle: createTitle } }() })(jQuery, DevExpress); /*! Module viz-core, file baseWidget.js */ (function($, DX, undefined) { var core = DX.viz.core, utils = DX.utils; DX.viz.core.BaseWidget = DX.DOMComponent.inherit({ NAMESPACE: DX.ui, _init: function() { this._setRedrawOnResize(this._getOptionRedrawOnResize()); this._incidentOccured = this._createIncidentOccured(); this._renderVisiblityChange() }, _optionChanged: function(name, value, prevValue) { var that = this; switch (name) { case'redrawOnResize': that._setRedrawOnResize(that._getOptionRedrawOnResize()); break; case'loadingIndicator': that._updateLoadIndicator(that._getLoadIndicatorOption()); break; default: that._invalidate() } that.callBase(name, value, prevValue) }, _getOptionRedrawOnResize: function() { var redrawOnResize = this.option('redrawOnResize'); redrawOnResize = redrawOnResize !== undefined ? !!redrawOnResize : true; return redrawOnResize }, _getLoadIndicatorOption: function() { return this.option('loadingIndicator') }, _dispose: function() { var that = this; if (that._resizeHandlerCallback) that._removeResizeCallbacks(); that._incidentOccured = null; that.callBase() }, _visibilityChanged: function(visible) { if (visible) this.render() }, _setRedrawOnResize: function(redrawOnResize) { var that = this; if (redrawOnResize) { if (!that._resizeHandlerCallback && utils.isFunction(that._resize)) { that._resizeHandlerCallback = DX.utils.createResizeHandler(function() { that._resize() }); utils.windowResizeCallbacks.add(that._resizeHandlerCallback) } } else that._removeResizeCallbacks() }, _removeResizeCallbacks: function() { var that = this; that._resizeHandlerCallback && that._resizeHandlerCallback.stop(); utils.windowResizeCallbacks.remove(that._resizeHandlerCallback); delete that._resizeHandlerCallback }, _showLoadIndicator: function(options, canvas) { var that = this; that._loadIndicator = this._loadIndicator || core.CoreFactory.createLoadIndicator(options, that._element()); that._loadIndicator.show(canvas.width, canvas.height); that._initializing && that._loadIndicator.endLoading(undefined, true) }, _updateLoadIndicator: function(options, width, height) { this._loadIndicator && this._loadIndicator.applyOptions(options, width, height) }, _endLoading: function(complete) { if (this._loadIndicator) this._loadIndicator.endLoading(complete); else complete && complete() }, _reappendLoadIndicator: function() { this._loadIndicator && this._loadIndicator.toForeground() }, _disposeLoadIndicator: function() { this._loadIndicator && this._loadIndicator.dispose(); this._loadIndicator = null }, _setDefaultOptions: function() { this.callBase(); this.option({incidentOccured: function(options) { var message = "" + options.id + " - " + options.text, majorVerision = options.version.split(".").slice(0, 2).join("_"), url = "http://js.devexpress.com/error/" + majorVerision + "/" + options.id; utils.logger.warn(message + "\n" + url) }}) }, _createIncidentOccured: function() { var that = this; return function(errorOrWarningId, options) { var isError = errorOrWarningId[0] === 'E', type = isError ? "error" : "warning", formattingArray = options ? options.slice(0) : [], text, incidentOccuredFunc = that.option('incidentOccured'); formattingArray.unshift(core.errorsWarnings[errorOrWarningId]); text = utils.stringFormat.apply(null, formattingArray); if (utils.isFunction(incidentOccuredFunc)) setTimeout(function() { incidentOccuredFunc({ id: errorOrWarningId, type: type, args: options, text: text, widget: that.NAME, version: DevExpress.VERSION }) }) } }, _normalizeHtml: function(html) { var re = /xmlns="[\s\S]*?"/gi, first = true; html = html.replace(re, function(match) { if (!first) return ""; first = false; return match }); return html.replace(/xmlns:NS1="[\s\S]*?"/gi, "").replace(/NS1:xmlns:xlink="([\s\S]*?)"/gi, 'xmlns:xlink="$1"') }, _drawn: function() { var that = this, drawnCallback = that.option('drawn'); utils.isFunction(drawnCallback) && setTimeout(function() { drawnCallback(that) }) }, showLoadingIndicator: function() { this._showLoadIndicator(this.option('loadingIndicator'), this.canvas || {}) }, hideLoadingIndicator: function() { this._loadIndicator && this._loadIndicator.hide() }, endUpdate: function() { if (this._updateLockCount === 1 && !this._requireRefresh) this.hideLoadingIndicator(); this.callBase() }, svg: function() { var renderer = this.renderer || this._renderer; return renderer ? this._normalizeHtml(renderer.svg()) : '' } }) })(jQuery, DevExpress); /*! Module viz-core, file CoreFactory.js */ (function(DX, undefined) { var renderers = DX.viz.renderers, core = DX.viz.core; DX.viz.core.CoreFactory = function() { return { createSeries: function(renderer, options) { return new core.series.Series(renderer, options) }, createPoint: function(data, options) { return new core.series.points.Point(data, options) }, createLabel: function(type, data, options) { if (type === "pie" || type === "doughnut" || type === "donut") return new core.series.points.PieLabel(data, options); else return new core.series.points.Label(data, options) }, createRenderer: function(options) { return new renderers.Renderer(options) }, createTranslator1D: function(fromValue, toValue, fromAngle, toAngle) { return (new core.Translator1D).setDomain(fromValue, toValue).setCodomain(fromAngle, toAngle) }, createTranslator2D: function(range, canvas, options) { return new core.Translator2D(range, canvas, options) }, getTickProvider: function() { return core.tickProvider }, createTooltip: function(options, group, renderer) { return new core.Tooltip(options, group, renderer) }, createLoadIndicator: function(options, group) { return new core.LoadIndicator(options, group) }, createLegend: function(data, options, renderer, group) { return new core.Legend(data, options, renderer, group) }, createSeriesFamily: function(options) { return new core.series.helpers.SeriesFamily(options) } } }() })(DevExpress); DevExpress.MOD_VIZ_CORE = true } if (!DevExpress.MOD_VIZ_CHARTS) { if (!DevExpress.MOD_VIZ_CORE) throw Error('Required module is not referenced: viz-core'); /*! Module viz-charts, file chartTitle.js */ (function($, DX, undefined) { var isDefined = DX.utils.isDefined, endsWith = function(value, pattern) { return value.substr(value.length - pattern.length) === pattern }, startsWith = function(value, pattern) { return value.indexOf(pattern) === 0 }, decreaseGaps = DevExpress.viz.core.utils.decreaseGaps, DEFAULT_MARGIN = 10; DX.viz.charts.ChartTitle = DX.Class.inherit({ ctor: function(renderer, options, width, group) { var that = this; that._init(options, width); that.renderer = renderer; that.titleGroup = group }, dispose: function() { var that = this; that.renderer = null; that.clipRect = null; that.title = null; that.innerTitleGroup = null; that.titleGroup = null; that.options = null }, update: function(options, width) { this._init(options, width) }, _init: function(options, width) { var that = this; if (options) { that._parseAlignments(options); that.horizontalAlignment = options.horizontalAlignment; that.verticalAlignment = options.verticalAlignment; that._parseMargins(options); that.margin = options.margin; that.options = options } that.setSize({width: width}) }, _parseMargins: function(options) { options.margin = isDefined(options.margin) ? options.margin : {}; if (typeof options.margin === 'number') { options.margin = options.margin >= 0 ? options.margin : DEFAULT_MARGIN; options.margin = { top: options.margin, bottom: options.margin, left: options.margin, right: options.margin } } else { options.margin.top = options.margin.top >= 0 ? options.margin.top : DEFAULT_MARGIN; options.margin.bottom = options.margin.bottom >= 0 ? options.margin.bottom : DEFAULT_MARGIN; options.margin.left = options.margin.left >= 0 ? options.margin.left : DEFAULT_MARGIN; options.margin.right = options.margin.right >= 0 ? options.margin.right : DEFAULT_MARGIN } }, _parseAlignments: function(options) { if (isDefined(options.position) && !(isDefined(options.verticalAlignment) && isDefined(options.horizontalAlignment))) { options.position = options.position.toLowerCase(); options.verticalAlignment = endsWith(options.position, 'top') ? 'top' : 'bottom'; options.horizontalAlignment = startsWith(options.position, 'left') ? 'left' : startsWith(options.position, 'center') && 'center' || 'right'; return } options.verticalAlignment = (options.verticalAlignment || '').toLowerCase(); options.horizontalAlignment = (options.horizontalAlignment || '').toLowerCase(); if (options.verticalAlignment !== 'top' && options.verticalAlignment !== 'bottom') options.verticalAlignment = 'top'; if (options.horizontalAlignment !== 'left' && options.horizontalAlignment !== 'center' && options.horizontalAlignment !== 'right') options.horizontalAlignment = 'center' }, _setBoundingRect: function() { var that = this, options = that.options, margin = that.changedMargin || that.margin, box; if (!that.innerTitleGroup) return; box = that.innerTitleGroup.getBBox(); box.height += margin.top + margin.bottom; box.width += margin.left + margin.right; box.x -= margin.left; box.y -= margin.top; if (isDefined(options.placeholderSize)) box.height = options.placeholderSize; that.boundingRect = box }, draw: function() { var that = this, titleOptions = that.options, renderer = that.renderer, attr; if (!titleOptions.text) return; that.changedMargin = null; if (!that.innerTitleGroup) { that.innerTitleGroup = renderer.createGroup(); that.clipRect = that.createClipRect(); that.titleGroup && that.clipRect && that.titleGroup.applySettings({clipId: that.clipRect.id}) } else that.innerTitleGroup.clear(); that.innerTitleGroup.append(that.titleGroup); attr = { font: titleOptions.font, align: that.horizontalAlignment, style: titleOptions.fontStyle }; that.title = renderer.createText(titleOptions.text, 0, 0, attr).append(that.innerTitleGroup); that.title.text = titleOptions.text; that._correctTitleLength(); that._setClipRectSettings() }, _correctTitleLength: function() { var that = this, text = that.title.text, updateText, lineLength, box; that.title.updateText(text); that._setBoundingRect(); box = that.getLayoutOptions(); if (that._width > box.width || text.indexOf("
") !== -1) return; lineLength = text.length * that._width / box.width; updateText = text.substr(0, ~~lineLength - 1 - 3) + "..."; that.title.updateText(updateText); that._setBoundingRect() }, changeSize: function(size) { var that = this, margin = $.extend(true, {}, that.margin); if (margin.top + margin.bottom < size.height) { if (this.innerTitleGroup) { that.options._incidentOccured("W2103"); this.innerTitleGroup.remove(); this.innerTitleGroup = null } if (that.clipRect) { that.clipRect.remove(); that.clipRect = null } } else if (size.height > 0) { decreaseGaps(margin, ["top", "bottom"], size.height); size.height && (that.changedMargin = margin) } that._correctTitleLength(); that._setBoundingRect(); that._setClipRectSettings() }, getLayoutOptions: function() { var options = this.options, boundingRect = this.innerTitleGroup ? this.boundingRect : { width: 0, height: 0, x: 0, y: 0 }; boundingRect.verticalAlignment = options.verticalAlignment; boundingRect.horizontalAlignment = options.horizontalAlignment; boundingRect.cutLayoutSide = options.verticalAlignment; return boundingRect }, setSize: function(size) { this._width = size.width || this._width }, shift: function(x, y) { var that = this, box = that.getLayoutOptions(); x -= box.x; y -= box.y; that.innerTitleGroup && that.innerTitleGroup.move(x, y); that.clipRect && that.clipRect.updateRectangle({ translateX: x, translateY: y }) }, createClipRect: function() { if (isDefined(this.options.placeholderSize)) return this.renderer.createClipRect(0, 0, 0, 0) }, _setClipRectSettings: function() { var bbox = this.getLayoutOptions(), clipRect = this.clipRect; if (clipRect) { clipRect.append(); clipRect.updateRectangle({ x: bbox.x, y: bbox.y, width: bbox.width, height: bbox.height }) } } }); DX.viz.charts.ChartTitle.__DEFAULT_MARGIN = DEFAULT_MARGIN })(jQuery, DevExpress); /*! Module viz-charts, file axis.js */ (function($, DX, undefined) { var utils = DX.utils, isDefinedUtils = utils.isDefined, isDateUtils = utils.isDate, mathAbs = Math.abs, core = DX.viz.core, AXIS_VALUE_MARGIN_PRIORITY = 100, DEFAULT_AXIS_LABEL_SPACING = 5, AXIS_STAGGER_OVERLAPPING_KOEF = 2, MAX_GRID_BORDER_ADHENSION = 4, CANVAS_POSITION_PREFIX = 'canvas_position_', CANVAS_POSITION_START = 'canvas_position_start', CANVAS_POSITION_END = 'canvas_position_end', TOP = 'top', BOTTOM = 'bottom', LEFT = 'left', RIGHT = 'right', CENTER = 'center'; DX.viz.charts.AXIS_STAGGER_OVERLAPPING_KOEF = AXIS_STAGGER_OVERLAPPING_KOEF; var processCustomOptions = function(options) { var label = options.label, position = options.position; if (options.isHorizontal) { if (!(position === BOTTOM || position === TOP)) position = BOTTOM } else if (!(position === LEFT || position === RIGHT)) position = LEFT; options.position = position; if (position === RIGHT && !label.userAlignment) label.alignment = LEFT }; var formatLabel = function(value, options, axisMinMax) { var formatObject = { value: value, valueText: DX.formatHelper.format(value, options.format, options.precision) || '' }; if (axisMinMax) { formatObject.min = axisMinMax.min; formatObject.max = axisMinMax.max } return options.customizeText ? options.customizeText.call(formatObject, formatObject) : formatObject.valueText }; var nextState = function(state) { switch (state) { case'overlap': return 'stagger'; case'stagger': return 'rotate'; case'rotate': default: return 'end' } }; DX.viz.charts.Axis = function(renderer, options) { var debug = DX.utils.debug; debug.assertParam(renderer, 'renderer was not passed'); debug.assertParam(options.label, 'label was not passed'); debug.assertParam(options.tick, 'tick was not passed'); debug.assertParam(options.grid, 'grid was not passed'); debug.assertParam(options.title, 'title was not passed'); debug.assert(options.axisDivisionFactor, 'axisDivisionFactor was not passed'); debug.assert(options.stripStyle, 'stripStyle was not passed'); debug.assert(options.constantLineStyle, 'constantLineStyle was not passed'); debug.assert(options.position, 'position was not passed'); debug.assertParam(options.isHorizontal, 'isHorizontal was not passed'); this.renderer = renderer; this._init(options) }; $.extend(DX.viz.charts.Axis.prototype, { dispose: function() { var that = this; that._axisElementsGroup && that._axisElementsGroup.dispose(); $.each(that.labels || [], function(_, label) { label.removeData() }); that.labels = null; that.title = null; that.stripLabels = null; that.stripRects = null; that.constantLineLabels = null; that.constantLines = null; that._axisStripGroup = null; that._axisConstantLineGroup = null; that._axisLableGroup = null; that._axisLineGroup = null; that._axisElementsGroup = null; that._axisGridGroup = null; that._axisGroup = null; that.axesContainerGroup = null; that.stripsGroup = null; that.constantLinesGroup = null; that._axisTitleGroup = null; that.renderer = null; that.translator = null; that.orthogonalTranslator = null; that.options = null; that.textOptions = null; that._tickValues = null; that._fullTickValues = null; that._fullTickPositions = null }, _init: function(options) { var that = this, categories = options.categories, labelOptions = options.label; options.hoverMode = options.hoverMode ? options.hoverMode.toLowerCase() : 'none'; that.hasLabelFormat = labelOptions.format !== '' && isDefinedUtils(labelOptions.format); that.options = options; that.staggered = labelOptions.staggered; labelOptions.minSpacing = isDefinedUtils(labelOptions.minSpacing) ? labelOptions.minSpacing : DEFAULT_AXIS_LABEL_SPACING; processCustomOptions(options); if (categories) { that.labelsNumber = categories.length; that.ticksNumber = that.labelsNumber } options.range = { min: options.min, max: options.max, categories: options.categories && options.categories.slice(0) }; that.pane = options.pane; that.textOptions = { align: labelOptions.alignment, font: labelOptions.font, opacity: labelOptions.opacity, style: labelOptions.style }; if (options.type === 'logarithmic') { if (options.logarithmBaseError) { options.incidentOccured('E2104'); delete options.logarithmBaseError } that.calcInterval = function(value, prevValue) { return utils.getLog(value / prevValue, options.logarithmBase) } } }, updateSize: function(clearAxis) { var that = this, options = that.options, direction = options.isHorizontal ? "horizontal" : "vertical"; if (that.title && that._axisTitleGroup) { options.incidentOccured('W2105', [direction]); that._axisTitleGroup.remove(); that._axisTitleGroup = null } if (clearAxis && that._axisElementsGroup && that.labels) { options.incidentOccured('W2106', [direction]); that._axisElementsGroup.remove(); that._axisElementsGroup = null } that._setBoundingRect() }, _updateTranslatorInterval: function() { var that = this, i, tickValues, businessRange = that.translator.getBusinessRange(); if (businessRange && businessRange.addRange && !that.options.categories) { tickValues = that.getTickValues(); for (i = 0; i < tickValues.length - 1; i++) businessRange.addRange({interval: mathAbs(tickValues[i] - tickValues[i + 1])}) } }, setTranslator: function(translator, orthogonalTranslator) { var that = this; var debug = DX.utils.debug; debug.assertParam(translator, 'translator was not passed'); that.translator = translator; orthogonalTranslator && (that.orthogonalTranslator = orthogonalTranslator); that.resetTicks(); that._updateTranslatorInterval() }, resetTicks: function() { var that = this; that._tickValues = that._tickPositions = that._fullTickValues = that._fullTickPositions = null }, setRange: function(range) { var debug = DX.utils.debug; debug.assertParam(range, 'range was not passed'); var options = this.options; options.min = range.minVisible; options.max = range.maxVisible; options.categories = range.categories; options.stubData = range.stubData; this.resetTicks() }, _drawAxis: function() { var that = this, translator = that.translator, options = that.options, hasCategories = !!options.categories, axisPosition = that.axisPosition, p11, p12, p21, p22; if (!options.visible) return; p11 = translator.translateSpecialCase(CANVAS_POSITION_START); p21 = translator.translateSpecialCase(CANVAS_POSITION_END); if (options.isHorizontal) p12 = p22 = axisPosition; else { p12 = p11; p22 = p21; p11 = p21 = axisPosition } that.renderer.createLine(p11, p12, p21, p22, { strokeWidth: options.width, stroke: options.color, strokeOpacity: options.opacity }).append(that._axisLineGroup) }, _getOptimalRotationAngle: function(tick1, tick2, labelOptions) { var that = this, translator = that.options.isHorizontal ? that.translator : that.orthogonalTranslator, renderer = that.renderer, outOfScreen = core.outOfScreen, textOptions = that.textOptions, svgElement1 = renderer.createText(formatLabel(tick1, labelOptions), outOfScreen.x + translator.translate(tick1), outOfScreen.y, textOptions).append(), svgElement2 = renderer.createText(formatLabel(tick2, labelOptions), outOfScreen.x + translator.translate(tick2), outOfScreen.y, textOptions).append(), bBox1 = svgElement1.getBBox(), bBox2 = svgElement2.getBBox(), angle = Math.asin((bBox1.height + labelOptions.minSpacing) / (bBox2.x - bBox1.x)) * 180 / Math.PI; svgElement1.remove(); svgElement2.remove(); return isNaN(angle) ? 90 : Math.ceil(angle) }, _applyOptimalOverlappingBehavior: function(ticks, ticksOptions) { var that = this, overlappingBehavior = that.overlappingBehavior, isOverlapped = false, rotationAngle = null, mode = null, options = $.extend({}, ticksOptions), state = 'overlap'; while (state !== 'end') { isOverlapped = rotationAngle && rotationAngle !== 90 ? false : that.options.tickProvider.isOverlappedTicks(ticks, options); state = nextState(isOverlapped ? state : null); that.testAutoOverlappingState = state; switch (state) { case'stagger': options.screenDelta *= AXIS_STAGGER_OVERLAPPING_KOEF; mode = state; break; case'rotate': rotationAngle = that._getOptimalRotationAngle(ticks[0], ticks[1], that.options.label); that.testAutoOverlappingRotationAngle = rotationAngle; options.screenDelta = ticksOptions.screenDelta; options.textOptions.rotate = rotationAngle; mode = state; break } } that.testAutoOverlappingOptions = options; overlappingBehavior.isOverlapped = isOverlapped; overlappingBehavior.mode = mode; overlappingBehavior.rotationAngle = rotationAngle }, _getTicksOptions: function() { var that = this, options = that.options, translator = that.translator, screenDelta = mathAbs(translator.translateSpecialCase(CANVAS_POSITION_START) - translator.translateSpecialCase(CANVAS_POSITION_END)), min = options.min, max = options.max, digitPosition = utils.getSignificantDigitPosition(mathAbs(max - min) / screenDelta), correctingValue, getText = function() { return '' }; if (utils.isNumber(min) && options.type !== 'logarithmic') { min = utils.roundValue(options.min, digitPosition); if (min < options.min) { correctingValue = Math.pow(10, -digitPosition); min = utils.applyPrecisionByMinDelta(min, correctingValue, min + correctingValue) } if (min > max) min = options.min } if (!options.stubData) getText = function(value) { return formatLabel(value, options.label, { min: min, max: max }) }; return { min: min, max: max, base: options.type === 'logarithmic' ? options.logarithmBase : undefined, axisType: options.type, dataType: options.dataType, customTicks: $.isArray(options.categories) ? options.categories : that._tickValues, useTicksAutoArrangement: false, textOptions: that.textOptions, getText: getText, renderer: that.renderer, textSpacing: options.label.minSpacing, translator: translator, tickInterval: options.stubData ? null : options.tickInterval, screenDelta: screenDelta, gridSpacingFactor: options.axisDivisionFactor, isHorizontal: options.isHorizontal, setTicksAtUnitBeginning: options.setTicksAtUnitBeginning, incidentOccured: options.incidentOccured } }, getTickValues: function() { var that = this, correctedScreenDelta, options = that.options, tickProvider = options.tickProvider, labelOptions = options.label, categories = options.categories, ticksOptions = that._getTicksOptions(); that._fullTickValues = that._tickValues = tickProvider.getTicks(ticksOptions); if ((isDateUtils(options.min) || isDateUtils(categories && categories[0])) && !that.hasLabelFormat && that._tickValues.length) labelOptions.format = DX.formatHelper.getDateFormatByTicks(that._tickValues); that.overlappingBehavior = labelOptions.overlappingBehavior ? $.extend({}, labelOptions.overlappingBehavior) : null; if (that.overlappingBehavior) { if (!options.isHorizontal && that.overlappingBehavior.mode !== 'ignore') that.overlappingBehavior.mode = 'enlargeTickInterval'; ticksOptions.useTicksAutoArrangement = that.overlappingBehavior.mode !== 'ignore'; if (ticksOptions.useTicksAutoArrangement) that._fullTickValues = that._tickValues = tickProvider.getCorrectedTicks(that._fullTickValues, ticksOptions); if (that.overlappingBehavior.mode === 'auto') { that.textOptions.rotate = 0; that._applyOptimalOverlappingBehavior(that._fullTickValues, ticksOptions); ticksOptions.useTicksAutoArrangement = that.overlappingBehavior.isOverlapped } if (that.overlappingBehavior.mode === 'rotate') { that.textOptions.rotate = that.overlappingBehavior.rotationAngle; if (!labelOptions.userAlignment) that.textOptions.align = LEFT } else if (!labelOptions.userAlignment) that.textOptions.align = labelOptions.alignment } if (ticksOptions.useTicksAutoArrangement) { correctedScreenDelta = that._tickValues.length ? that.translator.translate(that._tickValues[that._tickValues.length - 1]) - that.translator.translate(that._tickValues[0]) : null; if (correctedScreenDelta) { ticksOptions.screenDelta = mathAbs(correctedScreenDelta); ticksOptions.ticksCount = that._tickValues.length - 1 } else ticksOptions.ticksCount = that._tickValues.length; if (that.overlappingBehavior && that.overlappingBehavior.mode === 'stagger') ticksOptions.screenDelta *= AXIS_STAGGER_OVERLAPPING_KOEF; ticksOptions.customTicks = that._tickValues; that._tickValues = tickProvider.getTicks(ticksOptions) } that._testTKScreenDelta = ticksOptions.screenDelta; that._autoArrangementStep = that._tickValues.autoArrangementStep; that._useTicksAutoArrangement = ticksOptions.useTicksAutoArrangement; if (that.options.stubData) { that._testSkippedFormattingAndOverlapping = true; return that._tickValues } if (!$.isArray(categories)) that._fullTickValues = that._tickValues; return that._tickValues }, setTickValues: function(tickValues) { this.resetTicks(); this._fullTickValues = this._tickValues = tickValues }, _prepareLabelsToDraw: function() { var that = this, ticksValues = that.getTickValues(), ticks = [], i; if (ticksValues.hideLabels || that.options.stubData) ticks.hideLabels = true; for (i = 0; i < ticksValues.length; i++) ticks.push({ text: ticksValues[i], pos: that.translator.translate(ticksValues[i]) }); return ticks }, _correctTicksPosition: function(ticks) { var that = this, options = that.options, tickDelta = that.translator.getInterval() / 2, i; if (options.categories && (options.discreteAxisDivisionMode !== 'crossLabels' || !options.discreteAxisDivisionMode)) { if (options.isHorizontal) { if (!options.valueMarginsEnabled) ticks = ticks.slice(0, ticks.length - 1) } else { tickDelta = -tickDelta; if (!options.valueMarginsEnabled) ticks = ticks.slice(1, ticks.length) } for (i = 0; i < ticks.length; i++) ticks[i].pos = ticks[i].pos + tickDelta } return ticks }, _prepareFullTicksToDraw: function() { var that = this, ticksValues = that._fullTickValues, ticks = [], i; if (!that._fullTickPositions) { if (!ticksValues) { that.getTickValues(); ticksValues = that._fullTickValues || [] } for (i = 0; i < ticksValues.length; i++) ticks.push({pos: that.translator.translate(ticksValues[i])}); that._fullTickPositions = that._correctTicksPosition(ticks) } return that._fullTickPositions }, _drawTicks: function() { var that = this, options = that.options, ticksOptions = options.tick, i, axisPosition = that.axisPosition, tickStart = axisPosition - 4, tickEnd = axisPosition + 4, tick, ticksToDraw; if (!ticksOptions.visible) return; var drawLine = function(p11, p12, p21, p22) { that.renderer.createLine(p11, p12, p21, p22, { strokeWidth: 1, stroke: ticksOptions.color, strokeOpacity: ticksOptions.opacity }).append(that._axisLineGroup) }; ticksToDraw = that._prepareFullTicksToDraw(); if (options.isHorizontal) for (i = 0; i < ticksToDraw.length; i++) { tick = ticksToDraw[i]; drawLine(tick.pos, tickStart, tick.pos, tickEnd) } else for (i = 0; i < ticksToDraw.length; i++) { tick = ticksToDraw[i]; drawLine(tickStart, tick.pos, tickEnd, tick.pos) } }, setPercentLabelFormat: function() { var labelOptions = this.options.label; if (!this.hasLabelFormat) labelOptions.format = 'percent' }, resetAutoLabelFormat: function() { var labelOptions = this.options.label; if (!this.hasLabelFormat) delete labelOptions.format }, _drawLabels: function() { var that = this, i, options = that.options, renderer = that.renderer, axisPosition = that.axisPosition, labelOptions = options.label, labelOffset = labelOptions.indentFromAxis, labelsToDraw, labelPoint, label, labels = [], createText = options.isHorizontal ? renderer.createText : function(text, y, x, textOptions) { return this.createText(text, x, y, textOptions) }, emptyStrRegExp = /^\s+$/, currentLabelConst = options.position === TOP || options.position === LEFT ? axisPosition - labelOffset : axisPosition + labelOffset, text; if (!labelOptions.visible || !that._axisElementsGroup) return; labelsToDraw = that._prepareLabelsToDraw(); if (labelsToDraw.length === 0 || labelsToDraw.hideLabels) return true; for (i = 0; i < labelsToDraw.length; i++) { labelPoint = labelsToDraw[i]; text = formatLabel(labelPoint.text, labelOptions, { min: options.min, max: options.max }); if (isDefinedUtils(text) && text !== '' && !emptyStrRegExp.test(text)) { label = createText.call(renderer, text, labelPoint.pos, currentLabelConst, that.textOptions); labels.push(label); label.append(that._axisElementsGroup); label.data({argument: labelPoint.text}) } } that.labels = labels }, getMultipleAxesSpacing: function() { return this.options.multipleAxesSpacing || 0 }, _drawTitle: function() { var that = this, i, options = that.options, renderer = that.renderer, axisPosition = that.axisPosition, titleOptions = options.title, title, attr = { font: titleOptions.font, opacity: titleOptions.opacity, align: CENTER, 'class': 'dx-chart-axis-title' }, centerPosition = that.translator.translateSpecialCase(CANVAS_POSITION_PREFIX + CENTER), x, y; if (!titleOptions.text || !that._axisTitleGroup) return; if (options.isHorizontal) { x = centerPosition; y = axisPosition } else { if (options.position === LEFT) attr.rotate = 270; else attr.rotate = 90; x = axisPosition; y = centerPosition } that.title = renderer.createText(titleOptions.text, x, y, attr).append(that._axisTitleGroup) }, _drawGrid: function(borderOptions) { var that = this, positionsToDraw, options = that.options, gridOptions = options.grid, i; if (!gridOptions.visible) return; borderOptions = borderOptions || {visible: false}; var drawLine = function() { var translator = that.translator, orthogonalTranslator = that.orthogonalTranslator, isHorizontal = options.isHorizontal, canvasStart = isHorizontal ? LEFT : TOP, canvasEnd = isHorizontal ? RIGHT : BOTTOM, positionFrom = orthogonalTranslator.translateSpecialCase(CANVAS_POSITION_START), positionTo = orthogonalTranslator.translateSpecialCase(CANVAS_POSITION_END), firstBorderLinePosition = borderOptions.visible && borderOptions[canvasStart] ? translator.translateSpecialCase(CANVAS_POSITION_PREFIX + canvasStart) : undefined, lastBorderLinePosition = borderOptions.visible && borderOptions[canvasEnd] ? translator.translateSpecialCase(CANVAS_POSITION_PREFIX + canvasEnd) : undefined; return function(tick) { if (mathAbs(tick.pos - firstBorderLinePosition) < MAX_GRID_BORDER_ADHENSION || mathAbs(tick.pos - lastBorderLinePosition) < MAX_GRID_BORDER_ADHENSION) return; var p11 = tick.pos, p12 = positionFrom, p21 = tick.pos, p22 = positionTo; if (!isHorizontal) { p11 = positionFrom; p12 = p22 = tick.pos; p21 = positionTo } that.renderer.createLine(p11, p12, p21, p22, { strokeWidth: gridOptions.width, stroke: gridOptions.color, strokeOpacity: gridOptions.opacity }).append(that._axisGridGroup) } }(); positionsToDraw = that._prepareFullTicksToDraw(); for (i = 0; i < positionsToDraw.length; i++) drawLine(positionsToDraw[i]) }, _drawConstantLine: function() { var that = this, group = that._axisConstantLineGroup, renderer = that.renderer, options = that.options, data = options.constantLines, translator = that.translator, orthogonalTranslator = that.orthogonalTranslator, isHorizontal = options.isHorizontal, i, lines = [], labels = [], positionFrom = orthogonalTranslator.translateSpecialCase(CANVAS_POSITION_START), positionTo = orthogonalTranslator.translateSpecialCase(CANVAS_POSITION_END), canvasStart = translator.translateSpecialCase(CANVAS_POSITION_START), canvasEnd = translator.translateSpecialCase(CANVAS_POSITION_END), range = translator.getBusinessRange(); var getPos = function(lineValue) { var parsedValue = that.validateUnit(lineValue, "E2105", 'constantLine'), value = translator.translate(parsedValue), isContinous = !!(range.minVisible || range.maxVisible); if (!isContinous && $.inArray(lineValue, range.categories || []) === -1 || !isDefinedUtils(value) || value < Math.min(canvasStart, canvasEnd) || value > Math.max(canvasStart, canvasEnd)) return {}; return { value: value, parsedValue: parsedValue } }; var drawLinesAndLabels = function(lineOptions) { if (lineOptions.value === undefined) return; var pos = getPos(lineOptions.value), labelOptions = lineOptions.label || {}, value = pos.value, line, attr = { stroke: lineOptions.color, strokeWidth: lineOptions.width, dashStyle: lineOptions.dashStyle }; if (!isDefinedUtils(value)) { lines.push(null); if (labelOptions.visible) labels.push(null); return } line = isHorizontal ? renderer.createLine(value, positionTo, value, positionFrom, attr) : renderer.createLine(positionFrom, value, positionTo, value, attr); lines.push(line.append(group)); if (labelOptions.visible) labels.push(that._drawConstantLineLabels(pos.parsedValue, labelOptions, value, group)); else labels.push(null) }; for (i = 0; i < data.length; i++) drawLinesAndLabels(data[i]); that.constantLines = lines; that.constantLineLabels = labels }, _checkAlignmentConstantLineLabels: function(labelOptions) { var options = this.options; labelOptions.verticalAlignment = (labelOptions.verticalAlignment || '').toLowerCase(); labelOptions.horizontalAlignment = (labelOptions.horizontalAlignment || '').toLowerCase(); if (options.isHorizontal && labelOptions.position === 'outside') { labelOptions.verticalAlignment = labelOptions.verticalAlignment === BOTTOM ? BOTTOM : TOP; labelOptions.horizontalAlignment = CENTER } if (options.isHorizontal && labelOptions.position === 'inside') { labelOptions.verticalAlignment = labelOptions.verticalAlignment === CENTER ? CENTER : labelOptions.verticalAlignment === BOTTOM ? BOTTOM : TOP; labelOptions.horizontalAlignment = labelOptions.horizontalAlignment === LEFT ? LEFT : RIGHT } if (!options.isHorizontal && labelOptions.position === 'outside') { labelOptions.verticalAlignment = CENTER; labelOptions.horizontalAlignment = labelOptions.horizontalAlignment === LEFT ? LEFT : RIGHT } if (!options.isHorizontal && labelOptions.position === 'inside') { labelOptions.verticalAlignment = labelOptions.verticalAlignment === BOTTOM ? BOTTOM : TOP; labelOptions.horizontalAlignment = labelOptions.horizontalAlignment === RIGHT ? RIGHT : labelOptions.horizontalAlignment === CENTER ? CENTER : LEFT } }, _drawConstantLineLabels: function(parsedValue, lineLabelOptions, value, group) { var that = this, text = lineLabelOptions.text, orthogonalTranslator = that.orthogonalTranslator, options = that.options, labelOptions = options.label, attr = { align: CENTER, font: $.extend({}, labelOptions.font, lineLabelOptions.font) }, x, y; that._checkAlignmentConstantLineLabels(lineLabelOptions); text = isDefinedUtils(text) ? text : formatLabel(parsedValue, labelOptions); if (options.isHorizontal) { x = value; switch (lineLabelOptions.horizontalAlignment) { case LEFT: attr.align = RIGHT; break; case RIGHT: attr.align = LEFT; break } y = orthogonalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + lineLabelOptions.verticalAlignment) } else { y = value; x = orthogonalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + lineLabelOptions.horizontalAlignment); switch (lineLabelOptions.horizontalAlignment) { case LEFT: attr.align = lineLabelOptions.position === 'inside' ? LEFT : RIGHT; break; case CENTER: attr.align = CENTER; break; case RIGHT: attr.align = lineLabelOptions.position === 'inside' ? RIGHT : LEFT; break } } return that.renderer.createText(text, x, y, attr).append(group) }, _adjustConstantLineLabels: function() { var that = this, options = that.options, isHorizontal = options.isHorizontal, lines = that.constantLines, labels = that.constantLineLabels, label, line, lineBox, linesOptions, labelOptions, box, x, y, i, padding = isHorizontal ? { top: 0, bottom: 0 } : { left: 0, right: 0 }; if (labels === undefined && lines === undefined) return; for (i = 0; i < labels.length; i++) { x = y = 0; linesOptions = options.constantLines[i]; labelOptions = linesOptions.label; label = labels[i]; if (label !== null) { line = lines[i]; box = label.getBBox(); lineBox = line.getBBox(); if (isHorizontal) if (labelOptions.position === 'inside') { switch (labelOptions.horizontalAlignment) { case LEFT: x -= linesOptions.paddingLeftRight; break; default: x += linesOptions.paddingLeftRight; break } switch (labelOptions.verticalAlignment) { case CENTER: y += lineBox.y + lineBox.height / 2 - box.y - box.height / 2; break; case BOTTOM: y -= linesOptions.paddingTopBottom; break; default: y += linesOptions.paddingTopBottom + box.height; break } } else switch (labelOptions.verticalAlignment) { case BOTTOM: y += box.height + linesOptions.paddingTopBottom - (box.y + box.height - that.orthogonalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + labelOptions.verticalAlignment)); if (padding[BOTTOM] < box.height + linesOptions.paddingTopBottom) padding[BOTTOM] = box.height + linesOptions.paddingTopBottom; break; default: y -= linesOptions.paddingTopBottom; if (padding[TOP] < linesOptions.paddingTopBottom + box.height) padding[TOP] = linesOptions.paddingTopBottom + box.height; break } else if (labelOptions.position === 'inside') { switch (labelOptions.horizontalAlignment) { case CENTER: x += lineBox.x + lineBox.width / 2 - box.x - box.width / 2; break; case RIGHT: x -= linesOptions.paddingLeftRight; break; default: x += linesOptions.paddingLeftRight; break } switch (labelOptions.verticalAlignment) { case BOTTOM: y += lineBox.y - box.y + linesOptions.paddingTopBottom; break; default: y -= linesOptions.paddingTopBottom; break } } else { y += lineBox.y + lineBox.height / 2 - box.y - box.height / 2; switch (labelOptions.horizontalAlignment) { case RIGHT: x += linesOptions.paddingLeftRight; if (padding[RIGHT] < linesOptions.paddingLeftRight + box.width) padding[RIGHT] = linesOptions.paddingLeftRight + box.width; break; default: x -= linesOptions.paddingLeftRight; if (padding[LEFT] < linesOptions.paddingLeftRight + box.width) padding[LEFT] = linesOptions.paddingLeftRight + box.width; break } } label.move(x, y) } } that.padding = padding }, _drawStrip: function() { var that = this, renderer = that.renderer, options = that.options, stripData = options.strips, translator = that.translator, orthogonalTranslator = that.orthogonalTranslator, range = translator.getBusinessRange(), i, stripLabels = [], stripRects = [], rect, isHorizontal = options.isHorizontal, stripOptions, positionFrom, positionTo, stripPos, stripLabelOptions, attr; if (options.stubData) return; var getPos = function(startV, endV) { var isContinous = !!(range.minVisible || range.maxVisible), cateories = range.categories || [], start = translator.translate(that.validateUnit(startV, "E2105", "strip")), end = translator.translate(that.validateUnit(endV, "E2105", "strip")), canvasStart = translator.translateSpecialCase(CANVAS_POSITION_START), canvasEnd = translator.translateSpecialCase(CANVAS_POSITION_END), min = range.minVisible; if (!isContinous && ($.inArray(startV, cateories) === -1 || $.inArray(endV, cateories) === -1)) return { stripFrom: 0, stripTo: 0 }; if (!isDefinedUtils(start) && isContinous) start = startV < min ? canvasStart : canvasEnd; if (!isDefinedUtils(end) && isContinous) end = endV < min ? canvasStart : canvasEnd; return start < end ? { stripFrom: start, stripTo: end } : { stripFrom: end, stripTo: start } }; positionFrom = orthogonalTranslator.translateSpecialCase(CANVAS_POSITION_START); positionTo = orthogonalTranslator.translateSpecialCase(CANVAS_POSITION_END); for (i = 0; i < stripData.length; i++) { stripOptions = stripData[i]; stripLabelOptions = stripOptions.label || {}; attr = {fill: stripOptions.color}; if (stripOptions.startValue !== undefined && stripOptions.endValue !== undefined && stripOptions.color !== undefined) { stripPos = getPos(stripOptions.startValue, stripOptions.endValue); if (stripPos.stripTo - stripPos.stripFrom === 0 || !stripPos.stripTo && stripPos.stripTo !== 0 || !stripPos.stripFrom && stripPos.stripFrom !== 0) { stripRects.push(null); if (stripLabelOptions.text) stripLabels.push(null); continue } rect = isHorizontal ? renderer.createRect(stripPos.stripFrom, Math.min(positionFrom, positionTo), stripPos.stripTo - stripPos.stripFrom, mathAbs(positionFrom - positionTo), 0, attr) : renderer.createRect(Math.min(positionFrom, positionTo), stripPos.stripFrom, mathAbs(positionFrom - positionTo), stripPos.stripTo - stripPos.stripFrom, 0, attr); stripRects.push(rect.append(that._axisStripGroup)); if (stripLabelOptions.text) stripLabels.push(that._drawStripLabel(stripLabelOptions, stripPos.stripFrom, stripPos.stripTo)); else stripLabels.push(null) } } that.stripLabels = stripLabels; that.stripRects = stripRects }, _drawStripLabel: function(stripLabelOptions, stripFrom, stripTo) { var that = this, orthogonalTranslator = that.orthogonalTranslator, options = that.options, isHorizontal = options.isHorizontal, attr = { align: isHorizontal ? CENTER : LEFT, font: $.extend({}, options.label.font, stripLabelOptions.font) }, x, y; if (isHorizontal) { if (stripLabelOptions.horizontalAlignment === CENTER) { x = stripFrom + (stripTo - stripFrom) / 2; attr.align = CENTER } else if (stripLabelOptions.horizontalAlignment === LEFT) { x = stripFrom; attr.align = LEFT } else if (stripLabelOptions.horizontalAlignment === RIGHT) { x = stripTo; attr.align = RIGHT } y = orthogonalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + stripLabelOptions.verticalAlignment) } else { x = orthogonalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + stripLabelOptions.horizontalAlignment); attr.align = stripLabelOptions.horizontalAlignment; if (stripLabelOptions.verticalAlignment === TOP) y = stripFrom; else if (stripLabelOptions.verticalAlignment === CENTER) y = stripTo + (stripFrom - stripTo) / 2; else if (stripLabelOptions.verticalAlignment === BOTTOM) y = stripTo } return that.renderer.createText(stripLabelOptions.text, x, y, attr).append(that._axisLableGroup) }, _initAxisPositions: function() { var that = this, position = that.options.position, delta = 0; if (that.delta) delta = that.delta[position] || 0; that.axisPosition = that.orthogonalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + position) + delta }, _adjustLabels: function() { var that = this, options = that.options, isHorizontal = options.isHorizontal, position = options.position, labels = that.labels, label, labelHeight, isNeedLabelAdjustment, staggeringSpacing, i, xt, shift = that.padding && that.padding[position] || 0, boxAxis = that._axisElementsGroup && that._axisElementsGroup.getBBox() || {}, box; if (!options.label.visible || !labels || !labels.length) return; for (i = 0; i < labels.length; i++) { label = labels[i]; box = label.getBBox(); if (isHorizontal && position === BOTTOM) label.applySettings({y: 2 * label.settings.y - box.y + shift}); else if (!isHorizontal) { if (position === LEFT) if (that.textOptions.align === RIGHT) xt = box.x + box.width - shift; else if (that.textOptions.align === CENTER) xt = box.x + box.width / 2 - shift - (boxAxis.width / 2 || 0); else xt = box.x - shift - (boxAxis.width || 0); else if (that.textOptions.align === CENTER) xt = box.x + box.width / 2 + (boxAxis.width / 2 || 0) + shift; else if (that.textOptions.align === RIGHT) xt = box.x + box.width + (boxAxis.width || 0) + shift; else xt = box.x + shift; label.applySettings({ x: xt, y: label.settings.y + ~~(label.settings.y - box.y - box.height / 2) }) } else if (isHorizontal && position === TOP) label.applySettings({y: 2 * label.settings.y - box.y - box.height - shift}) } isNeedLabelAdjustment = isHorizontal && that.overlappingBehavior && that.overlappingBehavior.mode === 'stagger'; that._testIsNeedLabelAdjustment = isNeedLabelAdjustment; if (isNeedLabelAdjustment) { labelHeight = 0; for (i = 0; i < labels.length; i = i + 2) { label = labels[i]; box = label.getBBox(); if (box.height > labelHeight) labelHeight = box.height } staggeringSpacing = that.overlappingBehavior.staggeringSpacing; that._testStaggeringSpacing = staggeringSpacing; labelHeight = Math.round(labelHeight) + staggeringSpacing; for (i = 1; i < labels.length; i = i + 2) { label = labels[i]; if (position === BOTTOM) label.move(0, labelHeight); else if (position === TOP) label.move(0, -labelHeight) } for (i = 0; i < labels.length; i++) labels[i].rotate(0) } }, _adjustStripLabels: function() { var that = this, labelOptions, labels = that.stripLabels, rects = that.stripRects, label, i, box, rectBox, stripOptions, x, y; if (labels === undefined && rects === undefined) return; for (i = 0; i < labels.length; i++) { x = y = 0; stripOptions = that.options.strips[i]; labelOptions = stripOptions.label; label = labels[i]; if (label !== null) { box = label.getBBox(); rectBox = rects[i].getBBox(); if (labelOptions.horizontalAlignment === LEFT) x += stripOptions.paddingLeftRight; else if (labelOptions.horizontalAlignment === RIGHT) x -= stripOptions.paddingLeftRight; if (labelOptions.verticalAlignment === TOP) y += rectBox.y - box.y + stripOptions.paddingTopBottom; else if (labelOptions.verticalAlignment === CENTER) y += rectBox.y + rectBox.height / 2 - box.y - box.height / 2; else if (labelOptions.verticalAlignment === BOTTOM) y -= stripOptions.paddingTopBottom; label.move(x, y) } } }, _adjustTitle: function() { var that = this, options = that.options, position = options.position, title = that.title, margin = options.title.margin, boxGroup, boxTitle; if (!title || !that._axisElementsGroup) return; boxTitle = title.getBBox(); boxGroup = that._axisElementsGroup.getBBox(); if (options.isHorizontal) if (position === BOTTOM) title.applySettings({ y: boxGroup.isEmpty ? undefined : boxGroup.y + boxGroup.height, translateY: margin + boxTitle.height }); else title.applySettings({ y: boxGroup.isEmpty ? undefined : boxGroup.y, translateY: -margin }); else if (position === LEFT) title.applySettings({ x: boxGroup.isEmpty ? undefined : boxGroup.x, translateX: -margin }); else title.applySettings({ x: boxGroup.isEmpty ? undefined : boxGroup.x + boxGroup.width, translateX: margin }) }, draw: function(externalOptions, adjustAxis) { var that = this, options = that.options, isHorizontal = options.isHorizontal, cssClass = isHorizontal ? 'dxc-h-axis' : 'dxc-v-axis', stripClass = isHorizontal ? 'dxc-h-strips' : 'dxc-v-strips', constantLineClass = isHorizontal ? 'dxc-h-constant-lines' : 'dxc-v-constant-lines'; externalOptions = externalOptions || {}; var debug = DX.utils.debug; debug.assertParam(this.translator, 'translator was not set before Draw call'); if (that._axisGroup) { that._axisGroup.detach(); that._axisStripGroup.detach(); that._axisLableGroup.detach(); that._axisConstantLineGroup.detach(); that._axisTitleGroup ? that._axisTitleGroup.clear() : !adjustAxis && (that._axisTitleGroup = that.renderer.createGroup({'class': 'dxc-title'}).append(that._axisGroup)); that._axisGridGroup.clear(); that._axisElementsGroup ? that._axisElementsGroup.clear() : !adjustAxis && (that._axisElementsGroup = that.renderer.createGroup({'class': 'dxc-elements'}).append(that._axisGroup)); that._axisLineGroup.clear(); that._axisStripGroup.clear(); that._axisConstantLineGroup.clear(); that._axisLableGroup.clear() } else { that._axisGroup = that.renderer.createGroup({ 'class': cssClass, clipId: that.clipRectID }); that._axisStripGroup = that.renderer.createGroup({'class': stripClass}); that._axisGridGroup = that.renderer.createGroup({'class': 'dxc-grid'}).append(that._axisGroup); that._axisElementsGroup = that.renderer.createGroup({'class': 'dxc-elements'}).append(that._axisGroup); that._axisLineGroup = that.renderer.createGroup({'class': 'dxc-line'}).append(that._axisGroup); that._axisTitleGroup = that.renderer.createGroup({'class': 'dxc-title'}).append(that._axisGroup); that._axisConstantLineGroup = that.renderer.createGroup({'class': constantLineClass}); that._axisLableGroup = that.renderer.createGroup({'class': 'dxc-axis-labels'}) } that._initAxisPositions(); if (!that._virtual) { that._drawAxis(); that._drawTicks(); that._drawLabels(); that._drawTitle() } if (options.strips) that._drawStrip(); if (options.constantLines) that._drawConstantLine(); that._drawGrid(externalOptions.borderOptions); that._axisStripGroup.append(that.stripsGroup); that._axisConstantLineGroup.append(that.constantLinesGroup); that._axisGroup.append(that.axesContainerGroup); that._axisLableGroup.append(that.labelAxesGroup); that._adjustConstantLineLabels(); that._adjustLabels(); that._adjustStripLabels(); that._adjustTitle(); that._setBoundingRect() }, _setBoundingRect: function() { var that = this, options = that.options, axisBox = that._axisElementsGroup ? that._axisElementsGroup.getBBox() : { x: 0, y: 0, width: 0, height: 0, isEmpty: true }, lineBox = that._axisLineGroup.getBBox(), placeholderSize = options.placeholderSize, start, isHorizontal = options.isHorizontal, coord = isHorizontal && 'y' || 'x', side = isHorizontal && 'height' || 'width', axisTitleBox = that.title && that._axisTitleGroup ? that._axisTitleGroup.getBBox() : axisBox; if (axisBox.isEmpty && axisTitleBox.isEmpty && !placeholderSize) { that.boundingRect = axisBox; return } start = lineBox[coord] || that.axisPosition; if (options.position === (isHorizontal && BOTTOM || RIGHT)) { axisBox[side] = placeholderSize || axisTitleBox[coord] + axisTitleBox[side] - start; axisBox[coord] = start } else { axisBox[side] = placeholderSize || lineBox[side] + start - axisTitleBox[coord]; axisBox[coord] = axisTitleBox.isEmpty ? start : axisTitleBox[coord] } that.boundingRect = axisBox }, getBoundingRect: function() { return this._axisElementsGroup ? this.boundingRect : { x: 0, y: 0, width: 0, height: 0 } }, shift: function(x, y) { var settings = {}; if (x) settings.translateX = x; if (y) settings.translateY = y; this._axisGroup.applySettings(settings) }, applyClipRect: function(clipId) { this._axisStripGroup.applySettings({clipId: clipId}) }, validate: function(isArgumentAxis, incidentOccured) { var that = this, options = that.options, range = options.range, parseUtils = new core.ParseUtils, dataType = isArgumentAxis ? options.argumentType : options.valueType, parser = dataType ? parseUtils.getParser(dataType, 'axis') : function(unit) { return unit }; that.parser = parser; that.incidentOccured = incidentOccured; options.dataType = dataType; if (options.min) options.min = that.validateUnit(options.min, "E2106"); if (options.max) options.max = that.validateUnit(options.max, "E2106"); if (range.min) range.min = that.validateUnit(range.min); if (range.max) range.max = that.validateUnit(range.max) }, validateUnit: function(unit, idError, parameters) { var that = this, dataType = that.options.dataType; unit = that.parser(unit); if (unit === undefined && idError) that.incidentOccured(idError, [parameters]); return unit }, adjustZoomValues: function(min, max) { var that = this, range = that.options.range; min = that.validateUnit(min); max = that.validateUnit(max); if (range && isDefinedUtils(range.min)) { min = isDefinedUtils(min) ? range.min < min ? min : range.min : min; max = isDefinedUtils(max) ? range.min < max ? max : range.min : max } if (range && isDefinedUtils(range.max)) { max = isDefinedUtils(max) ? range.max > max ? max : range.max : max; min = isDefinedUtils(min) ? range.max > min ? min : range.max : min } that.minRangeArg = min; that.maxRangeArg = max; return { min: min, max: max } }, getRangeData: function() { var that = this, options = that.options, optionsRange = options.range, range = {}, min, max; var addValueMarginToRange = function(prefix) { if (options.valueMarginsEnabled) { if (isDefinedUtils(options[prefix])) { range[prefix] = options[prefix]; range[prefix + 'Priority'] = AXIS_VALUE_MARGIN_PRIORITY } } else { range[prefix] = 0; range[prefix + 'Priority'] = AXIS_VALUE_MARGIN_PRIORITY } }; if (isDefinedUtils(optionsRange.min) && isDefinedUtils(optionsRange.max)) { min = optionsRange.min < optionsRange.max ? optionsRange.min : optionsRange.max; max = optionsRange.max > optionsRange.min ? optionsRange.max : optionsRange.min } else { min = optionsRange.min; max = optionsRange.max } range.min = min; range.max = max; addValueMarginToRange('minValueMargin'); addValueMarginToRange('maxValueMargin'); range.stick = !options.valueMarginsEnabled; range.categories = optionsRange.categories; range.dataType = options.dataType; range.axisType = options.type; if (range.axisType === 'logarithmic') range.base = options.logarithmBase; if (options.isHorizontal) { range.minVisible = isDefinedUtils(that.minRangeArg) ? that.minRangeArg : optionsRange.min; range.maxVisible = isDefinedUtils(that.maxRangeArg) ? that.maxRangeArg : optionsRange.max; range.invert = options.inverted } else { range.minVisible = optionsRange.min; range.maxVisible = optionsRange.max; range.invert = options.inverted || options.type === 'discrete' && options.oppositeDirectionYAxis } return range } }) })(jQuery, DevExpress); /*! Module viz-charts, file baseChart.js */ (function($, DX, undefined) { var ui = DX.ui, charts = DX.viz.charts, utils = DX.utils, TRACKER_RENDERING_DELAY = 1200, resizeRedrawOptions = { animate: false, isResize: true }, ACTIONS_BY_PRIORITY = ['reinit', '_reinitDataSource', '_handleDataSourceChanged', 'force_render'], core = DX.viz.core, DEFAULT_ANIMATION_OPTIONS = { asyncSeriesRendering: true, asyncTrackersRendering: true, trackerRenderingDelay: TRACKER_RENDERING_DELAY }; charts.BaseChart = core.BaseWidget.inherit({ _setDefaultOptions: function() { this.callBase(); this.option({ done: $.noop, drawn: $.noop, seriesClick: null, pointClick: null, legendClick: null, argumentAxisClick: null, seriesHover: null, pointHover: null, seriesSelected: null, pointSelected: null, seriesSelectionChanged: null, pointSelectionChanged: null, seriesHoverChanged: null, pointHoverChanged: null }) }, _createThemeManager: function() { return charts.factory.createThemeManager(this.option()) }, _init: function() { this.__TRACKER_RENDERING_DELAY = TRACKER_RENDERING_DELAY; var that = this; that.callBase(); that.themeManager = this._createThemeManager(); that._initRenderer(); that.canvasClipRect = that.renderer.createClipRect(); that._createHtmlStructure(); that._needHandleRenderComplete = true; that.layoutManager = charts.factory.createChartLayoutManager(that.themeManager.getOptions("adaptiveLayout")); that._reinit(); that._element().css({webkitUserSelect: 'none'}).on('contextmenu', function(event) { that.eventType = 'contextmenu'; if (ui.events.isTouchEvent(event) || ui.events.isPointerEvent(event)) event.preventDefault() }).on('MSHoldVisual', function(event) { that.eventType = 'MSHoldVisual'; event.preventDefault() }) }, _reinit: function() { var that = this; that.layoutManager.update(that); that._createTracker(); that._reinitDataSource() }, _createHtmlStructure: function() { var that = this, renderer = that.renderer; that._panesBackgroundGroup = renderer.createGroup({'class': 'dxc-background'}); that._titleGroup = renderer.createGroup({'class': 'dxc-title'}); that._legendGroup = renderer.createGroup({ 'class': 'dxc-legend', clipId: that._getCanvasClipRectID() }); that._stripsGroup = renderer.createGroup({'class': 'dxc-strips-group'}); that._constantLinesGroup = renderer.createGroup({'class': 'dxc-constant-lines-group'}); that._axesGroup = renderer.createGroup({'class': 'dxc-axes-group'}); that._panesBorderGroup = renderer.createGroup({'class': 'dxc-border'}); that._labelAxesGroup = renderer.createGroup({'class': 'dxc-strips-labels-group'}); that._seriesGroup = renderer.createGroup({'class': 'dxc-series-group'}); that._labelsGroup = renderer.createGroup({'class': 'dxc-labels-group'}); that._tooltipGroup = renderer.createGroup({'class': 'dxc-tooltip'}); that._trackerGroup = renderer.createGroup({ 'class': 'dxc-trackers', opacity: 0.0001, stroke: "gray", fill: "gray" }); that._crosshairTrackerGroup = renderer.createGroup({ 'class': 'dxc-crosshair-trackers', stroke: 'none', fill: 'grey' }).append(that._trackerGroup); that._seriesTrackerGroup = renderer.createGroup({'class': 'dxc-series-trackers'}).append(that._trackerGroup); that._markerTrackerGroup = renderer.createGroup({ 'class': 'dxc-markers-trackers', stroke: 'none', fill: 'grey' }).append(that._trackerGroup); that._crossHairCursorGroup = renderer.createGroup({'class': 'dxc-crosshair-cursor'}) }, _cleanHtmlStructure: function() { var that = this; that._panesBackgroundGroup && that._panesBackgroundGroup.clear(); that._titleGroup && that._titleGroup.clear(); that._legendGroup && (that._legendGroup.detach(), that._legendGroup.clear()); that._stripsGroup && (that._stripsGroup.detach(), that._stripsGroup.clear()); that._constantLinesGroup && (that._constantLinesGroup.detach(), that._constantLinesGroup.clear()); that._axesGroup && (that._axesGroup.detach(), that._axesGroup.clear()); that._labelAxesGroup && (that._labelAxesGroup.detach(), that._labelAxesGroup.clear()); that._seriesGroup && (that._seriesGroup.detach(), that._seriesGroup.clear()); that._labelsGroup && (that._labelsGroup.detach(), that._labelsGroup.clear()); that._trackerGroup && (that._trackerGroup.detach(), that._seriesTrackerGroup.clear(), that._markerTrackerGroup.clear(), that._crosshairTrackerGroup.clear()); that._panesBorderGroup && that._panesBorderGroup.clear(); that._tooltipGroup && that._tooltipGroup.clear(); that._crossHairCursorGroup && (that._crossHairCursorGroup.clear(), that._crossHairCursorGroup.detach()) }, _disposeObjectsInArray: function(propName, fieldNames) { $.each(this[propName] || [], function(_, item) { if (fieldNames && item) $.each(fieldNames, function(_, field) { item[field] && item[field].dispose() }); else item && item.dispose() }); this[propName] = null }, _dispose: function() { var that = this, disposeObject = function(propName) { that[propName] && that[propName].dispose(), that[propName] = null }, detachGroup = function(groupName) { that[groupName] && that[groupName].detach() }, disposeObjectsInArray = this._disposeObjectsInArray; clearTimeout(that.delayedRedraw); that.callBase(); disposeObjectsInArray.call(that, "businessRanges", ["arg", "val"]); that.translators = null; disposeObjectsInArray.call(that, "series"); disposeObject("layoutManager"); disposeObject("themeManager"); disposeObject("renderer"); disposeObject("tracker"); disposeObject("tooltip"); disposeObject("chartTitle"); that.paneAxis = null; that._userOptions = null; that.dirtyCanvas = null; that.canvas = null; detachGroup("_legendGroup"); detachGroup("_stripsGroup"); detachGroup("_constantLinesGroup"); detachGroup("_axesGroup"); detachGroup("_labelAxesGroup"); detachGroup("_seriesGroup"); detachGroup("_labelsGroup"); detachGroup("_trackerGroup"); detachGroup("_crossHairCursorGroup"); disposeObject("canvasClipRect"); disposeObject("_panesBackgroundGroup"); disposeObject("_titleGroup"); disposeObject("_legendGroup"); disposeObject("_stripsGroup"); disposeObject("_constantLinesGroup"); disposeObject("_axesGroup"); disposeObject("_labelAxesGroup"); disposeObject("_panesBorderGroup"); disposeObject("_seriesGroup"); disposeObject("_labelsGroup"); disposeObject("_tooltipGroup"); disposeObject("_crossHairCursorGroup"); disposeObject("_seriesTrackerGroup"); disposeObject("_markerTrackerGroup"); disposeObject("_crosshairTrackerGroup"); disposeObject("_trackerGroup"); that._disposeLoadIndicator() }, _clean: function _clean(hideLoadIndicator) { this.renderer && this.renderer.stopAllAnimations(); hideLoadIndicator && this.hideLoadingIndicator(); this._cleanHtmlStructure(); this.callBase(); this._saveDirtyCanvas() }, _getAnimationOptions: function() { return $.extend({}, DEFAULT_ANIMATION_OPTIONS, this.themeManager.getOptions("animation")) }, _initRenderer: function _initRenderer() { if (this.renderer) return; this.renderer = core.CoreFactory.createRenderer({ animation: this._getAnimationOptions(), cssClass: 'dxc dxc-chart', pathModified: this.option('pathModified'), rtl: this.themeManager.getOptions('rtlEnabled') }) }, _initSeries: function() { this.series = this.series || this._populateSeries() }, _reinitDataSource: function() { this._refreshDataSource() }, _saveDirtyCanvas: function() { this.dirtyCanvas = $.extend({}, this.canvas) }, _resize: function() { this._render(resizeRedrawOptions) }, _calculateCanvas: function() { var canvas = this.themeManager.getOptions('size'), result = {}, container = this._element(); if (!utils.isDefined(canvas.width)) result.width = container.width() || 400; else result.width = canvas.width < 0 ? 0 : canvas.width; if (!utils.isDefined(canvas.height)) result.height = container.height() || 400; else result.height = canvas.height < 0 ? 0 : canvas.height; return $.extend({}, result, this.themeManager.getOptions('margin')) }, _createTracker: function() { var that = this, tooltipOptions = that.themeManager.getOptions('tooltip') || {}; if (that.tracker) that.tracker.dispose(); that.tracker = charts.factory.createTracker({ series: that.series, valueAxis: that._valueAxes, argumentAxis: that._argumentAxes, seriesSelectionMode: that.themeManager.getOptions('seriesSelectionMode'), pointSelectionMode: that.themeManager.getOptions('pointSelectionMode'), tooltipShown: that.option('tooltipShown'), tooltipHidden: that.option('tooltipHidden'), markerTrackerGroup: that._markerTrackerGroup, crossHairOptions: that._crossHairOptions, seriesTrackerGroup: that._seriesTrackerGroup, seriesGroup: that._seriesGroup, tooltipEnabled: tooltipOptions.enabled, renderer: that.renderer, events: { seriesClick: that.option('seriesClick'), pointClick: that.option('pointClick'), argumentAxisClick: that.option('argumentAxisClick'), seriesHover: that.option('seriesHover'), seriesSelected: that.option('seriesSelected'), pointHover: that.option('pointHover'), pointSelected: that.option('pointSelected'), legendClick: that.option('legendClick'), seriesSelectionChanged: that.option('seriesSelectionChanged'), pointSelectionChanged: that.option('pointSelectionChanged'), seriesHoverChanged: that.option('seriesHoverChanged'), pointHoverChanged: that.option('pointHoverChanged') } }) }, _updateTracker: function() { var that = this; if (!that.tracker) that._createTracker(); else that.tracker._reinit({ series: that.series, valueAxis: that._valueAxes, argumentAxis: that._argumentAxes, legendGroup: that.legend.getTrackerGroup(), legendCallback: $.proxy(that.legend.getActionCallback, that.legend) }) }, _render: function(drawOptions) { this._optionsInitializing = false; var that = this, renderer = that.renderer, updatedCanvas = that.canvas, container = this._element(), currentDirtyCanvas = that._calculateCanvas(), oldDirtyCanvas = that.dirtyCanvas; drawOptions = drawOptions || {recreateCanvas: true}; drawOptions.recreateCanvas = drawOptions.recreateCanvas || !renderer.isInitialized(); if (!drawOptions.force && oldDirtyCanvas && oldDirtyCanvas.width === currentDirtyCanvas.width && oldDirtyCanvas.height === currentDirtyCanvas.height && !that.hiddenContainer) { that.stopRedraw = true; return } clearTimeout(that.delayedRedraw); if (drawOptions.recreateCanvas) that.canvas = updatedCanvas = that._calculateCanvas(); if (updatedCanvas.width && updatedCanvas.height && container.is(':visible')) that.hiddenContainer = false; else { that._incidentOccured('W2001', [that.NAME]); that.hiddenContainer = true; that.stopRedraw = true; renderer.detachContainer(); return } if (drawOptions.recreateCanvas) { renderer.recreateCanvas(that.canvas.width, that.canvas.height); renderer.draw(that._element()[0]); that._reappendLoadIndicator(); that._updateLoadIndicator(undefined, updatedCanvas.width, updatedCanvas.height); that._updateCanvasClipRect() } that.renderer.stopAllAnimations(true); that.layoutManager.update(that); that._cleanGroups(drawOptions); that._saveDirtyCanvas() }, _cleanGroups: function(drawOptions) { var that = this; that._stripsGroup.detach(); that._constantLinesGroup.detach(); that._axesGroup.detach(); that._labelAxesGroup.detach(); that._labelsGroup.detach(); that._tooltipGroup.detach(); that._crossHairCursorGroup.detach(); if (!drawOptions || drawOptions.drawLegend) { that._legendGroup.detach(); that._legendGroup.clear() } if (!drawOptions || drawOptions.drawTitle) { that._titleGroup.detach(); that._titleGroup.clear() } that._stripsGroup.clear(); that._constantLinesGroup.clear(); that._axesGroup.clear(); that._labelAxesGroup.clear(); that._labelsGroup.clear(); that._tooltipGroup.clear(); that._crossHairCursorGroup.clear(); that._crosshairTrackerGroup.clear() }, _drawTitle: function() { var that = this, options = that.themeManager.getOptions("title"), width = that.canvas.width - that.canvas.left - that.canvas.right; options._incidentOccured = that._incidentOccured; if (that.chartTitle) that.chartTitle.update(options, width); else that.chartTitle = charts.factory.createTitle(that.renderer, options, width, that._titleGroup) }, _createTooltip: function() { var that = this, tooltipOptions = $.extend(true, { canvasWidth: that.canvas.width, canvasHeight: that.canvas.height }, that.themeManager.getOptions('tooltip') || {}), tooltipCoords, point = this.tracker.pointAtShownTooltip; if (!$.isFunction(tooltipOptions.customizeText) && utils.isDefined(tooltipOptions.customizeText)) { that._incidentOccured("E2103", ['customizeText']); tooltipOptions.customizeText = undefined } if (that.tooltip) that.tooltip.update(tooltipOptions); else that.tooltip = core.CoreFactory.createTooltip(tooltipOptions, that._tooltipGroup, that.renderer); that.tracker.setTooltip(that.tooltip); if (point) { tooltipCoords = point.getTooltipCoords(); that.tooltip.move(~~tooltipCoords.x, ~~tooltipCoords.y, tooltipCoords.offset); that.tooltip.show() } }, _prepareDrawOptions: function(drawOptions) { var animationOptions = this._getAnimationOptions(), options; options = $.extend({}, { force: false, adjustAxes: true, drawLegend: true, drawTitle: true, adjustSeriesLabels: true, animate: animationOptions.enabled, animationPointsLimit: animationOptions.maxPointCountSupported, asyncSeriesRendering: animationOptions.asyncSeriesRendering, asyncTrackersRendering: animationOptions.asyncTrackersRendering, trackerRenderingDelay: animationOptions.trackerRenderingDelay }, drawOptions); if (!utils.isDefined(options.recreateCanvas)) options.recreateCanvas = options.adjustAxes && options.drawLegend && options.drawTitle; return options }, _processRefreshData: function(newRefreshAction) { var currentRefreshActionPosition = $.inArray(this._currentRefreshData, ACTIONS_BY_PRIORITY), newRefreshActionPosition = $.inArray(newRefreshAction, ACTIONS_BY_PRIORITY); if (!this._currentRefreshData || currentRefreshActionPosition >= 0 && newRefreshActionPosition < currentRefreshActionPosition) this._currentRefreshData = newRefreshAction }, _disposeSeries: function() { var that = this; that.tracker._clean(); $.each(that.series || [], function(_, series) { series.dispose() }); that.series = null; $.each(that.seriesFamilies || [], function(_, family) { family.dispose() }); that.seriesFamilies = null }, _optionChanged: function(name) { var that = this, themeManager = this.themeManager; themeManager.resetOptions(name); themeManager.update(that._options); if (name === 'animation') { that.renderer.updateAnimationOptions(this._getAnimationOptions()); return } clearTimeout(that.delayedRedraw); switch (name) { case'dataSource': that._needHandleRenderComplete = true; that._processRefreshData('_reinitDataSource'); break; case'palette': that.themeManager.updatePalette(this.option(name)); that._disposeSeries(); that._needHandleRenderComplete = true; that._processRefreshData('_handleDataSourceChanged'); break; case'series': case'commonSeriesSettings': case'containerBackgroundColor': case'dataPrepareSettings': that._disposeSeries(); that._needHandleRenderComplete = true; that._processRefreshData('_handleDataSourceChanged'); break; case'legend': case'seriesTemplate': that._processRefreshData('_handleDataSourceChanged'); break; case'title': that._processRefreshData('force_render'); break; case'valueAxis': case'argumentAxis': case'commonAxisSettings': that._needHandleRenderComplete = true; that._processRefreshData('reinit'); that._disposeSeries(); that.paneAxis = {}; break; case'panes': case'defaultPane': that._disposeSeries(); that.paneAxis = {}; that._needHandleRenderComplete = true; that._processRefreshData('reinit'); break; case'size': that._processRefreshData('force_render'); break; case'rotated': case'equalBarWidth': case'customizePoint': case'customizeLabel': that._disposeSeries(); that._needHandleRenderComplete = true; that._processRefreshData('reinit'); break; case'theme': that._disposeSeries(); themeManager.setTheme(that.option(name)); that._processRefreshData('reinit'); break; default: that._processRefreshData('reinit') } that.callBase.apply(that, arguments) }, _getLoadIndicatorOption: function() { return this.themeManager.getOptions("loadingIndicator") }, _refresh: function() { var that = this; this.renderer.stopAllAnimations(true); if (that._currentRefreshData) { switch (that._currentRefreshData) { case'force_render': that._render({force: true}); break; case'reinit': that._reinit(true); break; default: that[that._currentRefreshData] && that[that._currentRefreshData]() } delete that._currentRefreshData } else that._render({force: true}) }, _dataSourceOptions: function() { return { paginate: false, _preferSync: true } }, _updateCanvasClipRect: function(canvas) { var that = this, width, height; canvas = canvas || that.canvas; width = Math.max(canvas.width - canvas.left - canvas.right, 0); height = Math.max(canvas.height - canvas.top - canvas.bottom, 0); that.canvasClipRect.updateRectangle({ x: canvas.left, y: canvas.top, width: width, height: height }); that.canvasClipRect.append() }, _getCanvasClipRectID: function() { return this.canvasClipRect.id }, _handleDataSourceChanged: function() { clearTimeout(this.delayedRedraw); this._dataSpecificInit(true) }, _groupSeries: function() { this._groupedSeries = [this.series] }, _dataSpecificInit: function(needRedraw) { this._initSeries(); this._repopulateSeries(); this._handleSeriesPopulated(needRedraw) }, _processSingleSeries: function(){}, _repopulateSeries: function() { var that = this, parsedData, data = that._dataSource && that._dataSource.items(), dataValidatorOptions = that.themeManager.getOptions('dataPrepareSettings'), seriesTemplate = that.themeManager.getOptions('seriesTemplate'); if (that._dataSource && seriesTemplate) { that._templatedSeries = utils.processSeriesTemplate(seriesTemplate, that._dataSource.items()); that._populateSeries(); delete that._templatedSeries; data = that.teamplateData || data } that._groupSeries(); that._dataValidator = charts.factory.createDataValidator(data, that._groupedSeries, that._incidentOccured, dataValidatorOptions); parsedData = that._dataValidator.validate(); that.themeManager.resetPalette(); $.each(that.series, function(_, singleSeries) { singleSeries.updateData(parsedData); that._processSingleSeries(singleSeries) }) }, _handleRenderComplete: function() { var that = this, userHandle = this.option('done'), allSeriesInited = true; if (that._needHandleRenderComplete) { $.each(that.series, function(_, s) { allSeriesInited = allSeriesInited && s.canRenderCompleteHandle() }); if (allSeriesInited) { that._needHandleRenderComplete = false; $.isFunction(userHandle) && userHandle.call(that) } } }, _renderTitleAndLegend: function(drawOptions, legendHasInsidePosition) { var that = this, titleOptions = that.themeManager.getOptions("title"), drawTitle = titleOptions.text && drawOptions.drawTitle, drawLegend = drawOptions.drawLegend && that.legend && !legendHasInsidePosition, drawElements = []; if (drawTitle) { that._titleGroup.append(); that._drawTitle(); drawElements.push(that.chartTitle) } if (drawLegend) { that._legendGroup.append(); drawElements.push(that.legend) } drawElements.length && that.layoutManager.drawElements(drawElements, that.canvas); if (drawTitle) that.layoutManager.correctSizeElement(that.chartTitle, that.canvas) }, getAllSeries: function getAllSeries() { return this.series.slice() }, getSeriesByName: function getSeriesByName(name) { var found = null; $.each(this.series, function(i, singleSeries) { if (singleSeries.name === name) { found = singleSeries; return false } }); return found }, getSeriesByPos: function getSeriesByPos(pos) { return this.series[pos] }, getSelectedSeries: function getSelectedSeries() { return null }, clearSelection: function clearSelection() { this.tracker.clearSelection() }, hideTooltip: function() { this.tracker._hideTooltip() }, showLoadingIndicator: function() { this._showLoadIndicator(this.themeManager.getOptions("loadingIndicator"), this.canvas || {}) }, render: function(renderOptions) { this._render(renderOptions) }, getSize: function() { var canvas = this.canvas || {}; return { width: canvas.width, height: canvas.height } } }).include(ui.DataHelperMixin) })(jQuery, DevExpress); /*! Module viz-charts, file chart.js */ (function($, DX, undefined) { var core = DX.viz.core, charts = DX.viz.charts, utils = DX.utils, MAX_ADJUSTMENT_ATTEMPTS = 5, DEFAULT_PANE_NAME = 'default', DEFAULT_AXIS_NAME = 'defaultAxisName', DEFAULT_BUSINESS_RANGE_VALUE_MARGIN = 0.1, ASYNC_SERIES_RENDERING_DELAY = 25, _each = $.each; function prepareAxis(axisOptions) { return $.isArray(axisOptions) ? axisOptions.length === 0 ? [{}] : axisOptions : [axisOptions] } charts.Chart = charts.BaseChart.inherit({ _setDefaultOptions: function() { this.callBase(); this.option({ defaultPane: DEFAULT_PANE_NAME, panes: [{ name: DEFAULT_PANE_NAME, border: {} }] }) }, _dispose: function() { var that = this, disposeObjectsInArray = this._disposeObjectsInArray; that.callBase(); that.panes = null; that.legend && (that.legend.dispose(), that.legend = null); disposeObjectsInArray.call(that, "panesBackground"); disposeObjectsInArray.call(that, "panesClipRects"); disposeObjectsInArray.call(that, "financialPanesClipRects"); disposeObjectsInArray.call(that, "_argumentAxes"); disposeObjectsInArray.call(that, "_valueAxes"); disposeObjectsInArray.call(that, "seriesFamilies"); _each(that._paneTrackerGroups || [], function(_, groups) { groups.paneSeriesGroup.dispose(); groups.paneMarkerGroup.dispose() }); that._paneTrackerGroups = null }, _init: function() { this.__ASYNC_SERIES_RENDERING_DELAY = ASYNC_SERIES_RENDERING_DELAY; this.paneAxis = {}; this._crossHairOptions = {}; this.callBase() }, _reinit: function(needRedraw) { var that = this; that.translators = {}; that.panes = that._createPanes(); that._populateAxes(); that.callBase(); delete that._seriesInitializing; if (!that.series) that._dataSpecificInit(); else that._correctValueAxes(); that._endLoading(function() { needRedraw && that._render({force: true}) }) }, _correctBusinessRange: function(range, tickInterval, setTicksAtUnitBeginning) { var min = 'min', max = 'max'; if (!tickInterval || !utils.isDefined(range[min]) || !utils.isDefined(range[max])) return false; var tickIntervalRange = {}, originInterval = tickInterval; tickInterval = $.isNumeric(tickInterval) ? tickInterval : utils.convertDateTickIntervalToMilliseconds(tickInterval); if (tickInterval >= Math.abs(range[max] - range[min])) { if (utils.isDate(range[min])) { if (!$.isNumeric(originInterval)) { tickIntervalRange[min] = utils.addInterval(range[min], originInterval, true); tickIntervalRange[max] = utils.addInterval(range[max], originInterval, false) } else { tickIntervalRange[min] = new Date(range[min].valueOf() - tickInterval); tickIntervalRange[max] = new Date(range[max].valueOf() + tickInterval) } if (setTicksAtUnitBeginning) { utils.correctDateWithUnitBeginning(tickIntervalRange[max], originInterval); utils.correctDateWithUnitBeginning(tickIntervalRange[min], originInterval) } } else { tickIntervalRange[min] = range[min] - tickInterval; tickIntervalRange[max] = range[max] + tickInterval } range.addRange(tickIntervalRange); return true } return false }, _seriesVisibilityChanged: function() { this._processSeriesFamilies(); this._populateBusinessRange(); this.renderer.stopAllAnimations(true); this._render({ force: true, asyncSeriesRendering: false, asyncTrackersRendering: false }) }, _populateBusinessRange: function(visibleArea) { var that = this, businessRanges = [], aggregationRange, minBound, maxBound, i, themeManager = that.themeManager, rotated = themeManager.getOptions('rotated'), singleSeriesRange, valAxes = that._valueAxes, valueAxes = {}, argAxes = that._argumentAxes, useAggregation = themeManager.getOptions('useAggregation'), argumentTickInterval, setTicksAtUnitBeginning, paneAxis = that.paneAxis, groupedSeries = that._groupedSeries; that._disposeObjectsInArray("businessRanges", ["arg", "val"]); var argRange = new core.Range({ rotated: !!rotated, minValueMargin: DEFAULT_BUSINESS_RANGE_VALUE_MARGIN, maxValueMargin: DEFAULT_BUSINESS_RANGE_VALUE_MARGIN }); _each(valAxes, function(_, axis) { valueAxes[axis.name] = axis }); _each(paneAxis, function(paneName, pane) { _each(pane, function(axisName, _) { var seriesForRange = [], firstSeriesForRange, options, valueAxesForRange, valRange = new core.Range({ isValueRange: true, rotated: !!rotated, pane: paneName, axis: axisName, minValueMargin: DEFAULT_BUSINESS_RANGE_VALUE_MARGIN, maxValueMargin: DEFAULT_BUSINESS_RANGE_VALUE_MARGIN }), valueType, calcInterval; _each(groupedSeries, function(_, particularSeriesGroup) { if (particularSeriesGroup[0].pane === paneName && particularSeriesGroup[0].axis === axisName) seriesForRange = particularSeriesGroup }); _each(valAxes, function(_, axis) { if (axis.pane === paneName && axis.name === axisName) { valueAxesForRange = axis; return false } }); firstSeriesForRange = seriesForRange && seriesForRange.length ? seriesForRange[0] : {}; _each(argAxes, function(_, axis) { var options = axis.options; options.type = firstSeriesForRange.argumentAxisType || options.type; options.argumentType = firstSeriesForRange.argumentType || options.argumentType; axis.validate(true, that._incidentOccured); argRange = argRange.addRange(axis.getRangeData()); argumentTickInterval = options.tickInterval; setTicksAtUnitBeginning = options.setTicksAtUnitBeginning; calcInterval = axis.calcInterval }); options = valueAxesForRange.options; options.type = firstSeriesForRange.valueAxisType || options.type; options.valueType = firstSeriesForRange.valueType || options.valueType; valueAxesForRange.validate(false, that._incidentOccured); var axisRange = new core.Range(valueAxesForRange.getRangeData()); valueType = valueType || options.valueType === 'datetime' ? 'datetime' : undefined; valRange = valRange.addRange(axisRange); minBound = valRange.min; maxBound = valRange.max; for (i = 0; i < seriesForRange.length; i++) { if (visibleArea) { visibleArea.minVal = minBound; visibleArea.maxVal = maxBound; if (useAggregation && !visibleArea.adjustOnZoom) { aggregationRange = seriesForRange[i]._originalBusinessRange; visibleArea.minVal = utils.isDefined(visibleArea.minVal) ? visibleArea.minVal : aggregationRange.val.min; visibleArea.maxVal = utils.isDefined(visibleArea.maxVal) ? visibleArea.maxVal : aggregationRange.val.max } } singleSeriesRange = seriesForRange[i].getRangeData(visibleArea, calcInterval); valRange = valRange.addRange(singleSeriesRange.val); argRange = argRange.addRange(singleSeriesRange.arg) } if (!valRange.isDefined()) valRange.setStubData(valueType); businessRanges.push({val: valRange}) }) }); if (!argRange.isDefined()) argRange.setStubData(argAxes[0].options.argumentType); var bussinesRangeCorrectedWithTickInterval = that._correctBusinessRange(argRange, argumentTickInterval, setTicksAtUnitBeginning); !bussinesRangeCorrectedWithTickInterval && argRange.applyValueMargins(); _each(businessRanges, function(_, item) { var range = item.val, vAxis = valueAxes[range.axis]; range.applyValueMargins(); if (vAxis && vAxis.options.showZero) range.correctValueZeroLevel(); item.arg = argRange }); that.businessRanges = businessRanges }, _groupSeries: function() { var that = this, panes = that.panes, valAxes = that._valueAxes, paneList = $.map(panes, function(pane) { return pane.name }), series = that.series, paneAxis = that.paneAxis, groupedSeries = that._groupedSeries = []; var getFirstAxisNameForPane = function(axes, paneName) { var result; for (var i = 0; i < axes.length; i++) if (axes[i].pane === paneName) { result = axes[i].name; break } if (!result) result = valAxes[0].name; return result }; _each(series, function(i, particularSeries) { particularSeries.axis = particularSeries.axis || getFirstAxisNameForPane(valAxes, particularSeries.pane); if (particularSeries.axis) { paneAxis[particularSeries.pane] = paneAxis[particularSeries.pane] || {}; paneAxis[particularSeries.pane][particularSeries.axis] = true } }); _each(valAxes, function(_, axis) { if (axis.name && axis.pane && $.inArray(axis.pane, paneList) != -1) { paneAxis[axis.pane] = paneAxis[axis.pane] || {}; paneAxis[axis.pane][axis.name] = true } }); that._correctValueAxes(); var hideGridsOnNonFirstValueAxisForPane = function(paneName) { var axesForPane = [], firstShownAxis; _each(valAxes, function(_, axis) { if (axis.pane === paneName) axesForPane.push(axis) }); if (axesForPane.length > 1 && that.themeManager.getOptions('synchronizeMultiAxes')) _each(axesForPane, function(_, axis) { var gridOpt = axis.options.grid; if (firstShownAxis && gridOpt && gridOpt.visible) gridOpt.visible = false; else firstShownAxis = firstShownAxis ? firstShownAxis : gridOpt && gridOpt.visible }) }; _each(paneAxis, function(paneName, pane) { hideGridsOnNonFirstValueAxisForPane(paneName); _each(pane, function(axisName, _) { var group = []; _each(series, function(_, particularSeries) { if (particularSeries.pane === paneName && particularSeries.axis === axisName) group.push(particularSeries) }); group.length && groupedSeries.push(group) }) }) }, _cleanPanesClipRects: function(clipArrayName) { var that = this, clipArray = that[clipArrayName]; _each(clipArray || [], function(_, clipRect) { clipRect && clipRect.remove() }); that[clipArrayName] = [] }, _createPanes: function() { var that = this, panes = that.option('panes'), panesNameCounter = 0, bottomPaneName; if (panes && utils.isArray(panes) && !panes.length || $.isEmptyObject(panes)) panes = that.initialOption("panes"); that._cleanPanesClipRects('panesClipRects'); that._cleanPanesClipRects('financialPanesClipRects'); that.defaultPane = that.option('defaultPane'); panes = $.isArray(panes) ? panes : panes ? [panes] : []; _each(panes, function(_, pane) { pane.name = !utils.isDefined(pane.name) ? DEFAULT_PANE_NAME + panesNameCounter++ : pane.name }); if (!that._doesPaneExists(panes, that.defaultPane) && panes.length > 0) { bottomPaneName = panes[panes.length - 1].name; that._incidentOccured('W2101', [that.defaultPane, bottomPaneName]); that.defaultPane = bottomPaneName } panes = that.themeManager.getOptions('rotated') ? panes.reverse() : panes; return panes }, _doesPaneExists: function(panes, paneName) { var found = false; _each(panes, function(_, pane) { if (pane.name === paneName) { found = true; return false } }); return found }, _populateSeries: function() { var that = this, themeManager = that.themeManager, hasSeriesTemplate = !!themeManager.getOptions('seriesTemplate'), series = hasSeriesTemplate ? that._templatedSeries : that.option('series'), allSeriesOptions = $.isArray(series) ? series : series ? [series] : [], argumentAxisOptions = that.option('argumentAxis'), valueAxisOptions = that.option('valueAxis'), data, particularSeriesOptions, particularSeries, rotated = themeManager.getOptions('rotated'), i, paneList = $.map(that.panes, function(pane) { return pane.name }), paneName, paneIndex; that.teamplateData = []; _each(that._paneTrackerGroups || [], function(_, groups) { groups.paneSeriesGroup.remove(); groups.paneMarkerGroup.remove() }); that._paneTrackerGroups = []; _each(that.panes, function(_, pane) { var paneSeriesTrackerGroup = that.renderer.createGroup({'class': 'dxc-pane-tracker'}), paneMarkerTrackerGroup = that.renderer.createGroup({'class': 'dxc-pane-tracker'}); that._paneTrackerGroups.push({ paneSeriesGroup: paneSeriesTrackerGroup, paneMarkerGroup: paneMarkerTrackerGroup }) }); that._disposeSeries(); that.series = []; themeManager.resetPalette(); for (i = 0; i < allSeriesOptions.length; i++) { particularSeriesOptions = $.extend(true, {}, allSeriesOptions[i]); if (particularSeriesOptions.type && !utils.isString(particularSeriesOptions.type)) particularSeriesOptions.type = ''; data = particularSeriesOptions.data; particularSeriesOptions.data = null; particularSeriesOptions.rotated = rotated; particularSeriesOptions.customizePoint = themeManager.getOptions("customizePoint"); particularSeriesOptions.customizeLabel = themeManager.getOptions("customizeLabel"); particularSeriesOptions.visibilityChanged = $.proxy(this._seriesVisibilityChanged, this); particularSeriesOptions.resolveLabelsOverlapping = themeManager.getOptions("resolveLabelsOverlapping"); if (argumentAxisOptions) { particularSeriesOptions.argumentCategories = argumentAxisOptions.categories; particularSeriesOptions.argumentAxisType = argumentAxisOptions.type; particularSeriesOptions.argumentType = argumentAxisOptions.argumentType } if (valueAxisOptions) if (utils.isArray(valueAxisOptions)) _each(valueAxisOptions, function(iter, options) { if (!particularSeriesOptions.axis && !iter || particularSeriesOptions.axis === options.name) { particularSeriesOptions.valueCategories = options.categories; particularSeriesOptions.valueAxisType = options.type; particularSeriesOptions.valueType = options.valueType; particularSeriesOptions.showZero = options.showZero } }); else { particularSeriesOptions.valueCategories = valueAxisOptions.categories; particularSeriesOptions.valueAxisType = valueAxisOptions.type; particularSeriesOptions.valueType = valueAxisOptions.valueType; particularSeriesOptions.showZero = valueAxisOptions.showZero } particularSeriesOptions.incidentOccured = that._incidentOccured; if (!particularSeriesOptions.name) particularSeriesOptions.name = 'Series ' + (i + 1).toString(); var seriesTheme = themeManager.getOptions("series", particularSeriesOptions); seriesTheme.pane = seriesTheme.pane || that.defaultPane; paneName = seriesTheme.pane; paneIndex = that._getPaneIndex(paneName); if ($.inArray(paneName, paneList) === -1) continue; seriesTheme.seriesGroup = that._seriesGroup; seriesTheme.labelsGroup = that._labelsGroup; seriesTheme.trackersGroup = that._paneTrackerGroups[paneIndex].paneSeriesGroup; seriesTheme.markerTrackerGroup = that._paneTrackerGroups[paneIndex].paneMarkerGroup; particularSeries = core.CoreFactory.createSeries(that.renderer, seriesTheme); if (!particularSeries.isUpdated) that._incidentOccured("E2101", [seriesTheme.type]); else { particularSeries.index = i; that.series.push(particularSeries) } if (hasSeriesTemplate) { _each(data, function(_, data) { _each(particularSeries.getTeamplatedFields(), function(_, field) { data[field.teamplateField] = data[field.originalField] }); that.teamplateData.push(data) }); particularSeries.updateTeamplateFieldNames() } } return that.series }, _createValueAxis: function(axisOptions, rotated, tickProvider) { var that = this, axis; axisOptions = that.themeManager.getOptions("valueAxis", $.extend({ isHorizontal: rotated, tickProvider: tickProvider, incidentOccured: that._incidentOccured }, axisOptions), rotated); if (axisOptions.strips) _each(axisOptions.strips, function(i, strips) { axisOptions.strips[i] = $.extend(true, {}, axisOptions.stripStyle, axisOptions.strips[i]) }); if (axisOptions.constantLines) _each(axisOptions.constantLines, function(i, line) { axisOptions.constantLines[i] = $.extend(true, {}, axisOptions.constantLineStyle, line) }); axis = charts.factory.createAxis(that.renderer, axisOptions); axis.name = axisOptions.name; axis.pane = axis.pane || axisOptions.pane; axis.priority = axisOptions.priority; return axis }, _disposeAxes: function() { var that = this; _each(that._valueAxes || [], function(_, axis) { axis.dispose() }); _each(that._argumentAxes || [], function(_, axis) { axis.dispose() }); that._valueAxes = null; that._argumentAxes = null }, _populateAxes: function() { var that = this, valueAxes = [], argumentAxes = [], panes = that.panes, themeManager = that.themeManager, rotated = themeManager.getOptions('rotated'), valueAxisOptions = that.option('valueAxis') || {}, argumentOption = that.option('argumentAxis') || {}, argumentAxesOptions = prepareAxis(argumentOption), valueAxesOptions = prepareAxis(valueAxisOptions), axis, axisNames = [], tickProvider = core.CoreFactory.getTickProvider(), paneWithNonVirtualAxis; that._disposeAxes(); var createArgumentAxis = function(axisOptions, virtual) { axisOptions = that.themeManager.getOptions("argumentAxis", $.extend(true, { isHorizontal: !rotated, tickProvider: tickProvider, pane: that.defaultPane, incidentOccured: that._incidentOccured }, axisOptions), rotated); if (axisOptions.strips) _each(axisOptions.strips, function(i, strips) { axisOptions.strips[i] = $.extend(true, {}, axisOptions.stripStyle, axisOptions.strips[i]) }); if (axisOptions.constantLines) _each(axisOptions.constantLines, function(i, line) { axisOptions.constantLines[i] = $.extend(true, {}, axisOptions.constantLineStyle, line) }); axis = charts.factory.createAxis(that.renderer, axisOptions); axis._virtual = virtual; argumentAxes.push(axis); return axis }; if (rotated) paneWithNonVirtualAxis = argumentAxesOptions[0].position === 'right' ? panes[panes.length - 1].name : panes[0].name; else paneWithNonVirtualAxis = argumentAxesOptions[0].position === 'top' ? panes[0].name : panes[panes.length - 1].name; _each(panes, function(_, pane) { var paneName = pane.name, virtual = paneName != paneWithNonVirtualAxis; var axisOptions = $.extend(true, {}, argumentAxesOptions[0], {pane: paneName}); createArgumentAxis(axisOptions, virtual) }); var valueAxesCounter = 0; var getNextAxisName = function() { return DEFAULT_AXIS_NAME + valueAxesCounter++ }; var unique = function(array) { var values = {}, i, len = array.length; for (i = 0; i < len; i++) values[array[i]] = true; return $.map(values, function(_, key) { return key }) }; _each(valueAxesOptions, function(priority, axisOptions) { var axisPanes = [], name = axisOptions.name; if (name && $.inArray(name, axisNames) != -1) { that._incidentOccured("E2102"); return } name && axisNames.push(name); if (axisOptions.pane) axisPanes.push(axisOptions.pane); if (axisOptions.panes && axisOptions.panes.length) axisPanes = axisPanes.concat(axisOptions.panes.slice(0)); axisPanes = unique(axisPanes); if (!axisPanes.length) axisPanes.push(undefined); _each(axisPanes, function(_, pane) { valueAxes.push(that._createValueAxis($.extend(true, {}, axisOptions, { name: name || getNextAxisName(), pane: pane, priority: priority }), rotated, tickProvider)) }) }); that._valueAxes = valueAxes; that._argumentAxes = argumentAxes }, _correctValueAxes: function() { var that = this, rotated = that.themeManager.getOptions('rotated'), valueAxisOptions = that.option('valueAxis') || {}, valueAxesOptions = $.isArray(valueAxisOptions) ? valueAxisOptions : [valueAxisOptions], tickProvider = core.CoreFactory.getTickProvider(), valueAxes = that._valueAxes || [], defaultAxisName = valueAxes[0].name, paneAxis = that.paneAxis || {}, panes = that.panes, i, neededAxis = {}; var getPaneForAxis = function(axisNameWithoutPane) { var result; _each(that.paneAxis, function(paneName, pane) { _each(pane, function(axisName, _) { if (axisNameWithoutPane == axisName) { result = paneName; return false } }) }); return result }; var axesWithoutPanes = $.map(valueAxes, function(axis) { if (axis.pane) return null; return axis }); _each(axesWithoutPanes, function(_, axis) { axis.pane = getPaneForAxis(axis.name); if (!axis.pane) { axis.pane = that.defaultPane; paneAxis[axis.pane] = paneAxis[axis.pane] || {}; paneAxis[axis.pane][axis.name] = true } axis.options.pane = axis.pane }); for (i = 0; i < panes.length; i++) if (!paneAxis[panes[i].name]) { paneAxis[panes[i].name] = {}; paneAxis[panes[i].name][defaultAxisName] = true } var findAxisOptions = function(axisName) { var result, axInd; for (axInd = 0; axInd < valueAxesOptions.length; axInd++) if (valueAxesOptions[axInd].name == axisName) { result = valueAxesOptions[axInd]; result.priority = axInd; break } if (!result) for (axInd = 0; axInd < valueAxes.length; axInd++) if (valueAxes[axInd].name == axisName) { result = valueAxes[axInd].options; result.priority = valueAxes[axInd].priority; break } if (!result) { that._incidentOccured("W2102", [axisName]); result = { name: axisName, priority: valueAxes.length } } return result }; var findAxis = function(paneName, axisName) { var axis; for (i = 0; i < valueAxes.length; i++) { axis = valueAxes[i]; if (axis.name === axisName && axis.pane === paneName) return axis } }; _each(that.paneAxis, function(paneName, axisNames) { _each(axisNames, function(axisName, _) { neededAxis[axisName + '-' + paneName] = true; if (!findAxis(paneName, axisName)) { var axisOptions = findAxisOptions(axisName); if (axisOptions) valueAxes.push(that._createValueAxis($.extend(true, {}, axisOptions, { pane: paneName, name: axisName }), rotated, tickProvider)) } }) }); valueAxes = $.grep(valueAxes, function(elem) { return !!neededAxis[elem.name + '-' + elem.pane] }); valueAxes.sort(function(a, b) { return a.priority - b.priority }); that._valueAxes = valueAxes }, _processSeriesFamilies: function() { var that = this, types = [], families = [], paneSeries, themeManager = that.themeManager, rotated = themeManager.getOptions('rotated'); if (that.seriesFamilies && that.seriesFamilies.length) { _each(that.seriesFamilies, function(_, family) { family.adjustSeriesValues() }); return } _each(that.series, function(_, item) { if ($.inArray(item.type, types) === -1) types.push(item.type) }); _each(that.panes, function(_, pane) { paneSeries = []; _each(that.series, function(_, oneSeries) { if (oneSeries.pane === pane.name) paneSeries.push(oneSeries) }); _each(types, function(_, type) { var family = core.CoreFactory.createSeriesFamily({ type: type, pane: pane.name, rotated: rotated, equalBarWidth: themeManager.getOptions('equalBarWidth'), minBubbleSize: themeManager.getOptions('minBubbleSize'), maxBubbleSize: themeManager.getOptions('maxBubbleSize') }); family.add(paneSeries); family.adjustSeriesValues(); families.push(family) }) }); that.seriesFamilies = families }, _createLegend: function() { var that = this, legendData = [], legendOptions = that.themeManager.getOptions('legend'); legendData = $.map(that.series, function(seriesItem) { if (seriesItem.getOptions().showInLegend) return { text: seriesItem.name, color: seriesItem.getColor(), id: seriesItem.index, states: seriesItem.getLegendStyles() } }); legendOptions.containerBackgroundColor = that.themeManager.getOptions("containerBackgroundColor"); legendOptions._incidentOccured = that._incidentOccured; if (that.legend) that.legend.update(legendData, legendOptions); else that.legend = core.CoreFactory.createLegend(legendData, legendOptions, that.renderer, that._legendGroup) }, _createTranslator: function(range, canvas, options) { return core.CoreFactory.createTranslator2D(range, canvas, options) }, _createPanesBorderOptions: function() { var commonBorderOptions = this.themeManager.getOptions('commonPaneSettings').border, panesBorderOptions = {}; _each(this.panes, function(_, pane) { var borderOptions = $.extend(true, {}, commonBorderOptions, pane.border); panesBorderOptions[pane.name] = borderOptions }); return panesBorderOptions }, _render: function(drawOptions) { var that = this, themeManager = that.themeManager, rotated = themeManager.getOptions('rotated'), i, layoutManager = that.layoutManager, panesBorderOptions = that._createPanesBorderOptions(), needHideLoadIndicator, legendHasInsidePosition = that.legend && that.legend.getPosition() === "inside"; var drawSeries = function drawSeries() { var panes = that.panes, hideLayoutLabels = that.layoutManager.needMoreSpaceForPanesCanvas(that.panes, rotated) && !that.themeManager.getOptions("adaptiveLayout").keepLabels, stackPoints = {}; _each(that.seriesFamilies || [], function(_, seriesFamily) { var tr = that._getTranslator(seriesFamily.pane) || {}, translators = {}; translators[rotated ? 'x' : 'y'] = tr.val; translators[rotated ? 'y' : 'x'] = tr.arg; seriesFamily.updateSeriesValues(translators); seriesFamily.adjustSeriesDimensions(translators) }); that._createCrossHairCursor(); function applyPaneClipRect(seriesOptions) { var paneIndex = that._getPaneIndex(seriesOptions.pane); seriesOptions.setClippingParams(seriesOptions.isFinancialSeries() ? that.financialPanesClipRects[paneIndex].id : that.panesClipRects[paneIndex].id, that._getPaneBorderVisibility(paneIndex)) } function preparePointsForSharedTooltip(singleSeries, stackPoints) { if (!themeManager.getOptions('tooltip').shared) return; var points = singleSeries.getPoints(), stackName = singleSeries.getStackName(); _each(points, function(index, point) { var argument = point.argument; if (!stackPoints[argument]) { stackPoints[argument] = {}; stackPoints[argument][null] = [] } if (stackName && !DX.utils.isArray(stackPoints[argument][stackName])) { stackPoints[argument][stackName] = []; _each(stackPoints[argument][null], function(_, point) { if (!point.stackName) stackPoints[argument][stackName].push(point) }) } if (stackName) { stackPoints[argument][stackName].push(point); stackPoints[argument][null].push(point) } else _each(stackPoints[argument], function(_, stack) { stack.push(point) }); point.stackPoints = stackPoints[argument][stackName]; point.stackName = stackName }) } _each(that.series, function(_, particularSeries) { preparePointsForSharedTooltip(particularSeries, stackPoints); applyPaneClipRect(particularSeries); particularSeries.setAdjustSeriesLabels(drawOptions.adjustSeriesLabels); var tr = that._getTranslator(particularSeries.pane, particularSeries.axis), translators = {}; translators[rotated ? 'x' : 'y'] = tr.val; translators[rotated ? 'y' : 'x'] = tr.arg; particularSeries.draw(translators, drawOptions.animate && particularSeries.getPoints().length <= drawOptions.animationPointsLimit && that.renderer.animationEnabled(), hideLayoutLabels, that.legend && that.legend.getActionCallback(particularSeries)) }); that._trackerGroup.append(); if (drawOptions.drawLegend && that.legend && legendHasInsidePosition) { var newCanvas = $.extend({}, panes[0].canvas), layoutManager = charts.factory.createChartLayoutManager(); newCanvas.right = panes[panes.length - 1].canvas.right; newCanvas.bottom = panes[panes.length - 1].canvas.bottom; that._legendGroup.append(); that._tooltipGroup.append(); layoutManager.drawElements([that.legend], newCanvas); layoutManager.placeDrawnElements(newCanvas) } needHideLoadIndicator && that.hideLoadingIndicator(); that._drawn(); var drawChartTrackers = function drawChartTrackers() { var i; for (i = 0; i < that.series.length; i++) that.series[i].drawTrackers(); if (that.legend) { that.legend.drawTrackers(); legendHasInsidePosition && that._legendGroup.append(); legendHasInsidePosition && that._tooltipGroup.append() } that.tracker._prepare(); _each(that._paneTrackerGroups, function(index, paneGroups) { paneGroups.paneSeriesGroup.append(that._seriesTrackerGroup); paneGroups.paneMarkerGroup.append(that._markerTrackerGroup) }); that._handleRenderComplete() }; that._createTooltip(); if (drawOptions.asyncTrackersRendering) that.delayedRedraw = setTimeout(drawChartTrackers, drawOptions.trackerRenderingDelay); else drawChartTrackers() }; drawOptions = that._prepareDrawOptions(drawOptions); that.callBase(drawOptions); if (that.stopRedraw) { that.stopRedraw = false; return } that._createPanesBackground(); that._stripsGroup.append(); that._axesGroup.append(); that._constantLinesGroup.append(); that._labelAxesGroup.append(); that._createTranslators(drawOptions); that._options.useAggregation && _each(that.series, function(_, series) { series._originalBusinessRange = series._originalBusinessRange || series.getRangeData(); var tr = that._getTranslator(series.pane, series.axis), translators = {}; translators[rotated ? 'x' : 'y'] = tr.val; translators[rotated ? 'y' : 'x'] = tr.arg; series.resamplePoints(translators, that._zoomMinArg, that._zoomMaxArg) }); if (utils.isDefined(that._zoomMinArg) || utils.isDefined(that._zoomMaxArg)) that._populateBusinessRange({ adjustOnZoom: themeManager.getOptions('adjustOnZoom'), minArg: that._zoomMinArg, maxArg: that._zoomMaxArg }); if (that._options.useAggregation || utils.isDefined(that._zoomMinArg) || utils.isDefined(that._zoomMaxArg)) that._updateTranslators(); that._renderTitleAndLegend(drawOptions, legendHasInsidePosition); if (drawOptions && drawOptions.recreateCanvas) layoutManager.updatePanesCanvases(that.panes, that.canvas, rotated); that._drawAxes(panesBorderOptions, drawOptions); if (layoutManager.needMoreSpaceForPanesCanvas(that.panes, rotated)) { layoutManager.updateDrawnElements(that._argumentAxes, that._valueAxes, that.canvas, that.dirtyCanvas, that.panes, rotated); if (that.chartTitle) that.layoutManager.correctSizeElement(that.chartTitle, that.canvas); that._updateCanvasClipRect(that.dirtyCanvas); layoutManager.updatePanesCanvases(that.panes, that.canvas, rotated); that._drawAxes(panesBorderOptions, drawOptions, true) } layoutManager.placeDrawnElements(that.canvas); that._drawPanesBorders(panesBorderOptions); that._createClipRectsForPanes(); for (i = 0; i < that._argumentAxes.length; i++) that._argumentAxes[i].applyClipRect(that._getElementsClipRectID(that._argumentAxes[i].pane)); for (i = 0; i < that._valueAxes.length; i++) that._valueAxes[i].applyClipRect(that._getElementsClipRectID(that._valueAxes[i].pane)); that._fillPanesBackground(); that._seriesGroup.append(); that._labelsGroup.append(); that._crossHairCursorGroup.append(); that._legendGroup.append(); that._tooltipGroup.append(); needHideLoadIndicator = that._loadIndicator && that._loadIndicator.isShown && that._dataSource && that._dataSource.isLoaded() && !drawOptions.isResize; if (drawOptions.asyncSeriesRendering) that.delayedRedraw = setTimeout(drawSeries, ASYNC_SERIES_RENDERING_DELAY); else drawSeries() }, _createTranslators: function(drawOptions) { var that = this, rotated = that.themeManager.getOptions("rotated"), translators; if (!drawOptions.recreateCanvas) return; that.translators = translators = {}; that.layoutManager.updatePanesCanvases(that.panes, that.canvas, rotated); _each(that.paneAxis, function(paneName, pane) { translators[paneName] = translators[paneName] || {}; _each(pane, function(axisName, _) { var translator = that._createTranslator(new core.Range(that._getBusinessRange(paneName, axisName).val), that._getCanvasForPane(paneName), rotated ? {direction: 'horizontal'} : {}); translator.pane = paneName; translator.axis = axisName; translators[paneName][axisName] = {val: translator} }) }); _each(that._argumentAxes, function(_, axis) { var translator = that._createTranslator(new core.Range(that._getBusinessRange(axis.pane).arg), that._getCanvasForPane(axis.pane), !rotated ? {direction: 'horizontal'} : {}); _each(translators[axis.pane], function(valAxis, paneAsixTran) { paneAsixTran.arg = translator }) }) }, _updateTranslators: function() { var that = this; _each(that.translators, function(pane, axisTrans) { _each(axisTrans, function(axis, translator) { translator.arg.updateBusinessRange(new core.Range(that._getBusinessRange(pane).arg)); delete translator.arg._originalBusinessRange; translator.val.updateBusinessRange(new core.Range(that._getBusinessRange(pane, axis).val)); delete translator.val._originalBusinessRange }) }) }, _reinitTranslators: function() { var that = this; _each(that._argumentAxes, function(_, axis) { var translator = that._getTranslator(axis.pane); if (translator) { translator.arg.reinit(); axis.setRange(translator.arg.getBusinessRange()); axis.setTranslator(translator.arg, translator.val) } }); _each(that._valueAxes, function(_, axis) { var translator = that._getTranslator(axis.pane, axis.name); if (translator) { translator.val.reinit(); axis.setRange(translator.val.getBusinessRange()); axis.setTranslator(translator.val, translator.arg) } }) }, _drawAxes: function(panesBorderOptions, drawOptions, adjustUnits) { var that = this, i = 0, layoutManager = that.layoutManager, rotated = that.themeManager.getOptions("rotated"), translators = that.translators, adjustmentCounter = 0, synchronizeMultiAxes = that.themeManager.getOptions('synchronizeMultiAxes'); that._reinitTranslators(); do { for (i = 0; i < that._argumentAxes.length; i++) that._argumentAxes[i].resetTicks(); for (i = 0; i < that._valueAxes.length; i++) that._valueAxes[i].resetTicks(); if (synchronizeMultiAxes) charts.multiAxesSynchronizer.synchronize(that._valueAxes); drawAxes(rotated ? that._valueAxes : that._argumentAxes); layoutManager.requireAxesRedraw = false; if (drawOptions.adjustAxes) { layoutManager.applyHorizontalAxesLayout(rotated ? that._valueAxes : that._argumentAxes); !layoutManager.stopDrawAxes && _each(translators, function(pane, axisTrans) { _each(axisTrans, function(axis, translator) { translator.arg.reinit(); translator.val.reinit() }) }) } drawAxes(rotated ? that._argumentAxes : that._valueAxes); if (drawOptions.adjustAxes && !layoutManager.stopDrawAxes) { layoutManager.applyVerticalAxesLayout(rotated ? that._argumentAxes : that._valueAxes); !layoutManager.stopDrawAxes && _each(translators, function(pane, axisTrans) { _each(axisTrans, function(axis, translator) { translator.arg.reinit(); translator.val.reinit() }) }) } adjustmentCounter = adjustmentCounter + 1 } while (!layoutManager.stopDrawAxes && layoutManager.requireAxesRedraw && adjustmentCounter < MAX_ADJUSTMENT_ATTEMPTS); that.__axisAdjustmentsCount = adjustmentCounter; function drawAxes(axes) { _each(axes, function(_, axis) { axis.clipRectID = that._getCanvasClipRectID(); axis.stripsGroup = that._stripsGroup; axis.labelAxesGroup = that._labelAxesGroup; axis.constantLinesGroup = that._constantLinesGroup; axis.axesContainerGroup = that._axesGroup; axis.draw({borderOptions: panesBorderOptions[axis.pane]}, adjustUnits) }) } }, _createCrossHairCursor: function() { var that = this, renderer = that.renderer, panes = that.panes, commonCanvas, canvas, options = that.themeManager.getOptions('crosshair') || {}, hLine, vLine, attrHLine, attrVLine, i; if (!options || !options.enabled) return; attrHLine = { stroke: options.horizontalLine.color || options.color, strokeWidth: options.horizontalLine.width || options.width, dashStyle: options.horizontalLine.dashStyle || options.dashStyle, visibility: 'hidden', opacity: options.horizontalLine.opacity || options.opacity }; attrVLine = { stroke: options.verticalLine.color || options.color, strokeWidth: options.verticalLine.width || options.width, dashStyle: options.verticalLine.dashStyle || options.dashStyle, visibility: 'hidden', opacity: options.verticalLine.opacity || options.opacity }; for (i = 0; i < panes.length; i++) { canvas = panes[i].canvas; if (!commonCanvas) commonCanvas = $.extend({}, canvas); else { commonCanvas.right = canvas.right; commonCanvas.bottom = canvas.bottom } renderer.createRect(canvas.left, canvas.top, canvas.width - canvas.right - canvas.left, canvas.height - canvas.bottom - canvas.top, 0).append(this._crosshairTrackerGroup) } if (options.horizontalLine && options.horizontalLine.visible) hLine = renderer.createLine(commonCanvas.left, commonCanvas.top, commonCanvas.width - commonCanvas.right, commonCanvas.top, attrHLine).append(that._crossHairCursorGroup); if (options.verticalLine && options.verticalLine.visible) vLine = renderer.createLine(commonCanvas.left, commonCanvas.top, commonCanvas.left, commonCanvas.height - commonCanvas.bottom, attrVLine).append(that._crossHairCursorGroup); that._crossHairOptions.horizontalLine = hLine; that._crossHairOptions.verticalLine = vLine; that._crossHairOptions.canvas = commonCanvas }, _createPanesBackground: function() { var that = this, defaultBackgroundColor = that.themeManager.getOptions('commonPaneSettings').backgroundColor, backgroundColor, renderer = that.renderer, rect, i, rects = []; that._panesBackgroundGroup && that._panesBackgroundGroup.clear(); for (i = 0; i < that.panes.length; i++) { backgroundColor = that.panes[i].backgroundColor || defaultBackgroundColor; if (!backgroundColor || backgroundColor === 'none') { rects.push(null); continue } rect = renderer.createRect(0, 0, 0, 0, 0, { fill: backgroundColor, strokeWidth: 0 }).append(that._panesBackgroundGroup); rects.push(rect) } that.panesBackground = rects; that._panesBackgroundGroup.append() }, _fillPanesBackground: function() { var that = this, bc; _each(that.panes, function(i, pane) { bc = pane.borderCoords; if (that.panesBackground[i] != null) that.panesBackground[i].applySettings({ x: bc.left, y: bc.top, width: bc.width, height: bc.height }) }) }, _calcPaneBorderCoords: function(pane, rotated) { var canvas = pane.canvas, bc = pane.borderCoords = pane.borderCoords || {}; bc.left = canvas.left; bc.top = canvas.top; bc.right = canvas.width - canvas.right; bc.bottom = canvas.height - canvas.bottom; bc.width = Math.max(bc.right - bc.left, 0); bc.height = Math.max(bc.bottom - bc.top, 0) }, _drawPanesBorders: function(panesBorderOptions) { var that = this, rotated = that.themeManager.getOptions('rotated'); that._panesBorderGroup && (that._panesBorderGroup.detach(), that._panesBorderGroup.clear()); _each(that.panes, function(i, pane) { var bc, borderOptions = panesBorderOptions[pane.name], attr = { fill: 'none', stroke: borderOptions.color, strokeOpacity: borderOptions.opacity, strokeWidth: borderOptions.width, dashStyle: borderOptions.dashStyle }; that._calcPaneBorderCoords(pane, rotated); if (!borderOptions.visible) return; bc = pane.borderCoords; that.renderer.createSegmentRect(bc.left, bc.top, bc.width, bc.height, 0, borderOptions, attr).append(that._panesBorderGroup) }); that._panesBorderGroup.append() }, _createClipRect: function(clipArray, index, left, top, width, height) { var that = this, clipRect = clipArray[index]; if (!clipRect) { clipRect = that.renderer.createClipRect(left, top, width, height); clipArray[index] = clipRect } else clipRect.updateRectangle({ x: left, y: top, width: width, height: height }); clipRect.append() }, _createClipRectsForPanes: function() { var that = this, canvas = that.canvas; _each(that.panes, function(i, pane) { var hasFinancialSeries = false, bc = pane.borderCoords, left = bc.left, top = bc.top, width = bc.width, height = bc.height; that._createClipRect(that.panesClipRects, i, left, top, width, height); _each(that.series, function(_, series) { if (series.pane === pane.name && series.isFinancialSeries()) hasFinancialSeries = true }); if (hasFinancialSeries) { if (that.themeManager.getOptions('rotated')) { top = 0; height = canvas.height } else { left = 0; width = canvas.width } that._createClipRect(that.financialPanesClipRects, i, left, top, width, height) } else that.financialPanesClipRects.push(null) }) }, _getPaneIndex: function(paneName) { var paneIndex; _each(this.panes, function(index, pane) { if (pane.name === paneName) { paneIndex = index; return false } }); return paneIndex }, _getPaneBorderVisibility: function(paneIndex) { var commonPaneBorderVisible = this.themeManager.getOptions('commonPaneSettings').border.visible, pane = this.panes[paneIndex] || {}, paneBorder = pane.border || {}; return 'visible' in paneBorder ? paneBorder.visible : commonPaneBorderVisible }, _getElementsClipRectID: function(paneName) { return this.panesClipRects[this._getPaneIndex(paneName)].id }, _getTranslator: function(paneName, axisName) { var paneTrans = this.translators[paneName], foundTranslator = null; if (!paneTrans) return foundTranslator; foundTranslator = paneTrans[axisName]; if (!foundTranslator) _each(paneTrans, function(axis, trans) { foundTranslator = trans; return false }); return foundTranslator }, _getCanvasForPane: function(paneName) { var panes = this.panes, panesNumber = panes.length, i; for (i = 0; i < panesNumber; i++) if (panes[i].name === paneName) return panes[i].canvas }, _getBusinessRange: function(paneName, axisName) { var ranges = this.businessRanges || [], rangesNumber = ranges.length, foundRange, i; for (i = 0; i < rangesNumber; i++) if (ranges[i].val.pane === paneName && ranges[i].val.axis === axisName) { foundRange = ranges[i]; break } if (!foundRange) for (i = 0; i < rangesNumber; i++) if (ranges[i].val.pane === paneName) { foundRange = ranges[i]; break } return foundRange }, _handleSeriesPopulated: function(needRedraw) { var that = this; that._processSeriesFamilies(); that._createLegend(); that._populateBusinessRange(); that._processValueAxisFormat(); that._updateTracker(); that._endLoading(function() { needRedraw && that._render({force: true}) }) }, _processValueAxisFormat: function() { var that = this, valueAxes = that._valueAxes, axesWithFullStackedFormat = []; _each(that.series, function() { if (this.isFullStackedSeries() && $.inArray(this.axis, axesWithFullStackedFormat) === -1) axesWithFullStackedFormat.push(this.axis) }); _each(valueAxes, function() { if ($.inArray(this.name, axesWithFullStackedFormat) !== -1) this.setPercentLabelFormat(); else this.resetAutoLabelFormat() }) }, zoomArgument: function(min, max) { var that = this, zoomArg = that._argumentAxes[0].adjustZoomValues(min, max); that._zoomMinArg = zoomArg.min; that._zoomMaxArg = zoomArg.max; that._render({ force: true, drawTitle: false, drawLegend: false, adjustAxes: false, animate: false, adjustSeriesLabels: false, asyncSeriesRendering: false }) } }) })(jQuery, DevExpress); /*! Module viz-charts, file pieChart.js */ (function($, DX, undefined) { var core = DX.viz.core, charts = DX.viz.charts, utils = DX.utils; charts.PieChart = charts.BaseChart.inherit({ _createThemeManager: function() { return charts.factory.createThemeManager(this.option(), "pie") }, _reinit: function(needRedraw) { var that = this; that.callBase(); if (!that.series) that._dataSpecificInit(); that._endLoading(function() { needRedraw && that._render({force: true}) }) }, _populateBusinessRange: function() { var businessRanges = [], series = this.series, singleSeries = series[0], range, singleSeriesRange; this._disposeObjectsInArray("businessRanges"); if (singleSeries) { range = new core.Range({series: singleSeries}); singleSeriesRange = singleSeries.getRangeData(); range = range.addRange(singleSeriesRange.val); if (!range.isDefined()) range.setStubData(); businessRanges.push(range) } this.businessRanges = businessRanges }, _seriesVisibilytyChanged: function() { this.series[0].arrangePoints(); this._populateBusinessRange(); this._refresh() }, _createTranslator: function(range) { return core.CoreFactory.createTranslator1D(range.min, range.max, 360, 0) }, _populateSeries: function() { var that = this, renderer = that.renderer, themeManager = that.themeManager, hasSeriesTemplate = !!themeManager.getOptions("seriesTemplate"), seriesOptions = hasSeriesTemplate ? that._templatedSeries : that.option("series"), allSeriesOptions = $.isArray(seriesOptions) ? seriesOptions : seriesOptions ? [seriesOptions] : [], data, particularSeriesOptions, particularSeries, seriesTheme; that._disposeSeries(); that.series = []; themeManager.resetPalette(); if (allSeriesOptions.length) { particularSeriesOptions = $.extend(true, {}, allSeriesOptions[0]); if (particularSeriesOptions.type && !utils.isString(particularSeriesOptions.type)) particularSeriesOptions.type = ""; data = particularSeriesOptions.data; particularSeriesOptions.data = null; particularSeriesOptions.incidentOccured = that._incidentOccured; seriesTheme = themeManager.getOptions("series", particularSeriesOptions, true); seriesTheme.seriesGroup = that._seriesGroup; seriesTheme.trackerGroup = that._trackerGroup; seriesTheme.seriesLabelsGroup = that._labelsGroup; seriesTheme.seriesTrackerGroup = that._seriesTrackerGroup; seriesTheme.markerTrackerGroup = that._markerTrackerGroup; seriesTheme.visibilityChanged = $.proxy(this._seriesVisibilytyChanged, this); seriesTheme.customizePoint = themeManager.getOptions("customizePoint"); seriesTheme.customizeLabel = themeManager.getOptions("customizeLabel"); particularSeries = core.CoreFactory.createSeries(renderer, seriesTheme); if (!particularSeries.isUpdated) that._incidentOccured("E2101", [seriesTheme.type]); else { that._processSingleSeries(particularSeries); that.series.push(particularSeries) } particularSeriesOptions.data = data } return that.series }, _processSingleSeries: function(singleSeries) { singleSeries.arrangePoints() }, _handleSeriesPopulated: function(needRedraw) { var that = this; that._populateBusinessRange(); that._createLegend(); that._updateTracker(); that._endLoading(function() { needRedraw && that._render({ force: true, recreateCanvas: true }) }) }, _createLegend: function() { var that = this, legendOptions = that.themeManager.getOptions("legend"), data = $.map(that.series[0] ? that.series[0].getPoints() : [], function(item) { return { text: item.argument, color: item.getColor(), id: item.index, states: item.getLegendStyles() } }); legendOptions._incidentOccured = that._incidentOccured; that.legend = core.CoreFactory.createLegend(data, legendOptions, that.renderer, that._legendGroup) }, _render: function(drawOptions) { var that = this, singleSeries = that.series && that.series[0], layoutManager = that.layoutManager, hideLayoutLabels; drawOptions = that._prepareDrawOptions(drawOptions); that.callBase(drawOptions); if (that.stopRedraw) { that.stopRedraw = false; return } that._renderTitleAndLegend(drawOptions); if (layoutManager.needMoreSpaceForPanesCanvas([that])) { layoutManager.updateDrawnElements([], [], that.canvas, that.dirtyCanvas, [that]); if (that.chartTitle) that.layoutManager.correctSizeElement(that.chartTitle, that.canvas); that._updateCanvasClipRect(that.dirtyCanvas) } layoutManager.placeDrawnElements(that.canvas); if (singleSeries) { hideLayoutLabels = layoutManager.needMoreSpaceForPanesCanvas([that]) && !that.themeManager.getOptions("adaptiveLayout").keepLabels; layoutManager.applyPieChartSeriesLayout(that.canvas, singleSeries, true); that._seriesGroup.append(); that._labelsGroup.append(); singleSeries.canvas = that.canvas; singleSeries.resetLabelEllipsis(); singleSeries.draw(that._createTranslator(that.businessRanges[0], that.canvas), drawOptions.animate && that.renderer.animationEnabled(), hideLayoutLabels); if (singleSeries.redraw) { that.renderer.stopAllAnimations(true); layoutManager.applyPieChartSeriesLayout(that.canvas, singleSeries, hideLayoutLabels); singleSeries.draw(that._createTranslator(that.businessRanges[0], that.canvas), drawOptions.animate && that.renderer.animationEnabled(), hideLayoutLabels) } that._tooltipGroup.append(); that._trackerGroup.append(); that._createTooltip(); singleSeries.drawTrackers(); that.tracker._prepare("pieChart") } that._dataSource && that._dataSource.isLoaded() && !drawOptions.isResize && that.hideLoadingIndicator(); that._drawn(); that._handleRenderComplete() }, getSeries: function getSeries() { return this.series && this.series[0] } }) })(jQuery, DevExpress); /*! Module viz-charts, file layoutManager.js */ (function($, DX, undefined) { var isNumber = DX.utils.isNumber, math = Math, decreaseGaps = DevExpress.viz.core.utils.decreaseGaps, CONNECTOR_MARGIN = 10, round = math.round; DX.viz.charts.LayoutManager = DX.Class.inherit(function() { var ctor = function(options) { this.verticalElements = []; this.horizontalElements = []; this._options = options }; var update = function(chart) { this.chart = chart; setCanvasValues(chart && chart.canvas) }; var dispose = function() { this.chart = null }; var setCanvasValues = function(canvas) { if (canvas) { canvas.originalTop = canvas.top; canvas.originalBottom = canvas.bottom; canvas.originalLeft = canvas.left; canvas.originalRight = canvas.right } }; var placeElementAndCutCanvas = function(elements, canvas) { $.each(elements, function(_, element) { var shiftX, shiftY, options = element.getLayoutOptions(), length = getLength(options.cutLayoutSide); if (!options.width) return; switch (options.horizontalAlignment) { case"left": shiftX = canvas.left; break; case"center": shiftX = (canvas.width - canvas.left - canvas.right - options.width) / 2 + canvas.left; break; case"right": shiftX = canvas.width - canvas.right - options.width; break } switch (options.verticalAlignment) { case"top": shiftY = canvas.top; break; case"bottom": shiftY = canvas.height - canvas.bottom - options.height; break } element.shift(round(shiftX), round(shiftY)); canvas[options.cutLayoutSide] += options[length]; setCanvasValues(canvas) }) }; var drawElements = function(elements, canvas) { var that = this, verticalElements = that.verticalElements = [], horizontalElements = that.horizontalElements = []; $.each(elements, function(_, element) { var freeHeight = canvas.height - canvas.top - canvas.bottom, freeWidth = canvas.width - canvas.left - canvas.right, options, length, arrayElements; element.setSize({ height: freeHeight, width: freeWidth }); element.draw(); options = element.getLayoutOptions(); length = getLength(options.cutLayoutSide); arrayElements = length === "width" ? horizontalElements : verticalElements; arrayElements.push(element); canvas[options.cutLayoutSide] += options[length]; setCanvasValues(canvas) }) }; var getLength = function(side) { var length = "height"; if (side === "left" || side === "right") length = "width"; return length }; var updatePanesCanvases = function(panes, canvas, rotated) { var pane, i, paneSpaceHeight = canvas.height - canvas.top - canvas.bottom, paneSpaceWidth = canvas.width - canvas.left - canvas.right, weightSum = 0, padding = panes.padding || 10; for (i = 0; i < panes.length; i++) { pane = panes[i]; pane.weight = pane.weight || 1; weightSum = weightSum + pane.weight } rotated ? createPanes(panes, paneSpaceWidth, "left", "right") : createPanes(panes, paneSpaceHeight, "top", "bottom"); function createPanes(panes, paneSpace, startName, endName) { var distributedSpace = 0, oneWeight = (paneSpace - padding * (panes.length - 1)) / weightSum; $.each(panes, function(_, pane) { var calcLength = round(pane.weight * oneWeight); pane.canvas = pane.canvas || {}; $.extend(pane.canvas, { deltaLeft: 0, deltaRight: 0, deltaTop: 0, deltaBottom: 0 }, canvas); pane.canvas[startName] = canvas[startName] + distributedSpace; pane.canvas[endName] = canvas[endName] + (paneSpace - calcLength - distributedSpace); distributedSpace = distributedSpace + calcLength + padding; setCanvasValues(pane.canvas) }) } }; var applyPieChartSeriesLayout = function(canvas, singleSeries, hideLayoutLabels) { var paneSpaceHeight = canvas.height - canvas.top - canvas.bottom, paneSpaceWidth = canvas.width - canvas.left - canvas.right, paneCenterX = paneSpaceWidth / 2 + canvas.left, paneCenterY = paneSpaceHeight / 2 + canvas.top, accessibleRadius = Math.min(paneSpaceWidth, paneSpaceHeight) / 2, minR = 0.7 * accessibleRadius, innerRadius = getInnerRadius(singleSeries); if (!hideLayoutLabels) $.each(singleSeries.getPoints(), function(_, point) { if (point._label.hasText() && point.isVisible()) { var labelBBox = point._label._getOutsideGroupLabelPosition(), nearestX = getNearestCoord(labelBBox.x, labelBBox.x + labelBBox.width, paneCenterX), nearestY = getNearestCoord(labelBBox.y, labelBBox.y + labelBBox.height, paneCenterY), minRadiusWithLabels = Math.max(getLengthFromCenter(nearestX, nearestY) - CONNECTOR_MARGIN, minR); accessibleRadius = Math.min(accessibleRadius, minRadiusWithLabels) } point._label.setPosition(point._label.originalPosition) }); else $.each(singleSeries.getPoints(), function(_, point) { if (singleSeries.getOptions().label.position === "inside") return false; point._label.originalPosition = point._label.getPosition(); point._label.setPosition('outside') }); singleSeries.correctPosition({ centerX: math.floor(paneCenterX), centerY: math.floor(paneCenterY), radiusInner: math.floor(accessibleRadius * innerRadius), radiusOuter: math.floor(accessibleRadius) }); function getNearestCoord(firstCoord, secondCoord, pointCenterCoord) { var nearestCoord; if (pointCenterCoord < firstCoord) nearestCoord = firstCoord; else if (secondCoord < pointCenterCoord) nearestCoord = secondCoord; else nearestCoord = pointCenterCoord; return nearestCoord } function getLengthFromCenter(x, y) { return Math.sqrt(Math.pow(x - paneCenterX, 2) + Math.pow(y - paneCenterY, 2)) } function getInnerRadius(series) { var innerRadius; if (singleSeries.type === 'pie') innerRadius = 0; else { innerRadius = singleSeries.innerRadius; if (!isNumber(innerRadius)) innerRadius = 0.5; else { innerRadius = Number(innerRadius); if (innerRadius < 0.2) innerRadius = 0.2; if (innerRadius > 0.8) innerRadius = 0.8 } } return innerRadius } }; var isValidBox = function isValidBox(box) { return !!(box.x || box.y || box.width || box.height) }; var correctDeltaMarginValue = function(panes, marginSides) { var axisPanePosition, canvasCell, canvas, deltaSide, requireAxesRedraw; $.each(panes, function(_, pane) { canvas = pane.canvas; $.each(marginSides, function(_, side) { deltaSide = 'delta' + side; canvas[deltaSide] = Math.max(canvas[deltaSide] - (canvas[side.toLowerCase()] - canvas['original' + side]), 0); if (canvas[deltaSide] > 0) requireAxesRedraw = true }) }); return requireAxesRedraw }; var getPane = function getPane(name, panes) { var findPane = panes[0]; $.each(panes, function(_, pane) { if (name === pane.name) findPane = pane }); return findPane }; var applyAxesLayout = function(axes, panes, rotated) { var that = this, canvas, axisPanePosition, axisPosition, canvasCell, box, delta, axis, axisLength, direction, directionMultiplier, someDirection = [], pane, i; $.each(panes, function(_, pane) { $.extend(pane.canvas, { deltaLeft: 0, deltaRight: 0, deltaTop: 0, deltaBottom: 0 }) }); for (i = 0; i < axes.length; i++) { axis = axes[i]; axisPosition = axis.options.position || 'left'; axis.delta = {}; box = axis.getBoundingRect(); pane = getPane(axis.pane, panes); canvas = pane.canvas; if (!isValidBox(box)) continue; direction = "delta" + axisPosition.slice(0, 1).toUpperCase() + axisPosition.slice(1); switch (axisPosition) { case"right": directionMultiplier = 1; canvas.deltaLeft += axis.padding ? axis.padding.left : 0; break; case"left": directionMultiplier = -1; canvas.deltaRight += axis.padding ? axis.padding.right : 0; break; case"top": directionMultiplier = -1; canvas.deltaBottom += axis.padding ? axis.padding.bottom : 0; break; case"bottom": directionMultiplier = 1; canvas.deltaTop += axis.padding ? axis.padding.top : 0; break } switch (axisPosition) { case"right": case"left": if (!box.isEmpty) { delta = box.y + box.height - (canvas.height - canvas.originalBottom); if (delta > 0) { that.requireAxesRedraw = true; canvas.deltaBottom += delta } delta = canvas.originalTop - box.y; if (delta > 0) { that.requireAxesRedraw = true; canvas.deltaTop += delta } } axisLength = box.width; someDirection = ['Left', 'Right']; break; case"top": case"bottom": if (!box.isEmpty) { delta = box.x + box.width - (canvas.width - canvas.originalRight); if (delta > 0) { that.requireAxesRedraw = true; canvas.deltaRight += delta } delta = canvas.originalLeft - box.x; if (delta > 0) { that.requireAxesRedraw = true; canvas.deltaLeft += delta } } someDirection = ['Bottom', 'Top']; axisLength = box.height; break } if (!axis.delta[axisPosition] && canvas[direction] > 0) canvas[direction] += axis.getMultipleAxesSpacing(); axis.delta[axisPosition] = axis.delta[axisPosition] || 0; axis.delta[axisPosition] += canvas[direction] * directionMultiplier; canvas[direction] += axisLength } that.requireAxesRedraw = correctDeltaMarginValue(panes, someDirection) || that.requireAxesRedraw; this.stopDrawAxes = applyFoundExceedings(panes, rotated) }; var applyVerticalAxesLayout = function(axes) { var chart = this.chart; this.applyAxesLayout(axes, chart.panes, chart.option('rotated')) }; var applyHorizontalAxesLayout = function(axes) { var chart = this.chart; axes.reverse(); this.applyAxesLayout(axes, chart.panes, chart.option('rotated')); axes.reverse() }; var placeDrawnElements = function(canvas) { var that = this, horizontalElements = that.horizontalElements, verticalElements = that.verticalElements; correctElementsPosition(horizontalElements, 'width'); placeElementAndCutCanvas(horizontalElements, canvas); correctElementsPosition(verticalElements, 'height'); placeElementAndCutCanvas(verticalElements, canvas); function correctElementsPosition(elements, direction) { $.each(elements, function(_, element) { var options = element.getLayoutOptions(), side = options.cutLayoutSide; canvas[side] -= options[direction] }) } }; var needMoreSpaceForPanesCanvas = function(panes, rotated) { var that = this, needHorizontalSpace = 0, needVerticalSpace = 0; $.each(panes, function(_, pane) { var paneCanvas = pane.canvas, needPaneHorizonralSpace = that._options.width - (paneCanvas.width - paneCanvas.left - paneCanvas.right), needPaneVerticalSpace = that._options.height - (paneCanvas.height - paneCanvas.top - paneCanvas.bottom); if (rotated) { needHorizontalSpace += needPaneHorizonralSpace > 0 ? needPaneHorizonralSpace : 0; needVerticalSpace = Math.max(needPaneVerticalSpace > 0 ? needPaneVerticalSpace : 0, needVerticalSpace) } else { needHorizontalSpace = Math.max(needPaneHorizonralSpace > 0 ? needPaneHorizonralSpace : 0, needHorizontalSpace); needVerticalSpace += needPaneVerticalSpace > 0 ? needPaneVerticalSpace : 0 } }); return needHorizontalSpace > 0 || needVerticalSpace > 0 ? { width: needHorizontalSpace, height: needVerticalSpace } : false }; var updateDrawnElements = function(argumentAxis, valueAxis, canvas, dirtyCanvas, panes, rotated) { var that = this, needRemoveSpace, saveDirtyCanvas = $.extend({}, dirtyCanvas), verticalAxes = rotated ? argumentAxis : valueAxis, horizontalAxes = rotated ? valueAxis : argumentAxis; needRemoveSpace = this.needMoreSpaceForPanesCanvas(panes, rotated); if (!needRemoveSpace) return; needRemoveSpace.height = decreaseGaps(dirtyCanvas, ["top", "bottom"], needRemoveSpace.height); needRemoveSpace.width = decreaseGaps(dirtyCanvas, ["left", "right"], needRemoveSpace.width); canvas.top -= saveDirtyCanvas.top - dirtyCanvas.top; canvas.bottom -= saveDirtyCanvas.bottom - dirtyCanvas.bottom; canvas.left -= saveDirtyCanvas.left - dirtyCanvas.left; canvas.right -= saveDirtyCanvas.right - dirtyCanvas.right; updateElements(that.horizontalElements, "width", "height"); updateElements(that.verticalElements, "height", "width"); updateAxis(verticalAxes, "width"); updateAxis(horizontalAxes, "height"); function updateAxis(axes, side) { if (axes && needRemoveSpace[side] > 0) { $.each(axes, function(i, axis) { var bbox = axis.getBoundingRect(); axis.updateSize(); needRemoveSpace[side] -= bbox[side] - axis.getBoundingRect()[side] }); if (needRemoveSpace[side] > 0) $.each(axes, function(_, axis) { axis.updateSize(true) }) } } function updateElements(elements, length, otherLength) { $.each(elements, function(_, element) { var options = element.getLayoutOptions(), side = options.cutLayoutSide, freeSpaceWidth = dirtyCanvas.width - dirtyCanvas.left - dirtyCanvas.right, freeSpaceHeight = dirtyCanvas.height - dirtyCanvas.top - dirtyCanvas.bottom, updateObject = {}; element.setSize({ width: freeSpaceWidth, height: freeSpaceHeight }); updateObject[otherLength] = 0; updateObject[length] = needRemoveSpace[length]; element.changeSize(updateObject); canvas[side] -= options[length] - element.getLayoutOptions()[length]; needRemoveSpace[length] -= options[length] - element.getLayoutOptions()[length] }) } }; var correctSizeElement = function(element, canvas) { element.setSize({ width: canvas.width - canvas.right - canvas.left, height: canvas.width - canvas.right - canvas.left }); element.changeSize({ width: 0, height: 0 }) }; var applyFoundExceedings = function applyFoundExceedings(panes, rotated) { var col, row, stopDrawAxes, maxLeft = 0, maxRight = 0, maxTop = 0, maxBottom = 0, maxColNumber = 0; $.each(panes, function(_, pane) { maxLeft = Math.max(maxLeft, pane.canvas.deltaLeft); maxRight = Math.max(maxRight, pane.canvas.deltaRight); maxTop = Math.max(maxTop, pane.canvas.deltaTop); maxBottom = Math.max(maxBottom, pane.canvas.deltaBottom) }); if (rotated) $.each(panes, function(_, pane) { pane.canvas.top += maxTop; pane.canvas.bottom += maxBottom; pane.canvas.right += pane.canvas.deltaRight; pane.canvas.left += pane.canvas.deltaLeft }); else $.each(panes, function(_, pane) { pane.canvas.top += pane.canvas.deltaTop; pane.canvas.bottom += pane.canvas.deltaBottom; pane.canvas.right += maxRight; pane.canvas.left += maxLeft }); $.each(panes, function(_, pane) { if (pane.canvas.top + pane.canvas.bottom > pane.canvas.height) stopDrawAxes = true; if (pane.canvas.left + pane.canvas.right > pane.canvas.width) stopDrawAxes = true }); return stopDrawAxes }; return { ctor: ctor, update: update, drawElements: drawElements, updatePanesCanvases: updatePanesCanvases, applyVerticalAxesLayout: applyVerticalAxesLayout, applyHorizontalAxesLayout: applyHorizontalAxesLayout, applyAxesLayout: applyAxesLayout, applyPieChartSeriesLayout: applyPieChartSeriesLayout, dispose: dispose, updateDrawnElements: updateDrawnElements, placeDrawnElements: placeDrawnElements, needMoreSpaceForPanesCanvas: needMoreSpaceForPanesCanvas, correctSizeElement: correctSizeElement } }()) })(jQuery, DevExpress); /*! Module viz-charts, file multiAxesSynchronizer.js */ (function($, DX, undefined) { var Range = DX.viz.core.Range, utils = DX.utils, adjustValueUtils = utils.adjustValue, applyPrecisionByMinDeltaUtils = utils.applyPrecisionByMinDelta, isDefinedUtils = utils.isDefined, math = Math, mathFloor = math.floor, mathMax = math.max, _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; if (!axis.translator._originalBusinessRange) axis.translator._originalBusinessRange = new Range(axis.translator.getBusinessRange()); else { businessRange = new Range(axis.translator._originalBusinessRange); axis.translator.updateBusinessRange(businessRange); axis.setRange(businessRange) } }; var linearConvertor = { transform: function(v, b) { return utils.getLog(v, b) }, addInterval: function(v, i) { return v + i }, getInterval: function(base, tickInterval) { return tickInterval }, adjustValue: mathFloor }; var logConvertor = { transform: function(v, b) { return utils.raiseTo(v, b) }, addInterval: function(v, i) { return v * i }, getInterval: function(base, tickInterval) { return math.pow(base, tickInterval) }, adjustValue: adjustValueUtils }; var convertAxisInfo = function(axisInfo, convertor) { if (!axisInfo.isLogarithmic) return; var base = axisInfo.logarithmicBase, tickValues = axisInfo.tickValues, tick, ticks = [], interval; axisInfo.minValue = convertor.transform(axisInfo.minValue, base); axisInfo.oldMinValue = convertor.transform(axisInfo.oldMinValue, base); axisInfo.maxValue = convertor.transform(axisInfo.maxValue, base); axisInfo.oldMaxValue = convertor.transform(axisInfo.oldMaxValue, base); axisInfo.tickInterval = math.round(axisInfo.tickInterval); if (axisInfo.tickInterval < 1) axisInfo.tickInterval = 1; interval = convertor.getInterval(base, axisInfo.tickInterval); for (tick = convertor.adjustValue(convertor.transform(tickValues[0], base)); ticks.length < tickValues.length; tick = convertor.addInterval(tick, interval)) ticks.push(tick); ticks.tickInterval = axisInfo.tickInterval; axisInfo.tickValues = ticks }; var populateAxesInfo = function(axes) { return $.map(axes, function(axis) { restoreOriginalBusinessRange(axis); var tickValues = axis.getTickValues(), options = axis.options, minValue, maxValue, axisInfo = null, businessRange, tickInterval, synchronizedValue; if (tickValues && tickValues.length > 0 && utils.isNumber(tickValues[0]) && options.type !== 'discrete') { tickInterval = tickValues.tickInterval; businessRange = axis.translator.getBusinessRange(); minValue = businessRange.minVisible; maxValue = businessRange.maxVisible; synchronizedValue = options.synchronizedValue; if (minValue === maxValue && isDefinedUtils(synchronizedValue)) { minValue = tickValues[0] - 1; maxValue = tickValues[0] + 1; tickInterval = 1 } axisInfo = { axis: axis, isLogarithmic: options.type === 'logarithmic', logarithmicBase: businessRange.base, tickValues: tickValues, 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 = mathMax(maxTicksCount, axisInfo.tickValues.length) }); _each(axesInfo, function(_, axisInfo) { var ticksMultiplier, ticksCount, additionalStartTicksCount = 0, synchronizedValue = axisInfo.synchronizedValue, tickValues = axisInfo.tickValues, tickInterval = axisInfo.tickInterval; if (isDefinedUtils(synchronizedValue)) { axisInfo.baseTickValue = axisInfo.invertedBaseTickValue = synchronizedValue; axisInfo.tickValues = [axisInfo.baseTickValue] } else { if (tickValues.length > 1 && tickInterval) { ticksMultiplier = mathFloor((maxTicksCount + 1) / tickValues.length); ticksCount = ticksMultiplier > 1 ? mathFloor((maxTicksCount + 1) / ticksMultiplier) : maxTicksCount; additionalStartTicksCount = mathFloor((ticksCount - tickValues.length) / 2); while (additionalStartTicksCount > 0 && tickValues[0] !== 0) { tickValues.unshift(applyPrecisionByMinDeltaUtils(tickValues[0], tickInterval, tickValues[0] - tickInterval)); additionalStartTicksCount-- } while (tickValues.length < ticksCount) tickValues.push(applyPrecisionByMinDeltaUtils(tickValues[0], tickInterval, tickValues[tickValues.length - 1] + tickInterval)); axisInfo.tickInterval = tickInterval / ticksMultiplier } axisInfo.baseTickValue = tickValues[0]; axisInfo.invertedBaseTickValue = tickValues[tickValues.length - 1] } }) }; var getAxisRange = function(axisInfo) { return axisInfo.maxValue - axisInfo.minValue || 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 && isDefinedUtils(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 = mathMax(startPadding, inverted ? maxPadding : minPadding); endPadding = mathMax(endPadding, inverted ? minPadding : maxPadding) }); return { start: startPadding, end: endPadding } }; var correctMinMaxValuesByPaddings = function(axesInfo, paddings) { _each(axesInfo, function(_, info) { var range = getAxisRange(info), inverted = info.inverted; info.minValue -= paddings[inverted ? 'end' : 'start'] * range; info.maxValue += paddings[inverted ? 'start' : 'end'] * range; if (range > MIN_RANGE_FOR_ADJUST_BOUNDS) { info.minValue = math.min(info.minValue, adjustValueUtils(info.minValue)); info.maxValue = mathMax(info.maxValue, adjustValueUtils(info.maxValue)) } }) }; var updateTickValuesIfSyncronizedValueUsed = function(axesInfo) { var hasSyncronizedValue = false; _each(axesInfo, function(_, info) { hasSyncronizedValue = hasSyncronizedValue || isDefinedUtils(info.synchronizedValue) }); _each(axesInfo, function(_, info) { var lastTickValue, tickInterval = info.tickInterval, tickValues = info.tickValues, maxValue = info.maxValue, minValue = info.minValue; if (hasSyncronizedValue && tickInterval) { while (tickValues[0] - tickInterval >= minValue) tickValues.unshift(adjustValueUtils(tickValues[0] - tickInterval)); lastTickValue = tickValues[tickValues.length - 1]; while ((lastTickValue = lastTickValue + tickInterval) <= maxValue) tickValues.push(utils.isExponential(lastTickValue) ? adjustValueUtils(lastTickValue) : utils.applyPrecisionByMinDelta(minValue, tickInterval, lastTickValue)) } while (tickValues[0] < minValue) tickValues.shift(); while (tickValues[tickValues.length - 1] > maxValue) tickValues.pop() }) }; var applyMinMaxValues = function(axesInfo) { _each(axesInfo, function(_, info) { var axis = info.axis, range = axis.translator.getBusinessRange(); if (range.min === range.minVisible) range.min = info.minValue; if (range.max === range.maxVisible) range.max = info.maxValue; range.minVisible = info.minValue; range.maxVisible = info.maxValue; if (isDefinedUtils(info.stubData)) range.stubData = info.stubData; if (range.min > range.minVisible) range.min = range.minVisible; if (range.max < range.maxVisible) range.max = range.maxVisible; axis.translator.updateBusinessRange(range); axis.setRange(range); axis.setTickValues(info.tickValues) }) }; var correctAfterSynchronize = function(axesInfo) { var invalidAxisInfo = [], correctValue, validAxisInfo; _each(axesInfo, function(i, info) { if (info.oldMaxValue - info.oldMinValue === 0) invalidAxisInfo.push(info); else if (!isDefinedUtils(correctValue) && !isDefinedUtils(info.synchronizedValue)) { correctValue = math.abs((info.maxValue - info.minValue) / (info.tickValues[mathFloor(info.tickValues.length / 2)] || info.maxValue)); validAxisInfo = info } }); if (!isDefinedUtils(correctValue)) return; _each(invalidAxisInfo, function(i, info) { var firstTick = info.tickValues[0], correctedTick = firstTick * correctValue, tickValues = validAxisInfo.tickValues, centralTick = tickValues[mathFloor(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) { var charts = DX.viz.charts, eventsConsts = DX.viz.core.series.helpers.consts.events, utils = DX.utils, isFunction = utils.isFunction, isDefined = utils.isDefined, MULTIPLE_MODE = 'multiple', SINGLE_MODE = 'single', ALL_ARGUMENTS_POINTS_MODE = 'allargumentpoints', ALL_SERIES_POINTS_MODE = 'allseriespoints', msPointerEnabled = window.navigator.msPointerEnabled && window.navigator.msMaxTouchPoints || window.navigator.pointerEnabled && window.navigator.maxTouchPoints || null, MOUSE_EVENT_LOCK_TIMEOUT = 1000, CLICK_EVENT_LOCK_TIMEOUT = 600, HOVER_START_DELAY = 100, HOVER_HOLD_DELAY = 200, TOOLTIP_HOLD_TIMEOUT = 400, NONE_MODE = 'none'; var processMode = function(mode) { return (mode + "").toLowerCase() }; charts.Tracker = DX.Class.inherit({ ctor: function(options) { this.__HOVER_HOLD_DELAY = HOVER_HOLD_DELAY; this.__TOOLTIP_HOLD_TIMEOUT = TOOLTIP_HOLD_TIMEOUT; this.__HOVER_START_DELAY = HOVER_START_DELAY; var that = this, events = options.events = options.events || {}, getEventHandler = function(func) { return func && func.call ? function() { var eventContext = this, eventArgs = arguments; setTimeout(function() { func.apply(eventContext, eventArgs) }) } : null }; that._reinit(options); that.pointSelectionMode = that._prepareMode(options.pointSelectionMode); that.seriesSelectionMode = that._prepareMode(options.seriesSelectionMode); that.hoverStartDelay = 0; that.sensitivity = 7; if (that.pointSelectionMode === MULTIPLE_MODE) { that._releaseSelectedPoint = that._releaseSelectedPointMultiMode; that.selectedPoint = [] } else that._releaseSelectedPoint = that._releaseSelectedPointSingleMode; if (that.seriesSelectionMode === MULTIPLE_MODE) { that._releaseSelectedSeries = that._releaseSelectedSeriesMultiMode; that.selectedSeries = [] } else that._releaseSelectedSeries = that._releaseSelectedSeriesSingleMode; that.tooltipEnabled = options.tooltipEnabled; that.tooltipShown = options.tooltipShown; that.tooltipHidden = options.tooltipHidden; that.seriesClick = getEventHandler(events.seriesClick); that.pointClick = getEventHandler(events.pointClick); that.legendClick = getEventHandler(events.legendClick); that.argumentAxisClick = getEventHandler(events.argumentAxisClick); that.seriesHover = getEventHandler(events.seriesHover); that.seriesSelected = getEventHandler(events.seriesSelected); that.pointHover = getEventHandler(events.pointHover); that.seriesSelectionChanged = getEventHandler(events.seriesSelectionChanged); that.pointSelectionChanged = getEventHandler(events.pointSelectionChanged); that.seriesHoverChanged = getEventHandler(events.seriesHoverChanged); that.pointHoverChanged = getEventHandler(events.pointHoverChanged); that.pointSelected = getEventHandler(events.pointSelected); that.renderer = options.renderer; that.seriesTrackerGroup = options.seriesTrackerGroup; that.markerTrackerGroup = options.markerTrackerGroup; that.seriesGroup = options.seriesGroup; that.seriesGroup.on(eventsConsts.selectSeries, {tracker: that}, that._selectSeries); that.seriesGroup.on(eventsConsts.deselectSeries, {tracker: that}, that._deselectSeries); that.seriesGroup.on(eventsConsts.selectPoint, {tracker: that}, that._selectPoint); that.seriesGroup.on(eventsConsts.deselectPoint, {tracker: that}, that._deselectPoint); that.seriesGroup.on(eventsConsts.showPointTooltip, {tracker: that}, that._showPointTooltip); that.seriesGroup.on(eventsConsts.hidePointTooltip, {tracker: that}, that._hidePointTooltip); that.crossHairOptions = options.crossHairOptions }, _clean: function() { var that = this; that.selectedPoint = that.pointSelectionMode === MULTIPLE_MODE ? [] : null; that.selectedSeries = that.seriesSelectionMode === MULTIPLE_MODE ? [] : null; that.hoveredPoint = null; that.hoveredSeries = null; that._hideTooltip(that.pointAtShownTooltip); that._clearTimeouts() }, _reinit: function(options) { var that = this; options = options || {}; if (that.storedSeries !== options.series) { that.storedSeries = options.series || []; that._clean() } else if (isDefined(that.storedSeries)) { that._clearPointSelection(); that._clearHover(that); that._clearTimeouts() } that.argumentAxis = options.argumentAxis || []; that.legendGroup = options.legendGroup; that.legendCallback = options.legendCallback || $.noop }, _clearTimeouts: function() { var that = this, _clearTimeout = clearTimeout; _clearTimeout(that.tooltipHoldTimeout); _clearTimeout(that.cmpCoordTimeout); _clearTimeout(that.hoverStartTimeOut); _clearTimeout(that.hoverHoldTimeOut) }, dispose: function() { var that = this; that._clearTimeouts(); clearTimeout(that.unlockMouseTimer); clearTimeout(that.lockClickTimer); $.each(that.argumentAxis, function(_, axis) { axis._axisElementsGroup && axis._axisElementsGroup.off() }); that.seriesTrackerGroup.off(); that.markerTrackerGroup.off(); that.legendGroup && that.legendGroup.off(); that.seriesGroup.off(); that.rootTracker && that.rootTracker.off(); that.argumentAxis = null; that.seriesTrackerGroup = null; that.markerTrackerGroup = null; that.legendGroup = null; that.legendCallback = null; that.seriesGroup = null; that.crossHairOptions = null; that.selectedPoint = null; that.selectedSeries = null; that.hoveredSeries = null; that.hoveredPoint = null; that.storedSeries = null; that.argumentAxis = null; that.hoveredObject = null; that.pointAtShownTooltip = null }, _prepareMode: function(mode) { mode = (mode || '').toLowerCase(); return mode = mode !== SINGLE_MODE && mode !== MULTIPLE_MODE ? SINGLE_MODE : mode }, _prepare: function(typeChart) { var that = this; that.rootTracker = that.renderer.getRoot(); $.each(that.argumentAxis, function(_, axis) { axis._axisElementsGroup && that._eventHandler(axis._axisElementsGroup, { parser: that._getOptionsAxis, condition: that._axisCondition, execute: that._axisEvent }, { tracker: that, axis: axis }) }); that._eventHandler(that.seriesTrackerGroup, { parser: that._getOptionsPointSeries, condition: that._seriesCondition, execute: that._seriesEvent }, {tracker: that}); that._eventHandler(that.markerTrackerGroup, { parser: that._getOptionsPointSeries, condition: that._pointCondition, execute: that._pointEvent }, {tracker: that}); that.legendGroup && that._eventHandler(that.legendGroup, { parser: that._getLegendData(typeChart), condition: that._seriesCondition, execute: that._getLegendEvent(typeChart) }, {tracker: that}); that._eventHandler(that.rootTracker, { parser: that._getOptionsCrossHair, execute: that._crossHairEvent }, {tracker: that}) }, _getLegendData: function(typeChart) { return function(event) { var target = $(event.target), itemIndex = target.data('itemIndex'), that = event.data.tracker, mode = utils.isNumber(itemIndex) && target.data('mode'); if (event.type === 'mousemove') return [that, event.pageX, event.pageY, event.offsetX, event.offsetY]; if (!utils.isNumber(itemIndex)) return null; if (typeChart === 'pieChart') return [that, that.storedSeries[0].getPoints()[itemIndex], mode, event]; else return [that, that.storedSeries[itemIndex], mode, event] } }, _getLegendEvent: function(typeChart) { var that = this, legendEvent; if (typeChart === 'pieChart') legendEvent = $.extend({}, this._pointEvent, { touchend: function(that, point, mode, event) { if (!that.showHoldTooltip) that._legendClick(that, point, true, event) || that._pointClick(that, point, true, event); clearTimeout(that.tooltipHoldTimeout); that._clickLock(that); that._clearHover(that) }, click: function(that, point, mode, event) { that._legendClick(that, point, false, event) || that._pointClick(that, point, false, event) } }); else legendEvent = $.extend({}, this._seriesEvent, { click: function(that, series, mode, event) { that._legendClick(that, series, false, event) || that._seriesClick(that, series, false, event) }, touchend: function(that, series, mode, event) { that._legendClick(that, series, true, event) || that._seriesClick(that, series, true, event); that._clickLock(that) } }); this.__legendEvent = legendEvent; return legendEvent }, _eventHandler: function(group, handlers, data) { var prepareHandlers = this._designerHandlers(handlers); group.off(".dxc-tracker"); group.on(prepareHandlers, data) }, _designerHandlers: function(handler) { var handlers = {}, parser = handler.parser, condition = handler.condition, execute = handler.execute, designerHandle = function(eventType, func) { if (condition && condition[eventType] === null) return; handlers[eventType + ".dxc-tracker"] = function(event) { var options = parser ? parser(event) : event; if (!options) return; if (condition && condition[eventType] && condition[eventType].call) condition[eventType].apply(null, options.concat([func])); else func.apply(null, options) } }; $.each(execute, designerHandle); return handlers }, _getOptionsCrossHair: function(event) { var that = event.data.tracker; var rootOffset = utils.getRootOffset(that.renderer); var xe = event.pageX - rootOffset.left; var ye = event.pageY - rootOffset.top; return [that, xe, ye] }, _getOptionsPointSeries: function(event) { var object = $(event.target).data('point') || $(event.target).data('series'), that = event.data.tracker, mode = object && processMode($(event.target).data('mode') || object.getOptions().hoverMode); if (event.type === 'mousemove') return [that, event.pageX, event.pageY, event.offsetX, event.offsetY]; if (!object) return null; return [that, object, mode, event] }, _getOptionsAxis: function(event) { var that = event.data.tracker, axis = event.data.axis, mode = axis.options.hoverMode, argument; if (event.target.tagName === "tspan") argument = $(event.target).parent().data('argument'); else argument = $(event.target).data('argument'); if (event.type === 'mousemove') return [that, event.pageX, event.pageY]; if (!axis) return null; return [that, axis, mode, argument, event] }, _pointEvent: { mouseover: function(that, point, mode) { if (that.mouseLocked) return; that._setHoveredPoint(point, mode); if (that.tooltipEnabled && point && point.getOptions()) that._compareCoords(that, function() { that._showTooltip(that.tooltip, point) }) }, mouseout: function(that, point, mode) { if (that.mouseLocked) return; that._clearHover(that) }, touchmove: function(that, point, mode) { clearTimeout(that.tooltipHoldTimeout); that.tooltipHoldTimeout = null; that.showHoldTooltip = true }, mousemove: function(that, pageX, pageY, offsetX, offsetY) { that._setCurCoords(that, pageX, pageY) }, touchstart: function(that, point, mode) { that.showHoldTooltip = false; that._mouseLock(that); if (that.tooltipEnabled) that.tooltipHoldTimeout = setTimeout(function() { that.showHoldTooltip = true; that._showTooltip(that.tooltip, point) }, TOOLTIP_HOLD_TIMEOUT) }, touchend: function(that, point, mode, event) { if (!that.showHoldTooltip) that._pointClick(that, point, true, event); clearTimeout(that.tooltipHoldTimeout); that._clickLock(that); that._clearHover(that) }, click: function(that, point, mode, event) { that._pointClick(that, point, false, event) }, mousedown: function(that, point, mode) { that._pointEvent.touchstart(that, point, mode) }, mouseup: function(that, point, mode, event) { that._pointEvent.touchend(that, point, mode, event) } }, _pointCondition: { mouseover: function(that, point, mode, event, func) { if (mode === ALL_ARGUMENTS_POINTS_MODE && that.hoveredPoint && that.hoveredPoint.argument === point.argument) { that.hoverHoldTimeOut = clearTimeout(that.hoverHoldTimeOut); that.hoveredObject = point; func(that, point, mode); return } that._setHover(that, point, mode, func) }, mouseout: function(that, point, mode, event, func) { that._releaseHover(that, point, mode, func) }, touchstart: !msPointerEnabled, touchend: !msPointerEnabled, mousedown: msPointerEnabled, mouseup: msPointerEnabled }, _seriesEvent: { mouseover: function(that, series, mode) { if (that.mouseLocked) return; that._setHoveredSeries(series, mode) }, mouseout: function(that, series, mode) { that._clearHover(that) }, mousemove: function(that, pageX, pageY, offsetX, offsetY) { that._setCurCoords(that, pageX, pageY) }, touchstart: function(that) { that._mouseLock(that) }, touchend: function(that, series, _, event) { that._seriesClick(that, series, true, event); that._clickLock(that) }, click: function(that, series, mode, event) { that._seriesClick(that, series, false, event) }, mousedown: function(that, point, mode) { that._seriesEvent.touchstart(that, point, mode) }, mouseup: function(that, point, mode) { that._seriesEvent.touchend(that, point, mode) } }, _crossHairEvent: { mousemove: function(that, x, y) { if (!that.eventType) { that.eventType = 'mouse'; return } else if (that.eventType === 'touch') return; else if (that.eventType === 'mouse') { that._moveCrossHair(that, x, y); that.eventType = null } }, mouseout: function(that) { that._hideCrossHair(that); that.eventType = null }, touchstart: function(that, x, y) { that.eventType = 'touch' }, touchend: function(that, x, y) { that.eventType = null }, mousedown: function(that, x, y) { that._crossHairEvent.touchstart(that, x, y) }, mouseup: function(that, x, y) { that._crossHairEvent.touchend(that, x, y) } }, _hideCrossHair: function(that) { if (!that.crossHairOptions) return; var horizontalLine = that.crossHairOptions.horizontalLine, verticalLine = that.crossHairOptions.verticalLine; horizontalLine && horizontalLine.applySettings({visibility: 'hidden'}); verticalLine && verticalLine.applySettings({visibility: 'hidden'}) }, _moveCrossHair: function(that, x, y) { if (!that.crossHairOptions) return; var horizontalLine = that.crossHairOptions.horizontalLine, verticalLine = that.crossHairOptions.verticalLine, canvas = that.crossHairOptions.canvas || {}; if (x > canvas.left && x < canvas.width - canvas.right && y > canvas.top && y < canvas.height - canvas.bottom) { horizontalLine && horizontalLine.applySettings({visibility: 'visible'}); verticalLine && verticalLine.applySettings({visibility: 'visible'}); horizontalLine && horizontalLine.applySettings({translateY: y - canvas.top}); verticalLine && verticalLine.applySettings({translateX: x - canvas.left}) } else { horizontalLine && horizontalLine.applySettings({visibility: 'hidden'}); verticalLine && verticalLine.applySettings({visibility: 'hidden'}) } }, _seriesCondition: { mouseover: function(that, series, mode, event, func) { that.hoverStartDelay = 0; that._setHover(that, series, mode, func) }, mouseout: function(that, series, mode, event, func) { that.hoverStartDelay = HOVER_START_DELAY; that._releaseHover(that, series, mode, func) }, touchstart: !msPointerEnabled, touchend: !msPointerEnabled, mousedown: msPointerEnabled, mouseup: msPointerEnabled }, _axisEvent: { mouseover: function(that, axis, argument) { if (that.mouseLocked || isDefined(that.hoveredArgument) && that.hoveredArgument === argument) return; that._clearHover(that); if (isDefined(that.hoveredArgument)) that._toAllArgumentPoints(that.hoveredArgument, 'releasePointHoverState'); that._toAllArgumentPoints(argument, 'setPointHoverState'); that.hoveredArgument = argument }, mouseout: function(that, axis) { if (that.mouseLocked || !isDefined(that.hoveredArgument)) return; that._toAllArgumentPoints(that.hoveredArgument, 'releasePointHoverState'); that.hoveredArgument = null }, mousemove: function(that, pageX, pageY) { that._setCurCoords(that, pageX, pageY) }, touchstart: function(that) { that._mouseLock(that) }, touchend: function(that, axis, mode, argument, event) { that._argumentAxisClick(that, axis, argument, true, event); that._clearHover(that); that._clickLock(that) }, click: function(that, axis, mode, argument, event) { that._clearHover(that); that._argumentAxisClick(that, axis, argument, false, event) }, mousedown: function(that) { that._axisEvent.touchstart(that) }, mouseup: function(that, axis, mode, argument, event) { that._axisEvent.touchend(that, axis, mode, argument, event) } }, _axisCondition: { mouseover: function(that, axis, mode, argument, event, func) { that._hideCrossHair(that); if (mode === ALL_ARGUMENTS_POINTS_MODE) that._setHover(that, axis, argument, func) }, mouseout: function(that, axis, mode, argument, event, func) { that._releaseHover(that, axis, argument, func) }, touchstart: !msPointerEnabled, touchend: !msPointerEnabled, mousedown: msPointerEnabled, mouseup: msPointerEnabled }, _setHover: function(that, object, mode, func) { if (object === that.hoveredObject) { that.hoverHoldTimeOut = clearTimeout(that.hoverHoldTimeOut); if (mode === object.lastHoverMode) return } if (that.mouseLocked) return; clearTimeout(that.cmpCoordTimeout); clearTimeout(that.hoverStartTimeOut); that.hoverStartTimeOut = setTimeout(function() { clearTimeout(that.hoverHoldTimeOut); that.hoveredObject = object; func(that, object, mode) }, that.hoverStartDelay) }, _releaseHover: function(that, object, mode, func) { if (that.mouseLocked) return; clearTimeout(that.cmpCoordTimeout); clearTimeout(that.hoverStartTimeOut); if (object === that.hoveredObject) that.hoverHoldTimeOut = setTimeout(function() { that.hoveredObject = null; func(that, object, mode); that.hoverStartDelay = 0 }, HOVER_HOLD_DELAY) }, _compareCoords: function(that, func) { clearTimeout(that.cmpCoordTimeout); if (Math.abs(that.pX - that.cX) + Math.abs(that.pY - that.cY) < that.sensitivity) { if (that.mouseLocked) return; func() } else { that.pX = that.cX; that.pY = that.cY; that.cmpCoordTimeout = setTimeout(function() { that._compareCoords(that, func) }, that.hoverStartDelay === 0 ? HOVER_START_DELAY : 0) } }, _seriesClick: function(that, series, touchEvent, event) { if (that.lockClick && !touchEvent) return; that.seriesClick && that.seriesClick.call(series, series, event) }, _legendClick: function(that, series, touchEvent, event) { var legendClick = that.legendClick; if (that.lockClick && !touchEvent) return true; if (legendClick) { legendClick.call(series, series, event); return true } return false }, _pointClick: function(that, point, touchEvent, event) { var series = point.series; if (that.lockClick && !touchEvent) return; if (that.pointClick) { that.pointClick.call(point, point, event); return } that.seriesClick && that.seriesClick.call(series, series, event); return }, _argumentAxisClick: function(that, axis, argument, touchEvent, event) { if (that.lockClick && !touchEvent) return; that.argumentAxisClick && that.argumentAxisClick.call(axis, axis, argument, event) }, _selectSeries: function(event, mode) { event.data.tracker._setSelectedSeries(event.target, mode) }, _deselectSeries: function(event, mode) { event.data.tracker._releaseSelectedSeries(event.target, mode) }, _selectPoint: function(event, point) { event.data.tracker._setSelectedPoint(point) }, _deselectPoint: function(event, point) { event.data.tracker._releaseSelectedPoint(point) }, _showPointTooltip: function(event, point) { var that = event.data.tracker; that._showTooltip(that.tooltip, point) }, _hidePointTooltip: function(event, point) { event.data.tracker._hideTooltip(point) }, _hideTooltip: function(point) { var tooltip = this && this.tooltip; if (!tooltip || point && this.pointAtShownTooltip !== point) return; point = point || this.pointAtShownTooltip; tooltip.hide(); if (this.pointAtShownTooltip) { this.pointAtShownTooltip = null; isFunction(this.tooltipHidden) && this.tooltipHidden.call(point, point) } }, _showTooltip: function(tooltip, point) { var tooltipFormatObject = point.getTooltipFormatObject(tooltip); if (!isDefined(tooltipFormatObject.valueText) && !tooltipFormatObject.points || !point.isVisible()) return; this.pointAtShownTooltip && this._hideTooltip(this.pointAtShownTooltip); if (point && point.getOptions()) { var tooltipCoords = point.getTooltipCoords(); if (!tooltip.prepare(tooltipFormatObject, { x: tooltipCoords.x, y: tooltipCoords.y, offset: tooltipCoords.offset })) return; tooltip.show(); !this.pointAtShownTooltip && isFunction(this.tooltipShown) && this.tooltipShown.call(point, point); this.pointAtShownTooltip = point } }, _setHoveredSeries: function(series, mode) { var that = this; if (mode !== NONE_MODE && that.hoveredSeries !== series || series.lastHoverMode !== mode) { that._clearHover(that); that.hoveredSeries = series; series.setHoverState(mode, that.legendCallback(series)); that.seriesHover && that.seriesHover.call(series, series); that.seriesHoverChanged && that.seriesHoverChanged.call(series, series) } if (mode === NONE_MODE) $(series).trigger('NoneMode') }, _setSelectedSeries: function(series, mode) { var that = this, seriesContain = false; if (this.seriesSelectionMode === MULTIPLE_MODE) $.each(that.selectedSeries, function(_, sr) { if (sr == series) { seriesContain = true; return false } }); else if (that.selectedSeries == series) seriesContain = true; if (!seriesContain || series.lastSelectionMode !== mode) { if (that.seriesSelectionMode === SINGLE_MODE) { this._releaseSelectedSeries(); that.selectedSeries = series } else that.selectedSeries.push(series); series.setSelectedState(mode, that.legendCallback(series)); that.seriesSelected && that.seriesSelected.call(series, series); that.seriesSelectionChanged && that.seriesSelectionChanged.call(series, series) } }, _setHoveredPoint: function(point, mode) { var that = this; var debug = DX.utils.debug; debug.assert(point.series, 'series was not assigned to point or empty'); if (that.hoveredPoint === point && !point.series) return; that._clearHover(that); that.hoveredPoint = point; if (point && point.getOptions()) that._setHoverStylePointWithMode(point, 'setPointHoverState', mode || processMode(point.getOptions().hoverMode), that.pointHoverChanged, that.legendCallback(point)); that.pointHover && that.pointHover.call(point, point) }, _toAllArgumentPoints: function(argument, func, callBack) { var that = this; $.each(that.storedSeries, function(_, series) { var neighborPoint = series.getPointByArg(argument); if (neighborPoint) { series[func](neighborPoint); callBack && callBack.call(neighborPoint, neighborPoint) } }) }, _setHoverStylePointWithMode: function(point, func, mode, callBack, legendCallback) { var that = this; switch (mode) { case ALL_ARGUMENTS_POINTS_MODE: this._toAllArgumentPoints(point.argument, func, callBack); break; case ALL_SERIES_POINTS_MODE: $.each(point.series.getPoints(), function(_, point) { point.series[func](point); callBack && callBack.call(point, point) }); break; case NONE_MODE: break; default: point.series[func](point, legendCallback); callBack && callBack.call(point, point) } }, _setSelectedPoint: function(point) { var that = this, pointContain = false; if (this.pointSelectionMode === MULTIPLE_MODE) { $.each(that.selectedPoint, function(_, pt) { if (pt == point) { pointContain = true; return false } }); !pointContain && that.selectedPoint.push(point) } else if (that.selectedPoint !== point) { this._releaseSelectedPoint(); that.selectedPoint = point } else pointContain = true; if (!pointContain) { that._setHoverStylePointWithMode(point, 'setPointSelectedState', processMode(point.getOptions().selectionMode), that.pointSelectionChanged, that.legendCallback(point)); that.pointSelected && that.pointSelected.call(point, point) } }, _releaseHoveredSeries: function() { var that = this; if (!that.hoveredSeries) return; that.hoveredSeries.releaseHoverState(undefined, that.legendCallback(that.hoveredSeries)); that.seriesHoverChanged && that.seriesHoverChanged.call(that.hoveredSeries, that.hoveredSeries); that.hoveredSeries = null }, _releaseSelectedSeriesMultiMode: function(series) { var that = this; if (!that.selectedSeries) return; series.releaseSelectedState(undefined, that.legendCallback(series)); that.seriesSelectionChanged && that.seriesSelectionChanged.call(series, series); that.selectedSeries = $.map(that.selectedSeries, function(sr) { if (sr !== series) return sr }) }, _releaseSelectedSeriesSingleMode: function() { var that = this, series = this.selectedSeries; if (!series) return; series.releaseSelectedState(undefined, that.legendCallback(series)); that.seriesSelectionChanged && that.seriesSelectionChanged.call(series, series); that.selectedSeries = null }, _releaseHoveredPoint: function() { var that = this, point = that.hoveredPoint, mode; if (!point || !point.getOptions()) return; mode = processMode(point.getOptions().hoverMode); if (mode === ALL_SERIES_POINTS_MODE) $.each(point.series.getPoints(), function(_, point) { point.series.releasePointHoverState(point); that.pointHoverChanged && that.pointHoverChanged.call(point, point) }); else if (mode === ALL_ARGUMENTS_POINTS_MODE) that._toAllArgumentPoints(point.argument, 'releasePointHoverState', that.pointHoverChanged); else { point.releaseHoverState(that.legendCallback(point)); that.pointHoverChanged && that.pointHoverChanged.call(point, point) } if (that.tooltipEnabled && !that.showHoldTooltip) that._hideTooltip(point); that.hoveredPoint = null }, _releaseSelectedPointMultiMode: function(point) { var that = this, points = that.selectedPoint; if (!points) return; that._setHoverStylePointWithMode(point, 'releasePointSelectedState', processMode(point.getOptions().selectionMode), that.pointSelectionChanged, that.legendCallback(point)); this.selectedPoint = $.map(this.selectedPoint, function(pt) { if (pt !== point) return pt }) }, _releaseSelectedPointSingleMode: function() { var that = this, point = that.selectedPoint; if (!point) return; that._setHoverStylePointWithMode(point, 'releasePointSelectedState', processMode(point.getOptions().selectionMode), that.pointSelectionChanged, that.legendCallback(point)); this.selectedPoint = null }, _clearPointSelection: function() { var that = this; if (that.pointSelectionMode === SINGLE_MODE) that._releaseSelectedPoint(); else $.each(that.selectedPoint || [], function(_, point) { that._releaseSelectedPoint(point) }) }, clearSelection: function() { var that = this; that._clearPointSelection(); if (that.seriesSelectionMode === SINGLE_MODE) that._releaseSelectedSeries(); else $.each(that.selectedSeries, function(_, series) { that._releaseSelectedSeries(series) }) }, setTooltip: function(tooltip) { this.tooltip = tooltip }, _mouseLock: function(tracker) { if (tracker.unlockMouseTimer) clearTimeout(tracker.unlockMouseTimer); tracker.mouseLocked = true; tracker.unlockMouseTimer = setTimeout(function() { tracker.mouseLocked = false }, MOUSE_EVENT_LOCK_TIMEOUT) }, _clickLock: function(tracker) { tracker.lockClick = true; if (tracker.lockClickTimer) clearTimeout(tracker.lockClickTimer); tracker.lockClickTimer = setTimeout(function() { tracker.lockClick = false }, CLICK_EVENT_LOCK_TIMEOUT) }, _setCurCoords: function(that, pageX, pageY) { that.cX = pageX; that.cY = pageY }, _clearHover: function(that) { that._releaseHoveredSeries(); that._releaseHoveredPoint() } }) })(jQuery, DevExpress); /*! Module viz-charts, file dxChart.js */ (function($, DX, undefined) { var ui = DX.ui, viz = DX.viz; DX.registerComponent("dxChart", viz.charts.Chart) })(jQuery, DevExpress); /*! Module viz-charts, file dxPieChart.js */ (function($, DX, undefined) { var ui = DX.ui, viz = DX.viz; DX.registerComponent("dxPieChart", viz.charts.PieChart) })(jQuery, DevExpress); DevExpress.MOD_VIZ_CHARTS = true } if (!DevExpress.MOD_VIZ_GAUGES) { if (!DevExpress.MOD_VIZ_CORE) throw Error('Required module is not referenced: viz-core'); /*! Module viz-gauges, file namespaces.js */ (function(DX) { DX.viz.gauges = {__internals: { circularNeedles: {}, circularMarkers: {}, linearNeedles: {}, linearMarkers: {} }}; DX.viz.gauges.__tests = {} })(DevExpress); /*! Module viz-gauges, file factory.js */ (function(DX, $, undefined) { var internals = DX.viz.gauges.__internals, circularNeedles = internals.circularNeedles, circularMarkers = internals.circularMarkers, linearNeedles = internals.linearNeedles, linearMarkers = internals.linearMarkers; var _String = window.String, _isString = DX.utils.isString; DX.viz.gauges.__factory = { createCircularValueIndicator: function(type) { var indicatorType = circularNeedles.RectangleNeedle; switch (_String(type).toLowerCase()) { case'rectangleneedle': case'rectangle': indicatorType = circularNeedles.RectangleNeedle; break; case'triangleneedle': case'triangle': indicatorType = circularNeedles.TriangleNeedle; break; case'twocolorneedle': case'twocolorrectangle': indicatorType = circularNeedles.TwoColorRectangleNeedle; break; case'rangebar': indicatorType = internals.CircularRangeBar; break } return new indicatorType }, createLinearValueIndicator: function(type) { var indicatorType = internals.LinearRangeBar; switch (_String(type).toLowerCase()) { case'rectangle': indicatorType = linearNeedles.RectangleNeedle; break; case'rhombus': indicatorType = linearNeedles.RhombusNeedle; break; case'circle': indicatorType = linearNeedles.CircleNeedle; break; case'rangebar': indicatorType = internals.LinearRangeBar; break } return new indicatorType }, createCircularSubvalueIndicator: function(type) { var indicatorType = circularMarkers.TriangleMarker; switch (_String(type).toLowerCase()) { case'trianglemarker': case'triangle': indicatorType = circularMarkers.TriangleMarker; break; case'textcloud': indicatorType = circularMarkers.TextCloudMarker; break } return new indicatorType }, createLinearSubvalueIndicator: function(type) { var indicatorType = linearMarkers.TriangleMarker; switch (_String(type).toLowerCase()) { case'trianglemarker': case'triangle': indicatorType = linearMarkers.TriangleMarker; break; case'textcloud': indicatorType = linearMarkers.TextCloudMarker; break } return new indicatorType }, createCircularValueIndicatorInHardMode: function(type) { var indicatorType = null; switch (_String(type).toLowerCase()) { case'rectangleneedle': indicatorType = circularNeedles.RectangleNeedle; break; case'triangleneedle': indicatorType = circularNeedles.TriangleNeedle; break; case'twocolorneedle': indicatorType = circularNeedles.TwoColorRectangleNeedle; break; case'rangebar': indicatorType = internals.CircularRangeBar; break; case'trianglemarker': indicatorType = circularMarkers.TriangleMarker; break; case'textcloud': indicatorType = circularMarkers.TextCloudMarker; break } return indicatorType ? new indicatorType : null }, createLinearValueIndicatorInHardMode: function(type) { var indicatorType = null; switch (_String(type).toLowerCase()) { case'rectangle': indicatorType = linearNeedles.RectangleNeedle; break; case'rhombus': indicatorType = linearNeedles.RhombusNeedle; break; case'circle': indicatorType = linearNeedles.CircleNeedle; break; case'rangebar': indicatorType = internals.LinearRangeBar; break; case'trianglemarker': indicatorType = linearMarkers.TriangleMarker; break; case'textcloud': indicatorType = linearMarkers.TextCloudMarker; break } return indicatorType ? new indicatorType : null }, createCircularNeedle: function(type) { switch (_String(type).toLowerCase()) { case'rectangleneedle': case'rectangle': return new circularNeedles.RectangleNeedle; case'twocolorneedle': case'twocolorrectangle': return new circularNeedles.TwoColorRectangleNeedle; case'triangleneedle': case'triangle': return new circularNeedles.TriangleNeedle; case'rangebar': return new internals.CircularRangeBar } return undefined }, createLinearNeedle: function(type) { switch (_String(type).toLowerCase()) { case'rectangle': return new linearNeedles.RectangleNeedle; case'rhombus': return new linearNeedles.RhombusNeedle; case'circle': return new linearNeedles.CircleNeedle; case'rangebar': return new internals.LinearRangeBar } return undefined }, createCircularMarker: function(type) { switch (_String(type).toLowerCase()) { case'trianglemarker': case'triangle': return new circularMarkers.TriangleMarker; case'textcloud': return new circularMarkers.TextCloudMarker } return undefined }, createLinearMarker: function(type) { switch (_String(type).toLowerCase()) { case'trianglemarker': case'triangle': return new linearMarkers.TriangleMarker; case'textcloud': return new linearMarkers.TextCloudMarker } return undefined }, createCircularRangeBar: function(parameters) { return new internals.CircularRangeBar(parameters) }, createLinearRangeBar: function(parameters) { return new internals.LinearRangeBar(parameters) }, createCircularScale: function(parameters) { return new internals.CircularScale(parameters) }, createLinearScale: function(parameters) { return new internals.LinearScale(parameters) }, createCircularRangeContainer: function(parameters) { return new internals.CircularRangeContainer(parameters) }, createLinearRangeContainer: function(parameters) { return new internals.LinearRangeContainer(parameters) }, createTitle: function(parameters) { return new internals.Title(parameters) }, createIndicator: function() { return internals.Indicator && new internals.Indicator || null }, createLayoutManager: function() { return new internals.LayoutManager }, createThemeManager: function(options) { return new internals.ThemeManager(options) }, createTracker: function(parameters) { return new internals.Tracker(parameters) } }; var _isFunction = DX.utils.isFunction, _String = window.String, _extend = $.extend; var _formatHelper = DX.formatHelper; internals.formatValue = function(value, options, extra) { options = options || {}; var text = _formatHelper.format(value, options.format, options.precision), context; if (_isFunction(options.customizeText)) { var context = _extend({ value: value, valueText: text }, extra); return _String(options.customizeText.call(context, context)) } return text }; internals.getSampleText = function(translator, options) { var text1 = internals.formatValue(translator.getDomainStart(), options), text2 = internals.formatValue(translator.getDomainEnd(), options); return text1.length >= text2.length ? text1 : text2 } })(DevExpress, jQuery); /*! Module viz-gauges, file scale.js */ (function(DX, $, undefined) { var _Number = Number, _String = String, _isFinite = isFinite, _min = Math.min, _max = Math.max, _abs = Math.abs, _atan = Math.atan, _acos = Math.acos, _ceil = Math.ceil, _isFunction = DX.utils.isFunction, _isArray = DX.utils.isArray, _getCosAndSin = DX.utils.getCosAndSin, _normalizeAngle = DX.utils.normalizeAngle, _convertAngleToRendererSpace = DX.utils.convertAngleToRendererSpace, _map = $.map; var _formatHelper = DX.formatHelper, _tickProvider = DX.viz.core.tickProvider; var PI_DIV_180 = Math.PI / 180; function binarySearch(x, list) { var a = 0, b = list.length - 1, flag = list[a] - list[b] < 0, c, k = -1; if (list[a] === x) k = a; if (list[b] === x) k = b; while (k < 0 && a <= b) { c = ~~((a + b) / 2); if (list[c] === x) k = c; else if (list[c] - x < 0 === flag) a = c + 1; else b = c - 1 } return k } function sortAsc(x, y) { return x - y } function sortDes(x, y) { return y - x } DX.viz.gauges.__internals.BaseScale = DX.Class.inherit({ ctor: function(parameters) { var that = this; that._renderer = parameters.renderer; that._container = parameters.container; that._translator = parameters.translator; that._root = that._renderer.createGroup({'class': 'dxg-scale'}); that._majorTicks = that._renderer.createGroup({'class': 'dxg-major-ticks'}); that._minorTicks = that._renderer.createGroup({'class': 'dxg-minor-ticks'}); that._labels = that._renderer.createGroup({'class': 'dxg-labels'}) }, dispose: function() { var that = this; that._renderer = that._container = that._renderer = that._root = that._majorTicks = that._minorTicks = that._labels = null; return that }, clean: function() { var that = this; that._root.detach(); that._majorTicks.detach().clear(); that._minorTicks.detach().clear(); that._labels.detach().clear(); that._majorTicksEnabled = that._minorTicksEnabled = that._labelsEnabled = that._options = that.enabled = null; return that }, render: function(options) { var that = this; that._options = options; that._processOptions(options); if (that._majorTicksEnabled || that._minorTicksEnabled || that._labelsEnabled) { that.enabled = true; that._root.append(that._container); if (that._majorTicksEnabled) that._majorTicks.append(that._root); if (that._minorTicksEnabled) that._minorTicks.append(that._root); if (that._labelsEnabled) { that._labels.append(that._root); that._measureText() } } return that }, _processOptions: function(options) { var that = this; that._majorTicksEnabled = options.majorTick.visible && options.majorTick.length > 0 && options.majorTick.width > 0; that._minorTicksEnabled = options.minorTick.visible && options.minorTick.length > 0 && options.minorTick.width > 0; that._labelsEnabled = options.label.visible && _Number(options.label.indentFromTick) !== 0; that._setupOrientation() }, _getSampleText: function() { var that = this, domain = that._translator.getDomain(), texts = [], i, ii, text, maxLength = 0, maxText = ''; var ticks = _tickProvider.getTicks({ min: domain[0], max: domain[1], tickInterval: that._options.majorTick.tickInterval > 0 ? _Number(that._options.majorTick.tickInterval) : undefined, screenDelta: that._options.approximateScreenDelta, gridSpacingFactor: that._getGridSpacingFactor().majorTicks }); for (i = 0, ii = ticks.length; i < ii; ++i) { text = that._formatValue(ticks[i]); text.length > maxLength && (maxText = text) && (maxLength = text.length) } return maxText }, _measureText: function() { var that = this, value = that._getSampleText(), text = that._renderer.createText(value, 0, 0, {font: that._options.label.font}).append(that._labels), bbox = text.getBBox(); text.remove(); that._textVerticalOffset = -bbox.y - bbox.height / 2; that._textWidth = bbox.width; that._textHeight = bbox.height; that._textLength = value.length }, _formatValue: function(value) { var options = this._options.label, text = _formatHelper.format(value, options.format, options.precision); if (_isFunction(options.customizeText)) { text = { value: value, valueText: text }; text = _String(options.customizeText.call(text, text)) } return text }, _setupOrientation: null, _getCustomValues: function(values, compare) { var translator = this._translator, result = []; if (_isArray(values)) { result = _map(values, function(x) { return _isFinite(translator.translate(x)) ? _Number(x) : null }).sort(compare); result = _map(result, function(x, i) { return x !== result[i - 1] ? x : null }) } return result }, _generateTicks: function(layout) { var that = this, majorTicksOptions = { tickInterval: that._options.majorTick.tickInterval > 0 ? _Number(that._options.majorTick.tickInterval) : undefined, gridSpacingFactor: that._getGridSpacingFactor().majorTicks, numberMultipliers: [1, 2, 5] }, minorTicksOptions = { tickInterval: that._options.minorTick.tickInterval > 0 ? _Number(that._options.minorTick.tickInterval) : undefined, gridSpacingFactor: that._getGridSpacingFactor().minorTicks, numberMultipliers: [1, 2, 5] }; if (that._options.majorTick.useTicksAutoArrangement) { majorTicksOptions.useTicksAutoArrangement = true; majorTicksOptions.renderer = that._renderer; majorTicksOptions.translator = that._translator; majorTicksOptions.getCustomAutoArrangementStep = function(values) { return that._getCuttingFactor(values.length, { width: that._textWidth, height: that._textHeight }, layout) } } return _tickProvider.getFullTicks(that._translator.getDomain()[0], that._translator.getDomain()[1], that._getScreenDelta(layout), majorTicksOptions, minorTicksOptions) }, _getTicks: function(layout) { var that = this, compareCallback = that._translator.getDomain()[0] < that._translator.getDomain()[1] ? sortAsc : sortDes, info = that._generateTicks(layout); var majorValues = that._options.majorTick.showCalculatedTicks ? info.majorTicks : []; var customMajorValues = that._getCustomValues(that._options.majorTick.customTickValues, compareCallback); customMajorValues = _map(customMajorValues, function(value) { return binarySearch(value, majorValues) === -1 ? value : null }); var minorValues = that._options.minorTick.showCalculatedTicks ? info.minorTicks : []; minorValues = _map(minorValues, function(value) { return binarySearch(value, customMajorValues) === -1 ? value : null }); var customMinorValues = that._getCustomValues(that._options.minorTick.customTickValues, compareCallback); var list = majorValues.concat(minorValues, customMajorValues).sort(compareCallback); customMinorValues = _map(customMinorValues, function(value) { return binarySearch(value, list) === -1 ? value : null }); return { major: _map(majorValues.concat(customMajorValues), function(value) { return { value: value, position: that._translator.translate(value) } }), minor: _map(minorValues.concat(customMinorValues), function(value) { return { value: value, position: that._translator.translate(value) } }) } }, _createMajorTicks: function(ticks, layout) { var that = this; that._majorTicks.clear().applySettings({fill: that._options.majorTick.color}); var points = that._getTickPoints(_Number(that._options.majorTick.length), _Number(that._options.majorTick.width), layout); if (points) { var i = 0, ii = ticks.length, element; that._options.hideFirstTick && ++i; that._options.hideLastTick && --ii; for (; i < ii; ++i) { element = that._renderer.createArea(points); that._moveTick(element, ticks[i], layout); element.append(that._majorTicks) } } }, _createMinorTicks: function(ticks, layout) { var that = this; that._minorTicks.clear().applySettings({fill: that._options.minorTick.color}); var points = that._getTickPoints(_Number(that._options.minorTick.length), _Number(that._options.minorTick.width), layout); if (points) { var i = 0, ii = ticks.length, element; for (; i < ii; ++i) { element = that._renderer.createArea(points); that._moveTick(element, ticks[i], layout); element.append(that._minorTicks) } } }, _createLabels: function(ticks, layout) { var that = this, indentFromTick = _Number(that._options.label.indentFromTick); that._labels.clear().applySettings({ align: that._getLabelAlign(indentFromTick), font: that._options.label.font }); var textPosition = that._getLabelPosition(that._majorTicksEnabled ? _Number(that._options.majorTick.length) : 0, indentFromTick, layout); if (textPosition) { var i = 0, ii = ticks.length, points, text; that._options.hideFirstLabel && ++i; that._options.hideLastLabel && --ii; for (; i < ii; ++i) { text = that._formatValue(ticks[i].value); points = that._getLabelOptions(text, textPosition, indentFromTick, ticks[i], layout); that._renderer.createText(text, points.x, points.y + that._textVerticalOffset).append(that._labels) } } }, resize: function(layout) { var that = this, ticks = that._getTicks(layout); if (that._majorTicksEnabled) that._createMajorTicks(ticks.major, layout); if (that._minorTicksEnabled) that._createMinorTicks(ticks.minor, layout); if (that._labelsEnabled) that._createLabels(ticks.major, layout); return that } }); function getBasedAngle(startAngle, endAngle) { var startDelta, endDelta, tmp; if (startAngle > endAngle) { tmp = endAngle; endAngle = startAngle; startAngle = tmp } startDelta = 0 <= startAngle && startAngle <= 180 ? _abs(90 - startAngle) : _abs(270 - startAngle); startDelta = startAngle < 90 && 90 < endAngle || startAngle < 270 && 270 < endAngle ? 0 : startDelta; endDelta = 0 < endAngle && endAngle < 180 ? _abs(90 - endAngle) : _abs(270 - endAngle); return startDelta < endDelta ? startDelta : endDelta } DX.viz.gauges.__internals.CircularScale = DX.viz.gauges.__internals.BaseScale.inherit({ _getGridSpacingFactor: function() { return { majorTicks: 17, minorTicks: 5 } }, _getScreenDelta: function(layout) { return (this._translator.getCodomainStart() - this._translator.getCodomainEnd()) * layout.radius * PI_DIV_180 }, _getCuttingFactor: function(ticksCount, maxLabelSize, layout) { var that = this, options = that._options, startAngle = that._translator.getCodomainStart(), endAngle = that._translator.getCodomainEnd(), radius = that._getLabelPosition(that._majorTicksEnabled ? _Number(that._options.majorTick.length) : 0, _Number(that._options.label.indentFromTick), layout), baseAngle = getBasedAngle(_normalizeAngle(startAngle), _normalizeAngle(endAngle)), baseAngleCosSin = _getCosAndSin(baseAngle), degreesPerTick = (startAngle - endAngle) / ticksCount, minAngleBetweenTicks, widthBasedAngle, tanOfWidthBasedAngle, heightBasedAngle, cosOfHeightBasedAngle, cuttingBackFactor = 1; tanOfWidthBasedAngle = (baseAngleCosSin.sin * radius + maxLabelSize.width) / (baseAngleCosSin.cos * radius); widthBasedAngle = _abs(baseAngle - _atan(tanOfWidthBasedAngle) / PI_DIV_180); cosOfHeightBasedAngle = baseAngleCosSin.cos - maxLabelSize.height / radius; heightBasedAngle = -1 > cosOfHeightBasedAngle || cosOfHeightBasedAngle > 1 ? 90 : _abs(baseAngle - _acos(cosOfHeightBasedAngle) / PI_DIV_180); minAngleBetweenTicks = widthBasedAngle < heightBasedAngle ? widthBasedAngle : heightBasedAngle; if (degreesPerTick < minAngleBetweenTicks) cuttingBackFactor = _ceil(minAngleBetweenTicks / degreesPerTick); return _max(1, cuttingBackFactor) }, _setupOrientation: function() { var that = this; that._inner = that._outer = 0; switch (that._options.orientation) { case'inside': that._inner = 1; break; case'center': that._inner = that._outer = 0.5; break; default: that._outer = 1; break } }, _getTickPoints: function(length, width, layout) { var x1 = layout.x - width / 2, x2 = layout.x + width / 2, y1 = layout.y - layout.radius - length * this._outer, y2 = layout.y - layout.radius + length * this._inner; return y1 > 0 && y2 > 0 ? [x1, y1, x2, y1, x2, y2, x1, y2] : null }, _moveTick: function(element, tick, layout) { element.rotate(_convertAngleToRendererSpace(tick.position), layout.x, layout.y) }, _getLabelPosition: function(tickLength, textIndent, layout) { var position = layout.radius + tickLength * (textIndent >= 0 ? this._outer : -this._inner) + textIndent; return position > 0 ? position : null }, _getLabelAlign: function() { return 'center' }, _getLabelOptions: function(textValue, textPosition, textIndent, tick, layout) { var cossin = _getCosAndSin(tick.position), x = layout.x + cossin.cos * textPosition, y = layout.y - cossin.sin * textPosition, dx = cossin.cos * (textValue.length / this._textLength) * this._textWidth / 2, dy = cossin.sin * this._textHeight / 2; if (textIndent > 0) { x += dx; y -= dy } else { x -= dx; y += dy } return { x: x, y: y } }, measure: function(layout) { var that = this, result = { min: layout.radius, max: layout.radius }; if (that._majorTicksEnabled) { result.min = _min(result.min, layout.radius - that._inner * that._options.majorTick.length); result.max = _max(result.max, layout.radius + that._outer * that._options.majorTick.length) } if (that._minorTicksEnabled) { result.min = _min(result.min, layout.radius - that._inner * that._options.minorTick.length); result.max = _max(result.max, layout.radius + that._outer * that._options.minorTick.length) } if (that._labelsEnabled) { if (that._options.label.indentFromTick > 0) { result.horizontalOffset = _Number(that._options.label.indentFromTick) + that._textWidth; result.verticalOffset = _Number(that._options.label.indentFromTick) + that._textHeight } else { result.horizontalOffset = result.verticalOffset = 0; result.min -= -_Number(that._options.label.indentFromTick) + _max(that._textWidth, that._textHeight) } result.inverseHorizontalOffset = that._textWidth / 2; result.inverseVerticalOffset = that._textHeight / 2 } return result } }); DX.viz.gauges.__internals.LinearScale = DX.viz.gauges.__internals.BaseScale.inherit({ _getGridSpacingFactor: function() { return { majorTicks: 25, minorTicks: 5 } }, _getScreenDelta: function(layout) { return _abs(this._translator.getCodomainEnd() - this._translator.getCodomainStart()) }, _getCuttingFactor: function(ticksCount, maxLabelSize, layout) { var that = this, labelSize = that.vertical ? maxLabelSize.height : maxLabelSize.width, screenSize = _abs(that._translator.getCodomainEnd() - that._translator.getCodomainStart()); return _max(1, _ceil(ticksCount * labelSize / (screenSize + labelSize))) }, _setupOrientation: function() { var that = this; that.vertical = that._options.vertical; that._inner = that._outer = 0; if (that.vertical) switch (that._options.horizontalOrientation) { case'left': that._inner = 1; break; case'center': that._inner = that._outer = 0.5; break; default: that._outer = 1; break } else switch (that._options.verticalOrientation) { case'top': that._inner = 1; break; case'middle': that._inner = that._outer = 0.5; break; default: that._outer = 1; break } }, _getTickPoints: function(length, width, layout) { var that = this, x1, x2, y1, y2; if (that.vertical) { x1 = layout.x - length * that._inner; x2 = layout.x + length * that._outer; y1 = -width / 2; y2 = +width / 2 } else { x1 = -width / 2; x2 = +width / 2; y1 = layout.y - length * that._inner; y2 = layout.y + length * that._outer } return [x1, y1, x2, y1, x2, y2, x1, y2] }, _moveTick: function(element, tick, layout) { var x = 0, y = 0; if (this.vertical) y = tick.position; else x = tick.position; element.move(x, y) }, _getLabelPosition: function(tickLength, textIndent, layout) { var position = tickLength * (textIndent >= 0 ? this._outer : -this._inner) + textIndent; if (this.vertical) position += layout.x; else position += layout.y + (textIndent >= 0 ? 1 : -1) * this._textVerticalOffset; return position }, _getLabelAlign: function(textIndent) { return this.vertical ? textIndent > 0 ? 'left' : 'right' : 'center' }, _getLabelOptions: function(textValue, textPosition, textIndent, tick, layout) { var x, y; if (this.vertical) { x = textPosition; y = tick.position } else { x = tick.position; y = textPosition } return { x: x, y: y } }, measure: function(layout) { var that = this, p = layout[that.vertical ? 'x' : 'y'], result = { min: p, max: p }; if (that._majorTicksEnabled) { result.min = _min(result.min, p - that._inner * that._options.majorTick.length); result.max = _max(result.max, p + that._outer * that._options.majorTick.length) } if (that._minorTicksEnabled) { result.min = _min(result.min, p - that._inner * that._options.minorTick.length); result.max = _max(result.max, p + that._outer * that._options.minorTick.length) } if (that._labelsEnabled) { if (that._options.label.indentFromTick > 0) result.max += +_Number(that._options.label.indentFromTick) + that[that.vertical ? '_textWidth' : '_textHeight']; else result.min -= -_Number(that._options.label.indentFromTick) + that[that.vertical ? '_textWidth' : '_textHeight']; result.indent = that[that.vertical ? '_textHeight' : '_textWidth'] / 2 } return result } }) })(DevExpress, jQuery); /*! Module viz-gauges, file baseIndicator.js */ (function(DX, $, undefined) { var _isFinite = isFinite, _Number = Number, _extend = $.extend; DX.viz.gauges.__internals.BaseIndicator = DX.Class.inherit({ setup: function(parameters) { var that = this; that._renderer = parameters.renderer; that._translator = parameters.translator; that._owner = parameters.owner; that._tracker = parameters.tracker; that._className = parameters.className; that._options = {}; that._rootElement = that._createRoot(); that._trackerElement = that._createTracker(); return that }, dispose: function() { var that = this; that._renderer = that._owner = that._translator = that._tracker = that._options = that._rootElement = that._trackerElement = null; return that }, _setupAnimation: function() { var that = this; if (that._options.animation) that._animation = { step: function(pos) { that._actualValue = that._animation.start + that._animation.delta * pos; that._actualPosition = that._translator.translate(that._actualValue); that._move() }, duration: that._options.animation.duration > 0 ? _Number(that._options.animation.duration) : 0, easing: that._options.animation.easing } }, _runAnimation: function(value) { var that = this, animation = that._animation; animation.start = that._actualValue; animation.delta = value - that._actualValue; that._rootElement.animate({_: 0}, { step: animation.step, duration: animation.duration, easing: animation.easing }) }, _createRoot: function() { return this._renderer.createGroup({'class': this._className}) }, _createTracker: function() { return this._renderer.createArea() }, _getTrackerSettings: function(){}, clean: function() { var that = this; that._animation && that._rootElement.stopAnimation(); that._rootElement.detach(); that._rootElement.clear(); that._clear(); that._tracker.detach(that._trackerElement); that._options = that.enabled = that._animation = null; return that }, render: function(options) { var that = this; that.type = options.type; that._options = options; that._actualValue = that._currentValue = that._translator.adjust(that._options.currentValue); that.enabled = that._isEnabled(); if (that.enabled) { that._setupAnimation(); that._rootElement.applySettings({fill: that._options.color}).append(that._owner); that._tracker.attach(that._trackerElement, that, that._trackerInfo) } return that }, resize: function(layout) { var that = this; that._rootElement.clear(); that._clear(); that.visible = that._isVisible(layout); if (that.visible) { _extend(that._options, layout); that._actualPosition = that._translator.translate(that._actualValue); that._render(); that._trackerElement.applySettings(that._getTrackerSettings()); that._move() } return that }, value: function(arg, _noAnimation) { var that = this; if (arg !== undefined) { var val = that._translator.adjust(arg); if (that._currentValue !== val && _isFinite(val)) { that._currentValue = val; if (that.visible) if (that._animation && !_noAnimation) that._runAnimation(val); else { that._actualValue = val; that._actualPosition = that._translator.translate(val); that._move() } } return that } return that._currentValue }, _isEnabled: null, _isVisible: null, _render: null, _clear: null, _move: null }) })(DevExpress, jQuery); /*! Module viz-gauges, file baseMarker.js */ (function(DX, undefined) { var TextCloud = DX.viz.core.TextCloud; var formatValue = DX.viz.gauges.__internals.formatValue, getSampleText = DX.viz.gauges.__internals.getSampleText; DX.viz.gauges.__internals.BaseTextCloudMarker = DX.viz.gauges.__internals.BaseIndicator.inherit({ _move: function() { var that = this, bbox, info = new TextCloud, textCloudOptions = that._getTextCloudOptions(); that._text.applySettings({text: formatValue(that._actualValue, that._options.text)}); bbox = that._text.getBBox(); info.setup({ x: textCloudOptions.x, y: textCloudOptions.y, textWidth: bbox.width, textHeight: bbox.height, horMargin: that._options.horizontalOffset, verMargin: that._options.verticalOffset, tailLength: that._options.arrowLength, type: textCloudOptions.type }); that._text.applySettings({ x: info.cx(), y: info.cy() + that._textVerticalOffset }); that._cloud.applySettings({points: info.points()}); that._trackerElement && that._trackerElement.applySettings({points: info.points()}) }, _measureText: function() { var that = this, root, text, bbox; if (!that._textVerticalOffset) { root = that._createRoot().append(that._owner); text = that._renderer.createText(getSampleText(that._translator, that._options.text), 0, 0, { align: 'center', font: that._options.text.font }).append(root); bbox = text.getBBox(); root.remove(); that._textVerticalOffset = -bbox.y - bbox.height / 2; that._textWidth = bbox.width; that._textHeight = bbox.height; that._textFullWidth = that._textWidth + 2 * that._options.horizontalOffset; that._textFullHeight = that._textHeight + 2 * that._options.verticalOffset } }, _render: function() { var that = this; that._measureText(); that._cloud = that._cloud || that._renderer.createArea().append(that._rootElement); that._text = that._text || that._renderer.createText().append(that._rootElement); that._text.applySettings({ align: 'center', font: that._options.text.font }) }, _clear: function() { delete this._cloud; delete this._text }, getTooltipParameters: function() { var position = this._getTextCloudOptions(); return { x: position.x, y: position.y, value: this._currentValue, color: this._options.color } } }) })(DevExpress); /*! Module viz-gauges, file baseRangeBar.js */ (function(DX, $, undefined) { var $extend = $.extend; var formatValue = DX.viz.gauges.__internals.formatValue, getSampleText = DX.viz.gauges.__internals.getSampleText; DX.viz.gauges.__internals.BaseRangeBar = DX.viz.gauges.__internals.BaseIndicator.inherit({ _measureText: function() { var that = this, root, text, bbox; that._hasText = that._isTextVisible(); if (that._hasText && !that._textVerticalOffset) { root = that._createRoot().append(that._owner); text = that._renderer.createText(getSampleText(that._translator, that._options.text), 0, 0, { 'class': 'dxg-text', align: 'center', font: that._options.text.font }).append(root); bbox = text.getBBox(); root.remove(); that._textVerticalOffset = -bbox.y - bbox.height / 2; that._textWidth = bbox.width; that._textHeight = bbox.height } }, _move: function() { var that = this; that._updateBarItemsPositions(); if (that._hasText) { that._text.applySettings({text: formatValue(that._actualValue, that._options.text)}); that._updateTextPosition(); that._updateLinePosition() } }, _updateBarItems: function() { var that = this, options = that._options, backgroundColor, spaceColor; that._setBarSides(); that._startPosition = that._translator.translate(that._translator.getDomainStart()); that._endPosition = that._translator.translate(that._translator.getDomainEnd()); that._basePosition = that._translator.translate(options.baseValue); that._space = that._getSpace(); backgroundColor = options.backgroundColor || 'none'; if (backgroundColor !== 'none' && that._space > 0) spaceColor = options.containerBackgroundColor || 'none'; else { that._space = 0; spaceColor = 'none' } that._backItem1.applySettings({fill: backgroundColor}); that._backItem2.applySettings({fill: backgroundColor}); that._spaceItem1.applySettings({fill: spaceColor}); that._spaceItem2.applySettings({fill: spaceColor}) }, _getSpace: function() { return 0 }, _updateTextItems: function() { var that = this; if (that._hasText) { that._line = that._line || that._renderer.createPath([], {'class': 'dxg-main-bar'}).append(that._rootElement); that._text = that._text || that._renderer.createText('', 0, 0, {'class': 'dxg-text'}).append(that._rootElement); that._text.applySettings({ align: that._getTextAlign(), font: that._getFontOptions() }); that._setTextItemsSides() } else { if (that._line) { that._line.remove(); delete that._line } if (that._text) { that._text.remove(); delete that._text } } }, _isTextVisible: function() { return false }, _getTextAlign: function() { return 'center' }, _getFontOptions: function() { var options = this._options, font = options.text.font; if (!font || !font.color) font = $extend({}, font, {color: options.color}); return font }, _updateBarItemsPositions: function() { var that = this, positions = that._getPositions(); that._backItem1.applySettings(that._buildItemSettings(positions.start, positions.back1)); that._backItem2.applySettings(that._buildItemSettings(positions.back2, positions.end)); that._spaceItem1.applySettings(that._buildItemSettings(positions.back1, positions.main1)); that._spaceItem2.applySettings(that._buildItemSettings(positions.main2, positions.back2)); that._mainItem.applySettings(that._buildItemSettings(positions.main1, positions.main2)); that._trackerElement && that._trackerElement.applySettings(that._buildItemSettings(positions.main1, positions.main2)) }, _render: function() { var that = this; that._measureText(); if (!that._backItem1) { that._backItem1 = that._createBarItem(); that._backItem1.applySettings({'class': 'dxg-back-bar'}) } if (!that._backItem2) { that._backItem2 = that._createBarItem(); that._backItem2.applySettings({'class': 'dxg-back-bar'}) } if (!that._spaceItem1) { that._spaceItem1 = that._createBarItem(); that._spaceItem1.applySettings({'class': 'dxg-space-bar'}) } if (!that._spaceItem2) { that._spaceItem2 = that._createBarItem(); that._spaceItem2.applySettings({'class': 'dxg-space-bar'}) } if (!that._mainItem) { that._mainItem = that._createBarItem(); that._mainItem.applySettings({'class': 'dxg-main-bar'}) } that._updateBarItems(); that._updateTextItems() }, _clear: function() { var that = this; delete that._backItem1; delete that._backItem2; delete that._spaceItem1; delete that._spaceItem2; delete that._mainItem; delete that._hasText; delete that._line; delete that._text }, getTooltipParameters: function() { var position = this._getTooltipPosition(); return { x: position.x, y: position.y, value: this._currentValue, color: this._options.color, offset: 0 } } }) })(DevExpress, jQuery); /*! Module viz-gauges, file circularNeedle.js */ (function(DX, undefined) { var circularNeedles = DX.viz.gauges.__internals.circularNeedles; var _Number = Number; circularNeedles.SimpleIndicator = DX.viz.gauges.__internals.BaseIndicator.inherit({ _move: function() { var that = this, options = that._options, angle = DX.utils.convertAngleToRendererSpace(that._actualPosition); that._rootElement.rotate(angle, options.x, options.y); that._trackerElement && that._trackerElement.rotate(angle, options.x, options.y) }, _isEnabled: function() { return this._options.width > 0 }, _isVisible: function(layout) { return layout.radius - _Number(this._options.indentFromCenter) > 0 }, _getTrackerSettings: function() { var options = this._options, x = options.x, y = options.y - (options.radius + _Number(options.indentFromCenter)) / 2, width = options.width / 2, length = (options.radius - _Number(options.indentFromCenter)) / 2; width > 10 || (width = 10); length > 10 || (length = 10); return {points: [x - width, y - length, x - width, y + length, x + width, y + length, x + width, y - length]} }, _renderSpindle: function() { var that = this, options = that._options, gapSize; if (options.spindleSize > 0) { gapSize = _Number(options.spindleGapSize) || 0; if (gapSize > 0) gapSize = gapSize <= options.spindleSize ? gapSize : _Number(options.spindleSize); that._spindleOuter = that._spindleOuter || that._renderer.createCircle().append(that._rootElement); that._spindleInner = that._spindleInner || that._renderer.createCircle().append(that._rootElement); that._spindleOuter.applySettings({ 'class': 'dxg-spindle-border', cx: options.x, cy: options.y, r: options.spindleSize / 2 }); that._spindleInner.applySettings({ 'class': 'dxg-spindle-hole', cx: options.x, cy: options.y, r: gapSize / 2, fill: options.containerBackgroundColor }) } }, _render: function() { var that = this; that._renderPointer(); that._renderSpindle() }, _clearSpindle: function() { delete this._spindleOuter; delete this._spindleInner }, _clearPointer: function() { delete this._element }, _clear: function() { this._clearPointer(); this._clearSpindle() }, measure: function(layout) { var result = {max: layout.radius}; if (this._options.indentFromCenter < 0) result.inverseHorizontalOffset = result.inverseVerticalOffset = -_Number(this._options.indentFromCenter); return result }, getTooltipParameters: function() { var options = this._options, cossin = DX.utils.getCosAndSin(this._actualPosition), r = (options.radius + _Number(options.indentFromCenter)) / 2; return { x: options.x + cossin.cos * r, y: options.y - cossin.sin * r, value: this._currentValue, color: options.color, offset: options.width / 2 } } }); circularNeedles.RectangleNeedle = circularNeedles.SimpleIndicator.inherit({_renderPointer: function() { var that = this, options = that._options, y2 = options.y - options.radius, y1 = options.y - _Number(options.indentFromCenter), x1 = options.x - options.width / 2, x2 = x1 + _Number(options.width); that._element = that._element || that._renderer.createArea().append(that._rootElement); that._element.applySettings({points: [x1, y1, x1, y2, x2, y2, x2, y1]}) }}); circularNeedles.TriangleNeedle = circularNeedles.SimpleIndicator.inherit({_renderPointer: function() { var that = this, options = that._options, y2 = options.y - options.radius, y1 = options.y - _Number(options.indentFromCenter), x1 = options.x - options.width / 2, x2 = options.x + options.width / 2; that._element = that._element || that._renderer.createArea().append(that._rootElement); that._element.applySettings({points: [x1, y1, options.x, y2, x2, y1]}) }}); circularNeedles.TwoColorRectangleNeedle = circularNeedles.SimpleIndicator.inherit({ _renderPointer: function() { var that = this, options = that._options, x1 = options.x - options.width / 2, x2 = options.x + options.width / 2, y4 = options.y - options.radius, y1 = options.y - _Number(options.indentFromCenter), fraction = _Number(options.secondFraction) || 0, y2, y3; if (fraction >= 1) y2 = y3 = y1; else if (fraction <= 0) y2 = y3 = y2; else { y3 = y4 + (y1 - y4) * fraction; y2 = y3 + options.space } that._firstElement = that._firstElement || that._renderer.createArea().append(that._rootElement); that._spaceElement = that._spaceElement || that._renderer.createArea().append(that._rootElement); that._secondElement = that._secondElement || that._renderer.createArea().append(that._rootElement); that._firstElement.applySettings({points: [x1, y1, x1, y2, x2, y2, x2, y1]}); that._spaceElement.applySettings({ points: [x1, y2, x1, y3, x2, y3, x2, y2], 'class': 'dxg-hole', fill: options.containerBackgroundColor }); that._secondElement.applySettings({ points: [x1, y3, x1, y4, x2, y4, x2, y3], 'class': 'dxg-part', fill: options.secondColor }) }, _clearPointer: function() { delete this._firstElement; delete this._secondElement; delete this._spaceElement } }) })(DevExpress); /*! Module viz-gauges, file linearNeedle.js */ (function(DX, undefined) { var linearNeedles = DX.viz.gauges.__internals.linearNeedles; var _Number = Number; linearNeedles.SimpleIndicator = DX.viz.gauges.__internals.BaseIndicator.inherit({ _move: function() { var that = this, delta = that._actualPosition - that._zeroPosition; that._rootElement.move(that.vertical ? 0 : delta, that.vertical ? delta : 0); that._trackerElement && that._trackerElement.move(that.vertical ? 0 : delta, that.vertical ? delta : 0) }, _isEnabled: function() { this.vertical = this._options.vertical; return this._options.length > 0 && this._options.width > 0 }, _isVisible: function(layout) { return true }, _getTrackerSettings: function() { var options = this._options, x1, x2, y1, y2, width = options.width / 2, length = options.length / 2, p = this._zeroPosition; width > 10 || (width = 10); length > 10 || (length = 10); if (this.vertical) { x1 = options.x - length; x2 = options.x + length; y1 = p + width; y2 = p - width } else { x1 = p - width; x2 = p + width; y1 = options.y + length; y2 = options.y - length } return {points: [x1, y1, x1, y2, x2, y2, x2, y1]} }, _render: function() { var that = this; that._zeroPosition = that._translator.getCodomainStart() }, _clear: function() { delete this._element }, measure: function(layout) { var p = this.vertical ? layout.x : layout.y; return { min: p - this._options.length / 2, max: p + this._options.length / 2 } }, getTooltipParameters: function() { var that = this, options = that._options, p = that._actualPosition, parameters = { x: p, y: p, value: that._currentValue, color: options.color, offset: options.width / 2 }; that.vertical ? parameters.x = options.x : parameters.y = options.y; return parameters } }); linearNeedles.RectangleNeedle = linearNeedles.SimpleIndicator.inherit({_render: function() { var that = this, options = that._options, p, x1, x2, y1, y2; that.callBase(); p = that._zeroPosition; if (that.vertical) { x1 = options.x - options.length / 2; x2 = options.x + options.length / 2; y1 = p + options.width / 2; y2 = p - options.width / 2 } else { x1 = p - options.width / 2; x2 = p + options.width / 2; y1 = options.y + options.length / 2; y2 = options.y - options.length / 2 } that._element = that._element || that._renderer.createArea().append(that._rootElement); that._element.applySettings({points: [x1, y1, x1, y2, x2, y2, x2, y1]}) }}); linearNeedles.RhombusNeedle = linearNeedles.SimpleIndicator.inherit({_render: function() { var that = this, options = that._options, x, y, dx, dy; that.callBase(); if (that.vertical) { x = options.x; y = that._zeroPosition; dx = options.length / 2 || 0; dy = options.width / 2 || 0 } else { x = that._zeroPosition; y = options.y; dx = options.width / 2 || 0; dy = options.length / 2 || 0 } that._element = that._element || that._renderer.createArea().append(that._rootElement); that._element.applySettings({points: [x - dx, y, x, y - dy, x + dx, y, x, y + dy]}) }}); linearNeedles.CircleNeedle = linearNeedles.SimpleIndicator.inherit({_render: function() { var that = this, options = that._options, x, y, r; that.callBase(); if (that.vertical) { x = options.x; y = that._zeroPosition } else { x = that._zeroPosition; y = options.y } r = options.length / 2 || 0; that._element = that._element || that._renderer.createCircle().append(that._rootElement); that._element.applySettings({ cx: x, cy: y, r: r }) }}) })(DevExpress); /*! Module viz-gauges, file circularMarker.js */ (function(DX, undefined) { var circularMarkers = DX.viz.gauges.__internals.circularMarkers; var _Number = Number; circularMarkers.TriangleMarker = DX.viz.gauges.__internals.circularNeedles.SimpleIndicator.inherit({ _isEnabled: function() { return this._options.length > 0 && this._options.width > 0 }, _isVisible: function(layout) { return layout.radius > 0 }, _render: function() { var that = this, options = that._options, x = options.x, y1 = options.y - options.radius, dx = options.width / 2 || 0, y2 = y1 - _Number(options.length), settings; that._element = that._element || that._renderer.createArea().append(that._rootElement); settings = { points: [x, y1, x - dx, y2, x + dx, y2], stroke: 'none', strokeWidth: 0 }; if (options.space > 0) { settings.strokeWidth = Math.min(options.space, options.width / 4) || 0; settings.stroke = settings.strokeWidth > 0 ? options.containerBackgroundColor || 'none' : 'none' } that._element.applySettings(settings) }, _clear: function() { delete this._element }, _getTrackerSettings: function() { var options = this._options, x = options.x, y = options.y - options.radius - options.length / 2, width = options.width / 2, length = options.length / 2; width > 10 || (width = 10); length > 10 || (length = 10); return {points: [x - width, y - length, x - width, y + length, x + width, y + length, x + width, y - length]} }, measure: function(layout) { return { min: layout.radius, max: layout.radius + _Number(this._options.length) } }, getTooltipParameters: function() { var options = this._options, cossin = DX.utils.getCosAndSin(this._actualPosition), r = options.radius + options.length / 2, parameters = this.callBase(); parameters.x = options.x + cossin.cos * r; parameters.y = options.y - cossin.sin * r; parameters.offset = options.length / 2; return parameters } }); circularMarkers.TextCloudMarker = DX.viz.gauges.__internals.BaseTextCloudMarker.inherit({ _isEnabled: function() { return true }, _isVisible: function(layout) { return layout.radius > 0 }, _getTextCloudOptions: function() { var that = this, cossin = DX.utils.getCosAndSin(that._actualPosition), nangle = DX.utils.normalizeAngle(that._actualPosition); return { x: that._options.x + cossin.cos * that._options.radius, y: that._options.y - cossin.sin * that._options.radius, type: nangle > 270 ? 'left-top' : nangle > 180 ? 'top-right' : nangle > 90 ? 'right-bottom' : 'bottom-left' } }, measure: function(layout) { var that = this; that._measureText(); return { min: layout.radius, max: layout.radius, horizontalOffset: that._textFullWidth + (_Number(that._options.arrowLength) || 0), verticalOffset: that._textFullHeight + (_Number(that._options.arrowLength) || 0) } } }) })(DevExpress); /*! Module viz-gauges, file linearMarker.js */ (function(DX, undefined) { var linearMarkers = DX.viz.gauges.__internals.linearMarkers; var _Number = Number, _String = String; linearMarkers.TriangleMarker = DX.viz.gauges.__internals.linearNeedles.SimpleIndicator.inherit({ _isEnabled: function() { var that = this; that.vertical = that._options.vertical; that._inverted = that.vertical ? _String(that._options.horizontalOrientation).toLowerCase() === 'right' : _String(that._options.verticalOrientation).toLowerCase() === 'bottom'; return that._options.length > 0 && that._options.width > 0 }, _isVisible: function(layout) { return true }, _render: function() { var that = this, options = that._options, x1, x2, y1, y2, settings = { stroke: 'none', strokeWidth: 0 }; that.callBase(); if (that.vertical) { x1 = options.x; y1 = that._zeroPosition; x2 = x1 + _Number(that._inverted ? options.length : -options.length); settings.points = [x1, y1, x2, y1 - options.width / 2, x2, y1 + options.width / 2] } else { y1 = options.y; x1 = that._zeroPosition; y2 = y1 + _Number(that._inverted ? options.length : -options.length); settings.points = [x1, y1, x1 - options.width / 2, y2, x1 + options.width / 2, y2] } if (options.space > 0) { settings.strokeWidth = Math.min(options.space, options.width / 4) || 0; settings.stroke = settings.strokeWidth > 0 ? options.containerBackgroundColor || 'none' : 'none' } that._element = that._element || that._renderer.createArea().append(that._rootElement); that._element.applySettings(settings) }, _getTrackerSettings: function() { var that = this, options = that._options, width = options.width / 2, length = _Number(options.length), x1, x2, y1, y2, result; width > 10 || (width = 10); length > 20 || (length = 20); if (that.vertical) { x1 = x2 = options.x; x2 = x1 + (that._inverted ? length : -length); y1 = that._zeroPosition + width; y2 = that._zeroPosition - width; result = [x1, y1, x2, y1, x2, y2, x1, y2] } else { y1 = options.y; y2 = y1 + (that._inverted ? length : -length); x1 = that._zeroPosition - width; x2 = that._zeroPosition + width; result = [x1, y1, x1, y2, x2, y2, x2, y1] } return {points: result} }, measure: function(layout) { var that = this, length = _Number(that._options.length), minbound, maxbound; if (that.vertical) { minbound = maxbound = layout.x; if (that._inverted) maxbound = minbound + length; else minbound = maxbound - length } else { minbound = maxbound = layout.y; if (that._inverted) maxbound = minbound + length; else minbound = maxbound - length } return { min: minbound, max: maxbound, indent: that._options.width / 2 } }, getTooltipParameters: function() { var that = this, options = that._options, s = (that._inverted ? options.length : -options.length) / 2, parameters = that.callBase(); that.vertical ? parameters.x += s : parameters.y += s; parameters.offset = options.length / 2; return parameters } }); linearMarkers.TextCloudMarker = DX.viz.gauges.__internals.BaseTextCloudMarker.inherit({ _isEnabled: function() { var that = this; that.vertical = that._options.vertical; that._inverted = that.vertical ? _String(that._options.horizontalOrientation).toLowerCase() === 'right' : _String(that._options.verticalOrientation).toLowerCase() === 'bottom'; return true }, _isVisible: function(layout) { return true }, _getTextCloudOptions: function() { var that = this, x = that._actualPosition, y = that._actualPosition, type; if (that.vertical) { x = that._options.x; type = that._inverted ? 'top-left' : 'top-right' } else { y = that._options.y; type = that._inverted ? 'right-top' : 'right-bottom' } return { x: x, y: y, type: type } }, measure: function(layout) { var that = this, minbound, maxbound, arrowLength = _Number(that._options.arrowLength) || 0, indent; that._measureText(); if (that.vertical) { indent = that._textFullHeight; if (that._inverted) { minbound = layout.x; maxbound = layout.x + arrowLength + that._textFullWidth } else { minbound = layout.x - arrowLength - that._textFullWidth; maxbound = layout.x } } else { indent = that._textFullWidth; if (that._inverted) { minbound = layout.y; maxbound = layout.y + arrowLength + that._textFullHeight } else { minbound = layout.y - arrowLength - that._textFullHeight; maxbound = layout.y } } return { min: minbound, max: maxbound, indent: indent } } }) })(DevExpress); /*! Module viz-gauges, file circularRangeBar.js */ (function(DX, undefined) { var _Number = Number, getCosAndSin = DX.utils.getCosAndSin, convertAngleToRendererSpace = DX.utils.convertAngleToRendererSpace, max = Math.max, min = Math.min; DX.viz.gauges.__internals.CircularRangeBar = DX.viz.gauges.__internals.BaseRangeBar.inherit({ _isEnabled: function() { return this._options.size > 0 }, _isVisible: function(layout) { return layout.radius - _Number(this._options.size) > 0 }, _createBarItem: function() { return this._renderer.createArc().append(this._rootElement) }, _createTracker: function() { return this._renderer.createArc() }, _setBarSides: function() { var that = this; that._maxSide = that._options.radius; that._minSide = that._maxSide - _Number(that._options.size) }, _getSpace: function() { var options = this._options; return options.space > 0 ? options.space * 180 / options.radius / Math.PI : 0 }, _isTextVisible: function() { var options = this._options.text || {}; return options.indent > 0 }, _setTextItemsSides: function() { var that = this, options = that._options; that._lineFrom = options.y - options.radius; that._lineTo = that._lineFrom - _Number(options.text.indent); that._textRadius = options.radius + _Number(options.text.indent) }, _getPositions: function() { var that = this, basePosition = that._basePosition, actualPosition = that._actualPosition, mainPosition1, mainPosition2; if (basePosition >= actualPosition) { mainPosition1 = basePosition; mainPosition2 = actualPosition } else { mainPosition1 = actualPosition; mainPosition2 = basePosition } return { start: that._startPosition, end: that._endPosition, main1: mainPosition1, main2: mainPosition2, back1: min(mainPosition1 + that._space, that._startPosition), back2: max(mainPosition2 - that._space, that._endPosition) } }, _buildItemSettings: function(from, to) { var that = this; return { x: that._options.x, y: that._options.y, innerRadius: that._minSide, outerRadius: that._maxSide, startAngle: to, endAngle: from } }, _updateTextPosition: function() { var that = this, cossin = getCosAndSin(that._actualPosition), x = that._options.x + that._textRadius * cossin.cos, y = that._options.y - that._textRadius * cossin.sin; x += cossin.cos * that._textWidth * 0.6; y -= cossin.sin * that._textHeight * 0.6; that._text.applySettings({ x: x, y: y + that._textVerticalOffset }) }, _updateLinePosition: function() { var that = this, x = that._options.x, x1, x2; if (that._basePosition > that._actualPosition) { x1 = x - 2; x2 = x } else if (that._basePosition < that._actualPosition) { x1 = x; x2 = x + 2 } else { x1 = x - 1; x2 = x + 1 } that._line.applySettings({points: [x1, that._lineFrom, x1, that._lineTo, x2, that._lineTo, x2, that._lineFrom]}); that._line.rotate(convertAngleToRendererSpace(that._actualPosition), x, that._options.y) }, _getTooltipPosition: function() { var that = this, cossin = getCosAndSin((that._basePosition + that._actualPosition) / 2), r = (that._minSide + that._maxSide) / 2; return { x: that._options.x + cossin.cos * r, y: that._options.y - cossin.sin * r } }, measure: function(layout) { var that = this, result = { min: layout.radius - _Number(that._options.size), max: layout.radius }; that._measureText(); if (that._hasText) { result.max += _Number(that._options.text.indent); result.horizontalOffset = that._textWidth; result.verticalOffset = that._textHeight } return result } }) })(DevExpress); /*! Module viz-gauges, file linearRangeBar.js */ (function(DX, undefined) { var _Number = Number, _String = String; DX.viz.gauges.__internals.LinearRangeBar = DX.viz.gauges.__internals.BaseRangeBar.inherit({ _isEnabled: function() { var that = this; that.vertical = that._options.vertical; that._inverted = that.vertical ? _String(that._options.horizontalOrientation).toLowerCase() === 'right' : _String(that._options.verticalOrientation).toLowerCase() === 'bottom'; return that._options.size > 0 }, _isVisible: function(layout) { return true }, _createBarItem: function() { return this._renderer.createArea().append(this._rootElement) }, _createTracker: function() { return this._renderer.createArea() }, _setBarSides: function() { var that = this, options = that._options, size = _Number(options.size), minSide, maxSide; if (that.vertical) if (that._inverted) { minSide = options.x; maxSide = options.x + size } else { minSide = options.x - size; maxSide = options.x } else if (that._inverted) { minSide = options.y; maxSide = options.y + size } else { minSide = options.y - size; maxSide = options.y } that._minSide = minSide; that._maxSide = maxSide; that._minBound = minSide; that._maxBound = maxSide }, _getSpace: function() { var options = this._options; return options.space > 0 ? _Number(options.space) : 0 }, _isTextVisible: function() { var textOptions = this._options.text || {}; return textOptions.indent > 0 || textOptions.indent < 0 }, _getTextAlign: function() { return this.vertical ? this._options.text.indent > 0 ? 'left' : 'right' : 'center' }, _setTextItemsSides: function() { var that = this, indent = _Number(that._options.text.indent); if (indent > 0) { that._lineStart = that._maxSide; that._lineEnd = that._maxSide + indent; that._textPosition = that._lineEnd + (that.vertical ? 2 : that._textHeight / 2); that._maxBound = that._textPosition + (that.vertical ? that._textWidth : that._textHeight / 2) } else if (indent < 0) { that._lineStart = that._minSide; that._lineEnd = that._minSide + indent; that._textPosition = that._lineEnd - (that.vertical ? 2 : that._textHeight / 2); that._minBound = that._textPosition - (that.vertical ? that._textWidth : that._textHeight / 2) } }, _getPositions: function() { var that = this, options = that._options, startPosition = that._startPosition, endPosition = that._endPosition, space = that._space, basePosition = that._basePosition, actualPosition = that._actualPosition, mainPosition1, mainPosition2, backPosition1, backPosition2; if (startPosition < endPosition) { if (basePosition < actualPosition) { mainPosition1 = basePosition; mainPosition2 = actualPosition } else { mainPosition1 = actualPosition; mainPosition2 = basePosition } backPosition1 = mainPosition1 - space; backPosition2 = mainPosition2 + space } else { if (basePosition > actualPosition) { mainPosition1 = basePosition; mainPosition2 = actualPosition } else { mainPosition1 = actualPosition; mainPosition2 = basePosition } backPosition1 = mainPosition1 + space; backPosition2 = mainPosition2 - space } return { start: startPosition, end: endPosition, main1: mainPosition1, main2: mainPosition2, back1: backPosition1, back2: backPosition2 } }, _buildItemSettings: function(from, to) { var that = this, side1 = that._minSide, side2 = that._maxSide; var points = that.vertical ? [side1, from, side1, to, side2, to, side2, from] : [from, side1, from, side2, to, side2, to, side1]; return {points: points} }, _updateTextPosition: function() { var that = this; that._text.applySettings(that.vertical ? { x: that._textPosition, y: that._actualPosition + that._textVerticalOffset } : { x: that._actualPosition, y: that._textPosition + that._textVerticalOffset }) }, _updateLinePosition: function() { var that = this, actualPosition = that._actualPosition, side1, side2, points; if (that.vertical) { if (that._basePosition >= actualPosition) { side1 = actualPosition; side2 = actualPosition + 2 } else { side1 = actualPosition - 2; side2 = actualPosition } points = [that._lineStart, side1, that._lineStart, side2, that._lineEnd, side2, that._lineEnd, side1] } else { if (that._basePosition <= actualPosition) { side1 = actualPosition - 2; side2 = actualPosition } else { side1 = actualPosition; side2 = actualPosition + 2 } points = [side1, that._lineStart, side1, that._lineEnd, side2, that._lineEnd, side2, that._lineStart] } that._line.applySettings({points: points}) }, _getTooltipPosition: function() { var that = this, crossCenter = (that._minSide + that._maxSide) / 2, alongCenter = (that._basePosition + that._actualPosition) / 2, position = {}; if (that.vertical) position = { x: crossCenter, y: alongCenter }; else position = { x: alongCenter, y: crossCenter }; return position }, measure: function(layout) { var that = this, size = _Number(that._options.size), textIndent = _Number(that._options.text.indent), minbound, maxbound, indent; that._measureText(); if (that.vertical) { minbound = maxbound = layout.x; if (that._inverted) maxbound = maxbound + size; else minbound = minbound - size; if (that._hasText) { indent = that._textHeight / 2; if (textIndent > 0) maxbound += textIndent + that._textWidth; if (textIndent < 0) minbound += textIndent - that._textWidth } } else { minbound = maxbound = layout.y; if (that._inverted) maxbound = maxbound + size; else minbound = minbound - size; if (that._hasText) { indent = that._textWidth / 2; if (textIndent > 0) maxbound += textIndent + that._textHeight; if (textIndent < 0) minbound += textIndent - that._textHeight } } return { min: minbound, max: maxbound, indent: indent } } }) })(DevExpress); /*! Module viz-gauges, file rangeContainer.js */ (function(DX, $, undefined) { var _Number = Number, _String = String, _max = Math.max, _abs = Math.abs, _isString = DX.utils.isString, _isArray = DX.utils.isArray, _isFinite = isFinite, _each = $.each, _map = $.map; var _Palette = DX.viz.core.Palette; DX.viz.gauges.__internals.BaseRangeContainer = DX.Class.inherit({ ctor: function(parameters) { var that = this; that._renderer = parameters.renderer; that._container = parameters.container; that._translator = parameters.translator; that._root = that._renderer.createGroup({'class': 'dxg-range-container'}) }, dispose: function() { var that = this; that._renderer = that._container = that._translator = that._root = null }, clean: function() { this._root.detach().clear(); this._options = this.enabled = null; return this }, _getRanges: function() { var that = this, options = that._options, translator = that._translator, totalStart = translator.getDomain()[0], totalEnd = translator.getDomain()[1], totalDelta = totalEnd - totalStart, isNotEmptySegment = totalDelta >= 0 ? isNotEmptySegmentAsc : isNotEmptySegmentDes, subtractSegment = totalDelta >= 0 ? subtractSegmentAsc : subtractSegmentDes, list = [], ranges = [], backgroundRanges = [{ start: totalStart, end: totalEnd }], threshold = _abs(totalDelta) / 1E4, palette = new _Palette(options.palette, { type: 'indicatingSet', theme: options.themeName }), backgroundColor = _isString(options.backgroundColor) ? options.backgroundColor : 'none', width = options.width || {}, startWidth = _Number(width > 0 ? width : width.start), endWidth = _Number(width > 0 ? width : width.end), deltaWidth = endWidth - startWidth; if (options.ranges !== undefined && !_isArray(options.ranges)) return null; if (!(startWidth >= 0 && endWidth >= 0 && startWidth + endWidth > 0)) return null; list = _map(_isArray(options.ranges) ? options.ranges : [], function(rangeOptions, i) { rangeOptions = rangeOptions || {}; var start = translator.adjust(rangeOptions.startValue), end = translator.adjust(rangeOptions.endValue); return _isFinite(start) && _isFinite(end) && isNotEmptySegment(start, end, threshold) ? { start: start, end: end, color: rangeOptions.color, classIndex: i } : null }); _each(list, function(i, item) { var paletteColor = palette.getNextColor(); item.color = _isString(item.color) && item.color || paletteColor || 'none'; item.className = 'dxg-range dxg-range-' + item.classIndex; delete item.classIndex }); _each(list, function(_, item) { var i, ii, sub, subs, range, newRanges = [], newBackgroundRanges = []; for (i = 0, ii = ranges.length; i < ii; ++i) { range = ranges[i]; subs = subtractSegment(range.start, range.end, item.start, item.end); (sub = subs[0]) && (sub.color = range.color) && (sub.className = range.className) && newRanges.push(sub); (sub = subs[1]) && (sub.color = range.color) && (sub.className = range.className) && newRanges.push(sub) } newRanges.push(item); ranges = newRanges; for (i = 0, ii = backgroundRanges.length; i < ii; ++i) { range = backgroundRanges[i]; subs = subtractSegment(range.start, range.end, item.start, item.end); (sub = subs[0]) && newBackgroundRanges.push(sub); (sub = subs[1]) && newBackgroundRanges.push(sub) } backgroundRanges = newBackgroundRanges }); _each(backgroundRanges, function(_, range) { range.color = backgroundColor; range.className = 'dxg-range dxg-background-range'; ranges.push(range) }); _each(ranges, function(_, range) { range.startWidth = (range.start - totalStart) / totalDelta * deltaWidth + startWidth; range.endWidth = (range.end - totalStart) / totalDelta * deltaWidth + startWidth }); return ranges }, render: function(options) { var that = this; that._options = options; that._processOptions(); that._ranges = that._getRanges(); if (that._ranges) { that.enabled = true; that._root.append(that._container) } return that }, resize: function(layout) { var that = this; that._root.clear(); if (that._isVisible(layout)) _each(that._ranges, function(_, range) { that._createRange(range, layout).applySettings({ fill: range.color, 'class': range.className }).append(that._root) }); return that }, _processOptions: null, _isVisible: null, _createRange: null }); function subtractSegmentAsc(segmentStart, segmentEnd, otherStart, otherEnd) { var result; if (otherStart > segmentStart && otherEnd < segmentEnd) result = [{ start: segmentStart, end: otherStart }, { start: otherEnd, end: segmentEnd }]; else if (otherStart >= segmentEnd || otherEnd <= segmentStart) result = [{ start: segmentStart, end: segmentEnd }]; else if (otherStart <= segmentStart && otherEnd >= segmentEnd) result = []; else if (otherStart > segmentStart) result = [{ start: segmentStart, end: otherStart }]; else if (otherEnd < segmentEnd) result = [{ start: otherEnd, end: segmentEnd }]; return result } function subtractSegmentDes(segmentStart, segmentEnd, otherStart, otherEnd) { var result; if (otherStart < segmentStart && otherEnd > segmentEnd) result = [{ start: segmentStart, end: otherStart }, { start: otherEnd, end: segmentEnd }]; else if (otherStart <= segmentEnd || otherEnd >= segmentStart) result = [{ start: segmentStart, end: segmentEnd }]; else if (otherStart >= segmentStart && otherEnd <= segmentEnd) result = []; else if (otherStart < segmentStart) result = [{ start: segmentStart, end: otherStart }]; else if (otherEnd > segmentEnd) result = [{ start: otherEnd, end: segmentEnd }]; return result } function isNotEmptySegmentAsc(start, end, threshold) { return end - start >= threshold } function isNotEmptySegmentDes(start, end, threshold) { return start - end >= threshold } DX.viz.gauges.__internals.CircularRangeContainer = DX.viz.gauges.__internals.BaseRangeContainer.inherit({ _processOptions: function() { var that = this; that._inner = that._outer = 0; switch (_String(that._options.orientation).toLowerCase()) { case'inside': that._inner = 1; break; case'center': that._inner = that._outer = 0.5; break; default: that._outer = 1; break } }, _isVisible: function(layout) { var width = this._options.width; width = _Number(width) || _max(_Number(width.start), _Number(width.end)); return layout.radius - this._inner * width > 0 }, _createRange: function(range, layout) { var that = this, width = (range.startWidth + range.endWidth) / 2; return that._renderer.createArc(layout.x, layout.y, layout.radius + that._outer * width, layout.radius - that._inner * width, that._translator.translate(range.end), that._translator.translate(range.start)) }, measure: function(layout) { var width = this._options.width; width = _Number(width) || _max(_Number(width.start), _Number(width.end)); return { min: layout.radius - this._inner * width, max: layout.radius + this._outer * width } } }); DX.viz.gauges.__internals.LinearRangeContainer = DX.viz.gauges.__internals.BaseRangeContainer.inherit({ _processOptions: function() { var that = this; that.vertical = that._options.vertical; that._inner = that._outer = 0; if (that.vertical) switch (_String(that._options.horizontalOrientation).toLowerCase()) { case'left': that._inner = 1; break; case'center': that._inner = that._outer = 0.5; break; default: that._outer = 1; break } else switch (_String(that._options.verticalOrientation).toLowerCase()) { case'top': that._inner = 1; break; case'middle': that._inner = that._outer = 0.5; break; default: that._outer = 1; break } }, _isVisible: function(layout) { return true }, _createRange: function(range, layout) { var that = this, inner = that._inner, outer = that._outer, startPosition = that._translator.translate(range.start), endPosition = that._translator.translate(range.end), points; if (that.vertical) points = [layout.x - range.startWidth * inner, startPosition, layout.x - range.endWidth * inner, endPosition, layout.x + range.endWidth * outer, endPosition, layout.x + range.startWidth * outer, startPosition]; else points = [startPosition, layout.y + range.startWidth * outer, startPosition, layout.y - range.startWidth * inner, endPosition, layout.y - range.endWidth * inner, endPosition, layout.y + range.endWidth * outer]; return that._renderer.createArea(points) }, measure: function(layout) { var result = {}; result.min = result.max = layout[this.vertical ? 'x' : 'y']; var width = this._options.width; width = _Number(width) || _max(_Number(width.start), _Number(width.end)); result.min -= this._inner * width; result.max += this._outer * width; return result } }) })(DevExpress, jQuery); /*! Module viz-gauges, file title.js */ (function(DX, $, undefined) { var _isString = DX.utils.isString, _max = Math.max, _extend = $.extend; DX.viz.gauges.__internals.Title = DX.Class.inherit({ ctor: function(parameters) { this._renderer = parameters.renderer; this._container = parameters.container }, dispose: function() { this._renderer = this._container = null; return this }, clean: function() { var that = this; if (that._root) { that._root.detach().clear(); that._root = that._layout = null } return that }, render: function(titleOptions, subtitleOptions) { var that = this, hasTitle = _isString(titleOptions.text) && titleOptions.text.length > 0, hasSubtitle = _isString(subtitleOptions.text) && subtitleOptions.text.length > 0; if (!hasTitle && !hasSubtitle) return that; that._root = that._renderer.createGroup({'class': 'dxg-title'}).append(that._container); var title = hasTitle ? that._renderer.createText(titleOptions.text, 0, 0, { align: 'center', font: titleOptions.font }).append(that._root) : null, subtitle = hasSubtitle ? that._renderer.createText(subtitleOptions.text, 0, 0, { align: 'center', font: subtitleOptions.font }).append(that._root) : null, titleBox = title ? title.getBBox() : {}, subtitleBox = subtitle ? subtitle.getBBox() : {}, y = 0; if (title) { y += -titleBox.y; title.applySettings({ x: 0, y: y }) } if (subtitle) { y += -subtitleBox.y; subtitle.applySettings({ x: 0, y: y }) } that._layout = _extend({ position: titleOptions.position, width: _max(titleBox.width || 0, subtitleBox.width || 0), height: title && subtitle ? -titleBox.y + subtitleBox.height : titleBox.height || subtitleBox.height }, titleOptions.layout); return that }, getLayoutOptions: function() { return this._layout }, locate: function(left, top) { this._root.applySettings({ translateX: left + this._layout.width / 2, translateY: top }); return this } }) })(DevExpress, jQuery); /*! Module viz-gauges, file tooltip.js */ (function(DX, $, undefined) { var _extend = $.extend; DX.viz.gauges.__internals.Tooltip = DX.viz.core.Tooltip.inherit({ ctor: function(parameters) { var that = this; that._container = parameters.container; that._tracker = parameters.tracker; that._root = parameters.renderer.createGroup({'class': 'dxg-tooltip'}); that.callBase(null, that._root, parameters.renderer); that._setTrackerCallbacks() }, dispose: function() { var that = this; that._container = that._tracker = that._root = null; return that._shadow ? that.callBase.apply(that, arguments) : that }, _setTrackerCallbacks: function() { var that = this; function prepareCallback(target, info) { var tooltipParameters = target.getTooltipParameters(), formatObject = _extend({ value: tooltipParameters.value, valueText: that.formatValue(tooltipParameters.value), color: tooltipParameters.color }, info); return that.prepare(formatObject, { x: tooltipParameters.x, y: tooltipParameters.y, offset: tooltipParameters.offset }) } function showCallback() { return that.show() } function hideCallback() { return that.hide() } that._tracker.setCallbacks({ 'tooltip-prepare': prepareCallback, 'tooltip-show': showCallback, 'tooltip-hide': hideCallback }) }, clean: function() { this._root.detach(); return this }, render: function(options, size) { var that = this; options.canvasWidth = size.width; options.canvasHeight = size.height; options.text = {'class': 'dxg-text'}; that.update(options); that._tracker.setTooltipState(that.enabled()); that.enabled() && that._root.append(that._container); return that } }) })(DevExpress, jQuery); /*! Module viz-gauges, file layoutManager.js */ (function(DX, $, undefined) { var _Number = Number, _String = String, _min = Math.min, _max = Math.max, _each = $.each; function patchLayoutOptions(options) { if (options.position) { var position = _String(options.position).toLowerCase().split('-'); options.verticalAlignment = position[0]; options.horizontalAlignment = position[1] } } DX.viz.gauges.__internals.LayoutManager = DX.Class.inherit({ setRect: function(rect) { this._currentRect = rect.clone(); return this }, getRect: function() { return this._currentRect.clone() }, beginLayout: function(rect) { this._rootRect = rect.clone(); this._currentRect = rect.clone(); this._cache = []; return this }, applyLayout: function(target) { var options = target.getLayoutOptions(); if (!options) return this; var currentRect = this._currentRect, verticalOverlay = _Number(options.overlay) || 0; patchLayoutOptions(options); switch (_String(options.verticalAlignment).toLowerCase()) { case'bottom': currentRect.bottom -= _max(options.height - verticalOverlay, 0); break; default: currentRect.top += _max(options.height - verticalOverlay, 0); break } this._cache.push({ target: target, options: options }); return this }, endLayout: function() { var that = this, rootRect = that._rootRect, currentRect = that._currentRect; _each(that._cache, function(_, cacheItem) { var options = cacheItem.options, left, top, verticalOverlay = _Number(options.overlay) || 0; switch (_String(options.verticalAlignment).toLowerCase()) { case'bottom': top = currentRect.bottom - verticalOverlay; currentRect.bottom += _max(options.height - verticalOverlay, 0); break; default: top = currentRect.top - options.height + verticalOverlay; currentRect.top -= _max(options.height - verticalOverlay, 0); break } switch (_String(options.horizontalAlignment).toLowerCase()) { case'left': left = rootRect.left; break; case'right': left = rootRect.right - options.width; break; default: left = rootRect.horizontalMiddle() - options.width / 2; break } cacheItem.target.locate(left, top) }); that._cache = null; return that }, selectRectByAspectRatio: function(aspectRatio, margins) { var rect = this._currentRect.clone(), selfAspectRatio, width = 0, height = 0; margins = margins || {}; if (aspectRatio > 0) { rect.left += margins.left || 0; rect.right -= margins.right || 0; rect.top += margins.top || 0; rect.bottom -= margins.bottom || 0; if (rect.width() > 0 && rect.height() > 0) { selfAspectRatio = rect.height() / rect.width(); if (selfAspectRatio > 1) aspectRatio < selfAspectRatio ? width = rect.width() : height = rect.height(); else aspectRatio > selfAspectRatio ? height = rect.height() : width = rect.width(); width > 0 || (width = height / aspectRatio); height > 0 || (height = width * aspectRatio); width = (rect.width() - width) / 2; height = (rect.height() - height) / 2; rect.left += width; rect.right -= width; rect.top += height; rect.bottom -= height } else { rect.left = rect.right = rect.horizontalMiddle(); rect.top = rect.bottom = rect.verticalMiddle() } } return rect }, selectRectBySizes: function(sizes, margins) { var rect = this._currentRect.clone(), step; margins = margins || {}; if (sizes) { rect.left += margins.left || 0; rect.right -= margins.right || 0; rect.top += margins.top || 0; rect.bottom -= margins.bottom || 0; if (sizes.width > 0) { step = (rect.width() - sizes.width) / 2; if (step > 0) { rect.left += step; rect.right -= step } } if (sizes.height > 0) { step = (rect.height() - sizes.height) / 2; if (step > 0) { rect.top += step; rect.bottom -= step } } } return rect } }) })(DevExpress, jQuery); /*! Module viz-gauges, file themeManager.js */ (function(DX, $, undefined) { var _extend = $.extend; DX.viz.gauges.__internals.ThemeManager = DX.viz.core.BaseThemeManager.inherit({ _themeSection: 'gauge', _initializeTheme: function() { var that = this; if (that._subTheme) { var subTheme = _extend(true, {}, that._theme[that._subTheme], that._theme); _extend(true, that._theme, subTheme) } that._initializeFont(that._theme.scale.label.font); that._initializeFont(that._theme.valueIndicator.rangebar.text.font); that._initializeFont(that._theme.subvalueIndicator.textcloud.text.font); that._initializeFont(that._theme.valueIndicators.rangebar.text.font); that._initializeFont(that._theme.valueIndicators.textcloud.text.font); that._initializeFont(that._theme.title.font); that._initializeFont(that._theme.subtitle.font); that._initializeFont(that._theme.tooltip.font); that._initializeFont(that._theme.indicator.text.font); that._initializeFont(that._theme.loadingIndicator.font) } }) })(DevExpress, jQuery); /*! Module viz-gauges, file presetManager.js */ /*! Module viz-gauges, file baseGauge.js */ (function(DX, $, undefined) { var _Number = Number, _isNumber = DX.utils.isNumber, _isString = DX.utils.isString, _getAppropriateFormat = DX.utils.getAppropriateFormat, _extend = $.extend, _each = $.each; DX.viz.gauges.__internals.BaseGauge = DX.viz.core.BaseWidget.inherit({ _init: function() { var that = this; that.callBase.apply(that, arguments); that._renderer = that._factory.createRenderer({ width: 1, height: 1, pathModified: that.option('pathModified'), rtl: that.option('rtlEnabled') }); that._root = that._renderer.getRoot(); that._root.applySettings({'class': 'dxg ' + that._rootClass}); that._translator = that._factory.createTranslator(); that._themeManager = that._factory.createThemeManager(); that._tracker = that._factory.createTracker({ renderer: that._renderer, container: that._root }); that._layoutManager = that._factory.createLayoutManager(); that._tooltip = that._factory.createTooltip({ renderer: that._renderer, container: that._root, tracker: that._tracker }); that._title = that._factory.createTitle({ renderer: that._renderer, container: that._root }); that._deltaIndicator = that._factory.createDeltaIndicator({ renderer: that._renderer, container: that._root }); that._setupDomain(); that._themeManager.setTheme(that.option('theme')) }, _dispose: function() { var that = this; that.callBase.apply(that, arguments); that._renderer.dispose(); that._themeManager.dispose(); that._tracker.dispose(); that._title.dispose(); that._deltaIndicator && that._deltaIndicator.dispose(); that._tooltip.dispose(); that._disposeLoadIndicator(); that._renderer = that._root = that._translator = that._themeManager = that._tracker = that._layoutManager = that._title = that._tooltip = null }, _refresh: function() { var that = this, callBase = that.callBase; that._endLoading(function() { callBase.call(that) }) }, _clean: function() { this._cleanCore() }, _render: function() { var that = this; that._setupCodomain(); that._setupAnimationSettings(); if (that._calculateSize() && that._checkDomain()) { that._renderer.draw(that._element()[0]); that._setupDefaultFormat(); that._renderCore() } that._drawn() }, _cleanCore: function() { var that = this; that._tooltip.clean(); that._title.clean(); that._deltaIndicator && that._deltaIndicator.clean(); that._tracker.deactivate(); that._cleanContent() }, _renderCore: function() { var that = this; that._title.render(_extend(true, {}, that._themeManager.theme()['title'], processTitleOptions(that.option('title'))), _extend(true, {}, that._themeManager.theme()['subtitle'], processTitleOptions(that.option('subtitle')))); that._deltaIndicator && that._deltaIndicator.render(_extend(true, {}, that._themeManager.theme()['indicator'], that.option('indicator'))); that._layoutManager.beginLayout(that._rootRect); _each([that._deltaIndicator, that._title], function(_, item) { item && that._layoutManager.applyLayout(item) }); that._mainRect = that._layoutManager.getRect(); that._renderContent(); that._layoutManager.endLayout(); that._tooltip.render(_extend(true, {}, that._themeManager.theme()['tooltip'], that.option('tooltip')), { width: that._width, height: that._height }); that._tracker.activate(); that._updateLoadIndicator(undefined, that._width, that._height); that._noAnimation = null; that.option('debugMode') === true && that._renderDebugInfo(); that._debug_rendered && that._debug_rendered() }, _renderDebugInfo: function() { var that = this, group = that._debugGroup || that._renderer.createGroup({'class': 'debug-info'}).append(), rect; group.clear(); rect = that._rootRect; that._renderer.createRect(rect.left, rect.top, rect.width(), rect.height(), 0, { stroke: '#000000', strokeWidth: 1, fill: 'none' }).append(group); rect = that._mainRect; that._renderer.createRect(rect.left, rect.top, rect.width(), rect.height(), 0, { stroke: '#0000FF', strokeWidth: 1, fill: 'none' }).append(group); rect = that._layoutManager.getRect(); rect && that._renderer.createRect(rect.left, rect.top, rect.width(), rect.height(), 0, { stroke: '#FF0000', strokeWidth: 1, fill: 'none' }).append(group); rect = that._title.getLayoutOptions() ? that._title._root.getBBox() : null; rect && that._renderer.createRect(rect.x, rect.y, rect.width, rect.height, 0, { stroke: '#00FF00', strokeWidth: 1, fill: 'none' }).append(group); rect = that._deltaIndicator && that._deltaIndicator.getLayoutOptions() ? that._deltaIndicator._root.getBBox() : null; rect && that._renderer.createRect(rect.x, rect.y, rect.width, rect.height, 0, { stroke: '#00FF00', strokeWidth: 1, fill: 'none' }).append(group) }, _resize: function() { var that = this; if (that._calculateSize()) { that._resizing = that._noAnimation = true; that._cleanCore(); that._renderCore(); that._resizing = null } }, render: function(options) { options && options.animate !== undefined && !options.animate && (this._noAnimation = true); this._refresh(); return this }, showLoadingIndicator: function() { this._showLoadIndicator(this._getLoadIndicatorOption(), { width: this._width, height: this._height }) }, _getLoadIndicatorOption: function() { return _extend(true, {}, this._themeManager.theme()['loadingIndicator'], this.option('loadingIndicator')) }, _optionChanged: function(name, newv, oldv) { var that = this; switch (name) { case'theme': that._themeManager.setTheme(newv); that._invalidate(); break; case'startValue': case'endValue': that._setupDomain(); that._invalidate(); break; default: that.callBase.apply(that, arguments); break } }, _calculateSize: function() { var that = this; that._calculateSizeCore(); if (that._width === 0 || that._height === 0 || !that._element().is(':visible')) { that._incidentOccured('W2001', [that.NAME]); return false } else { that._renderer.resize(that._width, that._height); return true } }, _checkDomain: function() { var that = this, domain = that._translator.getDomain(), isValid = isFinite(1 / (domain[1] - domain[0])); if (!isValid) that._incidentOccured('W2301'); return isValid }, _setupAnimationSettings: function() { var that = this, option = that.option('animation'); that._animationSettings = null; if (option === undefined || option) { if (option === undefined) option = { enabled: that.option('animationEnabled'), duration: that.option('animationDuration') }; option = _extend({ enabled: true, duration: 1000, easing: 'easeOutCubic' }, option); if (option.enabled && option.duration > 0) that._animationSettings = { duration: _Number(option.duration), easing: option.easing } } that._containerBackgroundColor = that.option('containerBackgroundColor') || that._themeManager.theme().containerBackgroundColor }, _setupDefaultFormat: function() { var domain = this._translator.getDomain(); this._defaultFormatOptions = _getAppropriateFormat(domain[0], domain[1], this._getApproximateScreenRange()) }, _setupDomain: null, _calculateSizeCore: null, _cleanContent: null, _renderContent: null, _setupCodomain: null, _getApproximateScreenRange: null, _factory: { createRenderer: DX.viz.core.CoreFactory.createRenderer, createTranslator: function() { return new DX.viz.core.Translator1D }, createTracker: function(parameters) { return new DX.viz.gauges.__internals.Tracker(parameters) }, createLayoutManager: function() { return new DX.viz.gauges.__internals.LayoutManager }, createTitle: function(parameters) { return new DX.viz.gauges.__internals.Title(parameters) }, createDeltaIndicator: function(parameters) { return DX.viz.gauges.__internals.DeltaIndicator ? new DX.viz.gauges.__internals.DeltaIndicator(parameters) : null }, createTooltip: function(parameters) { return new DX.viz.gauges.__internals.Tooltip(parameters) } } }); function processTitleOptions(options) { return _isString(options) ? {text: options} : options || {} } })(DevExpress, jQuery); /*! Module viz-gauges, file gauge.js */ (function(DX, $, undefined) { var _Rectangle = DX.viz.core.Rectangle; var _isDefined = DX.utils.isDefined, _isArray = DX.utils.isArray, _isNumber = DX.utils.isNumber, _isFinite = isFinite, _Number = Number, _String = String, _abs = Math.abs, _extend = $.extend, _each = $.each, _map = $.map, _noop = $.noop; var OPTION_VALUE = 'value', OPTION_SUBVALUES = 'subvalues'; DX.viz.gauges.Gauge = DX.viz.gauges.__internals.BaseGauge.inherit({ _init: function() { var that = this; that.__value = that.option(OPTION_VALUE); that.__subvalues = that.option(OPTION_SUBVALUES); if (!_isArray(that.__subvalues)) that.__subvalues = _isNumber(that.__subvalues) ? [that.__subvalues] : null; that._selectMode(); that.callBase.apply(that, arguments); that._scale = that._createScale({ renderer: that._renderer, container: that._root, translator: that._translator }); that._rangeContainer = that._createRangeContainer({ renderer: that._renderer, container: that._root, translator: that._translator }) }, _dispose: function() { var that = this; that.callBase.apply(that, arguments); that._scale.dispose(); that._rangeContainer.dispose(); that._disposeValueIndicators(); that._scale = that._rangeContainer = null }, _disposeValueIndicators: function() { var that = this; that._valueIndicator && that._valueIndicator.dispose(); that._subvalueIndicatorsSet && that._subvalueIndicatorsSet.dispose(); that._valueIndicator = that._subvalueIndicatorsSet = null }, _selectMode: function() { var that = this; if (that.option(OPTION_VALUE) === undefined && that.option(OPTION_SUBVALUES) === undefined) if (that.option('needles') !== undefined || that.option('markers') !== undefined || that.option('rangeBars') !== undefined) { disableDefaultMode(that); selectObsoleteMode(that) } else if (that.option('valueIndicators') !== undefined) { disableDefaultMode(that); selectHardMode(that) } }, _setupDomain: function() { var that = this, scaleOption = that.option('scale') || {}, startValue = that.option('startValue'), endValue = that.option('endValue'); startValue = _isNumber(startValue) ? _Number(startValue) : _isNumber(scaleOption.startValue) ? _Number(scaleOption.startValue) : 0; endValue = _isNumber(endValue) ? _Number(endValue) : _isNumber(scaleOption.endValue) ? _Number(scaleOption.endValue) : 100; that._baseValue = startValue < endValue ? startValue : endValue; that._translator.setDomain(startValue, endValue); that._setupValueState() }, _setupValueState: function() { this._setupValue(); this.__subvalues !== null && this._setupSubvalues() }, _calculateSizeCore: function() { var that = this, size = that.option('size') || {}, margin = that.option('margin') || {}; if (_Number(size.width) === 0 || _Number(size.height) === 0) { that._width = that._height = 0; that._rootRect = new _Rectangle } else { var width = size.width > 0 ? _Number(size.width) : that._element().width() || that._getDefaultContainerSize().width, height = size.height > 0 ? _Number(size.height) : that._element().height() || that._getDefaultContainerSize().height, marginL = margin.left > 0 ? _Number(margin.left) : 0, marginR = margin.right > 0 ? _Number(margin.right) : 0, marginT = margin.top > 0 ? _Number(margin.top) : 0, marginB = margin.bottom > 0 ? _Number(margin.bottom) : 0; marginL + marginR >= width && (marginL = marginR = 0); marginT + marginB >= height && (marginT = marginB = 0); that._width = width; that._height = height; that._rootRect = new _Rectangle({ left: marginL, top: marginT, right: width - marginR, bottom: height - marginB }) } }, _cleanContent: function() { var that = this; that._rangeContainer.clean(); that._scale.clean(); that._cleanValueIndicators() }, _renderContent: function() { var that = this; that._rangeContainer.render(_extend(true, {}, that._themeManager.theme().rangeContainer, that.option('rangeContainer'), { themeName: that._themeManager.themeName(), vertical: that._area.vertical })); that._scale.render(_extend(true, {}, that._themeManager.theme().scale, that.option('scale'), { approximateScreenDelta: that._getApproximateScreenRange(), offset: 0, vertical: that._area.vertical })); var elements = that._prepareValueIndicators(); elements = _map([that._scale, that._rangeContainer].concat(elements), function(element) { return element && element.enabled ? element : null }); that._applyMainLayout(elements); _each(elements, function(_, element) { that._updateElementPosition(element) }); that._updateActiveElements() }, _updateIndicatorSettings: function(settings) { var that = this; settings.currentValue = settings.baseValue = _isFinite(that._translator.translate(settings.baseValue)) ? _Number(settings.baseValue) : that._baseValue; settings.vertical = that._area.vertical; if (settings.text && !settings.text.format && !settings.text.precision) { settings.text.format = that._defaultFormatOptions.format; settings.text.precision = that._defaultFormatOptions.precision } }, _prepareValueIndicatorSettings: function() { var that = this, options = that.option('valueIndicator') || {}, defaultOptions = _extend(true, {}, that._themeManager.theme().valueIndicator), type = _String(options.type || defaultOptions.type).toLowerCase(); that._valueIndicatorSettings = _extend(true, defaultOptions._default, defaultOptions[type], options, { type: type, animation: that._animationSettings, containerBackgroundColor: that._containerBackgroundColor }); that._updateIndicatorSettings(that._valueIndicatorSettings) }, _prepareSubvalueIndicatorSettings: function() { var that = this, options = that.option('subvalueIndicator') || {}, defaultOptions = _extend(true, {}, that._themeManager.theme().subvalueIndicator), type = _String(options.type || defaultOptions.type).toLowerCase(); that._subvalueIndicatorSettings = _extend(true, defaultOptions._default, defaultOptions[type], options, { type: type, animation: that._animationSettings, containerBackgroundColor: that._containerBackgroundColor }); that._updateIndicatorSettings(that._subvalueIndicatorSettings) }, _cleanValueIndicators: function() { this._valueIndicator && this._valueIndicator.clean(); this._subvalueIndicatorsSet && this._subvalueIndicatorsSet.clean() }, _prepareValueIndicators: function() { var that = this; that._prepareValueIndicator(); that.__subvalues !== null && that._prepareSubvalueIndicators(); return [that._valueIndicator, that._subvalueIndicatorsSet] }, _updateActiveElements: function() { this._updateValueIndicator(); this._updateSubvalueIndicators() }, _prepareValueIndicator: function() { var that = this, indicator = that._valueIndicator, currentValue; that._prepareValueIndicatorSettings(); indicator && that._valueIndicatorType !== that._valueIndicatorSettings.type && indicator.dispose() && (indicator = null); that._valueIndicatorType = that._valueIndicatorSettings.type; if (!indicator) { indicator = that._valueIndicator = that._createValueIndicator(that._valueIndicatorType); if (indicator) { indicator.setup({ renderer: that._renderer, translator: that._translator, owner: that._root, tracker: that._tracker, className: 'dxg-value-indicator' }); indicator._trackerInfo = {type: 'value-indicator'} } } indicator.render(that._valueIndicatorSettings) }, _prepareSubvalueIndicators: function() { var that = this, subvalueIndicatorsSet = that._subvalueIndicatorsSet; if (!subvalueIndicatorsSet) subvalueIndicatorsSet = that._subvalueIndicatorsSet = new DX.viz.gauges.__internals.ValueIndicatorsSet({ renderer: that._renderer, translator: that._translator, owner: that._root, tracker: that._tracker, className: 'dxg-subvalue-indicators', indicatorClassName: 'dxg-subvalue-indicator', trackerType: 'subvalue-indicator', createIndicator: function() { return that._createSubvalueIndicator(that._subvalueIndicatorType) } }); that._prepareSubvalueIndicatorSettings(); var isRecreate = that._subvalueIndicatorSettings.type !== that._subvalueIndicatorType; that._subvalueIndicatorType = that._subvalueIndicatorSettings.type; if (that._createSubvalueIndicator(that._subvalueIndicatorType)) subvalueIndicatorsSet.render(that._subvalueIndicatorSettings, isRecreate) }, _processValue: function(value, fallbackValue) { var _value = this._translator.adjust(value !== undefined ? value : this.__value); return _isFinite(_value) ? _value : fallbackValue }, _setupValue: function(value) { this.__value = this._processValue(value, this.__value) }, _setupSubvalues: function(subvalues) { var _subvalues = subvalues === undefined ? this.__subvalues : _isArray(subvalues) ? subvalues : _isNumber(subvalues) ? [subvalues] : null; if (_subvalues === null) return; var i = 0, ii = _subvalues.length, list = []; for (; i < ii; ++i) list.push(this._processValue(_subvalues[i], this.__subvalues[i])); this.__subvalues = list }, _updateValueIndicator: function() { var that = this; that._valueIndicator && that._valueIndicator.value(that.__value, that._noAnimation); that._resizing || that.hideLoadingIndicator() }, _updateSubvalueIndicators: function() { var that = this; that._subvalueIndicatorsSet && that._subvalueIndicatorsSet.values(that.__subvalues, that._noAnimation); that._resizing || that.hideLoadingIndicator() }, value: function(arg) { var that = this; if (arg !== undefined) { that._setupValue(arg); that._updateValueIndicator(); that.option(OPTION_VALUE, that.__value); return that } return that.__value }, subvalues: function(arg) { var that = this; if (arg !== undefined) { if (that.__subvalues !== null) { that._setupSubvalues(arg); that._updateSubvalueIndicators(); that.option(OPTION_SUBVALUES, that.__subvalues) } return that } return that.__subvalues !== null ? that.__subvalues.slice() : undefined }, _handleValueChanged: function(name, newv, oldv) { var that = this; switch (name) { case OPTION_VALUE: that._setupValue(newv); that._updateValueIndicator(); that.option(OPTION_VALUE, that.__value); return true; case OPTION_SUBVALUES: if (that.__subvalues !== null) { that._setupSubvalues(newv); that._updateSubvalueIndicators(); that.option(OPTION_SUBVALUES, that.__subvalues); return true } return false; default: return false } }, _optionChanged: function(name, newValue, oldValue) { var that = this; if (that._handleValueChanged(name, newValue, oldValue)) return; switch (name) { case'scale': that._setupDomain(); that._invalidate(); break; default: that.callBase.apply(that, arguments); break } }, _optionValuesEqual: function(name, oldValue, newValue) { switch (name) { case OPTION_VALUE: return oldValue === newValue; case OPTION_SUBVALUES: return compareArrays(oldValue, newValue); default: return this.callBase.apply(this, arguments) } }, _getDefaultContainerSize: null, _applyMainLayout: null, _updateElementPosition: null, _createScale: null, _createRangeContainer: null, _createValueIndicator: null, _createSubvalueIndicator: null, _getApproximateScreenRange: null }); DX.viz.gauges.Gauge.prototype._factory = DX.utils.clone(DX.viz.gauges.__internals.BaseGauge.prototype._factory); DX.viz.gauges.Gauge.prototype._factory.createThemeManager = function() { return new DX.viz.gauges.__internals.ThemeManager }; function valueGetter(arg) { return arg.value } function setupValues(that, fieldName, optionItems) { var currentValues = that[fieldName], newValues = _isArray(optionItems) ? _map(optionItems, valueGetter) : [], i = 0, ii = newValues.length, list = []; for (; i < ii; ++i) list.push(that._processValue(newValues[i], currentValues[i])); that[fieldName] = list } function disableDefaultMode(that) { that.value = that.subvalues = _noop; that._setupValue = that._setupSubvalues = that._updateValueIndicator = that._updateSubvalueIndicators = null } function selectObsoleteMode(that) { that._needleValues = _map(that.option('needles') || [], valueGetter); that._markerValues = _map(that.option('markers') || [], valueGetter); that._rangeBarValues = _map(that.option('rangeBars') || [], valueGetter); that._needles = []; that._markers = []; that._rangeBars = []; that._setupValueState = function() { var that = this; setupValues(that, '_needleValues', that.option('needles')); setupValues(that, '_markerValues', that.option('markers')); setupValues(that, '_rangeBarValues', that.option('rangeBars')) }; that._handleValueChanged = function(name, newv, oldv) { var that = this, result = false; switch (name) { case'needles': setupValues(that, '_needleValues', newv); result = true; break; case'markers': setupValues(that, '_markerValues', newv); result = true; break; case'rangeBars': setupValues(that, '_rangeBarValues', newv); result = true; break } result && that._invalidate(); return result }; that._updateActiveElements = function() { var that = this; _each(that._needles, function(_, needle) { needle.value(that._needleValues[needle._index], that._noAnimation) }); _each(that._markers, function(_, marker) { marker.value(that._markerValues[marker._index], that._noAnimation) }); _each(that._rangeBars, function(_, rangeBar) { rangeBar.value(that._rangeBarValues[rangeBar._index], that._noAnimation) }); that._resizing || that.hideLoadingIndicator() }; that._prepareValueIndicators = function() { return prepareObsoleteElements(this) }; that._disposeValueIndicators = function() { var that = this; _each([].concat(that._needles, that._markers, that._rangeBars), function(_, pointer) { pointer.dispose() }); that._needles = that._markers = that._rangeBars = null }; that._cleanValueIndicators = function() { _each([].concat(this._needles, this._markers, this._rangeBars), function(_, pointer) { pointer.clean() }) }; that.needleValue = function(index, value) { return accessPointerValue(this, this._needles, this._needleValues, index, value) }; that.markerValue = function(index, value) { return accessPointerValue(this, this._markers, this._markerValues, index, value) }; that.rangeBarValue = function(index, value) { return accessPointerValue(this, this._rangeBars, this._rangeBarValues, index, value) } } function selectHardMode(that) { that._indicatorValues = []; that._valueIndicators = []; that._setupValueState = function() { setupValues(this, '_indicatorValues', this.option('valueIndicators')) }; that._handleValueChagned = function(name, newv, oldv) { if (name === 'valueIndicators') { setupValues(this, '_indicatorValues', newv); this._invalidate(); return true } return false }; that._updateActiveElements = function() { var that = this; _each(that._valueIndicators, function(_, valueIndicator) { valueIndicator.value(that._indicatorValues[valueIndicator._index], that._noAnimation) }); that._resizing || that.hideLoadingIndicator() }; that._prepareValueIndicators = function() { return prepareValueIndicatorsInHardMode(this) }; that._disposeValueIndicators = function() { _each(this._valueIndicators, function(_, valueIndicator) { valueIndicator.dispose() }); this._valueIndicators = null }; that._cleanValueIndicators = function() { _each(this._valueIndicators, function(_, valueIndicator) { valueIndicator.clean() }) }; that.indicatorValue = function(index, value) { return accessPointerValue(this, this._valueIndicators, this._indicatorValues, index, value) } } function prepareValueIndicatorsInHardMode(that) { var valueIndicators = that._valueIndicators || [], userOptions = that.option('valueIndicators'), optionList = [], i = 0, ii; for (ii = _isArray(userOptions) ? userOptions.length : 0; i < ii; ++i) optionList.push(userOptions[i]); for (ii = valueIndicators.length; i < ii; ++i) optionList.push(null); var themeSettings = that._themeManager.theme().valueIndicators, parameters = { renderer: that._renderer, owner: that._root, translator: that._translator, tracker: that._tracker }, newValueIndicators = []; _each(optionList, function(i, userSettings) { var valueIndicator = valueIndicators[i]; if (!userSettings) { valueIndicator && valueIndicator.dispose(); return } var type = _String(userSettings.type || themeSettings._type).toLowerCase(); if (valueIndicator && type !== valueIndicator.type) { valueIndicator.dispose(); valueIndicator = null } if (!valueIndicator) { valueIndicator = that._createValueIndicatorInHardMode(type); valueIndicator && valueIndicator.setup(parameters) } if (valueIndicator) { var settings = _extend(true, {}, themeSettings._default, themeSettings[type], userSettings, { type: type, animation: that._animationSettings, containerBackgroundColor: that._containerBackgroundColor }); that._updateIndicatorSettings(settings); valueIndicator.render(settings); valueIndicator._index = i; valueIndicator._trackerInfo = {index: i}; newValueIndicators.push(valueIndicator) } }); that._valueIndicators = newValueIndicators; return that._valueIndicators } function prepareObsoleteElements(that) { var rangeBars = prepareObsoletePointers(that, '_rangeBars', '_createRangeBar', { user: that.option('rangeBars'), common: that.option('commonRangeBarSettings'), theme: that._themeManager.theme().valueIndicator, preset: {}, type: 'rangebar', className: 'dxg-value-indicator' }); var needles = prepareObsoletePointers(that, '_needles', '_createNeedle', { user: that.option('needles'), common: that.option('commonNeedleSettings'), theme: that._themeManager.theme().valueIndicator, preset: that._getPreset().commonNeedleSettings, className: 'dxg-value-indicator' }); var markers = prepareObsoletePointers(that, '_markers', '_createMarker', { user: that.option('markers'), common: that.option('commonMarkerSettings'), theme: that._themeManager.theme().subvalueIndicator, preset: that._getPreset().commonMarkerSettings, className: 'dxg-subvalue-indicator' }); var spindle = that._prepareObsoleteSpindle && that._prepareObsoleteSpindle(); return [].concat(rangeBars, needles, markers, [spindle]) } function prepareObsoletePointers(that, fieldName, methodName, options) { var pointers = that[fieldName], userOptions = [], i = 0, ii; for (ii = _isArray(options.user) ? options.user.length : 0; i < ii; ++i) userOptions.push(options.user[i]); for (ii = pointers.length; i < ii; ++i) userOptions.push(null); var themeOption = options.theme, presetOption = options.preset, commonOption = options.common || {}, parameters = { renderer: that._renderer, owner: that._root, translator: that._translator, tracker: that._tracker, className: options.className }, newPointers = []; _each(userOptions, function(i, pointerOption) { var pointer = pointers[i]; if (!pointerOption) { pointer && pointer.dispose(); return } var type = _String(pointerOption.type || commonOption.type || presetOption.type || themeOption.type).toLowerCase(), settings; if (pointer && pointer.type !== type) { pointer.dispose(); pointer = null } if (!pointer) { pointer = that[methodName](type); pointer.setup(parameters) } if (pointer) { type = options.type || type; settings = _extend(true, {}, themeOption._default, themeOption[type], commonOption, pointerOption), settings.spindleSize = null; settings.animation = that._animationSettings; settings.containerBackgroundColor = that._containerBackgroundColor; that._updateIndicatorSettings(settings); pointer.render(settings); pointer._index = i; pointer._trackerInfo = {index: i}; newPointers.push(pointer) } }); that[fieldName] = newPointers; return newPointers } function accessPointerValue(that, pointers, values, index, value) { if (value !== undefined) { if (values[index] !== undefined) { values[index] = that._processValue(value, values[index]); pointers[index] && pointers[index].value(values[index]); that._resizing || that.hideLoadingIndicator() } return that } else return values[index] } function compareArrays(array1, array2) { if (array1 === array2) return true; if (_isArray(array1) && _isArray(array2) && array1.length === array2.length) { for (var i = 0, ii = array1.length; i < ii; ++i) if (_abs(array1[i] - array2[i]) > 1E-8) return false; return true } return false } DX.viz.gauges.__internals.ValueIndicatorsSet = DX.Class.inherit({ ctor: function(parameters) { var that = this; that._parameters = parameters; that._createIndicator = that._parameters.createIndicator || _noop; that._root = that._parameters.renderer.createGroup({'class': that._parameters.className}); that._indicatorParameters = that._indicatorParameters || { renderer: that._parameters.renderer, translator: that._parameters.translator, owner: that._root, tracker: that._parameters.tracker, className: that._parameters.indicatorClassName }; that._indicators = [] }, dispose: function() { var that = this; _each(that._indicators, function(_, indicator) { indicator.dispose() }); that._parameters = that._createIndicator = that._root = that._options = that._indicators = that._colorPalette = that._palette = null; return that }, clean: function() { var that = this; that._root.detach(); that._sample && that._sample.clean().dispose(); _each(that._indicators, function(_, indicator) { indicator.clean() }); that._sample = that._options = that._palette = null; return that }, render: function(options, isRecreate) { var that = this; that._options = options; that._sample = that._createIndicator(); that._sample && that._sample.setup(that._indicatorParameters).render(options); that.enabled = that._sample && that._sample.enabled; that._palette = _isDefined(options.palette) ? new DX.viz.core.Palette(options.palette) : null; if (that.enabled) { that._root.append(that._parameters.owner); that._generatePalette(that._indicators.length); that._indicators = _map(that._indicators, function(indicator, i) { if (isRecreate) { indicator.dispose(); indicator = that._createIndicator(); indicator.setup(that._indicatorParameters); indicator._trackerInfo = { type: that._parameters.trackerType, index: i } } indicator.render(that._getIndicatorOptions(i)); return indicator }) } return that }, resize: function(layout) { var that = this; that._layout = layout; _each(that._indicators, function(_, indicator) { indicator.resize(layout) }); return that }, measure: function(layout) { return this._sample.measure(layout) }, _getIndicatorOptions: function(index) { var result = this._options; if (this._colorPalette) result = _extend({}, result, {color: this._colorPalette[index]}); return result }, _generatePalette: function(count) { var that = this, colors = null; if (that._palette) { colors = []; that._palette.reset(); var i = 0; for (; i < count; ++i) colors.push(that._palette.getNextColor()) } that._colorPalette = colors }, _adjustIndicatorsCount: function(count) { var that = this, indicators = that._indicators, i, ii, indicatorOptions, indicator, indicatorsLen = indicators.length, palette = that._parameters.palette; if (indicatorsLen > count) { for (i = count, ii = indicatorsLen; i < ii; ++i) indicators[i].clean().dispose(); that._indicators = indicators.slice(0, count); that._generatePalette(indicators.length) } else if (indicatorsLen < count) { that._generatePalette(count); for (i = indicatorsLen, ii = count; i < ii; ++i) { indicator = that._createIndicator(); indicator.setup(that._indicatorParameters); indicator._trackerInfo = { type: that._parameters.trackerType, index: i }; indicator.render(that._getIndicatorOptions(i)).resize(that._layout); indicators.push(indicator) } } }, values: function(arg, _noAnimation) { var that = this; if (!that.enabled) return; if (arg !== undefined) { if (!_isArray(arg)) arg = _isFinite(arg) ? [Number(arg)] : null; if (arg) { that._adjustIndicatorsCount(arg.length); _each(that._indicators, function(i, indicator) { indicator.value(arg[i], _noAnimation) }) } return that } return _map(that._indicators, function(indicator) { return indicator.value() }) } }) })(DevExpress, jQuery); /*! Module viz-gauges, file circularGauge.js */ (function(DX, $, undefined) { var factory = DX.viz.gauges.__factory; var isFinite = window.isFinite, Number = window.Number, normalizeAngle = DX.utils.normalizeAngle, getCosAndSin = DX.utils.getCosAndSin, abs = Math.abs, max = Math.max, min = Math.min, round = Math.round, slice = Array.prototype.slice, $extend = $.extend, $each = $.each; var PI = Math.PI; function getSides(startAngle, endAngle) { var startCosSin = getCosAndSin(startAngle), endCosSin = getCosAndSin(endAngle), startCos = startCosSin.cos, startSin = startCosSin.sin, endCos = endCosSin.cos, endSin = endCosSin.sin; return { left: startSin <= 0 && endSin >= 0 || startSin <= 0 && endSin <= 0 && startCos <= endCos || startSin >= 0 && endSin >= 0 && startCos >= endCos ? -1 : min(startCos, endCos, 0), right: startSin >= 0 && endSin <= 0 || startSin >= 0 && endSin >= 0 && startCos >= endCos || startSin <= 0 && endSin <= 0 && startCos <= endCos ? 1 : max(startCos, endCos, 0), up: startCos <= 0 && endCos >= 0 || startCos <= 0 && endCos <= 0 && startSin >= endSin || startCos >= 0 && endCos >= 0 && startSin <= endSin ? -1 : -max(startSin, endSin, 0), down: startCos >= 0 && endCos <= 0 || startCos >= 0 && endCos >= 0 && startSin <= endSin || startCos <= 0 && endCos <= 0 && startSin >= endSin ? 1 : -min(startSin, endSin, 0) } } DX.viz.gauges.CircularGauge = DX.viz.gauges.Gauge.inherit({ _rootClass: 'dxg-circular-gauge', _selectMode: function() { this.callBase.apply(this, arguments); if (typeof this.indicatorValue === 'function') this._createValueIndicatorInHardMode = function(type) { return factory.createCircularValueIndicatorInHardMode(type) } }, _setupCodomain: function() { var that = this, geometry = that.option('geometry') || {}, startAngle = geometry.startAngle, endAngle = geometry.endAngle, sides; startAngle = isFinite(startAngle) ? normalizeAngle(startAngle) : 225; endAngle = isFinite(endAngle) ? normalizeAngle(endAngle) : -45; if (abs(startAngle - endAngle) < 1) { endAngle -= 360; sides = { left: -1, up: -1, right: 1, down: 1 } } else { startAngle < endAngle && (endAngle -= 360); sides = getSides(startAngle, endAngle) } that._area = { x: 0, y: 0, radius: 100, startCoord: startAngle, endCoord: endAngle, scaleRadius: geometry.scaleRadius > 0 ? Number(geometry.scaleRadius) : undefined, sides: sides }; that._translator.setCodomain(startAngle, endAngle) }, _measureMainElements: function(elements) { var that = this, maxRadius = 0, minRadius = Infinity, maxHorizontalOffset = 0, maxVerticalOffset = 0, maxInverseHorizontalOffset = 0, maxInverseVerticalOffset = 0; $each(elements, function(_, element) { var bounds = element.measure({radius: that._area.radius - (Number(element._options.offset) || 0)}); bounds.min > 0 && (minRadius = min(minRadius, bounds.min)); bounds.max > 0 && (maxRadius = max(maxRadius, bounds.max)); bounds.horizontalOffset > 0 && (maxHorizontalOffset = max(maxHorizontalOffset, bounds.max + bounds.horizontalOffset)); bounds.verticalOffset > 0 && (maxVerticalOffset = max(maxVerticalOffset, bounds.max + bounds.verticalOffset)); bounds.inverseHorizontalOffset > 0 && (maxInverseHorizontalOffset = max(maxInverseHorizontalOffset, bounds.inverseHorizontalOffset)); bounds.inverseVerticalOffset > 0 && (maxInverseVerticalOffset = max(maxInverseVerticalOffset, bounds.inverseVerticalOffset)) }); maxHorizontalOffset = max(maxHorizontalOffset - maxRadius, 0); maxVerticalOffset = max(maxVerticalOffset - maxRadius, 0); return { minRadius: minRadius, maxRadius: maxRadius, horizontalMargin: maxHorizontalOffset, verticalMargin: maxVerticalOffset, inverseHorizontalMargin: maxInverseHorizontalOffset, inverseVerticalMargin: maxInverseVerticalOffset } }, _applyMainLayout: function(elements) { var that = this, measurements = that._measureMainElements(elements), area = that._area, sides = area.sides, margins = { left: (sides.left < -0.1 ? measurements.horizontalMargin : measurements.inverseHorizontalMargin) || 0, right: (sides.right > 0.1 ? measurements.horizontalMargin : measurements.inverseHorizontalMargin) || 0, top: (sides.up < -0.1 ? measurements.verticalMargin : measurements.inverseVerticalMargin) || 0, bottom: (sides.down > 0.1 ? measurements.verticalMargin : measurements.inverseVerticalMargin) || 0 }, rect = that._layoutManager.selectRectByAspectRatio((sides.down - sides.up) / (sides.right - sides.left), margins), radius = min(rect.width() / (sides.right - sides.left), rect.height() / (sides.down - sides.up)), x, y; var scaler = (measurements.maxRadius - area.radius + area.scaleRadius) / radius; if (0 < scaler && scaler < 1) { rect = rect.scale(scaler); radius *= scaler } radius = radius - measurements.maxRadius + area.radius; x = rect.left - rect.width() * sides.left / (sides.right - sides.left); y = rect.top - rect.height() * sides.up / (sides.down - sides.up); area.x = round(x); area.y = round(y); area.radius = radius; rect.left -= margins.left; rect.right += margins.right; rect.top -= margins.top; rect.bottom += margins.bottom; that._layoutManager.setRect(rect) }, _updateElementPosition: function(element) { element.resize({ x: this._area.x, y: this._area.y, radius: round(this._area.radius - (Number(element._options.offset) || 0)) }) }, _createScale: function(parameters) { return factory.createCircularScale(parameters) }, _createRangeContainer: function(parameters) { return factory.createCircularRangeContainer(parameters) }, _createValueIndicator: function(type) { return factory.createCircularValueIndicator(type) }, _createSubvalueIndicator: function(type) { return factory.createCircularSubvalueIndicator(type) }, _getApproximateScreenRange: function() { var that = this, area = that._area, r = min(that._width / (area.sides.right - area.sides.left), that._height / (area.sides.down - area.sides.up)); r > area.totalRadius && (r = area.totalRadius); r = 0.8 * r; return -that._translator.getCodomainRange() * r * PI / 180 }, _getDefaultContainerSize: function() { return { width: 300, height: 300 } }, _getPreset: function() { var preset = this.option('preset'), result; if (preset === 'preset2') result = { commonNeedleSettings: {type: 'twocolorrectangle'}, commonMarkerSettings: {type: 'triangle'} }; else if (preset === 'preset3') result = { commonNeedleSettings: {type: 'rectangle'}, commonMarkerSettings: {type: 'triangle'} }; else result = { commonNeedleSettings: {type: 'rectangle'}, commonMarkerSettings: {type: 'textcloud'} }; return result }, _createNeedle: function(type) { return factory.createCircularNeedle(type) }, _createMarker: function(type) { return factory.createCircularMarker(type) }, _createRangeBar: function() { return factory.createCircularRangeBar() }, _prepareObsoleteSpindle: function() { var that = this, spindleOption = that.option('spindle') || {}, visible = that._needles && ('visible' in spindleOption ? !!spindleOption.visible : true); if (visible) { var themeOption = that._themeManager.theme().valueIndicator._default, size = spindleOption.size || themeOption.spindleSize; visible = size > 0 } if (visible) { var gapSize = spindleOption.gapSize || themeOption.spindleGapSize, color = spindleOption.color || themeOption.color; gapSize = gapSize <= size ? gapSize : size; that._spindle = that._spindle || that._renderer.createGroup({'class': 'dxg-value-indicator'}); that._spindle.append(that._root); that._spindleOuter = that._spindleOuter || that._renderer.createCircle(0, 0, 0, { 'class': 'dxg-spindle-border', stroke: 'none', strokeWidth: 0 }).append(that._spindle); that._spindleInner = that._spindleInner || that._renderer.createCircle(0, 0, 0, { 'class': 'dxg-spindle-hole', stroke: 'none', strokeWidth: 0 }).append(that._spindle); that._spindleOuter.applySettings({ cx: that._area.x, cy: that._area.y, r: size / 2, fill: color }); that._spindleInner.applySettings({ cx: that._area.x, cy: that._area.y, r: gapSize / 2, fill: that._containerBackgroundColor }); return { enabled: true, _options: {offset: 0}, measure: function(layout) { return {} }, resize: function(layout) { that._spindleOuter.applySettings({ cx: layout.x, cy: layout.y }); that._spindleInner.applySettings({ cx: layout.x, cy: layout.y }); return that } } } else { that._spindle && that._spindle.remove(); delete that._spindle; delete that._spindleOuter; delete that._spindleInner; return null } } }); DX.viz.gauges.CircularGauge.prototype._factory = DX.utils.clone(DX.viz.gauges.__internals.BaseGauge.prototype._factory); DX.viz.gauges.CircularGauge.prototype._factory.createThemeManager = function() { var themeManager = new DX.viz.gauges.__internals.ThemeManager; themeManager._subTheme = '_circular'; return themeManager } })(DevExpress, jQuery); /*! Module viz-gauges, file linearGauge.js */ (function(DX, $, undefined) { var factory = DX.viz.gauges.__factory; var _String = String, _Number = Number, max = Math.max, min = Math.min, round = Math.round, slice = Array.prototype.slice, $extend = $.extend, $each = $.each; DX.viz.gauges.LinearGauge = DX.viz.gauges.Gauge.inherit({ _rootClass: 'dxg-linear-gauge', _selectMode: function() { this.callBase.apply(this, arguments); if (typeof this.indicatorValue === 'function') this._createValueIndicatorInHardMode = function(type) { return factory.createLinearValueIndicatorInHardMode(type) } }, _setupCodomain: function() { var that = this, geometry = that.option('geometry') || {}, vertical = _String(geometry.orientation).toLowerCase() === 'vertical'; that._area = { vertical: vertical, x: 0, y: 0, startCoord: -100, endCoord: 100, scaleSize: geometry.scaleSize > 0 ? _Number(geometry.scaleSize) : undefined }; that._scale.vertical = vertical; that._rangeContainer.vertical = vertical }, _measureMainElements: function(elements) { var that = this, minBound = 1000, maxBound = 0, indent = 0; $each(elements, function(_, element) { var bounds = element.measure({ x: that._area.x + (_Number(element._options.offset) || 0), y: that._area.y + (_Number(element._options.offset) || 0) }); maxBound = max(maxBound, bounds.max); minBound = min(minBound, bounds.min); bounds.indent > 0 && (indent = max(indent, bounds.indent)) }); return { minBound: minBound, maxBound: maxBound, indent: indent } }, _applyMainLayout: function(elements) { var that = this, measurements = that._measureMainElements(elements), area = that._area, rect, offset, counterSize = area.scaleSize + 2 * measurements.indent; if (area.vertical) { rect = that._layoutManager.selectRectBySizes({ width: measurements.maxBound - measurements.minBound, height: counterSize }); offset = rect.horizontalMiddle() - (measurements.minBound + measurements.maxBound) / 2; area.startCoord = rect.bottom - measurements.indent; area.endCoord = rect.top + measurements.indent; area.x = round(area.x + offset) } else { rect = that._layoutManager.selectRectBySizes({ height: measurements.maxBound - measurements.minBound, width: counterSize }); offset = rect.verticalMiddle() - (measurements.minBound + measurements.maxBound) / 2; area.startCoord = rect.left + measurements.indent; area.endCoord = rect.right - measurements.indent; area.y = round(area.y + offset) } that._translator.setCodomain(area.startCoord, area.endCoord); that._layoutManager.setRect(rect) }, _updateElementPosition: function(element) { element.resize({ x: round(this._area.x + (_Number(element._options.offset) || 0)), y: round(this._area.y + (_Number(element._options.offset) || 0)) }) }, _createScale: function(parameters) { return factory.createLinearScale(parameters) }, _createRangeContainer: function(parameters) { return factory.createLinearRangeContainer(parameters) }, _createValueIndicator: function(type) { return factory.createLinearValueIndicator(type) }, _createSubvalueIndicator: function(type) { return factory.createLinearSubvalueIndicator(type) }, _getApproximateScreenRange: function() { var that = this, area = that._area, s = area.vertical ? that._height : that._width; s > area.totalSize && (s = area.totalSize); s = s * 0.8; return s }, _getDefaultContainerSize: function() { var geometry = this.option('geometry') || {}; if (geometry.orientation === 'vertical') return { width: 100, height: 300 }; else return { width: 300, height: 100 } }, _getPreset: function() { var preset = this.option('preset'), result; if (preset === 'preset2') result = { commonNeedleSettings: {type: 'rhombus'}, commonMarkerSettings: {type: 'triangle'} }; else result = { commonNeedleSettings: {type: 'circle'}, commonMarkerSettings: {type: 'textcloud'} }; return result }, _createNeedle: function(type) { return factory.createLinearNeedle(type) }, _createMarker: function(type) { return factory.createLinearMarker(type) }, _createRangeBar: function() { return factory.createLinearRangeBar() } }); DX.viz.gauges.LinearGauge.prototype._factory = DX.utils.clone(DX.viz.gauges.__internals.BaseGauge.prototype._factory); DX.viz.gauges.LinearGauge.prototype._factory.createThemeManager = function() { var themeManager = new DX.viz.gauges.__internals.ThemeManager; themeManager._subTheme = '_linear'; return themeManager } })(DevExpress, jQuery); /*! Module viz-gauges, file barGauge.js */ (function(DX, $, undefined) { var PI = Math.PI; var _Number = window.Number, _isFinite = window.isFinite, _abs = Math.abs, _round = Math.round, _floor = Math.floor, _min = Math.min, _max = Math.max, _isArray = DX.utils.isArray, _convertAngleToRendererSpace = DX.utils.convertAngleToRendererSpace, _getCosAndSin = DX.utils.getCosAndSin, _noop = $.noop, _extend = $.extend, _getSampleText = DX.viz.gauges.__internals.getSampleText, _formatValue = DX.viz.gauges.__internals.formatValue; var _Rectangle = DX.viz.core.Rectangle, _Palette = DX.viz.core.Palette; DX.viz.gauges.BarGauge = DX.viz.gauges.__internals.BaseGauge.inherit({ _rootClass: 'dxbg-bar-gauge', _init: function() { var that = this; that.callBase.apply(that, arguments); that._barsGroup = that._renderer.createGroup({'class': 'dxbg-bars'}); that._values = []; that._context = { renderer: that._renderer, translator: that._translator, tracker: that._tracker, group: that._barsGroup }; that._animateStep = function(pos) { var bars = that._bars, i = 0, ii = bars.length; for (; i < ii; ++i) bars[i].animate(pos) }; that._animateComplete = function() { var bars = that._bars, i = 0, ii = bars.length; for (; i < ii; ++i) bars[i].endAnimation() } }, _dispose: function() { var that = this; that.callBase.apply(that, arguments); that._barsGroup = that._values = that._context = that._animateStep = that._animateComplete = null }, _setupDomain: function() { var that = this, startValue = that.option('startValue'), endValue = that.option('endValue'); _isFinite(startValue) || (startValue = 0); _isFinite(endValue) || (endValue = 100); that._translator.setDomain(startValue, endValue); that._baseValue = that._translator.adjust(that.option('baseValue')); _isFinite(that._baseValue) || (that._baseValue = startValue < endValue ? startValue : endValue) }, _calculateSizeCore: function() { var that = this, size = that.option('size') || {}; if (_Number(size.width) === 0 || _Number(size.height) === 0) { that._width = that._height = 0; that._rootRect = new _Rectangle } else { that._width = size.width > 0 ? _Number(size.width) : that._element().width() || 300; that._height = size.height > 0 ? _Number(size.height) : that._element().height() || 300; that._rootRect = new _Rectangle({ left: 0, top: 0, right: that._width, bottom: that._height }) } }, _setupCodomain: DX.viz.gauges.CircularGauge.prototype._setupCodomain, _getApproximateScreenRange: function() { var that = this, sides = that._area.sides, width = that._width / (sides.right - sides.left), height = that._height / (sides.down - sides.up), r = width < height ? width : height; return -that._translator.getCodomainRange() * r * PI / 180 }, _setupAnimationSettings: function() { this.callBase(); if (this._animationSettings) _extend(this._animationSettings, { step: this._animateStep, complete: this._animateComplete }) }, _cleanContent: function() { var that = this; that._barsGroup.detach(); that._animationSettings && that._barsGroup.stopAnimation(); var i = 0, ii = that._bars ? that._bars.length : 0; for (; i < ii; ++i) that._bars[i].dispose(); that._palette = that._bars = null }, _renderContent: function() { var that = this, labelOptions = that.option('label'); that._barsGroup.append(that._root); that._context.textEnabled = labelOptions === undefined || labelOptions && (!('visible' in labelOptions) || labelOptions.visible); if (that._context.textEnabled) { that._context.textColor = labelOptions && labelOptions.font && labelOptions.font.color || null; labelOptions = _extend(true, {}, that._themeManager.theme().label, labelOptions); that._context.formatOptions = { format: labelOptions.format !== undefined || labelOptions.precision !== undefined ? labelOptions.format : that._defaultFormatOptions.format, precision: labelOptions.format !== undefined || labelOptions.precision !== undefined ? labelOptions.precision : that._defaultFormatOptions.precision, customizeText: labelOptions.customizeText }; that._context.textOptions = { font: _extend({}, that._themeManager.theme().label.font, labelOptions.font, {color: null}), align: 'center' }; that._textIndent = labelOptions.indent > 0 ? _Number(labelOptions.indent) : 0; that._context.lineWidth = labelOptions.connectorWidth > 0 ? _Number(labelOptions.connectorWidth) : 0; that._context.lineColor = labelOptions.connectorColor || null; var text = that._renderer.createText(_getSampleText(that._translator, that._context.formatOptions), 0, 0, that._context.textOptions).append(that._barsGroup), bbox = text.getBBox(); text.detach(); that._context.textVerticalOffset = -bbox.y - bbox.height / 2; that._context.textWidth = bbox.width; that._context.textHeight = bbox.height } DX.viz.gauges.CircularGauge.prototype._applyMainLayout.call(that); that._renderBars() }, _measureMainElements: function() { var result = {maxRadius: this._area.radius}; if (this._context.textEnabled) { result.horizontalMargin = this._context.textWidth; result.verticalMargin = this._context.textHeight } return result }, _renderBars: function() { var that = this, options = _extend({}, that._themeManager.theme(), that.option()); that._palette = new _Palette(options.palette, { stepHighlight: 50, theme: that._themeManager.themeName() }); var relativeInnerRadius = options.relativeInnerRadius > 0 && options.relativeInnerRadius < 1 ? _Number(options.relativeInnerRadius) : 0.1, radius = that._area.radius; if (that._context.textEnabled) { that._textIndent = _round(_min(that._textIndent, radius / 2)); radius -= that._textIndent } that._outerRadius = _round(radius); that._innerRadius = _round(radius * relativeInnerRadius); that._barSpacing = options.barSpacing > 0 ? _Number(options.barSpacing) : 0; _extend(that._context, { backgroundColor: options.backgroundColor, x: that._area.x, y: that._area.y, startAngle: that._area.startCoord, endAngle: that._area.endCoord, baseAngle: that._translator.translate(that._baseValue) }); that._bars = []; that._updateValues(that.option('values')) }, _arrangeBars: function(count) { var that = this, radius = that._outerRadius - that._innerRadius; that._context.barSize = count > 0 ? _max((radius - (count - 1) * that._barSpacing) / count, 1) : 0; var spacing = count > 1 ? _max(_min((radius - count * that._context.barSize) / (count - 1), that._barSpacing), 0) : 0, _count = _min(_floor((radius + spacing) / that._context.barSize), count); that._setBarsCount(_count); radius = that._outerRadius; that._context.textRadius = radius + that._textIndent; that._palette.reset(); var unitOffset = that._context.barSize + spacing, i = 0; for (; i < _count; ++i, radius -= unitOffset) that._bars[i].arrange({ radius: radius, color: that._palette.getNextColor() }) }, _setBarsCount: function(count) { var that = this, i, ii; if (that._bars.length > count) { for (i = count, ii = that._bars.length; i < ii; ++i) that._bars[i].dispose(); that._bars.splice(count, ii - count) } else if (that._bars.length < count) for (i = that._bars.length, ii = count; i < ii; ++i) that._bars.push(new BarWrapper(i, that._context)); if (that._bars.length > 0) { if (that._dummyBackground) { that._dummyBackground.detach(); that._dummyBackground = null } } else { if (!that._dummyBackground) that._dummyBackground = that._renderer.createArc().append(that._barsGroup); that._dummyBackground.applySettings({ x: that._context.x, y: that._context.y, outerRadius: that._outerRadius, innerRadius: that._innerRadius, startAngle: that._context.endAngle, endAngle: that._context.startAngle, fill: that._context.backgroundColor }) } }, _updateBars: function() { var that = this, i = 0, ii = that._bars.length; for (; i < ii; ++i) that._bars[i].setValue(that._values[i]) }, _animateBars: function() { var that = this, i = 0, ii = that._bars.length; if (ii > 0) { for (; i < ii; ++i) that._bars[i].beginAnimation(that._values[i]); that._barsGroup.animate({_: 0}, that._animationSettings) } }, _updateValues: function(values, noAnimation) { var that = this, list = _isArray(values) && values || _isFinite(values) && [values] || [], i = 0, ii = list.length, value; that._values = []; for (; i < ii; ++i) { value = that._translator.adjust(list[i]); _isFinite(value) && that._values.push(value) } that._animationSettings && that._barsGroup.stopAnimation(); if (that._bars) { that._arrangeBars(that._values.length); if (that._animationSettings && !that._noAnimation) that._animateBars(); else that._updateBars() } if (!that._resizing) { that.option('values', that._values); that.hideLoadingIndicator() } }, values: function(arg) { if (arg !== undefined) { this._updateValues(arg); return this } else return this._values.slice(0) }, _optionChanged: function(name, newValue, oldValue) { switch (name) { case'values': this._updateValues(newValue); break; default: this.callBase.apply(this, arguments); break } }, _optionValuesEqual: function(name, oldValue, newValue) { switch (name) { case'values': return compareArrays(oldValue, newValue); default: return this.callBase.apply(this, arguments) } } }); var ThemeManager = DX.viz.gauges.__internals.ThemeManager.inherit({ _themeSection: 'barGauge', _initializeTheme: function() { var that = this; that._initializeFont(that._theme.label.font); that._initializeFont(that._theme.title.font); that._initializeFont(that._theme.tooltip.font); that._initializeFont(that._theme.loadingIndicator.font) } }); DX.viz.gauges.BarGauge.prototype._factory = DX.utils.clone(DX.viz.gauges.__internals.BaseGauge.prototype._factory); DX.viz.gauges.BarGauge.prototype._factory.createThemeManager = function() { return new ThemeManager }; function BarWrapper(index, context) { var that = this; that._context = context; that._background = context.renderer.createArc().append(context.group); that._background.applySettings({fill: context.backgroundColor}); that._bar = context.renderer.createArc().append(context.group); if (context.textEnabled) { that._line = context.renderer.createPath([], {strokeWidth: context.lineWidth}).append(context.group); that._text = context.renderer.createText('', 0, 0, context.textOptions).append(context.group) } that._tracker = context.renderer.createArc(); context.tracker.attach(that._tracker, that, {index: index}); that._index = index; that._angle = context.baseAngle; that._settings = { x: context.x, y: context.y, startAngle: context.baseAngle, endAngle: context.baseAngle } } _extend(BarWrapper.prototype, { dispose: function() { var that = this; that._background.detach(); that._bar.detach(); if (that._context.textEnabled) { that._line.detach(); that._text.detach() } that._context.tracker.detach(that._tracker); that._context = that._settings = that._background = that._bar = that._line = that._text = that._tracker = null; return that }, arrange: function(options) { var that = this; that._settings.outerRadius = options.radius; that._settings.innerRadius = options.radius - that._context.barSize; that._background.applySettings(_extend({}, that._settings, { startAngle: that._context.endAngle, endAngle: that._context.startAngle })); that._bar.applySettings(that._settings); that._tracker.applySettings(that._settings); that._color = options.color; that._bar.applySettings({fill: options.color}); if (that._context.textEnabled) { that._line.applySettings({ points: [that._context.x, that._context.y - that._settings.innerRadius, that._context.x, that._context.y - that._context.textRadius], stroke: that._context.lineColor || options.color }); that._text.applySettings({font: {color: that._context.textColor || options.color}}) } return that }, getTooltipParameters: function() { var that = this, cossin = _getCosAndSin((that._angle + that._context.baseAngle) / 2); return { x: _round(that._context.x + (that._settings.outerRadius + that._settings.innerRadius) / 2 * cossin.cos), y: _round(that._context.y - (that._settings.outerRadius + that._settings.innerRadius) / 2 * cossin.sin), offset: 0, color: that._color, value: that._value } }, setAngle: function(angle) { var that = this; that._angle = angle; setAngles(that._settings, that._context.baseAngle, that._angle); that._bar.applySettings(that._settings); that._tracker.applySettings(that._settings); if (that._context.textEnabled) { that._line.rotate(_convertAngleToRendererSpace(that._angle), that._context.x, that._context.y); var cossin = _getCosAndSin(that._angle); that._text.applySettings({ text: _formatValue(that._value, that._context.formatOptions, {index: that._index}), x: that._context.x + (that._context.textRadius + that._context.textWidth * 0.6) * cossin.cos, y: that._context.y - (that._context.textRadius + that._context.textHeight * 0.6) * cossin.sin + that._context.textVerticalOffset }) } return that }, setValue: function(value) { this._value = value; return this.setAngle(this._context.translator.translate(value)) }, beginAnimation: function(value) { var that = this; that._value = value; var angle = that._context.translator.translate(value); if (!compareFloats(that._angle, angle)) { that._start = that._angle; that._delta = angle - that._angle; that._tracker.applySettings({visibility: 'hidden'}); if (that._context.textEnabled) { that._line.applySettings({visibility: 'hidden'}); that._text.applySettings({visibility: 'hidden'}) } } else that.animate = _noop }, animate: function(pos) { var that = this; that._angle = that._start + that._delta * pos; setAngles(that._settings, that._context.baseAngle, that._angle); that._bar.applySettings(that._settings) }, endAnimation: function() { var that = this; if (that._delta !== undefined) { if (compareFloats(that._angle, that._start + that._delta)) { that._tracker.applySettings({visibility: null}); if (that._context.textEnabled) { that._line.applySettings({visibility: null}); that._text.applySettings({visibility: null}) } that.setAngle(that._angle) } } else delete that.animate; delete that._start; delete that._delta } }); function setAngles(target, angle1, angle2) { target.startAngle = angle1 < angle2 ? angle1 : angle2; target.endAngle = angle1 < angle2 ? angle2 : angle1 } function compareFloats(value1, value2) { return _abs(value1 - value2) < 0.0001 } function compareArrays(array1, array2) { if (array1 === array2) return true; if (_isArray(array1) && _isArray(array2) && array1.length === array2.length) { for (var i = 0, ii = array1.length; i < ii; ++i) if (!compareFloats(array1[i], array2[i])) return false; return true } return false } var __BarWrapper = BarWrapper; DX.viz.gauges.__tests.BarWrapper = __BarWrapper; DX.viz.gauges.__tests.stubBarWrapper = function(barWrapperType) { BarWrapper = barWrapperType }; DX.viz.gauges.__tests.restoreBarWrapper = function() { BarWrapper = __BarWrapper }; DX.registerComponent('dxBarGauge', DX.viz.gauges.BarGauge) })(DevExpress, jQuery); /*! Module viz-gauges, file tracker.js */ (function(DX, $, undefined) { var _setTimeout = window.setTimeout, _clearTimeout = window.clearTimeout, _extend = $.extend, _abs = Math.abs; var TOOLTIP_SHOW_DELAY = 300, TOOLTIP_HIDE_DELAY = 300, TOOLTIP_TOUCH_SHOW_DELAY = 400, TOOLTIP_TOUCH_HIDE_DELAY = 300; DX.viz.gauges.__internals.Tracker = DX.Class.inherit({ ctor: function(parameters) { DX.utils.debug.assertParam(parameters, 'parameters'); DX.utils.debug.assertParam(parameters.renderer, 'parameters.renderer'); DX.utils.debug.assertParam(parameters.container, 'parameters.container'); var that = this; that._container = parameters.container; that._element = parameters.renderer.createGroup({ 'class': 'dxg-tracker', stroke: 'none', strokeWidth: 0, fill: '#000000', opacity: 0.0001 }); that._showTooltipCallback = function() { that._showTooltipTimeout = null; var target = that._tooltipEvent.target; that._targetEvent = null; if (that._tooltipTarget !== target) { that._tooltipTarget = target; that._callbacks['tooltip-show']() } }; that._hideTooltipCallback = function() { that._hideTooltipTimeout = null; that._targetEvent = null; if (that._tooltipTarget) { that._callbacks['tooltip-hide'](); that._tooltipTarget = null } }; that._dispose = function() { that._showTooltipCallback = that._hideTooltipCallback = that._dispose = null }; that._DEBUG_showTooltipTimeoutSet = that._DEBUG_showTooltipTimeoutCleared = that._DEBUG_hideTooltipTimeoutSet = that._DEBUG_hideTooltipTimeoutCleared = 0 }, dispose: function() { var that = this; that._dispose(); that.deactivate(); that._element.off(); that._container = that._element = that._context = that._callbacks = null; return that }, activate: function() { this._element.append(this._container); return this }, deactivate: function() { this._element.detach(); this._element.clear(); return this }, attach: function(element, target, info) { element.data({ target: target, info: info }); element.append(this._element); return this }, detach: function(element) { element.detach(); element.removeData(); return this }, setTooltipState: function(state) { var that = this, data; that._element.off(tooltipMouseEvents).off(tooltipTouchEvents); if (state) { data = {tracker: that}; that._element.on(tooltipMouseEvents, data).on(tooltipTouchEvents, data) } return that }, setCallbacks: function(callbacks) { this._callbacks = callbacks; return this }, _showTooltip: function(event, delay) { var that = this, data = $(event.target).data(); if (that._tooltipTarget === event.target || that._callbacks['tooltip-prepare'](data.target, data.info)) { that._hideTooltipTimeout && ++that._DEBUG_hideTooltipTimeoutCleared; _clearTimeout(that._hideTooltipTimeout); that._hideTooltipTimeout = null; _clearTimeout(that._showTooltipTimeout); that._tooltipEvent = event; ++that._DEBUG_showTooltipTimeoutSet; that._showTooltipTimeout = _setTimeout(that._showTooltipCallback, delay) } }, _hideTooltip: function(delay) { var that = this; that._showTooltipTimeout && ++that._DEBUG_showTooltipTimeoutCleared; _clearTimeout(that._showTooltipTimeout); that._showTooltipTimeout = null; _clearTimeout(that._hideTooltipTimeout); ++that._DEBUG_hideTooltipTimeoutSet; that._hideTooltipTimeout = _setTimeout(that._hideTooltipCallback, delay) } }); var tooltipMouseEvents = { 'mouseover.gauge-tooltip': handleTooltipMouseOver, 'mouseout.gauge-tooltip': handleTooltipMouseOut }; var tooltipMouseMoveEvents = {'mousemove.gauge-tooltip': handleTooltipMouseMove}; var tooltipTouchEvents = {'touchstart.gauge-tooltip': handleTooltipTouchStart}; function handleTooltipMouseOver(event) { var tracker = event.data.tracker; tracker._x = event.pageX; tracker._y = event.pageY; tracker._element.off(tooltipMouseMoveEvents).on(tooltipMouseMoveEvents, event.data); tracker._showTooltip(event, TOOLTIP_SHOW_DELAY) } function handleTooltipMouseMove(event) { var tracker = event.data.tracker; if (tracker._showTooltipTimeout && _abs(event.pageX - tracker._x) > 4 || _abs(event.pageY - tracker._y) > 4) { tracker._x = event.pageX; tracker._y = event.pageY; tracker._showTooltip(event, TOOLTIP_SHOW_DELAY) } } function handleTooltipMouseOut(event) { var tracker = event.data.tracker; tracker._element.off(tooltipMouseMoveEvents); tracker._hideTooltip(TOOLTIP_HIDE_DELAY) } var active_touch_tooltip_tracker = null; DX.viz.gauges.__internals.Tracker._DEBUG_reset = function() { active_touch_tooltip_tracker = null }; function handleTooltipTouchStart(event) { event.preventDefault(); var tracker = active_touch_tooltip_tracker; if (tracker && tracker !== event.data.tracker) tracker._hideTooltip(TOOLTIP_TOUCH_HIDE_DELAY); tracker = active_touch_tooltip_tracker = event.data.tracker; tracker._showTooltip(event, TOOLTIP_TOUCH_SHOW_DELAY); tracker._touch = true } function handleTooltipDocumentTouchStart(event) { var tracker = active_touch_tooltip_tracker; if (tracker) { if (!tracker._touch) { tracker._hideTooltip(TOOLTIP_TOUCH_HIDE_DELAY); active_touch_tooltip_tracker = null } tracker._touch = null } } function handleTooltipDocumentTouchEnd(event) { var tracker = active_touch_tooltip_tracker; if (tracker) if (tracker._showTooltipTimeout) { tracker._hideTooltip(TOOLTIP_TOUCH_HIDE_DELAY); active_touch_tooltip_tracker = null } } $(window.document).on({ 'touchstart.gauge-tooltip': handleTooltipDocumentTouchStart, 'touchend.gauge-tooltip': handleTooltipDocumentTouchEnd }) })(DevExpress, jQuery); /*! Module viz-gauges, file dxCircularGauge.js */ (function(DX, undefined) { DX.registerComponent("dxCircularGauge", DX.viz.gauges.CircularGauge) })(DevExpress); /*! Module viz-gauges, file dxLinearGauge.js */ (function(DX, undefined) { DX.registerComponent("dxLinearGauge", DX.viz.gauges.LinearGauge) })(DevExpress); DevExpress.MOD_VIZ_GAUGES = true } if (!DevExpress.MOD_VIZ_RANGESELECTOR) { if (!DevExpress.MOD_VIZ_CORE) throw Error('Required module is not referenced: viz-core'); /*! Module viz-rangeselector, file namespaces.js */ (function(DevExpress) { DevExpress.viz.rangeSelector = {utils: {}} })(DevExpress); /*! Module viz-rangeselector, file utils.js */ (function($, DX, undefined) { var rangeSelector = DX.viz.rangeSelector, utils = rangeSelector.utils, dxUtils = DX.utils; var INVISIBLE_POS = -1000; var findLessOrEqualValueIndex = function(values, value) { if (!values || values.length === 0) return -1; var minIndex = 0, maxIndex = values.length - 1, index = 0; while (maxIndex - minIndex > 1) { var index = minIndex + maxIndex >> 1; if (values[index] > value) maxIndex = index; else minIndex = index } return values[maxIndex] <= value ? maxIndex : minIndex }; var findLessOrEqualValue = function(values, value) { var index = findLessOrEqualValueIndex(values, value); if (values && index >= 0 && index < values.length) return values[index]; return value }; var findNearValue = function(values, value) { var index = findLessOrEqualValueIndex(values, value); if (values && index >= 0 && index < values.length) { if (index + 1 < values.length) if (dxUtils.isDate(value)) { if (values[index + 1].getTime() - value.getTime() < value.getTime() - values[index].getTime()) index++ } else if (values[index + 1] - value < value - values[index]) index++; return values[index] } return value }; var findGreaterOrEqualValue = function(values, value) { var index = findLessOrEqualValueIndex(values, value); if (values && index >= 0 && index < values.length) { if (values[index] < value && index + 1 < values.length) index++; return values[index] } return value }; var getInterval = function(valueMin, valueMax, delta) { var result, minDateDaysCount, maxDateDaysCount, daysCount, prevMaxDaysCount; if (dxUtils.isDate(valueMin)) { if (delta === 'year' || delta === 'quarter' || delta === 'month') return {months: valueMax.getFullYear() * 12 + valueMax.getMonth() - valueMin.getFullYear() * 12 - valueMin.getMonth()}; else return {milliseconds: valueMax.valueOf() - valueMin.valueOf()}; return result } else return valueMax - valueMin }; var getRootOffsetLeft = function(renderer) { return dxUtils.getRootOffset(renderer).left || 0 }; var getEventPageX = function(eventArgs) { var result = 0; if (eventArgs.pageX) result = eventArgs.pageX; else if (eventArgs.originalEvent && eventArgs.originalEvent.pageX) result = eventArgs.originalEvent.pageX; if (eventArgs.originalEvent && eventArgs.originalEvent.touches) if (eventArgs.originalEvent.touches.length > 0) result = eventArgs.originalEvent.touches[0].pageX; else if (eventArgs.originalEvent.changedTouches.length > 0) result = eventArgs.originalEvent.changedTouches[0].pageX; return result }; var getTextBBox = function(renderer, text, fontOptions) { var textElement = renderer.createText(text, INVISIBLE_POS, INVISIBLE_POS, {font: fontOptions}).append(); var textBBox = textElement.getBBox(); textElement.remove(); return textBBox }; utils.findLessOrEqualValue = findLessOrEqualValue; utils.findNearValue = findNearValue; utils.findGreaterOrEqualValue = findGreaterOrEqualValue; utils.getInterval = getInterval; utils.getRootOffsetLeft = getRootOffsetLeft; utils.getEventPageX = getEventPageX; utils.getTextBBox = getTextBBox })(jQuery, DevExpress); /*! Module viz-rangeselector, file baseVisualElement.js */ (function(DX) { DevExpress.viz.rangeSelector.BaseVisualElement = DX.Class.inherit({ ctor: function(renderer) { this._renderer = renderer; this._isDrawn = false }, applyOptions: function(options) { this._options = options || {}; this._applyOptions(this._options) }, _applyOptions: function(options){}, redraw: function(group) { var that = this; if (!that._isDrawn) { that._isDrawn = !(that._draw(group || that._group) === false); if (group) that._group = group } else that._update(group || that._group) }, isDrawn: function() { return !!this._isDrawn }, isInitialized: function() { return !!this._options }, _draw: function(group){}, _update: function(group) { group.clear(); this._draw(group) } }) })(DevExpress); /*! Module viz-rangeselector, file rangeSelector.js */ (function($, DX, undefined) { var rangeSelector = DX.viz.rangeSelector, utils = DX.utils, dataUtils = DX.data.utils, rangeSelectorUtils = rangeSelector.utils, ParseUtils = DX.viz.core.ParseUtils, formatHelper = DX.formatHelper, core = DX.viz.core, _max = Math.max, _isDefined = utils.isDefined; rangeSelector.consts = { fontHeightRatio: 0.55, emptySliderMarkerText: '. . .' }; rangeSelector.formatValue = function(value, formatOptions) { var formatObject = { value: value, valueText: formatHelper.format(value, formatOptions.format, formatOptions.precision) }; return String(utils.isFunction(formatOptions.customizeText) ? formatOptions.customizeText.call(formatObject, formatObject) : formatObject.valueText) }; rangeSelector.RangeSelector = core.BaseWidget.inherit(function() { var SCALE_TEXT_SPACING = 5; var defaultRangeSelectorOptions = { size: undefined, margin: { left: 0, top: 0, right: 0, bottom: 0 }, scale: { showCustomBoundaryTicks: true, showMinorTicks: true, startValue: undefined, endValue: undefined, minorTickCount: undefined, minorTickInterval: undefined, majorTickInterval: undefined, useTicksAutoArrangement: true, setTicksAtUnitBeginning: true, minRange: undefined, maxRange: undefined, placeholderHeight: undefined, valueType: undefined, label: { visible: true, format: undefined, precision: undefined, customizeText: undefined }, marker: { visible: true, label: { format: undefined, precision: undefined, customizeText: undefined } }, logarithmBase: 10 }, selectedRange: undefined, sliderMarker: { visible: true, format: undefined, precision: undefined, customizeText: undefined, placeholderSize: undefined }, behavior: { snapToTicks: true, animationEnabled: true, moveSelectedRangeByClick: true, manualRangeSelectionEnabled: true, allowSlidersSwap: true, callSelectedRangeChanged: "onMovingComplete" }, background: { color: "#C0BAE1", visible: true, image: { url: undefined, location: 'full' } }, dataSource: undefined, dataSourceField: 'arg', redrawOnResize: true, theme: undefined, selectedRangeChanged: null }; var calculateMarkerSize = function(renderer, value, sliderMarkerOptions) { var formattedText = value === undefined ? rangeSelector.consts.emptySliderMarkerText : rangeSelector.formatValue(value, sliderMarkerOptions), textBBox = rangeSelectorUtils.getTextBBox(renderer, formattedText, sliderMarkerOptions.font); return { width: Math.ceil(textBBox.width) + 2 * sliderMarkerOptions.padding, height: Math.ceil(textBBox.height * rangeSelector.consts.fontHeightRatio) + 2 * sliderMarkerOptions.padding + sliderMarkerOptions.pointerSize } }; var calculateScaleLabelHalfWidth = function(renderer, value, scaleOptions) { var formattedText = rangeSelector.formatValue(value, scaleOptions.label), textBBox = rangeSelectorUtils.getTextBBox(renderer, formattedText, scaleOptions.label.font); return Math.ceil(textBBox.width / 2) }; var calculateRangeContainerCanvas = function(size, margin, sliderMarkerSpacing) { var canvas = { left: margin.left + sliderMarkerSpacing.left, top: margin.top + sliderMarkerSpacing.top, width: size.width - margin.left - margin.right - sliderMarkerSpacing.left - sliderMarkerSpacing.right, height: size.height - margin.top - margin.bottom - sliderMarkerSpacing.top - sliderMarkerSpacing.bottom }; if (canvas.width <= 0) canvas.width = 1; return canvas }; var parseSliderMarkersPlaceholderSize = function(placeholderSize) { var placeholderWidthLeft, placeholderWidthRight, placeholderHeight; if (utils.isNumber(placeholderSize)) placeholderWidthLeft = placeholderWidthRight = placeholderHeight = placeholderSize; else if (placeholderSize) { if (utils.isNumber(placeholderSize.height)) placeholderHeight = placeholderSize.height; if (utils.isNumber(placeholderSize.width)) placeholderWidthLeft = placeholderWidthRight = placeholderSize.width; else if (placeholderSize.width) { if (utils.isNumber(placeholderSize.width.left)) placeholderWidthLeft = placeholderSize.width.left; if (utils.isNumber(placeholderSize.width.right)) placeholderWidthRight = placeholderSize.width.right } } return { widthLeft: placeholderWidthLeft, widthRight: placeholderWidthRight, height: placeholderHeight } }; var calculateSliderMarkersSpacing = function(renderer, size, scale, sliderMarkerOptions) { var leftMarkerSize, leftScaleLabelWidth = 0, rightScaleLabelWidth = 0, rightMarkerSize, placeholderWidthLeft = 0, placeholderWidthRight = 0, placeholderHeight = 0, parsedPlaceholderSize, markerMaxWidth; parsedPlaceholderSize = parseSliderMarkersPlaceholderSize(sliderMarkerOptions.placeholderSize); placeholderWidthLeft = parsedPlaceholderSize.widthLeft || 0; placeholderWidthRight = parsedPlaceholderSize.widthRight || 0; placeholderHeight = parsedPlaceholderSize.height || 0; if (sliderMarkerOptions.visible) { leftMarkerSize = calculateMarkerSize(renderer, scale.startValue, sliderMarkerOptions); rightMarkerSize = calculateMarkerSize(renderer, scale.endValue, sliderMarkerOptions); markerMaxWidth = _max(leftMarkerSize.width, rightMarkerSize.width); if (!placeholderWidthLeft) placeholderWidthLeft = markerMaxWidth; if (!placeholderWidthRight) placeholderWidthRight = markerMaxWidth; if (!placeholderHeight) placeholderHeight = _max(leftMarkerSize.height, rightMarkerSize.height) } if (scale.label.visible) { leftScaleLabelWidth = calculateScaleLabelHalfWidth(renderer, scale.startValue, scale); rightScaleLabelWidth = calculateScaleLabelHalfWidth(renderer, scale.endValue, scale) } placeholderWidthLeft = _max(placeholderWidthLeft, leftScaleLabelWidth); placeholderWidthRight = _max(placeholderWidthRight, rightScaleLabelWidth); return { left: placeholderWidthLeft, right: placeholderWidthRight, top: placeholderHeight, bottom: 0 } }; var clearContainer = function(container) { if (container) container.empty() }; var getContainer = function(that) { return that._element() }; var createRangeContainer = function(rangeContainerOptions) { return rangeSelector.rangeSelectorFactory.createRangeContainer(rangeContainerOptions) }; var createTranslator = function(range, canvas) { return { x: core.CoreFactory.createTranslator2D(range.arg, canvas, {direction: "horizontal"}), y: core.CoreFactory.createTranslator2D(range.val, canvas) } }; var createTranslatorCanvas = function(sizeOptions, rangeContainerCanvas, scaleLabelsAreaHeight) { return { left: rangeContainerCanvas.left, top: rangeContainerCanvas.top, right: sizeOptions.width - rangeContainerCanvas.width - rangeContainerCanvas.left, bottom: sizeOptions.height - rangeContainerCanvas.height - rangeContainerCanvas.top + scaleLabelsAreaHeight, width: sizeOptions.width, height: sizeOptions.height } }; var createRenderer = function(that) { var renderer = that.option('renderer'); if (renderer) return renderer; return core.CoreFactory.createRenderer({ pathModified: that.option('pathModified'), rtl: that.option('rtlEnabled') }) }; var createThemeManager = function(theme) { return rangeSelector.rangeSelectorFactory.createThemeManager(theme) }; var calculateValueType = function(firstValue, secondValue) { var types = [$.type(firstValue), $.type(secondValue)]; $.inArray(); return $.inArray('date', types) != -1 ? 'datetime' : $.inArray('number', types) != -1 ? 'numeric' : '' }; var createSeriesDataSource = function(that) { var seriesDataSource, dataSource = that._dataSource && that._dataSource.items(), scaleOptions = that.option('scale'), chartOptions = that.option('chart') || {}, valueType = scaleOptions.valueType; if (!valueType) valueType = calculateValueType(scaleOptions.startValue, scaleOptions.endValue); if (dataSource || chartOptions.series) { seriesDataSource = new rangeSelector.SeriesDataSource({ renderer: that.renderer, dataSource: dataSource, valueType: (valueType || '').toLowerCase(), axisType: scaleOptions.type, chart: chartOptions, dataSourceField: that.option('dataSourceField'), backgroundColor: that._userBackgroundColor, incidentOccured: that._incidentOccured }); checkLogarithmicOptions(chartOptions.valueAxis, seriesDataSource.themeManager.theme().valueAxis.logarithmBase, that._incidentOccured) } return seriesDataSource }; var calculateTranslatorRange = function(that, seriesDataSource, scaleOptions) { var translatorRange, minValue, maxValue, inverted = false, isEqualDates; if (_isDefined(scaleOptions.startValue) && _isDefined(scaleOptions.endValue)) { inverted = scaleOptions.inverted = scaleOptions.startValue > scaleOptions.endValue; minValue = inverted ? scaleOptions.endValue : scaleOptions.startValue; maxValue = inverted ? scaleOptions.startValue : scaleOptions.endValue } else if (_isDefined(scaleOptions.startValue) || _isDefined(scaleOptions.endValue)) { minValue = scaleOptions.startValue; maxValue = scaleOptions.endValue } translatorRange = seriesDataSource ? seriesDataSource.getBoundRange() : { arg: new core.Range, val: new core.Range({isValueRange: true}) }; isEqualDates = utils.isDate(minValue) && utils.isDate(maxValue) && minValue.getTime() === maxValue.getTime(); if (minValue !== maxValue && !isEqualDates) translatorRange.arg.addRange({ invert: inverted, min: minValue, max: maxValue, minVisible: minValue, maxVisible: maxValue, dataType: scaleOptions.valueType }); translatorRange.arg.addRange({ base: scaleOptions.logarithmBase, axisType: scaleOptions.type }); if (!translatorRange.arg.isDefined()) { if (isEqualDates) scaleOptions.valueType = 'numeric'; translatorRange.arg.setStubData(scaleOptions.valueType) } return translatorRange }; var calculateScaleAreaHeight = function(renderer, scaleOptions, visibleMarkers) { var textBBox, visibleLabels = scaleOptions.label.visible; if (scaleOptions.placeholderHeight) return scaleOptions.placeholderHeight; else { textBBox = rangeSelectorUtils.getTextBBox(renderer, '0', scaleOptions.label.font); return (visibleLabels ? scaleOptions.label.topIndent + textBBox.height : 0) + (visibleMarkers ? scaleOptions.marker.topIndent + scaleOptions.marker.separatorHeight : 0) } }; var getTicksInfo = function(that, scaleOptions, translators, screenDelta) { var isEmpty = scaleOptions.isEmpty, tickProvider = core.CoreFactory.getTickProvider(), minorTicksOptions, majorTicksOptions, startValue, endValue, businessRange = translators.x.getBusinessRange(); minorTicksOptions = { tickInterval: isEmpty ? 0 : that.option('scale').minorTickInterval, showCustomBoundaryTicks: scaleOptions.showCustomBoundaryTicks, minorTickCount: scaleOptions.minorTickCount }; majorTicksOptions = { textOptions: { align: 'center', font: scaleOptions.label.font }, renderer: that.renderer, getText: function(value) { return rangeSelector.formatValue(value, scaleOptions.label) }, translator: translators.x, isStartTickGenerated: !_isDefined(that.option('scale').majorTickInterval), tickInterval: scaleOptions.majorTickInterval, textSpacing: SCALE_TEXT_SPACING, setTicksAtUnitBeginning: scaleOptions.setTicksAtUnitBeginning, useTicksAutoArrangement: scaleOptions.useTicksAutoArrangement, hideLabels: isEmpty }; startValue = isEmpty ? businessRange.min : scaleOptions.startValue; endValue = isEmpty ? businessRange.max : scaleOptions.endValue; return tickProvider.getFullTicks(startValue, endValue, screenDelta, majorTicksOptions, minorTicksOptions, { axisType: scaleOptions.type, dataType: scaleOptions.valueType, base: scaleOptions.logarithmBase }) }; var updateTickIntervals = function(scaleOptions, screenDelta, incidentOccured) { var tickProvider = core.CoreFactory.getTickProvider(), tickIntervals = tickProvider.getTickIntervals(scaleOptions.startValue, scaleOptions.endValue, screenDelta, { tickInterval: scaleOptions.majorTickInterval, incidentOccured: incidentOccured }, { tickInterval: scaleOptions.minorTickInterval, incidentOccured: incidentOccured }, { axisType: scaleOptions.type, dataType: scaleOptions.valueType, base: scaleOptions.logarithmBase }); scaleOptions.minorTickInterval = tickIntervals.minorTickInterval; scaleOptions.majorTickInterval = tickIntervals.majorTickInterval }; var updateScaleOptions = function(that, seriesDataSource, translatorRange, screenDelta, scaleOptions) { var minVisibleX = _isDefined(translatorRange.arg.minVisible) ? translatorRange.arg.minVisible : translatorRange.arg.min, maxVisibleX = _isDefined(translatorRange.arg.maxVisible) ? translatorRange.arg.maxVisible : translatorRange.arg.max, isEmptyInterval; if (seriesDataSource && !seriesDataSource.isEmpty()) { scaleOptions.startValue = scaleOptions.inverted ? maxVisibleX : minVisibleX; scaleOptions.endValue = scaleOptions.inverted ? minVisibleX : maxVisibleX } isEmptyInterval = utils.isDate(scaleOptions.startValue) && utils.isDate(scaleOptions.endValue) && scaleOptions.startValue.getTime() === scaleOptions.endValue.getTime() || scaleOptions.startValue === scaleOptions.endValue; scaleOptions.isEmpty = !_isDefined(scaleOptions.startValue) || !_isDefined(scaleOptions.endValue) || isEmptyInterval || scaleOptions.valueType === 'string'; if (scaleOptions.isEmpty) scaleOptions.startValue = scaleOptions.endValue = undefined; else { updateTickIntervals(scaleOptions, screenDelta, that._incidentOccured); if (scaleOptions.valueType === 'datetime' && !_isDefined(scaleOptions.label.format)) if (!scaleOptions.marker.visible) scaleOptions.label.format = formatHelper.getDateFormatByTickInterval(scaleOptions.startValue, scaleOptions.endValue, scaleOptions.majorTickInterval); else scaleOptions.label.format = utils.getDateUnitInterval(scaleOptions.majorTickInterval) } }; var prepareSliderMarkersOptions = function(that, scaleOptions, screenDelta) { var sliderMarkerOptions = $.extend(true, {}, that.option('sliderMarker')), businessInterval; if (!sliderMarkerOptions.format) { if (!that.option('behavior').snapToTicks && utils.isNumber(scaleOptions.startValue)) { businessInterval = Math.abs(scaleOptions.endValue - scaleOptions.startValue); sliderMarkerOptions.format = 'fixedPoint'; sliderMarkerOptions.precision = utils.getSignificantDigitPosition(businessInterval / screenDelta) } if (scaleOptions.valueType === 'datetime') if (!scaleOptions.marker.visible) { if (_isDefined(scaleOptions.startValue) && _isDefined(scaleOptions.endValue)) sliderMarkerOptions.format = formatHelper.getDateFormatByTickInterval(scaleOptions.startValue, scaleOptions.endValue, scaleOptions.minorTickInterval !== 0 ? scaleOptions.minorTickInterval : scaleOptions.majorTickInterval) } else sliderMarkerOptions.format = utils.getDateUnitInterval(_isDefined(scaleOptions.minorTickInterval) && scaleOptions.minorTickInterval !== 0 ? scaleOptions.minorTickInterval : scaleOptions.majorTickInterval) } return sliderMarkerOptions }; var showScaleMarkers = function(scaleOptions) { return scaleOptions.valueType == 'datetime' && scaleOptions.marker.visible }; var updateTranslatorRangeInterval = function(translatorRange, scaleOptions) { var intervalX = scaleOptions.minorTickInterval || scaleOptions.majorTickInterval; translatorRange = translatorRange.arg.addRange({interval: intervalX}) }; var checkLogarithmicOptions = function(options, logarithmBase, incidentOccured) { if (!options) return; if (options.type === 'logarithmic' && options.logarithmBase <= 0 || options.logarithmBase && !$.isNumeric(options.logarithmBase)) { options.logarithmBase = logarithmBase; incidentOccured('E2104') } else if (options.type !== 'logarithmic') options.logarithmBase = undefined }; var prepareScaleOptions = function(that, seriesDataSource) { var scaleOptions = $.extend(true, {}, that.option('scale')), incidentOccured = that._incidentOccured, parsedValue = 0, parseUtils = new ParseUtils({incidentOccured: incidentOccured}), valueType = parseUtils.correctValueType((scaleOptions.valueType || '').toLowerCase()); if (seriesDataSource) valueType = seriesDataSource.getCalculatedValueType() || valueType; if (!valueType) valueType = calculateValueType(scaleOptions.startValue, scaleOptions.endValue) || 'numeric'; scaleOptions.valueType = valueType; if (scaleOptions.valueType === 'string') { that._incidentOccured("E2201"); return scaleOptions } var parser = parseUtils.getParser(valueType, 'scale'); if (_isDefined(scaleOptions.startValue)) { parsedValue = parser(scaleOptions.startValue); if (_isDefined(parsedValue)) scaleOptions.startValue = parsedValue; else { scaleOptions.startValue = undefined; that._incidentOccured("E2202", ["start"]) } } if (_isDefined(scaleOptions.endValue)) { parsedValue = parser(scaleOptions.endValue); if (_isDefined(parsedValue)) scaleOptions.endValue = parsedValue; else { scaleOptions.endValue = undefined; that._incidentOccured("E2202", ["end"]) } } checkLogarithmicOptions(scaleOptions, defaultRangeSelectorOptions.scale.logarithmBase, that._incidentOccured); if (!scaleOptions.type) scaleOptions.type = 'continuous'; scaleOptions.parser = parser; return scaleOptions }; var correctSizeOptions = function(that, sizeOptions, scaleOptions) { var size = that.option('size') || {}; if (!sizeOptions.height && size.height !== 0) if (scaleOptions.valueType === 'datetime' && scaleOptions.marker.visible !== false) sizeOptions.height = 160; else sizeOptions.height = 120; if (!sizeOptions.width && size.width !== 0) sizeOptions.width = 400 }; var applyOptions = function(that) { var rangeContainerCanvas, seriesDataSource, translatorRange, scaleLabelsAreaHeight, sizeOptions, sliderMarkerSpacing, sliderMarkerOptions, selectedRange, $container = that.container; that._isUpdating = true; sizeOptions = calculateSize(that); that._actualSize = sizeOptions; seriesDataSource = createSeriesDataSource(that); that._scaleOptions = prepareScaleOptions(that, seriesDataSource); correctSizeOptions(that, sizeOptions, that._scaleOptions); if (!sizeOptions.width || !sizeOptions.height || !$container.is(':visible')) { that.stopRedraw = true; that._incidentOccured("W2001", [that.NAME]); return } else that.stopRedraw = false; updateRendererSize(that, sizeOptions); that._updateLoadIndicator(undefined, that.canvas.width, that.canvas.height); translatorRange = calculateTranslatorRange(that, seriesDataSource, that._scaleOptions); updateScaleOptions(that, seriesDataSource, translatorRange, sizeOptions.width, that._scaleOptions); updateTranslatorRangeInterval(translatorRange, that._scaleOptions); sliderMarkerOptions = prepareSliderMarkersOptions(that, that._scaleOptions, sizeOptions.width); selectedRange = initSelection(that, that._scaleOptions); sliderMarkerSpacing = calculateSliderMarkersSpacing(that.renderer, sizeOptions, that._scaleOptions, sliderMarkerOptions); rangeContainerCanvas = calculateRangeContainerCanvas(sizeOptions, that.option('margin'), sliderMarkerSpacing); scaleLabelsAreaHeight = calculateScaleAreaHeight(that.renderer, that._scaleOptions, showScaleMarkers(that._scaleOptions)); that.translators = createTranslator(translatorRange, createTranslatorCanvas(sizeOptions, rangeContainerCanvas, scaleLabelsAreaHeight)); that._scaleOptions.ticksInfo = getTicksInfo(that, that._scaleOptions, that.translators, rangeContainerCanvas.width); that._testTicksInfo = that._scaleOptions.ticksInfo; that._selectedRange = selectedRange; if (seriesDataSource) seriesDataSource.adjustSeriesDimensions(that.translators); that.rangeContainer.applyOptions({ canvas: rangeContainerCanvas, scaleLabelsAreaHeight: scaleLabelsAreaHeight, sliderMarkerSpacing: sliderMarkerSpacing, translators: that.translators, selectedRange: selectedRange, scale: that._scaleOptions, behavior: that.option('behavior'), background: that.option('background'), chart: that.option('chart'), seriesDataSource: seriesDataSource, sliderMarker: sliderMarkerOptions, sliderHandle: that.option('sliderHandle'), shutter: that.option('shutter'), selectedRangeChanged: createSelectedRangeChangedFunction(that), setSelectedRange: function(selectedRange) { that.setSelectedRange(selectedRange) } }); that._isUpdating = false }; var createSelectedRangeChangedFunction = function(that) { return function(selectedRange, blockSelectedRangeChanged) { var selectedRangeChanged = that.option('selectedRangeChanged'); that.option('selectedRange', selectedRange); if (selectedRangeChanged && !blockSelectedRangeChanged) setTimeout(function() { selectedRangeChanged.call(null, selectedRange) }) } }; var calculateSize = function(that) { var $container = that.container, size = that.option('size') || {}, result = { width: size.width, height: size.height }; if ($container) { if (!result.width) result.width = $container.width(); if (!result.height) result.height = $container.height() } that.canvas = result; return result }; var updateRendererSize = function(that, size) { var renderer = that.renderer; if (renderer.isInitialized()) renderer.getRoot().applySettings({ width: size.width, height: size.height }); else { renderer.recreateCanvas(size.width, size.height); renderer.draw(that.container[0]) } }; var prepareChartThemeOptions = function(that, options) { var chartTheme, chartOption = that.option('chart') || {}; if (!chartOption.theme && options && options.theme) { chartTheme = options.theme; if (chartTheme) { if (typeof chartTheme === 'object') { chartTheme = chartTheme.chart || {}; chartTheme.name = options.theme.name } chartOption.theme = chartTheme } } }; var initSelection = function(that, scaleOptions) { var selectedRangeOptions = that.option('selectedRange'), startValue, endValue, parser = scaleOptions.parser || function() { return null }, parseValue = function(value, entity) { var parsedValue, result = scaleOptions[entity]; if (_isDefined(value)) parsedValue = parser(value); if (!_isDefined(parsedValue)) that._incidentOccured("E2203", [entity]); else result = parsedValue; return result }; if (!selectedRangeOptions) return { startValue: scaleOptions.startValue, endValue: scaleOptions.endValue }; else { startValue = parseValue(selectedRangeOptions.startValue, 'startValue'); startValue = that.rangeContainer.slidersContainer.truncateSelectedRange(startValue, scaleOptions); endValue = parseValue(selectedRangeOptions.endValue, 'endValue'); endValue = that.rangeContainer.slidersContainer.truncateSelectedRange(endValue, scaleOptions); return { startValue: startValue, endValue: endValue } } }; var _isSizeChanged = function(that) { var actualSize = that._actualSize, newSize = calculateSize(that); return actualSize && (actualSize.width !== newSize.width || actualSize.height !== newSize.height) }; return { isSizeChanged: function() { return _isSizeChanged(this) }, _setDefaultOptions: function() { this.callBase(); this.option(defaultRangeSelectorOptions) }, _dataSourceOptions: function() { return { paginate: false, _preferSync: true } }, _init: function() { var that = this; that.container = getContainer(that); clearContainer(that.container); that.renderer = createRenderer(that); that.rangeContainer = createRangeContainer(that.renderer); that.callBase(); that._reinitDataSource() }, _reinitDataSource: function() { this._refreshDataSource() }, _dispose: function() { var that = this, disposeObject = function(propName) { that[propName] && that[propName].dispose(), that[propName] = null }; that.callBase(); disposeObject("renderer"); that.translators = null; disposeObject("rangeContainer") }, _initOptions: function(options) { var that = this, themeManager; that._optionsInitializing = true; options = options || {}; that._userOptions = $.extend(true, {}, options); themeManager = createThemeManager(options.theme); themeManager.setBackgroundColor(options.containerBackgroundColor); that.option(themeManager.applyRangeSelectorTheme(options)); prepareChartThemeOptions(that, options); if (options.background) that._userBackgroundColor = options.background.color }, _refresh: function() { var that = this, callBase = that.callBase; that._endLoading(function() { callBase.call(that) }) }, _render: function(isResizing) { var that = this, currentAnimationEnabled, behaviorOptions; that._optionsInitializing = false; applyOptions(that); if (!that.stopRedraw) { if (isResizing) { behaviorOptions = that.option('behavior'); currentAnimationEnabled = behaviorOptions.animationEnabled; behaviorOptions.animationEnabled = false; that.rangeContainer.redraw(); behaviorOptions.animationEnabled = currentAnimationEnabled } else that.rangeContainer.redraw(); !isResizing && (!that._dataSource || that._dataSource && that._dataSource.isLoaded()) && that.hideLoadingIndicator() } that._drawn(); that.__rendered && that.__rendered() }, _optionChanged: function(name, value, prevValue) { var that = this; if (!that._optionsInitializing) dataUtils.compileSetter(name)(that._userOptions, value, { functionsAsIs: true, merge: true }); if (name === "dataSource") { that._reinitDataSource(); that._invalidate() } else if (name === "selectedRange") that.setSelectedRange(that.option('selectedRange')); else if (name === "selectedRangeChanged") that.rangeContainer.slidersContainer.selectedRangeChanged = createSelectedRangeChangedFunction(that); else if (name === 'containerBackgroundColor' || name === 'theme') { that._initOptions(that._userOptions); that._invalidate() } else that.callBase(name, value, prevValue) }, _resize: function() { if (_isSizeChanged(this)) this._render(true) }, _handleDataSourceChanged: function() { var that = this; that._endLoading(function() { if (that.renderer.isInitialized()) that._render() }) }, getSelectedRange: function() { var that = this; var selectedRange = that.rangeContainer.slidersContainer.getSelectedRange(); return { startValue: selectedRange.startValue, endValue: selectedRange.endValue } }, setSelectedRange: function(selectedRange) { var that = this; if (that._isUpdating || !selectedRange) return; var oldSelectedRange = that.rangeContainer.slidersContainer.getSelectedRange(); if (oldSelectedRange && oldSelectedRange.startValue === selectedRange.startValue && oldSelectedRange.endValue === selectedRange.endValue) return; that.rangeContainer.slidersContainer.setSelectedRange(selectedRange) }, resetSelectedRange: function(blockSelectedRangeChanged) { var that = this; that.setSelectedRange({ startValue: that._scaleOptions.startValue, endValue: that._scaleOptions.endValue, blockSelectedRangeChanged: blockSelectedRangeChanged }) }, render: function(isResizing) { this._render(isResizing); return this } } }()).include(DX.ui.DataHelperMixin) })(jQuery, DevExpress); /*! Module viz-rangeselector, file rangeContainer.js */ (function($, DX, undefined) { var rangeSelector = DX.viz.rangeSelector; rangeSelector.RangeContainer = rangeSelector.BaseVisualElement.inherit(function() { var ctor = function(renderer) { this.callBase(renderer); this.slidersContainer = createSlidersContainer(renderer); this.rangeView = createRangeView(renderer); this.scale = createScale(renderer) }; var _applyOptions = function(options) { var that = this, isEmpty = options.scale.isEmpty, viewCanvas = { left: options.canvas.left, top: options.canvas.top, width: options.canvas.width, height: options.canvas.height >= options.scaleLabelsAreaHeight ? options.canvas.height - options.scaleLabelsAreaHeight : 0 }; that._viewCanvas = viewCanvas; that.slidersContainer.applyOptions({ canvas: viewCanvas, translator: options.translators.x, scale: options.scale, selectedRange: options.selectedRange, sliderMarker: options.sliderMarker, sliderHandle: options.sliderHandle, shutter: options.shutter, behavior: options.behavior, selectedRangeChanged: options.selectedRangeChanged, isEmpty: isEmpty }); that.rangeView.applyOptions({ canvas: viewCanvas, translators: options.translators, background: options.background, chart: options.chart, seriesDataSource: options.seriesDataSource, behavior: options.behavior, isEmpty: isEmpty }); that.scale.applyOptions({ canvas: options.canvas, translator: options.translators.x, scale: options.scale, hideLabels: isEmpty, scaleLabelsAreaHeight: options.scaleLabelsAreaHeight, setSelectedRange: options.setSelectedRange }) }; var createSlidersContainer = function(options) { return rangeSelector.rangeSelectorFactory.createSlidersContainer(options) }; var createScale = function(options) { return rangeSelector.rangeSelectorFactory.createScale(options) }; var createRangeView = function(options) { return rangeSelector.rangeSelectorFactory.createRangeView(options) }; var _createClipRectCanvas = function(canvas, sliderMarkerSpacing) { return { left: canvas.left - sliderMarkerSpacing.left, top: canvas.top - sliderMarkerSpacing.top, width: canvas.width + sliderMarkerSpacing.right + sliderMarkerSpacing.left, height: canvas.height + sliderMarkerSpacing.bottom + sliderMarkerSpacing.top } }; var _draw = function() { var that = this, containerGroup, rangeViewGroup, slidersContainerGroup, scaleGroup, trackersGroup, clipRectCanvas = _createClipRectCanvas(that._options.canvas, that._options.sliderMarkerSpacing), viewCanvas = that._viewCanvas; that._clipRect = that._renderer.createClipRect(clipRectCanvas.left, clipRectCanvas.top, clipRectCanvas.width, clipRectCanvas.height).append(); containerGroup = that._renderer.createGroup({ 'class': 'rangeContainer', clipId: that._clipRect.id }).append(); that._viewClipRect = that._renderer.createClipRect(viewCanvas.left, viewCanvas.top, viewCanvas.width, viewCanvas.height).append(); rangeViewGroup = that._renderer.createGroup({ 'class': 'view', clipId: that._viewClipRect.id }); rangeViewGroup.append(containerGroup); that.rangeView.redraw(rangeViewGroup); slidersContainerGroup = that._renderer.createGroup({'class': 'slidersContainer'}); slidersContainerGroup.append(containerGroup); that.slidersContainer.redraw(slidersContainerGroup); scaleGroup = that._renderer.createGroup({'class': 'scale'}); scaleGroup.append(containerGroup); that.scale.redraw(scaleGroup); trackersGroup = that._renderer.createGroup({'class': 'trackers'}); trackersGroup.append(containerGroup); that._trackersGroup = trackersGroup; that.slidersContainer.appendTrackers(trackersGroup) }; var _update = function() { var that = this, clipRectCanvas = _createClipRectCanvas(that._options.canvas, that._options.sliderMarkerSpacing), viewCanvas = that._viewCanvas; that._clipRect.updateRectangle({ x: clipRectCanvas.left, y: clipRectCanvas.top, width: clipRectCanvas.width, height: clipRectCanvas.height }); that._viewClipRect.updateRectangle({ x: viewCanvas.left, y: viewCanvas.top, width: viewCanvas.width, height: viewCanvas.height }); that.rangeView.redraw(); that.slidersContainer.redraw(); that.slidersContainer.appendTrackers(that._trackersGroup); that.scale.redraw() }; var dispose = function() { this.slidersContainer.dispose(); this.slidersContainer = null }; var prototypeObject = { createSlidersContainer: createSlidersContainer, createScale: createScale, ctor: ctor, dispose: dispose, _applyOptions: _applyOptions, _draw: _draw, _update: _update }; return prototypeObject }()) })(jQuery, DevExpress); /*! Module viz-rangeselector, file scale.js */ (function($, DX, undefined) { var rangeSelector = DX.viz.rangeSelector, formatHelper = DX.formatHelper, utils = DX.utils; var SCALE_TEXT_SPACING = 5; rangeSelector.Scale = rangeSelector.BaseVisualElement.inherit({ _setupDateUnitInterval: function(scaleOptions) { var key, hasObjectSingleField = function(object) { var fieldsCounter = 0; $.each(object, function() { return ++fieldsCounter < 2 }); return fieldsCounter === 1 }, millisecTickInterval, majorTickInterval = scaleOptions.ticksInfo.majorTickInterval, majorTicks = scaleOptions.ticksInfo.majorTicks; if (scaleOptions.valueType === 'datetime') { if (utils.isObject(majorTickInterval) && !hasObjectSingleField(majorTickInterval)) utils.logger.warn('More than one field is specified within the object assigned to the "tickInterval" option. Assign an object with a single field specified (days, hours or a similar one).'); if (majorTicks && majorTicks.autoArrangementStep > 1) { if (utils.isString(majorTickInterval)) majorTickInterval = utils.getDateIntervalByString(majorTickInterval); for (key in majorTickInterval) if (majorTickInterval.hasOwnProperty(key)) { majorTickInterval[key] *= majorTicks.autoArrangementStep; millisecTickInterval = utils.convertDateTickIntervalToMilliseconds(majorTickInterval) } majorTickInterval = utils.convertMillisecondsToDateUnits(millisecTickInterval) } this.dateUnitInterval = utils.getDateUnitInterval(majorTickInterval) } }, _prepareDatesDifferences: function(datesDifferences, tickInterval) { var deleteDifferent = tickInterval, dateUnitInterval, i; if (deleteDifferent === 'week') deleteDifferent = 'day'; if (deleteDifferent === 'quarter') deleteDifferent = 'month'; if (datesDifferences[deleteDifferent]) for (i = 0; i < utils.dateUnitIntervals.length; i++) { dateUnitInterval = utils.dateUnitIntervals[i]; if (datesDifferences[dateUnitInterval]) { datesDifferences[dateUnitInterval] = false; datesDifferences.count-- } if (dateUnitInterval === deleteDifferent) break } }, _getMarkerDate: function(date, tickInterval) { var markerDate = new Date(date.getTime()), month = 0; switch (tickInterval) { case'quarter': month = formatHelper.getFirstQuarterMonth(date.getMonth()); case'month': markerDate.setMonth(month); case'week': case'day': markerDate.setDate(1); case'hour': markerDate.setHours(0, 0, 0, 0); break; case'millisecond': markerDate.setMilliseconds(0); break; case'second': markerDate.setSeconds(0, 0); break; case'minute': markerDate.setMinutes(0, 0, 0); break } return markerDate }, _drawDateMarker: function(date, options) { var labelPosX, labelPosY, dateFormated, scaleOptions, textElement; if (options.x === null) return; scaleOptions = this._options.scale; this.lineOptions['class'] = 'dx-range-selector-date-marker'; this._renderer.createLine(options.x, options.y, options.x, options.y + scaleOptions.marker.separatorHeight, this.lineOptions).append(options.group); dateFormated = this._getLabel(date, options.label); labelPosX = options.x + scaleOptions.tick.width + scaleOptions.marker.textLeftIndent; labelPosY = options.y + scaleOptions.marker.textTopIndent + scaleOptions.label.font.size; this.textOptions.align = 'left'; textElement = this._renderer.createText(dateFormated, labelPosX, labelPosY, this.textOptions).append(options.group); return labelPosX + textElement.getBBox().width }, _drawDateMarkers: function(dates, group) { var dateMarker, i, datesDifferences, markerDate, posX, prevMarkerRightX = -1; if (this._options.scale.valueType !== 'datetime' || !this.visibleMarkers) return; var markerDatePositions = []; if (dates.length > 1) { for (i = 1; i < dates.length; i++) { datesDifferences = utils.getDatesDifferences(dates[i - 1], dates[i]); this._prepareDatesDifferences(datesDifferences, this.dateUnitInterval); if (datesDifferences.count > 0) { markerDate = this._getMarkerDate(dates[i], this.dateUnitInterval); this.markerDates = this.markerDates || []; this.markerDates.push(markerDate); posX = this.translator.translate(markerDate); if (posX > prevMarkerRightX) { posX !== null && markerDatePositions.push({ date: markerDate, posX: posX }); prevMarkerRightX = this._drawDateMarker(markerDate, { group: group, y: this._options.canvas.top + this._options.canvas.height - this.markersAreaHeight + this._options.scale.marker.topIndent, x: posX, label: this._getLabelFormatOptions(formatHelper.getDateFormatByDifferences(datesDifferences)) }) } } } this._initializeMarkersEvents(markerDatePositions, group) } }, _getLabelFormatOptions: function(formatString) { if (!utils.isDefined(this._options.scale.marker.label.format)) return $.extend({}, this._options.scale.marker.label, {format: formatString}); return this._options.scale.marker.label }, _calculateRangeByMarkerPosition: function(posX, markerDatePositions, scaleOptions) { var selectedRange = {}, i, position; for (i = 0; i < markerDatePositions.length; i++) { position = markerDatePositions[i]; if (!scaleOptions.inverted) { if (posX >= position.posX) selectedRange.startValue = position.date; else if (!selectedRange.endValue) selectedRange.endValue = position.date } else if (posX < position.posX) selectedRange.endValue = position.date; else if (!selectedRange.startValue) selectedRange.startValue = position.date } selectedRange.startValue = selectedRange.startValue || scaleOptions.startValue; selectedRange.endValue = selectedRange.endValue || scaleOptions.endValue; return selectedRange }, _initializeMarkersEvents: function(markerDatePositions, group) { var that = this, markersAreaTop = this._options.canvas.top + this._options.canvas.height - this.markersAreaHeight + this._options.scale.marker.topIndent, markersTracker, svgOffsetLeft, index, posX, selectedRange; if (markerDatePositions.length > 0) { markersTracker = that._renderer.createRect(that._options.canvas.left, markersAreaTop, that._options.canvas.width, that._options.scale.marker.separatorHeight, 0, { fill: 'grey', stroke: 'grey', opacity: 0.0001 }); markersTracker.append(group); markersTracker.on(rangeSelector.events.start, function(e) { svgOffsetLeft = rangeSelector.utils.getRootOffsetLeft(that._renderer); posX = rangeSelector.utils.getEventPageX(e) - svgOffsetLeft; selectedRange = that._calculateRangeByMarkerPosition(posX, markerDatePositions, that._options.scale); that._options.setSelectedRange(selectedRange) }); that._markersTracker = markersTracker } }, _getLabel: function(value, options) { var formatObject = { value: value, valueText: formatHelper.format(value, options.format, options.precision) }; return String(utils.isFunction(options.customizeText) ? options.customizeText.call(formatObject, formatObject) : formatObject.valueText) }, _drawLabel: function(value, group) { var textY = this._options.canvas.top + this._options.canvas.height - this.markersAreaHeight, textElement = this._renderer.createText(this._getLabel(value, this._options.scale.label), this.translator.translate(value), textY, this.textOptions); textElement.append(group); this.textElements = this.textElements || []; this.textElements.push(textElement) }, _drawTick: function(value, group) { this.lineOptions['class'] = 'dx-range-selector-tick'; var secondY = this._options.canvas.top + this._options.canvas.height - this.scaleLabelsAreaHeight, posX = this.translator.translate(value), tickElement = this._renderer.createLine(posX, this._options.canvas.top, posX, secondY, this.lineOptions).append(group); this.tickElements = this.tickElements || []; this.tickElements.push(tickElement) }, _redraw: function(group, isOptimize) { var that = this, scaleOptions = that._options.scale, ticksGroup = that._renderer.createGroup(), labelsGroup = that._renderer.createGroup().append(group), majorTicks = scaleOptions.ticksInfo.majorTicks, minorTicks = scaleOptions.ticksInfo.minorTicks, customBoundaryTicks = scaleOptions.ticksInfo.customBoundaryTicks, hideLabels = that._options.hideLabels || majorTicks.hideLabels || !scaleOptions.label.visible, i; for (i = 0; i < majorTicks.length; i++) { if (!hideLabels) that._drawLabel(majorTicks[i], labelsGroup); that._drawTick(majorTicks[i], ticksGroup) } if (scaleOptions.showMinorTicks) for (i = 0; i < minorTicks.length; i++) that._drawTick(minorTicks[i], ticksGroup); for (i = 0; i < customBoundaryTicks.length; i++) that._drawTick(customBoundaryTicks[i], ticksGroup); ticksGroup.append(group); that._drawDateMarkers(majorTicks, labelsGroup) }, _applyOptions: function(options) { var scaleOptions = options.scale, labelsAreaHeight; this.textOptions = { align: 'center', 'class': 'dx-range-selector-scale', font: scaleOptions.label.font, style: {'-webkit-user-select': 'none'} }; this.lineOptions = { strokeWidth: scaleOptions.tick.width, stroke: scaleOptions.tick.color, strokeOpacity: scaleOptions.tick.opacity }; this._setupDateUnitInterval(scaleOptions); this.visibleMarkers = scaleOptions.marker.visible === undefined ? true : scaleOptions.marker.visible; labelsAreaHeight = scaleOptions.label.visible ? scaleOptions.label.topIndent + scaleOptions.label.font.size : 0; this.scaleLabelsAreaHeight = options.scaleLabelsAreaHeight; this.markersAreaHeight = this.scaleLabelsAreaHeight - labelsAreaHeight; this.translator = options.translator }, _draw: function(group) { this._redraw(group, false) }, _update: function(group) { var callBase = this.callBase; if (this._markersTracker) this._markersTracker.off(rangeSelector.events.start, '**'); this.callBase = callBase; this.callBase(group) } }) })(jQuery, DevExpress); /*! Module viz-rangeselector, file rangeFactory.js */ (function($, DX, undefined) { var rangeSelector = DX.viz.rangeSelector, renderers = DX.viz.renderers; rangeSelector.rangeSelectorFactory = function() { return { createRangeContainer: function(rangeContainerOptions) { return new rangeSelector.RangeContainer(rangeContainerOptions) }, createSlidersContainer: function(options) { return new rangeSelector.SlidersContainer(options) }, createScale: function(options) { return new rangeSelector.Scale(options) }, createSliderMarker: function(options) { return new rangeSelector.SliderMarker(options) }, createRangeView: function(options) { return new rangeSelector.RangeView(options) }, createThemeManager: function(options) { return new rangeSelector.ThemeManager(options) }, createSlider: function(renderer, sliderIndex) { return new rangeSelector.Slider(renderer, sliderIndex) }, createSlidersEventsManager: function(renderer, slidersController, processSelectionChanged) { return new rangeSelector.SlidersEventsManager(renderer, slidersController, processSelectionChanged) }, createSlidersController: function(sliders) { return new rangeSelector.SlidersController(sliders) } } }() })(jQuery, DevExpress); /*! Module viz-rangeselector, file slidersContainer.js */ (function($, DX, undefined) { var rangeSelector = DX.viz.rangeSelector, utils = DX.utils; var msPointerEnabled = window.navigator.msPointerEnabled || window.navigator.pointerEnabled; var isNumber = DX.utils.isNumber; var isDate = DX.utils.isDate; var START_VALUE_INDEX = 0, END_VALUE_INDEX = 1; rangeSelector.SlidersContainer = rangeSelector.BaseVisualElement.inherit(function() { var prototypeObject = { getController: function() { return this._controller }, _drawAreaTracker: function(group) { var that = this, areaTracker, selectedAreaTracker; areaTracker = that._renderer.createRect(that._options.canvas.left, that._options.canvas.top, that._options.canvas.width, that._options.canvas.height, 0, { fill: 'grey', stroke: 'grey', opacity: 0.0001 }); areaTracker.append(group); selectedAreaTracker = that._renderer.createRect(that._options.canvas.left, that._options.canvas.top, that._options.canvas.width, that._options.canvas.height, 0, { fill: 'grey', stroke: 'grey', opacity: 0.0001, style: {cursor: 'pointer'} }); selectedAreaTracker.append(group); that._controller.setAreaTrackers(areaTracker, selectedAreaTracker) }, dispose: function() { this._eventsManager.dispose(); this._eventManager = null }, _processSelectionChanged: function(moving, blockSelectedRangeChanged) { var that = this, equalLastSelectedRange = function(selectedRange) { return selectedRange && that._lastSelectedRange.startValue === selectedRange.startValue && that._lastSelectedRange.endValue === selectedRange.endValue }, selectedRange = that.getSelectedRange(); if ((!moving || (that._options.behavior.callSelectedRangeChanged || '').toLowerCase() === "onmoving") && that._options.selectedRangeChanged && !equalLastSelectedRange(selectedRange)) { that._updateLastSelectedRange(selectedRange); if (typeof that._options.selectedRangeChanged === 'function') that._options.selectedRangeChanged.call(null, selectedRange, blockSelectedRangeChanged); if (!moving && !equalLastSelectedRange(selectedRange)) that.setSelectedRange(selectedRange) } }, _updateLastSelectedRange: function(selectedRange) { selectedRange = selectedRange || this._options.selectedRange; this._lastSelectedRange = { startValue: selectedRange.startValue, endValue: selectedRange.endValue } }, _createSlider: function(sliderIndex) { return rangeSelector.rangeSelectorFactory.createSlider(this._renderer, sliderIndex) }, _createSlidersController: function(sliders) { return rangeSelector.rangeSelectorFactory.createSlidersController(sliders) }, _createSlidersEventsManager: function(controller) { var that = this; return rangeSelector.rangeSelectorFactory.createSlidersEventsManager(that._renderer, controller, function(moving) { that._processSelectionChanged(moving) }) }, ctor: function(renderer) { var that = this, sliders; that.callBase(renderer); sliders = [that._createSlider(START_VALUE_INDEX), that._createSlider(END_VALUE_INDEX)]; that._controller = that._createSlidersController(sliders); that._eventsManager = that._createSlidersEventsManager(that._controller); that._lastSelectedRange = {} }, getSelectedRange: function() { return this._controller.getSelectedRange() }, truncateSelectedRange: function(value, scaleOptions) { var min = scaleOptions.startValue > scaleOptions.endValue ? scaleOptions.endValue : scaleOptions.startValue, max = scaleOptions.startValue > scaleOptions.endValue ? scaleOptions.startValue : scaleOptions.endValue; if (value < min) value = min; if (value > max) value = max; return value }, setSelectedRange: function(selectedRange) { var that = this, scale = that._options.scale, startValue, endValue, currentSelectedRange = that._options.selectedRange; if (selectedRange) { startValue = selectedRange.startValue; endValue = selectedRange.endValue } if (isNumber(scale.startValue) && isNumber(startValue) || isDate(scale.startValue) && isDate(startValue)) currentSelectedRange.startValue = startValue; if (isNumber(scale.endValue) && isNumber(endValue) || isDate(scale.endValue) && isDate(endValue)) currentSelectedRange.endValue = endValue; currentSelectedRange.startValue = that.truncateSelectedRange(currentSelectedRange.startValue, scale); currentSelectedRange.endValue = that.truncateSelectedRange(currentSelectedRange.endValue, scale); that._controller.applySelectedRange(currentSelectedRange); that._controller.applyPosition(); that._processSelectionChanged(false, selectedRange && selectedRange.blockSelectedRangeChanged) }, appendTrackers: function(group) { this._controller.appendTrackers(group) }, _applyOptions: function(options) { var that = this; that._controller.applyOptions({ translator: options.translator, canvas: options.canvas, sliderMarker: options.sliderMarker, sliderHandle: options.sliderHandle, shutter: options.shutter, scale: options.scale, behavior: options.behavior }); that._eventsManager.applyOptions({behavior: options.behavior}) }, _draw: function(group) { var that = this, rootElement; if (msPointerEnabled) { rootElement = that._renderer.getRoot(); rootElement && (rootElement.element.style.msTouchAction = "pinch-zoom") } that._controller.redraw(group); that._drawAreaTracker(group); that._eventsManager.initialize(); that._update() }, _update: function() { var that = this, isEmpty = that._options.isEmpty; that._eventsManager.setEnabled(!isEmpty); that._controller.applySelectedRange(isEmpty ? {} : that._options.selectedRange); that._controller.applyPosition(that.isDrawn()); that._updateLastSelectedRange(); that._controller.redraw() } }; return prototypeObject }()) })(jQuery, DevExpress); /*! Module viz-rangeselector, file slidersController.js */ (function($, DX, undefined) { var rangeSelector = DX.viz.rangeSelector, utils = DX.utils; var START_VALUE_INDEX = 0, END_VALUE_INDEX = 1; rangeSelector.SlidersController = DX.Class.inherit(function() { return { ctor: function(sliders) { this._sliders = sliders; sliders[START_VALUE_INDEX].setAnotherSlider(sliders[END_VALUE_INDEX]); sliders[END_VALUE_INDEX].setAnotherSlider(sliders[START_VALUE_INDEX]) }, setAreaTrackers: function(areaTracker, selectedAreaTracker) { this._areaTracker = areaTracker; this._selectedAreaTracker = selectedAreaTracker }, applyOptions: function(options) { var that = this, values = null; that._options = options; that.getSlider(START_VALUE_INDEX).applyOptions(options); that.getSlider(END_VALUE_INDEX).applyOptions(options); if (options.behavior.snapToTicks) { values = options.scale.ticksInfo.fullTicks; if (values.length > 1 && values[0] > values[values.length - 1]) values = values.reverse() } that.getSlider(START_VALUE_INDEX).setAvailableValues(values); that.getSlider(END_VALUE_INDEX).setAvailableValues(values) }, processDocking: function(sliderIndex) { var that = this; if (sliderIndex !== undefined) that.getSlider(sliderIndex).processDocking(); else { that.getSlider(START_VALUE_INDEX).processDocking(); that.getSlider(END_VALUE_INDEX).processDocking() } that.setTrackersCursorStyle('default'); that.applyAreaTrackersPosition() }, getSelectedRangeInterval: function() { var that = this, type = that._options.scale.type, base = that._options.scale.logarithmBase, startValue = that.getSlider(START_VALUE_INDEX).getValue(), endValue = that.getSlider(END_VALUE_INDEX).getValue(); if (type === 'logarithmic') return rangeSelector.utils.getInterval(utils.getLog(startValue, base), utils.getLog(endValue, base)); else return rangeSelector.utils.getInterval(startValue, endValue) }, moveSliders: function(postitionDelta, selectedRangeInterval) { var that = this; that.getSlider(START_VALUE_INDEX).setPosition(that.getSlider(START_VALUE_INDEX).getPosition() + postitionDelta, false, selectedRangeInterval); that.applyPosition(true) }, moveSlider: function(sliderIndex, fastSwap, position, offsetPosition, startOffsetPosition, startOffsetPositionChangedCallback) { var that = this, slider = that.getSlider(sliderIndex), anotherSlider = slider.getAnotherSlider(), anotherSliderIndex = anotherSlider.getIndex(), doSwap; if (slider.canSwap()) if (sliderIndex === START_VALUE_INDEX ? position > anotherSlider.getPosition() : position < anotherSlider.getPosition()) { doSwap = fastSwap; if (!fastSwap) if (Math.abs(offsetPosition) >= Math.abs(startOffsetPosition) && offsetPosition * startOffsetPosition < 0) { doSwap = true; position += 2 * startOffsetPosition; startOffsetPositionChangedCallback(-startOffsetPosition) } if (doSwap) { that.swapSliders(); anotherSlider.applyPosition(true) } } slider.setPosition(position, true); slider.applyPosition(true); that.applyAreaTrackersPosition(); that.setTrackersCursorStyle('w-resize') }, applySelectedAreaCenterPosition: function(pos) { var that = this, slidersContainerHalfWidth = (that.getSlider(END_VALUE_INDEX).getPosition() - that.getSlider(START_VALUE_INDEX).getPosition()) / 2, selectedRangeInterval = that.getSelectedRangeInterval(); that.getSlider(START_VALUE_INDEX).setPosition(pos - slidersContainerHalfWidth, false, selectedRangeInterval); that.applyPosition(); that.processDocking() }, processManualSelection: function(startPosition, endPosition, eventArgs) { var that = this, animateSliderIndex, movingSliderIndex, positionRange = [Math.min(startPosition, endPosition), Math.max(startPosition, endPosition)]; animateSliderIndex = startPosition < endPosition ? START_VALUE_INDEX : END_VALUE_INDEX; movingSliderIndex = startPosition < endPosition ? END_VALUE_INDEX : START_VALUE_INDEX; that.getSlider(movingSliderIndex).setPosition(positionRange[movingSliderIndex]); that.getSlider(animateSliderIndex).setPosition(positionRange[animateSliderIndex]); that.getSlider(movingSliderIndex).setPosition(positionRange[movingSliderIndex], true); that.getSlider(movingSliderIndex).startEventHandler(eventArgs); that.getSlider(animateSliderIndex).processDocking(); that.getSlider(movingSliderIndex).applyPosition(true) }, applySelectedRange: function(selectedRange) { var that = this, inverted = that._options.scale.inverted; utils.debug.assertParam(selectedRange, 'selectedRange not passed'); if (!inverted && selectedRange.startValue > selectedRange.endValue || inverted && selectedRange.startValue < selectedRange.endValue) { that.getSlider(START_VALUE_INDEX).setValue(selectedRange.endValue); that.getSlider(END_VALUE_INDEX).setValue(selectedRange.startValue) } else { that.getSlider(START_VALUE_INDEX).setValue(selectedRange.startValue); that.getSlider(END_VALUE_INDEX).setValue(selectedRange.endValue) } }, getSelectedRange: function() { var that = this; return { startValue: that.getSlider(START_VALUE_INDEX).getValue(), endValue: that.getSlider(END_VALUE_INDEX).getValue() } }, swapSliders: function() { var that = this; that._sliders.reverse(); that.getSlider(START_VALUE_INDEX).changeLocation(); that.getSlider(END_VALUE_INDEX).changeLocation() }, applyAreaTrackersPosition: function() { var that = this, selectedRange = that.getSelectedRange(), scaleOptions = that._options.scale, width = that.getSlider(END_VALUE_INDEX).getPosition() - that.getSlider(START_VALUE_INDEX).getPosition(), options = { x: that.getSlider(START_VALUE_INDEX).getPosition(), width: width < 0 ? 0 : width, y: that._options.canvas.top, height: that._options.canvas.height, style: {cursor: scaleOptions.endValue - scaleOptions.startValue === selectedRange.endValue - selectedRange.startValue ? 'default' : 'pointer'} }; that._selectedAreaTracker.applySettings(options); that._areaTracker.applySettings({ x: that._options.canvas.left, width: that._options.canvas.width, y: that._options.canvas.top, height: that._options.canvas.height }) }, applyPosition: function(disableAnimation) { var that = this; that.getSlider(START_VALUE_INDEX).applyPosition(disableAnimation); that.getSlider(END_VALUE_INDEX).applyPosition(disableAnimation); that.applyAreaTrackersPosition() }, redraw: function(group) { var that = this; that.getSlider(START_VALUE_INDEX).redraw(group); that.getSlider(END_VALUE_INDEX).redraw(group) }, appendTrackers: function(group) { var that = this; if (that._areaTracker && that._selectedAreaTracker) { that._areaTracker.append(group); that._selectedAreaTracker.append(group) } that.getSlider(START_VALUE_INDEX).appendTrackers(group); that.getSlider(END_VALUE_INDEX).appendTrackers(group) }, getSlider: function(sliderIndex) { return this._sliders[sliderIndex] }, getAreaTracker: function() { return this._areaTracker }, getSelectedAreaTracker: function() { return this._selectedAreaTracker }, setTrackersCursorStyle: function(style) { var that = this; that._selectedAreaTracker.applySettings({style: {cursor: style}}); that._areaTracker.applySettings({style: {cursor: style}}) } } }()) })(jQuery, DevExpress); /*! Module viz-rangeselector, file slidersEventsManager.js */ (function($, DX, undefined) { var rangeSelector = DX.viz.rangeSelector, utils = DX.utils, MIN_MANUAL_SELECTING_WIDTH = 10, START_VALUE_INDEX = 0, END_VALUE_INDEX = 1, addNamespace = DX.ui.events.addNamespace, setEvents = function() { var win = window; win = DX.viz.rangeSelector.mockWindow || window; var touchSupport = "ontouchstart" in win, msPointerEnabled = win.navigator.msPointerEnabled, pointerEnabled = win.navigator.pointerEnabled; rangeSelector.events = { start: pointerEnabled ? "pointerdown" : msPointerEnabled ? "MSPointerDown" : touchSupport ? "touchstart mousedown" : "mousedown", move: pointerEnabled ? "pointermove" : msPointerEnabled ? "MSPointerMove" : touchSupport ? "touchmove mousemove" : "mousemove", end: pointerEnabled ? "pointerup pointercancel" : msPointerEnabled ? "MSPointerUp MSPointerCancel" : touchSupport ? "touchend mouseup" : "mouseup" } }, _SlidersEventManager, getEventPageX = rangeSelector.utils.getEventPageX, rangeSelectorCount = 0; setEvents(); var isLeftButtonPressed = function(event) { var e = event || window.event, originalEvent = e.originalEvent, touches = e.touches, pointerType = originalEvent ? originalEvent.pointerType : false, eventTouches = originalEvent ? originalEvent.touches : false, isIE8LeftClick = e.which === undefined && e.button === 1, isMSPointerLeftClick = originalEvent && pointerType !== undefined && (pointerType === (originalEvent.MSPOINTER_TYPE_TOUCH || 'touch') || pointerType === (originalEvent.MSPOINTER_TYPE_MOUSE || 'mouse') && originalEvent.buttons === 1), isLeftClick = isIE8LeftClick || e.which === 1, isTouches = touches && touches.length > 0 || eventTouches && eventTouches.length > 0; return isLeftClick || isMSPointerLeftClick || isTouches }; var isMultiTouches = function(event) { var originalEvent = event.originalEvent, touches = event.touches, eventTouches = originalEvent ? originalEvent.touches : false; return touches && touches.length > 1 || eventTouches && eventTouches.length > 1 || null }; var isTouchEventArgs = function(e) { return e && e.type && e.type.indexOf('touch') === 0 }; _SlidersEventManager = rangeSelector.SlidersEventsManager = function(renderer, slidersController, processSelectionChanged) { var that = this, uniqueNS = that._uniqueNS = 'dx-range-selector_' + rangeSelectorCount++, rangeSelectorEvents = rangeSelector.events; that._renderer = renderer; that._slidersController = slidersController; that._processSelectionChanged = processSelectionChanged; that._enabled = true; that._eventsNames = { start: addNamespace(rangeSelectorEvents.start, uniqueNS), move: addNamespace(rangeSelectorEvents.move, uniqueNS), end: addNamespace(rangeSelectorEvents.end, uniqueNS) } }; _SlidersEventManager.prototype = { constructor: _SlidersEventManager, _getRootOffsetLeft: function() { return rangeSelector.utils.getRootOffsetLeft(this._renderer) }, _initializeSliderEvents: function(sliderIndex) { var that = this, renderer = that._renderer, isTouchEvent, slidersController = that._slidersController, processSelectionChanged = that._processSelectionChanged, slider = slidersController.getSlider(sliderIndex), anotherSlider = slider.getAnotherSlider(), fastSwap, startOffsetPosition, splitterMoving, sliderEndHandler = function(e) { if (splitterMoving) { splitterMoving = false; slidersController.processDocking(); processSelectionChanged(false) } }, sliderMoveHandler = function(e) { var doSwap, pageX, offsetPosition, svgOffsetLeft = that._getRootOffsetLeft(), position, sliderIndex = slider.getIndex(); if (isTouchEvent !== isTouchEventArgs(e)) return; if (!isLeftButtonPressed(e, true) && splitterMoving) { splitterMoving = false; slidersController.processDocking(); processSelectionChanged(false) } else if (splitterMoving) { if (!isMultiTouches(e)) { this.preventedDefault = true; e.preventDefault() } pageX = getEventPageX(e); position = pageX - startOffsetPosition - svgOffsetLeft; offsetPosition = pageX - slider.getPosition() - svgOffsetLeft; slidersController.moveSlider(sliderIndex, fastSwap, position, offsetPosition, startOffsetPosition, function(newStartOffsetPosition) { startOffsetPosition = newStartOffsetPosition }); processSelectionChanged(true) } }, eventsNames = that._eventsNames; slider.startEventHandler = function(e) { if (!that._enabled || !isLeftButtonPressed(e) || splitterMoving) return; fastSwap = this === slider.getSliderTracker().element; splitterMoving = true; isTouchEvent = isTouchEventArgs(e); startOffsetPosition = getEventPageX(e) - slider.getPosition() - that._getRootOffsetLeft(); if (!isMultiTouches(e)) { this.preventedDefault = true; e.stopPropagation(); e.preventDefault() } }; slider.on(eventsNames.start, slider.startEventHandler); $(document).on(eventsNames.end, sliderEndHandler).on(eventsNames.move, sliderMoveHandler); slider.__moveEventHandler = sliderMoveHandler }, _initializeAreaEvents: function() { var that = this, renderer = that._renderer, isTouchEvent, slidersController = that._slidersController, processSelectionChanged = that._processSelectionChanged, areaTracker = slidersController.getAreaTracker(), unselectedAreaProcessing = false, splitterMoving = false, startPageX, areaEndHandler = function(e) { var pageX; if (unselectedAreaProcessing) { pageX = getEventPageX(e); if (that._options.behavior.moveSelectedRangeByClick && Math.abs(startPageX - pageX) < MIN_MANUAL_SELECTING_WIDTH) slidersController.applySelectedAreaCenterPosition(pageX - that._getRootOffsetLeft()); unselectedAreaProcessing = false; processSelectionChanged(false) } }, areaMoveHandler = function(e) { var pageX, startPosition, endPosition, svgOffsetLeft = that._getRootOffsetLeft(); if (isTouchEvent !== isTouchEventArgs(e)) return; if (unselectedAreaProcessing && !isLeftButtonPressed(e)) { unselectedAreaProcessing = false; processSelectionChanged(false) } if (unselectedAreaProcessing) { pageX = getEventPageX(e); if (that._options.behavior.manualRangeSelectionEnabled && Math.abs(startPageX - pageX) >= MIN_MANUAL_SELECTING_WIDTH) { startPosition = startPageX - svgOffsetLeft; endPosition = pageX - svgOffsetLeft; slidersController.processManualSelection(startPosition, endPosition, e); unselectedAreaProcessing = false; processSelectionChanged(true) } } }, eventsNames = that._eventsNames; areaTracker.on(eventsNames.start, function(e) { if (!that._enabled || !isLeftButtonPressed(e) || unselectedAreaProcessing) return; unselectedAreaProcessing = true; isTouchEvent = isTouchEventArgs(e); startPageX = getEventPageX(e) }); $(document).on(eventsNames.end, areaEndHandler).on(eventsNames.move, areaMoveHandler); that.__areaMoveEventHandler = areaMoveHandler }, _initializeSelectedAreaEvents: function() { var that = this, renderer = that._renderer, isTouchEvent, slidersController = that._slidersController, processSelectionChanged = that._processSelectionChanged, selectedAreaTracker = slidersController.getSelectedAreaTracker(), selectedAreaMoving = false, offsetStartPosition, selectedRangeInterval, selectedAreaEndHandler = function(e) { if (selectedAreaMoving) { selectedAreaMoving = false; slidersController.processDocking(); processSelectionChanged(false) } }, selectedAreaMoveHandler = function(e) { var positionDelta, pageX; if (isTouchEvent !== isTouchEventArgs(e)) return; if (selectedAreaMoving && !isLeftButtonPressed(e)) { selectedAreaMoving = false; slidersController.processDocking(); processSelectionChanged(false) } if (selectedAreaMoving) { if (!isMultiTouches(e)) { this.preventedDefault = true; e.preventDefault() } pageX = getEventPageX(e); positionDelta = pageX - slidersController.getSlider(START_VALUE_INDEX).getPosition() - offsetStartPosition; slidersController.moveSliders(positionDelta, selectedRangeInterval); processSelectionChanged(true) } }, eventsNames = that._eventsNames; selectedAreaTracker.on(eventsNames.start, function(e) { if (!that._enabled || !isLeftButtonPressed(e) || selectedAreaMoving) return; selectedAreaMoving = true; isTouchEvent = isTouchEventArgs(e); offsetStartPosition = getEventPageX(e) - slidersController.getSlider(START_VALUE_INDEX).getPosition(); selectedRangeInterval = slidersController.getSelectedRangeInterval(); if (!isMultiTouches(e)) { this.preventedDefault = true; e.stopPropagation(); e.preventDefault() } }); $(document).on(eventsNames.end, selectedAreaEndHandler).on(eventsNames.move, selectedAreaMoveHandler); that.__selectedAreaMoveEventHandler = selectedAreaMoveHandler }, applyOptions: function(options) { this._options = options }, dispose: function() { $(document).off('.' + this._uniqueNS) }, initialize: function() { var that = this; if (!that._renderer.isInitialized()) return; that._initializeSelectedAreaEvents(that); that._initializeAreaEvents(); that._initializeSliderEvents(START_VALUE_INDEX); that._initializeSliderEvents(END_VALUE_INDEX) }, setEnabled: function(enabled) { this._enabled = enabled } }; rangeSelector.__setEvents = setEvents })(jQuery, DevExpress); /*! Module viz-rangeselector, file slider.js */ (function($, DX, undefined) { var rangeSelector = DX.viz.rangeSelector, utils = DX.utils; var touchSupport = "ontouchstart" in window; var msPointerEnabled = window.navigator.msPointerEnabled || window.navigator.pointerEnabled; var animationOptions = {duration: 250}; var SPLITTER_WIDTH = 8, TOUCH_SPLITTER_WIDTH = 20, START_VALUE_INDEX = 0, END_VALUE_INDEX = 1; rangeSelector.Slider = rangeSelector.BaseVisualElement.inherit(function() { return { getText: function() { if (this._marker) return this._marker.getText() }, getAvailableValues: function() { return this._values }, getShutter: function() { return this._shutter }, getMarker: function() { return this._marker }, _createSlider: function() { var that = this, sliderHandle, sliderGroup, sliderHandleOptions = that._options.sliderHandle; sliderGroup = that._renderer.createGroup({'class': 'slider'}); sliderGroup.applySettings({ translateX: that._options.canvas.left, translateY: that._options.canvas.top }); sliderHandle = that._renderer.createLine(0, 0, 0, that._options.canvas.height, { 'class': 'dx-range-selector-slider', strokeWidth: sliderHandleOptions.width, stroke: sliderHandleOptions.color, strokeOpacity: sliderHandleOptions.opacity }); sliderHandle.append(sliderGroup); sliderGroup.setValid = function(correct) { sliderHandle.applySettings({stroke: correct ? that._options.sliderHandle.color : that._options.sliderMarker.invalidRangeColor}) }; sliderGroup.updateHeight = function() { sliderHandle.applySettings({points: [0, 0, 0, that._options.canvas.height]}) }; sliderGroup.applyOptions = function(options) { sliderHandle.applySettings(options) }; sliderGroup.__line = sliderHandle; return sliderGroup }, _createSliderTracker: function() { var that = this, sliderHandleWidth = that._options.sliderHandle.width, splitterWidth = SPLITTER_WIDTH < sliderHandleWidth ? sliderHandleWidth : SPLITTER_WIDTH, sliderWidth = touchSupport || msPointerEnabled ? TOUCH_SPLITTER_WIDTH : splitterWidth, sliderTracker, sliderTrackerGroup; sliderTracker = that._renderer.createRect(-sliderWidth / 2, 0, sliderWidth, that._options.canvas.height, 0, { fill: 'grey', stroke: 'grey', opacity: 0.0001, style: {cursor: 'w-resize'} }); sliderTrackerGroup = that._renderer.createGroup({'class': 'sliderTracker'}); sliderTrackerGroup.applySettings({ translateX: 0, translateY: that._options.canvas.top }); sliderTracker.append(sliderTrackerGroup); sliderTrackerGroup.updateHeight = function() { sliderTracker.applySettings({height: that._options.canvas.height}) }; sliderTrackerGroup.__rect = sliderTracker; return sliderTrackerGroup }, _drawSliderTracker: function(group) { var that = this, sliderTracker = that._createSliderTracker(); if (sliderTracker) { sliderTracker.append(group); that._sliderTracker = sliderTracker } }, _createSliderMarker: function(options) { return rangeSelector.rangeSelectorFactory.createSliderMarker(options) }, _setPosition: function(position, correctByMinMaxRange) { var that = this, correctedPosition = that._correctPosition(position), value = that._options.translator.untranslate(correctedPosition); that.setValue(value, correctByMinMaxRange, false); that._position = correctedPosition }, _setPositionForBothSliders: function(startPosition, interval) { var that = this, anotherSlider, startValue, endValue, endPosition, type = that._options.scale.type, base = that._options.scale.logarithmBase, inverted = that._options.scale.inverted; var getNextValue = function(value, isNegative) { var lgPower; if (type === 'logarithmic') { lgPower = utils.addInterval(utils.adjustValue(utils.getLog(value, base)), interval, isNegative); return utils.raiseTo(lgPower, base) } else return utils.addInterval(value, interval, isNegative) }; anotherSlider = that.getAnotherSlider(); startPosition = that._correctBounds(startPosition); startValue = that._options.translator.untranslate(startPosition); endValue = getNextValue(startValue); if (!inverted && endValue > that._options.scale.endValue || inverted && endValue < that._options.scale.endValue) { endValue = that._options.scale.endValue; endPosition = that._options.canvas.left + that._options.canvas.width; startValue = getNextValue(endValue, true); startPosition = that._options.translator.translate(startValue) } else endPosition = that._options.translator.translate(endValue); if (that._values) if (!inverted ? startValue < that._values[0] : startValue > that._values[that._values.length - 1]) { startValue = that._correctBusinessValueByAvailableValues(startValue, false); endValue = getNextValue(startValue) } else { endValue = that._correctBusinessValueByAvailableValues(endValue, false); startValue = getNextValue(endValue, true) } anotherSlider.setValue(endValue, undefined, false); that.setValue(startValue, undefined, false); that._position = startPosition; anotherSlider._position = endPosition }, _correctPosition: function(position) { var that = this, correctedPosition = that._correctInversion(position); correctedPosition = that._correctBounds(correctedPosition); return correctedPosition }, _correctInversion: function(position) { var that = this, correctedPosition = position, anotherSliderPosition = that.getAnotherSlider().getPosition(), slidersInverted = that.getIndex() === START_VALUE_INDEX ? position > anotherSliderPosition : position < anotherSliderPosition; if (slidersInverted) correctedPosition = anotherSliderPosition; return correctedPosition }, _correctBounds: function(position) { var that = this, correctedPosition = position, canvas = that._options.canvas; if (position < canvas.left) correctedPosition = canvas.left; if (position > canvas.left + canvas.width) correctedPosition = canvas.left + canvas.width; return correctedPosition }, _correctBusinessValue: function(businessValue, correctByMinMaxRange, skipCorrection) { var that = this, result = that._correctBusinessValueByAvailableValues(businessValue, skipCorrection); if (correctByMinMaxRange) result = that._correctBusinessValueByMinMaxRangeFromAnotherSlider(result); result = that._correctBusinessValueByMinRangeFromStartEndValues(result); return result }, _correctBusinessValueByAvailableValues: function(businessValue, skipCorrection) { var values = this._values; if (!skipCorrection && values) return rangeSelector.utils.findNearValue(values, businessValue); return businessValue }, _correctBusinessValueByMinMaxRangeFromAnotherSlider: function(businessValue) { var that = this, result = businessValue, scale = that._options.scale, values = that._values, sliderIndex = that.getIndex(), anotherBusinessValue = that.getAnotherSlider().getValue(), isValid = true, minValue, maxValue; if (!scale.inverted && sliderIndex === START_VALUE_INDEX || scale.inverted && sliderIndex === END_VALUE_INDEX) { if (scale.maxRange) minValue = that._addInterval(anotherBusinessValue, scale.maxRange, true); if (scale.minRange) maxValue = that._addInterval(anotherBusinessValue, scale.minRange, true) } else { if (scale.maxRange) maxValue = that._addInterval(anotherBusinessValue, scale.maxRange); if (scale.minRange) minValue = that._addInterval(anotherBusinessValue, scale.minRange) } if (maxValue !== undefined && result > maxValue) { result = values ? rangeSelector.utils.findLessOrEqualValue(values, maxValue) : maxValue; isValid = false } else if (minValue !== undefined && result < minValue) { result = values ? rangeSelector.utils.findGreaterOrEqualValue(values, minValue) : minValue; isValid = false } that._setValid(isValid); return result }, _addInterval: function(value, interval, isNegative) { var result, type = this._options.scale.type, base = type === "logarithmic" && this._options.scale.logarithmBase; if (base) { var power = utils.addInterval(utils.getLog(value, base), interval, isNegative); result = Math.pow(base, power) } else result = utils.addInterval(value, interval, isNegative); return result }, _correctBusinessValueByMinRangeFromStartEndValues: function(businessValue) { var that = this, values = that._values, startValue, endValue, isValid = true, scale = that._options.scale, result = businessValue; if (scale.minRange) if (that.getIndex() === END_VALUE_INDEX) { startValue = that._addInterval(scale.startValue, scale.minRange, scale.inverted); if (!scale.inverted && result < startValue || scale.inverted && result > startValue) result = startValue } else if (that.getIndex() === START_VALUE_INDEX) { endValue = that._addInterval(scale.endValue, scale.minRange, !scale.inverted); if (!scale.inverted && result > endValue || scale.inverted && result < endValue) result = endValue } return result }, _applySliderPosition: function(position, disableAnimation) { var that = this, isAnimation = that._options.behavior.animationEnabled && !disableAnimation, top = that._options.canvas.top, slider = that._slider; if (isAnimation || slider.inAnimation) { slider.inAnimation = true; slider.animate({translate: { x: position, y: top }}, isAnimation ? animationOptions : {duration: 0}, function() { slider.inAnimation = false }); that._sliderTracker.animate({translate: { x: position, y: top }}, isAnimation ? animationOptions : {duration: 0}) } else { that._slider.applySettings({ translateX: position, translateY: top }); that._sliderTracker.applySettings({ translateX: position, translateY: top }) } that._sliderTracker.updateHeight(); that._slider.updateHeight() }, _applyShutterPosition: function(position, disableAnimation) { var that = this, shutterSettings, shutter = that._shutter, isAnimation = that._options.behavior.animationEnabled && !disableAnimation, sliderIndex = that.getIndex(); if (sliderIndex == START_VALUE_INDEX) shutterSettings = { x: that._options.canvas.left, y: that._options.canvas.top, width: position - that._options.canvas.left, height: that._options.canvas.height }; else if (sliderIndex == END_VALUE_INDEX) shutterSettings = { x: position + 1, y: that._options.canvas.top, width: that._options.canvas.left + that._options.canvas.width - position, height: that._options.canvas.height }; if (shutterSettings) if (isAnimation || shutter.inAnimation) { shutter.inAnimation = true; shutter.animate(shutterSettings, isAnimation ? animationOptions : {duration: 0}, function() { shutter.inAnimation = false }) } else shutter.applySettings(shutterSettings) }, _setValid: function(isValid) { var that = this; if (that._marker) that._marker.setValid(isValid); that._slider.setValid(isValid) }, _setText: function(text) { var that = this; if (that._marker) that._marker.setText(text) }, ctor: function(renderer, index) { var that = this; that.callBase(renderer); that._index = index }, getIndex: function() { return this._index }, setAvailableValues: function(values) { this._values = values }, setAnotherSlider: function(slider) { this._anotherSlider = slider }, getAnotherSlider: function(slider) { return this._anotherSlider }, appendTrackers: function(group) { var that = this; if (that._sliderTracker) that._sliderTracker.append(group) }, getSliderTracker: function() { return this._sliderTracker }, changeLocation: function() { var that = this; if (that._marker) that._marker.changeLocation(); that._index = this._index === START_VALUE_INDEX ? END_VALUE_INDEX : START_VALUE_INDEX; that._lastPosition = null }, setPosition: function(position, correctByMinMaxRange, selectedRangeInterval) { var that = this, slider; if (selectedRangeInterval !== undefined) { slider = that.getIndex() === START_VALUE_INDEX ? that : that.getAnotherSlider(); slider._setPositionForBothSliders(position, selectedRangeInterval) } else that._setPosition(position, correctByMinMaxRange) }, getPosition: function() { return this._position }, _applyOptions: function(options) { this._lastPosition = null }, setValue: function(value, correctByMinMaxRange, skipCorrection) { var that = this; if (value === undefined) { that._value = undefined; that._valuePosition = that._position = that.getIndex() === START_VALUE_INDEX ? that._options.canvas.left : that._options.canvas.left + that._options.canvas.width; that._setText(rangeSelector.consts.emptySliderMarkerText) } else { that._value = that._correctBusinessValue(value, correctByMinMaxRange, utils.isDefined(skipCorrection) ? !!skipCorrection : true); that._valuePosition = that._position = that._options.translator.translate(that._value); that._setText(rangeSelector.formatValue(that._value, that._options.sliderMarker)) } }, getValue: function() { return this._value }, canSwap: function() { var that = this, scale = that._options.scale, startValue, endValue, anotherSliderValue; if (that._options.behavior.allowSlidersSwap) { if (scale.minRange) { anotherSliderValue = that.getAnotherSlider().getValue(); if (that.getIndex() === START_VALUE_INDEX) { endValue = utils.addInterval(scale.endValue, scale.minRange, !scale.inverted); if (!scale.inverted && anotherSliderValue > endValue || scale.inverted && anotherSliderValue < endValue) return false } else { startValue = utils.addInterval(scale.startValue, scale.minRange, scale.inverted); if (!scale.inverted && anotherSliderValue < startValue || scale.inverted && anotherSliderValue > startValue) return false } } return true } return false }, processDocking: function() { var that = this; that._position = that._valuePosition; that.applyPosition(false); that._setValid(true) }, applyPosition: function(disableAnimation) { var that = this, position = that.getPosition(); if (that._lastPosition !== position) { that._applySliderPosition(position, disableAnimation); that._applyShutterPosition(position, disableAnimation); that._lastPosition = position } }, on: function(event, handler) { var that = this; that._sliderTracker.on(event, handler); if (that._marker) that._marker.getTracker().on(event, handler) }, _update: function() { var that = this; that._marker && that._marker.applyOptions(that._options.sliderMarker); that._shutter && that._shutter.applySettings({ fill: that._options.shutter.color, fillOpacity: that._options.shutter.opacity }); that._slider && that._slider.applyOptions({ strokeWidth: that._options.sliderHandle.width, stroke: that._options.sliderHandle.color, strokeOpacity: that._options.sliderHandle.opacity }) }, _draw: function(group) { var that = this, slider, marker, sliderAreaGroup, shutter, startPos, startWidth, index = that.getIndex(); sliderAreaGroup = that._renderer.createGroup({'class': 'sliderArea'}); sliderAreaGroup.append(group); if (index === START_VALUE_INDEX) shutter = that._renderer.createRect(that._options.canvas.left, that._options.canvas.top, 0, that._options.canvas.height, 0); else if (index === END_VALUE_INDEX) shutter = that._renderer.createRect(that._options.canvas.left, that._options.canvas.top, that._options.canvas.width, that._options.canvas.height, 0); if (shutter) { shutter.append(sliderAreaGroup); slider = that._createSlider(); if (slider) slider.append(sliderAreaGroup); if (that._options.sliderMarker.visible) { marker = that._createSliderMarker({ renderer: that._renderer, isLeftPointer: index === END_VALUE_INDEX, sliderMarkerOptions: that._options.sliderMarker }); marker.draw(slider) } that._shutter = shutter; that._slider = slider; that._marker = marker } that._drawSliderTracker(group) } } }()) })(jQuery, DevExpress); /*! Module viz-rangeselector, file sliderMarker.js */ (function($, DX, undefined) { var rangeSelector = DX.viz.rangeSelector, _SliderMarker; _SliderMarker = rangeSelector.SliderMarker = function(options) { var that = this; that._renderer = options.renderer; that._text = options.text; that._isLeftPointer = options.isLeftPointer; that._options = options.sliderMarkerOptions; that._isValid = true; initializeAreaPoints(that, { width: 10, height: 10 }) }; var applyOptions = function(options) { this._options = options; this.update() }; var getRectSize = function(that, textSize) { return { width: Math.round(2 * that._options.padding + textSize.width), height: Math.round(2 * that._options.padding + textSize.height * rangeSelector.consts.fontHeightRatio) } }; var initializeAreaPoints = function(that, textSize) { var rectSize = getRectSize(that, textSize); that._points = []; if (that._isLeftPointer) { that._points.push({ x: 0, y: 0 }); that._points.push({ x: rectSize.width, y: 0 }); that._points.push({ x: rectSize.width, y: rectSize.height }); that._points.push({ x: that._options.pointerSize, y: rectSize.height }); that._points.push({ x: 0, y: rectSize.height + that._options.pointerSize }) } else { that._points.push({ x: 0, y: 0 }); that._points.push({ x: rectSize.width, y: 0 }); that._points.push({ x: rectSize.width, y: rectSize.height + that._options.pointerSize }); that._points.push({ x: rectSize.width - that._options.pointerSize, y: rectSize.height }); that._points.push({ x: 0, y: rectSize.height }) } }; var getPointerPosition = function(that, textSize) { var rectSize = getRectSize(that, textSize); if (that._isLeftPointer) return { x: 0, y: rectSize.height + that._options.pointerSize }; else return { x: rectSize.width - 1, y: rectSize.height + that._options.pointerSize } }; var draw = function(group) { var that = this; var padding = that._options.padding; that._sliderMarkerGroup = that._renderer.createGroup({'class': 'sliderMarker'}); that._sliderMarkerGroup.append(group); that._area = that._renderer.createArea(that.points, {fill: that._options.color}); that._area.append(that._sliderMarkerGroup); that._label = that._renderer.createText(that._text, padding, padding, { font: that._options.font, align: 'left', style: {'-webkit-user-select': 'none'} }); that._label.append(that._sliderMarkerGroup); that._tracker = that._renderer.createRect(0, 0, 2 * padding, 2 * padding + that._options.pointerSize, 0, { fill: 'grey', stroke: 'grey', opacity: 0.0001, style: {cursor: 'pointer'} }); that._tracker.append(that._sliderMarkerGroup); that._drawn = true; that.update() }; var getTextSize = function(that) { var textSize = that._label.getBBox(); if (!that._textHeight && isFinite(textSize.height)) that._textHeight = textSize.height; return { width: textSize.width, height: that._textHeight } }; var update = function(stop) { var that = this, textSize, rectSize, pointerPosition; that._interval && clearInterval(that._interval); delete that._interval; if (!that._drawn) return; that._label.updateText(that._text); textSize = getTextSize(that); if (!stop) { that._textSize = that._textSize || textSize; that._textSize = textSize.width > that._textSize.width || textSize.height > that._textSize.height ? textSize : that._textSize; textSize = that._textSize; that._interval = setInterval(function() { update.call(that, [true]) }, 75) } else { delete that._textSize; that._textSize = textSize } rectSize = getRectSize(that, textSize); pointerPosition = getPointerPosition(that, textSize); that._sliderMarkerGroup.applySettings({ translateX: -pointerPosition.x, translateY: -pointerPosition.y }); initializeAreaPoints(that, textSize); that._area.applySettings({ points: that._points, fill: that._isValid ? that._options.color : that._options.invalidRangeColor }); that._tracker.applySettings({ width: rectSize.width, height: rectSize.height + that._options.pointerSize }); that._label.applySettings({ x: that._options.padding, y: rectSize.height - that._options.padding }) }; var getText = function() { var that = this; return that._text }; var setText = function(value) { var that = this; if (that._text !== value) { that._text = value; that.update() } }; var setValid = function(isValid) { var that = this; that._isValid = isValid; that.update() }; var changeLocation = function() { var that = this; that._isLeftPointer = !that._isLeftPointer; that.update() }; var getTracker = function() { var that = this; return that._tracker }; _SliderMarker.prototype = { constructor: _SliderMarker, draw: draw, update: update, getText: getText, setText: setText, changeLocation: changeLocation, applyOptions: applyOptions, getTracker: getTracker, setValid: setValid } })(jQuery, DevExpress); /*! Module viz-rangeselector, file rangeView.js */ (function($, DX, undefined) { var rangeSelector = DX.viz.rangeSelector; rangeSelector.RangeView = rangeSelector.BaseVisualElement.inherit(function() { return {_draw: function(group) { var that = this, viewRect, viewImage, backgroundColor, series, i, showChart, canvas, options = that._options, seriesOptions, isEmpty = options.isEmpty; showChart = options.seriesDataSource && options.seriesDataSource.isShowChart() && !isEmpty; canvas = options.canvas; if (showChart) backgroundColor = options.seriesDataSource.getBackgroundColor(); else if (!isEmpty && options.background.visible) backgroundColor = options.background.color; if (options.background.visible && backgroundColor) { viewRect = that._renderer.createRect(canvas.left, canvas.top, canvas.width + 1, canvas.height, 0, { fill: backgroundColor, 'class': 'dx-range-selector-background' }); viewRect.append(group) } if (options.background.visible && options.background.image && options.background.image.url) { viewImage = that._renderer.createImage(canvas.left, canvas.top, canvas.width + 1, canvas.height, options.background.image.url, {location: options.background.image.location}); viewImage.append(group) } if (showChart) { series = options.seriesDataSource.getSeries(); options.seriesDataSource.adjustSeriesDimensions(options.translators, options.chart.useAggregation); for (i = 0; i < series.length; i++) { seriesOptions = series[i].getOptions(); seriesOptions.seriesGroup = group; seriesOptions.labelsGroup = group; series[i].draw(options.translators, options.behavior && options.behavior.animationEnabled && that._renderer.animationEnabled()) } } }} }()) })(jQuery, DevExpress); /*! Module viz-rangeselector, file seriesDataSource.js */ (function($, DX, undefined) { var rangeSelector = DX.viz.rangeSelector, charts = DX.viz.charts, core = DX.viz.core, coreFactory = core.CoreFactory, utils = DX.utils; rangeSelector.SeriesDataSource = DX.Class.inherit(function() { var createThemeManager = function(chartOptions) { return charts.factory.createThemeManager(chartOptions, 'rangeSelector.chart') }; var isArrayOfSimpleTypes = function(data) { return $.isArray(data) && data.length > 0 && (utils.isNumber(data[0]) || utils.isDate(data[0])) }; var convertToArrayOfObjects = function(data) { return $.map(data, function(item, i) { return { arg: item, val: i } }) }; var calculateSeries = function(that, options, templatedSeries) { var series = [], particularSeriesOptions, seriesTheme, data, parsedData, chartThemeManager = that.themeManager, hasSeriesTemplate = !!chartThemeManager.getOptions('seriesTemplate'), allSeriesOptions = hasSeriesTemplate ? templatedSeries : options.chart.series, seriesValueType = options.chart.valueAxis && options.chart.valueAxis.valueType, dataSourceField, i; that.teamplateData = []; if (options.dataSource && !allSeriesOptions) { if (isArrayOfSimpleTypes(options.dataSource)) options.dataSource = convertToArrayOfObjects(options.dataSource); dataSourceField = options.dataSourceField || 'arg'; allSeriesOptions = { argumentField: dataSourceField, valueField: dataSourceField }; that._hideChart = true } allSeriesOptions = $.isArray(allSeriesOptions) ? allSeriesOptions : allSeriesOptions ? [allSeriesOptions] : []; that._backgroundColor = options.backgroundColor !== undefined ? options.backgroundColor : chartThemeManager.getOptions("backgroundColor"); for (i = 0; i < allSeriesOptions.length; i++) { particularSeriesOptions = $.extend(true, { argumentType: options.valueType, argumentAxisType: options.axisType, valueType: dataSourceField ? options.valueType : seriesValueType, incidentOccured: options.incidentOccured }, allSeriesOptions[i]); particularSeriesOptions.rotated = false; data = particularSeriesOptions.data || options.dataSource; seriesTheme = chartThemeManager.getOptions("series", particularSeriesOptions); seriesTheme.argumentField = seriesTheme.argumentField || options.dataSourceField; if (data && data.length > 0) { var newSeries = coreFactory.createSeries(options.renderer, seriesTheme); series.push(newSeries) } if (hasSeriesTemplate) { $.each(data, function(_, data) { $.each(newSeries.getTeamplatedFields(), function(_, field) { data[field.teamplateField] = data[field.originalField] }); that.teamplateData.push(data) }); newSeries.updateTeamplateFieldNames() } } data = hasSeriesTemplate ? that.teamplateData : data; that._dataValidator = charts.factory.createDataValidator(data, [series], options.incidentOccured, chartThemeManager.getOptions("dataPrepareSettings")); parsedData = that._dataValidator.validate(); for (i = 0; i < series.length; i++) { var particularSeries = series[i]; particularSeries.updateData(parsedData) } return series }; var processSeriesFamilies = function(series, equalBarWidth, minBubbleSize, maxBubbleSize) { var families = [], types = []; $.each(series, function(i, item) { if ($.inArray(item.type, types) === -1) types.push(item.type) }); $.each(types, function(_, type) { var family = new coreFactory.createSeriesFamily({ type: type, equalBarWidth: equalBarWidth, minBubbleSize: minBubbleSize, maxBubbleSize: maxBubbleSize }); family.add(series); family.adjustSeriesValues(); families.push(family) }); return families }; var prototypeObject = { ctor: function(options) { var that = this, templatedSeries, seriesTemplate, themeManager = that.themeManager = createThemeManager(options.chart), topIndent = themeManager.getOptions('topIndent'), bottomIndent = themeManager.getOptions('bottomIndent'); that._indent = { top: topIndent >= 0 && topIndent < 1 ? topIndent : 0, bottom: bottomIndent >= 0 && bottomIndent < 1 ? bottomIndent : 0 }; that._valueAxis = themeManager.getOptions('valueAxisRangeSelector') || {}; that._hideChart = false; seriesTemplate = themeManager.getOptions('seriesTemplate'); if (options.dataSource && seriesTemplate) templatedSeries = utils.processSeriesTemplate(seriesTemplate, options.dataSource); that._series = calculateSeries(that, options, templatedSeries); that._seriesFamilies = processSeriesFamilies(that._series, themeManager.getOptions('equalBarWidth'), themeManager.getOptions('minBubbleSize'), themeManager.getOptions('maxBubbleSize')) }, adjustSeriesDimensions: function(translators, useAggregation) { var that = this; if (useAggregation) $.each(that._series || [], function(_, s) { s.resamplePoints(translators) }); $.each(that._seriesFamilies, function() { this.adjustSeriesDimensions(translators) }) }, getBoundRange: function() { var that = this, rangeData, valueAxisMin = that._valueAxis.min, valueAxisMax = that._valueAxis.max, valRange = new core.Range({ isValueRange: true, min: valueAxisMin, minVisible: valueAxisMin, max: valueAxisMax, maxVisible: valueAxisMax, axisType: that._valueAxis.type, base: that._valueAxis.logarithmBase }), argRange = new core.Range({}), rangeYSize, rangeVisibleSizeY, i, minIndent, maxIndent; for (i = 0; i < that._series.length; i++) { rangeData = that._series[i].getRangeData(); valRange.addRange(rangeData.val); argRange.addRange(rangeData.arg) } if (valRange.isDefined() && argRange.isDefined()) { minIndent = that._valueAxis.inverted ? that._indent.top : that._indent.bottom; maxIndent = that._valueAxis.inverted ? that._indent.bottom : that._indent.top; rangeYSize = valRange.max - valRange.min; rangeVisibleSizeY = ($.isNumeric(valRange.maxVisible) ? valRange.maxVisible : valRange.max) - ($.isNumeric(valRange.minVisible) ? valRange.minVisible : valRange.min); if (utils.isDate(valRange.min)) valRange.min = new Date(valRange.min.valueOf() - rangeYSize * minIndent); else valRange.min -= rangeYSize * minIndent; if (utils.isDate(valRange.max)) valRange.max = new Date(valRange.max.valueOf() + rangeYSize * maxIndent); else valRange.max += rangeYSize * maxIndent; if ($.isNumeric(rangeVisibleSizeY)) { valRange.maxVisible = valRange.maxVisible ? valRange.maxVisible + rangeVisibleSizeY * maxIndent : undefined; valRange.minVisible = valRange.minVisible ? valRange.minVisible - rangeVisibleSizeY * minIndent : undefined } valRange.invert = that._valueAxis.inverted } return { arg: argRange, val: valRange } }, getSeries: function() { var that = this; return that._series }, getBackgroundColor: function() { var that = this; return that._backgroundColor }, isEmpty: function() { var that = this; return that.getSeries().length === 0 }, isShowChart: function() { var that = this; return !that.isEmpty() && !that._hideChart }, getCalculatedValueType: function() { var that = this, result; if (that._series.length) result = that._series[0].argumentType; return result } }; return prototypeObject }()) })(jQuery, DevExpress); /*! Module viz-rangeselector, file themeManager.js */ (function($, DX, undefined) { DX.viz.rangeSelector = DX.viz.rangeSelector; DX.viz.rangeSelector.ThemeManager = DX.viz.core.BaseThemeManager.inherit({ _themeSection: 'rangeSelector', ctor: function(userTheme) { this.setTheme(userTheme) }, _initializeTheme: function() { this._initializeFont(this._theme.scale.label.font); this._initializeFont(this._theme.sliderMarker.font); this._initializeFont(this._theme.loadingIndicator.font) }, applyRangeSelectorTheme: function(userOptions) { var that = this, chart = userOptions.chart, dataSource = userOptions.dataSource, result; delete userOptions.dataSource; delete userOptions.chart; result = $.extend(true, {}, that._theme, userOptions); result.dataSource = dataSource; if (chart) result.chart = chart; return result }, setBackgroundColor: function(containerBackgroundColor) { var theme = this._theme; if (containerBackgroundColor) theme.containerBackgroundColor = containerBackgroundColor; theme.shutter.color = theme.shutter.color || theme.containerBackgroundColor } }) })(jQuery, DevExpress); /*! Module viz-rangeselector, file dxRangeSelector.js */ (function($, DX, undefined) { var ui = DX.ui, viz = DX.viz; DX.registerComponent("dxRangeSelector", viz.rangeSelector.RangeSelector) })(jQuery, DevExpress); DevExpress.MOD_VIZ_RANGESELECTOR = true } if (!DevExpress.MOD_VIZ_VECTORMAP) { if (!DevExpress.MOD_VIZ_CORE) throw Error('Required module is not referenced: viz-core'); /*! Module viz-vectormap, file map.js */ (function(DX, $, undefined) { DX.viz.map = {}; var _Number = window.Number, _isFunction = DX.utils.isFunction, _getRootOffset = DX.utils.getRootOffset; var DEFAULT_WIDTH = 800, DEFAULT_HEIGHT = 400; var DATA_KEY = DX.viz.map.__DATA_KEY = 'vectormap-data'; DX.viz.map.Map = DX.viz.core.BaseWidget.inherit({ _init: function() { var that = this; that.callBase.apply(that, arguments); that.renderer = that._renderer = that._factory.createRenderer({ width: 1, height: 1, pathModified: that.option('pathModified'), rtl: that.option('rtlEnabled') }); that.renderer.draw(that._element().get(0)); that._root = that._renderer.getRoot(); that._root.applySettings({ 'class': 'dxm', stroke: 'none', strokeWidth: 0, fill: 'none', align: 'center', cursor: 'default', style: {overflow: 'hidden'} }); that._themeManager = that._factory.createThemeManager(); that._projection = that._factory.createProjection(); that._tracker = that._factory.createTracker({root: that._root}); that._background = that._renderer.createRect(0, 0, 0, 0, 0, {'class': 'dxm-background'}).data(DATA_KEY, {type: 'background'}); that._areasManager = that._factory.createAreasManager({ container: that._root, renderer: that._renderer, projection: that._projection, themeManager: that._themeManager, tracker: that._tracker, ready: function() { that.hideLoadingIndicator() } }); that._areasManager.setData(that.option('mapData')); that._markersManager = that._factory.createMarkersManager({ container: that._root, renderer: that._renderer, projection: that._projection, themeManager: that._themeManager, tracker: that._tracker }); that._markersManager.setData(that.option('markers')); that._controlBar = that._factory.createControlBar({ container: that._root, renderer: that._renderer, context: that, resetCallback: controlResetCallback, beginMoveCallback: controlBeginMoveCallback, endMoveCallback: controlEndMoveCallback, moveCallback: controlMoveCallback, zoomCallback: controlZoomCallback }); that._legend = that._factory.createLegend({ container: that._root, renderer: that._renderer, themeManager: that._themeManager }); that._tooltip = that._factory.createTooltip({ container: that._root, renderer: that._renderer, tracker: that._tracker }); that._projection.setBounds(that.option('bounds')).setMaxZoom(that.option('maxZoomFactor')).setZoom(that.option('zoomFactor')).setCenter(that.option('center')); that._themeManager.setTheme(that.option('theme')); that._themeManager.patchRtlSettings(that.option('rtlEnabled')); that._setClickCallback(that.option('click')); that._setCenterChangedCallback(that.option('centerChanged')); that._setZoomFactorChangedCallback(that.option('zoomFactorChanged')); that._setTrackerCallbacks() }, _dispose: function() { var that = this; that.callBase.apply(that, arguments); that._resetTrackerCallbacks(); that._themeManager.dispose(); that._tracker.dispose(); that._areasManager.dispose(); that._markersManager.dispose(); that._controlBar.dispose(); that._legend.dispose(); that._tooltip.dispose(); that._renderer.dispose(); that._disposeLoadIndicator(); that._renderer = that._themeManager = that._projection = that._tracker = that._root = that._background = that._areasManager = that._markersManager = that._controlBar = that._legend = that._tooltip = that._centerChangedCallback = that._zoomFactorChangedCallback = null }, _setTrackerCallbacks: function() { var that = this, renderer = that._renderer, managers = { area: that._areasManager, marker: that._markersManager }, projection = that._projection, controlBar = that._controlBar, tooltip = that._tooltip, xdrag, ydrag, isControlDrag = false; that._tracker.setCallbacks({ click: function(arg) { var offset = _getRootOffset(renderer); arg.$event.x = arg.x - offset.left; arg.$event.y = arg.y - offset.top; var manager = managers[arg.data.type]; if (manager) manager.raiseClick(arg.data.index, arg.$event); if (manager || arg.data.type === 'background') that._raiseClick(arg.$event) }, start: function(arg) { isControlDrag = arg.data.type === 'control-bar'; if (isControlDrag) { arg.data = arg.data.index; controlBar.processStart(arg) } else { xdrag = arg.x; ydrag = arg.y; projection.snapCenter() } }, move: function(arg) { if (isControlDrag) { arg.data = arg.data.index; controlBar.processMove(arg) } else { projection.moveCenter(xdrag - arg.x, ydrag - arg.y); xdrag = arg.x; ydrag = arg.y; that._applyTranslate() } }, end: function(arg) { if (isControlDrag) { arg.data = arg.data.index; controlBar.processEnd(arg) } else projection.isCenterChanged() && that._raiseCenterChanged(); isControlDrag = false }, zoom: function(arg) { controlBar.processZoom(arg) }, 'hover-on': function(arg) { var manager = managers[arg.data.type]; if (manager) manager.hoverItem(arg.data.index, true) }, 'hover-off': function(arg) { var manager = managers[arg.data.type]; if (manager) manager.hoverItem(arg.data.index, false) }, 'focus-on': function(arg, done) { var result = false; if (tooltip.enabled()) { var proxy = managers[arg.data.type] ? managers[arg.data.type].getProxyItem(arg.data.index) : null; if (!!proxy && tooltip.prepare(proxy, {offset: 12})) { var offset = _getRootOffset(renderer); tooltip.show().move(arg.x - offset.left, arg.y - offset.top); result = true } } done(result) }, 'focus-move': function(arg) { var offset = _getRootOffset(renderer); tooltip.move(arg.x - offset.left, arg.y - offset.top) }, 'focus-off': function(arg) { tooltip.hide() } }); that._resetTrackerCallbacks = function() { that._resetTrackerCallbacks = that = renderer = managers = projection = controlBar = tooltip = null } }, _adjustSize: function(force) { var that = this, size = that.option('size') || {}, width = size.width >= 0 ? _Number(size.width) : that._element().width(), height = size.height >= 0 ? _Number(size.height) : that._element().height(), hidden = false; if (width === 0) if (_Number(size.width) === 0) hidden = true; else width = DEFAULT_WIDTH; if (height === 0) if (_Number(size.height) === 0) hidden = true; else height = DEFAULT_HEIGHT; if (hidden || !that._element().is(':visible')) { that._incidentOccured("W2001", [that.NAME]); that._width = that._height = 0; return false } var needResize = that._width !== width || that._height !== height || force; if (needResize) { that._width = width; that._height = height; that._renderer.resize(width, height); that._projection.setSize(width, height); that._legend.applyLayout(width, height); that._tooltip.setSize(width, height); that._background.applySettings({ x: 0, y: 0, width: width, height: height }); that._applyTranslate(); that._updateLoadIndicator(undefined, width, height) } return needResize }, _clean: function() { var that = this; that._tracker.clean(); that._background.detach(); that._areasManager.clean(); that._markersManager.clean(); that._controlBar.clean(); that._legend.clean(); that._tooltip.clean() }, _render: function() { var that = this; if (!that._adjustSize(true)) return; that._tooltip.update(that._themeManager.getTooltipSettings(that.option('tooltip'))); that._tracker.setOptions(that.option('interaction') || {}); that._controlBar.setZoomPartition(that._projection.getZoomScalePartition()).setZoom(that._projection.getScaledZoom()).setOptions(that._themeManager.getControlBarSettings(that.option('controlBar')), that.option('interaction')); that._background.applySettings(that._themeManager.getBackgroundSettings(that.option('background'))); that._background.append(that._root); that._areasManager.render(that.option('areaSettings')); that._markersManager.render(that.option('markerSettings')); that._controlBar.render(); that._legend.render(that._themeManager.getLegendSettings(that.option('legend'))); that._tooltip.render(); that._tracker.render(); that._drawn() }, _optionChanged: function(name, value) { var that = this; switch (name) { case'theme': that._themeManager.setTheme(value); that._themeManager.patchRtlSettings(that.option('rtlEnabled')); that._invalidate(); break; case'click': that._setClickCallback(value); break; case'centerChanged': that._setCenterChangedCallback(value); break; case'zoomFactorChanged': that._setZoomFactorChangedCallback(value); break; case'mapData': that._areasManager.setData(value); break; case'markers': that._markersManager.setData(value); break; case'bounds': that._projection.setBounds(value); that._invalidate(); break; case'maxZoomFactor': that._projection.setMaxZoom(value); that._invalidate(); break; case'zoomFactor': that._updateZoomFactor(value); break; case'center': that._updateCenter(value); break; default: that.callBase.apply(that, arguments); break } }, _getLoadIndicatorOption: function() { return this._themeManager.getLoadIndicatorSettings(this.option('loadingIndicator')) }, _setClickCallback: function(callback) { this._clickCallback = _isFunction(callback) ? callback : null }, _setCenterChangedCallback: function(callback) { var that = this; that._centerChangedCallback = _isFunction(callback) ? function() { that._centerChangedCallback && callback.call(that, that._projection.getCenter()) } : null }, _setZoomFactorChangedCallback: function(callback) { var that = this; that._zoomFactorChangedCallback = _isFunction(callback) ? function() { that._zoomFactorChangedCallback && callback.call(that, that._projection.getZoom()) } : null }, _raiseClick: function(arg) { var that = this; that._clickCallback && setTimeout(function() { that._clickCallback && that._clickCallback.call(that, arg) }, 0) }, _raiseCenterChanged: function() { this._centerChangedCallback && setTimeout(this._centerChangedCallback, 0) }, _raiseZoomFactorChanged: function() { this._zoomFactorChangedCallback && setTimeout(this._zoomFactorChangedCallback, 0) }, _updateCenter: function(center, _noEvent) { this._projection.snapCenter().setCenter(center); if (this._projection.isCenterChanged()) { this._applyTransform(); _noEvent || this._raiseCenterChanged() } }, _updateZoomFactor: function(zoomFactor, _noEvent) { var that = this; that._projection.snapZoom().setZoom(zoomFactor); if (that._projection.isZoomChanged()) { that._controlBar.setZoom(that._projection.getScaledZoom()); that._applyTransform(true); _noEvent || that._raiseZoomFactorChanged() } }, _updateViewport: function(viewport, _noEvent) { var that = this; that._projection.snapCenter().snapZoom().setViewport(viewport); that._applyTransform(that._projection.isZoomChanged()); if (that._projection.isCenterChanged()) _noEvent || that._raiseCenterChanged(); if (that._projection.isZoomChanged()) { that._controlBar.setZoom(that._projection.getScaledZoom()); _noEvent || that._raiseZoomFactorChanged() } }, _resize: function() { if (this._adjustSize()) this._applyTransform(true) }, _applyTranslate: function() { var transform = this._projection.getTransform(); this._areasManager.transform(transform); this._markersManager.transform(transform) }, _applyTransform: function(redraw, _noTrackerReset) { _noTrackerReset || this._tracker.reset(); this._applyTranslate(); if (redraw) { this._areasManager.redraw(); this._markersManager.redraw() } }, _refresh: function() { var that = this, callBase = that.callBase; that._endLoading(function() { callBase.call(that) }) }, render: function() { var that = this; if (that._width === 0 && that._height === 0) that._refresh(); else that._resize(); return that }, getAreas: function() { return this._areasManager.getProxyItems() }, getMarkers: function() { return this._markersManager.getProxyItems() }, clearAreaSelection: function(_noEvent) { this._areasManager.clearSelection(_noEvent); return this }, clearMarkerSelection: function(_noEvent) { this._markersManager.clearSelection(_noEvent); return this }, clearSelection: function(_noEvent) { return this.clearAreaSelection(_noEvent).clearMarkerSelection(_noEvent) }, center: function(value, _noEvent) { if (value === undefined) return this._projection.getCenter(); else { this._updateCenter(value, _noEvent); return this } }, zoomFactor: function(value, _noEvent) { if (value === undefined) return this._projection.getZoom(); else { this._updateZoomFactor(value, _noEvent); return this } }, viewport: function(value, _noEvent) { if (value === undefined) return this._projection.getViewport(); else { this._updateViewport(value, _noEvent); return this } }, convertCoordinates: function(x, y) { return this._projection.fromScreenPointStrict(x, y) }, showLoadingIndicator: function() { this._showLoadIndicator(this._themeManager.getLoadIndicatorSettings(this.option('loadingIndicator')), { width: this._width, height: this._height }) }, _factory: { createRenderer: function(options) { return new DX.viz.renderers.Renderer(options) }, createTooltip: function(parameters) { return new Tooltip(parameters) }, createLegend: function(parameters) { return new Legend(parameters) } } }); var Tooltip = DX.viz.core.Tooltip.inherit({ ctor: function(parameters) { var that = this; that._container = parameters.container; that._root = parameters.renderer.createGroup({'class': 'dxm-tooltip'}); that.callBase(null, that._root, parameters.renderer); that._tracker = parameters.tracker; that._enabled = false }, dispose: function() { var that = this; that._container = that._root = that._tracker = null; return that.callBase.apply(that, arguments) }, clean: function() { this._root.detach(); return this }, render: function() { this._root.append(this._container); return this } }); var Legend = DX.viz.core.Legend.inherit({ ctor: function(parameters) { var that = this; that._container = parameters.container; that._root = parameters.renderer.createGroup({'class': 'dxm-legend'}); that._themeManager = parameters.themeManager; that.callBase(null, null, parameters.renderer, that._root) }, dispose: function() { var that = this; that._container = that._root = that._themeManager = null; return that.callBase.apply(that, arguments) }, clean: function() { this._root.detach(); return this }, render: function(options) { var that = this, items = [], i = 0, ii = options.items ? options.items.length : 0; for (; i < ii; ++i) items.push(that._themeManager.getLegendItemSettings(options.items[i] || {})); that.update(items, options); that._root.append(that._container); return that.applyLayout(that._size.width, that._size.height) }, applyLayout: function(width, height) { var that = this, layoutOptions; that.setSize({ width: width, height: height }); that.draw(); layoutOptions = that.getLayoutOptions(); if (layoutOptions) { var left, top; if (layoutOptions.horizontalAlignment === 'left') left = 0; else if (layoutOptions.horizontalAlignment === 'center') left = width / 2 - layoutOptions.width / 2; else left = width - layoutOptions.width; if (layoutOptions.verticalAlignment === 'top') top = 0; else top = height - layoutOptions.height; that.shift(left, top) } return that } }); function projectAreaDefault(dataItem) { return this._projection.projectArea(dataItem.coordinates) } function projectAreaGeoJson(dataItem) { if (dataItem.geometry) { var type = dataItem.geometry.type, coordinates = dataItem.geometry.coordinates; if (coordinates && (type === 'Polygon' || type === 'MultiPolygon')) { type === 'MultiPolygon' && (coordinates = [].concat.apply([], coordinates)); return this._projection.projectArea(coordinates) } } return [] } function controlResetCallback() { var projection = this._projection, isCenterChanged, isZoomChanged; projection.snapCenter().snapZoom().setCenter(null).setZoom(null); isCenterChanged = projection.isCenterChanged(); isZoomChanged = projection.isZoomChanged(); if (isCenterChanged || isZoomChanged) this._applyTransform(isZoomChanged, true); isCenterChanged && this._raiseCenterChanged(); isZoomChanged && this._raiseZoomFactorChanged() } function controlBeginMoveCallback() { this._projection.snapCenter() } function controlEndMoveCallback() { this._projection.isCenterChanged() && this._raiseCenterChanged() } function controlMoveCallback(dx, dy) { this._projection.moveCenter(dx, dy); this._applyTranslate() } function controlZoomCallback(zoom, x, y) { var that = this, keepPosition = x !== undefined && y !== undefined, coords, screenPosition; if (keepPosition) { screenPosition = _getRootOffset(that._renderer); screenPosition = [x - screenPosition.left, y - screenPosition.top]; coords = that._projection.fromScreenPoint(screenPosition[0], screenPosition[1]) } that._projection.snapZoom().setScaledZoom(zoom); if (that._projection.isZoomChanged()) { keepPosition && that._projection.snapCenter().setCenterByPoint(coords, screenPosition); that._applyTransform(true, true); that._raiseZoomFactorChanged(); keepPosition && that._projection.isCenterChanged() && that._raiseCenterChanged() } } DX.registerComponent('dxVectorMap', DX.viz.map.Map); DX.viz.map._internal = {}; DX.viz.map.sources = {}; DX.viz.map._tests = {}; DX.viz.map._tests.Legend = Legend; DX.viz.map._tests.Tooltip = Tooltip })(DevExpress, jQuery); /*! Module viz-vectormap, file projection.js */ (function(DX, $, undefined) { var _Number = Number, _isFinite = isFinite, _min = Math.min, _max = Math.max, _abs = Math.abs, _tan = Math.tan, _atan = Math.atan, _exp = Math.exp, _round = Math.round, _ln = Math.log, _pow = Math.pow, _isArray = DX.utils.isArray, _buildPath = DX.viz.renderers.buildPath; var PI = Math.PI, QUARTER_PI = PI / 4, PI_TO_360 = PI / 360, TWO_TO_LN2 = 2 / Math.LN2; var DEFAULT_MIN_ZOOM = 1, DEFAULT_MAX_ZOOM = 1 << 8; var MERCATOR_MIN_LON = -180, MERCATOR_MAX_LON = 180, MERCATOR_MIN_LAT = -85.0511, MERCATOR_MAX_LAT = 85.0511; var mercator = { aspectRatio: 1, project: function(coordinates) { var lon = coordinates[0], lat = coordinates[1]; return [lon <= MERCATOR_MIN_LON ? -1 : lon >= MERCATOR_MAX_LON ? +1 : lon / 180, lat <= MERCATOR_MIN_LAT ? +1 : lat >= MERCATOR_MAX_LAT ? -1 : -_ln(_tan(QUARTER_PI + lat * PI_TO_360)) / PI] }, unproject: function(coordinates) { var x = coordinates[0], y = coordinates[1]; return [x <= -1 ? MERCATOR_MIN_LON : x >= +1 ? MERCATOR_MAX_LON : 180 * x, y <= -1 ? MERCATOR_MAX_LAT : y >= +1 ? MERCATOR_MIN_LAT : (_atan(_exp(-PI * coordinates[1])) - QUARTER_PI) / PI_TO_360] } }; function createProjectUnprojectMethods(p1, p2, delta) { var x0 = (p1[0] + p2[0]) / 2 - delta / 2, y0 = (p1[1] + p2[1]) / 2 - delta / 2, k = 2 / delta; return { project: function(coordinates) { var p = mercator.project(coordinates); return [-1 + (p[0] - x0) * k, -1 + (p[1] - y0) * k] }, unproject: function(coordinates) { var p = [x0 + (coordinates[0] + 1) / k, y0 + (coordinates[1] + 1) / k]; return mercator.unproject(p) } } } function floatsEqual(f1, f2) { return _abs(f1 - f2) < 1E-8 } function truncate(value, min, max, fallback) { var _value = _Number(value); if (_value < min) _value = min; else if (_value > max) _value = max; else if (!(min <= _value && _value <= max)) _value = fallback; return _value } function truncateQuad(quad, min, max) { return { lt: [truncate(quad[0], min[0], max[0], min[0]), truncate(quad[1], min[1], max[1], min[1])], rb: [truncate(quad[2], min[0], max[0], max[0]), truncate(quad[3], min[1], max[1], max[1])] } } function parseBounds(bounds) { var p1 = mercator.unproject([-1, -1]), p2 = mercator.unproject([+1, +1]), min = [_min(p1[0], p2[0]), _min(p1[1], p2[1])], max = [_max(p1[0], p2[0]), _max(p1[1], p2[1])], quad = bounds; if (quad && quad.minLon) quad = [quad.minLon, quad.minLat, quad.maxLon, quad.maxLat]; if (quad) quad = truncateQuad(quad, min, max); return { minBase: min, maxBase: max, min: quad ? [_min(quad.lt[0], quad.rb[0]), _min(quad.lt[1], quad.rb[1])] : min, max: quad ? [_max(quad.lt[0], quad.rb[0]), _max(quad.lt[1], quad.rb[1])] : max } } function selectCenterValue(value1, value2, center1, center2) { var result; if (value1 > -1 && value2 >= +1) result = center1; else if (value1 <= -1 && value2 < +1) result = center2; else result = (center1 + center2) / 2; return result } function Projection() { this.setBounds(null) } Projection.prototype = { constructor: Projection, _minZoom: DEFAULT_MIN_ZOOM, _maxZoom: DEFAULT_MAX_ZOOM, _zoom: DEFAULT_MIN_ZOOM, setSize: function(width, height) { var that = this; that._x0 = width / 2; that._y0 = height / 2; if (width / height <= mercator.aspectRatio) { that._xradius = width / 2; that._yradius = width / 2 / mercator.aspectRatio } else { that._xradius = height / 2 * mercator.aspectRatio; that._yradius = height / 2 } return that }, setBounds: function(bounds) { var that = this, _bounds = parseBounds(bounds); that._minBase = _bounds.minBase; that._maxBase = _bounds.maxBase; that._minBound = _bounds.min; that._maxBound = _bounds.max; var p1 = mercator.project(_bounds.min), p2 = mercator.project(_bounds.max), delta = _min(truncate(_abs(p2[0] - p1[0]), 0.1, 2, 2), truncate(_abs(p2[1] - p1[1]), 0.1, 2, 2)), methods = delta < 2 ? createProjectUnprojectMethods(p1, p2, delta) : mercator; that._project = methods.project; that._unproject = methods.unproject; var minv = that._project(_bounds.minBase), maxv = that._project(_bounds.maxBase); that._minv = [_min(minv[0], maxv[0]), _min(minv[1], maxv[1])]; that._maxv = [_max(minv[0], maxv[0]), _max(minv[1], maxv[1])]; that._defaultCenter = that._unproject([0, 0]); return that.setCenter(that._defaultCenter) }, _toScreen: function(coordinates) { return [this._x0 + this._xradius * coordinates[0], this._y0 + this._yradius * coordinates[1]] }, _fromScreen: function(coordinates) { return [(coordinates[0] - this._x0) / this._xradius, (coordinates[1] - this._y0) / this._yradius] }, _toTransformed: function(coordinates) { return [coordinates[0] * this._zoom + this._dxcenter, coordinates[1] * this._zoom + this._dycenter, ] }, _toTransformedFast: function(coordinates) { return [coordinates[0] * this._zoom, coordinates[1] * this._zoom] }, _fromTransformed: function(coordinates) { return [(coordinates[0] - this._dxcenter) / this._zoom, (coordinates[1] - this._dycenter) / this._zoom] }, _adjustCenter: function() { var that = this, center = that._project(that._center); that._dxcenter = -center[0] * that._zoom; that._dycenter = -center[1] * that._zoom }, projectArea: function(coordinates) { var i = 0, ii = _isArray(coordinates) ? coordinates.length : 0, subcoords, j, jj, subresult, result = []; for (; i < ii; ++i) { subcoords = coordinates[i]; subresult = []; for (j = 0, jj = _isArray(subcoords) ? subcoords.length : 0; j < jj; ++j) subresult.push(this._project(subcoords[j])); result.push(subresult) } return result }, projectPoint: function(coordinates) { return coordinates ? this._project(coordinates) : [] }, getAreaCoordinates: function(data) { var k = 0, kk = data.length, partialData, i, ii, list = [], partialPath, point; for (; k < kk; ++k) { partialData = data[k]; partialPath = []; for (i = 0, ii = partialData.length; i < ii; ++i) { point = this._toScreen(this._toTransformedFast(partialData[i])); partialPath.push(point[0], point[1]) } list.push(_buildPath(partialPath)) } return list.join(' ') }, getPointCoordinates: function(data) { var point = this._toScreen(this._toTransformedFast(data)); return { x: _round(point[0]), y: _round(point[1]) } }, getZoom: function() { return this._zoom }, setZoom: function(zoom) { var that = this; that._zoom = truncate(zoom, that._minZoom, that._maxZoom, that._minZoom); that._adjustCenter(); return that }, getScaledZoom: function() { return _round((this._scale.length - 1) * _ln(this._zoom) / _ln(this._maxZoom)) }, setScaledZoom: function(scaledZoom) { return this.setZoom(this._scale[_round(scaledZoom)]) }, getZoomScalePartition: function() { return this._scale.length - 1 }, _setupScaling: function() { var that = this, k = _round(TWO_TO_LN2 * _ln(that._maxZoom)); k = k > 4 ? k : 4; var step = _pow(that._maxZoom, 1 / k), zoom = that._minZoom, i = 1; that._scale = [zoom]; for (; i <= k; ++i) that._scale.push(zoom *= step) }, setMaxZoom: function(maxZoom) { var that = this; that._minZoom = DEFAULT_MIN_ZOOM; that._maxZoom = truncate(maxZoom, that._minZoom, _Number.MAX_VALUE, DEFAULT_MAX_ZOOM); that._setupScaling(); if (that._zoom > that._maxZoom) that.setZoom(that._maxZoom); return that }, getMinZoom: function() { return this._minZoom }, getMaxZoom: function() { return this._maxZoom }, getCenter: function() { return [this._center[0], this._center[1]] }, setCenter: function(center) { var _center = _isArray(center) ? center : null; _center = _center || center && (center.lon || center.lat) && [center.lon, center.lat] || []; var that = this; that._center = [truncate(_center[0], that._minBound[0], that._maxBound[0], that._defaultCenter[0]), truncate(_center[1], that._minBound[1], that._maxBound[1], that._defaultCenter[1])]; that._adjustCenter(); return that }, setCenterByPoint: function(coordinates, screenPosition) { var that = this, p = that._project(coordinates), q = that._fromScreen(screenPosition); return that.setCenter(that._unproject([-q[0] / that._zoom + p[0], -q[1] / that._zoom + p[1]])) }, moveCenter: function(screenDx, screenDy) { var that = this, current = that._toScreen(that._toTransformed(that._project(that._center))), center = that._unproject(that._fromTransformed(that._fromScreen([current[0] + screenDx, current[1] + screenDy]))); return that.setCenter(center) }, getViewport: function() { var p1 = this._unproject(this._fromTransformed([-1, -1])), p2 = this._unproject(this._fromTransformed([+1, +1])); return [p1[0], p1[1], p2[0], p2[1]] }, setViewport: function(viewport) { var that = this; if (!_isArray(viewport)) return that.setZoom(that._minZoom).setCenter(that._defaultCenter); var _viewport = truncateQuad(viewport, that._minBase, that._maxBase), lt = that._project(_viewport.lt), rb = that._project(_viewport.rb), l = _min(lt[0], rb[0]), t = _min(lt[1], rb[1]), r = _max(lt[0], rb[0]), b = _max(lt[1], rb[1]), zoom = 2 / _max(r - l, b - t), xc = selectCenterValue(l, r, -1 - zoom * l, +1 - zoom * r), yc = selectCenterValue(t, b, -1 - zoom * t, +1 - zoom * b); return that.setZoom(zoom).setCenter(that._unproject([-xc / zoom, -yc / zoom])) }, getTransform: function() { return { translateX: this._dxcenter * this._xradius, translateY: this._dycenter * this._yradius } }, fromScreenPoint: function(x, y) { return this._unproject(this._fromTransformed(this._fromScreen([x, y]))) }, fromScreenPointStrict: function(x, y) { var that = this, p = that._fromTransformed(that._fromScreen([x, y])), q = that._unproject(p); return [p[0] >= that._minv[0] && p[0] <= that._maxv[0] ? q[0] : NaN, p[1] >= that._minv[1] && p[1] <= that._maxv[1] ? q[1] : NaN] }, snapCenter: function() { this._snappedCenter = this.getCenter(); return this }, isCenterChanged: function() { var center = this.getCenter(); return !floatsEqual(this._snappedCenter[0], center[0]) || !floatsEqual(this._snappedCenter[1], center[1]) }, snapZoom: function() { this._snappedZoom = this.getZoom(); return this }, isZoomChanged: function() { return !floatsEqual(this._snappedZoom, this.getZoom()) } }; DX.viz.map._tests.Projection = Projection; DX.viz.map._tests.mercator = mercator; DX.viz.map._tests._DEBUG_stubMercator = function(stub) { mercator = stub }; DX.viz.map._tests._DEBUG_restoreMercator = function() { mercator = DX.viz.map._tests.mercator }; DX.viz.map.Map.prototype._factory.createProjection = function() { return new Projection } })(DevExpress, jQuery); /*! Module viz-vectormap, file controlBar.js */ (function(DX, undefined) { var _buildPath = DX.viz.renderers.buildPath, _setTimeout = setTimeout, _clearTimeout = clearTimeout, _round = Math.round, _pow = Math.pow, _ln = Math.log; var _LN2 = Math.LN2; var COMMAND_RESET = 'command-reset', COMMAND_MOVE_UP = 'command-move-up', COMMAND_MOVE_RIGHT = 'command-move-right', COMMAND_MOVE_DOWN = 'command-move-down', COMMAND_MOVE_LEFT = 'command-move-left', COMMAND_ZOOM_IN = 'command-zoom-in', COMMAND_ZOOM_OUT = 'command-zoom-out', COMMAND_ZOOM_DRAG = 'command-zoom-drag'; var _DATA_KEY = DX.viz.map.__DATA_KEY, EVENT_TARGET_TYPE = 'control-bar'; var COMMAND_TO_TYPE_MAP = {}; COMMAND_TO_TYPE_MAP[COMMAND_RESET] = ResetCommand; COMMAND_TO_TYPE_MAP[COMMAND_MOVE_UP] = COMMAND_TO_TYPE_MAP[COMMAND_MOVE_RIGHT] = COMMAND_TO_TYPE_MAP[COMMAND_MOVE_DOWN] = COMMAND_TO_TYPE_MAP[COMMAND_MOVE_LEFT] = MoveCommand; COMMAND_TO_TYPE_MAP[COMMAND_ZOOM_IN] = COMMAND_TO_TYPE_MAP[COMMAND_ZOOM_OUT] = ZoomCommand; COMMAND_TO_TYPE_MAP[COMMAND_ZOOM_DRAG] = ZoomDragCommand; var ControlBar = DX.Class.inherit({ ctor: function(parameters) { var that = this; that._container = parameters.container; that._createElements(parameters.renderer); var context = parameters.context, resetCallback = parameters.resetCallback, beginMoveCallback = parameters.beginMoveCallback, endMoveCallback = parameters.endMoveCallback, moveCallback = parameters.moveCallback, zoomCallback = parameters.zoomCallback; parameters = null; that._reset = function() { resetCallback.call(context) }; that._beginMove = function() { beginMoveCallback.call(context) }; that._endMove = function() { endMoveCallback.call(context) }; that._move = function(dx, dy) { moveCallback.call(context, dx, dy) }; that._zoom = function(zoom, x, y) { zoomCallback.call(context, zoom, x, y) }; that._dispose = function() { this._reset = this._move = this._zoom = this._dispose = context = resetCallback = moveCallback = zoomCallback = null } }, _createElements: function(renderer) { var that = this; that._root = renderer.createGroup({'class': 'dxm-control-bar'}); that._buttonsGroup = renderer.createGroup({'class': 'dxm-control-buttons'}).append(that._root); that._trackersGroup = renderer.createGroup({ stroke: 'none', strokeWidth: 0, fill: '#000000', opacity: 0.0001, cursor: 'pointer' }).append(that._root); var options = { bigCircleSize: 58, smallCircleSize: 28, buttonSize: 10, arrowButtonOffset: 20, incdecButtonSize: 11, incButtonOffset: 66, decButtonOffset: 227, sliderLineStartOffset: 88.5, sliderLineEndOffset: 205.5, sliderLength: 20, sliderWidth: 8, trackerGap: 4 }; that._createButtons(renderer, options); that._createTrackers(renderer, options); that._root.applySettings({ translateX: 50.5, translateY: 50.5 }) }, _createButtons: function(renderer, options) { var group = this._buttonsGroup, size = options.buttonSize / 2, offset1 = options.arrowButtonOffset - size, offset2 = options.arrowButtonOffset, incdecButtonSize = options.incdecButtonSize / 2; renderer.createCircle(0, 0, options.bigCircleSize / 2).append(group); renderer.createCircle(0, 0, size).append(group); renderer.createPath([-size, -offset1, 0, -offset2, size, -offset1]).append(group); renderer.createPath([offset1, -size, offset2, 0, offset1, size]).append(group); renderer.createPath([size, offset1, 0, offset2, -size, offset1]).append(group); renderer.createPath([-offset1, size, -offset2, 0, -offset1, -size]).append(group); renderer.createCircle(0, options.incButtonOffset, options.smallCircleSize / 2).append(group); renderer.createSimplePath({d: _buildPath([-incdecButtonSize, options.incButtonOffset, incdecButtonSize, options.incButtonOffset]) + ' ' + _buildPath([0, options.incButtonOffset - incdecButtonSize, 0, options.incButtonOffset + incdecButtonSize])}).append(group); renderer.createCircle(0, options.decButtonOffset, options.smallCircleSize / 2).append(group); renderer.createSimplePath({d: _buildPath([-incdecButtonSize, options.decButtonOffset, incdecButtonSize, options.decButtonOffset])}).append(group); renderer.createSimplePath({d: _buildPath([0, options.sliderLineStartOffset, 0, options.sliderLineEndOffset])}).append(group); this._zoomDrag = renderer.createRect(-options.sliderLength / 2, options.sliderLineEndOffset - options.sliderWidth / 2, options.sliderLength, options.sliderWidth).append(group); this._sliderLineLength = options.sliderLineEndOffset - options.sliderLineStartOffset }, _createTrackers: function(renderer, options) { var group = this._trackersGroup, size = _round((options.arrowButtonOffset - options.trackerGap) / 2), offset1 = options.arrowButtonOffset - size, offset2 = _round(_pow(options.bigCircleSize * options.bigCircleSize / 4 - size * size, 0.5)), size2 = offset2 - offset1, element; renderer.createRect(-size, -size, size * 2, size * 2).append(group).data(_DATA_KEY, { index: COMMAND_RESET, type: EVENT_TARGET_TYPE }); renderer.createRect(-size, -offset2, size * 2, size2).append(group).data(_DATA_KEY, { index: COMMAND_MOVE_UP, type: EVENT_TARGET_TYPE }); renderer.createRect(offset1, -size, size2, size * 2).append(group).data(_DATA_KEY, { index: COMMAND_MOVE_RIGHT, type: EVENT_TARGET_TYPE }); renderer.createRect(-size, offset1, size * 2, size2).append(group).data(_DATA_KEY, { index: COMMAND_MOVE_DOWN, type: EVENT_TARGET_TYPE }); renderer.createRect(-offset2, -size, size2, size * 2).append(group).data(_DATA_KEY, { index: COMMAND_MOVE_LEFT, type: EVENT_TARGET_TYPE }); renderer.createCircle(0, options.incButtonOffset, options.smallCircleSize / 2).append(group).data(_DATA_KEY, { index: COMMAND_ZOOM_IN, type: EVENT_TARGET_TYPE }); renderer.createCircle(0, options.decButtonOffset, options.smallCircleSize / 2).append(group).data(_DATA_KEY, { index: COMMAND_ZOOM_OUT, type: EVENT_TARGET_TYPE }); this._zoomDragCover = renderer.createRect(-options.sliderLength / 2, options.sliderLineEndOffset - options.sliderWidth / 2, options.sliderLength, options.sliderWidth).append(group).data(_DATA_KEY, { index: COMMAND_ZOOM_DRAG, type: EVENT_TARGET_TYPE }) }, dispose: function() { var that = this; delete that._container; that._dispose(); that._root.clear(); delete that._root; delete that._buttonsGroup; delete that._zoomDrag; delete that._zoomDragCover; return that }, setZoomPartition: function(partition) { this._zoomPartition = partition; this._sliderUnitLength = this._sliderLineLength / partition; return this }, setZoom: function(zoom) { this._adjustZoom(zoom); return this }, setOptions: function(options, interactionOptions) { options = options || {}; interactionOptions = interactionOptions || {}; this._dragAndZoomEnabled = interactionOptions.dragAndZoomEnabled !== undefined ? !!interactionOptions.dragAndZoomEnabled : true; this._enabled = this._dragAndZoomEnabled && (options.enabled !== undefined ? !!options.enabled : true); this._buttonsGroup.applySettings(options.shape); return this }, clean: function() { this._enabled && this._root.detach(); return this }, render: function() { this._enabled && this._root.append(this._container); return this }, _adjustZoom: function(zoom) { var that = this; that._zoomFactor = _round(zoom); that._zoomFactor >= 0 || (that._zoomFactor = 0); that._zoomFactor <= that._zoomPartition || (that._zoomFactor = that._zoomPartition); var transform = {translateY: -that._zoomFactor * that._sliderUnitLength}; that._zoomDrag.applySettings(transform); that._zoomDragCover.applySettings(transform) }, _applyZoom: function(x, y) { this._zoom(this._zoomFactor, x, y) }, processStart: function(arg) { if (this._dragAndZoomEnabled) { var commandType = COMMAND_TO_TYPE_MAP[arg.data]; this._command = new commandType(this, arg) } return this }, processMove: function(arg) { if (this._dragAndZoomEnabled) this._command.update(arg); return this }, processEnd: function(arg) { if (this._dragAndZoomEnabled) this._command.finish(arg); return this }, processZoom: function(arg) { var that = this, zoomFactor; if (that._dragAndZoomEnabled) { if (arg.delta) zoomFactor = arg.delta; else if (arg.ratio) zoomFactor = _ln(arg.ratio) / _LN2; that._adjustZoom(that._zoomFactor + zoomFactor); that._applyZoom(arg.x, arg.y) } return that } }); function disposeCommand(command) { delete command._owner; command.update = function(){}; command.finish = function(){} } function ResetCommand(owner, arg) { this._owner = owner; this._command = arg.data } ResetCommand.prototype.update = function(arg) { arg.data !== this._command && disposeCommand(this) }; ResetCommand.prototype.finish = function() { this._owner._reset(); this._owner._adjustZoom(0); disposeCommand(this) }; function MoveCommand(owner, arg) { this._command = arg.data; var timeout = null, interval = 100, dx = 0, dy = 0; switch (this._command) { case COMMAND_MOVE_UP: dy = -10; break; case COMMAND_MOVE_RIGHT: dx = 10; break; case COMMAND_MOVE_DOWN: dy = 10; break; case COMMAND_MOVE_LEFT: dx = -10; break } function callback() { owner._move(dx, dy); timeout = _setTimeout(callback, interval) } this._stop = function() { _clearTimeout(timeout); owner._endMove(); this._stop = owner = callback = null; return this }; arg = null; owner._beginMove(); callback() } MoveCommand.prototype.update = function(arg) { this._command !== arg.data && this.finish() }; MoveCommand.prototype.finish = function() { disposeCommand(this._stop()) }; function ZoomCommand(owner, arg) { this._owner = owner; this._command = arg.data; var timeout = null, interval = 150, dzoom = this._command === COMMAND_ZOOM_IN ? 1 : -1; function callback() { owner._adjustZoom(owner._zoomFactor + dzoom); timeout = _setTimeout(callback, interval) } this._stop = function() { _clearTimeout(timeout); this._stop = owner = callback = null; return this }; arg = null; callback() } ZoomCommand.prototype.update = function(arg) { this._command !== arg.data && this.finish() }; ZoomCommand.prototype.finish = function() { this._owner._applyZoom(); disposeCommand(this._stop()) }; function ZoomDragCommand(owner, arg) { this._owner = owner; this._zoomFactor = owner._zoomFactor; this._pos = arg.y } ZoomDragCommand.prototype.update = function(arg) { var owner = this._owner; owner._adjustZoom(this._zoomFactor + owner._zoomPartition * (this._pos - arg.y) / owner._sliderLineLength) }; ZoomDragCommand.prototype.finish = function() { this._owner._applyZoom(); disposeCommand(this) }; DX.viz.map._tests.ControlBar = ControlBar; DX.viz.map.Map.prototype._factory.createControlBar = function(parameters) { return new ControlBar(parameters) } })(DevExpress); /*! Module viz-vectormap, file tracker.js */ (function(DX, $, undefined) { var _addNamespace = DX.ui.events.addNamespace, _abs = Math.abs, _sqrt = Math.sqrt, _round = Math.round, _max = Math.max, _min = Math.min, _now = $.now, _extend = $.extend; var _NAME = DX.viz.map.Map.prototype.NAME, _DATA_KEY = DX.viz.map.__DATA_KEY; var $doc = $(document); var EVENTS = {}; setupEvents(); var EVENT_START = 'start', EVENT_MOVE = 'move', EVENT_END = 'end', EVENT_ZOOM = 'zoom', EVENT_HOVER_ON = 'hover-on', EVENT_HOVER_OFF = 'hover-off', EVENT_CLICK = 'click', EVENT_FOCUS_ON = 'focus-on', EVENT_FOCUS_MOVE = 'focus-move', EVENT_FOCUS_OFF = 'focus-off'; var CLICK_TIME_THRESHOLD = 500, CLICK_COORD_THRESHOLD = 5, DRAG_COORD_THRESHOLD_MOUSE = 5, DRAG_COORD_THRESHOLD_TOUCH = 10, FOCUS_ON_DELAY_MOUSE = 300, FOCUS_OFF_DELAY_MOUSE = 300, FOCUS_ON_DELAY_TOUCH = 300, FOCUS_OFF_DELAY_TOUCH = 400, FOCUS_COORD_THRESHOLD_MOUSE = 5; function Tracker(parameters) { this._root = parameters.root; this._callbacks = {}; this._createEventHandlers(); this._focus = new Focus(this._callbacks) } _extend(Tracker.prototype, { dispose: function() { var that = this; that._focus.dispose(); that._root = that._callbacks = that._focus = that._rootClickEvents = that._$docClickEvents = that._rootZoomEvents = that._$docZoomEvents = that._rootHoverEvents = that._$docHoverEvents = that._rootFocusEvents = that._$docFocusEvents = null; return that }, _createEventHandlers: function() { var that = this; that._rootClickEvents = {}; that._rootClickEvents[EVENTS.start] = function(event) { var isTouch = isTouchEvent(event); if (isTouch && !that._isTouchEnabled) return; event.preventDefault(); var coords = getEventCoords(event); that._clickState = { x: coords.x, y: coords.y, time: _now() } }; that._$docClickEvents = {}; that._$docClickEvents[EVENTS.end] = function(event) { var state = that._clickState; if (!state) return; var isTouch = isTouchEvent(event); if (isTouch && !that._isTouchEnabled) return; if (_now() - state.time <= CLICK_TIME_THRESHOLD) { var coords = getEventCoords(event); if (_abs(coords.x - state.x) <= CLICK_COORD_THRESHOLD && _abs(coords.y - state.y) <= CLICK_COORD_THRESHOLD) that._callbacks[EVENT_CLICK]({ data: $(event.target).data(_DATA_KEY) || {}, x: coords.x, y: coords.y, $event: event }) } that._clickState = null }; that._rootDragEvents = {}; that._rootDragEvents[EVENTS.start] = function(event) { var isTouch = isTouchEvent(event); if (isTouch && !that._isTouchEnabled) return; var coords = getEventCoords(event); that._dragState = { x: coords.x, y: coords.y, data: $(event.target).data(_DATA_KEY) || {} }; if (that._isDragEnabled) that._callbacks[EVENT_START]({ data: that._dragState.data, x: coords.x, y: coords.y }) }; that._$docDragEvents = {}; that._$docDragEvents[EVENTS.move] = function(event) { var state = that._dragState; if (!state) return; var isTouch = isTouchEvent(event); if (isTouch && !that._isTouchEnabled) return; var coords = getEventCoords(event), threshold = isTouch ? DRAG_COORD_THRESHOLD_TOUCH : DRAG_COORD_THRESHOLD_MOUSE; if (state.active || _abs(coords.x - state.x) > threshold || _abs(coords.y - state.y) > threshold) { state.x = coords.x; state.y = coords.y; state.active = true; state.data = $(event.target).data(_DATA_KEY) || {}; if (that._isDragEnabled) that._callbacks[EVENT_MOVE]({ data: state.data, x: coords.x, y: coords.y }) } }; that._$docDragEvents[EVENTS.end] = function(event) { var state = that._dragState; if (!state) return; var isTouch = isTouchEvent(event); if (isTouch && !that._isTouchEnabled) return; that._endDragging() }; that._rootZoomEvents = {}; that._rootZoomEvents[EVENTS.wheel] = function(event) { if (!that._isWheelEnabled) return; event.preventDefault(); if (that._zoomState) return; var delta = event.originalEvent.wheelDelta / 120 || event.originalEvent.detail / -3 || 0; if (delta === 0) return; delta = delta > 0 ? _min(_round(delta) || +1, +4) : _max(_round(delta) || -1, -4); var coords = getEventCoords(event); if (that._isZoomEnabled) that._callbacks[EVENT_ZOOM]({ delta: delta, x: coords.x, y: coords.y }); that._zoomState = setTimeout(function() { that._zoomState = null }, 50) }; that._rootZoomEvents[EVENTS.start] = function(event) { var isTouch = isTouchEvent(event); if (!isTouch || !that._isTouchEnabled) return; var state = that._zoomState = that._zoomState || {}; if (state.pointer1 && state.pointer2) return; var coords; if (state.pointer1 === undefined) { state.pointer1 = getPointerId(event) || 0; coords = getMultitouchEventCoords(event, state.pointer1); state.x1 = state.x1_0 = coords.x; state.y1 = state.y1_0 = coords.y } if (state.pointer2 === undefined) { var pointer2 = getPointerId(event) || 1; if (pointer2 !== state.pointer1) { coords = getMultitouchEventCoords(event, pointer2); if (coords) { state.x2 = state.x2_0 = coords.x; state.y2 = state.y2_0 = coords.y; state.pointer2 = pointer2; state.ready = true; that._endDragging() } } } }; that._$docZoomEvents = {}; that._$docZoomEvents[EVENTS.move] = function(event) { var state = that._zoomState; if (!state) return; var isTouch = isTouchEvent(event); if (!isTouch || !that._isTouchEnabled) return; var coords; if (state.pointer1 !== undefined) { coords = getMultitouchEventCoords(event, state.pointer1); if (coords) { state.x1 = coords.x; state.y1 = coords.y } } if (state.pointer2 !== undefined) { coords = getMultitouchEventCoords(event, state.pointer2); if (coords) { state.x2 = coords.x; state.y2 = coords.y } } }; that._$docZoomEvents[EVENTS.end] = function(event) { var state = that._zoomState; if (!state) return; var isTouch = isTouchEvent(event); if (!isTouch || !that._isTouchEnabled) return; if (state.ready) { var startDistance = getDistance(state.x1_0, state.y1_0, state.x2_0, state.y2_0), currentDistance = getDistance(state.x1, state.y1, state.x2, state.y2); if (that._isZoomEnabled) that._callbacks[EVENT_ZOOM]({ ratio: currentDistance / startDistance, x: (state.x1_0 + state.x2_0) / 2, y: (state.y1_0 + state.y2_0) / 2 }) } that._zoomState = null }; that._rootHoverEvents = {}; that._rootHoverEvents[EVENTS.over] = function(event) { if (that._hoverTarget === event.target) return; var isTouch = isTouchEvent(event); if (isTouch) return; var data = $(event.target).data(_DATA_KEY); if (!data) return; that._hoverTarget && that._endHovering(); that._hoverTarget = event.target; that._hoverState = {data: data}; that._callbacks[EVENT_HOVER_ON]({data: data}) }; that._$docHoverEvents = {}; that._$docHoverEvents[EVENTS.out] = function(event) { var state = that._hoverState; if (!state) return; var isTouch = isTouchEvent(event); if (isTouch) return; var data = $(event.target).data(_DATA_KEY); if (!data) return; that._endHovering() }; that._rootFocusEvents = {}; that._rootFocusEvents[EVENTS.start] = function(event) { var isTouch = isTouchEvent(event); if (!isTouch || !that._isTouchEnabled) return; var data = $(event.target).data(_DATA_KEY); if (!data) return; that._focus.turnOff(FOCUS_OFF_DELAY_TOUCH); that._focus.turnOn(event.target, data, getEventCoords(event), FOCUS_ON_DELAY_TOUCH); that._skip$docEvent = true }; that._rootFocusEvents[EVENTS.over] = function(event) { if (that._focusTarget === event.target) return; that._focusTarget = event.target; var isTouch = isTouchEvent(event); if (isTouch) return; var data = $(event.target).data(_DATA_KEY); if (!data) return; if (that._focusTarget) that._focus.turnOff(FOCUS_OFF_DELAY_MOUSE); var coords = getEventCoords(event); if (that._focus.active) that._focus.move(event.target, data, coords); else that._focus.turnOn(event.target, data, coords, FOCUS_ON_DELAY_MOUSE) }; that._$docFocusEvents = {}; that._$docFocusEvents[EVENTS.start] = function(event) { that._focusTarget = event.target; var isTouch = isTouchEvent(event); if (!isTouch || !that._isTouchEnabled) return; if (!that._skip$docEvent) that._focus.turnOff(FOCUS_OFF_DELAY_TOUCH); that._skip$docEvent = null }; that._$docFocusEvents[EVENTS.move] = function(event) { if (that._focus.disabled) return; if (that._focusTarget !== event.target) return; var isTouch = isTouchEvent(event); if (isTouch && !that._isTouchEnabled) return; var data = $(event.target).data(_DATA_KEY); if (!data) return; var coords = getEventCoords(event); if (isTouch) { if (that._dragState && that._dragState.active || that._zoomState && that._zoomState.ready) that._focus.cancel() } else if (that._focus.active) if (that._dragState && that._dragState.active) { that._focus.cancel(); that._focus.turnOn(event.target, data, coords, FOCUS_ON_DELAY_MOUSE * 4) } else that._focus.move(event.target, data, coords); else if (_abs(coords.x - that._focus.x) > FOCUS_COORD_THRESHOLD_MOUSE || _abs(coords.y - that._focus.y) > FOCUS_COORD_THRESHOLD_MOUSE) that._focus.turnOn(event.target, data, coords, FOCUS_ON_DELAY_MOUSE) }; that._$docFocusEvents[EVENTS.end] = function(event) { if (that._focus.disabled) return; var isTouch = isTouchEvent(event); if (!isTouch || !that._isTouchEnabled) return; that._focusTarget = null; if (!that._focus.active) that._focus.turnOff(FOCUS_OFF_DELAY_TOUCH); else if (that._focus.changing) that._focus.cancel() }; that._$docFocusEvents[EVENTS.out] = function(event) { if (that._focus.disabled) return; var isTouch = isTouchEvent(event); if (isTouch) return; that._focusTarget = null; var data = $(event.target).data(_DATA_KEY); if (!data) return; that._focus.turnOff(FOCUS_OFF_DELAY_MOUSE) } }, _endDragging: function() { var that = this, state = that._dragState; that._dragState = null; if (state && that._isDragEnabled) that._callbacks[EVENT_END]({ data: state.data, x: state.x, y: state.y }) }, _endHovering: function() { var that = this, state = that._hoverState; that._hoverState = that._hoverTarget = null; if (state) that._callbacks[EVENT_HOVER_OFF]({data: state.data}) }, reset: function() { var that = this; that._clickState = null; that._endDragging(); that._endHovering(); that._focus.cancel(); that._focusTarget = null; return that }, setCallbacks: function(callbacks) { _extend(this._callbacks, callbacks); return this }, setOptions: function(options) { this._isTouchEnabled = options.touchEnabled === undefined || !!options.touchEnabled; this._isWheelEnabled = options.wheelEnabled === undefined || !!options.wheelEnabled; this._isDragEnabled = options.dragAndZoomEnabled === undefined || !!options.dragAndZoomEnabled; this._isZoomEnabled = options.dragAndZoomEnabled === undefined || !!options.dragAndZoomEnabled; return this }, clean: function() { var that = this; if (that._isTouchEnabled) { that._root.applySettings({style: { 'touch-action': '', '-ms-touch-action': '', '-webkit-user-select': '' }}); that._root.off(_addNamespace('MSHoldVisual', _NAME)).off(_addNamespace('contextmenu', _NAME)) } that._detachEventHandlers(); that.reset(); return that }, render: function() { var that = this; if (that._isTouchEnabled) { that._root.applySettings({style: { 'touch-action': 'none', '-ms-touch-action': 'none', '-webkit-user-select': 'none' }}); that._root.on(_addNamespace('MSHoldVisual', _NAME), function(event) { event.preventDefault() }).on(_addNamespace('contextmenu', _NAME), function(event) { isTouchEvent(event) && event.preventDefault() }) } that._attachEventHandlers(); return that }, _attachEventHandlers: function() { var that = this; that._root.on(that._rootClickEvents).on(that._rootDragEvents).on(that._rootZoomEvents).on(that._rootHoverEvents).on(that._rootFocusEvents); $doc.on(that._$docClickEvents).on(that._$docDragEvents).on(that._$docZoomEvents).on(that._$docHoverEvents).on(that._$docFocusEvents) }, _detachEventHandlers: function() { var that = this; that._root.off(that._rootClickEvents).off(that._rootDragEvents).off(that._rootZoomEvents).off(that._rootHoverEvents).off(that._rootFocusEvents); $doc.off(that._$docClickEvents).off(that._$docDragEvents).off(that._$docZoomEvents).off(that._$docHoverEvents).off(that._$docFocusEvents) } }); function Focus(callbacks) { this._callbacks = callbacks; this.disabled = true } _extend(Focus.prototype, { dispose: function() { var that = this; clearTimeout(that._onTimer); clearTimeout(that._offTimer); that._callbacks = that._onTimer = that._offTimer = that.active = that._data = null }, _createCallback: function(target, data, coords) { var that = this; return function() { if (that.active === target) { that._callbacks[EVENT_FOCUS_MOVE]({ data: that._data, x: coords.x, y: coords.y }); onCheck(true) } else that._callbacks[EVENT_FOCUS_ON]({ data: data, x: coords.x, y: coords.y }, onCheck) }; function onCheck(result) { that.changing = null; that.disabled = !result; if (result) { that._data = data; that.active = target; clearTimeout(that._offTimer); that._offTimer = null } } }, turnOn: function(target, data, coords, timeout) { var that = this; that.disabled = false; that.x = coords.x; that.y = coords.y; clearTimeout(that._onTimer); that.changing = true; that._onTimer = setTimeout(that._createCallback(target, data, coords), timeout) }, move: function(target, data, coords) { this.x = coords.x; this.y = coords.y; this._createCallback(target, data, coords)() }, turnOff: function(timeout) { var that = this; if (that.active) that._offTimer = that._offTimer || setTimeout(function() { that._offTimer = null; that._callbacks[EVENT_FOCUS_OFF]({data: that._data}); that._data = that.active = null; that.disabled = true }, timeout); else { clearTimeout(that._onTimer); that._onTimer = null; that.disabled = true } }, cancel: function() { var that = this; if (that.active) that._callbacks[EVENT_FOCUS_OFF]({data: that._data}); clearTimeout(that._onTimer); clearTimeout(that._offTimer); that._data = that.active = that._onTimer = that._offTimer = null; that.disabled = true } }); DX.viz.map._tests.Tracker = Tracker; DX.viz.map._tests._DEBUG_forceEventMode = function(mode) { setupEvents(mode) }; DX.viz.map._tests.Focus = Focus; DX.viz.map._tests._DEBUG_stubFocusType = function(focusType) { Focus = focusType }; DX.viz.map._tests._DEBUG_restoreFocusType = function() { Focus = DX.viz.map._tests.Focus }; DX.viz.map.Map.prototype._factory.createTracker = function(parameters) { return new Tracker(parameters) }; function getDistance(x1, y1, x2, y2) { return _sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) } function isTouchEvent(event) { var type = event.originalEvent.type, pointerType = event.originalEvent.pointerType; return /^touch/.test(type) || /^MSPointer/.test(type) && pointerType !== 4 || /^pointer/.test(type) && pointerType !== 'mouse' } function selectItem(flags, items) { var i = 0, ii = flags.length, item; for (; i < ii; ++i) if (flags[i]) { item = items[i]; break } return _addNamespace(item || items[i], _NAME) } function setupEvents() { var flags = [navigator.pointerEnabled, navigator.msPointerEnabled, 'ontouchstart' in window]; if (arguments.length) flags = [arguments[0] === 'pointer', arguments[0] === 'MSPointer', arguments[0] === 'touch']; EVENTS = { start: selectItem(flags, ['pointerdown', 'MSPointerDown', 'touchstart mousedown', 'mousedown']), move: selectItem(flags, ['pointermove', 'MSPointerMove', 'touchmove mousemove', 'mousemove']), end: selectItem(flags, ['pointerup', 'MSPointerUp', 'touchend mouseup', 'mouseup']), over: selectItem(flags, ['pointerover', 'MSPointerOver', 'mouseover', 'mouseover']), out: selectItem(flags, ['pointerout', 'MSPointerOut', 'mouseout', 'mouseout']), wheel: selectItem([], ['mousewheel DOMMouseScroll']) } } function getEventCoords(event) { var originalEvent = event.originalEvent, touch = originalEvent.touches && originalEvent.touches[0] || {}; return { x: touch.pageX || originalEvent.pageX || event.pageX, y: touch.pageY || originalEvent.pageY || event.pageY } } function getPointerId(event) { return event.originalEvent.pointerId } function getMultitouchEventCoords(event, pointerId) { var originalEvent = event.originalEvent; if (originalEvent.pointerId !== undefined) originalEvent = originalEvent.pointerId === pointerId ? originalEvent : null; else originalEvent = originalEvent.touches[pointerId]; return originalEvent ? { x: originalEvent.pageX || event.pageX, y: originalEvent.pageY || event.pageY } : null } })(DevExpress, jQuery); /*! Module viz-vectormap, file themeManager.js */ (function(DX, $, undefined) { var _Number = Number, _extend = $.extend, _each = $.each; var ThemeManager = DX.viz.core.BaseThemeManager.inherit({ _themeSection: 'map', _initializeTheme: function() { var that = this; that._initializeFont(that._theme.marker.font); that._initializeFont(that._theme.tooltip.font); that._initializeFont(that._theme.legend.font); that._initializeFont(that._theme.loadingIndicator.font) }, dispose: function() { var that = this; that.callBase.apply(that, arguments); that._areasPalette = that._markersPalette = null; return that }, getBackgroundSettings: function(options) { var theme = this._theme.background, merged = _extend({}, theme, options); return { strokeWidth: merged.borderWidth, stroke: merged.borderColor, fill: merged.color } }, getCommonAreaSettings: function(options) { var settings = _extend({}, this._theme.area, options); this._areasPalette = new DX.viz.core.GradientPalette(settings.palette, settings.paletteSize); this._DEBUG_areasPalette = this._areasPalette; return settings }, getAreaSettings: function(commonSettings, options) { options = options || {}; var settings = _extend({}, commonSettings, options); settings.borderWidth = _Number(settings.borderWidth) || 0; settings.borderColor = settings.borderColor || null; if (options.color === undefined && options.paletteIndex >= 0) settings.color = this._areasPalette.getColor(options.paletteIndex); settings.color = settings.color || null; settings.hoveredBorderWidth = _Number(settings.hoveredBorderWidth) || settings.borderWidth; settings.hoveredBorderColor = settings.hoveredBorderColor || settings.borderColor; settings.hoveredColor = settings.hoveredColor || settings.color; settings.selectedBorderWidth = _Number(settings.selectedBorderWidth) || settings.borderWidth; settings.selectedBorderColor = settings.selectedBorderColor || settings.borderColor; settings.selectedColor = settings.selectedColor || settings.color; return settings }, getCommonMarkerSettings: function(options) { options = options || {}; var theme = this._theme.marker, allSettings = {}; _each(theme, function(name) { if (name[0] === '_') { var partialTheme = theme[name] || {}, partialOptions = options[name] || {}, settings = _extend({}, theme, partialTheme, options, partialOptions); settings.font = _extend({}, theme.font, partialTheme.font, options.font, partialOptions.font); allSettings[name.substr(1)] = settings } }); this._markersPalette = new DX.viz.core.Palette(options.palette || theme.palette, { stepHighlight: 50, theme: this.themeName() }); this._DEBUG_markersPalette = this._markersPalette; return allSettings }, getMarkerSettings: function(commonSettings, options, type) { options = options || {}; var common = commonSettings[type], settings = _extend({}, common, options); settings.font = _extend({}, common.font, options.font); settings.borderWidth = _Number(settings.borderWidth) || 0; settings.borderColor = settings.borderColor || null; settings.color = settings.color || null; settings.opacity = settings.opacity || null; settings.hoveredBorderWidth = _Number(settings.hoveredBorderWidth) || settings.borderWidth; settings.hoveredBorderColor = settings.hoveredBorderColor || settings.borderColor; settings.hoveredColor = settings.hoveredColor || settings.color; settings.hoveredOpacity = settings.hoveredOpacity || settings.opacity; settings.selectedBorderWidth = _Number(settings.selectedBorderWidth) || settings.borderWidth; settings.selectedBorderColor = settings.selectedBorderColor || settings.borderColor; settings.selectedColor = settings.selectedColor || settings.color; settings.selectedOpacity = settings.selectedOpacity || settings.opacity; return settings }, getMarkerColors: function(count) { var i = 0, colors = []; for (; i < count; ++i) colors.push(this._markersPalette.getNextColor()); this._markersPalette.reset(); return colors }, getControlBarSettings: function(options) { var theme = this._theme.controlBar, merged = _extend({}, theme, options); return _extend({}, options, {shape: { strokeWidth: merged.borderWidth, stroke: merged.borderColor, fill: merged.color }}) }, getLoadIndicatorSettings: function(options) { var theme = this._theme.loadingIndicator; return _extend(true, {}, theme, options) }, getTooltipSettings: function(options) { var theme = this._theme.tooltip, merged = _extend({}, theme, options), borderOptions = _extend({}, theme.border, options && options.border, options && !options.border && {color: options.borderColor}); return _extend({}, options, { color: merged.color, border: borderOptions, text: { strokeWidth: 0, stroke: 'none', fill: 'none', font: _extend({}, theme.font, merged.font), 'class': 'dxm-tooltip-text' }, arrowLength: merged.arrowLength, paddingLeftRight: merged.paddingLeftRight, paddingTopBottom: merged.paddingTopBottom, opacity: merged.opacity, shadow: _extend({}, theme.shadow, merged.shadow) }) }, getLegendSettings: function(options) { return _extend(true, {}, this._theme.legend, options) }, getLegendItemSettings: function(item) { var color = item.color; if (color === undefined && item.paletteIndex >= 0) color = this._areasPalette.getColor(item.paletteIndex); return { text: item.text, color: color } }, patchRtlSettings: function(rtlEnabledOption) { var theme = this._theme; if (rtlEnabledOption || theme.rtlEnabled && rtlEnabledOption !== false) $.extend(true, theme, theme._rtl) } }); DX.viz.map._tests.ThemeManager = ThemeManager; DX.viz.map.Map.prototype._factory.createThemeManager = function() { return new ThemeManager } })(DevExpress, jQuery); /*! Module viz-vectormap, file mapItemsManager.js */ (function(DX, $, undefined) { var _String = String, _isString = DX.utils.isString, _isArray = DX.utils.isArray, _isFunction = DX.utils.isFunction, _extend = $.extend, _each = $.each, _map = $.map; var SELECTION_MODE_NONE = 'none', SELECTION_MODE_SINGLE = 'single', SELECTION_MODE_MULTIPLE = 'multiple'; var MapItemsManager = DX.Class.inherit({ _rootClass: null, ctor: function(parameters) { var that = this; that._container = parameters.container; that._renderer = parameters.renderer; that._projection = parameters.projection; that._themeManager = parameters.themeManager; that._tracker = parameters.tracker; that._ready = parameters.ready; that._root = that._renderer.createGroup({'class': that._rootClass}); that._items = []; that._context = { renderer: that._renderer, root: that._root, projection: that._projection, selectItem: function(index, state, noCallback) { that.selectItem(index, state, noCallback) } } }, dispose: function() { var that = this; that._container = that._renderer = that._projection = that._themeManager = that._tracker = that._ready = that._root = that._source = that._context = null; return that }, clean: function() { var that = this; that._rendered = false; that._root.detach(); that._customizeCallback = that._clickCallback = that._selectionChangedCallback = null; that._destroyItems(); return that }, render: function(options) { options = options || {}; var that = this; that._rendered = true; that._customizeCallback = _isFunction(options.customize) ? options.customize : null; that._clickCallback = _isFunction(options.click) ? options.click : null; that._selectionChangedCallback = _isFunction(options.selectionChanged) ? options.selectionChanged : null; that._hoverEnabled = 'hoverEnabled' in options ? !!options.hoverEnabled : true; var selectionMode = _String(options.selectionMode).toLowerCase(); that._selectionMode = selectionMode === SELECTION_MODE_NONE || selectionMode === SELECTION_MODE_SINGLE || selectionMode === SELECTION_MODE_MULTIPLE ? selectionMode : SELECTION_MODE_SINGLE; that._root.append(that._container); if (that._source !== null) that._createItems(); return that }, _destroyItems: function() { var that = this; that._root.clear(); _each(that._items, function(_, item) { item.clean().dispose() }); that._items = []; that._selectedItems = null }, _getItemSettings: null, _createItem: null, _isItemSelected: null, _arrangeItems: null, _createItems: function() { var that = this; that._selectedItems = that._selectionMode === SELECTION_MODE_MULTIPLE ? {} : null; var selectedList = []; _each(_isArray(that._source) ? that._source : [], function(i, dataItem) { dataItem = dataItem || {}; var settings = that._customizeCallback && that._customizeCallback.call(dataItem, dataItem) || {}; var source = { item: dataItem, coords: that._getItemCoordinates(dataItem), attrs: that._getItemAttributes(dataItem) }; settings = that._getItemSettings(source, settings); var item = that._createItem(settings); item.init(that._context, source, i).render(settings).locate(); that._items.push(item); if (that._isItemSelected(source, settings)) selectedList.push(i) }); if (that._selectionMode !== SELECTION_MODE_NONE && selectedList.length > 0) { if (that._selectionMode === SELECTION_MODE_SINGLE) selectedList = [selectedList[selectedList.length - 1]]; _each(selectedList, function(_, index) { that.selectItem(index, true, true) }) } that._arrangeItems(); that._ready && that._ready() }, _processSource: null, setData: function(data) { var that = this; that._source = null; if (_isString(data)) $.getJSON(data).done(updateSource).fail(function(_0, _1, error) { updateSource(null) }); else updateSource(data); return that; function updateSource(source) { that._source = that._processSource(source) || 0; if (that._rendered) { that._tracker.reset(); that._destroyItems(); that._createItems() } } }, transform: function(transform) { this._root.applySettings(transform); return this }, redraw: function() { _each(this._items, function(_, item) { item.locate() }); return this }, hoverItem: function(index, state) { if (this._hoverEnabled) this._items[index].setHovered(!!state); return this }, _raiseSelectionChanged: function(item) { var that = this; if (that._selectionChangedCallback) setTimeout(function() { that._selectionChangedCallback && that._selectionChangedCallback.call(item.proxy, item.proxy) }, 0) }, selectItem: function(index, state, noCallback) { var that = this; if (that._selectionMode === SELECTION_MODE_NONE) return that; var item = that._items[index], previous = item.selected; item.setSelected(!!state); if (item.selected === previous) return that; if (!noCallback) that._raiseSelectionChanged(item); if (item.selected && that._selectionMode === SELECTION_MODE_SINGLE && that._selectedItems) { that._selectedItems.setSelected(false); if (!noCallback) that._raiseSelectionChanged(that._selectedItems); that._selectedItems = null } if (that._selectionMode === SELECTION_MODE_SINGLE) that._selectedItems = item.selected ? item : null; else if (item.selected) that._selectedItems[index] = item; else delete that._selectedItems[index]; return that }, clearSelection: function() { var that = this; if (that._selectionMode === SELECTION_MODE_NONE) return that; if (that._selectionMode === SELECTION_MODE_SINGLE) { if (that._selectedItems) { that._selectedItems.setSelected(false); that._raiseSelectionChanged(that._selectedItems); that._selectedItems = null } } else _each(that._selectedItems, function(i, item) { item.setSelected(false); that._raiseSelectionChanged(item); delete that._selectedItems[i] }); return that }, raiseClick: function(index, $event) { var that = this, item = that._items[index]; if (that._clickCallback) setTimeout(function() { that._clickCallback && that._clickCallback.call(item.proxy, item.proxy, $event) }, 0); return that }, getProxyItems: function() { return _map(this._items, function(item) { return item.proxy }) }, getProxyItem: function(index) { return this._items[index].proxy } }); DX.viz.map._internal.mapItemBehavior = { init: function(ctx, src, index) { var that = this; that._ctx = ctx; that._src = src; that._coords = that._project(ctx.projection, src.coords); that._data = { index: index, type: that._type }; that.hovered = that.selected = false; that.proxy = createProxy(that, src.attrs, ctx.selectItem); that.proxy.type = that._type; that._init(); return that }, dispose: function() { disposeItem(this.proxy); disposeItem(this); return this }, locate: function() { var that = this; that._locate(that._transform(that._ctx.projection, that._coords)); return that }, clean: function() { this._root.detach(); return this }, render: function(settings) { var that = this; that._root = that._createRoot().append(that._ctx.root); that._render(settings); return that }, setHovered: function(state) { var that = this; that.hovered = !!state; that._onHover(); if (!that.selected) if (that.hovered) that._setHoveredState(); else that._setDefaultState(); return that }, setSelected: function(state) { var that = this; that.selected = !!state; if (that.selected) that._setSelectedState(); else that.setHovered(that.hovered); return that } }; function createProxy(item, attributes, selectItem) { attributes = attributes || {}; return { attribute: function(name) { return name !== undefined ? attributes[name] : _extend({}, attributes) }, selected: function(state, _noEvent) { if (state !== undefined) { if (item.selected !== !!state) selectItem(item._data.index, !!state, _noEvent); return this } else return item.selected } } } function disposeItem(item) { _each(item, function(name) { item[name] = null }) } DX.viz.map._tests.MapItemsManager = MapItemsManager; DX.viz.map.Map.prototype._factory.MapItemsManager = MapItemsManager })(DevExpress, jQuery); /*! Module viz-vectormap, file areasManager.js */ (function(DX, $, undefined) { var _DATA_KEY = DX.viz.map.__DATA_KEY; var AreasManager = DX.viz.map.Map.prototype._factory.MapItemsManager.inherit({ _rootClass: 'dxm-areas', _processSource: function(source) { var isGeoJson = source && source.type === 'FeatureCollection'; this._getItemCoordinates = isGeoJson ? getCoordinatesGeoJson : getCoordinatesDefault; this._getItemAttributes = isGeoJson ? getAttributesGeoJson : getAttributesDefault; return isGeoJson ? source.features : source }, clean: function() { this._commonSettings = null; return this.callBase.apply(this, arguments) }, render: function(options) { this._commonSettings = this._themeManager.getCommonAreaSettings(options || {}); return this.callBase.apply(this, arguments) }, _getItemSettings: function(_, options) { return this._themeManager.getAreaSettings(this._commonSettings, options) }, _createItem: function() { return new Area }, _isItemSelected: function(source, settings) { return source.attrs.isSelected || settings.isSelected }, _arrangeItems: $.noop }); function getCoordinatesDefault(dataItem) { return dataItem.coordinates } function getCoordinatesGeoJson(dataItem) { var coordinates; if (dataItem.geometry) { var type = dataItem.geometry.type; coordinates = dataItem.geometry.coordinates; if (coordinates && (type === 'Polygon' || type === 'MultiPolygon')) type === 'MultiPolygon' && (coordinates = [].concat.apply([], coordinates)); else coordinates = undefined } return coordinates } function getAttributesDefault(dataItem) { return dataItem.attributes } function getAttributesGeoJson(dataItem) { return dataItem.properties } function Area(){} $.extend(Area.prototype, DX.viz.map._internal.mapItemBehavior, { _type: 'area', _project: function(projection, coords) { return projection.projectArea(coords) }, _init: $.noop, _createRoot: function() { return this._ctx.renderer.createSimplePath() }, _render: function(settings) { var that = this; that._styles = { normal: { 'class': 'dxm-area', stroke: settings.borderColor, strokeWidth: settings.borderWidth, fill: settings.color }, hovered: { 'class': 'dxm-area dxm-area-hovered', stroke: settings.hoveredBorderColor, strokeWidth: settings.hoveredBorderWidth, fill: settings.hoveredColor }, selected: { 'class': 'dxm-area dxm-area-selected', stroke: settings.selectedBorderColor, strokeWidth: settings.selectedBorderWidth, fill: settings.selectedColor } }; that._root.applySettings(that._styles.normal).data(_DATA_KEY, that._data); return that }, _transform: function(projection, coords) { return projection.getAreaCoordinates(coords) }, _locate: function(coords) { this._root.applySettings({d: coords}) }, _onHover: $.noop, _setDefaultState: function() { this._root.applySettings(this._styles.normal).toBackground() }, _setHoveredState: function() { this._root.applySettings(this._styles.hovered).toForeground() }, _setSelectedState: function() { this._root.applySettings(this._styles.selected).toForeground() } }); DX.viz.map._tests.AreasManager = AreasManager; DX.viz.map._tests.Area = Area; DX.viz.map.Map.prototype._factory.createAreasManager = function(parameters) { return new AreasManager(parameters) } })(DevExpress, jQuery); /*! Module viz-vectormap, file markersManager.js */ (function(DX, $, undefined) { var _Number = Number, _String = String, _isFinite = isFinite, _round = Math.round, _max = Math.max, _min = Math.min, _extend = $.extend, _isArray = DX.utils.isArray, _processCircleSettings = DX.viz.renderers.processCircleSettings; var CLASS_DEFAULT = 'dxm-marker', CLASS_HOVERED = 'dxm-marker dxm-marker-hovered', CLASS_SELECTED = 'dxm-marker dxm-marker-selected', TRACKER_SETTINGS = { stroke: 'none', strokeWidth: 0, fill: '#000000', opacity: 0.0001 }; var _DATA_KEY = DX.viz.map.__DATA_KEY; var DEFAULT_MARKER_TYPE = 'dot', MARKER_TYPES = {}; var MarkersManager = DX.viz.map.Map.prototype._factory.MapItemsManager.inherit({ _rootClass: 'dxm-markers', ctor: function() { var that = this; that.callBase.apply(that, arguments); that._context.getColors = function(count) { return that._themeManager.getMarkerColors(count) }; that._filter = that._renderer.createFilter('shadow').applySettings({ x: '-40%', y: '-40%', width: '180%', height: '200%', color: '#000000', opacity: 0.2, dx: 0, dy: 1, blur: 1 }).append() }, dispose: function() { this._filter.dispose(); this._filter = null; return this.callBase.apply(this, arguments) }, _getItemCoordinates: function(dataItem) { return dataItem.coordinates }, _getItemAttributes: function(dataItem) { return dataItem.attributes }, _processSource: function(source) { return source }, clean: function() { var that = this; that._commonSettings = null; return that.callBase.apply(that, arguments) }, render: function(options) { var that = this; that._commonSettings = that._themeManager.getCommonMarkerSettings(options); that._commonSettings._filter = that._filter.ref; that._commonType = parseMarkerType(options && options.type); return that.callBase.apply(that, arguments) }, _arrangeBubbles: function() { var markers = this._items, bubbles = [], i, ii = markers.length, marker, values = []; for (i = 0; i < ii; ++i) { marker = markers[i]; if (marker.type === 'bubble') { bubbles.push(marker); if (marker.value !== null) values.push(marker.value) } } var minValue = _min.apply(null, values), maxValue = _max.apply(null, values), deltaValue = maxValue - minValue || 1; for (i = 0, ii = bubbles.length; i < ii; ++i) { marker = bubbles[i]; marker.setSize(marker.value !== null ? (marker.value - minValue) / deltaValue : 0) } }, _getItemSettings: function(source, options) { var type = parseMarkerType(source.item.type, this._commonType), style = _extend(source.item.style, options); style = this._themeManager.getMarkerSettings(this._commonSettings, style, type); _extend(source.item, {text: source.item.text || style.text}); style._type = type; return style }, _createItem: function(settings) { return new MARKER_TYPES[settings._type] }, _isItemSelected: function(source, settings) { return source.item.isSelected || settings.isSelected }, _arrangeItems: function() { this._arrangeBubbles() }, addMarker: function(dataItem) { var that = this, index = that._items.length, marker = that._createItem(dataItem, index); that._items.push(marker); if (marker._selected) that.selectItem(index, true, true); that._arrangeItems(); return that } }); var baseMarkerBehavior = _extend({}, DX.viz.map._internal.mapItemBehavior, { _type: 'marker', _project: function(projection, coords) { return projection.projectPoint(coords) }, _init: function() { this.proxy.coordinates = createCoordinatesGetter(this._src.coords); this.proxy.text = this._src.item.text }, _createRoot: function() { return this._ctx.renderer.createGroup() }, _render: function(settings) { var that = this; that._root.applySettings({'class': CLASS_DEFAULT}); that._create(settings, that._ctx.renderer, that._root); that._createText(settings, that._ctx.renderer, that._root); return that }, _createText: function(settings, renderer, root) { var that = this; if (!that._src.item.text) return; var rootbox = that._root.getBBox(), text = renderer.createText(that._src.item.text, 0, 0, { align: 'center', font: settings.font }).append(root), textBox = text.getBBox(), x = _round(-textBox.x + rootbox.width / 2) + 2, y = _round(-textBox.y - textBox.height / 2) - 1; text.applySettings({ x: x, y: y }); renderer.createRect(x + textBox.x - 1, y + textBox.y - 1, textBox.width + 2, textBox.height + 2, 0, TRACKER_SETTINGS).data(_DATA_KEY, that._data).append(root) }, _transform: function(projection, coords) { return projection.getPointCoordinates(coords) }, _locate: function(coords) { this._root.applySettings({ translateX: coords.x, translateY: coords.y }) }, _onHover: function() { this.hovered && this._root.toForeground() }, _setDefaultState: function() { this._root.applySettings({'class': CLASS_DEFAULT}).toBackground(); this._applyDefault() }, _setHoveredState: function() { this._root.applySettings({'class': CLASS_HOVERED}); this._applyHovered() }, _setSelectedState: function() { this._root.applySettings({'class': CLASS_SELECTED}).toForeground(); this._applySelected() } }); function createCoordinatesGetter(coordinates) { return function() { return [_Number(coordinates[0]), _Number(coordinates[1])] } } function DotMarker(){} _extend(DotMarker.prototype, baseMarkerBehavior, { type: 'dot', _create: function(style, renderer, root) { var that = this, size = style.size > 0 ? _Number(style.size) : 0, hoveredSize = size, selectedSize = size + (style.selectedStep > 0 ? _Number(style.selectedStep) : 0), hoveredBackSize = hoveredSize + (style.backStep > 0 ? _Number(style.backStep) : 0), selectedBackSize = selectedSize + (style.backStep > 0 ? _Number(style.backStep) : 0), settings = _processCircleSettings(0, 0, size, style.borderWidth); that._dotDefault = { cx: settings.cx, cy: settings.cy, r: settings.r, stroke: style.borderColor, strokeWidth: style.borderWidth, fill: style.color, filter: style.shadow ? style._filter : null }; that._dotHovered = { cx: settings.cx, cy: settings.cy, r: hoveredSize / 2, stroke: style.hoveredBorderColor, strokeWidth: style.hoveredBorderWidth, fill: style.hoveredColor }; that._dotSelected = { cx: settings.cx, cy: settings.cy, r: selectedSize / 2, stroke: style.selectedBorderColor, strokeWidth: style.selectedBorderWidth, fill: style.selectedColor }; that._backDefault = { cx: settings.cx, cy: settings.cy, r: settings.r, stroke: 'none', strokeWidth: 0, fill: style.backColor, opacity: style.backOpacity }; that._backHovered = { cx: settings.cx, cy: settings.cy, r: hoveredBackSize / 2, stroke: 'none', strokeWidth: 0, fill: style.backColor, opacity: style.backOpacity }; that._backSelected = { cx: settings.cx, cy: settings.cy, r: selectedBackSize / 2, stroke: 'none', strokeWidth: 0, fill: style.backColor, opacity: style.backOpacity }; that._back = renderer.createCircle().applySettings(that._backDefault).data(_DATA_KEY, that._data).append(root); that._dot = renderer.createCircle().applySettings(that._dotDefault).data(_DATA_KEY, that._data).append(root) }, _destroy: function() { this._back = this._dot = null }, _applyDefault: function() { this._back.applySettings(this._backDefault); this._dot.applySettings(this._dotDefault) }, _applyHovered: function() { this._back.applySettings(this._backHovered); this._dot.applySettings(this._dotHovered) }, _applySelected: function() { this._back.applySettings(this._backSelected); this._dot.applySettings(this._dotSelected) } }); function BubbleMarker(){} _extend(BubbleMarker.prototype, baseMarkerBehavior, { type: 'bubble', _create: function(style, renderer, root) { var that = this; that._minSize = style.minSize > 0 ? _Number(style.minSize) : 0; that._maxSize = style.maxSize > that._minSize ? _Number(style.maxSize) : that._minSize; that.value = _isFinite(that._src.item.value) ? _Number(that._src.item.value) : null; that._default = { stroke: style.borderColor, strokeWidth: style.borderWidth, fill: style.color, opacity: style.opacity }; that._hovered = { stroke: style.hoveredBorderColor, strokeWidth: style.hoveredBorderWidth, fill: style.hoveredColor, opacity: style.hoveredOpacity }; that._selected = { stroke: style.selectedBorderColor, strokeWidth: style.selectedBorderWidth, fill: style.selectedColor, opacity: style.selectedOpacity }; that._bubble = renderer.createCircle(0, 0, style.maxSize / 2).applySettings(that._default).data(_DATA_KEY, that._data).append(root) }, _destroy: function() { this._bubble = null }, _applyDefault: function() { this._bubble.applySettings(this._default) }, _applyHovered: function() { this._bubble.applySettings(this._hovered) }, _applySelected: function() { this._bubble.applySettings(this._selected) }, setSize: function(ratio) { var that = this, settings = _processCircleSettings(0, 0, that._minSize + ratio * (that._maxSize - that._minSize), that._default.strokeWidth); that._default.cx = that._hovered.cx = that._selected.cx = settings.cx; that._default.cy = that._hovered.cy = that._selected.cy = settings.cy; that._default.r = that._hovered.r = that._selected.r = settings.r; that._bubble.applySettings(settings); return that } }); function PieMarker(){} _extend(PieMarker.prototype, baseMarkerBehavior, { type: 'pie', _create: function(style, renderer, root) { var that = this, settings = _processCircleSettings(0, 0, style.size > 0 ? _Number(style.size) : 0, style.borderWidth); that._pieDefault = {opacity: style.opacity}; that._pieHovered = {opacity: style.hoveredOpacity}; that._pieSelected = {opacity: style.selectedOpacity}; that._borderDefault = { stroke: style.borderColor, strokeWidth: style.borderWidth }; that._borderHovered = { stroke: style.hoveredBorderColor, strokeWidth: style.hoveredBorderWidth }; that._borderSelected = { stroke: style.selectedBorderColor, strokeWidth: style.selectedBorderWidth }; var srcValues = that._src.item.values, i = 0, ii = _isArray(srcValues) ? srcValues.length : 0, values = [], value, sum = 0; for (; i < ii; ++i) { value = _Number(srcValues[i]); if (_isFinite(value)) { values.push(value); sum += value } } that._pie = renderer.createGroup(that._pieDefault); var translator = new DX.viz.core.Translator1D(0, sum, 90, 450), startAngle = translator.translate(0), endAngle, colors = that._ctx.getColors(values.length); for (value = 0, i = 0, ii = values.length; i < ii; ++i) { value += values[i]; endAngle = translator.translate(value); renderer.createArc(settings.cx, settings.cy, settings.r, 0, startAngle, endAngle, {fill: colors[i]}).data(_DATA_KEY, that._data).append(that._pie); startAngle = endAngle } that._pie.append(root); that._border = renderer.createCircle(settings.cx, settings.cy, settings.r, that._borderDefault).data(_DATA_KEY, that._data).append(root) }, _destroy: function() { this._pie = this._border = null }, _applyDefault: function() { this._pie.applySettings(this._pieDefault); this._border.applySettings(this._borderDefault) }, _applyHovered: function() { this._pie.applySettings(this._pieHovered); this._border.applySettings(this._borderHovered) }, _applySelected: function() { this._pie.applySettings(this._pieSelected); this._border.applySettings(this._borderSelected) } }); function ImageMarker(){} _extend(ImageMarker.prototype, baseMarkerBehavior, { type: 'image', _create: function(style, renderer, root) { var that = this, size = style.size > 0 ? _Number(style.size) : 0, hoveredSize = size + (style.hoveredStep > 0 ? _Number(style.hoveredStep) : 0), selectedSize = size + (style.selectedStep > 0 ? _Number(style.selectedStep) : 0); that._default = { x: -size / 2, y: -size / 2, width: size, height: size }; that._hovered = { x: -hoveredSize / 2, y: -hoveredSize / 2, width: hoveredSize, height: hoveredSize }; that._selected = { x: -selectedSize / 2, y: -selectedSize / 2, width: selectedSize, height: selectedSize }; that._image = renderer.createImage().applySettings(that._default).applySettings({ href: that._src.item.url, location: 'center' }).append(root); that._tracker = renderer.createRect().applySettings(that._default).applySettings(TRACKER_SETTINGS).data(_DATA_KEY, that._data).append(root) }, _destroy: function() { this._image = this._tracker = null }, _applyDefault: function() { this._image.applySettings(this._default); this._tracker.applySettings(this._default) }, _applyHovered: function() { this._image.applySettings(this._hovered); this._tracker.applySettings(this._hovered) }, _applySelected: function() { this._image.applySettings(this._selected); this._tracker.applySettings(this._selected) } }); MARKER_TYPES['dot'] = DotMarker; MARKER_TYPES['bubble'] = BubbleMarker; MARKER_TYPES['pie'] = PieMarker; MARKER_TYPES['image'] = ImageMarker; function parseMarkerType(type, defaultType) { return MARKER_TYPES[type] && type || defaultType || DEFAULT_MARKER_TYPE } var __originalDefaultMarkerType = DEFAULT_MARKER_TYPE, __originalMarkerTypes = $.extend({}, MARKER_TYPES); DX.viz.map._tests.stubMarkerTypes = function(markerTypes, defaultMarkerType) { DEFAULT_MARKER_TYPE = defaultMarkerType; MARKER_TYPES = markerTypes }; DX.viz.map._tests.restoreMarkerTypes = function() { DEFAULT_MARKER_TYPE = __originalDefaultMarkerType; MARKER_TYPES = __originalMarkerTypes }; DX.viz.map._tests.baseMarkerBehavior = baseMarkerBehavior; DX.viz.map._tests.MarkersManager = MarkersManager; DX.viz.map._tests.DotMarker = DotMarker; DX.viz.map._tests.BubbleMarker = BubbleMarker; DX.viz.map._tests.PieMarker = PieMarker; DX.viz.map._tests.ImageMarker = ImageMarker; DX.viz.map.Map.prototype._factory.createMarkersManager = function(parameters) { return new MarkersManager(parameters) } })(DevExpress, jQuery); DevExpress.MOD_VIZ_VECTORMAP = true } if (!DevExpress.MOD_VIZ_SPARKLINES) { if (!DevExpress.MOD_VIZ_CORE) throw Error('Required module is not referenced: viz-core'); /*! Module viz-sparklines, file baseSparkline.js */ (function($, DX) { var TOOLTIP_MARGIN = 100, TOOLTIP_ARROW_MARGIN = 10, DEFAULT_LINE_SPACING = 6, DEFAULT_EVENTS_DELAY = 200, TOUCH_EVENTS_DELAY = 1000, _extend = $.extend, _abs = Math.abs, _Number = Number, _round = Math.round, core = DX.viz.core, CoreFactory = core.CoreFactory; function DEFAULT_CUSTOMIZE_TOOLTIP(customizeObject) { return {text: customizeObject.valueText.join('
')} } DX.viz.sparklines = {}; DX.viz.sparklines.DEFAULT_CUSTOMIZE_TOOLTIP = DEFAULT_CUSTOMIZE_TOOLTIP; DX.viz.sparklines.BaseSparkline = core.BaseWidget.inherit({ render: function() { this._refresh(); return this }, _rendererType: DX.viz.renderers.Renderer, _clean: function() { if (this._tooltipShown) { this._tooltip.dispose(); this._tooltip = null; this._tooltipShown = null; this._tooltipGroup.clear() } this._tooltipContainer.detach(); this._cleanWidgetElements() }, _optionChanged: function(optionName, value) { if (optionName === 'size' && this._allOptions) { this._clean(); this._canvas = this._calculateCanvas(); this._renderer.resize(this._canvas.width, this._canvas.height); if (!this._isContainerVisible()) return; this._allOptions.size = value; this._redrawWidgetElements(); this._prepareTooltipContainer() } else if (optionName === 'dataSource' && this._allOptions) this._refreshDataSource(); else this.callBase.apply(this, arguments) }, _init: function() { this.callBase(); this._canvas = this._calculateCanvas(); this._renderer = new this._rendererType({ cssClass: this._widgetClass + ' ' + this._widgetClass + '-' + this._widgetType, pathModified: this.option('pathModified'), rtl: this.option('rtlEnabled') }); this._renderer.recreateCanvas(this._canvas.width, this._canvas.height); this._createHtmlElements(); this._createTooltipGroups(); this._initTooltipEvents(); this._drawContainer() }, _dispose: function() { var that = this; that.callBase(); that._disposeWidgetElements(); that._disposeTooltipEvents(); that._renderer.dispose(); that._tooltipRenderer.dispose(); that._translatorX = null; that._translatorY = null; delete that._renderer; delete that._tooltipRenderer; delete that._tooltipTrackerGroup; delete that._tooltipGroup; delete that._tooltipContainer }, _render: function() { var that = this; that._canvas = that._calculateCanvas(); that._renderer.resize(that._canvas.width, that._canvas.height); if (!that._isContainerVisible()) { that._incidentOccured('W2001', [that.NAME]); return } that._prepareOptions(); that._createWidgetElements(); that._drawWidgetElements(); that._drawn() }, _isContainerVisible: function() { var that = this, canvas = that._canvas, enoughWidth = canvas.width - canvas.left - canvas.right > 0, enoughHeight = canvas.height - canvas.top - canvas.bottom > 0; return canvas.height && canvas.width && enoughHeight && enoughWidth }, _createWidgetElements: function() { this._createRange(); this._createTranslator() }, _prepareOptions: function(defaultOptions) { var that = this, userOptions = that.option() || {}, options, defaultTheme, theme; defaultTheme = core.findTheme('default'); defaultTheme = defaultTheme[this._widgetType]; options = _extend(true, {}, defaultOptions, userOptions); if (typeof options.theme === 'string') { theme = core.findTheme(options.theme); theme = theme[this._widgetType] } else theme = options.theme; return _extend(true, {}, defaultTheme, theme, options) }, _calculateCanvas: function() { var that = this, canvas = {}, sizeOptions = that.option('size') || {}, marginOptions = that.option('margin') || {}, defaultSize = that._defaultSize, container = that._element(), width = sizeOptions.width >= 0 ? _Number(sizeOptions.width) : container.width(), height = sizeOptions.height >= 0 ? _Number(sizeOptions.height) : container.height(); if (!width && _Number(sizeOptions.width) !== 0) width = defaultSize.width; if (!height && _Number(sizeOptions.height) !== 0) height = defaultSize.height; return { width: width, height: height, top: _Number(marginOptions.top) || defaultSize.top, bottom: _Number(marginOptions.bottom) || defaultSize.bottom, left: _Number(marginOptions.left) || defaultSize.left, right: _Number(marginOptions.right) || defaultSize.right } }, _createTooltipGroups: function() { var that = this, renderer, root, widgetClass = that._widgetClass; that._tooltipRenderer = renderer = new that._rendererType({ cssClass: widgetClass + ' ' + widgetClass + '-tooltip', pathModified: this.option('pathModified'), rtl: this.option('rtlEnabled') }); renderer.recreateCanvas(1, 1); that._tooltipContainer = $('
'); renderer.draw(that._tooltipContainer[0]); root = renderer.getRoot(); that._tooltipGroup = renderer.createGroup({ 'class': widgetClass + '-tooltip-group', style: {'z-index': '1'} }).append(root); that._tooltipTrackerGroup = renderer.createGroup({'class': widgetClass + '-tooltip-tracker-group'}).append(root); that._tooltipTracker = that._createTooltipTracker().append(that._tooltipTrackerGroup) }, _createTooltipTracker: function() { return this._tooltipRenderer.createRect(0, 0, 0, 0, 0, { fill: 'grey', opacity: 0 }) }, _initTooltipEvents: function() { var that = this, data = { widget: that, container: that._tooltipTracker }; that._showTooltipCallback = function() { that._showTooltipTimeout = null; if (!that._tooltipShown) { that._tooltipShown = true; that._showTooltip() } that._DEBUG_showCallback && that._DEBUG_showCallback() }; that._hideTooltipCallback = function() { that._hideTooltipTimeout = null; if (that._tooltipShown) { that._tooltipShown = false; that._hideTooltip() } that._DEBUG_hideCallback && that._DEBUG_hideCallback() }; that._disposeCallbacks = function() { that = that._showTooltipCallback = that._hideTooltipCallback = that._disposeCallbacks = null }; that._tooltipTracker.on(mouseEvents, data).on(touchEvents, data); that._tooltipTracker.on(menuEvents) }, _disposeTooltipEvents: function() { clearTimeout(this._showTooltipTimeout); clearTimeout(this._hideTooltipTimeout); this._showTooltipTimeout = this._showTooltipTimeout = null; this._tooltipTracker.off(); this._disposeCallbacks() }, _drawContainer: function() { this._renderer.draw(this._element()[0]) }, _createTranslator: function() { this._translatorX = CoreFactory.createTranslator2D(this._ranges.arg, this._canvas, {direction: "horizontal"}); this._translatorY = CoreFactory.createTranslator2D(this._ranges.val, this._canvas) }, _prepareTooltipOptions: function() { var that = this, canvas = that._canvas, tooltipOpt = that._allOptions.tooltip, size = that._getTooltipSize(true), defaultOptions = { canvasWidth: size.width, canvasHeight: size.height, paddingLeftRight: tooltipOpt.paddingLeftRight, paddingTopBottom: tooltipOpt.paddingTopBottom, arrowLength: tooltipOpt.arrowLength, cloudHorizontalPosition: tooltipOpt.horizontalAlignment, cloudVerticalPosition: tooltipOpt.verticalAlignment, lineSpacing: tooltipOpt.font.lineSpacing !== undefined && tooltipOpt.font.lineSpacing !== null ? tooltipOpt.font.lineSpacing : DEFAULT_LINE_SPACING }, autoJustify = !$.isFunction(that._allOptions.tooltip.customizeText) && !$.isFunction(that._allOptions.tooltip.customizeTooltip), options = $.extend(defaultOptions, that._allOptions.tooltip, { customizeTooltip: autoJustify ? DEFAULT_CUSTOMIZE_TOOLTIP : that._allOptions.tooltip.customizeTooltip, _justify: that._allOptions.tooltip._justify || autoJustify, _rtl: that.option('rtlEnabled') }); that._tooltipOptions = { size: size, options: options }; return options }, _prepareTooltipContainer: function() { var that = this, canvas = that._canvas, width = canvas.width, height = canvas.height, renderer = that._tooltipRenderer; that._updateTooltipSizeToNormal(); that._tooltipTracker.applySettings({ width: width, height: height }); that._tooltipContainer.appendTo(that._element()); that._tooltipInitializated = false; that._canShowTooltip = that._allOptions.tooltip.enabled }, _isTooltipVisible: function() { return this._tooltip.enabled() && this._tooltip.prepare(this._getTooltipData(), {offset: 0}) }, _createTooltip: function() { var that = this; that._tooltip = CoreFactory.createTooltip(that._prepareTooltipOptions(), that._tooltipGroup, that._tooltipRenderer); if (that._isTooltipVisible()) { that._tooltip.show(); that._updateTooltipSizeToWide(); that._checkTooltipSize(); that._updateTooltipSizeToNormal() } else that._canShowTooltip = false }, _doShowTooltip: function(delay) { var that = this; if (!that._canShowTooltip) return; ++that._DEBUG_clearHideTooltipTimeout; clearTimeout(that._hideTooltipTimeout); that._hideTooltipTimeout = null; clearTimeout(that._showTooltipTimeout); ++that._DEBUG_showTooltipTimeoutSet; that._showTooltipTimeout = setTimeout(that._showTooltipCallback, delay) }, _doHideTooltip: function(delay) { var that = this; if (!that._canShowTooltip) return; ++that._DEBUG_clearShowTooltipTimeout; clearTimeout(that._showTooltipTimeout); that._showTooltipTimeout = null; clearTimeout(that._hideTooltipTimeout); ++that._DEBUG_hideTooltipTimeoutSet; that._hideTooltipTimeout = setTimeout(that._hideTooltipCallback, delay) }, _getNormalTooltipSize: function() { var size = {}; size.width = this._canvas.width; size.left = 0; size.tooltipLeft = _round(size.width / 2); return size }, _getWideTooltipSize: function(leftWidthDelta, rightWidthDelta) { var that = this, canvas = that._canvas, horizontalPos = that._allOptions.tooltip.horizontalAlignment, widthDelta = leftWidthDelta + rightWidthDelta, size = {}; size.width = canvas.width + widthDelta; size.left = -leftWidthDelta; if (horizontalPos === 'right') size.tooltipLeft = _round(canvas.width / 2); else if (horizontalPos === 'left') size.tooltipLeft = _round(canvas.width / 2) + widthDelta; else size.tooltipLeft = _round(size.width / 2); return size }, _getTooltipSize: function(isNormal, leftWidthDelta, rightWidthDelta, heightDelta) { var that = this, canvas = that._canvas, isVerticalPosTop = !(that._allOptions.tooltip.verticalAlignment === 'bottom'), size = !isNormal && (leftWidthDelta || rightWidthDelta) ? that._getWideTooltipSize(leftWidthDelta, rightWidthDelta) : that._getNormalTooltipSize(), yDelta = heightDelta > 0 ? heightDelta + TOOLTIP_MARGIN : TOOLTIP_MARGIN; size.height = canvas.height + yDelta; size.top = isVerticalPosTop ? -size.height : -canvas.height; size.trackerY = isVerticalPosTop ? yDelta : 0; size.tooltipY = isVerticalPosTop ? _round(canvas.height / 2) + yDelta - TOOLTIP_ARROW_MARGIN : _round(canvas.height / 2); return size }, _checkTooltipSize: function() { var that = this, tooltip = that._tooltip, options = that._tooltipOptions.options, tooltipBBox = tooltip.getBBox(), getWide = that._allOptions.tooltip.allowContainerResizing, leftDelta = -tooltipBBox.x, rightDelta = tooltipBBox.x + tooltipBBox.width - that._canvas.width, topDelta = tooltipBBox.height - TOOLTIP_MARGIN, size; if (leftDelta > 0 || rightDelta > 0 || topDelta > 0) if (getWide) { that._tooltipOptions.size = size = that._getTooltipSize(false, leftDelta > 0 ? leftDelta : 0, rightDelta > 0 ? rightDelta : 0, topDelta > 0 ? topDelta : 0); tooltip.setSize(size.width, size.height); that._updateTooltipSizeToWide() } else { that._canShowTooltip = false; tooltip.hide() } }, _updateTooltipSizeToWide: function() { var that = this, size = that._tooltipOptions.size, renderer = that._tooltipRenderer; renderer.resize(size.width, size.height); renderer.getRoot().applySettings({style: { left: size.left, top: size.top, position: 'absolute', overflow: 'hidden' }}); that._tooltipTracker.applySettings({ y: size.trackerY, x: -size.left }); that._tooltip.move(size.tooltipLeft, size.tooltipY) }, _updateTooltipSizeToNormal: function() { var that = this, renderer = that._tooltipRenderer, canvas = that._canvas; renderer.resize(canvas.width, canvas.height); renderer.getRoot().applySettings({style: { left: 0, top: -canvas.height, position: 'absolute' }}); that._tooltipTracker.applySettings({ y: 0, x: 0 }) }, _showTooltip: function() { if (!this._tooltipInitializated) { this._createTooltip(); this._tooltipInitializated = true; if (!this._canShowTooltip) return } this._updateTooltipSizeToWide(); this._tooltip.show() }, _hideTooltip: function() { this._updateTooltipSizeToNormal(); this._tooltip.hide() }, showLoadingIndicator: $.noop }); var menuEvents = { 'contextmenu.sparkline-tooltip': function(event) { if (DX.ui.events.isTouchEvent(event) || DX.ui.events.isPointerEvent(event)) event.preventDefault() }, 'MSHoldVisual.sparkline-tooltip': function(event) { event.preventDefault() } }; var mouseEvents = { 'mouseover.sparkline-tooltip': function(event) { isPointerDownCalled = false; var widget = event.data.widget; widget._x = event.pageX; widget._y = event.pageY; widget._tooltipTracker.off(mouseMoveEvents).on(mouseMoveEvents, event.data); widget._doShowTooltip(DEFAULT_EVENTS_DELAY) }, 'mouseout.sparkline-tooltip': function(event) { if (isPointerDownCalled) return; var widget = event.data.widget; widget._tooltipTracker.off(mouseMoveEvents); widget._doHideTooltip(DEFAULT_EVENTS_DELAY) } }; var mouseMoveEvents = {'mousemove.sparkline-tooltip': function(event) { var widget = event.data.widget; if (widget._showTooltipTimeout && (_abs(widget._x - event.pageX) > 3 || _abs(widget._y - event.pageY) > 3)) { widget._x = event.pageX; widget._y = event.pageY; widget._doShowTooltip(DEFAULT_EVENTS_DELAY) } }}; var active_touch_tooltip_widget = null, touchstartTooltipProcessing = function(event) { event.preventDefault(); var widget = active_touch_tooltip_widget; if (widget && widget !== event.data.widget) widget._doHideTooltip(DEFAULT_EVENTS_DELAY); widget = active_touch_tooltip_widget = event.data.widget; widget._doShowTooltip(TOUCH_EVENTS_DELAY); widget._touch = true }, touchstartDocumentProcessing = function() { var widget = active_touch_tooltip_widget; if (widget) { if (!widget._touch) { widget._doHideTooltip(DEFAULT_EVENTS_DELAY); active_touch_tooltip_widget = null } widget._touch = null } }, touchendDocumentProcessing = function() { var widget = active_touch_tooltip_widget; if (widget) if (widget._showTooltipTimeout) { widget._doHideTooltip(DEFAULT_EVENTS_DELAY); active_touch_tooltip_widget = null } }, isPointerDownCalled = false; var touchEvents = { 'pointerdown.sparkline-tooltip': function(event) { touchstartTooltipProcessing(event) }, 'touchstart.sparkline-tooltip': function(event) { touchstartTooltipProcessing(event) } }; $(document).on({ 'pointerdown.sparkline-tooltip': function() { isPointerDownCalled = true; touchstartDocumentProcessing() }, 'touchstart.sparkline-tooltip': function() { touchstartDocumentProcessing() }, 'pointerup.sparkline-tooltip': function() { touchendDocumentProcessing() }, 'touchend.sparkline-tooltip': function() { touchendDocumentProcessing() } }); DX.viz.sparklines.BaseSparkline._DEBUG_reset = function() { active_touch_tooltip_widget = null } })(jQuery, DevExpress); /*! Module viz-sparklines, file sparkline.js */ (function($, DX) { var viz = DX.viz, charts = viz.charts, core = viz.core, MIN_BAR_WIDTH = 1, MAX_BAR_WIDTH = 50, DEFAULT_BAR_INTERVAL = 4, DEFAULT_CANVAS_WIDTH = 250, DEFAULT_CANVAS_HEIGHT = 30, DEFAULT_HORIZONTAL_MARGIN = 5, DEFAULT_VERTICAL_MARGIN = 3, DEFAULT_OPTIONS = { disabled: false, theme: 'default', dataSource: [], size: {}, margin: {}, type: 'line', argumentField: 'arg', valueField: 'val', winlossThreshold: 0, showFirstLast: true, showMinMax: false, redrawOnResize: false }, ALLOWED_TYPES = { line: true, spline: true, stepline: true, area: true, steparea: true, splinearea: true, bar: true, winloss: true }, _map = $.map, _extend = $.extend, _abs = Math.abs, _round = Math.round, _isFinite = isFinite, _Number = Number, _String = String; viz.sparklines.Sparkline = viz.sparklines.BaseSparkline.inherit({ _widgetType: 'sparkline', _widgetClass: 'dxsl', _defaultSize: { width: DEFAULT_CANVAS_WIDTH, height: DEFAULT_CANVAS_HEIGHT, left: DEFAULT_HORIZONTAL_MARGIN, right: DEFAULT_HORIZONTAL_MARGIN, top: DEFAULT_VERTICAL_MARGIN, bottom: DEFAULT_VERTICAL_MARGIN }, _init: function() { this.callBase(); this._refreshDataSource() }, _handleDataSourceChanged: function() { if (this._initialized) { this._clean(); this._createWidgetElements(); this._drawWidgetElements() } }, _dataSourceOptions: function() { return { paginate: false, _preferSync: true } }, _redrawWidgetElements: function() { this._createTranslator(); this._correctPoints(); this._series.draw({ x: this._translatorX, y: this._translatorY }); this._seriesGroup.append(this._renderer.getRoot()) }, _disposeWidgetElements: function() { delete this._seriesGroup; delete this._seriesLabelGroup }, _cleanWidgetElements: function() { this._seriesGroup.detach(); this._seriesLabelGroup.detach(); this._seriesGroup.clear(); this._seriesLabelGroup.clear() }, _createWidgetElements: function() { this._createSeries(); this.callBase() }, _drawWidgetElements: function() { if (this._dataSource && this._dataSource.isLoaded()) this._drawSeries() }, _prepareOptions: function() { this._allOptions = this.callBase(DEFAULT_OPTIONS); this._allOptions.type = _String(this._allOptions.type).toLowerCase(); if (!ALLOWED_TYPES[this._allOptions.type]) this._allOptions.type = 'line' }, _createHtmlElements: function() { this._seriesGroup = this._renderer.createGroup({'class': 'dxsl-series'}); this._seriesLabelGroup = this._renderer.createGroup({'class': 'dxsl-series-labels'}) }, _createSeries: function() { var that = this, renderer = that._renderer, dataValidator; that._prepareDataSource(); that._prepareSeriesOptions(); that._series = core.CoreFactory.createSeries(renderer, that._seriesOptions); dataValidator = charts.factory.createDataValidator(that._simpleDataSource, [[that._series]], that._incidentOccured, { checkTypeForAllData: false, convertToAxisDataType: true, sortingMethod: true }); that._simpleDataSource = dataValidator.validate(); that._series._options.customizePoint = that._getCustomizeFunction(); that._series.updateData(that._simpleDataSource) }, _parseNumericDataSource: function(data, argField, valField) { var ignoreEmptyPoints = this.option('ignoreEmptyPoints'); return _map(data, function(dataItem, index) { var item = null, isDataNumber, value; if (dataItem !== undefined) { item = {}; isDataNumber = _isFinite(dataItem); item[argField] = isDataNumber ? _String(index) : dataItem[argField]; value = isDataNumber ? dataItem : dataItem[valField]; item[valField] = value === null ? ignoreEmptyPoints ? undefined : value : _Number(value); item = item[argField] !== undefined && item[valField] !== undefined ? item : null } return item }) }, _parseWinlossDataSource: function(data, argField, valField) { var lowBarValue = -1, zeroBarValue = 0, highBarValue = 1, delta = 0.0001, target = this._allOptions.winlossThreshold; return _map(data, function(dataItem) { var item = {}; item[argField] = dataItem[argField]; if (_abs(dataItem[valField] - target) < delta) item[valField] = zeroBarValue; else if (dataItem[valField] > target) item[valField] = highBarValue; else item[valField] = lowBarValue; return item }) }, _prepareDataSource: function() { var that = this, options = that._allOptions, argField = options.argumentField, valField = options.valueField, dataSource = that._dataSource ? that._dataSource.items() : [], data = that._parseNumericDataSource(dataSource, argField, valField); if (options.type === 'winloss') { that._winlossDataSource = data; that._simpleDataSource = that._parseWinlossDataSource(data, argField, valField) } else that._simpleDataSource = data }, _prepareSeriesOptions: function() { var that = this, options = that._allOptions, defaultPointOptions = { border: {}, hoverStyle: {border: {}}, selectionStyle: {border: {}} }, customPointOptions = { size: options.pointSize, symbol: options.pointSymbol, border: { visible: true, width: 2 }, color: options.pointColor }; that._seriesOptions = { visible: true, argumentField: options.argumentField, valueField: options.valueField, color: options.lineColor, width: options.lineWidth, widgetType: "chart" }; that._seriesOptions.border = { color: that._seriesOptions.color, width: that._seriesOptions.width, visible: true }; that._seriesOptions.type = options.type === 'winloss' ? 'bar' : options.type; if (options.type === 'winloss' || options.type === 'bar') { that._seriesOptions.argumentAxisType = 'discrete'; that._seriesOptions.border.visible = false } if (~~options.type.indexOf('area') !== -1) that._seriesOptions.opacity = that._allOptions.areaOpacity; that._seriesOptions.seriesGroup = that._seriesGroup; that._seriesOptions.seriesLabelsGroup = that._seriesLabelGroup; that._seriesOptions.point = _extend(defaultPointOptions, customPointOptions); that._seriesOptions.point.visible = false }, _createBarCustomizeFunction: function(pointIndexes) { var that = this, options = that._allOptions, winlossData = that._winlossDataSource; return function() { var index = this.index, isWinloss = options.type === 'winloss', target = isWinloss ? options.winlossThreshold : 0, value = isWinloss ? winlossData[index][options.valueField] : this.value, positiveColor = isWinloss ? options.winColor : options.barPositiveColor, negativeColor = isWinloss ? options.lossColor : options.barNegativeColor, color; if (value >= target) color = positiveColor; else color = negativeColor; if (index === pointIndexes.first || index === pointIndexes.last) color = options.firstLastColor; if (index === pointIndexes.min) color = options.minColor; if (index === pointIndexes.max) color = options.maxColor; return {color: color} } }, _createLineCustomizeFunction: function(pointIndexes) { var that = this, options = that._allOptions; return function() { var color, index = this.index; if (index === pointIndexes.first || index === pointIndexes.last) color = options.firstLastColor; if (index === pointIndexes.min) color = options.minColor; if (index === pointIndexes.max) color = options.maxColor; return color ? { visible: true, border: {color: color} } : {} } }, _getCustomizeFunction: function() { var that = this, options = that._allOptions, dataSource = that._winlossDataSource || that._simpleDataSource, drawnPointIndexes = that._getExtremumPointsIndexes(dataSource), customizeFunction; if (options.type === 'winloss' || options.type === 'bar') customizeFunction = that._createBarCustomizeFunction(drawnPointIndexes); else customizeFunction = that._createLineCustomizeFunction(drawnPointIndexes); return customizeFunction }, _getExtremumPointsIndexes: function(data) { var that = this, options = that._allOptions, lastIndex = data.length - 1, indexes = {}; that._minMaxIndexes = that._findMinMax(data); if (options.showFirstLast) { indexes.first = 0; indexes.last = lastIndex } if (options.showMinMax) { indexes.min = that._minMaxIndexes.minIndex; indexes.max = that._minMaxIndexes.maxIndex } return indexes }, _findMinMax: function(data) { var that = this, valField = that._allOptions.valueField, firstItem = data[0] || {}, firstValue = firstItem[valField] || 0, min = firstValue, max = firstValue, minIndex = 0, maxIndex = 0, dataLength = data.length, value, i; for (i = 1; i < dataLength; i++) { value = data[i][valField]; if (value < min) { min = value; minIndex = i } if (value > max) { max = value; maxIndex = i } } return { minIndex: minIndex, maxIndex: maxIndex } }, _createRange: function() { var that = this, series = that._series, isBarType = series.type === 'bar', DEFAULT_VALUE_RANGE_MARGIN = 0.15, DEFAULT_ARGUMENT_RANGE_MARGIN = isBarType ? 0.1 : 0, rangeData = series.getRangeData(); that._ranges = { arg: new core.Range({ stick: !isBarType && series.getPoints().length > 1, minValueMargin: DEFAULT_ARGUMENT_RANGE_MARGIN, maxValueMargin: DEFAULT_ARGUMENT_RANGE_MARGIN }), val: new core.Range({ isValueRange: true, keepValueMargins: true, minValueMargin: DEFAULT_VALUE_RANGE_MARGIN, maxValueMargin: DEFAULT_VALUE_RANGE_MARGIN }) }; that._ranges.arg.addRange(rangeData.arg); that._ranges.val.addRange(rangeData.val); that._ranges.arg.applyValueMargins(); that._ranges.val.applyValueMargins() }, _getBarWidth: function(pointsCount) { var that = this, canvas = that._canvas, intervalWidth = pointsCount * DEFAULT_BAR_INTERVAL, rangeWidth = canvas.width - canvas.left - canvas.right - intervalWidth, width = _round(rangeWidth / pointsCount); if (width < MIN_BAR_WIDTH) width = MIN_BAR_WIDTH; if (width > MAX_BAR_WIDTH) width = MAX_BAR_WIDTH; return width }, _correctPoints: function() { var that = this, seriesType = that._allOptions.type, seriesPoints = that._series.getPoints(), pointsLength = seriesPoints.length, barWidth, i; if (seriesType === 'bar' || seriesType === 'winloss') { barWidth = that._getBarWidth(pointsLength); for (i = 0; i < pointsLength; i++) seriesPoints[i].correctCoordinates({ width: barWidth, offset: 0 }) } }, _drawSeries: function() { var that = this; if (that._simpleDataSource.length !== 0) { that._correctPoints(); that._series.draw({ x: that._translatorX, y: that._translatorY }); that._seriesGroup.append(that._renderer.getRoot()); that._prepareTooltipContainer() } }, _isTooltipVisible: function() { return this.callBase() && this._dataSource.length !== 0 }, _getTooltipData: function() { var that = this, options = that._allOptions, dataSource = that._winlossDataSource || that._simpleDataSource, tooltip = that._tooltip; if (dataSource.length === 0) return {}; var minMax = that._minMaxIndexes, valueField = options.valueField, first = dataSource[0][valueField], last = dataSource[dataSource.length - 1][valueField], min = dataSource[minMax.minIndex][valueField], max = dataSource[minMax.maxIndex][valueField], formattedFirst = tooltip.formatValue(first), formattedLast = tooltip.formatValue(last), formattedMin = tooltip.formatValue(min), formattedMax = tooltip.formatValue(max), customizeObject = { firstValue: formattedFirst, lastValue: formattedLast, minValue: formattedMin, maxValue: formattedMax, originalFirstValue: first, originalLastValue: last, originalMinValue: min, originalMaxValue: max, valueText: ['Start:', formattedFirst, 'End:', formattedLast, 'Min:', formattedMin, 'Max:', formattedMax] }; if (options.type === 'winloss') { customizeObject.originalThresholdValue = options.winlossThreshold; customizeObject.thresholdValue = tooltip.formatValue(options.winlossThreshold) } return customizeObject } }).include(DX.ui.DataHelperMixin) })(jQuery, DevExpress); /*! Module viz-sparklines, file bullet.js */ (function($, DX) { var charts = DX.viz.charts, TARGET_MIN_Y = 0.02, TARGET_MAX_Y = 0.98, BAR_VALUE_MIN_Y = 0.1, BAR_VALUE_MAX_Y = 0.9, DEFAULT_CANVAS_WIDTH = 300, DEFAULT_CANVAS_HEIGHT = 30, DEFAULT_HORIZONTAL_MARGIN = 1, DEFAULT_VERTICAL_MARGIN = 2, DEFAULT_OPTIONS = { disabled: false, theme: 'default', size: {}, margin: {} }, _String = String, _Number = Number, _round = Math.round, _isFinite = isFinite; DX.viz.sparklines.Bullet = DX.viz.sparklines.BaseSparkline.inherit({ _widgetType: 'bullet', _widgetClass: 'dxb', _defaultSize: { width: DEFAULT_CANVAS_WIDTH, height: DEFAULT_CANVAS_HEIGHT, left: DEFAULT_HORIZONTAL_MARGIN, right: DEFAULT_HORIZONTAL_MARGIN, top: DEFAULT_VERTICAL_MARGIN, bottom: DEFAULT_VERTICAL_MARGIN }, _disposeWidgetElements: function() { delete this._zeroLevelPath; delete this._targetPath; delete this._barValuePath }, _redrawWidgetElements: function() { this._createTranslator(); this._drawBarValue(); this._drawTarget(); this._drawZeroLevel() }, _cleanWidgetElements: function() { this._zeroLevelPath.detach(); this._targetPath.detach(); this._barValuePath.detach() }, _drawWidgetElements: function() { this._drawBullet() }, _createHtmlElements: function() { var renderer = this._renderer; this._zeroLevelPath = renderer.createPath(undefined, {'class': 'dxb-zero-level'}); this._targetPath = renderer.createPath(undefined, {'class': 'dxb-target'}); this._barValuePath = renderer.createPath(undefined, {'class': 'dxb-bar-value'}) }, _prepareOptions: function() { var that = this, options, startScaleValue, endScaleValue, level, value, target; that._allOptions = options = that.callBase(DEFAULT_OPTIONS); if (that._allOptions.value === undefined) that._allOptions.value = 0; if (that._allOptions.target === undefined) that._allOptions.target = 0; options.value = value = _Number(options.value); options.target = target = _Number(options.target); if (that._allOptions.startScaleValue === undefined) { that._allOptions.startScaleValue = target < value ? target : value; that._allOptions.startScaleValue = that._allOptions.startScaleValue < 0 ? that._allOptions.startScaleValue : 0 } if (that._allOptions.endScaleValue === undefined) that._allOptions.endScaleValue = target > value ? target : value; options.startScaleValue = startScaleValue = _Number(options.startScaleValue); options.endScaleValue = endScaleValue = _Number(options.endScaleValue); if (endScaleValue < startScaleValue) { level = endScaleValue; that._allOptions.endScaleValue = startScaleValue; that._allOptions.startScaleValue = level; that._allOptions.inverted = true } }, _createRange: function() { var that = this, options = that._allOptions; that._ranges = { arg: { invert: options.inverted, min: options.startScaleValue, max: options.endScaleValue, axisType: "continuous", dataType: "numeric" }, val: { min: 0, max: 1, axisType: "continuous", dataType: "numeric" } } }, _drawBullet: function() { var that = this, options = that._allOptions, isValidBounds = options.startScaleValue !== options.endScaleValue, isValidMin = _isFinite(options.startScaleValue), isValidMax = _isFinite(options.endScaleValue), isValidValue = _isFinite(options.value), isValidTarget = _isFinite(options.target); if (isValidBounds && isValidMax && isValidMin && isValidTarget && isValidValue) { this._drawBarValue(); this._drawTarget(); this._drawZeroLevel(); this._prepareTooltipContainer() } }, _getTargetParams: function() { var that = this, options = that._allOptions, translatorX = that._translatorX, translatorY = that._translatorY, minY = translatorY.translate(TARGET_MIN_Y), maxY = translatorY.translate(TARGET_MAX_Y), x = translatorX.translate(options.target), points = [{ x: x, y: minY }, { x: x, y: maxY }]; return { points: points, stroke: options.targetColor, strokeWidth: options.targetWidth } }, _getBarValueParams: function() { var that = this, options = that._allOptions, translatorX = that._translatorX, translatorY = that._translatorY, startLevel = options.startScaleValue, endLevel = options.endScaleValue, value = options.value, y2 = translatorY.translate(BAR_VALUE_MIN_Y), y1 = translatorY.translate(BAR_VALUE_MAX_Y), x1, x2; if (value > 0) { x1 = startLevel <= 0 ? 0 : startLevel; x2 = value >= endLevel ? endLevel : value } else { x1 = endLevel >= 0 ? 0 : endLevel; x2 = value >= startLevel ? value : startLevel } x1 = translatorX.translate(x1); x2 = translatorX.translate(x2); return { points: [{ x: x1, y: y1 }, { x: x2, y: y1 }, { x: x2, y: y2 }, { x: x1, y: y2 }], fill: options.color } }, _getZeroLevelParams: function() { var that = this, options = that._allOptions, translatorX = that._translatorX, translatorY = that._translatorY, minY = translatorY.translate(TARGET_MIN_Y), maxY = translatorY.translate(TARGET_MAX_Y), x = translatorX.translate(0); return { points: [{ x: x, y: minY }, { x: x, y: maxY }], stroke: options.targetColor, strokeWidth: 1 } }, _drawZeroLevel: function() { var that = this, options = that._allOptions, params; if (0 > options.endScaleValue || 0 < options.startScaleValue || !options.showZeroLevel) return; params = that._getZeroLevelParams(); that._zeroLevelPath.applySettings(params); that._zeroLevelPath.append(that._renderer.getRoot()) }, _drawTarget: function() { var that = this, options = that._allOptions, target = options.target, startLevel = options.startScaleValue, endLevel = options.endScaleValue, params; if (target > endLevel || target < startLevel || !options.showTarget) return; params = that._getTargetParams(); that._targetPath.applySettings(params); that._targetPath.append(that._renderer.getRoot()) }, _drawBarValue: function() { var that = this, params = that._getBarValueParams(); that._barValuePath.applySettings(params); that._barValuePath.append(that._renderer.getRoot()) }, _getTooltipData: function() { var that = this, tooltip = that._tooltip, options = that._allOptions, value = options.value, target = options.target; return { originalValue: value, originalTarget: target, value: tooltip.formatValue(value), target: tooltip.formatValue(target), valueText: ['Actual Value:', value, 'Target Value:', target] } }, _getNormalTooltipSize: function() { var size = {}, bbox = this._barValuePath.getBBox(); size.width = this._canvas.width; size.left = 0; size.tooltipLeft = bbox.x + _round(bbox.width / 2); return size }, _getWideTooltipSize: function(leftWidthDelta, rightWidthDelta) { var that = this, bbox = that._barValuePath.getBBox(), horizontalPos = that._allOptions.tooltip.horizontalAlignment, size = {}; size.width = leftWidthDelta + rightWidthDelta + that._canvas.width; size.left = -leftWidthDelta; if (horizontalPos === 'right') size.tooltipLeft = bbox.x + _round(bbox.width / 2); else if (horizontalPos === 'left') size.tooltipLeft = _round(bbox.width / 2) + leftWidthDelta + rightWidthDelta + bbox.x; else size.tooltipLeft = _round(bbox.width / 2) + bbox.x + leftWidthDelta; return size } }) })(jQuery, DevExpress); /*! Module viz-sparklines, file dxSparkline.js */ (function($, DX, undefined) { var ui = DX.ui, viz = DX.viz; DX.registerComponent("dxSparkline", viz.sparklines.Sparkline) })(jQuery, DevExpress); /*! Module viz-sparklines, file dxBullet.js */ (function($, DX, undefined) { var ui = DX.ui, viz = DX.viz; DX.registerComponent("dxBullet", viz.sparklines.Bullet) })(jQuery, DevExpress); DevExpress.MOD_VIZ_SPARKLINES = true }