PageSourceSearch

https://madaras.hu/onkormanyzat/js/bootstrap-table-filter-control.js

js madaras.hu collected 2026-10-02 21:21:21 UTC 29,253 bytes, 917 lines download raw bytes

1/**
2 * @author: Dennis Hernández
3 * @webSite: http://djhvscf.github.io/Blog
4 * @version: v2.2.0
5 */
6
7($ => {
8  const Utils = $.fn.bootstrapTable.utils
9  const UtilsFilterControl = {
10    getOptionsFromSelectControl (selectControl) {
11      return selectControl.get(selectControl.length - 1).options
12    },
13
14    hideUnusedSelectOptions (selectControl, uniqueValues) {
15      const options = UtilsFilterControl.getOptionsFromSelectControl(
16        selectControl
17      )
18
19      for (let i = 0; i < options.length; i++) {
20        if (options[i].value !== '') {
21          if (!uniqueValues.hasOwnProperty(options[i].value)) {
22            selectControl
23              .find(Utils.sprintf('option[value=\'%s\']', options[i].value))
24              .hide()
25          } else {
26            selectControl
27              .find(Utils.sprintf('option[value=\'%s\']', options[i].value))
28              .show()
29          }
30        }
31      }
32    },
33    addOptionToSelectControl (selectControl, _value, text) {
34      const value = $.trim(_value)
35      const $selectControl = $(selectControl.get(selectControl.length - 1))
36      if (
37        !UtilsFilterControl.existOptionInSelectControl(selectControl, value)
38      ) {
39        $selectControl.append(
40          $('<option></option>')
41            .attr('value', value)
42            .text(
43              $('<div />')
44                .html(text)
45                .text()
46            )
47        )
48      }
49    },
50    sortSelectControl (selectControl) {
51      const $selectControl = $(selectControl.get(selectControl.length - 1))
52      const $opts = $selectControl.find('option:gt(0)')
53
54      $opts.sort((a, b) => {
55        let aa = $(a).text().toLowerCase()
56        let bb = $(b).text().toLowerCase()
57        if ($.isNumeric(a) && $.isNumeric(b)) {
58          // Convert numerical values from string to float.
59          aa = parseFloat(aa)
60          bb = parseFloat(bb)
61        }
62        return aa > bb ? 1 : aa < bb ? -1 : 0
63      })
64
65      $selectControl.find('option:gt(0)').remove()
66      $selectControl.append($opts)
67    },
68    existOptionInSelectControl (selectControl, value) {
69      const options = UtilsFilterControl.getOptionsFromSelectControl(
70        selectControl
71      )
72      for (let i = 0; i < options.length; i++) {
73        if (options[i].value === value.toString()) {
74          // The value is not valid to add
75          return true
76        }
77      }
78
79      // If we get here, the value is valid to add
80      return false
81    },
82    fixHeaderCSS ({ $tableHeader }) {
83      $tableHeader.css('height', '77px')
84    },
85    getCurrentHeader ({ $header, options, $tableHeader }) {
86      let header = $header
87      if (options.height) {
88        header = $tableHeader
89      }
90
91      return header
92    },
93    getCurrentSearchControls ({ options }) {
94      let searchControls = 'select, input'
95      if (options.height) {
96        searchControls = 'table select, table input'
97      }
98
99      return searchControls
100    },
101    getCursorPosition (el) {
102      if (Utils.isIEBrowser()) {
103        if ($(el).is('input[type=text]')) {
104          let pos = 0
105          if ('selectionStart' in el) {
106            pos = el.selectionStart
107          } else if ('selection' in document) {
108            el.focus()
109            const Sel = document.selection.createRange()
110            const SelLength = document.selection.createRange().text.length
111            Sel.moveStart('character', -el.value.length)
112            pos = Sel.text.length - SelLength
113          }
114          return pos
115        }
116        return -1
117
118      }
119      return -1
120    },
121    setCursorPosition (el) {
122      $(el).val(el.value)
123    },
124    copyValues (that) {
125      const header = UtilsFilterControl.getCurrentHeader(that)
126      const searchControls = UtilsFilterControl.getCurrentSearchControl
126s(that)
127
128      that.options.valuesFilterControl = []
129
130      header.find(searchControls).each(function () {
131        that.options.valuesFilterControl.push({
132          field: $(this)
133            .closest('[data-field]')
134            .data('field'),
135          value: $(this).val(),
136          position: UtilsFilterControl.getCursorPosition($(this).get(0)),
137          hasFocus: $(this).is(':focus')
138        })
139      })
140    },
141    setValues (that) {
142      let field = null
143      let result = []
144      const header = UtilsFilterControl.getCurrentHeader(that)
145      const searchControls = UtilsFilterControl.getCurrentSearchControls(that)
146
147      if (that.options.valuesFilterControl.length > 0) {
148        //  Callback to apply after settings fields values
149        let fieldToFocusCallback = null
150        header.find(searchControls).each(function (index, ele) {
151          field = $(this)
152            .closest('[data-field]')
153            .data('field')
154          result = that.options.valuesFilterControl.filter(valueObj => valueObj.field === field)
155
156          if (result.length > 0) {
157            $(this).val(result[0].value)
158            if (result[0].hasFocus) {
159              // set callback if the field had the focus.
160              fieldToFocusCallback = ((fieldToFocus, carretPosition) => {
161                // Closure here to capture the field and cursor position
162                const closedCallback = () => {
163                  fieldToFocus.focus()
164                  UtilsFilterControl.setCursorPosition(fieldToFocus, carretPosition)
165                }
166                return closedCallback
167              })($(this).get(0), result[0].position)
168            }
169          }
170        })
171
172        // Callback call.
173        if (fieldToFocusCallback !== null) {
174          fieldToFocusCallback()
175        }
176      }
177    },
178    collectBootstrapCookies () {
179      const cookies = []
180      const foundCookies = document.cookie.match(/(?:bs.table.)(\w*)/g)
181
182      if (foundCookies) {
183        $.each(foundCookies, (i, _cookie) => {
184          let cookie = _cookie
185          if (/./.test(cookie)) {
186            cookie = cookie.split('.').pop()
187          }
188
189          if ($.inArray(cookie, cookies) === -1) {
190            cookies.push(cookie)
191          }
192        })
193        return cookies
194      }
195    },
196    escapeID (id) {
197      return String(id).replace(/(:|\.|\[|\]|,)/g, '\\$1')
198    },
199    isColumnSearchableViaSelect ({ filterControl, searchable }) {
200      return filterControl &&
201        filterControl.toLowerCase() === 'select' &&
202        searchable
203    },
204    isFilterDataNotGiven ({ filterData }) {
205      return filterData === undefined ||
206        filterData.toLowerCase() === 'column'
207    },
208    hasSelectControlElement (selectControl) {
209      return selectControl && selectControl.length > 0
210    },
211    initFilterSelectControls (that) {
212      const data = that.data
213      const itemsPerPage = that.pageTo < that.options.data.length ? that.options.data.length : that.pageTo
214      const z = that.options.pagination
215        ? that.options.sidePagination === 'server'
216          ? that.pageTo
217          : that.options.totalRows
218        : that.pageTo
219
220      $.each(that.header.fields, (j, field) => {
221        const column = that.columns[that.fieldsColumnsIndex[field]]
222        const selectControl = $(`.bootstrap-table-filter-control-${UtilsFilterControl.escapeID(column.field)}`)
223
224        if (
225          UtilsFilterControl.isColumnSearchableViaSelect(column) &&
226          UtilsFilterControl.isFilterDataNotGiven(column) &&
227          UtilsFilterControl.hasSelectControlElement(selectControl)
228        ) {
229          if (selectControl.get(selectControl.length - 1).options.length === 0) {
230            // Added the default option
231            UtilsFilterControl.addOptionToSelectControl(selectControl, '', column.filterControlPlaceholder)
232          }
233
234          const uniqueValues = {}
235          for (let i = 0; i < z; i++) {
236            // Added a new value
237            const fieldValue = data[i][field]
238            const formattedValue = Utils.calculateObjectValue(that.header, that.header.formatters[j], [fieldValue, data[i], i], fieldValue)
239
240            uniqueValues[formattedValue] = fieldValue
241          }
242
243          // eslint-disable-next-line guard-for-in
244          for (const key in uniqueValues) {
245            UtilsFilterControl.addOptionToSelectControl(selectControl, uniqueValues[key], key)
246          }
247
248          UtilsFilterControl.sortSelectControl(selectControl)
249
250          if (that.options.hideUnusedSelectOptions) {
251            UtilsFilterControl.hideUnusedSelectOptions(selectControl, uniqueValues)
252          }
253        }
254      })
255
256      that.trigger('created-controls')
257    },
258    getFilterDataMethod (objFilterDataMethod, searchTerm) {
259      const keys = Object.keys(objFilterDataMethod)
260      for (let i = 0; i < keys.length; i++) {
261        if (keys[i] === searchTerm) {
262          return objFilterDataMethod[searchTerm]
263        }
264      }
265      return null
266    },
267    createControls (that, header) {
268      let addedFilterControl = false
269      let isVisible
270      let html
271
272      $.each(that.columns, (i, column) => {
273        isVisible = 'hidden'
274        html = []
275
276        if (!column.visible) {
277          return
278        }
279
280        if (!column.filterControl) {
281          html.push('<div class="no-filter-control"></div>')
282        } else {
283          html.push('<div class="filter-control">')
284
285          const nameControl = column.filterControl.toLowerCase()
286          if (column.searchable && that.options.filterTemplate[nameControl]) {
287            addedFilterControl = true
288            isVisible = 'visible'
289            html.push(
290              that.options.filterTemplate[nameControl](
291                that,
292                column.field,
293                isVisible,
294                column.filterControlPlaceholder
295                  ? column.filterControlPlaceholder
296                  : '',
297                `filter-control-${i}`
298              )
299            )
300          }
301        }
302
303        $.each(header.children().children(), (i, tr) => {
304          const $tr = $(tr)
305          if ($tr.data('field') === column.field) {
306            $tr.find('.fht-cell').append(html.join(''))
307            return false
308          }
309        })
310
311        if (
312          column.filterData !== undefined &&
313          column.filterData.toLowerCase() !== 'column'
314        ) {
315          const filterDataType = UtilsFilterControl.getFilterDataMethod(
316            /* eslint-disable no-use-before-define */
317            filterDataMethods,
318            column.filterData.substring(0, column.filterData.indexOf(':'))
319          )
320          let filterDataSource
321          let selectControl
322
323          if (filterDataType !== null) {
324            filterDataSource = column.filterData.substring(
325              column.filterData.indexOf(':') + 1,
326              column.filterData.length
327            )
328            selectControl = $(
329              `.bootstrap-table-filter-control-${UtilsFilterControl.escapeID(column.field)}`
330            )
331
332            UtilsFilterControl.addOptionToSelectControl(selectControl, '', column.filterControlPlaceholder)
333            filterDataType(filterDataSource, selectControl)
334          } else {
335            throw new SyntaxError(
336              'Error. You should use any of these allowed filter data methods: var, json, url.' +
337              ' Use like this: var: {key: "value"}'
338            )
339          }
340
341          let variableValues
342          let key
343          // eslint-disable-next-line default-case
344          switch (filterDataType) {
345            case 'url':
346              $.ajax({
347                url: filterDataSource,
348                dataType: 'json',
349                success (data) {
350                  // eslint-disable-next-line guard-for-in
351                  for (const key in data) {
352                    UtilsFilterControl.addOptionToSelectControl(selectControl, key, data[key])
353                  }
354                  UtilsFilterControl.sortSelectControl(selectControl)
355                }
356              })
357              break
358            case 'var':
359              variableValues = window[filterDataSource]
360              // eslint-disable-next-line guard-for-in
361              for (key in variableValues) {
362                UtilsFilterControl.addOptionToSelectControl(selectControl, key, variableValues[key])
363              }
364              UtilsFilterControl.sortSelectControl(selectControl)
365              break
366            case 'jso':
367              variableValues = JSON.parse(filterDataSource)
368              // eslint-disable-next-line guard-for-in
369              for (key in variableValues) {
370                UtilsFilterControl.addOptionToSelectControl(selectControl, key, variableValues[key])
371              }
372              UtilsFilterControl.sortSelectControl(selectControl)
373              break
374          }
375        }
376      })
377
378      if (addedFilterControl) {
379        header.off('keyup', 'input').on('keyup', 'input', (event, obj) => {
380          // Simulate enter key action from clear button
381          event.keyCode = obj ? obj.keyCode : event.keyCode
382
383          if (that.options.searchOnEnterKey && event.keyCode !== 13) {
384            return
385          }
386
387          if ($.inArray(event.keyCode, [37, 38, 39, 40]) > -1) {
388            return
389          }
390
391          const $currentTarget = $(event.currentTarget)
392
393          if ($currentTarget.is(':checkbox') || $currentTarget.is(':radio')) {
394            return
395          }
396
397          clearTimeout(event.currentTarget.timeoutId || 0)
398          event.currentTarget.timeoutId = setTimeout(() => {
399            that.onColumnSearch(event)
400          }, that.options.searchTimeOut)
401        })
402
403        header.off('change', 'select').on('change', 'select', event => {
404          if (that.options.searchOnEnterKey && event.keyCode !== 13) {
405            return
406          }
407
408          if ($.inArray(event.keyCode, [37, 38, 39, 40]) > -1) {
409            return
410          }
411
412          clearTimeout(event.currentTarget.timeoutId || 0)
413          event.currentTarget.timeoutId = setTimeout(() => {
414            that.onColumnSearch(event)
415          }, that.options.searchTimeOut)
416        })
417
418        header.off('mouseup', 'input').on('mouseup', 'input', function (event) {
419          const $input = $(this)
420          const oldValue = $input.val()
421
422          if (oldValue === '') {
423            return
424          }
425
426          setTimeout(() => {
427            const newValue = $input.val()
428
429            if (newValue === '') {
430              clearTimeout(event.currentTarget.timeoutId || 0)
431              event.currentTarget.timeoutId = setTimeout(() => {
432                that.onColumnSearch(event)
433              }, that.options.searchTimeOut)
434            }
435          }, 1)
436        })
437
438        if (header.find('.date-filter-control').length > 0) {
439          $.each(that.columns, (i, { filterControl, field, filterDatepickerOptions }) => {
440            if (
441              filterControl !== undefined &&
442              filterControl.toLowerCase() === 'datepicker'
443            ) {
444              header
445                .find(
446                  `.date-filter-control.bootstrap-table-filter-control-${field}`
447                )
448                .datepicker(filterDatepickerOptions)
449                .on('changeDate', ({ currentTarget }) => {
450                  $(currentTarget).val(
451                    currentTarget.value
452                  )
453                  // Fired the keyup event
454                  $(currentTarget).keyup()
455                })
456            }
457          })
458        }
459      } else {
460        header.find('.filterControl').hide()
461      }
462    },
463    getDirectionOfSelectOptions (_alignment) {
464      const alignment = _alignment === undefined ? 'left' : _alignment.toLowerCase()
465
466      switch (alignment) {
467        case 'left':
468          return 'ltr'
469        case 'right':
470          return 'rtl'
471        case 'auto':
472          return 'auto'
473        default:
474          return 'ltr'
475      }
476    }
477  }
478  const filterDataMethods = {
479    var (filterDataSource, selectControl) {
480      const variableValues = window[filterDataSource]
481      // eslint-disable-next-line guard-for-in
482      for (const key in variableValues) {
483        UtilsFilterControl.addOptionToSelectControl(selectControl, key, variableValues[key])
484      }
485      UtilsFilterControl.sortSelectControl(selectControl)
486    },
487    url (filterDataSource, selectControl) {
488      $.ajax({
489        url: filterDataSource,
490        dataType: 'json',
491        success (data) {
492          // eslint-disable-next-line guard-for-in
493          for (const key in data) {
494            UtilsFilterControl.addOptionToSelectControl(selectControl, key, data[key])
495          }
496          UtilsFilterControl.sortSelectControl(selectControl)
497        }
498      })
499    },
500    json (filterDataSource, selectControl) {
501      const variableValues = JSON.parse(filterDataSource)
502      // eslint-disable-next-line guard-for-in
503      for (const key in variableValues) {
504        UtilsFilterControl.addOptionToSelectControl(selectControl, key, variableValues[key])
505      }
506      UtilsFilterControl.sortSelectControl(selectControl)
507    }
508  }
509
510  const bootstrap = {
511    3: {
512      icons: {
513        clear: 'glyphicon-trash icon-clear'
514      }
515    },
516    4: {
517      icons: {
518        clear: 'fa-trash icon-clear'
519      }
520    }
521  }[Utils.bootstrapVersion]
522
523  $.extend($.fn.bootstrapTable.defaults, {
524    filterControl: false,
525    onColumnSearch (field, text) {
526      return false
527    },
528    onCreatedControls () {
529      return true
530    },
531    filterShowClear: false,
532    alignmentSelectControlOptions: undefined,
533    filterTemplate: {
534      input (that, field, isVisible, placeholder) {
535        return Utils.sprintf(
536          '<input type="text" class="form-control bootstrap-table-filter-control-%s" style="width: 100%; visibility: %s" placeholder="%s">',
537          field,
538          isVisible,
539          placeholder
540        )
541      },
542      select ({ options }, field, isVisible) {
543        return Utils.sprintf(
544          '<select class="form-control bootstrap-table-filter-control-%s" style="width: 100%; visibility: %s" dir="%s"></select>',
545          field,
546          isVisible,
547          UtilsFilterControl.getDirectionOfSelectOptions(
548            options.alignmentSelectControlOptions
549          )
550        )
551      },
552      datepicker (that, field, isVisible) {
553        return Utils.sprintf(
554          '<input type="text" class="form-control date-filter-control bootstrap-table-filter-control-%s" style="width: 100%; visibility: %s">',
555          field,
556          isVisible
557        )
558      }
559    },
560    disableControlWhenSearch: false,
561    searchOnEnterKey: false,
562    // internal variables
563    valuesFilterControl: []
564  })
565
566  $.extend($.fn.bootstrapTable.columnDefaults, {
567    filterControl: undefined,
568    filterData: undefined,
569    filterDatepickerOptions: undefined,
570    filterStrictSearch: false,
571    filterStartsWithSearch: false,
572    filterControlPlaceholder: ''
573  })
574
575  $.extend($.fn.bootstrapTable.Constructor.EVENTS, {
576    'column-search.bs.table': 'onColumnSearch',
577    'created-controls.bs.table': 'onCreatedControls'
578  })
579
580  $.extend($.fn.bootstrapTable.defaults.icons, {
581    clear: bootstrap.icons.clear
582  })
583
584  $.extend($.fn.bootstrapTable.locales, {
585    formatClearFilters () {
586      return 'Clear Filters'
587    }
588  })
589
590  $.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
591
592  $.fn.bootstrapTable.methods.push('triggerSearch')
593  $.fn.bootstrapTable.methods.push('clearFilterControl')
594
595  $.BootstrapTable = class extends $.BootstrapTable {
596    init () {
597      // Make sure that the filterControl option is set
598      if (this.options.filterControl) {
599        const that = this
600
601        // Make sure that the internal variables are set correctly
602        this.options.valuesFilterControl = []
603
604        this.$el
605          .on('reset-view.bs.table', () => {
606            // Create controls on $tableHeader if the height is set
607            if (!that.options.height) {
608              return
609            }
610
611            // Avoid recreate the controls
612            if (
613              that.$tableHeader.find('select').length > 0 ||
614              that.$tableHeader.find('input').length > 0
615            ) {
616              return
617            }
618
619            UtilsFilterControl.createControls(that, that.$tableHeader)
620          })
621          .on('post-header.bs.table', () => {
622            UtilsFilterControl.setValues(that)
623          })
624          .on('post-body.bs.table', () => {
625            if (that.options.height) {
626              UtilsFilterControl.fixHeaderCSS(that)
627            }
628          })
629          .on('column-switch.bs.table', () => {
630            UtilsFilterControl.setValues(that)
631          })
632          .on('load-success.bs.table', () => {
633            that.EnableControls(true)
634          })
635          .on('load-error.bs.table', () => {
636            that.EnableControls(true)
637          })
638      }
639
640      super.init()
641    }
642
643    initToolbar () {
644      this.showToolbar =
645        this.showToolbar ||
646        (this.options.filterControl && this.options.filterShowClear)
647
648      super.initToolbar()
649
650      if (this.options.filterControl && this.options.filterShowClear) {
651        const $btnGroup = this.$toolbar.find('>.btn-group')
652        let $btnClear = $btnGroup.find('.filter-show-clear')
653
654        if (!$btnClear.length) {
655          $btnClear = $(
656            [
657              Utils.sprintf(
658                '<button class="btn btn-%s filter-show-clear" ',
659                this.options.buttonsClass
660              ),
661              Utils.sprintf(
662                'type="button" title="%s">',
663                this.options.formatClearFilters()
664              ),
665              Utils.sprintf(
666                '<i class="%s %s"></i> ',
667                this.options.iconsPrefix,
668                this.options.icons.clear
669              ),
670              '</button>'
671            ].join('')
672          ).appendTo($btnGroup)
673
674          $btnClear
675            .off('click')
676            .on('click', $.proxy(this.clearFilterControl, this))
677        }
678      }
679    }
680
681    initHeader () {
682      super.initHeader()
683
684      if (!this.options.filterControl) {
685        return
686      }
687      UtilsFilterControl.createControls(this, this.$header)
688    }
689    initBody () {
690      super.initBody()
691
692      UtilsFilterControl.initFilterSelectControls(this)
693    }
694
695    initSearch () {
696      const that = this
697      const fp = $.isEmptyObject(that.filterColumnsPartial)
698        ? null
699        : that.filterColumnsPartial
700
701      if (fp === null || Object.keys(fp).length <= 1) {
702        super.initSearch()
703      }
704
705      if (this.options.sidePagination === 'server') {
706        return
707      }
708
709      if (fp === null) {
710        return
711      }
712
713      // Check partial column filter
714      that.data = fp
715        ? that.options.data.filter((item, i) => {
716          const itemIsExpected = []
717          Object.keys(item).forEach((key, index) => {
718            const thisColumn = that.columns[that.fieldsColumnsIndex[key]]
719            const fval = (fp[key] || '').toLowerCase()
720            let value = item[key]
721
722            if (fval === '') {
723              itemIsExpected.push(true)
724            } else {
725              // Fix #142: search use formated data
726              if (thisColumn && thisColumn.searchFormatter) {
727                value = $.fn.bootstrapTable.utils.calculateObjectValue(
728                  that.header,
729                  that.header.formatters[$.inArray(key, that.header.fields)],
730                  [value, item, i],
731                  value
732                )
733              }
734
735              if ($.inArray(key, that.header.fields) !== -1) {
736                if (typeof value === 'string' || typeof value === 'number') {
737                  if (thisColumn.filterStrictSearch) {
738                    if (value.toString().toLowerCase() === fval.toString().toLowerCase()) {
739                      itemIsExpected.push(true)
740                    } else {
741                      itemIsExpected.push(false)
742                    }
743                  } else if (thisColumn.filterStartsWithSearch) {
744                    if ((`${value}`).toLowerCase().indexOf(fval) === 0) {
745                      itemIsExpected.push(true)
746                    } else {
747                      itemIsExpected.push(false)
748                    }
749                  } else {
750                    if ((`${value}`).toLowerCase().includes(fval)) {
751                      itemIsExpected.push(true)
752                    } else {
753                      itemIsExpected.push(false)
754                    }
755                  }
756                }
757              }
758            }
759          })
760
761          return !itemIsExpected.includes(false)
762        })
763        : that.data
764    }
765
766    initColumnSearch (filterColumnsDefaults) {
767      UtilsFilterControl.copyValues(this)
768
769      if (filterColumnsDefaults) {
770        this.filterColumnsPartial = filterColumnsDefaults
771        this.updatePagination()
772
773        // eslint-disable-next-line guard-for-in
774        for (const filter in filterColumnsDefaults) {
775          this.trigger('column-search', filter, filterColumnsDefaults[filter])
776        }
777      }
778    }
779
780    onColumnSearch (event) {
781      if ($.inArray(event.keyCode, [37, 38, 39, 40]) > -1) {
782        return
783      }
784
785      UtilsFilterControl.copyValues(this)
786      const text = $.trim($(event.currentTarget).val())
787      const $field = $(event.currentTarget)
788        .closest('[data-field]')
789        .data('field')
790
791      if ($.isEmptyObject(this.filterColumnsPartial)) {
792        this.filterColumnsPartial = {}
793      }
794      if (text) {
795        this.filterColumnsPartial[$field] = text
796      } else {
797        delete this.filterColumnsPartial[$field]
798      }
799
800      // if the searchText is the same as the previously selected column value,
801      // bootstrapTable will not try searching again (even though the selected column
802      // may be different from the previous search).  As a work around
803      // we're manually appending some text to bootrap's searchText field
804      // to guarantee that it will perform a search again when we call this.onSearch(event)
805      this.searchText += 'randomText'
806
807      this.options.pageNumber = 1
808      this.EnableControls(false)
809      this.onSearch(event)
810      this.trigger('column-search', $field, text)
811    }
812
813    clearFilterControl () {
814      if (this.options.filterControl && this.options.filterShowClear) {
815        const that = this
816        const cookies = UtilsFilterControl.collectBootstrapCookies()
817        const header = UtilsFilterControl.getCurrentHeader(that)
818        const table = header.closest('table')
819        const controls = header.find(UtilsFilterControl.getCurrentSearchControl
819s(that))
820        const search = that.$toolbar.find('.search input')
821        let hasValues = false
822        let timeoutId = 0
823
824        $.each(that.options.valuesFilterControl, (i, item) => {
825          hasValues = hasValues ? true : item.value !== ''
826          item.value = ''
827        })
828
829        UtilsFilterControl.setValues(that)
830
831        // clear cookies once the filters are clean
832        clearTimeout(timeoutId)
833        timeoutId = setTimeout(() => {
834          if (cookies && cookies.length > 0) {
835            $.each(cookies, (i, item) => {
836              if (that.deleteCookie !== undefined) {
837                that.deleteCookie(item)
838              }
839            })
840          }
841        }, that.options.searchTimeOut)
842
843        // If there is not any value in the controls exit this method
844        if (!hasValues) {
845          return
846        }
847
848        // Clear each type of filter if it exists.
849        // Requires the body to reload each time a type of filter is found because we never know
850        // which ones are going to be present.
851        if (controls.length > 0) {
852          this.filterColumnsPartial = {}
853          $(controls[0]).trigger(
854            controls[0].tagName === 'INPUT' ? 'keyup' : 'change', { keyCode: 13 }
855          )
856        } else {
857          return
858        }
859
860        if (search.length > 0) {
861          that.resetSearch()
862        }
863
864        // use the default sort order if it exists. do nothing if it does not
865        if (
866          that.options.sortName !== table.data('sortName') ||
867          that.options.sortOrder !== table.data('sortOrder')
868        ) {
869          const sorter = header.find(
870            Utils.sprintf(
871              '[data-field="%s"]',
872              $(controls[0])
873                .closest('table')
874                .data('sortName')
875            )
876          )
877          if (sorter.length > 0) {
878            that.onSort({ type: 'keypress', currentTarget: sorter })
879            $(sorter)
880              .find('.sortable')
881              .trigger('click')
882          }
883        }
884      }
885    }
886
887    triggerSearch () {
888      const header = UtilsFilterControl.getCurrentHeader(this)
889      const searchControls = UtilsFilterControl.getCurrentSearchControls(this)
890
891      header.find(searchControls).each(function () {
892        const el = $(this)
893        if (el.is('select')) {
894          el.change()
895        } else {
896          el.keyup()
897        }
898      })
899    }
900
901    EnableControls (enable) {
902      if (
903        this.options.disableControlWhenSearch &&
904        this.options.sidePagination === 'server'
905      ) {
906        const header = UtilsFilterControl.getCurrentHeader(this)
907        const searchControls = UtilsFilterControl.getCurrentSearchControls(this)
908
909        if (!enable) {
910          header.find(searchControls).prop('disabled', 'disabled')
911        } else {
912          header.find(searchControls).removeProp('disabled')
913        }
914      }
915    }
916  }
917})(jQuery)

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.