UNPKG

@progress/kendo-ui

Version:

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

1,266 lines (1,070 loc) 57.8 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__(1183); /***/ }), /***/ 3: /***/ (function(module, exports) { module.exports = function() { throw new Error("define cannot be used indirect"); }; /***/ }), /***/ 1008: /***/ (function(module, exports) { module.exports = require("./kendo.dropdownlist"); /***/ }), /***/ 1058: /***/ (function(module, exports) { module.exports = require("./kendo.binder"); /***/ }), /***/ 1119: /***/ (function(module, exports) { module.exports = require("./kendo.datepicker"); /***/ }), /***/ 1134: /***/ (function(module, exports) { module.exports = require("./kendo.numerictextbox"); /***/ }), /***/ 1183: /***/ (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__(1119), __webpack_require__(1134), __webpack_require__(1008), __webpack_require__(1058) ], __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: "filtermenu", name: "Filtering Menu", category: "framework", depends: [ "datepicker", "numerictextbox", "dropdownlist", "binder" ], advanced: true }; /* jshint eqnull: true */ (function($, undefined) { var kendo = window.kendo, ui = kendo.ui, proxy = $.proxy, POPUP = "kendoPopup", INIT = "init", OPEN = "open", REFRESH = "refresh", CHANGE = "change", NS = ".kendoFilterMenu", EQ = "Is equal to", NEQ = "Is not equal to", roles = { "number": "numerictextbox", "date": "datepicker" }, mobileRoles = { "string": "text", "number": "number", "date": "date" }, isFunction = kendo.isFunction, Widget = ui.Widget; var booleanTemplate = '<div>' + '<div class="k-filter-help-text">#=messages.info#</div>'+ '<label>'+ '<input type="radio" data-#=ns#bind="checked: filters[0].value" value="true" name="filters[0].value"/>' + '#=messages.isTrue#' + '</label>' + '<label>'+ '<input type="radio" data-#=ns#bind="checked: filters[0].value" value="false" name="filters[0].value"/>' + '#=messages.isFalse#' + '</label>' + '<div>' + '<button type="submit" class="k-button k-primary">#=messages.filter#</button>' + '<button type="reset" class="k-button">#=messages.clear#</button>'+ '</div>' + '</div>'; var customBooleanTemplate = '<div>' + '<div class="k-filter-help-text">#=messages.info#</div>'+ '<label>'+ '<input class="k-textbox" data-#=ns#bind="value: filters[0].value" name="filters[0].value"/>' + '</label>' + '<div>' + '<button type="submit" class="k-button k-primary">#=messages.filter#</button>' + '<button type="reset" class="k-button">#=messages.clear#</button>'+ '</div>' + '</div>'; var defaultTemplate = '<div>' + '<div class="k-filter-help-text">#=messages.info#</div>'+ '<select title="#=messages.operator#" data-#=ns#bind="value: filters[0].operator" data-#=ns#role="dropdownlist">'+ '#for(var op in operators){#'+ '<option value="#=op#">#=operators[op]#</option>' + '#}#'+ '</select>'+ '#if(values){#' + '<select title="#=messages.value#" data-#=ns#bind="value:filters[0].value" data-#=ns#text-field="text" data-#=ns#value-field="value" data-#=ns#source=\'#=kendo.stringify(values).replace(/\'/g,"&\\#39;")#\' data-#=ns#role="dropdownlist" data-#=ns#option-label="#=messages.selectValue#" data-#=ns#value-primitive="true">' + '</select>' + '#}else{#' + '<input title="#=messages.value#" data-#=ns#bind="value:filters[0].value" class="k-textbox" type="text" #=role ? "data-" + ns + "role=\'" + role + "\'" : ""# />'+ '#}#' + '#if(extra){#'+ '<select title="#=messages.logic#" class="k-filter-and" data-#=ns#bind="value: logic" data-#=ns#role="dropdownlist">'+ '<option value="and">#=messages.and#</option>'+ '<option value="or">#=messages.or#</option>'+ '</select>'+ '<select title="#=messages.additionalOperator#" data-#=ns#bind="value: filters[1].operator" data-#=ns#role="dropdownlist">'+ '#for(var op in operators){#'+ '<option value="#=op#">#=operators[op]#</option>'+ '#}#'+ '</select>'+ '#if(values){#' + '<select title="#=messages.additionalValue#" data-#=ns#bind="value:filters[1].value" data-#=ns#text-field="text" data-#=ns#value-field="value" data-#=ns#source=\'#=kendo.stringify(values).replace(/\'/g,"&\\#39;")#\' data-#=ns#role="dropdownlist" data-#=ns#option-label="#=messages.selectValue#" data-#=ns#value-primitive="true">' + '</select>'+ '#}else{#' + '<input title="#=messages.additionalValue#" data-#=ns#bind="value: filters[1].value" class="k-textbox" type="text" #=role ? "data-" + ns + "role=\'" + role + "\'" : ""#/>'+ '#}#' + '#}#'+ '<div>'+ '<button type="submit" class="k-button k-primary">#=messages.filter#</button>'+ '<button type="reset" class="k-button">#=messages.clear#</button>'+ '</div>'+ '</div>'; var defaultMobileTemplate = '<div data-#=ns#role="view" data-#=ns#init-widgets="false" data-#=ns#use-native-scrolling="true" class="k-grid-filter-menu">'+ '<div data-#=ns#role="header" class="k-header">'+ '<button class="k-button k-i-cancel">#=messages.cancel#</button>'+ '#=title#'+ '<button type="submit" class="k-button k-submit">#=messages.filter#</button>'+ '</div>'+ '<form title="#=messages.title#" class="k-filter-menu k-mobile-list">'+ '<ul class="k-filter-help-text"><li><span class="k-link">#=messages.info#</span>'+ '<ul>'+ '<li class="k-item"><label class="k-label">#=messages.operator#'+ '<select data-#=ns#bind="value: filters[0].operator">'+ '#for(var op in operators){#'+ '<option value="#=op#">#=operators[op]#</option>' + '#}#'+ '</select>'+ '</label></li>' + '<li class="k-item"><label class="k-label">#=messages.value#'+ '#if(values){#' + '<select data-#=ns#bind="value:filters[0].value">'+ '<option value="">#=messages.selectValue#</option>' + '#for(var val in values){#'+ '<option value="#=values[val].value#">#=values[val].text#</option>' + '#}#'+ '</select>' + '#}else{#' + '<input data-#=ns#bind="value:filters[0].value" class="k-textbox" type="#=inputType#" '+ '#=useRole ? "data-" + ns + "role=\'" + role + "\'" : ""# />'+ '#}#' + '</label></li>'+ '#if(extra){#'+ '</ul>'+ '<ul class="k-filter-help-text"><li><span class="k-link"></span>'+ '<li class="k-item"><label class="k-label"><input type="radio" name="logic" class="k-check" data-#=ns#bind="checked: logic" value="and" />#=messages.and#</label></li>'+ '<li class="k-item"><label class="k-label"><input type="radio" name="logic" class="k-check" data-#=ns#bind="checked: logic" value="or" />#=messages.or#</label></li>'+ '</ul>'+ '<ul class="k-filter-help-text"><li><span class="k-link"></span>'+ '<li class="k-item"><label class="k-label">#=messages.additionalOperator#'+ '<select data-#=ns#bind="value: filters[1].operator">'+ '#for(var op in operators){#'+ '<option value="#=op#">#=operators[op]#</option>' + '#}#'+ '</select>'+ '</label></li>'+ '<li class="k-item"><label class="k-label">#=messages.additionalValue#'+ '#if(values){#' + '<select data-#=ns#bind="value:filters[1].value">'+ '<option value="">#=messages.selectValue#</option>' + '#for(var val in values){#'+ '<option value="#=values[val].value#">#=values[val].text#</option>' + '#}#'+ '</select>' + '#}else{#' + '<input data-#=ns#bind="value:filters[1].value" class="k-textbox" type="#=inputType#" '+ '#=useRole ? "data-" + ns + "role=\'" + role + "\'" : ""# />'+ '#}#' + '</label></li>'+ '#}#'+ '</ul>'+ '</li><li class="k-button-container">' + '<button type="reset" class="k-button">#=messages.clear#</button>'+ '</li></ul>' + '</div>'+ '</form>'+ '</div>'; var booleanMobileTemplate = '<div data-#=ns#role="view" data-#=ns#init-widgets="false" data-#=ns#use-native-scrolling="true" class="k-grid-filter-menu">'+ '<div data-#=ns#role="header" class="k-header">'+ '<button class="k-button k-i-cancel">#=messages.cancel#</button>'+ '#=title#'+ '<button type="submit" class="k-button k-submit">#=messages.filter#</button>'+ '</div>'+ '<form title="#=messages.title#" class="k-filter-menu k-mobile-list">'+ '<ul class="k-filter-help-text"><li><span class="k-link">#=messages.info#</span>'+ '<ul>'+ '<li class="k-item"><label class="k-label">'+ '<input class="k-check" type="radio" data-#=ns#bind="checked: filters[0].value" value="true" name="filters[0].value"/>' + '#=messages.isTrue#' + '</label></li>' + '<li class="k-item"><label class="k-label">'+ '<input class="k-check" type="radio" data-#=ns#bind="checked: filters[0].value" value="false" name="filters[0].value"/>' + '#=messages.isFalse#' + '</label></li>' + '</ul>'+ '</li><li class="k-button-container">' + '<button type="reset" class="k-button">#=messages.clear#</button>'+ '</li></ul>' + '</form>'+ '</div>'; function removeFiltersForField(expression, field) { if (expression.filters) { expression.filters = $.grep(expression.filters, function(filter) { removeFiltersForField(filter, field); if (filter.filters) { return filter.filters.length; } else { return filter.field != field; } }); } } function convertItems(items) { var idx, length, item, value, text, result; if (items && items.length) { result = []; for (idx = 0, length = items.length; idx < length; idx++) { item = items[idx]; text = item.text !== "" ? item.text || item.value || item : item.text; value = item.value == null ? (item.text || item) : item.value; result[idx] = { text: text, value: value }; } } return result; } function clearFilter(filters, field) { return $.grep(filters, function(expr) { if (expr.filters) { expr.filters = $.grep(expr.filters, function(nested) { return nested.field != field; }); return expr.filters.length; } return expr.field != field; }); } var FilterMenu = Widget.extend({ init: function(element, options) { var that = this, type = "string", operators, initial, link, field; Widget.fn.init.call(that, element, options); operators = that.operators = options.operators || {}; element = that.element; options = that.options; if (!options.appendToElement) { link = element.addClass("k-with-icon k-filterable").find(".k-grid-filter"); if (!link[0]) { link = element.prepend('<a class="k-grid-filter" href="#" title="' + options.messages.filter + '" aria-label="' + options.messages.filter + '"><span class="k-icon k-i-filter"></span></a>').find(".k-grid-filter"); } link.attr("tabindex", -1).on("click" + NS, proxy(that._click, that)); } that.link = link || $(); that.dataSource = DataSource.create(options.dataSource); that.field = options.field || element.attr(kendo.attr("field")); that.model = that.dataSource.reader.model; that._parse = function(value) { return value != null ? (value + "") : value; }; if (that.model && that.model.fields) { field = that.model.fields[that.field]; if (field) { type = field.type || "string"; if (field.parse) { that._parse = proxy(field.parse, field); } } } if (options.values) { type = "enums"; } that.type = type; operators = operators[type] || options.operators[type]; for (initial in operators) { // get the first operator break; } that._defaultFilter = function() { return { field: that.field, operator: initial || "eq", value: "" }; }; that._refreshHandler = proxy(that.refresh, that); that.dataSource.bind(CHANGE, that._refreshHandler); if (options.appendToElement) { // force creation if used in column menu that._init(); } else { that.refresh(); //refresh if DataSource is fitered before menu is created } }, _init: function() { var that = this, ui = that.options.ui, setUI = isFunction(ui), role; that.pane = that.options.pane; if (that.pane) { that._isMobile = true; } if (!setUI) { role = ui || roles[that.type]; } if (that._isMobile) { that._createMobileForm(role); } else { that._createForm(role); } that.form .on("submit" + NS, proxy(that._submit, that)) .on("reset" + NS, proxy(that._reset, that)); if (setUI) { that.form.find(".k-textbox") .removeClass("k-textbox") .each(function() { ui($(this)); }); } that.form .find("[" + kendo.attr("role") + "=numerictextbox]") .removeClass("k-textbox") .end() .find("[" + kendo.attr("role") + "=datetimepicker]") .removeClass("k-textbox") .end() .find("[" + kendo.attr("role") + "=timepicker]") .removeClass("k-textbox") .end() .find("[" + kendo.attr("role") + "=datepicker]") .removeClass("k-textbox"); that.refresh(); that.trigger(INIT, { field: that.field, container: that.form }); kendo.cycleForm(that.form); }, _createForm: function(role) { var that = this, options = that.options, operators = that.operators || {}, type = that.type, hasCustomTemplate = isFunction(that.options.ui); operators = operators[type] || options.operators[type]; that.form = $('<form title="' + that.options.messages.title + '" class="k-filter-menu"/>') .html(kendo.template(type === "boolean" ? (hasCustomTemplate ? customBooleanTemplate : booleanTemplate) : defaultTemplate)({ field: that.field, format: options.format, ns: kendo.ns, messages: options.messages, extra: options.extra, operators: operators, type: type, role: role, values: convertItems(options.values) })); if (!options.appendToElement) { that.popup = that.form[POPUP]({ anchor: that.link, open: proxy(that._open, that), activate: proxy(that._activate, that), close: function() { if (that.options.closeCallback) { that.options.closeCallback(that.element); } } }).data(POPUP); } else { that.element.append(that.form); that.popup = that.element.closest(".k-popup").data(POPUP); } that.form .on("keydown" + NS, proxy(that._keydown, that)); }, _createMobileForm: function(role) { var that = this, options = that.options, operators = that.operators || {}, type = that.type; operators = operators[type] || options.operators[type]; that.form = $("<div />") .html(kendo.template(type === "boolean" ? booleanMobileTemplate : defaultMobileTemplate)({ field: that.field, title: options.title || that.field, format: options.format, ns: kendo.ns, messages: options.messages, extra: options.extra, operators: operators, type: type, role: role, useRole: (!kendo.support.input.date && type === "date") || type === "number", inputType: mobileRoles[type], values: convertItems(options.values) })); that.view = that.pane.append(that.form.html()); that.form = that.view.element.find("form"); that.view.element .on("click", ".k-submit", function(e) { that.form.submit(); e.preventDefault(); }) .on("click", ".k-i-cancel", function(e) { that._closeForm(); e.preventDefault(); }); }, refresh: function() { var that = this, expression = that.dataSource.filter() || { filters: [], logic: "and" }; var defaultFilters = [ that._defaultFilter() ]; var defaultOperator = that._defaultFilter().operator; if (that.options.extra || (defaultOperator !== "isnull" && defaultOperator !== "isnullorempty" && defaultOperator !== "isnotnullorempty" && defaultOperator !== "isnotnull")) { defaultFilters.push(that._defaultFilter()); } that.filterModel = kendo.observable({ logic: "and", filters: defaultFilters }); if (that.form) { //NOTE: binding the form element directly causes weird error in IE when grid is bound through MVVM and column is sorted kendo.bind(that.form.children().first(), that.filterModel); } if (that._bind(expression)) { that.link.addClass("k-state-active"); } else { that.link.removeClass("k-state-active"); } }, destroy: function() { var that = this; Widget.fn.destroy.call(that); if (that.form) { kendo.unbind(that.form); kendo.destroy(that.form); that.form.unbind(NS); if (that.popup) { that.popup.destroy(); that.popup = null; } that.form = null; } if (that.view) { that.view.purge(); that.view = null; } that.link.unbind(NS); if (that._refreshHandler) { that.dataSource.unbind(CHANGE, that._refreshHandler); that.dataSource = null; } that.element = that.link = that._refreshHandler = that.filterModel = null; }, _bind: function(expression) { var that = this, filters = expression.filters, idx, length, found = false, current = 0, filterModel = that.filterModel, currentFilter, filter; for (idx = 0, length = filters.length; idx < length; idx++) { filter = filters[idx]; if (filter.field == that.field) { filterModel.set("logic", expression.logic); currentFilter = filterModel.filters[current]; if (!currentFilter) { filterModel.filters.push({ field: that.field }); currentFilter = filterModel.filters[current]; } currentFilter.set("value", that._parse(filter.value)); currentFilter.set("operator", filter.operator); current++; found = true; } else if (filter.filters) { found = found || that._bind(filter); } } return found; }, _stripFilters: function(filters) { return $.grep(filters, function(filter) { return (filter.value !== "" && filter.value != null) || (filter.operator === "isnull" || filter.operator === "isnotnull" || filter.operator === "isempty" || filter.operator === "isnotempty" || filter.operator == "isnullorempty" || filter.operator == "isnotnullorempty"); }); }, _merge: function(expression) { var that = this, logic = expression.logic || "and", filters = this._stripFilters(expression.filters), filter, result = that.dataSource.filter() || { filters:[], logic: "and" }, idx, length; removeFiltersForField(result, that.field); for (idx = 0, length = filters.length; idx < length; idx++) { filter = filters[idx]; filter.value = that._parse(filter.value); } if (filters.length) { if (result.filters.length) { expression.filters = filters; if (result.logic !== "and") { result.filters = [ { logic: result.logic, filters: result.filters }]; result.logic = "and"; } if (filters.length > 1) { result.filters.push(expression); } else { result.filters.push(filters[0]); } } else { result.filters = filters; result.logic = logic; } } return result; }, filter: function(expression) { var filters = this._stripFilters(expression.filters); if (filters.length && this.trigger("change", { filter: { logic: expression.logic, filters: filters }, field: this.field })) { return; } expression = this._merge(expression); if (expression.filters.length) { this.dataSource.filter(expression); } }, clear: function() { var that = this, expression = that.dataSource.filter() || { filters:[] }; if (this.trigger("change", { filter: null, field: that.field })) { return; } that._removeFilter(expression); }, _removeFilter: function(expression) { var that = this; expression.filters = $.grep(expression.filters, function(filter) { if (filter.filters) { filter.filters = clearFilter(filter.filters, that.field); return filter.filters.length; } return filter.field != that.field; }); if (!expression.filters.length) { expression = null; } that.dataSource.filter(expression); }, _submit: function(e) { e.preventDefault(); e.stopPropagation(); var expression = this.filterModel.toJSON(); var containsFilters = $.grep(expression.filters, function(filter) { return filter.value !== "" && filter.value !== null; }); if (this._checkForNullOrEmptyFilter(expression) || (containsFilters && containsFilters.length)) { this.filter(expression); } else { var currentExpression = this.dataSource.filter(); if (currentExpression) { currentExpression.filters.push(expression); expression = currentExpression; } this._removeFilter(expression); } this._closeForm(); }, _checkForNullOrEmptyFilter: function(expression) { if(!expression || !expression.filters || !expression.filters.length) { return false; } var firstNullOrEmpty = false; var secondNullOrEmpty = false; var operator; if (expression.filters[0]) { operator = expression.filters[0].operator; firstNullOrEmpty = operator == "isnull" || operator == "isnotnull" || operator == "isnotempty" || operator == "isempty" || operator == "isnullorempty" || operator == "isnotnullorempty"; } if (expression.filters[1]) { operator = expression.filters[1].operator; secondNullOrEmpty = operator == "isnull" || operator == "isnotnull" || operator == "isnotempty" || operator == "isempty" || operator == "isnullorempty" || operator == "isnotnullorempty"; } return (!this.options.extra && firstNullOrEmpty) || (this.options.extra && (firstNullOrEmpty || secondNullOrEmpty)); }, _reset: function() { this.clear(); if (this.options.search && this.container) { this.container.find("label").parent().show(); } this._closeForm(); }, _closeForm: function() { if (this._isMobile) { this.pane.navigate("", this.options.animations.right); } else { this.popup.close(); } }, _click: function(e) { e.preventDefault(); e.stopPropagation(); if (!this.popup && !this.pane) { this._init(); } if (this._isMobile) { this.pane.navigate(this.view, this.options.animations.left); } else { this.popup.toggle(); } }, _open: function() { var popup; $(".k-filter-menu").not(this.form).each(function() { popup = $(this).data(POPUP); if (popup) { popup.close(); } }); }, _activate: function() { this.form.find(":kendoFocusable:first").focus(); this.trigger(OPEN, { field: this.field, container: this.form }); }, _keydown: function(e) { if (e.keyCode == kendo.keys.ESC) { this.popup.close(); } }, events: [ INIT, "change", OPEN ], options: { name: "FilterMenu", extra: true, appendToElement: false, type: "string", operators: { string: { eq: EQ, neq: NEQ, startswith: "Starts with", contains: "Contains", doesnotcontain: "Does not contain", endswith: "Ends with", isnull: "Is null", isnotnull: "Is not null", isempty: "Is empty", isnotempty: "Is not empty", isnullorempty: "Has no value", isnotnullorempty: "Has value" }, number: { eq: EQ, neq: NEQ, gte: "Is greater than or equal to", gt: "Is greater than", lte: "Is less than or equal to", lt: "Is less than", isnull: "Is null", isnotnull: "Is not null" }, date: { eq: EQ, neq: NEQ, gte: "Is after or equal to", gt: "Is after", lte: "Is before or equal to", lt: "Is before", isnull: "Is null", isnotnull: "Is not null" }, enums: { eq: EQ, neq: NEQ, isnull: "Is null", isnotnull: "Is not null" } }, messages: { info: "Show items with value that:", title: "Show items with value that:", isTrue: "is true", isFalse: "is false", filter: "Filter", clear: "Clear", and: "And", or: "Or", selectValue: "-Select value-", operator: "Operator", value: "Value", additionalValue: "Additional value", additionalOperator: "Additional operator", logic: "Filters logic", cancel: "Cancel" }, animations: { left: "slide", right: "slide:right" } } }); var multiCheckNS = ".kendoFilterMultiCheck"; function filterValuesForField(expression, field) { if (expression.filters) { expression.filters = $.grep(expression.filters, function(filter) { filterValuesForField(filter, field); if (filter.filters) { return filter.filters.length; } else { return filter.field == field && filter.operator == "eq"; } }); } } function flatFilterValues(expression) { if (expression.logic == "and" && expression.filters.length > 1) { return []; } if (expression.filters) { return $.map(expression.filters, function(filter) { return flatFilterValues(filter); }); } else if (expression.value !== undefined) { return [expression.value]; } else { return []; } } function distinct(items, field) { var getter = kendo.getter(field, true), result = [], index = 0, seen = {}; while (index < items.length) { var item = items[index++], text = getter(item); if(text !== undefined && !seen.hasOwnProperty(text)){ result.push(item); seen[text] = true; } } return result; } function removeDuplicates (dataSelector, dataTextField) { return function(e) { var items = dataSelector(e); return distinct(items, dataTextField); }; } var DataSource = kendo.data.DataSource; var multiCkeckMobileTemplate = '<div data-#=ns#role="view" data-#=ns#init-widgets="false" class="k-grid-filter-menu">' + '<div data-#=ns#role="header" class="k-header">' + '<button class="k-button k-i-cancel">#=messages.cancel#</button>' + '#=title#' + '<button type="submit" class="k-button k-submit">#=messages.filter#</button>' + '</div>' + '<form class="k-filter-menu k-mobile-list">' + '#if(search){#' + "<div class='k-textbox k-space-right'>" + "<input placeholder='#=messages.search#'/>" + "<span class='k-icon k-i-zoom' />" + "</div>" + '#}#' + '<ul class="k-multicheck-wrap"></ul>' + '</li><li class="k-button-container">' + "#if(messages.selectedItemsFormat){#<div class='k-filter-selected-items'></div>#}#" + '<button type="reset" class="k-button">#=messages.clear#</button>' + '</li></ul>' + '</form>' + '</div>'; var FilterMultiCheck = Widget.extend({ init: function(element, options) { Widget.fn.init.call(this, element, options); options = this.options; this.element = $(element); var field = this.field = this.options.field || this.element.attr(kendo.attr("field")); var checkSource = options.checkSource; if (this._foreignKeyValues()) { this.checkSource = DataSource.create(options.values); this.checkSource.fetch(); } else if (options.forceUnique) { checkSource = $.extend(true, {}, options.dataSource.options); delete checkSource.pageSize; this.checkSource = DataSource.create(checkSource); this.checkSource.reader.data = removeDuplicates(this.checkSource.reader.data, this.field); } else { this.checkSource = DataSource.create(checkSource); } this.dataSource = options.dataSource; this.model = this.dataSource.reader.model; this._parse = function(value) { return value + ""; }; if (this.model && this.model.fields) { field = this.model.fields[this.field]; if (field) { if (field.type == "number") { this._parse = function (value) { if (typeof value === "string" && value.toLowerCase() === "null") { return null; } return parseFloat(value); }; } else if (field.parse) { this._parse = proxy(field.parse, field); } this.type = field.type || "string"; } } if (!options.appendToElement) { this._createLink(); } else { this._init(); } this._refreshHandler = proxy(this.refresh, this); this.dataSource.bind(CHANGE, this._refreshHandler); }, _createLink: function() { var element = this.element; var link = element.addClass("k-with-icon k-filterable").find(".k-grid-filter"); if (!link[0]) { link = element.prepend('<a class="k-grid-filter" href="#" aria-label="' + this.options.messages.filter + '"><span class="k-icon k-i-filter"/></a>').find(".k-grid-filter"); } this._link = link.attr("tabindex", -1).on("click" + NS, proxy(this._click, this)); }, _init: function() { var that = this; var forceUnique = this.options.forceUnique; var options = this.options; this.pane = options.pane; if (this.pane) { this._isMobile = true; } this._createForm(); if (this._foreignKeyValues()) { this.refresh(); } else if (forceUnique && !this.checkSource.options.serverPaging && this.dataSource.data().length) { this.checkSource.data(distinct(this.dataSource.data(),this.field)); this.refresh(); } else { this._attachProgress(); this.checkSource.fetch(function() { that.refresh.call(that); }); } if (!this.options.forceUnique) { this.checkChangeHandler = function() { that.container.empty(); that.refresh(); }; this.checkSource.bind(CHANGE, this.checkChangeHandler); } this.form.on("keydown" + multiCheckNS, proxy(this._keydown, this)) .on("submit" + multiCheckNS, proxy(this._filter, this)) .on("reset" + multiCheckNS, proxy(this._reset, this)); this.trigger(INIT, { field: this.field, container: this.form }); }, _attachProgress: function() { var that = this; this._progressHandler = function() { ui.progress(that.container, true); }; this._progressHideHandler = function() { ui.progress(that.container, false); }; this.checkSource .bind("progress", this._progressHandler) .bind("change", this._progressHideHandler); }, _input: function () { var that = this; that._clearTypingTimeout(); that._typingTimeout = setTimeout(function () { that.search(); }, 100); }, _clearTypingTimeout: function() { if (this._typingTimeout) { clearTimeout(this._typingTimeout); this._typingTimeout = null; } }, search: function () { var ignoreCase = this.options.ignoreCase; var searchString = this.searchTextBox[0].value; var labels = this.container.find("label"); if (ignoreCase) { searchString = searchString.toLowerCase(); } var i = 0; if(this.options.checkAll && labels.length) { labels[0].parentNode.style.display = searchString ? "none" : ""; i++; } while (i < labels.length) { var label = labels[i]; var labelText = label.textContent || label.innerText; if (ignoreCase) { labelText = labelText.toLowerCase(); } label.parentNode.style.display = labelText.indexOf(searchString) >= 0 ? "" : "none"; i++; } }, _activate: function() { this.form.find(":kendoFocusable:first").focus(); this.trigger(OPEN, { field: this.field, container: this.form }); }, _createForm: function() { var options = this.options; var html = ""; var that = this; if (!this._isMobile) { if (options.search) { html += "<div class='k-textbox k-space-right'>" + "<input placeholder='" + options.messages.search + "'/>" + "<span class='k-icon k-i-zoom' />" + "</div>"; } html += "<ul class='k-reset k-multicheck-wrap'></ul>"; if (options.messages.selectedItemsFormat) { html += "<div class='k-filter-selected-items'>" + kendo.format(options.messages.selectedItemsFormat, 0) + "</div>"; } html +="<button type='submit' class='k-button k-primary'>" + options.messages.filter + "</button>"; html += "<button type='reset' class='k-button'>" + options.messages.clear + "</button>"; this.form = $('<form class="k-filter-menu"/>').html(html); this.container = this.form.find(".k-multicheck-wrap"); } if (this._isMobile) { that.form = $("<div />") .html(kendo.template(multiCkeckMobileTemplate)({ field: that.field, title: options.title || that.field, ns: kendo.ns, messages: options.messages, search: options.search })); that.view = that.pane.append(that.form.html()); that.form = that.view.element.find("form"); var element = this.view.element; this.container = element.find(".k-multicheck-wrap"); element .on("click", ".k-submit", function (e) { that.form.submit(); e.preventDefault(); }) .on("click", ".k-i-cancel", function (e) { that._closeForm(); e.preventDefault(); }); } else { if (!options.appendToElement) { that.popup = that.form.kendoPopup({ anchor: that._link, open: proxy(that._open, that), activate: proxy(that._activate, that), close: function() { if (that.options.closeCallback) { that.options.closeCallback(that.element); } } }).data(POPUP); } else { this.popup = this.element.closest(".k-popup").data(POPUP); this.element.append(this.form); } } if (options.search) { this.searchTextBox = this.form.find(".k-textbox > input"); this.searchTextBox.on("input", proxy(this._input, this)); } }, createCheckAllItem: function () { var options = this.options; var template = kendo.template(options.itemTemplate({ field: "all", mobile: this._isMobile })); var checkAllContainer = $(template({ all: options.messages.checkAll})); this.container.prepend(checkAllContainer); this.checkBoxAll = checkAllContainer.find(":checkbox").eq(0).addClass("k-check-all"); this.checkAllHandler = proxy(this.checkAll, this); this.checkBoxAll.on(CHANGE+ multiCheckNS, this.checkAllHandler); }, updateCheckAllState: function() { if (this.options.messages.selectedItemsFormat) { this.form.find(".k-filter-selected-items").text(kendo.format(this.options.messages.selectedItemsFormat, this.container.find(":checked:not(.k-check-all)").length)); } if (this.checkBoxAll) { var state = this.container.find(":checkbox:not(.k-check-all)").length == this.container.find(":checked:not(.k-check-all)").length; this.checkBoxAll.prop("checked", state); } }, refresh: function(e) { var forceUnique = this.options.forceUnique; var dataSource = this.dataSource; var filters = this.getFilterArray(); if (this._link) { this._link.toggleClass("k-state-active", filters.length !== 0); } if (this.form) { if (e && forceUnique && e.sender === dataSource && !dataSource.options.serverPaging && (e.action == "itemchange" || e.action == "add" || e.action == "remove" || (dataSource.options.autoSync && e.action === "sync")) && !this._foreignKeyValues()) { this.checkSource.data(distinct(this.dataSource.data(),this.field)); this.container.empty(); } if (this.container.is(":empty")) { this.createCheckBoxes(); } this.checkValues(filters); this.trigger(REFRESH); } }, getFilterArray: function(