Completed
Push — master ( a503b2...32dcc3 )
by Jonathan
23:20 queued 10:26
created

datatable.js ➔ getInitialSearch   B

Complexity

Conditions 7
Paths 2

Size

Total Lines 26
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 14
nc 2
nop 0
dl 0
loc 26
rs 8
c 0
b 0
f 0
1
import 'datatables.net-bs';
2
import 'datatables.net-buttons-bs';
3
import 'datatables.net-buttons/js/buttons.colVis';
4
// import 'datatables.net-colreorder';
5
import 'datatables.net-fixedcolumns';
6
import 'datatables.net-responsive-bs';
7
import 'datatables.net-select';
8
import { sprintf } from 'sprintf-js'
9
import { Link } from './link'
10
11
export class Datatable {
12
    /**
13
     * Init Datatable configuration
14
     * @param {Element} element
15
     */
16
    init(element) {
17
        let linkManager = new Link(false)
18
19
        this.table = $(element).DataTable({
20
            dom: 'Brtp',
21
            autoWidth: false, // Else the width is not refreshed on window resize
22
            responsive: true,
23
            colReorder: true,
24
            serverSide: true,
25
            ajax: {
26
                url: this.url,
27
                type: "POST"
28
            },
29
            pageLength: this.getInitialPageLength(),
30
            order: this.getInitialOrder(),
31
            columnDefs: this.getDatatableColumnDefs(element),
32
            createdRow: (row, data, index) => {
0 ignored issues
show
Unused Code introduced by
The parameter index is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
33
                // Go to detail view when you click on a row
34
                $('td:gt(0):lt(-1)', row).click(() => {
35
                    document.location.href = sprintf(this.rowUrl, data.id);
36
                })
37
38
                // Init click listener on delete button
39
                linkManager.initClickListener(row)
40
41
                // Init click listener on the row if a callback is defined
42
                if (typeof this.rowClickCallback !== 'undefined') {
43
                    $(row).on('click', (event) => {
44
                        this.rowClickCallback(event, this.table, data)
45
                    })
46
                }
47
            },
48
            buttons: [
49
                {
50
                    extend: 'colvis',
51
                    columns: ':gt(0):lt(-1)'
52
                }
53
            ],
54
            language: {
55
                paginate: {
56
                    previous: '<',
57
                    next: '>'
58
                }
59
            },
60
            aoSearchCols: this.getInitialSearch()
61
        });
62
63
        // Config buttons
64
        this.configButtons()
65
66
        // Init search
67
        this.initDatatableColumnSearch()
68
    }
69
70
    /**
71
     * Make datatable columns from filter.
72
     * @param {Element} element
73
     * @return {array}
74
     */
75
    getDatatableColumnDefs(element) {
76
        let selector = new UccelloUitypeSelector.UitypeSelector() // UccelloUitypeSelector is replaced automaticaly by webpack. See webpack.mix.js
0 ignored issues
show
Bug introduced by
The variable UccelloUitypeSelector seems to be never declared. If this is a global, consider adding a /** global: UccelloUitypeSelector */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
77
78
        let datatableColumns = [];
79
80
        // Add first column
81
        datatableColumns.push({
82
            targets: 0,
83
            data: null,
84
            defaultContent: '',
85
            orderable: false,
86
            searchable: false
87
        })
88
89
        // Add all filter columns
90
        for (let i in this.columns) {
91
            let column = this.columns[i]
92
            datatableColumns.push({
93
                targets: parseInt(i) + 1, // Force integer
94
                data: column.name,
95
                createdCell: (td, cellData, rowData, row, col) => {
96
                    selector.get(column.uitype).createdCell(column, td, cellData, rowData, row, col)
97
                },
98
                visible: column.visible
99
            });
100
        }
101
102
        // Add last column (action buttons)
103
        datatableColumns.push({
104
            targets: this.columns.length + 1,
105
            data: null,
106
            defaultContent: '',
107
            orderable: false,
108
            searchable: false,
109
            createdCell: this.getActionsColumnCreatedCell(element)
110
        })
111
112
        return datatableColumns;
113
    }
114
115
    /**
116
     * Initialize initial columns search, according to selected filter conditions
117
     * @return {array}
118
     */
119
    getInitialSearch() {
120
        let search = []
121
122
        if (this.selectedFilter && this.selectedFilter.conditions && this.selectedFilter.conditions.search) {
123
            // First column
124
            search.push(null)
125
126
            for (let i in this.columns) {
127
                let value = null
0 ignored issues
show
Unused Code introduced by
The assignment to value seems to be never used. If you intend to free memory here, this is not necessary since the variable leaves the scope anyway.
Loading history...
128
129
                let column =  this.columns[i]
130
                value = typeof this.selectedFilter.conditions.search[column.name] !== 'undefined' ? this.selectedFilter.conditions.search[column.name] : null
131
132
                if (value) {
133
                    search.push({sSearch: value})
134
                } else {
135
                    search.push(null)
136
                }
137
            }
138
139
            // Last column
140
            search.push(null)
141
        }
142
143
        return search
144
    }
145
146
    /**
147
     * Get initial order
148
     * @return {array}
149
     */
150
    getInitialOrder() {
151
        let order = [[1, 'asc']] // Default
152
        if (this.selectedFilter && this.selectedFilter.data && this.selectedFilter.data.order) {
153
            order = this.selectedFilter.data.order
154
        }
155
156
        return order
157
    }
158
159
    /**
160
     * Get initial page length
161
     * @return {integer}
162
     */
163
    getInitialPageLength() {
164
        let length = 15 // Default
165
        if (this.selectedFilter && this.selectedFilter.data && this.selectedFilter.data.length) {
166
            length = this.selectedFilter.data.length
167
        }
168
169
        return length
170
    }
171
172
    /**
173
     * Make datatable action column.
174
     * @param {Element} element
175
     */
176
    getActionsColumnCreatedCell(element) {
177
        return (td, cellData, rowData, row, col) => {
0 ignored issues
show
Unused Code introduced by
The parameter row is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter col is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
178
            var dataTableContainer = $(element).parents('.dataTable-container:first');
179
180
            // Copy buttons from template
181
            let editButton = $(".template .edit-btn", dataTableContainer).clone().tooltip().appendTo($(td))
182
            let deleteButton = $(".template .delete-btn", dataTableContainer).clone().tooltip().appendTo($(td))
183
184
            // Config edit link url
185
            if (editButton.attr('href')) {
186
                let editLink = editButton.attr('href').replace('RECORD_ID', rowData.id)
187
                editButton.attr('href', editLink)
188
            }
189
190
            // Config delete link url
191
            if (deleteButton.attr('href')) {
192
                let deleteLink = deleteButton.attr('href').replace('RECORD_ID', rowData.id)
193
194
                // if relation_id is defined, replace RELATION_ID
195
                if (rowData.relation_id) {
196
                    deleteLink = deleteLink.replace('RELATION_ID', rowData.relation_id)
197
                }
198
199
                deleteButton.attr('href', deleteLink)
200
            }
201
        }
202
    }
203
204
    /**
205
     * Config buttons to display them correctly
206
     */
207
    configButtons() {
208
        let table = this.table
209
210
        // Get buttons container
211
        let buttonsContainer = table.buttons().container()
212
213
        // Retrieve container
214
        let dataTableContainer = buttonsContainer.parents('.dataTable-container:first');
215
216
        // Remove old buttons if datatable was initialized before (e.g. in related list selection modal)
217
        $('.action-buttons .buttons-colvis', dataTableContainer).remove()
218
219
        // Display mini buttons (related lists)
220
        if (dataTableContainer.data('button-size') === 'mini') {
221
222
            $('button', buttonsContainer).each((index, element) => {
223
                // Get content and use it as a title
224
                let title = $('span', element).html()
225
226
                // Add icon and effect
227
                $(element)
228
                    .addClass('btn-circle waves-effect waves-circle waves-float bg-primary')
229
                    .removeClass('btn-default')
230
                    .html('<i class="material-icons">view_column</i>')
231
                    .attr('title', title)
232
                    .tooltip({
233
                        placement: 'top'
234
                    })
235
236
                // Move button
237
                $(element).prependTo($('.action-buttons', dataTableContainer))
238
            })
239
        }
240
        // Display classic buttons (list)
241
        else {
242
            // Move buttons
243
            buttonsContainer.appendTo($('.action-buttons', dataTableContainer));
244
245
            $('button', buttonsContainer).each((index, element) => {
246
                // Replace <span>...</span> by its content
247
                $(element).html($('span', element).html())
248
249
                // Add icon and effect
250
                $(element).addClass('icon-right waves-effect bg-primary')
251
                $(element).removeClass('btn-default')
252
                $(element).append('<i class="material-icons">keyboard_arrow_down</i>')
253
            })
254
255
            // Move to the right
256
            $('.action-buttons .btn-group', dataTableContainer).addClass('pull-right')
257
        }
258
259
        // Change records number
260
        $('ul#items-number a').on('click', (event) => {
261
            let recordsNumber = $(event.target).data('number')
262
            $('strong.records-number').text(recordsNumber)
263
            table.page.len(recordsNumber).draw()
264
        })
265
266
        $(".dataTables_paginate", dataTableContainer).appendTo($('.paginator', dataTableContainer))
267
    }
268
269
    /**
270
     * Config column search.
271
     */
272
    initDatatableColumnSearch()
273
    {
274
        let table = this.table
275
276
        let timer = 0
277
278
        // Config each column
279
        table.columns().every(function (index) {
280
            let column = table.column(index)
281
282
            // Event listener to launch search
283
            $('input, select', this.header()).on('keyup change', function() {
284
                let value = $(this).val()
285
286
                if (value !== '') {
287
                    $('.clear-search').show()
288
                }
289
290
                if (column.search() !== value) {
291
                    clearTimeout(timer)
292
                    timer = setTimeout(() => {
293
                        column.search(value)
294
                        table.draw()
295
                    }, 500)
296
                }
297
            })
298
        })
299
300
        // Add clear search button listener
301
        this.addClearSearchButtonListener()
302
    }
303
304
    /**
305
     * Clear datatable search
306
     */
307
    addClearSearchButtonListener()
308
    {
309
        let table = this.table
310
311
        $('.actions-column .clear-search').on('click', (event) => {
312
            // Clear all search fields
313
            $('.dataTable thead input, .dataTable thead select').val(null).change()
314
315
            // Update columns
316
            table.columns().every(function (index) {
317
                let column = table.column(index)
318
                column.search('')
319
            })
320
321
            // Disable clear search button
322
            $(event.currentTarget).hide()
323
324
            // Update data
325
            table.draw()
326
        })
327
    }
328
}