UNPKG

12.5 kBJavaScriptView Raw
1/**
2 * @author: aperez <aperez@datadec.es>
3 * @version: v2.0.0
4 *
5 * @update Dennis Hernández
6 * @update zhixin wen <wenzhixin2010@gmail.com>
7 */
8
9const Utils = $.fn.bootstrapTable.utils
10
11const theme = {
12 bootstrap3: {
13 icons: {
14 advancedSearchIcon: 'glyphicon-chevron-down'
15 },
16 classes: {},
17 html: {
18 modal: `
19 <div id="avdSearchModal_%s" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
20 <div class="modal-dialog modal-xs">
21 <div class="modal-content">
22 <div class="modal-header">
23 <button type="button" class="close" data-dismiss="modal" aria-label="Close">
24 <span aria-hidden="true">&times;</span>
25 </button>
26 <h4 class="modal-title">%s</h4>
27 </div>
28 <div class="modal-body modal-body-custom">
29 <div class="container-fluid" id="avdSearchModalContent_%s"
30 style="padding-right: 0px; padding-left: 0px;" >
31 </div>
32 </div>
33 <div class="modal-footer">
34 <button type="button" id="btnCloseAvd_%s" class="btn btn-%s">%s</button>
35 </div>
36 </div>
37 </div>
38 </div>
39 `
40 }
41 },
42 bootstrap4: {
43 icons: {
44 advancedSearchIcon: 'fa-chevron-down'
45 },
46 classes: {},
47 html: {
48 modal: `
49 <div id="avdSearchModal_%s" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
50 <div class="modal-dialog modal-xs">
51 <div class="modal-content">
52 <div class="modal-header">
53 <h4 class="modal-title">%s</h4>
54 <button type="button" class="close" data-dismiss="modal" aria-label="Close">
55 <span aria-hidden="true">&times;</span>
56 </button>
57 </div>
58 <div class="modal-body modal-body-custom">
59 <div class="container-fluid" id="avdSearchModalContent_%s"
60 style="padding-right: 0; padding-left: 0;" >
61 </div>
62 </div>
63 <div class="modal-footer">
64 <button type="button" id="btnCloseAvd_%s" class="btn btn-%s">%s</button>
65 </div>
66 </div>
67 </div>
68 </div>
69 `
70 }
71 },
72 bootstrap5: {
73 icons: {
74 advancedSearchIcon: 'bi-chevron-down'
75 },
76 classes: {
77 formGroup: 'mb-3'
78 },
79 html: {
80 modal: `
81 <div id="avdSearchModal_%s" class="modal fade" tabindex="-1" aria-labelledby="mySmallModalLabel" aria-hidden="true">
82 <div class="modal-dialog modal-xs">
83 <div class="modal-content">
84 <div class="modal-header">
85 <h5 class="modal-title">%s</h5>
86 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
87 </div>
88 <div class="modal-body modal-body-custom">
89 <div class="container-fluid" id="avdSearchModalContent_%s"
90 style="padding-right: 0; padding-left: 0;" >
91 </div>
92 </div>
93 <div class="modal-footer">
94 <button type="button" id="btnCloseAvd_%s" class="btn btn-%s">%s</button>
95 </div>
96 </div>
97 </div>
98 </div>
99 `
100 }
101 },
102 bulma: {
103 icons: {
104 advancedSearchIcon: 'fa-chevron-down'
105 },
106 classes: {},
107 html: {
108 modal: `
109 <div class="modal" id="avdSearchModal_%s">
110 <div class="modal-background"></div>
111 <div class="modal-card">
112 <header class="modal-card-head">
113 <p class="modal-card-title">%s</p>
114 <button class="delete" aria-label="close"></button>
115 </header>
116 <section class="modal-card-body" id="avdSearchModalContent_%s"></section>
117 <footer class="modal-card-foot">
118 <button class="button" id="btnCloseAvd_%s" data-close="btn btn-%s">%s</button>
119 </footer>
120 </div>
121 </div>
122 `
123 }
124 },
125 foundation: {
126 icons: {
127 advancedSearchIcon: 'fa-chevron-down'
128 },
129 classes: {},
130 html: {
131 modal: `
132 <div class="reveal" id="avdSearchModal_%s" data-reveal>
133 <h1>%s</h1>
134 <div id="avdSearchModalContent_%s">
135
136 </div>
137 <button class="close-button" data-close aria-label="Close modal" type="button">
138 <span aria-hidden="true">&times;</span>
139 </button>
140
141 <button id="btnCloseAvd_%s" class="%s" type="button">%s</button>
142 </div>
143 `
144 }
145 },
146 materialize: {
147 icons: {
148 advancedSearchIcon: 'expand_more'
149 },
150 classes: {},
151 html: {
152 modal: `
153 <div id="avdSearchModal_%s" class="modal">
154 <div class="modal-content">
155 <h4>%s</h4>
156 <div id="avdSearchModalContent_%s">
157
158 </div>
159 </div>
160 <div class="modal-footer">
161 <a href="javascript:void(0)"" id="btnCloseAvd_%s" class="modal-close waves-effect waves-green btn-flat %s">%s</a>
162 </div>
163 </div>
164 `
165 }
166 },
167 semantic: {
168 icons: {
169 advancedSearchIcon: 'fa-chevron-down'
170 },
171 classes: {},
172 html: {
173 modal: `
174 <div class="ui modal" id="avdSearchModal_%s">
175 <i class="close icon"></i>
176 <div class="header">
177 %s
178 </div>
179 <div class="image content ui form" id="avdSearchModalContent_%s"></div>
180 <div class="actions">
181 <div id="btnCloseAvd_%s" class="ui black deny button %s">%s</div>
182 </div>
183 </div>
184 `
185 }
186 }
187}[$.fn.bootstrapTable.theme]
188
189Object.assign($.fn.bootstrapTable.defaults, {
190 advancedSearch: false,
191 idForm: 'advancedSearch',
192 actionForm: '',
193 idTable: undefined,
194 // eslint-disable-next-line no-unused-vars
195 onColumnAdvancedSearch (field, text) {
196 return false
197 }
198})
199
200Object.assign($.fn.bootstrapTable.defaults.icons, {
201 advancedSearchIcon: theme.icons.advancedSearchIcon
202})
203
204Object.assign($.fn.bootstrapTable.events, {
205 'column-advanced-search.bs.table': 'onColumnAdvancedSearch'
206})
207
208Object.assign($.fn.bootstrapTable.locales, {
209 formatAdvancedSearch () {
210 return 'Advanced search'
211 },
212 formatAdvancedCloseButton () {
213 return 'Close'
214 }
215})
216
217Object.assign($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
218
219$.BootstrapTable = class extends $.BootstrapTable {
220 initToolbar () {
221 const o = this.options
222
223 this.showToolbar = this.showToolbar ||
224 o.search &&
225 o.advancedSearch &&
226 o.idTable
227
228 if (o.search && o.advancedSearch && o.idTable) {
229 this.buttons = Object.assign(this.buttons, {
230 advancedSearch: {
231 text: this.options.formatAdvancedSearch(),
232 icon: this.options.icons.advancedSearchIcon,
233 event: this.showAvdSearch,
234 attributes: {
235 'aria-label': this.options.formatAdvancedSearch(),
236 title: this.options.formatAdvancedSearch()
237 }
238 }
239 })
240 }
241
242 super.initToolbar()
243 }
244
245 showAvdSearch () {
246 const o = this.options
247 const modalSelector = `#avdSearchModal_${o.idTable}`
248
249 if ($(modalSelector).length <= 0) {
250 $('body').append(Utils.sprintf(theme.html.modal, o.idTable, o.formatAdvancedSearch(), o.idTable, o.idTable, o.buttonsClass, o.formatAdvancedCloseButton()))
251
252 let timeoutId = 0
253
254 $(`#avdSearchModalContent_${o.idTable}`).append(this.createFormAvd().join(''))
255
256 $(`#${o.idForm}`).off('keyup blur', 'input').on('keyup blur', 'input', e => {
257 if (o.sidePagination === 'server') {
258 this.onColumnAdvancedSearch(e)
259 } else {
260 clearTimeout(timeoutId)
261 timeoutId = setTimeout(() => {
262 this.onColumnAdvancedSearch(e)
263 }, o.searchTimeOut)
264 }
265 })
266
267 $(`#btnCloseAvd_${o.idTable}`).click(() => this.hideModal())
268
269 if ($.fn.bootstrapTable.theme === 'bulma') {
270 $(modalSelector).find('.delete').off('click').on('click', () => this.hideModal())
271 }
272
273 this.showModal()
274 } else {
275 this.showModal()
276 }
277 }
278
279 showModal () {
280 const modalSelector = `#avdSearchModal_${this.options.idTable}`
281
282 if ($.inArray($.fn.bootstrapTable.theme, ['bootstrap3', 'bootstrap4']) !== -1) {
283 $(modalSelector).modal()
284 } else if ($.fn.bootstrapTable.theme === 'bootstrap5') {
285 if (!this.toolbarModal) {
286 // eslint-disable-next-line no-undef
287 this.toolbarModal = new bootstrap.Modal(document.getElementById(`avdSearchModal_${this.options.idTable}`), {})
288 }
289 this.toolbarModal.show()
290 } else if ($.fn.bootstrapTable.theme === 'bulma') {
291 $(modalSelector).toggleClass('is-active')
292 } else if ($.fn.bootstrapTable.theme === 'foundation') {
293 if (!this.toolbarModal) {
294 // eslint-disable-next-line no-undef
295 this.toolbarModal = new Foundation.Reveal($(modalSelector))
296 }
297 this.toolbarModal.open()
298 } else if ($.fn.bootstrapTable.theme === 'materialize') {
299 $(modalSelector).modal()
300 $(modalSelector).modal('open')
301 } else if ($.fn.bootstrapTable.theme === 'semantic') {
302 $(modalSelector).modal('show')
303 }
304
305 }
306
307 hideModal () {
308 const $closeModalButton = $(`#avdSearchModal_${this.options.idTable}`)
309 const modalSelector = `#avdSearchModal_${this.options.idTable}`
310
311 if ($.inArray($.fn.bootstrapTable.theme, ['bootstrap3', 'bootstrap4']) !== -1) {
312 $closeModalButton.modal('hide')
313 } else if ($.fn.bootstrapTable.theme === 'bootstrap5') {
314 this.toolbarModal.hide()
315 } else if ($.fn.bootstrapTable.theme === 'bulma') {
316 $('html').toggleClass('is-clipped')
317 $(modalSelector).toggleClass('is-active')
318 } else if ($.fn.bootstrapTable.theme === 'foundation') {
319 this.toolbarModal.close()
320 } else if ($.fn.bootstrapTable.theme === 'materialize') {
321 $(modalSelector).modal('open')
322 } else if ($.fn.bootstrapTable.theme === 'semantic') {
323 $(modalSelector).modal('close')
324 }
325
326 if (this.options.sidePagination === 'server') {
327 this.options.pageNumber = 1
328 this.updatePagination()
329 this.trigger('column-advanced-search', this.filterColumnsPartial)
330 }
331 }
332
333
334 createFormAvd () {
335 const o = this.options
336 const html = [`<form class="form-horizontal" id="${o.idForm}" action="${o.actionForm}">`]
337
338 for (const column of this.columns) {
339 if (!column.checkbox && column.visible && column.searchable) {
340 html.push(`
341 <div class="form-group row ${theme.classes.formGroup || ''}">
342 <label class="col-sm-4 control-label">${column.title}</label>
343 <div class="col-sm-6">
344 <input type="text" class="form-control ${this.constants.classes.input}" name="${column.field}" placeholder="${column.title}" id="${column.field}">
345 </div>
346 </div>
347 `)
348 }
349 }
350
351 html.push('</form>')
352
353 return html
354 }
355
356 initSearch () {
357 super.initSearch()
358
359 if (!this.options.advancedSearch || this.options.sidePagination === 'server') {
360 return
361 }
362
363 const fp = $.isEmptyObject(this.filterColumnsPartial) ? null : this.filterColumnsPartial
364
365 this.data = fp ? this.data.filter((item, i) => {
366 for (const [key, v] of Object.entries(fp)) {
367 const fval = v.toLowerCase()
368 let value = item[key]
369 const index = this.header.fields.indexOf(key)
370
371 value = Utils.calculateObjectValue(this.header,
372 this.header.formatters[index], [value, item, i], value)
373
374 if (
375 !(index !== -1 &&
376 (typeof value === 'string' || typeof value === 'number') &&
377 `${value}`.toLowerCase().includes(fval))
378 ) {
379 return false
380 }
381 }
382 return true
383 }) : this.data
384 this.unsortedData = [...this.data]
385 }
386
387 onColumnAdvancedSearch (e) {
388 const text = $(e.currentTarget).val().trim()
389 const $field = $(e.currentTarget)[0].id
390
391 if ($.isEmptyObject(this.filterColumnsPartial)) {
392 this.filterColumnsPartial = {}
393 }
394 if (text) {
395 this.filterColumnsPartial[$field] = text
396 } else {
397 delete this.filterColumnsPartial[$field]
398 }
399
400 if (this.options.sidePagination !== 'server') {
401 this.options.pageNumber = 1
402 this.initSearch()
403 this.updatePagination()
404 this.trigger('column-advanced-search', $field, text)
405 }
406 }
407}