@progress/kendo-ui
Version:
This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.
1,646 lines (1,337 loc) • 173 kB
JavaScript
module.exports =
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ({
/***/ 0:
/***/ (function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(1046);
/***/ }),
/***/ 3:
/***/ (function(module, exports) {
module.exports = function() { throw new Error("define cannot be used indirect"); };
/***/ }),
/***/ 1004:
/***/ (function(module, exports) {
module.exports = require("./kendo.core");
/***/ }),
/***/ 1046:
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function(f, define){
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(1004), __webpack_require__(1047), __webpack_require__(1048) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (f), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
})(function(){
var __meta__ = { // jshint ignore:line
id: "data",
name: "Data source",
category: "framework",
description: "Powerful component for using local and remote data.Fully supports CRUD, Sorting, Paging, Filtering, Grouping, and Aggregates.",
depends: [ "core" ],
features: [ {
id: "data-odata",
name: "OData",
description: "Support for accessing Open Data Protocol (OData) services.",
depends: [ "data.odata" ]
}, {
id: "data-signalr",
name: "SignalR",
description: "Support for binding to SignalR hubs.",
depends: [ "data.signalr" ]
}, {
id: "data-XML",
name: "XML",
description: "Support for binding to XML.",
depends: [ "data.xml" ]
}]
};
/*jshint eqnull: true, loopfunc: true, evil: true */
(function($, undefined) {
var extend = $.extend,
proxy = $.proxy,
isPlainObject = $.isPlainObject,
isEmptyObject = $.isEmptyObject,
isArray = $.isArray,
grep = $.grep,
ajax = $.ajax,
map,
each = $.each,
noop = $.noop,
kendo = window.kendo,
isFunction = kendo.isFunction,
Observable = kendo.Observable,
Class = kendo.Class,
STRING = "string",
FUNCTION = "function",
CREATE = "create",
READ = "read",
UPDATE = "update",
DESTROY = "destroy",
CHANGE = "change",
SYNC = "sync",
GET = "get",
ERROR = "error",
REQUESTSTART = "requestStart",
PROGRESS = "progress",
REQUESTEND = "requestEnd",
crud = [CREATE, READ, UPDATE, DESTROY],
identity = function(o) { return o; },
getter = kendo.getter,
stringify = kendo.stringify,
math = Math,
push = [].push,
join = [].join,
pop = [].pop,
splice = [].splice,
shift = [].shift,
slice = [].slice,
unshift = [].unshift,
toString = {}.toString,
stableSort = kendo.support.stableSort,
dateRegExp = /^\/Date\((.*?)\)\/$/;
var ObservableArray = Observable.extend({
init: function(array, type) {
var that = this;
that.type = type || ObservableObject;
Observable.fn.init.call(that);
that.length = array.length;
that.wrapAll(array, that);
},
at: function(index) {
return this[index];
},
toJSON: function() {
var idx, length = this.length, value, json = new Array(length);
for (idx = 0; idx < length; idx++){
value = this[idx];
if (value instanceof ObservableObject) {
value = value.toJSON();
}
json[idx] = value;
}
return json;
},
parent: noop,
wrapAll: function(source, target) {
var that = this,
idx,
length,
parent = function() {
return that;
};
target = target || [];
for (idx = 0, length = source.length; idx < length; idx++) {
target[idx] = that.wrap(source[idx], parent);
}
return target;
},
wrap: function(object, parent) {
var that = this,
observable;
if (object !== null && toString.call(object) === "[object Object]") {
observable = object instanceof that.type || object instanceof Model;
if (!observable) {
object = object instanceof ObservableObject ? object.toJSON() : object;
object = new that.type(object);
}
object.parent = parent;
object.bind(CHANGE, function(e) {
that.trigger(CHANGE, {
field: e.field,
node: e.node,
index: e.index,
items: e.items || [this],
action: e.node ? (e.action || "itemloaded") : "itemchange"
});
});
}
return object;
},
push: function() {
var index = this.length,
items = this.wrapAll(arguments),
result;
result = push.apply(this, items);
this.trigger(CHANGE, {
action: "add",
index: index,
items: items
});
return result;
},
slice: slice,
sort: [].sort,
join: join,
pop: function() {
var length = this.length, result = pop.apply(this);
if (length) {
this.trigger(CHANGE, {
action: "remove",
index: length - 1,
items:[result]
});
}
return result;
},
splice: function(index, howMany, item) {
var items = this.wrapAll(slice.call(arguments, 2)),
result, i, len;
result = splice.apply(this, [index, howMany].concat(items));
if (result.length) {
this.trigger(CHANGE, {
action: "remove",
index: index,
items: result
});
for (i = 0, len = result.length; i < len; i++) {
if (result[i] && result[i].children) {
result[i].unbind(CHANGE);
}
}
}
if (item) {
this.trigger(CHANGE, {
action: "add",
index: index,
items: items
});
}
return result;
},
shift: function() {
var length = this.length, result = shift.apply(this);
if (length) {
this.trigger(CHANGE, {
action: "remove",
index: 0,
items:[result]
});
}
return result;
},
unshift: function() {
var items = this.wrapAll(arguments),
result;
result = unshift.apply(this, items);
this.trigger(CHANGE, {
action: "add",
index: 0,
items: items
});
return result;
},
indexOf: function(item) {
var that = this,
idx,
length;
for (idx = 0, length = that.length; idx < length; idx++) {
if (that[idx] === item) {
return idx;
}
}
return -1;
},
forEach: function(callback, thisArg) {
var idx = 0;
var length = this.length;
var context = thisArg || window;
for (; idx < length; idx++) {
callback.call(context, this[idx], idx, this);
}
},
map: function(callback, thisArg) {
var idx = 0;
var result = [];
var length = this.length;
var context = thisArg || window;
for (; idx < length; idx++) {
result[idx] = callback.call(context, this[idx], idx, this);
}
return result;
},
reduce: function(callback) {
var idx = 0,
result,
length = this.length;
if (arguments.length == 2) {
result = arguments[1];
} else if (idx < length) {
result = this[idx++];
}
for (; idx < length; idx++) {
result = callback(result, this[idx], idx, this);
}
return result;
},
reduceRight: function(callback) {
var idx = this.length - 1,
result;
if (arguments.length == 2) {
result = arguments[1];
} else if (idx > 0) {
result = this[idx--];
}
for (; idx >= 0; idx--) {
result = callback(result, this[idx], idx, this);
}
return result;
},
filter: function(callback, thisArg) {
var idx = 0;
var result = [];
var item;
var length = this.length;
var context = thisArg || window;
for (; idx < length; idx++) {
item = this[idx];
if (callback.call(context, item, idx, this)) {
result[result.length] = item;
}
}
return result;
},
find: function(callback, thisArg) {
var idx = 0;
var item;
var length = this.length;
var context = thisArg || window;
for (; idx < length; idx++) {
item = this[idx];
if (callback.call(context, item, idx, this)) {
return item;
}
}
},
every: function(callback, thisArg) {
var idx = 0;
var item;
var length = this.length;
var context = thisArg || window;
for (; idx < length; idx++) {
item = this[idx];
if (!callback.call(context, item, idx, this)) {
return false;
}
}
return true;
},
some: function(callback, thisArg) {
var idx = 0;
var item;
var length = this.length;
var context = thisArg || window;
for (; idx < length; idx++) {
item = this[idx];
if (callback.call(context, item, idx, this)) {
return true;
}
}
return false;
},
// non-standard collection methods
remove: function(item) {
var idx = this.indexOf(item);
if (idx !== -1) {
this.splice(idx, 1);
}
},
empty: function() {
this.splice(0, this.length);
}
});
// Polyfill for Symbol.iterator
if (typeof Symbol !== "undefined" && Symbol.iterator && !ObservableArray.prototype[Symbol.iterator]) {
ObservableArray.prototype[Symbol.iterator] = [][Symbol.iterator];
}
var LazyObservableArray = ObservableArray.extend({
init: function(data, type) {
Observable.fn.init.call(this);
this.type = type || ObservableObject;
for (var idx = 0; idx < data.length; idx++) {
this[idx] = data[idx];
}
this.length = idx;
this._parent = proxy(function() { return this; }, this);
},
at: function(index) {
var item = this[index];
if (!(item instanceof this.type)) {
item = this[index] = this.wrap(item, this._parent);
} else {
item.parent = this._parent;
}
return item;
}
});
function eventHandler(context, type, field, prefix) {
return function(e) {
var event = {}, key;
for (key in e) {
event[key] = e[key];
}
if (prefix) {
event.field = field + "." + e.field;
} else {
event.field = field;
}
if (type == CHANGE && context._notifyChange) {
context._notifyChange(event);
}
context.trigger(type, event);
};
}
var ObservableObject = Observable.extend({
init: function(value) {
var that = this,
member,
field,
parent = function() {
return that;
};
Observable.fn.init.call(this);
this._handlers = {};
for (field in value) {
member = value[field];
if (typeof member === "object" && member && !member.getTime && field.charAt(0) != "_") {
member = that.wrap(member, field, parent);
}
that[field] = member;
}
that.uid = kendo.guid();
},
shouldSerialize: function(field) {
return this.hasOwnProperty(field) && field !== "_handlers" && field !== "_events" && typeof this[field] !== FUNCTION && field !== "uid";
},
forEach: function(f) {
for (var i in this) {
if (this.shouldSerialize(i)) {
f(this[i], i);
}
}
},
toJSON: function() {
var result = {}, value, field;
for (field in this) {
if (this.shouldSerialize(field)) {
value = this[field];
if (value instanceof ObservableObject || value instanceof ObservableArray) {
value = value.toJSON();
}
result[field] = value;
}
}
return result;
},
get: function(field) {
var that = this, result;
that.trigger(GET, { field: field });
if (field === "this") {
result = that;
} else {
result = kendo.getter(field, true)(that);
}
return result;
},
_set: function(field, value) {
var that = this;
var composite = field.indexOf(".") >= 0;
if (composite) {
var paths = field.split("."),
path = "";
while (paths.length > 1) {
path += paths.shift();
var obj = kendo.getter(path, true)(that);
if (obj instanceof ObservableObject) {
obj.set(paths.join("."), value);
return composite;
}
path += ".";
}
}
kendo.setter(field)(that, value);
return composite;
},
set: function(field, value) {
var that = this,
isSetPrevented = false,
composite = field.indexOf(".") >= 0,
current = kendo.getter(field, true)(that);
if (current !== value) {
if (current instanceof Observable && this._handlers[field]) {
if (this._handlers[field].get) {
current.unbind(GET, this._handlers[field].get);
}
current.unbind(CHANGE, this._handlers[field].change);
}
isSetPrevented = that.trigger("set", { field: field, value: value });
if (!isSetPrevented) {
if (!composite) {
value = that.wrap(value, field, function() { return that; });
}
if (!that._set(field, value) || field.indexOf("(") >= 0 || field.indexOf("[") >= 0) {
that.trigger(CHANGE, { field: field });
}
}
}
return isSetPrevented;
},
parent: noop,
wrap: function(object, field, parent) {
var that = this;
var get;
var change;
var type = toString.call(object);
if (object != null && (type === "[object Object]" || type === "[object Array]")) {
var isObservableArray = object instanceof ObservableArray;
var isDataSource = object instanceof DataSource;
if (type === "[object Object]" && !isDataSource && !isObservableArray) {
if (!(object instanceof ObservableObject)) {
object = new ObservableObject(object);
}
get = eventHandler(that, GET, field, true);
object.bind(GET, get);
change = eventHandler(that, CHANGE, field, true);
object.bind(CHANGE, change);
that._handlers[field] = { get: get, change: change };
} else if (type === "[object Array]" || isObservableArray || isDataSource) {
if (!isObservableArray && !isDataSource) {
object = new ObservableArray(object);
}
change = eventHandler(that, CHANGE, field, false);
object.bind(CHANGE, change);
that._handlers[field] = { change: change };
}
object.parent = parent;
}
return object;
}
});
function equal(x, y) {
if (x === y) {
return true;
}
var xtype = $.type(x), ytype = $.type(y), field;
if (xtype !== ytype) {
return false;
}
if (xtype === "date") {
return x.getTime() === y.getTime();
}
if (xtype !== "object" && xtype !== "array") {
return false;
}
for (field in x) {
if (!equal(x[field], y[field])) {
return false;
}
}
return true;
}
var parsers = {
"number": function(value) {
if (typeof value === STRING && value.toLowerCase() === "null") {
return null;
}
return kendo.parseFloat(value);
},
"date": function(value) {
if (typeof value === STRING && value.toLowerCase() === "null") {
return null;
}
return kendo.parseDate(value);
},
"boolean": function(value) {
if (typeof value === STRING) {
if (value.toLowerCase() === "null") {
return null;
} else {
return value.toLowerCase() === "true";
}
}
return value != null ? !!value : value;
},
"string": function(value) {
if (typeof value === STRING && value.toLowerCase() === "null") {
return null;
}
return value != null ? (value + "") : value;
},
"default": function(value) {
return value;
}
};
var defaultValues = {
"string": "",
"number": 0,
"date": new Date(),
"boolean": false,
"default": ""
};
function getFieldByName(obj, name) {
var field,
fieldName;
for (fieldName in obj) {
field = obj[fieldName];
if (isPlainObject(field) && field.field && field.field === name) {
return field;
} else if (field === name) {
return field;
}
}
return null;
}
var Model = ObservableObject.extend({
init: function(data) {
var that = this;
if (!data || $.isEmptyObject(data)) {
data = $.extend({}, that.defaults, data);
if (that._initializers) {
for (var idx = 0; idx < that._initializers.length; idx++) {
var name = that._initializers[idx];
data[name] = that.defaults[name]();
}
}
}
ObservableObject.fn.init.call(that, data);
that.dirty = false;
that.dirtyFields = {};
if (that.idField) {
that.id = that.get(that.idField);
if (that.id === undefined) {
that.id = that._defaultId;
}
}
},
shouldSerialize: function(field) {
return ObservableObject.fn.shouldSerialize.call(this, field) &&
field !== "uid" && !(this.idField !== "id" && field === "id") &&
field !== "dirty" && field !== "dirtyFields" && field !== "_accessors";
},
_parse: function(field, value) {
var that = this,
fieldName = field,
fields = (that.fields || {}),
parse;
field = fields[field];
if (!field) {
field = getFieldByName(fields, fieldName);
}
if (field) {
parse = field.parse;
if (!parse && field.type) {
parse = parsers[field.type.toLowerCase()];
}
}
return parse ? parse(value) : value;
},
_notifyChange: function(e) {
var action = e.action;
if (action == "add" || action == "remove") {
this.dirty = true;
this.dirtyFields[e.field] = true;
}
},
editable: function(field) {
field = (this.fields || {})[field];
return field ? field.editable !== false : true;
},
set: function(field, value, initiator) {
var that = this;
var dirty = that.dirty;
if (that.editable(field)) {
value = that._parse(field, value);
if (!equal(value, that.get(field))) {
that.dirty = true;
that.dirtyFields[field] = true;
if (ObservableObject.fn.set.call(that, field, value, initiator) && !dirty) {
that.dirty = dirty;
if (!that.dirty) {
that.dirtyFields[field] = false;
}
}
} else {
that.trigger("equalSet", { field: field, value: value });
}
}
},
accept: function(data) {
var that = this,
parent = function() { return that; },
field;
for (field in data) {
var value = data[field];
if (field.charAt(0) != "_") {
value = that.wrap(data[field], field, parent);
}
that._set(field, value);
}
if (that.idField) {
that.id = that.get(that.idField);
}
that.dirty = false;
that.dirtyFields = {};
},
isNew: function() {
return this.id === this._defaultId;
}
});
Model.define = function(base, options) {
if (options === undefined) {
options = base;
base = Model;
}
var model,
proto = extend({ defaults: {} }, options),
name,
field,
type,
value,
idx,
length,
fields = {},
originalName,
id = proto.id,
functionFields = [];
if (id) {
proto.idField = id;
}
if (proto.id) {
delete proto.id;
}
if (id) {
proto.defaults[id] = proto._defaultId = "";
}
if (toString.call(proto.fields) === "[object Array]") {
for (idx = 0, length = proto.fields.length; idx < length; idx++) {
field = proto.fields[idx];
if (typeof field === STRING) {
fields[field] = {};
} else if (field.field) {
fields[field.field] = field;
}
}
proto.fields = fields;
}
for (name in proto.fields) {
field = proto.fields[name];
type = field.type || "default";
value = null;
originalName = name;
name = typeof (field.field) === STRING ? field.field : name;
if (!field.nullable) {
value = proto.defaults[originalName !== name ? originalName : name] = field.defaultValue !== undefined ? field.defaultValue : defaultValues[type.toLowerCase()];
if (typeof value === "function") {
functionFields.push(name);
}
}
if (options.id === name) {
proto._defaultId = value;
}
proto.defaults[originalName !== name ? originalName : name] = value;
field.parse = field.parse || parsers[type];
}
if (functionFields.length > 0) {
proto._initializers = functionFields;
}
model = base.extend(proto);
model.define = function(options) {
return Model.define(model, options);
};
if (proto.fields) {
model.fields = proto.fields;
model.idField = proto.idField;
}
return model;
};
var Comparer = {
selector: function(field) {
return isFunction(field) ? field : getter(field);
},
compare: function(field) {
var selector = this.selector(field);
return function (a, b) {
a = selector(a);
b = selector(b);
if (a == null && b == null) {
return 0;
}
if (a == null) {
return -1;
}
if (b == null) {
return 1;
}
if (a.localeCompare) {
return a.localeCompare(b);
}
return a > b ? 1 : (a < b ? -1 : 0);
};
},
create: function(sort) {
var compare = sort.compare || this.compare(sort.field);
if (sort.dir == "desc") {
return function(a, b) {
return compare(b, a, true);
};
}
return compare;
},
combine: function(comparers) {
return function(a, b) {
var result = comparers[0](a, b),
idx,
length;
for (idx = 1, length = comparers.length; idx < length; idx ++) {
result = result || comparers[idx](a, b);
}
return result;
};
}
};
var StableComparer = extend({}, Comparer, {
asc: function(field) {
var selector = this.selector(field);
return function (a, b) {
var valueA = selector(a);
var valueB = selector(b);
if (valueA && valueA.getTime && valueB && valueB.getTime) {
valueA = valueA.getTime();
valueB = valueB.getTime();
}
if (valueA === valueB) {
return a.__position - b.__position;
}
if (valueA == null) {
return -1;
}
if (valueB == null) {
return 1;
}
if (valueA.localeCompare) {
return valueA.localeCompare(valueB);
}
return valueA > valueB ? 1 : -1;
};
},
desc: function(field) {
var selector = this.selector(field);
return function (a, b) {
var valueA = selector(a);
var valueB = selector(b);
if (valueA && valueA.getTime && valueB && valueB.getTime) {
valueA = valueA.getTime();
valueB = valueB.getTime();
}
if (valueA === valueB) {
return a.__position - b.__position;
}
if (valueA == null) {
return 1;
}
if (valueB == null) {
return -1;
}
if (valueB.localeCompare) {
return valueB.localeCompare(valueA);
}
return valueA < valueB ? 1 : -1;
};
},
create: function(sort) {
return this[sort.dir](sort.field);
}
});
map = function (array, callback) {
var idx, length = array.length, result = new Array(length);
for (idx = 0; idx < length; idx++) {
result[idx] = callback(array[idx], idx, array);
}
return result;
};
var operators = (function(){
function quote(str) {
if (typeof str == "string") {
str = str.replace(/[\r\n]+/g, "");
}
return JSON.stringify(str);
}
function textOp(impl) {
return function(a, b, ignore) {
b += "";
if (ignore) {
a = "(" + a + " || '').toString().toLowerCase()";
b = b.toLowerCase();
}
return impl(a, quote(b), ignore);
};
}
function operator(op, a, b, ignore) {
if (b != null) {
if (typeof b === STRING) {
var date = dateRegExp.exec(b);
if (date) {
b = new Date(+date[1]);
} else if (ignore) {
b = quote(b.toLowerCase());
a = "((" + a + " || '')+'').toLowerCase()";
} else {
b = quote(b);
}
}
if (b.getTime) {
//b looks like a Date
a = "(" + a + "&&" + a + ".getTime?" + a + ".getTime():" + a + ")";
b = b.getTime();
}
}
return a + " " + op + " " + b;
}
function getMatchRegexp(pattern) {
// take a pattern, as supported by Excel match filter, and
// convert it to the equivalent JS regular expression.
// Excel patterns support:
//
// * - match any sequence of characters
// ? - match a single character
//
// to match a literal * or ?, they must be prefixed by a tilde (~)
for (var rx = "/^", esc = false, i = 0; i < pattern.length; ++i) {
var ch = pattern.charAt(i);
if (esc) {
rx += "\\" + ch;
} else if (ch == "~") {
esc = true;
continue;
} else if (ch == "*") {
rx += ".*";
} else if (ch == "?") {
rx += ".";
} else if (".+^$()[]{}|\\/\n\r\u2028\u2029\xA0".indexOf(ch) >= 0) {
rx += "\\" + ch;
} else {
rx += ch;
}
esc = false;
}
return rx + "$/";
}
return {
quote: function(value) {
if (value && value.getTime) {
return "new Date(" + value.getTime() + ")";
}
return quote(value);
},
eq: function(a, b, ignore) {
return operator("==", a, b, ignore);
},
neq: function(a, b, ignore) {
return operator("!=", a, b, ignore);
},
gt: function(a, b, ignore) {
return operator(">", a, b, ignore);
},
gte: function(a, b, ignore) {
return operator(">=", a, b, ignore);
},
lt: function(a, b, ignore) {
return operator("<", a, b, ignore);
},
lte: function(a, b, ignore) {
return operator("<=", a, b, ignore);
},
startswith: textOp(function(a, b) {
return a + ".lastIndexOf(" + b + ", 0) == 0";
}),
doesnotstartwith: textOp(function(a, b) {
return a + ".lastIndexOf(" + b + ", 0) == -1";
}),
endswith: textOp(function(a, b) {
var n = b ? b.length - 2 : 0;
return a + ".indexOf(" + b + ", " + a + ".length - " + n + ") >= 0";
}),
doesnotendwith: textOp(function(a, b) {
var n = b ? b.length - 2 : 0;
return a + ".indexOf(" + b + ", " + a + ".length - " + n + ") < 0";
}),
contains: textOp(function(a, b) {
return a + ".indexOf(" + b + ") >= 0";
}),
doesnotcontain: textOp(function(a, b) {
return a + ".indexOf(" + b + ") == -1";
}),
matches: textOp(function(a, b){
b = b.substring(1, b.length - 1);
return getMatchRegexp(b) + ".test(" + a + ")";
}),
doesnotmatch: textOp(function(a, b){
b = b.substring(1, b.length - 1);
return "!" + getMatchRegexp(b) + ".test(" + a + ")";
}),
isempty: function(a) {
return a + " === ''";
},
isnotempty: function(a) {
return a + " !== ''";
},
isnull: function(a) {
return "(" + a + " == null)";
},
isnotnull: function(a) {
return "(" + a + " != null)";
},
isnullorempty: function(a) {
return "(" + a + " === null) || (" + a + " === '')";
},
isnotnullorempty: function(a) {
return "(" + a + " !== null) && (" + a + " !== '')";
}
};
})();
function Query(data) {
this.data = data || [];
}
Query.filterExpr = function(expression) {
var expressions = [],
logic = { and: " && ", or: " || " },
idx,
length,
filter,
expr,
fieldFunctions = [],
operatorFunctions = [],
field,
operator,
filters = expression.filters;
for (idx = 0, length = filters.length; idx < length; idx++) {
filter = filters[idx];
field = filter.field;
operator = filter.operator;
if (filter.filters) {
expr = Query.filterExpr(filter);
//Nested function fields or operators - update their index e.g. __o[0] -> __o[1]
filter = expr.expression
.replace(/__o\[(\d+)\]/g, function(match, index) {
index = +index;
return "__o[" + (operatorFunctions.length + index) + "]";
})
.replace(/__f\[(\d+)\]/g, function(match, index) {
index = +index;
return "__f[" + (fieldFunctions.length + index) + "]";
});
operatorFunctions.push.apply(operatorFunctions, expr.operators);
fieldFunctions.push.apply(fieldFunctions, expr.fields);
} else {
if (typeof field === FUNCTION) {
expr = "__f[" + fieldFunctions.length +"](d)";
fieldFunctions.push(field);
} else {
expr = kendo.expr(field);
}
if (typeof operator === FUNCTION) {
filter = "__o[" + operatorFunctions.length + "](" + expr + ", " + operators.quote(filter.value) + ")";
operatorFunctions.push(operator);
} else {
filter = operators[(operator || "eq").toLowerCase()](expr, filter.value, filter.ignoreCase !== undefined? filter.ignoreCase : true);
}
}
expressions.push(filter);
}
return { expression: "(" + expressions.join(logic[expression.logic]) + ")", fields: fieldFunctions, operators: operatorFunctions };
};
function normalizeSort(field, dir) {
if (field) {
var descriptor = typeof field === STRING ? { field: field, dir: dir } : field,
descriptors = isArray(descriptor) ? descriptor : (descriptor !== undefined ? [descriptor] : []);
return grep(descriptors, function(d) { return !!d.dir; });
}
}
var operatorMap = {
"==": "eq",
equals: "eq",
isequalto: "eq",
equalto: "eq",
equal: "eq",
"!=": "neq",
ne: "neq",
notequals: "neq",
isnotequalto: "neq",
notequalto: "neq",
notequal: "neq",
"<": "lt",
islessthan: "lt",
lessthan: "lt",
less: "lt",
"<=": "lte",
le: "lte",
islessthanorequalto: "lte",
lessthanequal: "lte",
">": "gt",
isgreaterthan: "gt",
greaterthan: "gt",
greater: "gt",
">=": "gte",
isgreaterthanorequalto: "gte",
greaterthanequal: "gte",
ge: "gte",
notsubstringof: "doesnotcontain",
isnull: "isnull",
isempty: "isempty",
isnotempty: "isnotempty"
};
function normalizeOperator(expression) {
var idx,
length,
filter,
operator,
filters = expression.filters;
if (filters) {
for (idx = 0, length = filters.length; idx < length; idx++) {
filter = filters[idx];
operator = filter.operator;
if (operator && typeof operator === STRING) {
filter.operator = operatorMap[operator.toLowerCase()] || operator;
}
normalizeOperator(filter);
}
}
}
function normalizeFilter(expression) {
if (expression && !isEmptyObject(expression)) {
if (isArray(expression) || !expression.filters) {
expression = {
logic: "and",
filters: isArray(expression) ? expression : [expression]
};
}
normalizeOperator(expression);
return expression;
}
}
Query.normalizeFilter = normalizeFilter;
function compareDescriptor(f1, f2) {
if (f1.logic || f2.logic) {
return false;
}
return f1.field === f2.field && f1.value === f2.value && f1.operator === f2.operator;
}
function normalizeDescriptor(filter) {
filter = filter || {};
if (isEmptyObject(filter)) {
return { logic: "and", filters: [] };
}
return normalizeFilter(filter);
}
function fieldComparer(a, b) {
if (b.logic || (a.field > b.field)) {
return 1;
} else if (a.field < b.field) {
return -1;
} else {
return 0;
}
}
function compareFilters(expr1, expr2) {
expr1 = normalizeDescriptor(expr1);
expr2 = normalizeDescriptor(expr2);
if (expr1.logic !== expr2.logic) {
return false;
}
var f1, f2;
var filters1 = (expr1.filters || []).slice();
var filters2 = (expr2.filters || []).slice();
if (filters1.length !== filters2.length) {
return false;
}
filters1 = filters1.sort(fieldComparer);
filters2 = filters2.sort(fieldComparer);
for (var idx = 0; idx < filters1.length; idx++) {
f1 = filters1[idx];
f2 = filters2[idx];
if (f1.logic && f2.logic) {
if (!compareFilters(f1, f2)) {
return false;
}
} else if (!compareDescriptor(f1, f2)) {
return false;
}
}
return true;
}
Query.compareFilters = compareFilters;
function normalizeAggregate(expressions) {
return isArray(expressions) ? expressions : [expressions];
}
function normalizeGroup(field, dir) {
var descriptor = typeof field === STRING ? { field: field, dir: dir } : field,
descriptors = isArray(descriptor) ? descriptor : (descriptor !== undefined ? [descriptor] : []);
return map(descriptors, function(d) { return { field: d.field, dir: d.dir || "asc", aggregates: d.aggregates }; });
}
Query.prototype = {
toArray: function () {
return this.data;
},
range: function(index, count) {
return new Query(this.data.slice(index, index + count));
},
skip: function (count) {
return new Query(this.data.slice(count));
},
take: function (count) {
return new Query(this.data.slice(0, count));
},
select: function (selector) {
return new Query(map(this.data, selector));
},
order: function(selector, dir, inPlace) {
var sort = { dir: dir };
if (selector) {
if (selector.compare) {
sort.compare = selector.compare;
} else {
sort.field = selector;
}
}
if (inPlace) {
return new Query(this.data.sort(Comparer.create(sort)));
}
return new Query(this.data.slice(0).sort(Comparer.create(sort)));
},
orderBy: function(selector, inPlace) {
return this.order(selector, "asc", inPlace);
},
orderByDescending: function(selector, inPlace) {
return this.order(selector, "desc", inPlace);
},
sort: function(field, dir, comparer, inPlace) {
var idx,
length,
descriptors = normalizeSort(field, dir),
comparers = [];
comparer = comparer || Comparer;
if (descriptors.length) {
for (idx = 0, length = descriptors.length; idx < length; idx++) {
comparers.push(comparer.create(descriptors[idx]));
}
return this.orderBy({ compare: comparer.combine(comparers) }, inPlace);
}
return this;
},
filter: function(expressions) {
var idx,
current,
length,
compiled,
predicate,
data = this.data,
fields,
operators,
result = [],
filter;
expressions = normalizeFilter(expressions);
if (!expressions || expressions.filters.length === 0) {
return this;
}
compiled = Query.filterExpr(expressions);
fields = compiled.fields;
operators = compiled.operators;
predicate = filter = new Function("d, __f, __o", "return " + compiled.expression);
if (fields.length || operators.length) {
filter = function(d) {
return predicate(d, fields, operators);
};
}
for (idx = 0, length = data.length; idx < length; idx++) {
current = data[idx];
if (filter(current)) {
result.push(current);
}
}
return new Query(result);
},
group: function(descriptors, allData) {
descriptors = normalizeGroup(descriptors || []);
allData = allData || this.data;
var that = this,
result = new Query(that.data),
descriptor;
if (descriptors.length > 0) {
descriptor = descriptors[0];
result = result.groupBy(descriptor).select(function(group) {
var data = new Query(allData).filter([ { field: group.field, operator: "eq", value: group.value, ignoreCase: false } ]);
return {
field: group.field,
value: group.value,
items: descriptors.length > 1 ? new Query(group.items).group(descriptors.slice(1), data.toArray()).toArray() : group.items,
hasSubgroups: descriptors.length > 1,
aggregates: data.aggregate(descriptor.aggregates)
};
});
}
return result;
},
groupBy: function(descriptor) {
if (isEmptyObject(descriptor) || !this.data.length) {
return new Query([]);
}
var field = descriptor.field,
sorted = this._sortForGrouping(field, descriptor.dir || "asc"),
accessor = kendo.accessor(field),
item,
groupValue = accessor.get(sorted[0], field),
group = {
field: field,
value: groupValue,
items: []
},
currentValue,
idx,
len,
result = [group];
for(idx = 0, len = sorted.length; idx < len; idx++) {
item = sorted[idx];
currentValue = accessor.get(item, field);
if(!groupValueComparer(groupValue, currentValue)) {
groupValue = currentValue;
group = {
field: field,
value: groupValue,
items: []
};
result.push(group);
}
group.items.push(item);
}
return new Query(result);
},
_sortForGrouping: function(field, dir) {
var idx, length,
data = this.data;
if (!stableSort) {
for (idx = 0, length = data.length; idx < length; idx++) {