| /** | 
|  * @author: Dennis Hernández | 
|  * @webSite: http://djhvscf.github.io/Blog | 
|  * @version: v1.0.0 | 
|  */ | 
|   | 
| !function ($) { | 
|   | 
|     'use strict'; | 
|   | 
|     var sprintf = $.fn.bootstrapTable.utils.sprintf; | 
|   | 
|     var addOptionToSelectControl = function (selectControl, value, text) { | 
|         value = $.trim(value); | 
|         selectControl = $(selectControl.get(selectControl.length - 1)); | 
|         if (existOptionInSelectControl(selectControl, value)) { | 
|             selectControl.append($("<option></option>") | 
|                 .attr("value", value) | 
|                 .text($('<div />').html(text).text())); | 
|   | 
|             // Sort it. Not overly efficient to do this here | 
|             var $opts = selectControl.find('option:gt(0)'); | 
|             $opts.sort(function (a, b) { | 
|                 a = $(a).text().toLowerCase(); | 
|                 b = $(b).text().toLowerCase(); | 
|                 if ($.isNumeric(a) && $.isNumeric(b)) { | 
|                     // Convert numerical values from string to float. | 
|                     a = parseFloat(a); | 
|                     b = parseFloat(b); | 
|                 } | 
|                 return a > b ? 1 : a < b ? -1 : 0; | 
|             }); | 
|   | 
|             selectControl.find('option:gt(0)').remove(); | 
|             selectControl.append($opts); | 
|         } | 
|     }; | 
|   | 
|     var existOptionInSelectControl = function (selectControl, value) { | 
|         var options = selectControl.get(selectControl.length - 1).options; | 
|         for (var i = 0; i < options.length; i++) { | 
|             if (options[i].value === value.toString()) { | 
|                 //The value is not valid to add | 
|                 return false; | 
|             } | 
|         } | 
|   | 
|         //If we get here, the value is valid to add | 
|         return true; | 
|     }; | 
|   | 
|     var fixHeaderCSS = function (that) { | 
|         that.$tableHeader.css('height', '77px'); | 
|     }; | 
|   | 
|     var getCurrentHeader = function (that) { | 
|         var header = that.$header; | 
|         if (that.options.height) { | 
|             header = that.$tableHeader; | 
|         } | 
|   | 
|         return header; | 
|     }; | 
|   | 
|     var getCurrentSearchControls = function (that) { | 
|         var searchControls = 'select, input'; | 
|         if (that.options.height) { | 
|             searchControls = 'table select, table input'; | 
|         } | 
|   | 
|         return searchControls; | 
|     }; | 
|   | 
|     var copyValues = function (that) { | 
|         var header = getCurrentHeader(that), | 
|             searchControls = getCurrentSearchControls(that); | 
|   | 
|         that.options.valuesFilterControl = []; | 
|   | 
|         header.find(searchControls).each(function () { | 
|             that.options.valuesFilterControl.push( | 
|                 { | 
|                     field: $(this).closest('[data-field]').data('field'), | 
|                     value: $(this).val() | 
|                 }); | 
|         }); | 
|     }; | 
|   | 
|     var setValues = function(that) { | 
|         var field = null, | 
|             result = [], | 
|             header = getCurrentHeader(that), | 
|             searchControls = getCurrentSearchControls(that); | 
|   | 
|         if (that.options.valuesFilterControl.length > 0) { | 
|             header.find(searchControls).each(function (index, ele) { | 
|                 field = $(this).closest('[data-field]').data('field'); | 
|                 result = $.grep(that.options.valuesFilterControl, function (valueObj) { | 
|                     return valueObj.field === field; | 
|                 }); | 
|   | 
|                 if (result.length > 0) { | 
|                     $(this).val(result[0].value); | 
|                 } | 
|             }); | 
|         } | 
|     }; | 
|   | 
|     var collectBootstrapCookies = function cookiesRegex() { | 
|         var cookies = [], | 
|             foundCookies = document.cookie.match(/(?:bs.table.)(\w*)/g); | 
|   | 
|         if (foundCookies) { | 
|             $.each(foundCookies, function (i, cookie) { | 
|                 if (/./.test(cookie)) { | 
|                     cookie = cookie.split(".").pop(); | 
|                 } | 
|   | 
|                 if ($.inArray(cookie, cookies) === -1) { | 
|                     cookies.push(cookie); | 
|                 } | 
|             }); | 
|             return cookies; | 
|         } | 
|     }; | 
|   | 
|     var initFilterSelectControls = function (bootstrapTable) { | 
|         var data = bootstrapTable.options.data, | 
|             itemsPerPage = bootstrapTable.pageTo < bootstrapTable.options.data.length ? bootstrapTable.options.data.length : bootstrapTable.pageTo, | 
|   | 
|             isColumnSearchableViaSelect = function (column) { | 
|                 return column.filterControl && column.filterControl.toLowerCase() === 'select' && column.searchable; | 
|             }, | 
|   | 
|             isFilterDataNotGiven = function (column) { | 
|                 return column.filterData === undefined || column.filterData.toLowerCase() === 'column'; | 
|             }, | 
|   | 
|             hasSelectControlElement = function (selectControl) { | 
|                 return selectControl && selectControl.length > 0; | 
|             }; | 
|   | 
|         for (var i = bootstrapTable.pageFrom - 1; i < bootstrapTable.pageTo; i++) { | 
|   | 
|             $.each(bootstrapTable.header.fields, function (j, field) { | 
|                 var column = bootstrapTable.columns[$.fn.bootstrapTable.utils.getFieldIndex(bootstrapTable.columns, field)], | 
|                     selectControl = $('.' + column.field); | 
|   | 
|   | 
|                 if (isColumnSearchableViaSelect(column) && isFilterDataNotGiven(column) && hasSelectControlElement(selectControl)) { | 
|                     if (selectControl.get(selectControl.length - 1).options.length === 0) { | 
|                         //Added the default option | 
|                         addOptionToSelectControl(selectControl, '', ''); | 
|                     } | 
|   | 
|                     //Added a new value | 
|                     var fieldValue = data[i][field], | 
|                         formattedValue = $.fn.bootstrapTable.utils.calculateObjectValue(bootstrapTable.header, bootstrapTable.header.formatters[j], [fieldValue, data[i], i], fieldValue); | 
|   | 
|                     addOptionToSelectControl(selectControl, fieldValue, formattedValue); | 
|                 } | 
|             }); | 
|         } | 
|   | 
|     } | 
|   | 
|     var createControls = function (that, header) { | 
|         var addedFilterControl = false, | 
|             isVisible, | 
|             html, | 
|             timeoutId = 0; | 
|   | 
|         $.each(that.columns, function (i, column) { | 
|             isVisible = 'hidden'; | 
|             html = []; | 
|   | 
|             if (!column.visible) { | 
|                 return; | 
|             } | 
|   | 
|             if (!column.filterControl) { | 
|                 html.push('<div style="height: 34px;"></div>'); | 
|             } else { | 
|                 html.push('<div style="margin: 0 2px 2px 2px;" class="filterControl">'); | 
|   | 
|                 var 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)); | 
|                 } | 
|             } | 
|   | 
|             $.each(header.children().children(), function (i, tr) { | 
|                 tr = $(tr); | 
|                 if (tr.data('field') === column.field) { | 
|                     tr.find('.fht-cell').append(html.join('')); | 
|                     return false; | 
|                 } | 
|             }); | 
|             if (column.filterData !== undefined && column.filterData.toLowerCase() !== 'column') { | 
|                 var filterDataType = column.filterData.substring(0, 3); | 
|                 var filterDataSource = column.filterData.substring(4, column.filterData.length); | 
|                 var selectControl = $('.' + column.field); | 
|                 addOptionToSelectControl(selectControl, '', ''); | 
|   | 
|                 switch (filterDataType) { | 
|                     case 'url': | 
|                         $.ajax({ | 
|                             url: filterDataSource, | 
|                             dataType: 'json', | 
|                             success: function (data) { | 
|                                 $.each(data, function (key, value) { | 
|                                     addOptionToSelectControl(selectControl, key, value); | 
|                                 }); | 
|                             } | 
|                         }); | 
|                         break; | 
|                     case 'var': | 
|                         var variableValues = window[filterDataSource]; | 
|                         for (var key in variableValues) { | 
|                             addOptionToSelectControl(selectControl, key, variableValues[key]); | 
|                         } | 
|                         break; | 
|                 } | 
|             } | 
|         }); | 
|   | 
|         if (addedFilterControl) { | 
|             header.off('keyup', 'input').on('keyup', 'input', function (event) { | 
|                 clearTimeout(timeoutId); | 
|                 timeoutId = setTimeout(function () { | 
|                     that.onColumnSearch(event); | 
|                 }, that.options.searchTimeOut); | 
|             }); | 
|   | 
|             header.off('change', 'select').on('change', 'select', function (event) { | 
|                 clearTimeout(timeoutId); | 
|                 timeoutId = setTimeout(function () { | 
|                     that.onColumnSearch(event); | 
|                 }, that.options.searchTimeOut); | 
|             }); | 
|   | 
|             header.off('mouseup', 'input').on('mouseup', 'input', function (event) { | 
|                 var $input = $(this), | 
|                 oldValue = $input.val(); | 
|   | 
|                 if (oldValue === "") { | 
|                     return; | 
|                 } | 
|   | 
|                 setTimeout(function(){ | 
|                     var newValue = $input.val(); | 
|   | 
|                     if (newValue === "") { | 
|                         clearTimeout(timeoutId); | 
|                         timeoutId = setTimeout(function () { | 
|                             that.onColumnSearch(event); | 
|                         }, that.options.searchTimeOut); | 
|                     } | 
|                 }, 1); | 
|             }); | 
|   | 
|             if (header.find('.date-filter-control').length > 0) { | 
|                 $.each(that.columns, function (i, column) { | 
|                     if (column.filterControl !== undefined && column.filterControl.toLowerCase() === 'datepicker') { | 
|                         header.find('.date-filter-control.' + column.field).datepicker(column.filterDatepickerOptions) | 
|                             .on('changeDate', function (e) { | 
|                                 //Fired the keyup event | 
|                                 $(e.currentTarget).keyup(); | 
|                             }); | 
|                     } | 
|                 }); | 
|             } | 
|         } else { | 
|             header.find('.filterControl').hide(); | 
|         } | 
|     }; | 
|   | 
|     var getDirectionOfSelectOptions = function (alignment) { | 
|         alignment = alignment === undefined ? 'left' : alignment.toLowerCase(); | 
|   | 
|         switch (alignment) { | 
|             case 'left': | 
|                 return 'ltr'; | 
|             case 'right': | 
|                 return 'rtl'; | 
|             case 'auto': | 
|                 return 'auto'; | 
|             default: | 
|                 return 'ltr' | 
|         } | 
|     }; | 
|   | 
|     $.extend($.fn.bootstrapTable.defaults, { | 
|         filterControl: false, | 
|         onColumnSearch: function (field, text) { | 
|             return false; | 
|         }, | 
|         filterShowClear: false, | 
|         alignmentSelectControlOptions: undefined, | 
|         //internal variables | 
|         valuesFilterControl: [], | 
|         filterTemplate: { | 
|             input: function (that, field, isVisible) { | 
|                 return sprintf('<input  type="text" class="form-control %s" style="width: 100%; visibility: %s">', field, isVisible); | 
|             }, | 
|             select: function (that, field, isVisible) { | 
|                 return sprintf('<select class="%s form-control" style="width: 100%; visibility: %s" dir="%s"></select>', | 
|                     field, isVisible, getDirectionOfSelectOptions(that.options.alignmentSelectControlOptions)) | 
|             }, | 
|             datepicker: function (that, field, isVisible) { | 
|                 return sprintf('<input  type="text" class="date-filter-control %s form-control" style="width: 100%; visibility: %s">', field, isVisible); | 
|             } | 
|         } | 
|     }); | 
|   | 
|     $.extend($.fn.bootstrapTable.COLUMN_DEFAULTS, { | 
|         filterControl: undefined, | 
|         filterData: undefined, | 
|         filterDatepickerOptions: undefined, | 
|         filterStrictSearch: false | 
|     }); | 
|   | 
|     $.extend($.fn.bootstrapTable.Constructor.EVENTS, { | 
|         'column-search.bs.table': 'onColumnSearch' | 
|     }); | 
|   | 
|     $.extend($.fn.bootstrapTable.defaults.icons, { | 
|         clear: 'glyphicon-trash icon-clear' | 
|     }); | 
|   | 
|     var BootstrapTable = $.fn.bootstrapTable.Constructor, | 
|         _init = BootstrapTable.prototype.init, | 
|         _initToolbar = BootstrapTable.prototype.initToolbar, | 
|         _initHeader = BootstrapTable.prototype.initHeader, | 
|         _initBody = BootstrapTable.prototype.initBody, | 
|         _initSearch = BootstrapTable.prototype.initSearch; | 
|   | 
|     BootstrapTable.prototype.init = function () { | 
|         //Make sure that the filterControl option is set | 
|         if (this.options.filterControl) { | 
|             var that = this; | 
|             //Make sure that the internal variables are set correctly | 
|             this.options.valuesFilterControl = []; | 
|   | 
|             this.$el.on('reset-view.bs.table', function () { | 
|                 //Create controls on $tableHeader if the height is set | 
|                 if (!that.options.height) { | 
|                     return; | 
|                 } | 
|   | 
|                 //Avoid recreate the controls | 
|                 if (that.$tableHeader.find('select').length > 0 || that.$tableHeader.find('input').length > 0) { | 
|                     return; | 
|                 } | 
|   | 
|                 createControls(that, that.$tableHeader); | 
|             }).on('post-header.bs.table', function () { | 
|                 setValues(that); | 
|             }).on('post-body.bs.table', function () { | 
|                 if (that.options.height) { | 
|                     fixHeaderCSS(that); | 
|                 } | 
|             }).on('column-switch.bs.table', function() { | 
|                 setValues(that); | 
|             }); | 
|         } | 
|         _init.apply(this, Array.prototype.slice.apply(arguments)); | 
|     }; | 
|   | 
|     $.extend($.fn.bootstrapTable.locales, { | 
|         formatClearFilters: function () { | 
|             return 'Clear Filters'; | 
|         } | 
|     }); | 
|     $.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales); | 
|   | 
|     BootstrapTable.prototype.initToolbar = function () { | 
|         if ((!this.showToolbar) && (this.options.filterControl)) { | 
|             this.showToolbar = this.options.filterControl; | 
|         } | 
|   | 
|         _initToolbar.apply(this, Array.prototype.slice.apply(arguments)); | 
|   | 
|         if (this.options.filterControl && this.options.filterShowClear) { | 
|             var $btnGroup = this.$toolbar.find('>.btn-group'), | 
|                 $btnClear = $btnGroup.find('div.export'); | 
|   | 
|             if (!$btnClear.length) { | 
|               $btnClear = $([ | 
|                     '<button class="btn btn-default" ', | 
|                     sprintf('type="button" title="%s">', this.options.formatClearFilters()), | 
|                     sprintf('<i class="%s %s"></i> ', this.options.iconsPrefix, this.options.icons.clear), | 
|                     '</button>', | 
|                     '</ul>'].join('')).appendTo($btnGroup); | 
|   | 
|                 $btnClear.off('click').on('click', $.proxy(this.clearFilterControl, this)); | 
|             } | 
|         } | 
|     }; | 
|   | 
|     BootstrapTable.prototype.initHeader = function () { | 
|         _initHeader.apply(this, Array.prototype.slice.apply(arguments)); | 
|   | 
|         if (!this.options.filterControl) { | 
|             return; | 
|         } | 
|         createControls(this, this.$header); | 
|     }; | 
|   | 
|     BootstrapTable.prototype.initBody = function () { | 
|         _initBody.apply(this, Array.prototype.slice.apply(arguments)); | 
|   | 
|         initFilterSelectControls(this); | 
|     }; | 
|   | 
|     BootstrapTable.prototype.initSearch = function () { | 
|         _initSearch.apply(this, Array.prototype.slice.apply(arguments)); | 
|   | 
|         if (!this.options.sidePagination === 'server') { | 
|             return; | 
|         } | 
|   | 
|         var that = this; | 
|         var fp = $.isEmptyObject(this.filterColumnsPartial) ? null : this.filterColumnsPartial; | 
|   | 
|         //Check partial column filter | 
|         this.data = fp ? $.grep(this.data, function (item, i) { | 
|             for (var key in fp) { | 
|                 var thisColumn = that.columns[$.fn.bootstrapTable.utils.getFieldIndex(that.columns, key)]; | 
|                 var fval = fp[key].toLowerCase(); | 
|                 var value = item[key]; | 
|                  | 
|                 // Fix #142: search use formated data | 
|                 if (thisColumn && thisColumn.searchFormatter) { | 
|                     value = $.fn.bootstrapTable.utils.calculateObjectValue(that.header, | 
|                     that.header.formatters[$.inArray(key, that.header.fields)], | 
|                     [value, item, i], value); | 
|                 } | 
|   | 
|                 if (thisColumn.filterStrictSearch) { | 
|                     if (!($.inArray(key, that.header.fields) !== -1 && | 
|                         (typeof value === 'string' || typeof value === 'number') && | 
|                         value.toString().toLowerCase() === fval.toString().toLowerCase())) { | 
|                         return false; | 
|                     } | 
|                 } | 
|                 else { | 
|                     if (!($.inArray(key, that.header.fields) !== -1 && | 
|                         (typeof value === 'string' || typeof value === 'number') && | 
|                         (value + '').toLowerCase().indexOf(fval) !== -1)) { | 
|                         return false; | 
|                     } | 
|                 } | 
|             } | 
|             return true; | 
|         }) : this.data; | 
|     }; | 
|   | 
|     BootstrapTable.prototype.onColumnSearch = function (event) { | 
|         copyValues(this); | 
|         var text = $.trim($(event.currentTarget).val()); | 
|         var $field = $(event.currentTarget).closest('[data-field]').data('field'); | 
|   | 
|         if ($.isEmptyObject(this.filterColumnsPartial)) { | 
|             this.filterColumnsPartial = {}; | 
|         } | 
|         if (text) { | 
|             this.filterColumnsPartial[$field] = text; | 
|         } else { | 
|             delete this.filterColumnsPartial[$field]; | 
|         } | 
|   | 
|         this.options.pageNumber = 1; | 
|         this.onSearch(event); | 
|         this.updatePagination(); | 
|         this.trigger('column-search', $field, text); | 
|     }; | 
|   | 
|     BootstrapTable.prototype.clearFilterControl = function () { | 
|         if (this.options.filterControl && this.options.filterShowClear) { | 
|             var that = this, | 
|                 cookies = collectBootstrapCookies(), | 
|                 header = getCurrentHeader(that), | 
|                 table = header.closest('table'), | 
|                 controls = header.find(getCurrentSearchControls(that)), | 
|                 search = that.$toolbar.find('.search input'), | 
|                 timeoutId = 0; | 
|   | 
|             $.each(that.options.valuesFilterControl, function (i, item) { | 
|                 item.value = ''; | 
|             }); | 
|   | 
|             setValues(that); | 
|   | 
|             // Clear each type of filter if it exists. | 
|             // Requires the body to reload each time a type of filter is found because we never know | 
|             // which ones are going to be present. | 
|             if (controls.length > 0) { | 
|                 this.filterColumnsPartial = {}; | 
|                 $(controls[0]).trigger(controls[0].tagName === 'INPUT' ? 'keyup' : 'change'); | 
|             } | 
|   | 
|             if (search.length > 0) { | 
|                 that.resetSearch(); | 
|             } | 
|   | 
|             // use the default sort order if it exists. do nothing if it does not | 
|             if (that.options.sortName !== table.data('sortName') || that.options.sortOrder !== table.data('sortOrder')) { | 
|                 var sorter = sprintf(header.find('[data-field="%s"]', $(controls[0]).closest('table').data('sortName'))); | 
|                 that.onSort(table.data('sortName'), table.data('sortName')); | 
|                 $(sorter).find('.sortable').trigger('click'); | 
|             } | 
|   | 
|             // clear cookies once the filters are clean | 
|             clearTimeout(timeoutId); | 
|             timeoutId = setTimeout(function () { | 
|                 if (cookies && cookies.length > 0) { | 
|                     $.each(cookies, function (i, item) { | 
|                         that.deleteCookie(item); | 
|                     }); | 
|                 } | 
|             }, that.options.searchTimeOut); | 
|         } | 
|     }; | 
| }(jQuery); |