@progress/kendo-ui
Version:
This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.
1,171 lines (994 loc) • 77.3 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__(1278);
/***/ }),
/***/ 3:
/***/ (function(module, exports) {
module.exports = function() { throw new Error("define cannot be used indirect"); };
/***/ }),
/***/ 1065:
/***/ (function(module, exports) {
module.exports = require("./kendo.dropdownlist");
/***/ }),
/***/ 1115:
/***/ (function(module, exports) {
module.exports = require("./kendo.binder");
/***/ }),
/***/ 1116:
/***/ (function(module, exports) {
module.exports = require("./kendo.numerictextbox");
/***/ }),
/***/ 1198:
/***/ (function(module, exports) {
module.exports = require("./kendo.datepicker");
/***/ }),
/***/ 1278:
/***/ (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__(1198), __webpack_require__(1116), __webpack_require__(1065), __webpack_require__(1115) ], __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,
support = kendo.support,
AUTOCOMPLETEVALUE = support.browser.chrome ? "disabled" : "off",
POPUP = "kendoPopup",
INIT = "init",
OPEN = "open",
REFRESH = "refresh",
CHANGE = "change",
NS = ".kendoFilterMenu",
COLUMNHEADERATTR = "[role='columnheader']",
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 class="k-filter-menu-container">' +
'<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 class="k-action-buttons">' +
'<button type="submit" title="#=messages.filter#" class="k-button k-button-md k-rounded-md k-button-solid k-button-solid-primary"><span class="k-button-text">#=messages.filter#</span></button>' +
'<button type="reset" title="#=messages.clear#" class="k-button k-button-md k-rounded-md k-button-solid k-button-solid-base"><span class="k-button-text">#=messages.clear#</span></button>' +
'</div>' +
'</div>';
var modernBooleanTemplate =
'#var inputId;#' +
'<div class="k-filter-menu-container">' +
'<div>' +
'<ul class="k-radio-list k-reset">' +
'<li>' +
'#inputId = kendo.guid()#' +
'<input type="radio" class="k-radio k-radio-md" id="#=inputId#" data-#=ns#bind="checked: filters[0].value" value="true" name="filters[0].value" />' +
'<label class="k-radio-label" for="#=inputId#">#=messages.isTrue#</label>' +
'</li>' +
'<li>' +
'#inputId = kendo.guid()#' +
'<input type="radio" class="k-radio k-radio-md" id="#=inputId#" data-#=ns#bind="checked: filters[0].value" value="false" name="filters[0].value" />' +
'<label class="k-radio-label" for="#=inputId#">#=messages.isFalse#</label>' +
'</li>' +
'</ul>' +
'<div class="k-columnmenu-actions">' +
'<button class="k-button k-button-md k-rounded-md k-button-solid k-button-solid-base" type="reset" title="#=messages.clear#"><span class="k-button-text">#=messages.clear#</span></button>' +
'<button class="k-button k-button-md k-rounded-md k-button-solid k-button-solid-primary" type="submit" title="#=messages.filter#"><span class="k-button-text">#=messages.filter#</span></button>' +
'</div>' +
'</div>' +
'</div>';
var customBooleanTemplate =
'<div class="k-filter-menu-container">' +
'<div class="k-filter-help-text">#=messages.info#</div>' +
'<label>' +
'<span class="k-textbox k-input k-input-md k-rounded-md k-input-solid"><input class="k-input-inner" data-#=ns#bind="value: filters[0].value" name="filters[0].value"/></span>' +
'</label>' +
'<div class="k-action-buttons">' +
'<button type="submit" title="#=messages.filter#" class="k-button k-button-md k-rounded-md k-button-solid k-button-solid-primary"><span class="k-button-text">#=messages.filter#</span></button>' +
'<button type="reset" title="#=messages.clear#" class="k-button k-button-md k-rounded-md k-button-solid k-button-solid-base"><span class="k-button-text">#=messages.clear#</span></button>' +
'</div>' +
'</div>';
var defaultTemplate =
'<div class="k-filter-menu-container">' +
'#if(componentType === "classic") {#' +
'<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-input-inner" type="text" #=role ? "data-" + ns + "role=\'" + role + "\'" : ""# />' +
'#}#' +
'#if(extra){#' +
'#if(componentType === "modern") {#' +
'<ul data-#=ns#role="buttongroup" data-bind="events: { select: onLogicChange }">' +
'<li data-#=ns#value="and">And</li>' +
'<li data-#=ns#value="or">Or</li>' +
'</ul>' +
'#} else {#' +
'<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-input-inner" type="text" #=role ? "data-" + ns + "role=\'" + role + "\'" : ""#/>' +
'#}#' +
'#}#' +
'<div class="k-action-buttons">' +
'<button type="submit" title="#=messages.filter#" class="k-button k-button-md k-rounded-md k-button-solid k-button-solid-primary"><span class="k-button-text">#=messages.filter#</span></button>' +
'<button type="reset" title="#=messages.clear#" class="k-button k-button-md k-rounded-md k-button-solid k-button-solid-base"><span class="k-button-text">#=messages.clear#</span></button>' +
'</div>' +
'</div>';
var defaultMobileTemplate =
'<div data-#=ns#role="view" class="k-grid-filter-menu">' +
'<div data-#=ns#role="header" class="k-header">' +
'<a href="\\#" class="k-header-cancel k-link" title="#=messages.cancel#" ' +
'aria-label="#=messages.cancel#"><span class="k-icon k-i-arrow-chevron-left"></span></a>' +
'#=messages.filter# #=messages.into# #=title#' +
'<a href="\\#" class="k-header-done k-link" title="#=messages.done#" ' +
'aria-label="#=messages.done#"><span class="k-icon k-i-check"></span></a>' +
'</div>' +
'<form title="#=messages.title#" class="k-filter-menu">' +
'<ul class="k-reset">' +
'<li>' +
'<span class="k-list-title k-filter-help-text">#=messages.info#</span>' +
'<ul class="k-listgroup k-listgroup-flush">' +
'<li class="k-item k-listgroup-item">' +
'<label class="k-listgroup-form-row k-label">' +
'<span class="k-listgroup-form-field-label k-filter-operator-text">#=messages.operator#</span>' +
'<span class="k-listgroup-form-field-wrapper">' +
'<select id="operator_#=filterMenuGuid#" title="#=messages.operator#" class="k-filter-operator" data-#=ns#bind="value: filters[0].operator" autocomplete="' + AUTOCOMPLETEVALUE + '" >' +
'#for(var op in operators){#' +
'<option value="#=op#">#=operators[op]#</option>' +
'#}#' +
'</select>' +
'</span>' +
'</label>' +
'</li>' +
'<li class="k-item k-listgroup-item">' +
'<label class="k-listgroup-form-row k-label">' +
'<span class="k-listgroup-form-field-label k-filter-input-text">#=messages.value#</span>' +
'<span class="k-listgroup-form-field-wrapper">' +
'#if(values){#' +
'<select id="value_#=filterMenuGuid#" title="#=messages.value#" data-#=ns#bind="value:filters[0].value" autocomplete="' + AUTOCOMPLETEVALUE + '" >' +
'<option value="">#=messages.selectValue#</option>' +
'#for(var val in values){#' +
'<option value="#=values[val].value#">#=values[val].text#</option>' +
'#}#' +
'</select>' +
'#}else{#' +
'<input id="value_#=filterMenuGuid#" title="#=messages.value#" data-#=ns#bind="value:filters[0].value" class="k-value-input" type="#=inputType#" autocomplete="' + AUTOCOMPLETEVALUE + '" />' +
'#}#' +
'</span>' +
'</label>' +
'</li>' +
'</ul>' +
'#if(extra){#' +
'<ul class="k-listgroup k-listgroup-flush">' +
'<li class="k-item k-listgroup-item">' +
'<label class="k-listgroup-form-row k-label">' +
'<span class="k-listgroup-form-field-label k-filter-logic-and-text">#=messages.and#</span>' +
'<span class="k-listgroup-form-field-wrapper">' +
'<input id="and_#=filterMenuGuid#" title="#=messages.and#" type="radio" name="logic"data-#=ns#bind="checked: logic" value="and" autocomplete="' + AUTOCOMPLETEVALUE + '" />' +
'</span>' +
'</label>' +
'</li>' +
'<li class="k-item k-listgroup-item">' +
'<label class="k-listgroup-form-row k-label">' +
'<span class="k-listgroup-form-field-label k-filter-logic-or-text">#=messages.or#</span>' +
'<span class="k-listgroup-form-field-wrapper">' +
'<input id="or_#=filterMenuGuid#" title="#=messages.or#" type="radio" name="logic" data-#=ns#bind="checked: logic" value="or" autocomplete="' + AUTOCOMPLETEVALUE + '" />' +
'</span>' +
'</label>' +
'</li>' +
'</ul>' +
'<ul class="k-listgroup k-listgroup-flush">' +
'<li class="k-item k-listgroup-item">' +
'<label class="k-listgroup-form-row k-label">' +
'<span class="k-listgroup-form-field-label k-filter-operator-text">#=messages.additionalOperator#</span>' +
'<span class="k-listgroup-form-field-wrapper">' +
'<select id="additionalOperator_#=filterMenuGuid#" title="#=messages.additionalOperator#" class="k-filter-operator" data-#=ns#bind="value: filters[1].operator" autocomplete="' + AUTOCOMPLETEVALUE + '" >' +
'#for(var op in operators){#' +
'<option value="#=op#">#=operators[op]#</option>' +
'#}#' +
'</select>' +
'</span>' +
'</label>' +
'</li>' +
'<li class="k-item k-listgroup-item">' +
'<label class="k-listgroup-form-row k-label">' +
'<span class="k-listgroup-form-field-label k-filter-input-text">#=messages.additionalValue#</span>' +
'<span class="k-listgroup-form-field-wrapper">' +
'#if(values){#' +
'<select id="additionalValue_#=filterMenuGuid#" title="#=messages.additionalValue#" data-#=ns#bind="value:filters[1].value" autocomplete="' + AUTOCOMPLETEVALUE + '" >' +
'<option value="">#=messages.selectValue#</option>' +
'#for(var val in values){#' +
'<option value="#=values[val].value#">#=values[val].text#</option>' +
'#}#' +
'</select>' +
'#}else{#' +
'<input id="additionalValue_#=filterMenuGuid#" title="#=messages.additionalValue#" data-#=ns#bind="value:filters[1].value" class="k-value-input" type="#=inputType#" autocomplete="' + AUTOCOMPLETEVALUE + '" />' +
'#}#' +
'</span>' +
'</label>' +
'</li>' +
'</ul>' +
'#}#' +
'</li>' +
'<li class="k-item k-clear-wrap">' +
'<span class="k-list-title"> </span>' +
'<ul class="k-listgroup k-listgroup-flush">' +
'<li class="k-listgroup-item">' +
'<span class="k-link k-label k-clear" title="#=messages.clear#" aria-label="#=messages.clear#">' +
'#=messages.clear#' +
'</span>' +
'</li>' +
'</ul>' +
'</li>' +
'</ul>' +
'</form>' +
'</div>';
var booleanMobileTemplate =
'<div data-#=ns#role="view" class="k-grid-filter-menu">' +
'<div data-#=ns#role="header" class="k-header">' +
'<a href="\\#" class="k-header-cancel k-link" title="#=messages.cancel#" ' +
'aria-label="#=messages.cancel#"><span class="k-icon k-i-arrow-chevron-left"></span></a>' +
'#=messages.filter# #=messages.into# #=title#' +
'<a href="\\#" class="k-header-done k-link" title="#=messages.done#" ' +
'aria-label="#=messages.done#"><span class="k-icon k-i-check"></span></a>' +
'</div>' +
'<form title="#=messages.title#" class="k-filter-menu">' +
'<ul class="k-reset">' +
'<li>' +
'<span class="k-list-title k-filter-help-text">#=messages.info#</span>' +
'<ul class="k-listgroup k-listgroup-flush k-multicheck-bool-wrap">' +
'<li class="k-item k-listgroup-item">' +
'<label class="k-listgroup-form-row k-label">' +
'<span class="k-listgroup-form-field-label k-item-title">#=messages.isTrue#</span>' +
'<span class="k-listgroup-form-field-wrapper"></span>' +
'<input id="true_#=filterMenuGuid#" title="#=messages.isTrue#" type="radio" data-#=ns#bind="checked: filters[0].value" value="true" name="filters[0].value" autocomplete="' + AUTOCOMPLETEVALUE + '" />' +
'</span>' +
'</label>' +
'</li>' +
'<li class="k-item k-listgroup-item">' +
'<label class="k-listgroup-form-row k-label">' +
'<span for="false_#=filterMenuGuid#" class="k-listgroup-form-field-label k-item-title">#=messages.isFalse#</span>' +
'<span class="k-listgroup-form-field-wrapper">' +
'<input id="false_#=filterMenuGuid#" title="#=messages.isFalse#" type="radio" data-#=ns#bind="checked: filters[0].value" value="false" name="filters[0].value" autocomplete="' + AUTOCOMPLETEVALUE + '" />' +
'</span>' +
'</label>' +
'</li>' +
'</ul>' +
'</li>' +
'<li class="k-item k-clear-wrap">' +
'<span class="k-list-title"> </span>' +
'<ul class="k-listgroup k-listgroup-flush">' +
'<li class="k-listgroup-item">' +
'<span class="k-link k-label k-clear" title="#=messages.clear#" aria-label="#=messages.clear#">' +
'#=messages.clear#' +
'</span>' +
'</li>' +
'</ul>' +
'</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,
field,
columnHeader;
options = options || {};
options.componentType = options.componentType || "classic";
Widget.fn.init.call(that, element, options);
operators = that.operators = options.operators || {};
element = that.element;
options = that.options;
that.dataSource = DataSource.create(options.dataSource);
that.field = options.field || element.attr(kendo.attr("field"));
columnHeader = $(element.closest(COLUMNHEADERATTR));
if (columnHeader.length) {
that.appendTo = columnHeader.find(options.appendTo);
} else {
that.appendTo = $(options.appendTo);
}
that.link = that._createLink() || $();
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 = field.parse.bind(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 = that.refresh.bind(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),
attrRole = kendo.attr("role"),
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, that._submit.bind(that))
.on("reset" + NS, that._reset.bind(that));
if (setUI) {
that.form.find(".k-input-inner")
.removeClass("k-input-inner")
.each(function() {
ui($(this));
});
} else {
that.form
.find(".k-input-inner[" + attrRole + "]")
.removeClass("k-input-inner");
that.form
.find(".k-input-inner:not([data-role]):not(.k-numerictextbox>.k-input-inner)")
.wrap("<span class='k-textbox k-input k-input-md k-rounded-md k-input-solid'></span>");
}
that.refresh();
that.trigger(INIT, { field: that.field, container: that.form });
if (that.options.cycleForm) {
kendo.cycleForm(that.form);
}
},
_createForm: function(role) {
var that = this,
options = that.options,
operators = that.operators || {},
type = that.type;
operators = operators[type] || options.operators[type];
that.form = $('<form title="' + that.options.messages.title + '" class="k-filter-menu"/>')
.html(kendo.template(that._getTemplate())({
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),
componentType: that.options.componentType
}));
if (!options.appendToElement) {
that.popup = that.form[POPUP]({
anchor: that.link,
copyAnchorStyles: false,
open: that._open.bind(that),
activate: that._activate.bind(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, that._keydown.bind(that));
},
_getTemplate: function() {
var that = this,
hasCustomTemplate = isFunction(that.options.ui);
if (that.type === 'boolean') {
if (hasCustomTemplate) {
return customBooleanTemplate;
} else if (that.options.componentType === 'modern') {
return modernBooleanTemplate;
} else {
return booleanTemplate;
}
} else {
return defaultTemplate;
}
},
_createMobileForm: function(role) {
var that = this,
options = that.options,
operators = that.operators || {},
filterMenuGuid = kendo.guid(),
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,
filterMenuGuid: filterMenuGuid,
type: type,
role: role,
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-header-done", function(e) {
that.form.submit();
e.preventDefault();
})
.on("click", ".k-header-cancel", function(e) {
that._closeForm();
e.preventDefault();
})
.on("click", ".k-clear", function(e) {
that._mobileClear();
e.preventDefault();
});
that.view.bind("showStart", function() {
that.refresh();
});
},
_createLink: function() {
var that = this,
element = that.element,
appendTarget = that.appendTo.length ? element.find(that.appendTo) : element,
options = that.options,
title = kendo.format(options.messages.buttonTitle, that.options.title || that.field),
link;
if (options.appendToElement) {
return;
}
link = element.addClass("k-filterable").find(".k-grid-filter");
if (!link[0]) {
link = appendTarget
.append('<a class="k-grid-filter-menu k-grid-filter" href="#" title="' +
title + '" aria-label="' +
title + '"><span class="k-icon k-i-filter"></span></a>')
.find(".k-grid-filter");
}
link.attr("tabindex", -1)
.on("click" + NS, that._click.bind(that));
return link;
},
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" && defaultOperator !== "isempty" && defaultOperator !== "isnotempty")) {
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.options.componentType === "modern" && that.options.extra && that.type !== "boolean" && !that._isMobile) {
that.filterModel.bind("change", function() {
var roleAttribute = kendo.attr("role");
var buttongroup = that.form.find("[" + roleAttribute + "='buttongroup']").data('kendoButtonGroup');
var index = this.logic === "and" ? 0 : 1;
buttongroup.select(buttongroup.element.children().eq(index));
});
that.filterModel.set("onLogicChange",that._logicChangeHandler);
}
}
if (that._bind(expression)) {
that.link.addClass("k-state-active");
} else {
that.link.removeClass("k-state-active");
}
},
_logicChangeHandler: function(e) {
var valueAttribute = kendo.attr('value');
var logic = e.sender.current().attr(valueAttribute);
this.set('logic', logic);
},
destroy: function() {
var that = this;
Widget.fn.destroy.call(that);
if (that.form) {
kendo.unbind(that.form);
kendo.destroy(that.form);
that.form.off(NS);
if (that.popup) {
that.popup.destroy();
that.popup = null;
}
that.form = null;
}
if (that.view) {
that.view.purge();
that.view = null;
}
that.link.off(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(expression) {
var that = this;
expression = expression || $.extend(true, {}, { filters: [] }, that.dataSource.filter()) || { filters: [] };
if (this.trigger("change", { filter: null, field: that.field })) {
return;
}
that._removeFilter(expression);
},
_mobileClear: function() {
var that = this;
var viewElement = that.view.element;
if (that.type === "boolean") {
var booleanRadioButton = viewElement.find("[type='radio']:checked");
var booleanRadioButtonValue = booleanRadioButton.val();
booleanRadioButton.val("");
booleanRadioButton.trigger("change");
booleanRadioButton.val(booleanRadioButtonValue);
booleanRadioButton.prop("checked", false);
} else {
var operatorSelects = viewElement.find("select");
operatorSelects.each(function(i, e) {
var input = $(e);
input.val(input.find("option").first().val());
input.trigger("change");
});
if (that.type === "string" || that.type === "date" || that.type === "number") {
var valueInputs = viewElement.find(".k-value-input");
valueInputs.each(function(i, e) {
var input = $(e);
input.val("");
input.trigger("change");
});
}
if (that.options.extra) {
var andLogicRadio = viewElement.find("[name=logic]").first();
andLogicRadio.prop("checked", true);
andLogicRadio.trigger("change");
}
}
},
_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.clear(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().trigger("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",
done: "Done",
into: "in",
buttonTitle: "{0} filter column settings"
},
animations: {
left: "slide",
right: "slide:right"
},
componentType: 'classic',
cycleForm: true,
appendTo: null
}
});
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)