bootstrap-table-filter-control.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  1. /**
  2. * @author: Dennis Hernández
  3. * @webSite: http://djhvscf.github.io/Blog
  4. * @version: v2.1.1
  5. */
  6. (function ($) {
  7. 'use strict';
  8. var sprintf = $.fn.bootstrapTable.utils.sprintf,
  9. objectKeys = $.fn.bootstrapTable.utils.objectKeys;
  10. var getOptionsFromSelectControl = function (selectControl) {
  11. return selectControl.get(selectControl.length - 1).options;
  12. };
  13. var hideUnusedSelectOptions = function (selectControl, uniqueValues) {
  14. var options = getOptionsFromSelectControl(selectControl);
  15. for (var i = 0; i < options.length; i++) {
  16. if (options[i].value !== "") {
  17. if (!uniqueValues.hasOwnProperty(options[i].value)) {
  18. selectControl.find(sprintf("option[value='%s']", options[i].value)).hide();
  19. } else {
  20. selectControl.find(sprintf("option[value='%s']", options[i].value)).show();
  21. }
  22. }
  23. }
  24. };
  25. var addOptionToSelectControl = function (selectControl, value, text) {
  26. value = $.trim(value);
  27. selectControl = $(selectControl.get(selectControl.length - 1));
  28. if (!existOptionInSelectControl(selectControl, value)) {
  29. selectControl.append($("<option></option>")
  30. .attr("value", value)
  31. .text($('<div />').html(text).text()));
  32. }
  33. };
  34. var sortSelectControl = function (selectControl) {
  35. var $opts = selectControl.find('option:gt(0)');
  36. $opts.sort(function (a, b) {
  37. a = $(a).text().toLowerCase();
  38. b = $(b).text().toLowerCase();
  39. if ($.isNumeric(a) && $.isNumeric(b)) {
  40. // Convert numerical values from string to float.
  41. a = parseFloat(a);
  42. b = parseFloat(b);
  43. }
  44. return a > b ? 1 : a < b ? -1 : 0;
  45. });
  46. selectControl.find('option:gt(0)').remove();
  47. selectControl.append($opts);
  48. };
  49. var existOptionInSelectControl = function (selectControl, value) {
  50. var options = getOptionsFromSelectControl(selectControl);
  51. for (var i = 0; i < options.length; i++) {
  52. if (options[i].value === value.toString()) {
  53. //The value is not valid to add
  54. return true;
  55. }
  56. }
  57. //If we get here, the value is valid to add
  58. return false;
  59. };
  60. var fixHeaderCSS = function (that) {
  61. that.$tableHeader.css('height', '77px');
  62. };
  63. var getCurrentHeader = function (that) {
  64. var header = that.$header;
  65. if (that.options.height) {
  66. header = that.$tableHeader;
  67. }
  68. return header;
  69. };
  70. var getCurrentSearchControls = function (that) {
  71. var searchControls = 'select, input';
  72. if (that.options.height) {
  73. searchControls = 'table select, table input';
  74. }
  75. return searchControls;
  76. };
  77. var getCursorPosition = function(el) {
  78. if ($.fn.bootstrapTable.utils.isIEBrowser()) {
  79. if ($(el).is('input')) {
  80. var pos = 0;
  81. if ('selectionStart' in el) {
  82. pos = el.selectionStart;
  83. } else if ('selection' in document) {
  84. el.focus();
  85. var Sel = document.selection.createRange();
  86. var SelLength = document.selection.createRange().text.length;
  87. Sel.moveStart('character', -el.value.length);
  88. pos = Sel.text.length - SelLength;
  89. }
  90. return pos;
  91. } else {
  92. return -1;
  93. }
  94. } else {
  95. return -1;
  96. }
  97. };
  98. var setCursorPosition = function (el, index) {
  99. if ($.fn.bootstrapTable.utils.isIEBrowser()) {
  100. if(el.setSelectionRange !== undefined) {
  101. el.setSelectionRange(index, index);
  102. } else {
  103. $(el).val(el.value);
  104. }
  105. }
  106. };
  107. var copyValues = function (that) {
  108. var header = getCurrentHeader(that),
  109. searchControls = getCurrentSearchControls(that);
  110. that.options.valuesFilterControl = [];
  111. header.find(searchControls).each(function () {
  112. that.options.valuesFilterControl.push(
  113. {
  114. field: $(this).closest('[data-field]').data('field'),
  115. value: $(this).val(),
  116. position: getCursorPosition($(this).get(0))
  117. });
  118. });
  119. };
  120. var setValues = function(that) {
  121. var field = null,
  122. result = [],
  123. header = getCurrentHeader(that),
  124. searchControls = getCurrentSearchControls(that);
  125. if (that.options.valuesFilterControl.length > 0) {
  126. header.find(searchControls).each(function (index, ele) {
  127. field = $(this).closest('[data-field]').data('field');
  128. result = $.grep(that.options.valuesFilterControl, function (valueObj) {
  129. return valueObj.field === field;
  130. });
  131. if (result.length > 0) {
  132. $(this).val(result[0].value);
  133. setCursorPosition($(this).get(0), result[0].position);
  134. }
  135. });
  136. }
  137. };
  138. var collectBootstrapCookies = function cookiesRegex() {
  139. var cookies = [],
  140. foundCookies = document.cookie.match(/(?:bs.table.)(\w*)/g);
  141. if (foundCookies) {
  142. $.each(foundCookies, function (i, cookie) {
  143. if (/./.test(cookie)) {
  144. cookie = cookie.split(".").pop();
  145. }
  146. if ($.inArray(cookie, cookies) === -1) {
  147. cookies.push(cookie);
  148. }
  149. });
  150. return cookies;
  151. }
  152. };
  153. var initFilterSelectControls = function (that) {
  154. var data = that.data,
  155. itemsPerPage = that.pageTo < that.options.data.length ? that.options.data.length : that.pageTo,
  156. isColumnSearchableViaSelect = function (column) {
  157. return column.filterControl && column.filterControl.toLowerCase() === 'select' && column.searchable;
  158. },
  159. isFilterDataNotGiven = function (column) {
  160. return column.filterData === undefined || column.filterData.toLowerCase() === 'column';
  161. },
  162. hasSelectControlElement = function (selectControl) {
  163. return selectControl && selectControl.length > 0;
  164. };
  165. var z = that.options.pagination ?
  166. (that.options.sidePagination === 'server' ? that.pageTo : that.options.totalRows) :
  167. that.pageTo;
  168. $.each(that.header.fields, function (j, field) {
  169. var column = that.columns[$.fn.bootstrapTable.utils.getFieldIndex(that.columns, field)],
  170. selectControl = $('.bootstrap-table-filter-control-' + escapeID(column.field));
  171. if (isColumnSearchableViaSelect(column) && isFilterDataNotGiven(column) && hasSelectControlElement(selectControl)) {
  172. if (selectControl.get(selectControl.length - 1).options.length === 0) {
  173. //Added the default option
  174. addOptionToSelectControl(selectControl, '', '');
  175. }
  176. var uniqueValues = {};
  177. for (var i = 0; i < z; i++) {
  178. //Added a new value
  179. var fieldValue = data[i][field],
  180. formattedValue = $.fn.bootstrapTable.utils.calculateObjectValue(that.header, that.header.formatters[j], [fieldValue, data[i], i], fieldValue);
  181. uniqueValues[formattedValue] = fieldValue;
  182. }
  183. for (var key in uniqueValues) {
  184. addOptionToSelectControl(selectControl, uniqueValues[key], key);
  185. }
  186. sortSelectControl(selectControl);
  187. if (that.options.hideUnusedSelectOptions) {
  188. hideUnusedSelectOptions(selectControl, uniqueValues);
  189. }
  190. }
  191. });
  192. };
  193. var escapeID = function(id) {
  194. return String(id).replace( /(:|\.|\[|\]|,)/g, "\\$1" );
  195. };
  196. var createControls = function (that, header) {
  197. var addedFilterControl = false,
  198. isVisible,
  199. html,
  200. timeoutId = 0;
  201. $.each(that.columns, function (i, column) {
  202. isVisible = 'hidden';
  203. html = [];
  204. if (!column.visible) {
  205. return;
  206. }
  207. if (!column.filterControl) {
  208. html.push('<div class="no-filter-control"></div>');
  209. } else {
  210. html.push('<div class="filter-control">');
  211. var nameControl = column.filterControl.toLowerCase();
  212. if (column.searchable && that.options.filterTemplate[nameControl]) {
  213. addedFilterControl = true;
  214. isVisible = 'visible';
  215. html.push(that.options.filterTemplate[nameControl](that, column.field, isVisible, column.filterControlPlaceholder));
  216. }
  217. }
  218. $.each(header.children().children(), function (i, tr) {
  219. tr = $(tr);
  220. if (tr.data('field') === column.field) {
  221. tr.find('.fht-cell').append(html.join(''));
  222. return false;
  223. }
  224. });
  225. if (column.filterData !== undefined && column.filterData.toLowerCase() !== 'column') {
  226. var filterDataType = getFilterDataMethod(filterDataMethods, column.filterData.substring(0, column.filterData.indexOf(':')));
  227. var filterDataSource, selectControl;
  228. if (filterDataType !== null) {
  229. filterDataSource = column.filterData.substring(column.filterData.indexOf(':') + 1, column.filterData.length);
  230. selectControl = $('.bootstrap-table-filter-control-' + escapeID(column.field));
  231. addOptionToSelectControl(selectControl, '', '');
  232. filterDataType(filterDataSource, selectControl);
  233. } else {
  234. throw new SyntaxError('Error. You should use any of these allowed filter data methods: var, json, url.' + ' Use like this: var: {key: "value"}');
  235. }
  236. var variableValues, key;
  237. switch (filterDataType) {
  238. case 'url':
  239. $.ajax({
  240. url: filterDataSource,
  241. dataType: 'json',
  242. success: function (data) {
  243. for (var key in data) {
  244. addOptionToSelectControl(selectControl, key, data[key]);
  245. }
  246. sortSelectControl(selectControl);
  247. }
  248. });
  249. break;
  250. case 'var':
  251. variableValues = window[filterDataSource];
  252. for (key in variableValues) {
  253. addOptionToSelectControl(selectControl, key, variableValues[key]);
  254. }
  255. sortSelectControl(selectControl);
  256. break;
  257. case 'jso':
  258. variableValues = JSON.parse(filterDataSource);
  259. for (key in variableValues) {
  260. addOptionToSelectControl(selectControl, key, variableValues[key]);
  261. }
  262. sortSelectControl(selectControl);
  263. break;
  264. }
  265. }
  266. });
  267. if (addedFilterControl) {
  268. header.off('keyup', 'input').on('keyup', 'input', function (event) {
  269. clearTimeout(timeoutId);
  270. timeoutId = setTimeout(function () {
  271. that.onColumnSearch(event);
  272. }, that.options.searchTimeOut);
  273. });
  274. header.off('change', 'select').on('change', 'select', function (event) {
  275. clearTimeout(timeoutId);
  276. timeoutId = setTimeout(function () {
  277. that.onColumnSearch(event);
  278. }, that.options.searchTimeOut);
  279. });
  280. header.off('mouseup', 'input').on('mouseup', 'input', function (event) {
  281. var $input = $(this),
  282. oldValue = $input.val();
  283. if (oldValue === "") {
  284. return;
  285. }
  286. setTimeout(function(){
  287. var newValue = $input.val();
  288. if (newValue === "") {
  289. clearTimeout(timeoutId);
  290. timeoutId = setTimeout(function () {
  291. that.onColumnSearch(event);
  292. }, that.options.searchTimeOut);
  293. }
  294. }, 1);
  295. });
  296. if (header.find('.date-filter-control').length > 0) {
  297. $.each(that.columns, function (i, column) {
  298. if (column.filterControl !== undefined && column.filterControl.toLowerCase() === 'datepicker') {
  299. header.find('.date-filter-control.bootstrap-table-filter-control-' + column.field).datepicker(column.filterDatepickerOptions)
  300. .on('changeDate', function (e) {
  301. $(sprintf(".%s", e.currentTarget.classList.toString().split(" ").join("."))).val(e.currentTarget.value);
  302. //Fired the keyup event
  303. $(e.currentTarget).keyup();
  304. });
  305. }
  306. });
  307. }
  308. } else {
  309. header.find('.filterControl').hide();
  310. }
  311. };
  312. var getDirectionOfSelectOptions = function (alignment) {
  313. alignment = alignment === undefined ? 'left' : alignment.toLowerCase();
  314. switch (alignment) {
  315. case 'left':
  316. return 'ltr';
  317. case 'right':
  318. return 'rtl';
  319. case 'auto':
  320. return 'auto';
  321. default:
  322. return 'ltr';
  323. }
  324. };
  325. var filterDataMethods =
  326. {
  327. 'var': function (filterDataSource, selectControl) {
  328. var variableValues = window[filterDataSource];
  329. for (var key in variableValues) {
  330. addOptionToSelectControl(selectControl, key, variableValues[key]);
  331. }
  332. sortSelectControl(selectControl);
  333. },
  334. 'url': function (filterDataSource, selectControl) {
  335. $.ajax({
  336. url: filterDataSource,
  337. dataType: 'json',
  338. success: function (data) {
  339. for (var key in data) {
  340. addOptionToSelectControl(selectControl, key, data[key]);
  341. }
  342. sortSelectControl(selectControl);
  343. }
  344. });
  345. },
  346. 'json':function (filterDataSource, selectControl) {
  347. var variableValues = JSON.parse(filterDataSource);
  348. for (var key in variableValues) {
  349. addOptionToSelectControl(selectControl, key, variableValues[key]);
  350. }
  351. sortSelectControl(selectControl);
  352. }
  353. };
  354. var getFilterDataMethod = function (objFilterDataMethod, searchTerm) {
  355. var keys = Object.keys(objFilterDataMethod);
  356. for (var i = 0; i < keys.length; i++) {
  357. if (keys[i] === searchTerm) {
  358. return objFilterDataMethod[searchTerm];
  359. }
  360. }
  361. return null;
  362. };
  363. $.extend($.fn.bootstrapTable.defaults, {
  364. filterControl: false,
  365. onColumnSearch: function (field, text) {
  366. return false;
  367. },
  368. filterShowClear: false,
  369. alignmentSelectControlOptions: undefined,
  370. filterTemplate: {
  371. input: function (that, field, isVisible, placeholder) {
  372. return sprintf('<input type="text" class="form-control bootstrap-table-filter-control-%s" style="width: 100%; visibility: %s" placeholder="%s">', field, isVisible, placeholder);
  373. },
  374. select: function (that, field, isVisible) {
  375. return sprintf('<select class="form-control bootstrap-table-filter-control-%s" style="width: 100%; visibility: %s" dir="%s"></select>',
  376. field, isVisible, getDirectionOfSelectOptions(that.options.alignmentSelectControlOptions));
  377. },
  378. datepicker: function (that, field, isVisible) {
  379. return sprintf('<input type="text" class="form-control date-filter-control bootstrap-table-filter-control-%s" style="width: 100%; visibility: %s">', field, isVisible);
  380. }
  381. },
  382. //internal variables
  383. valuesFilterControl: []
  384. });
  385. $.extend($.fn.bootstrapTable.COLUMN_DEFAULTS, {
  386. filterControl: undefined,
  387. filterData: undefined,
  388. filterDatepickerOptions: undefined,
  389. filterStrictSearch: false,
  390. filterStartsWithSearch: false,
  391. filterControlPlaceholder: ""
  392. });
  393. $.extend($.fn.bootstrapTable.Constructor.EVENTS, {
  394. 'column-search.bs.table': 'onColumnSearch'
  395. });
  396. $.extend($.fn.bootstrapTable.defaults.icons, {
  397. clear: 'glyphicon-trash icon-clear'
  398. });
  399. $.extend($.fn.bootstrapTable.locales, {
  400. formatClearFilters: function () {
  401. return 'Clear Filters';
  402. }
  403. });
  404. $.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales);
  405. var BootstrapTable = $.fn.bootstrapTable.Constructor,
  406. _init = BootstrapTable.prototype.init,
  407. _initToolbar = BootstrapTable.prototype.initToolbar,
  408. _initHeader = BootstrapTable.prototype.initHeader,
  409. _initBody = BootstrapTable.prototype.initBody,
  410. _initSearch = BootstrapTable.prototype.initSearch;
  411. BootstrapTable.prototype.init = function () {
  412. //Make sure that the filterControl option is set
  413. if (this.options.filterControl) {
  414. var that = this;
  415. // Compatibility: IE < 9 and old browsers
  416. if (!Object.keys) {
  417. objectKeys();
  418. }
  419. //Make sure that the internal variables are set correctly
  420. this.options.valuesFilterControl = [];
  421. this.$el.on('reset-view.bs.table', function () {
  422. //Create controls on $tableHeader if the height is set
  423. if (!that.options.height) {
  424. return;
  425. }
  426. //Avoid recreate the controls
  427. if (that.$tableHeader.find('select').length > 0 || that.$tableHeader.find('input').length > 0) {
  428. return;
  429. }
  430. createControls(that, that.$tableHeader);
  431. }).on('post-header.bs.table', function () {
  432. setValues(that);
  433. }).on('post-body.bs.table', function () {
  434. if (that.options.height) {
  435. fixHeaderCSS(that);
  436. }
  437. }).on('column-switch.bs.table', function() {
  438. setValues(that);
  439. });
  440. }
  441. _init.apply(this, Array.prototype.slice.apply(arguments));
  442. };
  443. BootstrapTable.prototype.initToolbar = function () {
  444. this.showToolbar = this.options.filterControl && this.options.filterShowClear;
  445. _initToolbar.apply(this, Array.prototype.slice.apply(arguments));
  446. if (this.options.filterControl && this.options.filterShowClear) {
  447. var $btnGroup = this.$toolbar.find('>.btn-group'),
  448. $btnClear = $btnGroup.find('.filter-show-clear');
  449. if (!$btnClear.length) {
  450. $btnClear = $([
  451. '<button class="btn btn-default filter-show-clear" ',
  452. sprintf('type="button" title="%s">', this.options.formatClearFilters()),
  453. sprintf('<i class="%s %s"></i> ', this.options.iconsPrefix, this.options.icons.clear),
  454. '</button>'
  455. ].join('')).appendTo($btnGroup);
  456. $btnClear.off('click').on('click', $.proxy(this.clearFilterControl, this));
  457. }
  458. }
  459. };
  460. BootstrapTable.prototype.initHeader = function () {
  461. _initHeader.apply(this, Array.prototype.slice.apply(arguments));
  462. if (!this.options.filterControl) {
  463. return;
  464. }
  465. createControls(this, this.$header);
  466. };
  467. BootstrapTable.prototype.initBody = function () {
  468. _initBody.apply(this, Array.prototype.slice.apply(arguments));
  469. initFilterSelectControls(this);
  470. };
  471. BootstrapTable.prototype.initSearch = function () {
  472. _initSearch.apply(this, Array.prototype.slice.apply(arguments));
  473. if (this.options.sidePagination === 'server') {
  474. return;
  475. }
  476. var that = this;
  477. var fp = $.isEmptyObject(this.filterColumnsPartial) ? null : this.filterColumnsPartial;
  478. //Check partial column filter
  479. this.data = fp ? $.grep(this.data, function (item, i) {
  480. for (var key in fp) {
  481. var thisColumn = that.columns[$.fn.bootstrapTable.utils.getFieldIndex(that.columns, key)];
  482. var fval = fp[key].toLowerCase();
  483. var value = item[key];
  484. // Fix #142: search use formated data
  485. if (thisColumn && thisColumn.searchFormatter) {
  486. value = $.fn.bootstrapTable.utils.calculateObjectValue(that.header,
  487. that.header.formatters[$.inArray(key, that.header.fields)],
  488. [value, item, i], value);
  489. }
  490. if (thisColumn.filterStrictSearch) {
  491. if (!($.inArray(key, that.header.fields) !== -1 &&
  492. (typeof value === 'string' || typeof value === 'number') &&
  493. value.toString().toLowerCase() === fval.toString().toLowerCase())) {
  494. return false;
  495. }
  496. } else if (thisColumn.filterStartsWithSearch) {
  497. if (!($.inArray(key, that.header.fields) !== -1 &&
  498. (typeof value === 'string' || typeof value === 'number') &&
  499. (value + '').toLowerCase().indexOf(fval) === 0)) {
  500. return false;
  501. }
  502. } else {
  503. if (!($.inArray(key, that.header.fields) !== -1 &&
  504. (typeof value === 'string' || typeof value === 'number') &&
  505. (value + '').toLowerCase().indexOf(fval) !== -1)) {
  506. return false;
  507. }
  508. }
  509. }
  510. return true;
  511. }) : this.data;
  512. };
  513. BootstrapTable.prototype.initColumnSearch = function(filterColumnsDefaults) {
  514. copyValues(this);
  515. if (filterColumnsDefaults) {
  516. this.filterColumnsPartial = filterColumnsDefaults;
  517. this.updatePagination();
  518. for (var filter in filterColumnsDefaults) {
  519. this.trigger('column-search', filter, filterColumnsDefaults[filter]);
  520. }
  521. }
  522. };
  523. BootstrapTable.prototype.onColumnSearch = function (event) {
  524. if ($.inArray(event.keyCode, [37, 38, 39, 40]) > -1) {
  525. return;
  526. }
  527. copyValues(this);
  528. var text = $.trim($(event.currentTarget).val());
  529. var $field = $(event.currentTarget).closest('[data-field]').data('field');
  530. if ($.isEmptyObject(this.filterColumnsPartial)) {
  531. this.filterColumnsPartial = {};
  532. }
  533. if (text) {
  534. this.filterColumnsPartial[$field] = text;
  535. } else {
  536. delete this.filterColumnsPartial[$field];
  537. }
  538. // if the searchText is the same as the previously selected column value,
  539. // bootstrapTable will not try searching again (even though the selected column
  540. // may be different from the previous search). As a work around
  541. // we're manually appending some text to bootrap's searchText field
  542. // to guarantee that it will perform a search again when we call this.onSearch(event)
  543. this.searchText += "randomText";
  544. this.options.pageNumber = 1;
  545. this.onSearch(event);
  546. this.trigger('column-search', $field, text);
  547. };
  548. BootstrapTable.prototype.clearFilterControl = function () {
  549. if (this.options.filterControl && this.options.filterShowClear) {
  550. var that = this,
  551. cookies = collectBootstrapCookies(),
  552. header = getCurrentHeader(that),
  553. table = header.closest('table'),
  554. controls = header.find(getCurrentSearchControls(that)),
  555. search = that.$toolbar.find('.search input'),
  556. timeoutId = 0;
  557. $.each(that.options.valuesFilterControl, function (i, item) {
  558. item.value = '';
  559. });
  560. setValues(that);
  561. // Clear each type of filter if it exists.
  562. // Requires the body to reload each time a type of filter is found because we never know
  563. // which ones are going to be present.
  564. if (controls.length > 0) {
  565. this.filterColumnsPartial = {};
  566. $(controls[0]).trigger(controls[0].tagName === 'INPUT' ? 'keyup' : 'change');
  567. } else {
  568. return;
  569. }
  570. if (search.length > 0) {
  571. that.resetSearch();
  572. }
  573. // use the default sort order if it exists. do nothing if it does not
  574. if (that.options.sortName !== table.data('sortName') || that.options.sortOrder !== table.data('sortOrder')) {
  575. var sorter = header.find(sprintf('[data-field="%s"]', $(controls[0]).closest('table').data('sortName')));
  576. if (sorter.length > 0) {
  577. that.onSort(table.data('sortName'), table.data('sortName'));
  578. $(sorter).find('.sortable').trigger('click');
  579. }
  580. }
  581. // clear cookies once the filters are clean
  582. clearTimeout(timeoutId);
  583. timeoutId = setTimeout(function () {
  584. if (cookies && cookies.length > 0) {
  585. $.each(cookies, function (i, item) {
  586. if (that.deleteCookie !== undefined) {
  587. that.deleteCookie(item);
  588. }
  589. });
  590. }
  591. }, that.options.searchTimeOut);
  592. }
  593. };
  594. })(jQuery);