@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,447 loc) • 611 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
require('./kendo.data.js');
require('./kendo.draganddrop.js');
require('./kendo.userevents.js');
require('./kendo.mobile.scroller.js');
require('./kendo.core.js');
require('./kendo.dataviz.core.js');
require('./html-sdnHcjkh.js');
require('./kendo.toolbar.js');
require('./kendo.editable.js');
require('./kendo.window.js');
require('./kendo.dropdownlist.js');
require('./kendo.dataviz.themes.js');
require('./kendo.html.button.js');
require('./kendo.data.odata.js');
require('./kendo.licensing.js');
require('@progress/kendo-licensing');
require('./kendo.data.xml.js');
require('./kendo.fx.js');
require('@progress/kendo-charts/dist/es/core-export.js');
require('./kendo.popup.js');
require('./kendo.icons.js');
require('./kendo.html.icon.js');
require('./kendo.html.base.js');
require('@progress/kendo-svg-icons');
require('@progress/kendo-drawing');
require('./kendo.color.js');
require('./kendo.splitbutton.js');
require('./kendo.button.menu.js');
require('./kendo.dropdownbutton.js');
require('./kendo.buttongroup.js');
require('./kendo.togglebutton.js');
require('./kendo.button.js');
require('./kendo.badge.js');
require('./kendo.menu.js');
require('./kendo.checkbox.js');
require('./kendo.toggleinputbase.js');
require('./kendo.html.input.js');
require('./kendo.datepicker.js');
require('./kendo.calendar.js');
require('./kendo.selectable.js');
require('./kendo.dateinput.js');
require('./kendo.label.js');
require('./kendo.floatinglabel.js');
require('@progress/kendo-dateinputs-common');
require('./kendo.actionsheet.js');
require('./kendo.numerictextbox.js');
require('./prefix-suffix-containers-BmDm564f.js');
require('./kendo.textbox.js');
require('./kendo.validator.js');
require('./kendo.binder.js');
require('./kendo.otpinput.js');
require('./kendo.list.js');
require('./dropdowns-loader-Bc4IELFi.js');
require('./kendo.virtuallist.js');
require('./valueMapper-q_OtZ-Tj.js');
require('@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