UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

388 lines (336 loc) • 17.1 kB
"use strict"; var $ = require("../../core/renderer"), domAdapter = require("../../core/dom_adapter"), isDefined = require("../../core/utils/type").isDefined, compileGetter = require("../../core/utils/data").compileGetter, each = require("../../core/utils/iterator").each, gridCoreUtils = require("./ui.grid_core.utils"), messageLocalization = require("../../localization/message"), dataQuery = require("../../data/query"); var SEARCH_PANEL_CLASS = "search-panel", SEARCH_TEXT_CLASS = "search-text", FILTERING_TIMEOUT = 700; function allowSearch(column) { return isDefined(column.allowSearch) ? column.allowSearch : column.allowFiltering; } function parseValue(column, text) { var lookup = column.lookup; if (lookup) { return column.parseValue.call(lookup, text); } else { return column.parseValue ? column.parseValue(text) : text; } } module.exports = { defaultOptions: function defaultOptions() { return { /** * @name GridBaseOptions.searchPanel * @publicName searchPanel * @type object */ searchPanel: { /** * @name GridBaseOptions.searchPanel.visible * @publicName visible * @type boolean * @default false */ visible: false, /** * @name GridBaseOptions.searchPanel.width * @publicName width * @type number * @default 160 */ width: 160, /** * @name GridBaseOptions.searchPanel.placeholder * @publicName placeholder * @type string * @default "Search..." */ placeholder: messageLocalization.format("dxDataGrid-searchPanelPlaceholder"), /** * @name GridBaseOptions.searchPanel.highlightSearchText * @publicName highlightSearchText * @type boolean * @default true */ highlightSearchText: true, /** * @name GridBaseOptions.searchPanel.highlightCaseSensitive * @publicName highlightCaseSensitive * @type boolean * @default false */ highlightCaseSensitive: false, /** * @name GridBaseOptions.searchPanel.text * @publicName text * @type string * @default "" * @fires GridBaseOptions.onOptionChanged */ text: "", /** * @name GridBaseOptions.searchPanel.searchVisibleColumnsOnly * @publicName searchVisibleColumnsOnly * @type boolean * @default false */ searchVisibleColumnsOnly: false } }; }, extenders: { controllers: { data: function () { var calculateSearchFilter = function calculateSearchFilter(that, text) { var i, column, columns = that._columnsController.getColumns(), searchVisibleColumnsOnly = that.option("searchPanel.searchVisibleColumnsOnly"), filterValue, lookup, filters = []; if (!text) return null; function onQueryDone(items) { var i, valueGetter = compileGetter(lookup.valueExpr), value; for (i = 0; i < items.length; i++) { value = valueGetter(items[i]); filters.push(column.createFilterExpression(value, null, "search")); } } for (i = 0; i < columns.length; i++) { column = columns[i]; if (searchVisibleColumnsOnly && !column.visible) continue; if (allowSearch(column) && column.calculateFilterExpression) { lookup = column.lookup; filterValue = parseValue(column, text); if (lookup && lookup.items) { dataQuery(lookup.items).filter(column.createFilterExpression.call({ dataField: lookup.displayExpr, dataType: lookup.dataType, calculateFilterExpression: column.calculateFilterExpression }, filterValue, null, "search")).enumerate().done(onQueryDone); } else { if (filterValue !== undefined) { filters.push(column.createFilterExpression(filterValue, null, "search")); } } } } return gridCoreUtils.combineFilters(filters, "or"); }; return { publicMethods: function publicMethods() { return this.callBase().concat(["searchByText"]); }, _calculateAdditionalFilter: function _calculateAdditionalFilter() { var that = this, filter = that.callBase(), searchFilter = calculateSearchFilter(that, that.option("searchPanel.text")); return gridCoreUtils.combineFilters([filter, searchFilter]); }, /** * @name GridBaseMethods.searchByText * @publicName searchByText(text) * @param1 text:string */ searchByText: function searchByText(text) { this.option("searchPanel.text", text); }, optionChanged: function optionChanged(args) { var that = this; switch (args.fullName) { case "searchPanel.text": case "searchPanel": that._applyFilter(); args.handled = true; break; default: that.callBase(args); } } }; }() }, views: { headerPanel: function () { var getSearchPanelOptions = function getSearchPanelOptions(that) { return that.option("searchPanel"); }; return { _getToolbarItems: function _getToolbarItems() { var items = this.callBase(); return this._prepareSearchItem(items); }, _prepareSearchItem: function _prepareSearchItem(items) { var that = this, dataController = that.getController("data"), searchPanelOptions = getSearchPanelOptions(that); if (searchPanelOptions && searchPanelOptions.visible) { var toolbarItem = { template: function template(data, index, container) { var $search = $("<div>").addClass(that.addWidgetPrefix(SEARCH_PANEL_CLASS)).appendTo(container); that.getController("editorFactory").createEditor($search, { width: searchPanelOptions.width, placeholder: searchPanelOptions.placeholder, parentType: "searchPanel", value: that.option("searchPanel.text"), updateValueTimeout: FILTERING_TIMEOUT, setValue: function setValue(value) { dataController.searchByText(value); }, editorOptions: { inputAttr: { "aria-label": messageLocalization.format("dxDataGrid-ariaSearchInGrid") } } }); that.resize(); }, name: "searchPanel", location: "after", locateInMenu: "never", sortIndex: 40 }; items.push(toolbarItem); } return items; }, _getSearchTextEditor: function _getSearchTextEditor() { var $searchPanel = this.element().find("." + this.addWidgetPrefix(SEARCH_PANEL_CLASS)); if ($searchPanel.length) { return $searchPanel.dxTextBox("instance"); } return null; }, isVisible: function isVisible() { var searchPanelOptions = getSearchPanelOptions(this); return this.callBase() || searchPanelOptions && searchPanelOptions.visible; }, optionChanged: function optionChanged(args) { if (args.name === "searchPanel") { if (args.fullName === "searchPanel.text") { var editor = this._getSearchTextEditor(); if (editor) { editor.option("value", args.value); } } else { this._invalidate(); } args.handled = true; } else { this.callBase(args); } } }; }(), rowsView: { init: function init() { this.callBase.apply(this, arguments); this._searchParams = []; }, _highlightSearchText: function _highlightSearchText(cellElement, isEquals, column) { var that = this, $parent, searchText = that.option("searchPanel.text"); if (searchText && that.option("searchPanel.highlightSearchText")) { var normalizeString = that.option("searchPanel.highlightCaseSensitive") ? function (str) { return str; } : function (str) { return str.toLowerCase(); }; if (isEquals && column) { var value = parseValue(column, searchText), formatOptions = gridCoreUtils.getFormatOptionsByColumn(column, "search"); searchText = gridCoreUtils.formatValue(value, formatOptions); if (!searchText) return; } $parent = cellElement.parent(); if (!$parent.length) { $parent = $("<div>").append(cellElement); } var $items = $parent.find("*").filter(function (index, element) { var $contents = $(element).contents(); for (var i = 0; i < $contents.length; i++) { var node = $contents.get(i); if (node.nodeType === 3) { return (node.textContent || node.nodeValue || "").toLowerCase().indexOf(searchText.toLowerCase()) > -1; } return false; } }); each($items, function (index, element) { each($(element).contents(), function (index, content) { if (content.nodeType !== 3) return; var highlightSearchTextInTextNode = function highlightSearchTextInTextNode($content, searchText) { var $searchTextSpan = $("<span>").addClass(that.addWidgetPrefix(SEARCH_TEXT_CLASS)), text = $content.text(), index = normalizeString(text).indexOf(normalizeString(searchText)); if (index >= 0) { if ($content[0].textContent) { $content[0].textContent = text.substr(0, index); } else { $content[0].nodeValue = text.substr(0, index); } $content.after($searchTextSpan.text(text.substr(index, searchText.length))); $content = $(domAdapter.createTextNode(text.substr(index + searchText.length))).insertAfter($searchTextSpan); return highlightSearchTextInTextNode($content, searchText); } }; if (isEquals) { if (normalizeString($(content).text()) === normalizeString(searchText)) { $(this).replaceWith($("<span>").addClass(that.addWidgetPrefix(SEARCH_TEXT_CLASS)).text($(content).text())); } } else { highlightSearchTextInTextNode($(content), searchText); } }); }); } }, _renderCore: function _renderCore() { this.callBase.apply(this, arguments); // T103538 if (this.option("rowTemplate")) { if (this.option("templatesRenderAsynchronously")) { clearTimeout(this._highlightTimer); this._highlightTimer = setTimeout(function () { this._highlightSearchText(this._getTableElement()); }.bind(this)); } else { this._highlightSearchText(this._getTableElement()); } } }, _updateCell: function _updateCell($cell, parameters) { var column = parameters.column, dataType = column.lookup && column.lookup.dataType || column.dataType, isEquals = dataType !== "string"; if (allowSearch(column)) { if (this.option("templatesRenderAsynchronously")) { if (!this._searchParams.length) { clearTimeout(this._highlightTimer); this._highlightTimer = setTimeout(function () { this._searchParams.forEach(function (params) { this._highlightSearchText.apply(this, params); }.bind(this)); this._searchParams = []; }.bind(this)); } this._searchParams.push([$cell, isEquals, column]); } else { this._highlightSearchText($cell, isEquals, column); } } this.callBase($cell, parameters); }, dispose: function dispose() { clearTimeout(this._highlightTimer); this.callBase(); } } } } };