浏览代码

Merge pull request #4678 from wenzhixin/feature/4576

Feature/4576
文翼 6 年之前
父节点
当前提交
c2ba90280a
共有 2 个文件被更改,包括 85 次插入71 次删除
  1. 11 0
      site/docs/extensions/filter-control.md
  2. 74 71
      src/extensions/filter-control/bootstrap-table-filter-control.js

+ 11 - 0
site/docs/extensions/filter-control.md

@@ -31,6 +31,17 @@ Dependence if you use the datepicker option: [bootstrap-datepicker](https://gith
 
 - **Default:** `false`
 
+### filterControlContainer
+
+- **type:** `Selector`
+
+- **Detail:**
+
+   Set to e.g. `#filter` to allow custom input filter in a element with the id `filter`.
+   Each filter element (input or select) must have the following id `bootstrap-table-filter-control-<Fieldname>` (<Fieldname> must be replaced with the defined [Field](https://bootstrap-table.com/docs/api/column-options/#field) name).
+
+- **Default:** `false`
+
 ### filterDataCollector
 
 - **type:** `Function`

+ 74 - 71
src/extensions/filter-control/bootstrap-table-filter-control.js

@@ -9,7 +9,19 @@ const UtilsFilterControl = {
   getOptionsFromSelectControl (selectControl) {
     return selectControl.get(selectControl.length - 1).options
   },
+  getControlContainer () {
+    if (UtilsFilterControl.bootstrapTableInstance.options.filterControlContainer) {
+      return $(`${UtilsFilterControl.bootstrapTableInstance.options.filterControlContainer}`)
+    }
+
+    return UtilsFilterControl.getCurrentHeader(UtilsFilterControl.bootstrapTableInstance)
+  },
+  getSearchControls (scope) {
+    const header = UtilsFilterControl.getControlContainer()
+    const searchControls = UtilsFilterControl.getCurrentSearchControls(scope)
 
+    return header.find(searchControls)
+  },
   hideUnusedSelectOptions (selectControl, uniqueValues) {
     const options = UtilsFilterControl.getOptionsFromSelectControl(
       selectControl
@@ -35,15 +47,7 @@ const UtilsFilterControl = {
     if (
       !UtilsFilterControl.existOptionInSelectControl(selectControl, value)
     ) {
-      const option = $(
-        $('<option></option>')
-          .attr('value', value)
-          .text(
-            $('<div />')
-              .html(text)
-              .text()
-          )
-      )
+      const option = $(`<option value="${value}">${text}</option>`)
 
       if (value === selected) {
         option.attr('selected', true)
@@ -77,10 +81,10 @@ const UtilsFilterControl = {
     // If we get here, the value is valid to add
     return false
   },
-  fixHeaderCSS ({ $tableHeader }) {
+  fixHeaderCSS ({$tableHeader}) {
     $tableHeader.css('height', '77px')
   },
-  getCurrentHeader ({ $header, options, $tableHeader }) {
+  getCurrentHeader ({$header, options, $tableHeader}) {
     let header = $header
     if (options.height) {
       header = $tableHeader
@@ -88,7 +92,7 @@ const UtilsFilterControl = {
 
     return header
   },
-  getCurrentSearchControls ({ options }) {
+  getCurrentSearchControls ({options}) {
     let searchControls = 'select, input'
     if (options.height) {
       searchControls = 'table select, table input'
@@ -120,12 +124,11 @@ const UtilsFilterControl = {
     $(el).val(el.value)
   },
   copyValues (that) {
-    const header = UtilsFilterControl.getCurrentHeader(that)
-    const searchControls = UtilsFilterControl.getCurrentSearchControls(that)
+    const searchControls = UtilsFilterControl.getSearchControls(that)
 
     that.options.valuesFilterControl = []
 
-    header.find(searchControls).each(function () {
+    searchControls.each(function () {
       that.options.valuesFilterControl.push({
         field: $(this)
           .closest('[data-field]')
@@ -139,13 +142,12 @@ const UtilsFilterControl = {
   setValues (that) {
     let field = null
     let result = []
-    const header = UtilsFilterControl.getCurrentHeader(that)
-    const searchControls = UtilsFilterControl.getCurrentSearchControls(that)
+    const searchControls = UtilsFilterControl.getSearchControls(that)
 
     if (that.options.valuesFilterControl.length > 0) {
       //  Callback to apply after settings fields values
       let fieldToFocusCallback = null
-      header.find(searchControls).each(function (index, ele) {
+      searchControls.each(function (index, ele) {
         field = $(this)
           .closest('[data-field]')
           .data('field')
@@ -192,14 +194,15 @@ const UtilsFilterControl = {
     }
   },
   escapeID (id) {
-    return String(id).replace(/(:|\.|\[|\]|,)/g, '\\$1')
+    // eslint-disable-next-line no-useless-escape
+    return String(id).replace(/([:.\[\],])/g, '\\$1')
   },
-  isColumnSearchableViaSelect ({ filterControl, searchable }) {
+  isColumnSearchableViaSelect ({filterControl, searchable}) {
     return filterControl &&
       filterControl.toLowerCase() === 'select' &&
       searchable
   },
-  isFilterDataNotGiven ({ filterData }) {
+  isFilterDataNotGiven ({filterData}) {
     return filterData === undefined ||
       filterData.toLowerCase() === 'column'
   },
@@ -208,7 +211,6 @@ const UtilsFilterControl = {
   },
   initFilterSelectControls (that) {
     const data = that.data
-    const itemsPerPage = that.pageTo < that.options.data.length ? that.options.data.length : that.pageTo
     const z = that.options.pagination
       ? that.options.sidePagination === 'server'
         ? that.pageTo
@@ -217,8 +219,7 @@ const UtilsFilterControl = {
 
     $.each(that.header.fields, (j, field) => {
       const column = that.columns[that.fieldsColumnsIndex[field]]
-      const selectControl = that.$tableBody.find(`.bootstrap-table-filter-control-${UtilsFilterControl.escapeID(column.field)}`)
-
+      const selectControl = UtilsFilterControl.getControlContainer().find(`.bootstrap-table-filter-control-${UtilsFilterControl.escapeID(column.field)}`)
       if (
         UtilsFilterControl.isColumnSearchableViaSelect(column) &&
         UtilsFilterControl.isFilterDataNotGiven(column) &&
@@ -239,6 +240,8 @@ const UtilsFilterControl = {
             formattedValue = Utils.calculateObjectValue(that.header, column.filterDataCollector, [fieldValue, data[i], formattedValue], formattedValue)
           }
 
+          uniqueValues[formattedValue] = fieldValue
+
           if (typeof formattedValue === 'object' && formattedValue !== null) {
             formattedValue.forEach((value) => {
               UtilsFilterControl.addOptionToSelectControl(selectControl, value, value, column.filterDefault)
@@ -274,42 +277,47 @@ const UtilsFilterControl = {
     let html
 
     $.each(that.columns, (i, column) => {
-      isVisible = 'hidden'
       html = []
 
       if (!column.visible) {
         return
       }
 
-      if (!column.filterControl) {
+      if (!column.filterControl && !that.options.filterControlContainer) {
         html.push('<div class="no-filter-control"></div>')
+      } else if (that.options.filterControlContainer) {
+        const $filterControl = $(`.bootstrap-table-filter-control-${column.field}`)
+        const placeholder = column.filterControlPlaceholder ? column.filterControlPlaceholder : ''
+        $filterControl.attr('placeholder', placeholder)
+        $filterControl.val(column.filterDefault)
+        $filterControl.attr('data-field', column.field)
+        addedFilterControl = true
       } else {
+        const nameControl = column.filterControl.toLowerCase()
+
         html.push('<div class="filter-control">')
+        addedFilterControl = true
 
-        const nameControl = column.filterControl.toLowerCase()
         if (column.searchable && that.options.filterTemplate[nameControl]) {
-          addedFilterControl = true
-          isVisible = 'visible'
           html.push(
             that.options.filterTemplate[nameControl](
               that,
               column.field,
-              isVisible,
               column.filterControlPlaceholder
                 ? column.filterControlPlaceholder
                 : '',
               column.filterDefault
             )
           )
+        }
+      }
 
-          if ('' !== column.filterDefault && 'undefined' !== typeof column.filterDefault) {
-            if ($.isEmptyObject(that.filterColumnsPartial)) {
-              that.filterColumnsPartial = {}
-            }
-
-            that.filterColumnsPartial[column.field] = column.filterDefault
-          }
+      if (!column.filterControl && '' !== column.filterDefault && 'undefined' !== typeof column.filterDefault) {
+        if ($.isEmptyObject(that.filterColumnsPartial)) {
+          that.filterColumnsPartial = {}
         }
+
+        that.filterColumnsPartial[column.field] = column.filterDefault
       }
 
       $.each(header.children().children(), (i, tr) => {
@@ -337,7 +345,7 @@ const UtilsFilterControl = {
             column.filterData.indexOf(':') + 1,
             column.filterData.length
           )
-          selectControl = that.$tableBody.find(`.bootstrap-table-filter-control-${UtilsFilterControl.escapeID(column.field)}`)
+          selectControl = UtilsFilterControl.getControlContainer().find(`.bootstrap-table-filter-control-${UtilsFilterControl.escapeID(column.field)}`)
 
           UtilsFilterControl.addOptionToSelectControl(selectControl, '', column.filterControlPlaceholder, column.filterDefault)
           filterDataType(filterDataSource, selectControl, column.filterDefault)
@@ -386,7 +394,7 @@ const UtilsFilterControl = {
     })
 
     if (addedFilterControl) {
-      header.off('keyup', 'input').on('keyup', 'input', ({currentTarget, keyCode}, obj) => {
+      UtilsFilterControl.getControlContainer().off('keyup', 'input').on('keyup', 'input', ({currentTarget, keyCode}, obj) => {
         // Simulate enter key action from clear button
         keyCode = obj ? obj.keyCode : keyCode
 
@@ -410,7 +418,7 @@ const UtilsFilterControl = {
         }, that.options.searchTimeOut)
       })
 
-      header.off('change', 'select').on('change', 'select', ({currentTarget, keyCode}) => {
+      UtilsFilterControl.getControlContainer().off('change', 'select').on('change', 'select', ({currentTarget, keyCode}) => {
         if (that.options.searchOnEnterKey && keyCode !== 13) {
           return
         }
@@ -445,13 +453,13 @@ const UtilsFilterControl = {
         }, 1)
       })
 
-      if (header.find('.date-filter-control').length > 0) {
-        $.each(that.columns, (i, { filterControl, field, filterDatepickerOptions }) => {
+      if (UtilsFilterControl.getControlContainer().find('.date-filter-control').length > 0) {
+        $.each(that.columns, (i, {filterControl, field, filterDatepickerOptions}) => {
           if (
             filterControl !== undefined &&
             filterControl.toLowerCase() === 'datepicker'
           ) {
-            header
+            UtilsFilterControl.getControlContainer()
               .find(
                 `.date-filter-control.bootstrap-table-filter-control-${field}`
               )
@@ -467,13 +475,11 @@ const UtilsFilterControl = {
       }
 
       if (that.options.sidePagination !== 'server') {
-        header.find('[class*=\'bootstrap-table-filter-control\']').each((k, input) => {
-          $(input).trigger('change')
-        })
+        that.triggerSearch()
       }
 
     } else {
-      header.find('.filterControl').hide()
+      UtilsFilterControl.getControlContainer().find('.filterControl').hide()
     }
   },
   getDirectionOfSelectOptions (_alignment) {
@@ -533,30 +539,27 @@ $.extend($.fn.bootstrapTable.defaults, {
   },
   alignmentSelectControlOptions: undefined,
   filterTemplate: {
-    input (that, field, isVisible, placeholder, value) {
+    input (that, field, placeholder, value) {
       return Utils.sprintf(
-        '<input type="text" class="form-control bootstrap-table-filter-control-%s" style="width: 100%; visibility: %s" placeholder="%s" value="%s">',
+        '<input type="text" class="form-control bootstrap-table-filter-control-%s" style="width: 100%;" placeholder="%s" value="%s">',
         field,
-        isVisible,
         'undefined' === typeof placeholder ? '' : placeholder,
         'undefined' === typeof value ? '' : value
       )
     },
-    select ({ options }, field, isVisible) {
+    select ({options}, field) {
       return Utils.sprintf(
-        '<select class="form-control bootstrap-table-filter-control-%s" style="width: 100%; visibility: %s" dir="%s"></select>',
+        '<select class="form-control bootstrap-table-filter-control-%s" style="width: 100%;" dir="%s"></select>',
         field,
-        isVisible,
         UtilsFilterControl.getDirectionOfSelectOptions(
           options.alignmentSelectControlOptions
         )
       )
     },
-    datepicker (that, field, isVisible, value) {
+    datepicker (that, field, value) {
       return Utils.sprintf(
-        '<input type="text" class="form-control date-filter-control bootstrap-table-filter-control-%s" style="width: 100%; visibility: %s" value="%s">',
+        '<input type="text" class="form-control date-filter-control bootstrap-table-filter-control-%s" style="width: 100%;" value="%s">',
         field,
-        isVisible,
         'undefined' === typeof value ? '' : value
       )
     }
@@ -603,6 +606,7 @@ $.fn.bootstrapTable.methods.push('clearFilterControl')
 
 $.BootstrapTable = class extends $.BootstrapTable {
   init () {
+    UtilsFilterControl.bootstrapTableInstance = this
     // Make sure that the filterControl option is set
     if (this.options.filterControl) {
       const that = this
@@ -619,19 +623,19 @@ $.BootstrapTable = class extends $.BootstrapTable {
 
           // Avoid recreate the controls
           if (
-            that.$tableHeader.find('select').length > 0 ||
-            that.$tableHeader.find('input').length > 0
+            UtilsFilterControl.getControlContainer().find('select').length > 0 ||
+            UtilsFilterControl.getControlContainer().find('input').length > 0
           ) {
             return
           }
 
-          UtilsFilterControl.createControls(that, that.$tableHeader)
+          UtilsFilterControl.createControls(that, UtilsFilterControl.getControlContainer())
         })
         .on('post-header.bs.table', () => {
           UtilsFilterControl.setValues(that)
         })
         .on('post-body.bs.table', () => {
-          if (that.options.height) {
+          if (that.options.height && !that.options.filterControlContainer) {
             UtilsFilterControl.fixHeaderCSS(that)
           }
           this.$tableLoading.css('top', this.$header.outerHeight() + 1)
@@ -656,8 +660,9 @@ $.BootstrapTable = class extends $.BootstrapTable {
     if (!this.options.filterControl) {
       return
     }
-    UtilsFilterControl.createControls(this, this.$header)
+    UtilsFilterControl.createControls(this, UtilsFilterControl.getControlContainer())
   }
+
   initBody () {
     super.initBody()
 
@@ -695,7 +700,7 @@ $.BootstrapTable = class extends $.BootstrapTable {
           if (fval === '') {
             itemIsExpected.push(true)
           } else {
-            // Fix #142: search use formated data
+            // Fix #142: search use formatted data
             if (thisColumn && thisColumn.searchFormatter) {
               value = $.fn.bootstrapTable.utils.calculateObjectValue(
                 that.header,
@@ -823,7 +828,7 @@ $.BootstrapTable = class extends $.BootstrapTable {
       if (controls.length > 0) {
         this.filterColumnsPartial = {}
         $(controls[0]).trigger(
-          controls[0].tagName === 'INPUT' ? 'keyup' : 'change', { keyCode: 13 }
+          controls[0].tagName === 'INPUT' ? 'keyup' : 'change', {keyCode: 13}
         )
       } else {
         return
@@ -847,7 +852,7 @@ $.BootstrapTable = class extends $.BootstrapTable {
           )
         )
         if (sorter.length > 0) {
-          that.onSort({ type: 'keypress', currentTarget: sorter })
+          that.onSort({type: 'keypress', currentTarget: sorter})
           $(sorter)
             .find('.sortable')
             .trigger('click')
@@ -857,10 +862,9 @@ $.BootstrapTable = class extends $.BootstrapTable {
   }
 
   triggerSearch () {
-    const header = UtilsFilterControl.getCurrentHeader(this)
-    const searchControls = UtilsFilterControl.getCurrentSearchControls(this)
+    const searchControls = UtilsFilterControl.getSearchControls(this)
 
-    header.find(searchControls).each(function () {
+    searchControls.each(function () {
       const el = $(this)
       if (el.is('select')) {
         el.change()
@@ -875,13 +879,12 @@ $.BootstrapTable = class extends $.BootstrapTable {
       this.options.disableControlWhenSearch &&
       this.options.sidePagination === 'server'
     ) {
-      const header = UtilsFilterControl.getCurrentHeader(this)
-      const searchControls = UtilsFilterControl.getCurrentSearchControls(this)
+      const searchControls = UtilsFilterControl.getSearchControls(this)
 
       if (!enable) {
-        header.find(searchControls).prop('disabled', 'disabled')
+        searchControls.prop('disabled', 'disabled')
       } else {
-        header.find(searchControls).removeProp('disabled')
+        searchControls.removeProp('disabled')
       }
     }
   }