UNPKG

@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
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++) {