From 3abb9302db20371a0f06770f22be6b760eabda37 Mon Sep 17 00:00:00 2001 From: Daniel Reznick Date: Sat, 15 Jun 2024 00:21:02 +0300 Subject: [PATCH] 0.9.5 https://github.com/vedmack/yadcf/issues/631 --- jquery.dataTables.yadcf.css | 40 +- jquery.dataTables.yadcf.js | 3448 +++++++++++++++++++++++++---------- 2 files changed, 2531 insertions(+), 957 deletions(-) diff --git a/jquery.dataTables.yadcf.css b/jquery.dataTables.yadcf.css index 2c4a414..84fe269 100644 --- a/jquery.dataTables.yadcf.css +++ b/jquery.dataTables.yadcf.css @@ -18,7 +18,7 @@ display: inline-block; } -.yadcf-filter-reset-button.range-number-slider-reset-button{ +.yadcf-filter-reset-button.range-number-slider-reset-button { position: relative; top: -6px; } @@ -30,23 +30,29 @@ padding-top: 3px; } -.yadcf-filter > option{ - background: white; +.yadcf-filter > option { + background: white; } .ui-autocomplete .ui-menu-item { - font-size:13px; + font-size: 13px; } #ui-datepicker-div { - font-size:13px; + font-size: 13px; } + .yadcf-filter-wrapper { display: inline-block; white-space: nowrap; margin-left: 2px; } +/* issue 669 */ +.yadcf-filter-wrapper .datepicker-months, .yadcf-filter-wrapper .datepicker-years, .yadcf-filter-wrapper .datepicker-decades { + white-space: normal; +} + .yadcf-filter-range-number { width: 40px; } @@ -94,7 +100,7 @@ } .yadcf-filter-range-number-slider { - overflow: visible; + overflow: visible; } .yadcf-number-slider-filter-wrapper-inner .yadcf-filter-range-number-slider-min-tip { @@ -107,17 +113,17 @@ .yadcf-number-slider-filter-wrapper-inner .yadcf-filter-range-number-slider-max-tip { font-size: 13px; font-weight: normal; - position:absolute; + position: absolute; outline-style: none; } .yadcf-number-slider-filter-wrapper-inner .yadcf-filter-range-number-slider-min-tip-inner { - position:absolute; + position: absolute; top: 11px; } .yadcf-number-slider-filter-wrapper-inner .yadcf-filter-range-number-slider-max-tip-inner { - position:absolute; + position: absolute; top: 11px; } @@ -128,21 +134,21 @@ } .yadcf-regex-wrapper { - display: inline-block; - vertical-align: middle; - margin-right: 5px; + display: inline-block; + vertical-align: middle; + margin-right: 5px; } .yadcf-null-wrapper { - display: inline-block; - vertical-align: middle; - margin-right: 5px; + display: inline-block; + vertical-align: middle; + margin-right: 5px; } .yadcf-label.small { font-size: 10px; } -.after{ - margin-left: 10px; +.after { + margin-left: 10px; } diff --git a/jquery.dataTables.yadcf.js b/jquery.dataTables.yadcf.js index f140309..c54d835 100644 --- a/jquery.dataTables.yadcf.js +++ b/jquery.dataTables.yadcf.js @@ -2,7 +2,7 @@ * Yet Another DataTables Column Filter - (yadcf) * * File: jquery.dataTables.yadcf.js -* Version: 0.9.3 +* Version: 0.9.5 * * Author: Daniel Reznick * Info: https://github.com/vedmack/yadcf @@ -24,10 +24,15 @@ * ------------- * column_number - Required: true + Required: true (or use column_selector) Type: int Description: The number of the column to which the filter will be applied +* column_selector + Required: true (or use column_number) + Type: see https://datatables.net/reference/type/column-selector for valid column-selector formats + Description: The column-selector of the column to which the filter will be applied + * filter_type Required: false Type: String @@ -72,14 +77,28 @@ Required: false Type: String Default value: 'text' - Possible values: text / html / rendered_html + Possible values: text / html / rendered_html / html5_data_complex Description: The type of data in column , use "html" when you have some html code in the column (support parsing of multiple elements per cell), - use rendered_html when you are using render function of columnDefs or similar, that produces a html code, note that both types rendered_html and html have a fallback for simple text parsing + use rendered_html when you are using render function of columnDefs or similar, that produces a html code, note that both types rendered_html and html have a fallback for simple text parsing. + html5_data_complex allows to populate filter with pairs of display/value by using datatables datatables HTML5 data-* attributes - should be used along with specifying html5_data attribute (read docs) + +* column_data_render + Required: false + Type: function + Possible values: function (data) {return data.someValue || ('whatever ' + data.otherValue)} + Description: function that will help yadcf to know what is "text" is present in the cell + Note: Originally added to enable cumulative_filtering with column_data_type: "rendered_html" * text_data_delimiter Required: false Type: String - Description: Delimiter that seperates text in table column, for example text_data_delimiter: "," + Description: Delimiter that separates text in table column, for example text_data_delimiter: "," + +* custom_range_delimiter: + Required: false + Type: String + Default value: '-yadcf_delim-' + Description: Delimiter that separates min and max values for number range filter type, for example custom_range_delimiter: 'minMax' * html_data_type Required: false @@ -104,6 +123,7 @@ Default value: undefined Possible values: data-filter / data-search / anything that is supported by datatables Description: Allows to filter based on data-filter / data-search attributes of the element, read more: http://www.datatables.net/examples/advanced_init/html5-data-attributes.html + Special notes: Can be used along with column_data_type: 'html5_data_complex' to populate filter with pairs of display/value instead of values only * filter_container_id Required: false @@ -144,7 +164,7 @@ Required: false Type: String Default value: 'alpha' - Possible values: alpha / num / alphaNum / none + Possible values: alpha / num / alphaNum / custom / none Description: Defines how the values in the filter will be sorted, alphabetically / numerically / alphanumeric / custom / not sorted at all (none is useful to preserve the order of the data attribute as is) Note: When custom value is set you must provide a custom sorting function for the sort_as_custom_func property @@ -175,13 +195,13 @@ Type: String Default value: undefined Possible values: Any format accepted by momentjs - Description: Defines the format in which the date values are being parsed into Date object by momentjs library + Description: Defines the format in which the table date values are being parsed into Date object by momentjs library Note: Currently relevant only when using datepicker_type: 'bootstrap-datetimepicker') * ignore_char Required: false Type: String - Description: Tells the range_number and range_number_slide to ignore specific char while filtering (that char can used as number separator) + Description: Tells the range_number and range_number_slider to ignore specific char while filtering (that char can used as number separator) Note: Use double escape for regex chars , e.g \\$ , also you can use multiple ignore chars with | , e.g '_|\\.|\\$' * filter_match_mode @@ -196,7 +216,7 @@ Type: boolean Default value: undefined Description: Adds a checkbox next to the filter that allows to do a "not/exclude" filtering (acts the same all filter_match_mode) - Note: Currently available for the text filter + Note: Currently available for the text, select and number_range filter * exclude_label Required: false @@ -204,6 +224,41 @@ Default value: 'exclude' Description: The label that will appear above the exclude checkbox +* regex_check_box + Required: false + Type: boolean + Default value: undefined + Description: Adds a checkbox next to the filter that allows to switch to regex filter_match_mode filtering on a fly + Note: Currently available for the text filter + +* regex_label + Required: false + Type: String + Default value: 'regex' + Description: The label that will appear above the regex checkbox + +* null_check_box + Required: false + Type: boolean + Default value: undefined + Description: Adds a checkbox next to the filter that allows to filter by null value, + works only for tables with data retrieved via data property, not working for html defined tables, + where null is represented as string + Note: Currently available for the text and range_number filters + +* null_label + Required: false + Type: String + Default value: 'null' + Description: The label that will appear above the null checkbox + +* checkbox_position_after + Required: false + Type: boolean + Default value: false + Description: Adds checkboxes exclude and regex after input text column + Note: Currently available for the text filter + * select_type Required: false Type: String @@ -219,6 +274,14 @@ Default value: {} Description: This parameter will be passed "as is" to the Chosen/Select2 plugin constructor +* select_null_option + Required: false + Type: string + Default value: 'null' + Description: String value which internally represents null option in select filters, + also it is send to server if serverside feature is enabled + Supports exclude, with exclude enabled the string is wrapped with exclude regex + * filter_plugin_options Required: false Type: Object @@ -231,7 +294,6 @@ Default value: true Description: Do case-insensitive filtering (supported in select / auto_complete / text filters) - * filter_delay Required: false Type: integer @@ -243,7 +305,7 @@ Required: false Type: String Default value: 'jquery-ui' - Possible values: 'jquery-ui' / 'bootstrap-datetimepicker' / bootstrap-datepicker + Possible values: 'jquery-ui' / 'bootstrap-datetimepicker' / bootstrap-datepicker / daterangepicker / dt-datetime (DataTable Editor DateTime picker) Description: You can choose datapicker library from defined in special notes Special notes: Currently supported only jQueryUI datepicker (datepicker) and Bootstrap datepicker (eonasdan-bootstrap-datetimepicker) Bootstrap datepicker depends moment library. This plugin depends moment too. @@ -259,6 +321,24 @@ Type: String Description: Allows adding additional class/classes to filter reset button +* externally_triggered_checkboxes_text + Required: false + Default value: false, + Type: boolean | string + Description: Adds external checkboxes button, and hides exclude/null/regex checkboxes + usecase: hide/show options (checkboxes) button, checkboxes in popover/modal + +* externally_triggered_checkboxes_function + Required: false + Default value: undefined, + Type: function + Description: Adds onclick function to external checkboxes button, with event parameter + +* externally_triggered_checkboxes_button_style_class + Required: false + Default value: '' + Type: String + Description: Allows adding additional class/classes to external checkboxes button * Global Parameters (per table rather than per column) * @@ -277,9 +357,8 @@ Required: false Type: boolean Default value: false - Description: Change the default behaviour of the filters so its options will be populated from the filtered rows (remaining - table data after filtering) only, unlike the normal behaviour in which the options of the filters are from all the table data - + Description: Change the default behavior of the filters so its options will be populated from the filtered rows (remaining + table data after filtering) only, unlike the normal behavior in which the options of the filters are from all the table data * filters_position Required: false @@ -287,8 +366,7 @@ Default value: header Possible values: 'header' / 'footer' Description: Filters can be placed in the header (thead) or in the footer (tfoot) of the table, - Note: When 'footer' you must provide a valid tfoot elemet in your table - + Note: When 'footer' you must provide a valid tfoot element in your table * filters_tr_index Required: false @@ -297,14 +375,38 @@ Description: Allow to control the index of the inside the thead of the table, e.g when one is used for headers/sort and another is used for filters - * onInitComplete Required: false Type: function Default value: undefined Description: Calls the provided callback function in the end of the yadcf init function - Note: This callback function will run before datatables fires its event such as draw/xhr/etc., migth be usefull for call some - third parties init / loading code + Note: This callback function will run before datatables fires its event such as draw/xhr/etc., might be useful for call some + third parties init / loading code + +* jquery_ui_datepicker_locale + Required: false + Type: string + Default value: "" + Description: Load localized jquery-ui datepicker + Note: Need to load jquery-ui-i18n lib. + Possible values: af, ar-DZ, ar, az, be, bg, bs, ca, cs, cy-GB, da, de, el, en-AU, en-GB, en-NZ, eo, es, et, eu, fa, fi, fo, fr-CA, fr-CH, + fr, gl, he, hi, hr, hu, hy, id, is, it-CH, it, ja, ka, kk, km, ko, ky, lb, lt, lv, mk, ml, ms, nb, nl-BE, nl, nn, no, pl, + pt-BR, pt, rm, ro, ru, sk, sl, sq, sr-SR, sr, sv, ta, th, tj, tr, uk, vi, zh-CN, zh-HK, zh-TW + +* null_api_call_value + Required: false + Type: string + Default value: "null" + Description: Value which represents null, and is used as argument for fnFilter function, and sent to server + Note: works with null filter enabled only + +* not_null_api_call_value + Required: false + Type: string + Default value: "!^@" + Description: Value which represents not null, and is used as argument for fnFilter function, and sent to server + Note: works with null filter enabled only + * * * @@ -329,7 +431,6 @@ Usage example: yadcf.exGetColumnFilterVal(oTable,1); Return value: String (for simple filter) / Object (for range filter) with from and to properties / Array of strings for multi_select filter - * exResetAllFilters Description: Allows to reset all filters externally/programmatically (support ALL filter types!!!) , perfect for adding a "reset all" button to your page! Arguments: table_arg: (variable of the datatable) @@ -343,11 +444,11 @@ array with columns numbers noRedraw: (boolean) , use it if you don't want your table to be reloaded after the filter reset, for example if you planning to call exFilterColumn function right after the exResetFilters (to avoid two AJAX requests) - Usage example: yadcf.exResetAllFilters(oTable, [1,2]); + Usage example: yadcf.exResetFilters(oTable, [1,2]); * initSelectPluginCustomTriggers Description: Allows to set any select jquery plugin initialize and refresh functions. jQuery selector will be passed to the user defined function to initialize and refresh the plugin. - Great for integrating any jquey select plugin (Selectize / MultiSelect / etc) + Great for integrating any jquery select plugin (Selectize / MultiSelect / etc) Arguments: initFunc : function which will initialize the plugin refreshFunc : function that will refresh the plugin. destroyFunc : function that will destroy the plugin (upon table destroy even trigger). @@ -356,7 +457,26 @@ * exFilterExternallyTriggered Description: Triggers all the available filters, should be used only when the externally_triggered option used Arguments: table_arg: (variable of the datatable) - Usage example: yadcf.exResetAllFilters(table_arg); + Usage example: yadcf.exFilterExternallyTriggered(table_arg); + +* exRefreshColumnFilterWithDataProp + Description: Updates column filter with new data, when data property was used in initialization for this filter + e.g. select filter, when we used data property and we want to update it + Arguments: table_arg: variable of the datatable + col_num: number index of column filter + updatedData: array of new data (use same data structure as was used in yadcf.init options) + Usage example: yadcf.exRefreshColumnFilterWithDataProp(table_arg, 5, ['One', 'Two', 'Three']); + +* initOnDtXhrComplete + Description: Allows to set a callback function to be called after dt xhr finishes + Arguments: function to do some logic + Usage example: yadcf.initOnDtXhrComplete(function() { $("#yadcf-filter--example-0").multiselect('refresh'); }); + +* initDefaults + Description: Init global defaults for all yadcf instances. + Arguments: Object consisting of anything defined inside default_options variable + Usage example: yadcf.initDefaults({language: {select: 'Pick some'}}); + * * * @@ -415,53 +535,53 @@ */ //Polyfills if (window.NodeList && !NodeList.prototype.forEach) { - NodeList.prototype.forEach = function (callback, thisArg) { - thisArg = thisArg || window; - for (var i = 0; i < this.length; i++) { - callback.call(thisArg, this[i], i, this); - } - }; + NodeList.prototype.forEach = function (callback, thisArg) { + thisArg = thisArg || window; + for (var i = 0; i < this.length; i++) { + callback.call(thisArg, this[i], i, this); + } + }; } if (!Object.entries) { - Object.entries = function(obj) { - var ownProps = Object.keys(obj), - i = ownProps.length, - resArray = new Array(i); // preallocate the Array - while (i--) - resArray[i] = [ownProps[i], obj[ownProps[i]]]; - - return resArray; - }; + Object.entries = function (obj) { + var ownProps = Object.keys(obj), + i = ownProps.length, + resArray = new Array(i); // preallocate the Array + while (i--) + resArray[i] = [ownProps[i], obj[ownProps[i]]]; + + return resArray; + }; } (function (factory) { - 'use strict'; - - if (typeof define === 'function' && define.amd) { - // AMD - define(['jquery'], function ($) { - return factory($, window, document); - }); - } else if (typeof module === 'object') { - // CommonJS - module.exports = function (root, $) { - if (!root) { - // CommonJS environments without a window global must pass a - // root. This will give an error otherwise - root = window; - } - - if (!$) { - $ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window - require('jquery') : - require('jquery')(root); - } - - return factory($, root, root.document); - }; - } else { - // Browser - factory(jQuery, window, document); - } + 'use strict'; + + if (typeof define === 'function' && define.amd) { + // AMD + define(['jquery'], function ($) { + return factory($, window, document); + }); + } else if (typeof module === 'object') { + // CommonJS + module.exports = function (root, $) { + if (!root) { + // CommonJS environments without a window global must pass a + // root. This will give an error otherwise + root = window; + } + + if (!$) { + $ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window + require('jquery') : + require('jquery')(root); + } + + return factory($, root, root.document); + }; + } else { + // Browser + factory(jQuery, window, document); + } } (function ($, window, document, undefined) { var yadcf = (function () { @@ -477,18 +597,49 @@ if (!Object.entries) { selectElementCustomInitFunc, selectElementCustomRefreshFunc, selectElementCustomDestroyFunc, - placeholderLang = { - select: 'Select value', - select_multi: 'Select values', - filter: 'Type to filter', - range: ['From', 'To'], - date: 'Select a date' + default_options = { + filter_type: "select", + enable_auto_complete: false, + sort_as: "alpha", + sort_order: "asc", + date_format: "mm/dd/yyyy", + ignore_char: undefined, + filter_match_mode: "contains", + select_type: undefined, + select_type_options: {}, + select_null_option: 'null', + case_insensitive: true, + column_data_type: 'text', + html_data_type: 'text', + exclude_label: 'exclude', + regex_label: 'regex', + null_label: 'null', + checkbox_position_after: false, + style_class: '', + reset_button_style_class: '', + datepicker_type: 'jquery-ui', + range_data_type: 'single', + range_data_type_delim: '-', + omit_default_label: false, + custom_range_delimiter: '-yadcf_delim-', + externally_triggered_checkboxes_text: false, + externally_triggered_checkboxes_function: undefined, + externally_triggered_checkboxes_button_style_class: '', + language: { + select: 'Select value', + select_multi: 'Select values', + filter: 'Type to filter', + range: ['From', 'To'], + date: 'Select a date' + } }, - settingsMap = {}; - + settingsMap = {}, + dTXhrComplete; + + let ctrlPressed = false; let closeBootstrapDatepicker = false; - let closeBootstrapDatepickerRange = false; - let closeSelect2 = false; + let closeBootstrapDatepickerRange = false; + let closeSelect2 = false; //From ColReorder (SpryMedia Ltd (www.sprymedia.co.uk)) function getSettingsObjFromTable(dt) { @@ -572,6 +723,10 @@ if (!Object.entries) { return column_number_obj; } + function initDefaults(params) { + return $.extend(true, default_options, params); + } + function getOptions(selector) { return options[selector]; } @@ -591,7 +746,7 @@ if (!Object.entries) { var i = 0; dot_refs = dot_refs.split("."); for (i = 0; i < dot_refs.length; i++) { - if (tmpObj[dot_refs[i]]) { + if (tmpObj[dot_refs[i]] !== undefined && tmpObj[dot_refs[i]] !== null) { tmpObj = tmpObj[dot_refs[i]]; } else { return ''; @@ -600,32 +755,11 @@ if (!Object.entries) { return tmpObj; } - function setOptions(selector_arg, options_arg, params) { + function setOptions(selector_arg, options_arg, params, table) { var tmpOptions = {}, i, - col_num_as_int, - default_options = { - filter_type: "select", - enable_auto_complete: false, - sort_as: "alpha", - sort_order: "asc", - date_format: "mm/dd/yyyy", - ignore_char: undefined, - filter_match_mode: "contains", - select_type: undefined, - select_type_options: {}, - case_insensitive: true, - column_data_type: 'text', - html_data_type: 'text', - exclude_label: 'exclude', - style_class: '', - reset_button_style_class: '', - datepicker_type: 'jquery-ui', - range_data_type: 'single', - range_data_type_delim: '-', - omit_default_label: false - }; - //adaptContainerCssClassImpl = function (dummy) { return ''; }; + col_num_as_int; + //adaptContainerCssClassImpl = function (dummy) { return ''; }; $.extend(true, default_options, params); @@ -653,26 +787,38 @@ if (!Object.entries) { return; } } - col_num_as_int = +options_arg[i].column_number; - if (isNaN(col_num_as_int)) { - tmpOptions[options_arg[i].column_number_str] = $.extend(true, {}, default_options, options_arg[i]); + if (!options_arg[i].column_selector) { + col_num_as_int = +options_arg[i].column_number; + if (isNaN(col_num_as_int)) { + tmpOptions[options_arg[i].column_number_str] = $.extend(true, {}, default_options, options_arg[i]); + } else { + tmpOptions[col_num_as_int] = $.extend(true, {}, default_options, options_arg[i]); + } } else { - tmpOptions[col_num_as_int] = $.extend(true, {}, default_options, options_arg[i]); + if (table && table.column) { + //translate from column_selector to column_number + let columnNumber = table.column(options_arg[i].column_selector); + if (columnNumber.index() >= 0) { + options_arg[i].column_number = columnNumber.index(); + tmpOptions[options_arg[i].column_number] = $.extend(true, {}, default_options, options_arg[i]); + } + } } } + options[selector_arg] = tmpOptions; - + check3rdPPluginsNeededClose(); } function check3rdPPluginsNeededClose() { - Object.entries(getAllOptions()).forEach(function(tableEntry) { - Object.entries(tableEntry[1]).forEach(function(columnEntry) { + Object.entries(getAllOptions()).forEach(function (tableEntry) { + Object.entries(tableEntry[1]).forEach(function (columnEntry) { if (columnEntry[1].datepicker_type === 'bootstrap-datepicker') { if (columnEntry[1].filter_type === 'range_date') { closeBootstrapDatepickerRange = true; } else { - closeBootstrapDatepicker = true; + closeBootstrapDatepicker = true; } } else if (columnEntry[1].select_type === 'select2') { closeSelect2 = true; @@ -680,7 +826,7 @@ if (!Object.entries) { }); }); } - + //taken and modified from DataTables 1.10.0-beta.2 source function yadcfVersionCheck(version) { var aThis = $.fn.dataTable.ext.sVersion.split('.'), @@ -708,17 +854,16 @@ if (!Object.entries) { function resetIApiIndex() { $.fn.dataTableExt.iApiIndex = 0; - } function escapeRegExp(string) { - return string.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"); + return string.replace(/([.*+?^=!:${}()|'\[\]\/\\])/g, "\\$1"); } function escapeRegExpInArray(arr) { var i; for (i = 0; i < arr.length; i++) { - arr[i] = arr[i].replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"); + arr[i] = arr[i].replace(/([.*+?^=!:${}()|'\[\]\/\\])/g, "\\$1"); } return arr; } @@ -778,7 +923,7 @@ if (!Object.entries) { function initializeSelectPlugin(selectType, $selectObject, select_type_options) { if (selectType === 'chosen') { $selectObject.chosen(select_type_options); - $selectObject.next().attr("onclick", "yadcf.stopPropagation(event);").attr("onmousedown", "yadcf.stopPropagation(event);"); + $selectObject.next().on("click", yadcf.stopPropagation).on("mousedown", yadcf.stopPropagation); refreshSelectPlugin({ select_type: selectType, select_type_options: select_type_options @@ -788,11 +933,11 @@ if (!Object.entries) { $selectObject.select2(select_type_options); } if ($selectObject.next().hasClass('select2-container')) { - $selectObject.next().attr("onclick", "yadcf.stopPropagation(event);").attr("onmousedown", "yadcf.stopPropagation(event);"); + $selectObject.next().on("click", yadcf.stopPropagation).on("mousedown", yadcf.stopPropagation); } } else if (selectType === 'custom_select') { selectElementCustomInitFunc($selectObject); - $selectObject.next().attr("onclick", "yadcf.stopPropagation(event);").attr("onmousedown", "yadcf.stopPropagation(event);"); + $selectObject.next().on("click", yadcf.stopPropagation).on("mousedown", yadcf.stopPropagation); } } @@ -820,6 +965,10 @@ if (!Object.entries) { selectElementCustomDestroyFunc = destroyFunc; } + function initOnDtXhrComplete(initFunc) { + dTXhrComplete = initFunc; + } + //Used by exFilterColumn for translating readable search value into proper search string for datatables filtering function yadcfMatchFilterString(table_arg, column_number, selected_value, filter_match_mode, multiple, exclude) { var case_insensitive = yadcf.getOptions(table_arg.selector)[column_number].case_insensitive, @@ -870,13 +1019,21 @@ if (!Object.entries) { } function yadcfMatchFilter(oTable, selected_value, filter_match_mode, column_number, exclude, original_column_number) { - var case_insensitive = yadcf.getOptions(oTable.selector)[original_column_number].case_insensitive; + var columnObj = getOptions(oTable.selector)[original_column_number], + case_insensitive = columnObj.case_insensitive; if (exclude !== true) { if (filter_match_mode === "contains") { - oTable.fnFilter(selected_value, column_number, false, true, true, case_insensitive); + oTable.fnFilter(selected_value, column_number, false, false, true, case_insensitive); } else if (filter_match_mode === "exact") { + let prefix = '^'; + let suffix = '$'; + if (columnObj.text_data_delimiter !== undefined) { + let text_data_delimiter = escapeRegExp(columnObj.text_data_delimiter); + prefix = '(' + prefix + '|' + text_data_delimiter + ')'; + suffix = '(' + suffix + '|' + text_data_delimiter + ')'; + } selected_value = escapeRegExp(selected_value); - oTable.fnFilter("^" + selected_value + "$", column_number, true, false, true, case_insensitive); + oTable.fnFilter(prefix + selected_value + suffix, column_number, true, false, true, case_insensitive); } else if (filter_match_mode === "startsWith") { selected_value = escapeRegExp(selected_value); oTable.fnFilter("^" + selected_value, column_number, true, false, true, case_insensitive); @@ -890,6 +1047,11 @@ if (!Object.entries) { oTable.fnFilter(selected_value, column_number, true, false, true, case_insensitive); } } else { + if (filter_match_mode === "exact") { + selected_value = "^" + escapeRegExp(selected_value) + "$"; + } else if (filter_match_mode === "startsWith") { + selected_value = "^" + escapeRegExp(selected_value); + } oTable.fnFilter("^((?!" + selected_value + ").)*$", column_number, true, false, true, case_insensitive); } } @@ -921,8 +1083,8 @@ if (!Object.entries) { if (arg.value !== undefined && arg.value !== "-1") { $("#yadcf-filter-" + table_selector_jq_friendly + "-" + column_number).addClass("inuse"); } else { - //wehn arg === 'clear' or arg.value === '-1' - $("#yadcf-filter-" + table_selector_jq_friendly + "-" + column_number).val('-1').focus(); + //when arg === 'clear' or arg.value === '-1' + $("#yadcf-filter-" + table_selector_jq_friendly + "-" + column_number).val('-1').trigger('focus'); $("#yadcf-filter-" + table_selector_jq_friendly + "-" + column_number).removeClass("inuse"); refreshSelectPlugin(columnObj, $("#yadcf-filter-" + table_selector_jq_friendly + "-" + column_number), '-1'); } @@ -934,9 +1096,9 @@ if (!Object.entries) { if (oTable.fnSettings().oFeatures.bStateSave === true) { if (oTable.fnSettings().oLoadedState.yadcfState !== undefined && oTable.fnSettings().oLoadedState.yadcfState[table_selector_jq_friendly] !== undefined) { oTable.fnSettings().oLoadedState.yadcfState[table_selector_jq_friendly][column_number] = - { - from: arg.value - }; + { + from: arg.value + }; } else { yadcfState = {}; yadcfState[table_selector_jq_friendly] = []; @@ -971,16 +1133,26 @@ if (!Object.entries) { selected_value, column_number_filter, columnObj, + exclude_checked = false, settingsDt = getSettingsObjFromTable(oTable); column_number_filter = calcColumnNumberFilter(settingsDt, column_number, table_selector_jq_friendly); columnObj = getOptions(oTable.selector)[column_number]; + if (columnObj.exclude) { + exclude_checked = $("#yadcf-filter-wrapper-" + table_selector_jq_friendly + "-" + column_number).find('.yadcf-exclude-wrapper :checkbox').prop('checked'); + } + if (arg === "clear") { + clearStateSave(oTable, column_number, table_selector_jq_friendly); + if (exclude_checked) { + resetExcludeRegexCheckboxes($("#yadcf-filter-wrapper-" + table_selector_jq_friendly + "-" + column_number)); + clearStateSave(oTable, column_number, table_selector_jq_friendly); + } if (exGetColumnFilterVal(oTable, column_number) === '') { return; } - $("#yadcf-filter-" + table_selector_jq_friendly + "-" + column_number).val("-1").focus(); + $("#yadcf-filter-" + table_selector_jq_friendly + "-" + column_number).val("-1").trigger('focus'); $("#yadcf-filter-" + table_selector_jq_friendly + "-" + column_number).removeClass("inuse"); $(document).data("#yadcf-filter-" + table_selector_jq_friendly + "-" + column_number + "_val", "-1"); oTable.fnFilter("", column_number_filter); @@ -990,21 +1162,62 @@ if (!Object.entries) { return; } + if (arg === "exclude" && $.trim($("#yadcf-filter-" + table_selector_jq_friendly + "-" + column_number).find('option:selected').val()) === "-1") { + return; + } + $("#yadcf-filter-" + table_selector_jq_friendly + "-" + column_number).addClass("inuse"); - $(document).data("#yadcf-filter-" + table_selector_jq_friendly + "-" + column_number + "_val", arg.value); + selected_value = $.trim($(arg === "exclude" ? "#yadcf-filter-" + table_selector_jq_friendly + "-" + column_number : arg).find('option:selected').val()); - selected_value = $.trim($(arg).find('option:selected').val()); + $(document).data("#yadcf-filter-" + table_selector_jq_friendly + "-" + column_number + "_val", (arg === "exclude" || exclude_checked) ? selected_value : arg.value); - if (arg.value !== "-1") { - yadcfMatchFilter(oTable, selected_value, filter_match_mode, column_number_filter, false, column_number); + if (arg.value !== "-1" && selected_value !== columnObj.select_null_option) { + if (oTable.fnSettings().oFeatures.bServerSide === false) { + oTable.fnDraw(); + } + yadcfMatchFilter(oTable, selected_value, filter_match_mode, column_number_filter, exclude_checked, column_number); + } else if (selected_value === columnObj.select_null_option) { + if (oTable.fnSettings().oFeatures.bServerSide === false) { + oTable.fnFilter("", column_number_filter); + addNullFilterCapability(table_selector_jq_friendly, column_number, true); + oTable.fnDraw(); + } else { + yadcfMatchFilter(oTable, selected_value, filter_match_mode, column_number_filter, exclude_checked, column_number); + } + if (oTable.fnSettings().oFeatures.bStateSave === true) { + stateSaveNullSelect(oTable, columnObj, table_selector_jq_friendly, column_number, filter_match_mode, exclude_checked); + oTable.fnSettings().oApi._fnSaveState(oTable.fnSettings()); + } } else { - oTable.fnFilter("", column_number_filter); $("#yadcf-filter-" + table_selector_jq_friendly + "-" + column_number).removeClass("inuse"); + oTable.fnFilter("", column_number_filter); } resetIApiIndex(); } + function stateSaveNullSelect(oTable, columnObj, table_selector_jq_friendly, column_number, filter_match_mode, exclude_checked) { + let null_str = columnObj.select_null_option; + switch (filter_match_mode) { + case "exact": + null_str = "^" + escapeRegExp(null_str) + "$"; + break; + case "startsWith": + null_str = "^" + escapeRegExp(null_str); + break; + default: + break; + } + const excludeStrStart = "^((?!"; + const excludeStrEnd = ").)*$"; + null_str = exclude_checked ? (excludeStrStart + null_str + excludeStrEnd) : null_str; + if (oTable.fnSettings().oLoadedState) { + if (oTable.fnSettings().oLoadedState.yadcfState !== undefined && oTable.fnSettings().oLoadedState.yadcfState[table_selector_jq_friendly] !== undefined) { + oTable.fnSettings().aoPreSearchCols[column_number].sSearch = null_str; + } + } + } + function doFilterMultiSelect(arg, table_selector_jq_friendly, column_number, filter_match_mode) { $.fn.dataTableExt.iApiIndex = oTablesIndex[table_selector_jq_friendly]; var oTable = oTables[table_selector_jq_friendly], @@ -1035,7 +1248,7 @@ if (!Object.entries) { stringForSearch = stringForSearch.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"); stringForSearch = stringForSearch.split('narutouzomaki').join('|'); if (filter_match_mode === "contains") { - oTable.fnFilter(stringForSearch, column_number_filter, true, false, true); + oTable.fnFilter(stringForSearch, column_number_filter, true, false, true);//"^((?!" + stringForSearch + ").)*$" } else if (filter_match_mode === "exact") { oTable.fnFilter("^(" + stringForSearch + ")$", column_number_filter, true, false, true); } else if (filter_match_mode === "startsWith") { @@ -1084,7 +1297,7 @@ if (!Object.entries) { if (exGetColumnFilterVal(oTable, column_number) === '') { return; } - $("#yadcf-filter-" + table_selector_jq_friendly + "-" + column_number).val("").focus(); + $("#yadcf-filter-" + table_selector_jq_friendly + "-" + column_number).val("").trigger('focus'); $("#yadcf-filter-" + table_selector_jq_friendly + "-" + column_number).removeClass("inuse"); $(document).removeData("#yadcf-filter-" + table_selector_jq_friendly + "-" + column_number + "_val"); oTable.fnFilter("", column_number_filter); @@ -1127,7 +1340,7 @@ if (!Object.entries) { } function findMinInArray(array, columnObj) { - var narray = [], + var narray = [], i, num, min; @@ -1136,7 +1349,7 @@ if (!Object.entries) { if (columnObj.ignore_char !== undefined) { array[i] = array[i].toString().replace(columnObj.ignore_char, ""); } - if (columnObj.range_data_type === 'single') { + if (columnObj.range_data_type !== 'range') { num = +array[i]; } else { num = array[i].split(columnObj.range_data_type_delim); @@ -1147,7 +1360,7 @@ if (!Object.entries) { } } } - min = Math.min.apply(Math, narray); + min = Math.min(...narray); if (!isFinite(min)) { min = 0; } else if (min !== 0) { @@ -1157,7 +1370,7 @@ if (!Object.entries) { min = -1 * Math.ceil(min * -1); } } - + return min; } @@ -1171,7 +1384,7 @@ if (!Object.entries) { if (columnObj.ignore_char !== undefined) { array[i] = array[i].toString().replace(columnObj.ignore_char, ""); } - if (columnObj.range_data_type === 'single') { + if (columnObj.range_data_type !== 'range') { num = +array[i]; } else { num = array[i].split(columnObj.range_data_type_delim); @@ -1182,7 +1395,7 @@ if (!Object.entries) { } } } - max = Math.max.apply(Math, narray); + max = Math.max(...narray); if (!isFinite(max)) { max = 0; } else { @@ -1207,7 +1420,8 @@ if (!Object.entries) { columnObj, column_number_filter, valFrom, - valTo; + valTo, + exclude_checked = false; if (table_selector_jq_friendly_local !== current_table_selector_jq_friendly) { return true; @@ -1221,10 +1435,31 @@ if (!Object.entries) { max = $('#' + toId).val(); } + if (columnObj.exclude) { + exclude_checked = $("#yadcf-filter-wrapper-" + table_selector_jq_friendly + "-" + col_num).find('.yadcf-exclude-wrapper :checkbox').prop('checked'); + } + column_number_filter = calcColumnNumberFilter(settingsDt, col_num, table_selector_jq_friendly); if (rowData !== undefined) { - aData = rowData; + let rowDataRender; + if (columnObj.column_number_render) { + rowDataRender = $.extend(true, [], rowData); + const index = columnObj.column_number_data ? columnObj.column_number_data : column_number_filter; + const meta = { + row: iDataIndex, + col: columnObj.column_number, + settings: settingsDt + }; + if (typeof index === 'string' && typeof rowDataRender === 'object') { + const cellDataRender = columnObj.column_number_render(getProp(rowDataRender, index), 'filter', rowData, meta); + setProp(rowDataRender, index, (cellDataRender !== undefined && cellDataRender !== null) ? cellDataRender : getProp(rowData, index)); + } else { + const cellDataRender = columnObj.column_number_render(rowDataRender[index], 'filter', rowData, meta); + rowDataRender[index] = (cellDataRender !== undefined && cellDataRender !== null) ? cellDataRender : rowData[index]; + } + } + aData = rowDataRender ? rowDataRender : rowData; if (columnObj.column_number_data !== undefined) { column_number_filter = columnObj.column_number_data; val = dot2obj(aData, column_number_filter); @@ -1246,18 +1481,18 @@ if (!Object.entries) { } if ($(val).length !== 0) { switch (html_data_type) { - case "text": - val = $(val).text(); - break; - case "value": - val = $(val).val(); - break; - case "id": - val = val.id; - break; - case "selector": - val = $(val).find(columnObj.html_data_selector).text(); - break; + case "text": + val = $(val).text(); + break; + case "value": + val = $(val).val(); + break; + case "id": + val = val.id; + break; + case "selector": + val = $(val).find(columnObj.html_data_selector).text(); + break; } } } else { @@ -1288,36 +1523,81 @@ if (!Object.entries) { } min = (min !== "") ? (+min) : min; max = (max !== "") ? (+max) : max; - if (columnObj.range_data_type === 'single') { - val = (val !== "") ? (+val) : val; - if (min === "" && max === "") { - retVal = true; - } else if (min === "" && val <= max) { - retVal = true; - } else if (min <= val && "" === max) { - retVal = true; - } else if (min <= val && val <= max) { - retVal = true; - } else if (val === '' || isNaN(val)) { - retVal = true; + if (!exclude_checked) { + if (columnObj.range_data_type === 'single') { + val = (val !== "") ? (+val) : val; + if (min === "" && max === "") { + retVal = true; + } else if (min === "" && val <= max) { + retVal = true; + } else if (min <= val && "" === max) { + retVal = true; + } else if (min <= val && val <= max) { + retVal = true; + } else if (val === '' || isNaN(val)) { + retVal = true; + } + } else if (columnObj.range_data_type === 'range') { + val = val.split(columnObj.range_data_type_delim); + valFrom = (val[0] !== "") ? (+val[0]) : val[0]; + valTo = (val[1] !== "") ? (+val[1]) : val[1]; + if (!columnObj.range_data_operator) { + if (min === "" && max === "") { + retVal = true; + } else if (min === "" && valTo <= max) { + retVal = true; + } else if (min <= valFrom && "" === max) { + retVal = true; + } else if (min <= valFrom && valTo <= max) { + retVal = true; + } else if ((valFrom === '' || isNaN(valFrom)) && (valTo === '' || isNaN(valTo))) { + retVal = true; + } + } + } else if (columnObj.range_data_type === 'delimiter') { + if (columnObj.text_data_delimiter !== undefined) { + let valSplitted = val.split(columnObj.text_data_delimiter); + let anyNumberInRange = function (fromToObj) { + return function (element, index, array) { + return element >= fromToObj.from && element <= fromToObj.to; + }; + }; + retVal = valSplitted.some(anyNumberInRange({ from: min, to: max })); + } } - } else if (columnObj.range_data_type === 'range') { - val = val.split(columnObj.range_data_type_delim); - valFrom = (val[0] !== "") ? (+val[0]) : val[0]; - valTo = (val[1] !== "") ? (+val[1]) : val[1]; - if (min === "" && max === "") { - retVal = true; - } else if (min === "" && valTo <= max) { - retVal = true; - } else if (min <= valFrom && "" === max) { - retVal = true; - } else if (min <= valFrom && valTo <= max) { - retVal = true; - } else if ((valFrom === '' || isNaN(valFrom)) && (valTo === '' || isNaN(valTo))) { - retVal = true; + return retVal; + } else { + if (columnObj.range_data_type === 'single') { + val = (val !== "") ? (+val) : val; + if (min === "" && max === "") { + retVal = true; + } else if (min === "" && val > max) { + retVal = true; + } else if (min > val && "" === max) { + retVal = true; + } else if (!(min <= val && val <= max) && ("" !== max && "" !== min)) { + retVal = true; + } else if (val === '' || isNaN(val)) { + retVal = true; + } + } else if (columnObj.range_data_type === 'range') { + val = val.split(columnObj.range_data_type_delim); + valFrom = (val[0] !== "") ? (+val[0]) : val[0]; + valTo = (val[1] !== "") ? (+val[1]) : val[1]; + if (min === "" && max === "") { + retVal = true; + } else if (min === "" && valTo > max) { + retVal = true; + } else if (min > valFrom && "" === max) { + retVal = true; + } else if (!(min <= valFrom && valTo <= max) && ("" !== max && "" !== min)) { + retVal = true; + } else if ((valFrom === '' || isNaN(valFrom)) && (valTo === '' || isNaN(valTo))) { + retVal = true; + } } + return retVal; } - return retVal; } ); } @@ -1368,11 +1648,20 @@ if (!Object.entries) { max_time, dataRenderFunc, dpg; - + //"2019/01/30 - 2019/01/30" if (table_selector_jq_friendly_local !== current_table_selector_jq_friendly) { return true; } columnObj = getOptions(settingsDt.oInstance.selector)[col_num]; + if (columnObj.filters_position === 'tfoot' && settingsDt.oScroll.sX) { + let selectorePrefix = '.dataTables_scrollFoot '; + min = document.querySelector(selectorePrefix + '#' + fromId) ? document.querySelector(selectorePrefix + '#' + fromId).value : ''; + max = document.querySelector(selectorePrefix + '#' + toId) ? document.querySelector(selectorePrefix + '#' + toId).value : ''; + } + if (columnObj.datepicker_type === 'daterangepicker') { + min = $.trim(min.substring(0, min.indexOf('-'))); + max = $.trim(max.substring(max.indexOf('-') + 1)); + } if (columnObj.datepicker_type === 'bootstrap-datepicker') { dpg = $.fn.datepicker.DPGlobal; } @@ -1400,18 +1689,18 @@ if (!Object.entries) { } if ($(val).length !== 0) { switch (html_data_type) { - case "text": - val = $(val).text(); - break; - case "value": - val = $(val).val(); - break; - case "id": - val = val.id; - break; - case "selector": - val = $(val).find(columnObj.html_data_selector).text(); - break; + case "text": + val = $(val).text(); + break; + case "value": + val = $(val).val(); + break; + case "id": + val = val.id; + break; + case "selector": + val = $(val).find(columnObj.html_data_selector).text(); + break; } } } else if (typeof val === 'object') { @@ -1419,33 +1708,33 @@ if (!Object.entries) { val = val['@' + columnObj.html5_data]; } } - + //omit empty rows when filtering if (val === '' && (min !== '' || max !== '')) { return false; } try { - if (min.length === (date_format.length + 2) || columnObj.datepicker_type.indexOf('bootstrap') !== -1) { + if (min.length === (date_format.length + 2) || columnObj.datepicker_type.indexOf('bootstrap') !== -1 || columnObj.datepicker_type === 'daterangepicker') { if (columnObj.datepicker_type === 'jquery-ui') { min = (min !== "") ? $.datepicker.parseDate(date_format, min) : min; - } else if (columnObj.datepicker_type === 'bootstrap-datetimepicker') { - min = (min !== "") ? moment(min, columnObj.moment_date_format).toDate() : min; + } else if (columnObj.datepicker_type === 'bootstrap-datetimepicker' || columnObj.datepicker_type === 'daterangepicker') { + min = (min !== "") ? moment(min, columnObj.date_format).toDate() : min; } else if (columnObj.datepicker_type === 'bootstrap-datepicker') { min = (min !== "") ? dpg.parseDate(min, dpg.parseFormat(columnObj.date_format)) : min; } } - } catch (err1) {} + } catch (err1) { } try { - if (max.length === (date_format.length + 2) || columnObj.datepicker_type.indexOf('bootstrap') !== -1) { + if (max.length === (date_format.length + 2) || columnObj.datepicker_type.indexOf('bootstrap') !== -1 || columnObj.datepicker_type === 'daterangepicker') { if (columnObj.datepicker_type === 'jquery-ui') { max = (max !== "") ? $.datepicker.parseDate(date_format, max) : max; - } else if (columnObj.datepicker_type === 'bootstrap-datetimepicker') { - max = (max !== "") ? moment(max, columnObj.moment_date_format).toDate() : max; + } else if (columnObj.datepicker_type === 'bootstrap-datetimepicker' || columnObj.datepicker_type === 'daterangepicker') { + max = (max !== "") ? moment(max, columnObj.date_format).toDate() : max; } else if (columnObj.datepicker_type === 'bootstrap-datepicker') { max = (max !== "") ? dpg.parseDate(max, dpg.parseFormat(columnObj.date_format)) : max; } } - } catch (err2) {} + } catch (err2) { } try { if (columnObj.datepicker_type === 'jquery-ui') { val = (val !== "") ? $.datepicker.parseDate(date_format, val) : val; @@ -1453,8 +1742,10 @@ if (!Object.entries) { val = (val !== "") ? moment(val, columnObj.moment_date_format).toDate() : val; } else if (columnObj.datepicker_type === 'bootstrap-datepicker') { val = (val !== "") ? dpg.parseDate(val, dpg.parseFormat(columnObj.date_format)) : val; + } else if (columnObj.datepicker_type === 'daterangepicker') { + val = (val !== "") ? moment(val, columnObj.date_format).toDate() : val; } - } catch (err3) {} + } catch (err3) { } if (date_format.toLowerCase() !== 'hh:mm') { if ((min === "" || !(min instanceof Date)) && (max === "" || !(max instanceof Date))) { @@ -1495,6 +1786,83 @@ if (!Object.entries) { ); } + function addNullFilterCapability(table_selector_jq_friendly, col_num, isSelect) { + + $.fn.dataTableExt.afnFiltering.push( + function (settingsDt, aData, iDataIndex, rowData) { + var val, + retVal = false, + table_selector_jq_friendly_local = table_selector_jq_friendly, + current_table_selector_jq_friendly = yadcf.generateTableSelectorJQFriendly2(settingsDt), + columnObj, + column_number_filter, + null_checked, + exclude_checked; + + if (table_selector_jq_friendly_local !== current_table_selector_jq_friendly) { + return true; + } + columnObj = getOptions(settingsDt.oInstance.selector)[col_num]; + + column_number_filter = calcColumnNumberFilter(settingsDt, col_num, table_selector_jq_friendly); + + var fixedPrefix = ''; + if (settingsDt._fixedHeader !== undefined && $('.fixedHeader-floating').is(":visible")) { + fixedPrefix = '.fixedHeader-floating '; + } + if (columnObj.filters_position === 'tfoot' && settingsDt.nScrollFoot) { + fixedPrefix = '.' + settingsDt.nScrollFoot.className + ' '; + } + + null_checked = $(fixedPrefix + "#yadcf-filter-wrapper-" + table_selector_jq_friendly + "-" + col_num).find('.yadcf-null-wrapper :checkbox').prop('checked'); + null_checked = isSelect ? ($.trim($("#yadcf-filter-" + table_selector_jq_friendly + "-" + col_num).find('option:selected').val()) === columnObj.select_null_option) : null_checked; + + if (!null_checked) { + return true; + } + if (columnObj.exclude) { + exclude_checked = $(fixedPrefix + "#yadcf-filter-wrapper-" + table_selector_jq_friendly + "-" + col_num).find('.yadcf-exclude-wrapper :checkbox').prop('checked'); + } + if (rowData !== undefined) { + // support dt render fn, usecase structured data when top is null inner property will return undefined + // e.g data = person.cat.name && person.cat = null + let rowDataRender; + if (columnObj.column_number_render) { + rowDataRender = $.extend(true, [], rowData); + const index = columnObj.column_number_data ? columnObj.column_number_data : column_number_filter; + const meta = { + row: iDataIndex, + col: columnObj.column_number, + settings: settingsDt + }; + if (typeof index === 'string' && typeof rowDataRender === 'object') { + const cellDataRender = columnObj.column_number_render(getProp(rowDataRender, index), 'filter', rowData, meta); + setProp(rowDataRender, index, (cellDataRender !== undefined) ? cellDataRender : getProp(rowData, index)); + } else { + const cellDataRender = columnObj.column_number_render(rowDataRender[index], 'filter', rowData, meta); + rowDataRender[index] = (cellDataRender !== undefined) ? cellDataRender : rowData[index]; + } + } + aData = rowDataRender ? rowDataRender : rowData; + if (columnObj.column_number_data !== undefined) { + column_number_filter = columnObj.column_number_data; + val = getProp(aData, column_number_filter); + } else { + val = aData[column_number_filter]; + } + } else { + val = aData[column_number_filter]; + } + if (columnObj.exclude && exclude_checked) { + retVal = val === null ? false : true; + } else { + retVal = val === null ? true : false; + } + return retVal; + } + ); + } + function addRangeNumberFilter(filter_selector_string, table_selector_jq_friendly, column_number, filter_reset_button_text, filter_default_label, ignore_char) { var fromId = "yadcf-filter-" + table_selector_jq_friendly + "-from-" + column_number, toId = "yadcf-filter-" + table_selector_jq_friendly + "-to-" + column_number, @@ -1502,7 +1870,9 @@ if (!Object.entries) { filter_wrapper_id, oTable, columnObj, - filterActionStr; + filterActionFn, + null_str, + exclude_str; filter_wrapper_id = "yadcf-filter-wrapper-" + table_selector_jq_friendly + "-" + column_number; @@ -1514,37 +1884,182 @@ if (!Object.entries) { columnObj = getOptions(oTable.selector)[column_number]; //add a wrapper to hold both filter and reset button - $(filter_selector_string).append("
"); + $(filter_selector_string).append(makeElement("
", { + onmousedown: yadcf.stopPropagation, + onclick: yadcf.stopPropagation, + id: filter_wrapper_id, + class: "yadcf-filter-wrapper " + columnObj.style_class + })); filter_selector_string += " div.yadcf-filter-wrapper"; filter_selector_string_tmp = filter_selector_string; - $(filter_selector_string).append("
"); + + $(filter_selector_string).append(makeElement("
", { + id: "yadcf-filter-wrapper-inner-" + table_selector_jq_friendly + "-" + column_number, + class: "yadcf-filter-wrapper-inner" + " -" + table_selector_jq_friendly + "-" + column_number + })); filter_selector_string += " div.yadcf-filter-wrapper-inner"; - filterActionStr = 'onkeyup="yadcf.rangeNumberKeyUP(\'' + table_selector_jq_friendly + '\',event);"'; + filterActionFn = function(tableSel){ + return function(event){ + yadcf.rangeNumberKeyUP(tableSel, event); + }; + }(table_selector_jq_friendly); if (columnObj.externally_triggered === true) { - filterActionStr = ''; + filterActionFn = function(){}; + } + + $(filter_selector_string).append(makeElement("", { + onkeydown: yadcf.preventDefaultForEnter, + placeholder: filter_default_label[0], + id: fromId, + class: "yadcf-filter-range-number yadcf-filter-range", + onkeyup: filterActionFn + })); + $(filter_selector_string).append(makeElement("", { + class: "yadcf-filter-range-number-seperator" + })); + $(filter_selector_string).append(makeElement("", { + onkeydown: yadcf.preventDefaultForEnter, + placeholder: filter_default_label[1], + id: toId, + class: "yadcf-filter-range-number yadcf-filter-range", + onkeyup: filterActionFn + })); + + if (filter_reset_button_text !== false) { + $(filter_selector_string_tmp).append(makeElement(""); + if (columnObj.checkbox_position_after) { + exclude_str.addClass("after"); + null_str.addClass("after"); + $(filter_selector_string_tmp).append(exclude_str, null_str); + } else { + $(filter_selector_string).before(exclude_str, null_str); + } + // hide on load + if (columnObj.externally_triggered_checkboxes_text && typeof columnObj.externally_triggered_checkboxes_function === 'function') { + const sel = $("#yadcf-filter-wrapper-" + table_selector_jq_friendly + "-" + column_number); + sel.find('.yadcf-exclude-wrapper').hide(); + sel.find('.yadcf-null-wrapper').hide(); } if (oTable.fnSettings().oFeatures.bStateSave === true && oTable.fnSettings().oLoadedState) { if (oTable.fnSettings().oLoadedState.yadcfState && oTable.fnSettings().oLoadedState.yadcfState[table_selector_jq_friendly] && oTable.fnSettings().oLoadedState.yadcfState[table_selector_jq_friendly][column_number]) { - $('#' + fromId).val(oTable.fnSettings().oLoadedState.yadcfState[table_selector_jq_friendly][column_number].from); - if (oTable.fnSettings().oLoadedState.yadcfState[table_selector_jq_friendly][column_number].from !== "") { - $('#' + fromId).addClass("inuse"); + let exclude_checked = false; + let null_checked = false; + if (columnObj.null_check_box) { + null_checked = oTable.fnSettings().oLoadedState.yadcfState[table_selector_jq_friendly][column_number].null_checked; + $('#' + filter_wrapper_id).find('.yadcf-null-wrapper :checkbox').prop('checked', null_checked); + if (columnObj.exclude) { + exclude_checked = oTable.fnSettings().oLoadedState.yadcfState[table_selector_jq_friendly][column_number].exclude_checked; + $('#' + filter_wrapper_id).find('.yadcf-exclude-wrapper :checkbox').prop('checked', exclude_checked); + } } - $('#' + toId).val(oTable.fnSettings().oLoadedState.yadcfState[table_selector_jq_friendly][column_number].to); - if (oTable.fnSettings().oLoadedState.yadcfState[table_selector_jq_friendly][column_number].to !== "") { - $('#' + toId).addClass("inuse"); + + if (null_checked) { + $('#' + fromId).prop('disabled', true); + $('#' + toId).prop('disabled', true); + } else { + const inuseClass = exclude_checked ? ' inuse inuse-exclude' : ' inuse '; + if (oTable.fnSettings().oLoadedState.yadcfState[table_selector_jq_friendly][column_number].from) { + $('#' + fromId).val(oTable.fnSettings().oLoadedState.yadcfState[table_selector_jq_friendly][column_number].from); + if (oTable.fnSettings().oLoadedState.yadcfState[table_selector_jq_friendly][column_number].from !== "") { + $('#' + fromId).addClass(inuseClass); + } + } + if (oTable.fnSettings().oLoadedState.yadcfState[table_selector_jq_friendly][column_number].to) { + $('#' + toId).val(oTable.fnSettings().oLoadedState.yadcfState[table_selector_jq_friendly][column_number].to); + if (oTable.fnSettings().oLoadedState.yadcfState[table_selector_jq_friendly][column_number].to !== "") { + $('#' + toId).addClass(inuseClass); + } + } } } } @@ -1553,7 +2068,6 @@ if (!Object.entries) { if (oTable.fnSettings().oFeatures.bServerSide !== true) { addRangeNumberAndSliderFilterCapability(table_selector_jq_friendly, fromId, toId, column_number, ignore_char); } - } function dateSelectSingle(pDate, pEvent, clear) { @@ -1565,15 +2079,22 @@ if (!Object.entries) { table_selector_jq_friendly, column_number_filter, settingsDt, - columnObj; - - if (pDate.type === 'dp') { - event = pDate.target; - } else if (pDate.type === 'changeDate') { - event = pDate.currentTarget; - } else { - date = pDate; - event = pEvent; + columnObj, + yadcfState; + + if (pDate) { + if (pDate.type === 'dp') { + event = pDate.target; + } else if (pDate.type === 'changeDate') { + event = pDate.currentTarget; + } else if ($(clear).length === 1) { // dt-datetime + date = pDate; + event = clear; + clear = undefined; + } else { + date = pDate; + event = pEvent; + } } column_number = $(event).attr('id').replace('yadcf-filter-', '').replace('-date', '').replace('-reset', ''); @@ -1592,7 +2113,7 @@ if (!Object.entries) { } else { clear = 'clear'; } - $(event).blur(); + $(event).trigger('blur'); } else if (columnObj.datepicker_type === 'bootstrap-datepicker') { if (pDate.dates) { date = pDate.format(0, columnObj.date_format); @@ -1622,9 +2143,9 @@ if (!Object.entries) { if (oTable.fnSettings().oFeatures.bStateSave === true) { if (oTable.fnSettings().oLoadedState.yadcfState !== undefined && oTable.fnSettings().oLoadedState.yadcfState[table_selector_jq_friendly] !== undefined) { oTable.fnSettings().oLoadedState.yadcfState[table_selector_jq_friendly][column_number] = - { - from: "" - }; + { + from: "" + }; } else { yadcfState = {}; yadcfState[table_selector_jq_friendly] = []; @@ -1637,7 +2158,16 @@ if (!Object.entries) { } } } - oTable.fnFilter('', column_number_filter); + if (columnObj.datepicker_type === 'daterangepicker' && oTable.fnSettings().oFeatures.bServerSide !== true) { + rangeClear(table_selector_jq_friendly, event, column_number); + } else { + if (columnObj.filter_type !== 'date_custom_func') { + oTable.fnFilter('', column_number_filter); + } else { + $('#yadcf-filter-' + table_selector_jq_friendly + '-' + column_number).val(''); + doFilterCustomDateFunc({ value: date }, table_selector_jq_friendly, column_number); + } + } $('#yadcf-filter-' + table_selector_jq_friendly + '-' + column_number).val('').removeClass("inuse"); if (columnObj.datepicker_type === 'bootstrap-datepicker') { $('#yadcf-filter-' + table_selector_jq_friendly + '-' + column_number).datepicker('update'); @@ -1658,9 +2188,10 @@ if (!Object.entries) { event, columnObj, column_number_filter, - settingsDt; + settingsDt, + keyUp; - if (pDate.type === 'dp') { + if (pDate.type === 'dp' || pDate.namespace === 'daterangepicker') { event = pDate.target; } else if (pDate.type === 'changeDate') { event = pDate.currentTarget; @@ -1691,7 +2222,7 @@ if (!Object.entries) { } else { $(event).addClass("inuse"); } - $(event).blur(); + $(event).trigger('blur'); } else if (pDate.type === 'changeDate') { if (pDate.date !== undefined) { $(event).addClass("inuse"); @@ -1701,45 +2232,60 @@ if (!Object.entries) { } else { $(event).addClass("inuse"); } - - if ($(event).attr("id").indexOf("-from-") !== -1) { - from = document.getElementById($(event).attr("id")).value; - to = document.getElementById($(event).attr("id").replace("-from-", "-to-")).value; + if (pDate.namespace === 'daterangepicker') { + from = moment(pEvent.startDate).format(columnObj.date_format); + to = moment(pEvent.endDate).format(columnObj.date_format); } else { - to = document.getElementById($(event).attr("id")).value; - from = document.getElementById($(event).attr("id").replace("-to-", "-from-")).value; + if ($(event).attr("id").indexOf("-from-") !== -1) { + from = document.getElementById($(event).attr("id")).value; + to = document.getElementById($(event).attr("id").replace("-from-", "-to-")).value; + } else { + to = document.getElementById($(event).attr("id")).value; + from = document.getElementById($(event).attr("id").replace("-to-", "-from-")).value; + } } - if (oTable.fnSettings().oFeatures.bServerSide !== true) { - oTable.fnDraw(); - } else { - oTable.fnFilter(from + '-yadcf_delim-' + to, column_number_filter); - } + keyUp = function () { + if (oTable.fnSettings().oFeatures.bServerSide !== true) { + oTable.fnDraw(); + } else { + oTable.fnFilter(from + columnObj.custom_range_delimiter + to, column_number_filter); + } - if (!oTable.fnSettings().oLoadedState) { - oTable.fnSettings().oLoadedState = {}; - oTable.fnSettings().oApi._fnSaveState(oTable.fnSettings()); - } - if (oTable.fnSettings().oFeatures.bStateSave === true) { - if (oTable.fnSettings().oLoadedState.yadcfState !== undefined && oTable.fnSettings().oLoadedState.yadcfState[table_selector_jq_friendly] !== undefined) { - oTable.fnSettings().oLoadedState.yadcfState[table_selector_jq_friendly][column_number] = + if (!oTable.fnSettings().oLoadedState) { + oTable.fnSettings().oLoadedState = {}; + oTable.fnSettings().oApi._fnSaveState(oTable.fnSettings()); + } + if (oTable.fnSettings().oFeatures.bStateSave === true) { + if (oTable.fnSettings().oLoadedState.yadcfState !== undefined && oTable.fnSettings().oLoadedState.yadcfState[table_selector_jq_friendly] !== undefined) { + oTable.fnSettings().oLoadedState.yadcfState[table_selector_jq_friendly][column_number] = { from: from, to: to }; - } else { - yadcfState = {}; - yadcfState[table_selector_jq_friendly] = []; - yadcfState[table_selector_jq_friendly][column_number] = { - from: from, - to: to - }; - oTable.fnSettings().oLoadedState.yadcfState = yadcfState; + } else { + yadcfState = {}; + yadcfState[table_selector_jq_friendly] = []; + yadcfState[table_selector_jq_friendly][column_number] = { + from: from, + to: to + }; + oTable.fnSettings().oLoadedState.yadcfState = yadcfState; + } + oTable.fnSettings().oApi._fnSaveState(oTable.fnSettings()); } - oTable.fnSettings().oApi._fnSaveState(oTable.fnSettings()); + if (from !== '' || to !== '') { + $('#' + event.id).addClass("inuse"); + } + resetIApiIndex(); + }; + if (columnObj.filter_delay === undefined) { + keyUp(); + } else { + yadcfDelay(function () { + keyUp(); + }, columnObj.filter_delay); } - - resetIApiIndex(); } function addRangeDateFilter(filter_selector_string, table_selector_jq_friendly, column_number, filter_reset_button_text, filter_default_label, date_format) { @@ -1750,7 +2296,7 @@ if (!Object.entries) { oTable, columnObj, datepickerObj = {}, - filterActionStr, + filterActionFn, $fromInput, $toInput, innerWrapperAdditionalClass = ''; @@ -1767,28 +2313,65 @@ if (!Object.entries) { innerWrapperAdditionalClass = 'input-daterange'; } //add a wrapper to hold both filter and reset button - $(filter_selector_string).append("
"); + $(filter_selector_string).append(makeElement("
", { + onmousedown: yadcf.stopPropagation, + onclick: yadcf.stopPropagation, + id: filter_wrapper_id, + class: "yadcf-filter-wrapper" + })); filter_selector_string += " div.yadcf-filter-wrapper"; filter_selector_string_tmp = filter_selector_string; - $(filter_selector_string).append("
"); + $(filter_selector_string).append(makeElement("
", { + id: "yadcf-filter-wrapper-inner-" + table_selector_jq_friendly + "-" + column_number, + class: "yadcf-filter-wrapper-inner " + innerWrapperAdditionalClass + })); filter_selector_string += " div.yadcf-filter-wrapper-inner"; - filterActionStr = 'onkeyup="yadcf.rangeDateKeyUP(\'' + table_selector_jq_friendly + '\',\'' + date_format + '\',event);"'; + filterActionFn = function(tableSel){ + return function(event){ + yadcf.rangeDateKeyUP(tableSel, date_format, event); + }; + }(table_selector_jq_friendly); if (columnObj.externally_triggered === true) { - filterActionStr = ''; - } - - $(filter_selector_string).append(""); - $(filter_selector_string).append("" + ""); - $(filter_selector_string).append(""); + filterActionFn = function(){}; + } + + $(filter_selector_string).append(makeElement("", { + onkeydown: yadcf.preventDefaultForEnter, + placeholder: filter_default_label[0], + id: fromId, + class: "yadcf-filter-range-date yadcf-filter-range yadcf-filter-range-start " + columnObj.style_class, + onkeyup: filterActionFn + })); + $(filter_selector_string).append(makeElement("", { + class: "yadcf-filter-range-date-seperator" + })); + $(filter_selector_string).append(makeElement("", { + onkeydown: yadcf.preventDefaultForEnter, + placeholder: filter_default_label[1], + id: toId, + class: "yadcf-filter-range-date yadcf-filter-range yadcf-filter-range-end " + columnObj.style_class, + onkeyup: filterActionFn + })); $fromInput = $("#" + fromId); $toInput = $("#" + toId); if (filter_reset_button_text !== false) { - $(filter_selector_string_tmp).append(""); + $(filter_selector_string_tmp).append(makeElement("'); + $(filter_selector_string_tmp).append(makeElement(""); + $(filter_selector_string_tmp).append(makeElement(""); + $(filter_selector_string).find(".yadcf-filter").after(makeElement(""); + regex_str = $(); + if (columnObj.regex_check_box === true) { + if (columnObj.externally_triggered !== true) { + regex_str = makeElement("", { + class: "yadcf-regex-wrapper", + onmousedown: yadcf.stopPropagation, + onclick: yadcf.stopPropagation + }).append(makeElement("
", { + class: "yadcf-label small", + text: columnObj.regex_label + })).append(makeElement("", { + type: "checkbox", + title: columnObj.regex_label, + onclick: function(colNo, tableSel){ + return function(event){ + yadcf.stopPropagation(event); + yadcf.textKeyUP(event, tableSel, colNo); + }; + }(column_number, table_selector_jq_friendly) + })); + } else { + regex_str = makeElement("", { + class: "yadcf-regex-wrapper", + onmousedown: yadcf.stopPropagation, + onclick: yadcf.stopPropagation + }).append(makeElement("
", { + class: "yadcf-label small", + text: columnObj.regex_label + })).append(makeElement("", { + type: "checkbox", + title: columnObj.regex_label, + onclick: yadcf.stopPropagation + })); + } } - if (settingsDt.aoPreSearchCols[column_position].sSearch !== '') { - tmpStr = settingsDt.aoPreSearchCols[column_position].sSearch; - if (columnObj.exclude === true) { - if (tmpStr.indexOf('^((?!') !== -1) { - $('#yadcf-filter-wrapper-' + table_selector_jq_friendly + '-' + column_number).find(':checkbox').prop('checked', true); - } - tmpStr = tmpStr.substring(5, tmpStr.indexOf(').)')); + null_str = $(); + if (columnObj.null_check_box === true) { + null_str = makeElement("", { + class: "yadcf-null-wrapper", + onmousedown: yadcf.stopPropagation, + onclick: yadcf.stopPropagation + }).append(makeElement("
", { + class: "yadcf-label small", + text: columnObj.null_label + })).append(makeElement("", { + type: "checkbox", + title: columnObj.null_label, + onclick: function(colNo, tableSel){ + return function(event){ + yadcf.stopPropagation(event); + yadcf.nullChecked(event, tableSel, colNo); + }; + }(column_number, table_selector_jq_friendly) + })); + if (oTable.fnSettings().oFeatures.bServerSide !== true) { + addNullFilterCapability(table_selector_jq_friendly, column_number, false); } - tmpStr = yadcfParseMatchFilter(tmpStr, getOptions(oTable.selector)[column_number].filter_match_mode); - $('#yadcf-filter-' + table_selector_jq_friendly + '-' + column_number).val(tmpStr).addClass("inuse"); } + let append_input = makeElement("", { + type: "text", + onkeydown: yadcf.preventDefaultForEnter, + id: "yadcf-filter-" + table_selector_jq_friendly + "-" + column_number, + class: "yadcf-filter " + columnObj.style_class, + onmousedown: yadcf.stopPropagation, + onclick: yadcf.stopPropagation, + placeholder: filter_default_label, + filter_match_mode: filter_match_mode, + onkeyup: filterActionFn + }); + + if (columnObj.checkbox_position_after) { + exclude_str.addClass("after"); + regex_str.addClass("after"); + null_str.addClass("after"); + $(filter_selector_string).append(append_input, exclude_str, regex_str, null_str); + } else { + $(filter_selector_string).append(exclude_str, regex_str, null_str, append_input); + } + + if (externally_triggered_checkboxes_text && typeof externally_triggered_checkboxes_function === 'function') { + const sel = $("#yadcf-filter-wrapper-" + table_selector_jq_friendly + "-" + column_number); + // hide on load + sel.find('.yadcf-exclude-wrapper').hide(); + sel.find('.yadcf-regex-wrapper').hide(); + sel.find('.yadcf-null-wrapper').hide(); + $(filter_selector_string).find(".yadcf-filter").after(makeElement(""); - } - if (tablesArray[0].table !== undefined) { - tableTmp = $('#' + tablesArray[0].table().node().id).dataTable(); - } else { - tableTmp = tablesArray[0]; - } - settingsDt = getSettingsObjFromTable(tableTmp); - if (settingsDt.aoPreSearchCols[columnForStateSaving].sSearch !== '') { - tmpStr = settingsDt.aoPreSearchCols[columnForStateSaving].sSearch; - tmpStr = yadcfParseMatchFilter(tmpStr, filterOptions.filter_match_mode); - $('#yadcf-filter-' + table_selector_jq_friendly + '-' + column_number_str).val(tmpStr).addClass("inuse"); - } - break; - case 'select': - case 'multi_select': - if (filterOptions.select_type === undefined) { - options_tmp = ""; - } else { - options_tmp = ""; - } - if (filterOptions.select_type === 'select2' && filterOptions.select_type_options.placeholder !== undefined && filterOptions.select_type_options.allowClear === true) { - options_tmp = ""; - } - if (filterOptions.data === undefined) { - filterOptions.data = []; - tableTmpArr = tablesSelectors.split(','); - for (tableTmpArrIndex = 0; tableTmpArrIndex < tableTmpArr.length; tableTmpArrIndex++) { - if (tablesArray[tableTmpArrIndex].table !== undefined) { - tableTmp = $('#' + tablesArray[tableTmpArrIndex].table().node().id).dataTable(); - } else { - tableTmp = tablesArray[tableTmpArrIndex]; - } - if (isDOMSource(tableTmp)) { - //check if ajax source, if so, listen for dt.draw - columnsTmpArr = filterOptions.column_number; - for (column_number_index = 0; column_number_index < columnsTmpArr.length; column_number_index++) { - filterOptions.column_number = columnsTmpArr[column_number_index]; - filterOptions.data = filterOptions.data.concat(parseTableColumn(tableTmp, filterOptions, table_selector_jq_friendly)); + case 'text': + $(filter_selector_string).append(makeElement("", { + type: "text", + id: "yadcf-filter-" + table_selector_jq_friendly + '-' + column_number_str, + class: "yadcf-filter", + onmousedown: yadcf.stopPropagation, + onclick: yadcf.stopPropagation, + placeholder: filterOptions.filter_default_label, + onkeyup: function(colNo){ + return function(event){ + yadcf.stopPropagation(event); + yadcf.textKeyUpMultiTables(tablesSelectors, event, colNo); + return false; + }; + }(column_number_str), + })); + if (filterOptions.filter_reset_button_text !== false) { + $(filter_selector_string).find(".yadcf-filter").after(makeElement(""); + if (filterOptions.filter_type === 'select') { + $(filter_selector_string).append(makeElement("", { + multiple: true, + "data-placeholder": filterOptions.filter_default_label, + id: "yadcf-filter-" + table_selector_jq_friendly + '-' + column_number_str, + class: "yadcf-filter", + onchange: function(colNo){ + return function(event){ + yadcf.stopPropagation(event); + yadcf.doFilterMultiTablesMultiSelect(tablesSelectors, event, colNo); + }; + }(column_number_str), + onmousedown: yadcf.stopPropagation, + onclick: yadcf.stopPropagation, + html: options_tmp + })); + if (settingsDt.aoPreSearchCols[columnForStateSaving].sSearch !== '') { + tmpStr = settingsDt.aoPreSearchCols[columnForStateSaving].sSearch; + tmpStr = yadcfParseMatchFilterMultiSelect(tmpStr, filterOptions.filter_match_mode); + tmpStr = tmpStr.replace(/\\/g, ""); + tmpStr = tmpStr.split("|"); + $('#yadcf-filter-' + table_selector_jq_friendly + '-' + column_number_str).val(tmpStr); + } } - } else if (filterOptions.filter_type === 'multi_select') { - if (filterOptions.filter_reset_button_text !== false) { - $(filter_selector_string).find(".yadcf-filter").after(""); + if (filterOptions.filter_type === 'select') { + if (filterOptions.filter_reset_button_text !== false) { + $(filter_selector_string).find(".yadcf-filter").after(makeElement("