UNPKG

@progress/kendo-ui

Version:

This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.

1,580 lines (1,449 loc) 610 kB
import './kendo.data.js'; import './kendo.draganddrop.js'; import './kendo.userevents.js'; import './kendo.mobile.scroller.js'; import './kendo.core.js'; import './kendo.dataviz.core.js'; import './html-DIrOxn6k.js'; import './kendo.toolbar.js'; import './kendo.editable.js'; import './kendo.window.js'; import './kendo.dropdownlist.js'; import './kendo.dataviz.themes.js'; import './kendo.html.button.js'; import './kendo.data.odata.js'; import './kendo.licensing.js'; import '@progress/kendo-licensing'; import './kendo.data.xml.js'; import './kendo.fx.js'; import '@progress/kendo-charts/dist/es/core-export.js'; import './kendo.popup.js'; import './kendo.icons.js'; import './kendo.html.icon.js'; import './kendo.html.base.js'; import '@progress/kendo-svg-icons'; import '@progress/kendo-drawing'; import './kendo.color.js'; import './kendo.splitbutton.js'; import './kendo.button.menu.js'; import './kendo.dropdownbutton.js'; import './kendo.buttongroup.js'; import './kendo.togglebutton.js'; import './kendo.button.js'; import './kendo.badge.js'; import './kendo.menu.js'; import './kendo.checkbox.js'; import './kendo.toggleinputbase.js'; import './kendo.html.input.js'; import './kendo.datepicker.js'; import './kendo.calendar.js'; import './kendo.selectable.js'; import './kendo.dateinput.js'; import './kendo.label.js'; import './kendo.floatinglabel.js'; import '@progress/kendo-dateinputs-common'; import './kendo.actionsheet.js'; import './kendo.numerictextbox.js'; import './prefix-suffix-containers-B9VRe3lS.js'; import './kendo.textbox.js'; import './kendo.validator.js'; import './kendo.binder.js'; import './kendo.otpinput.js'; import './kendo.list.js'; import './dropdowns-loader-00xUvouJ.js'; import './kendo.virtuallist.js'; import './valueMapper-CXgI6HWc.js'; import '@progress/kendo-charts'; (function($, undefined$1) { var kendo = window.kendo, diagram = kendo.dataviz.diagram = {}, deepExtend = kendo.deepExtend, isArray = Array.isArray, EPSILON = 1e-06; /*-------------------Diverse utilities----------------------------*/ var Utils = { }; deepExtend(Utils, { isNearZero: function(num) { return Math.abs(num) < EPSILON; }, isDefined: function(obj) { return typeof obj !== 'undefined'; }, isUndefined: function(obj) { return (typeof obj === 'undefined') || obj === null; }, /** * Returns whether the given object is an object or a value. */ isObject: function(obj) { return obj === Object(obj); }, /** * Returns whether the object has a property with the given name. */ has: function(obj, key) { return Object.hasOwnProperty.call(obj, key); }, /** * Returns whether the given object is a string. */ isString: function(obj) { return Object.prototype.toString.call(obj) == '[object String]'; }, isBoolean: function(obj) { return Object.prototype.toString.call(obj) == '[object Boolean]'; }, isType: function(obj, type) { return Object.prototype.toString.call(obj) == '[object ' + type + ']'; }, /** * Returns whether the given object is a number. */ isNumber: function(obj) { return !isNaN(parseFloat(obj)) && isFinite(obj); }, /** * Return whether the given object (array or dictionary). */ isEmpty: function(obj) { if (obj === null) { return true; } if (isArray(obj) || Utils.isString(obj)) { return obj.length === 0; } for (var key in obj) { if (Utils.has(obj, key)) { return false; } } return true; }, simpleExtend: function(destination, source) { if (!Utils.isObject(source)) { return; } for (var name in source) { destination[name] = source[name]; } }, /** * Returns an array of the specified size and with each entry set to the given value. * @param size * @param value * @returns {Array} */ initArray: function createIdArray(size, value) { var array = []; for (var i = 0; i < size; ++i) { array[i] = value; } return array; }, serializePoints: function(points) { var res = []; for (var i = 0; i < points.length; i++) { var p = points[i]; res.push(p.x + ";" + p.y); } return res.join(";"); }, deserializePoints: function(s) { var v = s.split(";"), points = []; if (v.length % 2 !== 0) { throw "Not an array of points."; } for (var i = 0; i < v.length; i += 2) { points.push(new diagram.Point( parseInt(v[i], 10), parseInt(v[i + 1], 10) )); } return points; }, /** * Returns an integer within the given bounds. * @param lower The inclusive lower bound. * @param upper The exclusive upper bound. * @returns {number} */ randomInteger: function(lower, upper) { return parseInt(Math.floor(Math.random() * upper) + lower, 10); } , /* Depth-first traversal of the given node. */ DFT: function(el, func) { func(el); if (el.childNodes) { for (var i = 0; i < el.childNodes.length; i++) { var item = el.childNodes[i]; this.DFT(item, func); } } }, /* Returns the angle in degrees for the given matrix */ getMatrixAngle: function(m) { if (m === null || m.d === 0) { return 0; } return Math.atan2(m.b, m.d) * 180 / Math.PI; }, /* Returns the scaling factors for the given matrix. */ getMatrixScaling: function(m) { var sX = Math.sqrt(m.a * m.a + m.c * m.c); var sY = Math.sqrt(m.b * m.b + m.d * m.d); return [sX, sY]; } }); /** * The Range defines an array of equally separated numbers. * @param start The start-value of the Range. * @param stop The end-value of the Range. * @param step The separation between the values (default:1). * @returns {Array} */ function Range(start, stop, step) { if (typeof start == 'undefined' || typeof stop == 'undefined') { return []; } if (step && Utils.sign(stop - start) != Utils.sign(step)) { throw "The sign of the increment should allow to reach the stop-value."; } step = step || 1; start = start || 0; stop = stop || start; if ((stop - start) / step === Infinity) { throw "Infinite range defined."; } var range = [], i = -1, j; function rangeIntegerScale(x) { var k = 1; while (x * k % 1) { k *= 10; } return k; } var k = rangeIntegerScale(Math.abs(step)); start *= k; stop *= k; step *= k; if (start > stop && step > 0) { step = -step; } if (step < 0) { while ((j = start + step * ++i) >= stop) { range.push(j / k); } } else { while ((j = start + step * ++i) <= stop) { range.push(j / k); } } return range; } /*-------------------Diverse math functions----------------------------*/ function findRadian(start, end) { if (start == end) { return 0; } var sngXComp = end.x - start.x, sngYComp = start.y - end.y, atan = Math.atan(sngXComp / sngYComp); if (sngYComp >= 0) { return sngXComp < 0 ? atan + (2 * Math.PI) : atan; } return atan + Math.PI; } Utils.sign = function(number) { return number ? number < 0 ? -1 : 1 : 0; }; Utils.findAngle = function(center, end) { return findRadian(center, end) * 180 / Math.PI; }; /*-------------------Array Helpers ----------------------------*/ Utils.forEach = function(arr, iterator, thisRef) { for (var i = 0; i < arr.length; i++) { iterator.call(thisRef, arr[i], i, arr); } }; Utils.any = function(arr, predicate) { for (var i = 0; i < arr.length; ++i) { if (predicate(arr[i])) { return arr[i]; } } return null; }; Utils.remove = function(arr, what) { var ax; while ((ax = Utils.indexOf(arr, what)) !== -1) { arr.splice(ax, 1); } return arr; }; Utils.contains = function(arr, obj) { return Utils.indexOf(arr, obj) !== -1; }; Utils.indexOf = function(arr, what) { return $.inArray(what, arr); }; Utils.fold = function(list, iterator, acc, context) { var initial = arguments.length > 2; for (var i = 0; i < list.length; i++) { var value = list[i]; if (!initial) { acc = value; initial = true; } else { acc = iterator.call(context, acc, value, i, list); } } if (!initial) { throw 'Reduce of empty array with no initial value'; } return acc; }; Utils.find = function(arr, iterator, context) { var result; Utils.any(arr, function(value, index, list) { if (iterator.call(context, value, index, list)) { result = value; return true; } return false; }); return result; }; Utils.first = function(arr, constraint, context) { if (arr.length === 0) { return null; } if (Utils.isUndefined(constraint)) { return arr[0]; } return Utils.find(arr, constraint, context); }; /** * Inserts the given element at the specified position and returns the result. */ Utils.insert = function(arr, element, position) { arr.splice(position, 0, element); return arr; }; Utils.all = function(arr, iterator, context) { var result = true; var value; for (var i = 0; i < arr.length; i++) { value = arr[i]; result = result && iterator.call(context, value, i, arr); if (!result) { break; } } return result; }; Utils.clear = function(arr) { arr.splice(0, arr.length); }; /** * Sort the arrays on the basis of the first one (considered as keys and the other array as values). * @param a * @param b * @param sortfunc (optiona) sorting function for the values in the first array */ Utils.bisort = function(a, b, sortfunc) { if (Utils.isUndefined(a)) { throw "First array is not specified."; } if (Utils.isUndefined(b)) { throw "Second array is not specified."; } if (a.length != b.length) { throw "The two arrays should have equal length"; } var all = [], i; for (i = 0; i < a.length; i++) { all.push({ 'x': a[i], 'y': b[i] }); } if (Utils.isUndefined(sortfunc)) { all.sort(function(m, n) { return m.x - n.x; }); } else { all.sort(function(m, n) { return sortfunc(m.x, n.x); }); } Utils.clear(a); Utils.clear(b); for (i = 0; i < all.length; i++) { a.push(all[i].x); b.push(all[i].y); } }; Utils.addRange = function(arr, range) { arr.push.apply(arr, range); }; var Easing = { easeInOut: function(pos) { return ((-Math.cos(pos * Math.PI) / 2) + 0.5); } }; /** * An animation ticker driving an adapter which sets a particular * property in function of the tick. * @type {*} */ var Ticker = kendo.Class.extend({ init: function() { this.adapters = []; this.target = 0; this.tick = 0; this.interval = 20; this.duration = 800; this.lastTime = null; this.handlers = []; var _this = this; this.transition = Easing.easeInOut; this.timerDelegate = function() { _this.onTimerEvent(); }; }, addAdapter: function(a) { this.adapters.push(a); }, onComplete: function(handler) { this.handlers.push(handler); }, removeHandler: function(handler) { this.handlers = $.grep(this.handlers, function(h) { return h !== handler; }); }, trigger: function() { var _this = this; if (this.handlers) { Utils.forEach(this.handlers, function(h) { return h.call(_this.caller !== null ? _this.caller : _this); }); } }, onStep: function() { }, seekTo: function(to) { this.seekFromTo(this.tick, to); }, seekFromTo: function(from, to) { this.target = Math.max(0, Math.min(1, to)); this.tick = Math.max(0, Math.min(1, from)); this.lastTime = new Date().getTime(); if (!this.intervalId) { this.intervalId = window.setInterval(this.timerDelegate, this.interval); } }, stop: function() { if (this.intervalId) { window.clearInterval(this.intervalId); this.intervalId = null; //this.trigger.call(this); this.trigger(); // this.next(); } }, play: function(origin) { if (this.adapters.length === 0) { return; } if (origin !== null) { this.caller = origin; } this.initState(); this.seekFromTo(0, 1); }, reverse: function() { this.seekFromTo(1, 0); }, initState: function() { if (this.adapters.length === 0) { return; } for (var i = 0; i < this.adapters.length; i++) { this.adapters[i].initState(); } }, propagate: function() { var value = this.transition(this.tick); for (var i = 0; i < this.adapters.length; i++) { this.adapters[i].update(value); } }, onTimerEvent: function() { var now = new Date().getTime(); var timePassed = now - this.lastTime; this.lastTime = now; var movement = (timePassed / this.duration) * (this.tick < this.target ? 1 : -1); if (Math.abs(movement) >= Math.abs(this.tick - this.target)) { this.tick = this.target; } else { this.tick += movement; } try { this.propagate(); } finally { this.onStep.call(this); if (this.target == this.tick) { this.stop(); } } } }); kendo.deepExtend(diagram, { init: function(element) { kendo.init(element, diagram.ui); }, Utils: Utils, Range: Range, Ticker: Ticker }); })(window.kendo.jQuery); (function($, undefined$1) { // Imports ================================================================ var kendo = window.kendo, diagram = kendo.dataviz.diagram, Class = kendo.Class, deepExtend = kendo.deepExtend, Utils = diagram.Utils, Point = kendo.geometry.Point, isFunction = kendo.isFunction, contains = Utils.contains, map = $.map; // Constants ============================================================== var HITTESTAREA = 3, EPSILON = 1e-06; class ExtendedPoint extends Point { constructor(x, y) { super(x, y); } clone() { return new ExtendedPoint(this.x, this.y); } plus(p) { return new ExtendedPoint(this.x + p.x, this.y + p.y); } minus(p) { return new ExtendedPoint(this.x - p.x, this.y - p.y); } offset(value) { return new ExtendedPoint(this.x - value, this.y - value); } times(s) { return new ExtendedPoint(this.x * s, this.y * s); } normalize() { if (this.length() === 0) { return new ExtendedPoint(); } return this.times(1 / this.length()); } length() { return Math.sqrt(this.x * this.x + this.y * this.y); } toString() { return "(" + this.x + "," + this.y + ")"; } lengthSquared() { return (this.x * this.x + this.y * this.y); } middleOf(p, q) { return new ExtendedPoint(q.x - p.x, q.y - p.y).times(0.5).plus(p); } toPolar(useDegrees) { var factor = 1; if (useDegrees) { factor = 180 / Math.PI; } var a = Math.atan2(Math.abs(this.y), Math.abs(this.x)); var halfpi = Math.PI / 2; var len = this.length(); if (this.x === 0) { // note that the angle goes down and not the usual mathematical convention if (this.y === 0) { return new Polar(0, 0); } if (this.y > 0) { return new Polar(len, factor * halfpi); } if (this.y < 0) { return new Polar(len, factor * 3 * halfpi); } } else if (this.x > 0) { if (this.y === 0) { return new Polar(len, 0); } if (this.y > 0) { return new Polar(len, factor * a); } if (this.y < 0) { return new Polar(len, factor * (4 * halfpi - a)); } } else { if (this.y === 0) { return new Polar(len, 2 * halfpi); } if (this.y > 0) { return new Polar(len, factor * (2 * halfpi - a)); } if (this.y < 0) { return new Polar(len, factor * (2 * halfpi + a)); } } } isOnLine(from, to) { if (from.x > to.x) { // from must be the leftmost point var temp = to; to = from; from = temp; } var r1 = new Rect(from.x, from.y).inflate(HITTESTAREA, HITTESTAREA), r2 = new Rect(to.x, to.y).inflate(HITTESTAREA, HITTESTAREA), o1, u1; if (r1.union(r2).contains(this)) { if (from.x === to.x || from.y === to.y) { return true; } else if (from.y < to.y) { o1 = r1.x + (((r2.x - r1.x) * (this.y - (r1.y + r1.height))) / ((r2.y + r2.height) - (r1.y + r1.height))); u1 = (r1.x + r1.width) + ((((r2.x + r2.width) - (r1.x + r1.width)) * (this.y - r1.y)) / (r2.y - r1.y)); } else { o1 = r1.x + (((r2.x - r1.x) * (this.y - r1.y)) / (r2.y - r1.y)); u1 = (r1.x + r1.width) + ((((r2.x + r2.width) - (r1.x + r1.width)) * (this.y - (r1.y + r1.height))) / ((r2.y + r2.height) - (r1.y + r1.height))); } return (this.x > o1 && this.x < u1); } return false; } parse(str) { var tempStr = str.slice(1, str.length - 1), xy = tempStr.split(","), x = parseInt(xy[0], 10), y = parseInt(xy[1], 10); if (!isNaN(x) && !isNaN(y)) { return new ExtendedPoint(x, y); } } } /** * Structure combining a Point with two additional points representing the handles or tangents attached to the first point. * If the additional points are null or equal to the first point the path will be sharp. * Left and right correspond to the direction of the underlying path. */ var PathDefiner = Class.extend( { init: function(p, left, right) { this.point = p; this.left = left; this.right = right; } } ); /** * Defines a rectangular region. */ var Rect = Class.extend({ init: function(x, y, width, height) { this.x = x || 0; this.y = y || 0; this.width = width || 0; this.height = height || 0; }, contains: function(point) { return ((point.x >= this.x) && (point.x <= (this.x + this.width)) && (point.y >= this.y) && (point.y <= (this.y + this.height))); }, inflate: function(dx, dy) { if (dy === undefined$1) { dy = dx; } this.x -= dx; this.y -= dy; this.width += 2 * dx + 1; this.height += 2 * dy + 1; return this; }, offset: function(dx, dy) { var x = dx, y = dy; if (dx instanceof ExtendedPoint) { x = dx.x; y = dx.y; } this.x += x; this.y += y; return this; }, union: function(r) { var x1 = Math.min(this.x, r.x); var y1 = Math.min(this.y, r.y); var x2 = Math.max((this.x + this.width), (r.x + r.width)); var y2 = Math.max((this.y + this.height), (r.y + r.height)); return new Rect(x1, y1, x2 - x1, y2 - y1); }, center: function() { return new ExtendedPoint(this.x + this.width / 2, this.y + this.height / 2); }, top: function() { return new ExtendedPoint(this.x + this.width / 2, this.y); }, right: function() { return new ExtendedPoint(this.x + this.width, this.y + this.height / 2); }, bottom: function() { return new ExtendedPoint(this.x + this.width / 2, this.y + this.height); }, left: function() { return new ExtendedPoint(this.x, this.y + this.height / 2); }, topLeft: function() { return new ExtendedPoint(this.x, this.y); }, topRight: function() { return new ExtendedPoint(this.x + this.width, this.y); }, bottomLeft: function() { return new ExtendedPoint(this.x, this.y + this.height); }, bottomRight: function() { return new ExtendedPoint(this.x + this.width, this.y + this.height); }, clone: function() { return new Rect(this.x, this.y, this.width, this.height); }, isEmpty: function() { return !this.width && !this.height; }, equals: function(rect) { return this.x === rect.x && this.y === rect.y && this.width === rect.width && this.height === rect.height; }, rotatedBounds: function(angle) { var rect = this.clone(), points = this.rotatedPoints(angle), tl = points[0], tr = points[1], br = points[2], bl = points[3]; rect.x = Math.min(br.x, tl.x, tr.x, bl.x); rect.y = Math.min(br.y, tl.y, tr.y, bl.y); rect.width = Math.max(br.x, tl.x, tr.x, bl.x) - rect.x; rect.height = Math.max(br.y, tl.y, tr.y, bl.y) - rect.y; return rect; }, rotatedPoints: function(angle) { var rect = this, c = rect.center(), br = rect.bottomRight().rotate(angle, c), tl = rect.topLeft().rotate(angle, c), tr = rect.topRight().rotate(angle, c), bl = rect.bottomLeft().rotate(angle, c); return [tl, tr, br, bl]; }, toString: function(delimiter) { delimiter = delimiter || " "; return this.x + delimiter + this.y + delimiter + this.width + delimiter + this.height; }, scale: function(scaleX, scaleY, staicPoint, adornerCenter, angle) { var tl = this.topLeft(); var thisCenter = this.center(); tl.rotate(angle, thisCenter).rotate(angle, adornerCenter); var delta = staicPoint.minus(tl); var scaled = new ExtendedPoint(delta.x * scaleX, delta.y * scaleY); var position = delta.minus(scaled); tl = tl.plus(position); tl.rotate(angle, adornerCenter).rotate(angle, thisCenter); this.x = tl.x; this.y = tl.y; this.width *= scaleX; this.height *= scaleY; }, zoom: function(zoom) { this.x *= zoom; this.y *= zoom; this.width *= zoom; this.height *= zoom; return this; }, overlaps: function(rect) { var bottomRight = this.bottomRight(); var rectBottomRight = rect.bottomRight(); var overlaps = !(bottomRight.x < rect.x || bottomRight.y < rect.y || rectBottomRight.x < this.x || rectBottomRight.y < this.y); return overlaps; } }); var Size = Class.extend({ init: function(width, height) { this.width = width; this.height = height; } }); Size.prototype.Empty = new Size(0, 0); Rect.toRect = function(rect) { if (!(rect instanceof Rect)) { rect = new Rect(rect.x, rect.y, rect.width, rect.height); } return rect; }; Rect.empty = function() { return new Rect(0, 0, 0, 0); }; Rect.fromPoints = function(p, q) { if (isNaN(p.x) || isNaN(p.y) || isNaN(q.x) || isNaN(q.y)) { throw "Some values are NaN."; } return new Rect(Math.min(p.x, q.x), Math.min(p.y, q.y), Math.abs(p.x - q.x), Math.abs(p.y - q.y)); }; function isNearZero(num) { return Math.abs(num) < EPSILON; } function intersectLine(start1, end1, start2, end2, isSegment) { var tangensdiff = ((end1.x - start1.x) * (end2.y - start2.y)) - ((end1.y - start1.y) * (end2.x - start2.x)); if (isNearZero(tangensdiff)) { //parallel lines return; } var num1 = ((start1.y - start2.y) * (end2.x - start2.x)) - ((start1.x - start2.x) * (end2.y - start2.y)); var num2 = ((start1.y - start2.y) * (end1.x - start1.x)) - ((start1.x - start2.x) * (end1.y - start1.y)); var r = num1 / tangensdiff; var s = num2 / tangensdiff; if (isSegment && (r < 0 || r > 1 || s < 0 || s > 1)) { //r < 0 => line 1 is below line 2 //r > 1 => line 1 is above line 2 //s < 0 => line 2 is below line 1 //s > 1 => line 2 is above line 1 return; } return new ExtendedPoint(start1.x + (r * (end1.x - start1.x)), start1.y + (r * (end1.y - start1.y))); } var Intersect = { lines: function(start1, end1, start2, end2) { return intersectLine(start1, end1, start2, end2); }, segments: function(start1, end1, start2, end2) { return intersectLine(start1, end1, start2, end2, true); }, rectWithLine: function(rect, start, end) { return Intersect.segments(start, end, rect.topLeft(), rect.topRight()) || Intersect.segments(start, end, rect.topRight(), rect.bottomRight()) || Intersect.segments(start, end, rect.bottomLeft(), rect.bottomRight()) || Intersect.segments(start, end, rect.topLeft(), rect.bottomLeft()); }, rects: function(rect1, rect2, angle) { var tl = rect2.topLeft(), tr = rect2.topRight(), bl = rect2.bottomLeft(), br = rect2.bottomRight(); var center = rect2.center(); if (angle) { tl = tl.rotate(angle, center); tr = tr.rotate(angle, center); bl = bl.rotate(angle, center); br = br.rotate(angle, center); } var intersect = rect1.contains(tl) || rect1.contains(tr) || rect1.contains(bl) || rect1.contains(br) || Intersect.rectWithLine(rect1, tl, tr) || Intersect.rectWithLine(rect1, tl, bl) || Intersect.rectWithLine(rect1, tr, br) || Intersect.rectWithLine(rect1, bl, br); if (!intersect) {//last possible case is rect1 to be completely within rect2 tl = rect1.topLeft(); tr = rect1.topRight(); bl = rect1.bottomLeft(); br = rect1.bottomRight(); if (angle) { var reverseAngle = 360 - angle; tl = tl.rotate(reverseAngle, center); tr = tr.rotate(reverseAngle, center); bl = bl.rotate(reverseAngle, center); br = br.rotate(reverseAngle, center); } intersect = rect2.contains(tl) || rect2.contains(tr) || rect2.contains(bl) || rect2.contains(br); } return intersect; } }; /** * Aligns two rectangles, where one is the container and the other is content. */ var RectAlign = Class.extend({ init: function(container) { this.container = Rect.toRect(container); }, align: function(content, alignment) { var alignValues = alignment.toLowerCase().split(" "); for (var i = 0; i < alignValues.length; i++) { content = this._singleAlign(content, alignValues[i]); } return content; }, _singleAlign: function(content, alignment) { if (isFunction(this[alignment])) { return this[alignment](content); } else { return content; } }, left: function(content) { return this._align(content, this._left); }, center: function(content) { return this._align(content, this._center); }, right: function(content) { return this._align(content, this._right); }, stretch: function(content) { return this._align(content, this._stretch); }, top: function(content) { return this._align(content, this._top); }, middle: function(content) { return this._align(content, this._middle); }, bottom: function(content) { return this._align(content, this._bottom); }, _left: function(container, content) { content.x = container.x; }, _center: function(container, content) { content.x = ((container.width - content.width) / 2) || 0; }, _right: function(container, content) { content.x = container.width - content.width; }, _top: function(container, content) { content.y = container.y; }, _middle: function(container, content) { content.y = ((container.height - content.height) / 2) || 0; }, _bottom: function(container, content) { content.y = container.height - content.height; }, _stretch: function(container, content) { content.x = 0; content.y = 0; content.height = container.height; content.width = container.width; }, _align: function(content, alignCalc) { content = Rect.toRect(content); alignCalc(this.container, content); return content; } }); var Polar = Class.extend({ init: function(r, a) { this.r = r; this.angle = a; } }); /** * SVG transformation matrix. */ var Matrix = Class.extend({ init: function(a, b, c, d, e, f) { this.a = a || 0; this.b = b || 0; this.c = c || 0; this.d = d || 0; this.e = e || 0; this.f = f || 0; }, plus: function(m) { this.a += m.a; this.b += m.b; this.c += m.c; this.d += m.d; this.e += m.e; this.f += m.f; }, minus: function(m) { this.a -= m.a; this.b -= m.b; this.c -= m.c; this.d -= m.d; this.e -= m.e; this.f -= m.f; }, times: function(m) { return new Matrix( this.a * m.a + this.c * m.b, this.b * m.a + this.d * m.b, this.a * m.c + this.c * m.d, this.b * m.c + this.d * m.d, this.a * m.e + this.c * m.f + this.e, this.b * m.e + this.d * m.f + this.f ); }, apply: function(p) { return new ExtendedPoint(this.a * p.x + this.c * p.y + this.e, this.b * p.x + this.d * p.y + this.f); }, applyRect: function(r) { return Rect.fromPoints(this.apply(r.topLeft()), this.apply(r.bottomRight())); }, toString: function() { return "matrix(" + this.a + " " + this.b + " " + this.c + " " + this.d + " " + this.e + " " + this.f + ")"; } }); deepExtend(Matrix, { fromSVGMatrix: function(vm) { var m = new Matrix(); m.a = vm.a; m.b = vm.b; m.c = vm.c; m.d = vm.d; m.e = vm.e; m.f = vm.f; return m; }, fromMatrixVector: function(v) { var m = new Matrix(); m.a = v.a; m.b = v.b; m.c = v.c; m.d = v.d; m.e = v.e; m.f = v.f; return m; }, fromList: function(v) { if (v.length !== 6) { throw "The given list should consist of six elements."; } var m = new Matrix(); m.a = v[0]; m.b = v[1]; m.c = v[2]; m.d = v[3]; m.e = v[4]; m.f = v[5]; return m; }, translation: function(x, y) { var m = new Matrix(); m.a = 1; m.b = 0; m.c = 0; m.d = 1; m.e = x; m.f = y; return m; }, unit: function() { return new Matrix(1, 0, 0, 1, 0, 0); }, rotation: function(angle, x, y) { var m = new Matrix(); m.a = Math.cos(angle * Math.PI / 180); m.b = Math.sin(angle * Math.PI / 180); m.c = -m.b; m.d = m.a; m.e = (x - x * m.a + y * m.b) || 0; m.f = (y - y * m.a - x * m.b) || 0; return m; }, scaling: function(scaleX, scaleY) { var m = new Matrix(); m.a = scaleX; m.b = 0; m.c = 0; m.d = scaleY; m.e = 0; m.f = 0; return m; }, parse: function(v) { var parts, nums; if (v) { v = v.trim(); // of the form "matrix(...)" if (v.slice(0, 6).toLowerCase() === "matrix") { nums = v.slice(7, v.length - 1).trim(); parts = nums.split(","); if (parts.length === 6) { return Matrix.fromList(map(parts, function(p) { return parseFloat(p); })); } parts = nums.split(" "); if (parts.length === 6) { return Matrix.fromList(map(parts, function(p) { return parseFloat(p); })); } } // of the form "(...)" if (v.slice(0, 1) === "(" && v.slice(v.length - 1) === ")") { v = v.substr(1, v.length - 1); } if (v.indexOf(",") > 0) { parts = v.split(","); if (parts.length === 6) { return Matrix.fromList(map(parts, function(p) { return parseFloat(p); })); } } if (v.indexOf(" ") > 0) { parts = v.split(" "); if (parts.length === 6) { return Matrix.fromList(map(parts, function(p) { return parseFloat(p); })); } } } return parts; } }); /** * SVG transformation represented as a vector. */ var MatrixVector = Class.extend({ init: function(a, b, c, d, e, f) { this.a = a || 0; this.b = b || 0; this.c = c || 0; this.d = d || 0; this.e = e || 0; this.f = f || 0; }, fromMatrix: function FromMatrix(m) { var v = new MatrixVector(); v.a = m.a; v.b = m.b; v.c = m.c; v.d = m.d; v.e = m.e; v.f = m.f; return v; } }); /** * Returns a value with Gaussian (normal) distribution. * @param mean The mean value of the distribution. * @param deviation The deviation (spreading at half-height) of the distribution. * @returns {number} */ function normalVariable(mean, deviation) { var x, y, r; do { x = Math.random() * 2 - 1; y = Math.random() * 2 - 1; r = x * x + y * y; } while (!r || r > 1); return mean + deviation * x * Math.sqrt(-2 * Math.log(r) / r); } /** * Returns a random identifier which can be used as an ID of objects, eventually augmented with a prefix. * @returns {string} */ function randomId(length) { if (Utils.isUndefined(length)) { length = 10; } // old version return Math.floor((1 + Math.random()) * 0x1000000).toString(16).substring(1); var result = ''; var chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; for (var i = length; i > 0; --i) { result += chars.charAt(Math.round(Math.random() * (chars.length - 1))); } return result; } var Geometry = { /** * Returns the squared distance to the line defined by the two given Points. * @param p An arbitrary Point. * @param a An endpoint of the line or segment. * @param b The complementary endpoint of the line or segment. */ _distanceToLineSquared: function(p, a, b) { function d2(pt1, pt2) { return (pt1.x - pt2.x) * (pt1.x - pt2.x) + (pt1.y - pt2.y) * (pt1.y - pt2.y); } if (a === b) { // returns the distance of p to a return d2(p, a); } var vx = b.x - a.x, vy = b.y - a.y, dot = (p.x - a.x) * vx + (p.y - a.y) * vy; if (dot < 0) { return d2(a, p); // sits on side of a } dot = (b.x - p.x) * vx + (b.y - p.y) * vy; if (dot < 0) { return d2(b, p); // sits on side of b } // regular case, use crossproduct to get the sine out dot = (b.x - p.x) * vy - (b.y - p.y) * vx; return dot * dot / (vx * vx + vy * vy); }, /** * Returns the distance to the line defined by the two given Points. * @param p An arbitrary Point. * @param a An endpoint of the line or segment. * @param b The complementary endpoint of the line or segment. */ distanceToLine: function(p, a, b) { return Math.sqrt(this._distanceToLineSquared(p, a, b)); }, /** * Returns the distance of the given points to the polyline defined by the points. * @param p An arbitrary point. * @param points The points defining the polyline. * @returns {Number} */ distanceToPolyline: function(p, points) { var minimum = Number.MAX_VALUE; if (Utils.isUndefined(points) || points.length === 0) { return Number.MAX_VALUE; } for (var s = 0; s < points.length - 1; s++) { var p1 = points[s]; var p2 = points[s + 1]; var d = this._distanceToLineSquared(p, p1, p2); if (d < minimum) { minimum = d; } } return Math.sqrt(minimum); } }; /*---------------The HashTable structure--------------------------------*/ /** * Represents a collection of key-value pairs that are organized based on the hash code of the key. * _buckets[hashId] = {key: key, value:...} * Important: do not use the standard Array access method, use the get/set methods instead. * See http://en.wikipedia.org/wiki/Hash_table */ var HashTable = kendo.Class.extend({ init: function() { this._buckets = []; this.length = 0; }, /** * Adds the literal object with the given key (of the form {key: key,....}). */ add: function(key, value) { var obj = this._createGetBucket(key); if (Utils.isDefined(value)) { obj.value = value; } return obj; }, /** * Gets the literal object with the given key. */ get: function(key) { if (this._bucketExists(key)) { return this._createGetBucket(key); } return null; }, /** * Set the key-value pair. * @param key The key of the entry. * @param value The value to set. If the key already exists the value will be overwritten. */ set: function(key, value) { this.add(key, value); }, /** * Determines whether the HashTable contains a specific key. */ containsKey: function(key) { return this._bucketExists(key); }, /** * Removes the element with the specified key from the hashtable. * Returns the removed bucket. */ remove: function(key) { if (this._bucketExists(key)) { var hashId = this._hash(key); delete this._buckets[hashId]; this.length--; return key; } }, /** * Foreach with an iterator working on the key-value pairs. * @param func */ forEach: function(func) { var hashes = this._hashes(); for (var i = 0, len = hashes.length; i < len; i++) { var hash = hashes[i]; var bucket = this._buckets[hash]; if (Utils.isUndefined(bucket)) { continue; } func(bucket); } }, /** * Returns a (shallow) clone of the current HashTable. * @returns {HashTable} */ clone: function() { var ht = new HashTable(); var hashes = this._hashes(); for (var i = 0, len = hashes.length; i < len; i++) { var hash = hashes[i]; var bucket = this._buckets[hash]; if (Utils.isUndefined(bucket)) { continue; } ht.add(bucket.key, bucket.value); } return ht; }, /** * Returns the hashes of the buckets. * @returns {Array} * @private */ _hashes: function() { var hashes = []; for (var hash in this._buckets) { if (this._buckets.hasOwnProperty(hash)) { hashes.push(hash); } } return hashes; }, _bucketExists: function(key) { var hashId = this._hash(key); return Utils.isDefined(this._buckets[hashId]); }, /** * Returns-adds the createGetBucket with the given key. If not present it will * be created and returned. * A createGetBucket is a literal object of the form {key: key, ...}. */ _createGetBucket: function(key) { var hashId = this._hash(key); var bucket = this._buckets[hashId]; if (Utils.isUndefined(bucket)) { bucket = { key: key }; this._buckets[hashId] = bucket; this.length++; } return bucket; }, /** * Hashing of the given key. */ _hash: function(key) { if (Utils.isNumber(key)) { return key; } if (Utils.isString(key)) { return this._hashString(key); } if (Utils.isObject(key)) { return this._objectHashId(key); } throw "Unsupported key type."; }, /** * Hashing of a string. */ _hashString: function(s) { // see for example http://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript-jquery var result = 0; if (s.length === 0) { return result; } for (var i = 0; i < s.length; i++) { var ch = s.charCodeAt(i); result = ((result * 32) - result) + ch; } return result; }, /** * Returns the unique identifier for an object. This is automatically assigned and add on the object. */ _objectHashId: function(key) { var id = key._hashId; if (Utils.isUndefined(id)) { id = randomId(); key._hashId = id; } return id; } }); /*---------------The Dictionary structure--------------------------------*/ /** * Represents a collection of key-value pairs. * Important: do not use the standard Array access method, use the get/Set methods instead. */ var Dictionary = kendo.Observable.extend({ /** * Initializes a new instance of the Dictionary class. * @param dictionary Loads the content of the given dictionary into this new one. */ init: function(dictionary) { var that = this; kendo.Observable.fn.init.call(that); this._hashTable = new HashTable(); this.length = 0; if (Utils.isDefined(dictionary)) { if (Array.isArray(dictionary)) { for (var i = 0; i < dictionary.length; i++) { this.add(dictionary[i]); } } else { dictionary.forEach(function(k, v) { this.add(k, v); }, this); } } }, /** * Adds a key-value to the dictionary. * If the key already exists this will assign the given value to the existing entry. */ add: function(key, value) { var entry = this._hashTable.get(key); if (!entry) { entry = this._hashTable.add(key); this.length++; this.trigger('changed'); } entry.value = value; }, /** * Set the key-value pair. * @param key The key of the entry. * @param value The value to set. If the key already exists the value will be overwritten. */ set: functio