jqGrid.custom.js ➔ shift_select   F
last analyzed

Complexity

Conditions 17

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 8
dl 0
loc 12
rs 1.8
c 0
b 0
f 0
cc 17

How to fix   Complexity   

Complexity

Complex classes like jqGrid.custom.js ➔ shift_select often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
const midcom_jqgrid_presets = {
2
    autowidth: true,
3
    altRows: true,
4
    altclass: 'even',
5
    deselectAfterSort: false,
6
    forceFit: true,
7
    gridview: true,
8
    headertitles: true,
9
    height: 'auto',
10
    hoverrows: true,
11
    shrinkToFit: true,
12
    sortable: true,
13
    autoencode: false,
14
    datatype: 'xml',
15
    iconSet: 'fontAwesome',
16
    jsonReader: {
17
        repeatitems: false,
18
        id: '0'
19
    }
20
};
21
$.extend(true, $.jgrid.cmTemplate, {
22
    title_from_index: {
23
        title: false,
24
        cellattr: function (rowId, cellValue, rawObject, cm, rdata) {
25
            if (cellValue) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if cellValue is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
26
                return ' title="' + rdata['index_' + cm.name] + '"';
27
            }
28
        }
29
    }
30
});
31
32
$.jgrid.defaults = $.extend($.jgrid.defaults, midcom_jqgrid_presets);
33
$.jgrid.search.searchOnEnter = false;
34
$.jgrid.search.defaultSearch = 'cn';
35
36
const midcom_grid_resize = {
37
    timer: false,
38
    containment: '#content-text',
39
    firstrun: true,
40
    add_header_controls: function() {
41
        $('table.ui-jqgrid-btable').jqGrid('setGridParam', {
42
            onHeaderClick: function(gridstate) {
43
                $(this).closest('.ui-jqgrid').find('.ui-jqgrid-titlebar-maximize').toggle(gridstate === 'visible');
44
                $(window).trigger('resize');
45
        }});
46
47
        midcom_grid_resize.attach_maximizer($('.ui-jqgrid-titlebar'));
48
    },
49
    event_handler: function() {
50
        if (midcom_grid_resize.firstrun) {
51
            midcom_grid_resize.firstrun = false;
52
            midcom_grid_resize.add_header_controls();
53
        } else {
54
            if (!midcom_grid_resize.timer) {
55
                $(midcom_grid_resize.containment).addClass('openpsa-resizing');
56
            } else {
57
                clearTimeout(midcom_grid_resize.timer);
58
            }
59
            midcom_grid_resize.timer = setTimeout(midcom_grid_resize.end_resize, 300);
60
        }
61
        if ($('.ui-jqgrid-maximized').length > 0) {
62
            midcom_grid_resize.maximize_height($('.ui-jqgrid-maximized'));
63
            midcom_grid_resize.fill_width($('.ui-jqgrid-maximized'));
64
        } else {
65
            midcom_grid_resize.set_height($('.fill-height'), 'fill');
66
            midcom_grid_resize.set_height($('.crop-height'), 'crop');
67
            midcom_grid_resize.fill_width($('.full-width'));
68
        }
69
    },
70
    end_resize: function() {
71
        midcom_grid_resize.timer = false;
72
        $(midcom_grid_resize.containment).removeClass('openpsa-resizing');
73
    },
74
    attach_maximizer: function(items) {
75
        items.each(function() {
76
            $('<a role="link" class="ui-jqgrid-titlebar-maximize"><span class="fa fa-plus-circle"></span></a>')
77
                .on('click', function() {
78
                    var container = $(this).closest('.ui-jqgrid').parent();
79
80
                    if (container.hasClass('ui-jqgrid-maximized')) {
81
                        $(this).find('span').removeClass('fa-minus-circle').addClass('fa-plus-circle');
82
                        var jqgrid_id = container.find('table.ui-jqgrid-btable').attr('id'),
83
                            placeholder = $('#maximized_placeholder');
84
85
                        try {
86
                            $("#" + jqgrid_id).jqGrid().setGridHeight(placeholder.data('orig_height'));
87
                        } catch(e){}
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
88
89
                        container
90
                            .detach()
91
                            .removeClass('ui-jqgrid-maximized')
92
                            .insertBefore(placeholder)
93
                            .find('.ui-jqgrid-titlebar-close').show();
94
                        placeholder.remove();
95
                        //no container is maximized
96
                        $(midcom_grid_resize.containment).children().removeClass('ui-jqgrid-maximized');
97
                        $(midcom_grid_resize.containment).find('.ui-jqgrid-titlebar-maximize').show();
98
                        $(midcom_grid_resize.containment).children().removeClass('ui-jqgrid-maximized-background');
99
                        $(midcom_grid_resize.containment).css('overflow', 'auto');
100
                    } else {
101
                        $(this).find('span').removeClass('fa-plus-circle').addClass('fa-minus-circle')
102
                        $(midcom_grid_resize.containment).scrollTop(0);
103
                        $('<div id="maximized_placeholder"></div>')
104
                            .data('orig_height', container.find('.ui-jqgrid-bdiv').outerHeight())
105
                            .insertAfter(container);
106
                        container
107
                            .detach()
108
                            .removeClass('ui-jqgrid-maximized-background')
109
                            .addClass('ui-jqgrid-maximized')
110
                            .prependTo($(midcom_grid_resize.containment))
111
                            .find('.ui-jqgrid-titlebar-close').hide();
112
                        $(midcom_grid_resize.containment).children(':not(:first-child)').addClass('ui-jqgrid-maximized-background');
113
                        $(midcom_grid_resize.containment).css('overflow', 'hidden');
114
                    }
115
                    $(window).trigger('resize');
116
                })
117
                .hover(function() {
118
                    $(this).addClass('ui-state-hover');
119
                }, function() {
120
                    $(this).removeClass('ui-state-hover');
121
                })
122
                .appendTo($(this));
123
            if ($(this).closest('.ui-jqgrid').find('.ui-jqgrid-btable').data('maximized')) {
124
                $(this).find('.ui-jqgrid-titlebar-maximize').trigger('click');
125
            }
126
            if ($(this).closest('.ui-jqgrid').find('.ui-jqgrid-btable').is(':hidden')) {
127
                $(this).find('.ui-jqgrid-titlebar-maximize').hide();
128
            }
129
        });
130
    },
131
    fill_width: function(items) {
132
        if (items.length === 0) {
133
            return;
134
        }
135
136
        var new_width;
137
138
        items.each(function(index, item) {
139
            if (items.hasClass('ui-jqgrid-maximized')) {
140
                new_width = $(midcom_grid_resize.containment).width();
141
            } else {
142
                //calculate for each item separately to take care of floating neighbors
143
                new_width = $(item).width();
144
            }
145
            $(item).find('.ui-jqgrid table.ui-jqgrid-btable').each(function() {
146
                let panel = $("#gbox_" + this.id).closest('.ui-tabs-panel');
147
                if (   panel.length > 0
148
                    && panel.hasClass('ui-tabs-hide')) {
149
                    return;
150
                }
151
                try {
152
                    var old_width = $(this).jqGrid().getGridParam('width');
153
                    if (!$(this).data('resized') || new_width != old_width) {
154
                        $(this).jqGrid().setGridWidth(new_width);
155
                        $(this).data('resized', true);
156
                    }
157
                } catch(e){}
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
158
            });
159
        });
160
    },
161
    set_height: function(items, mode) {
162
        if (items.length === 0 || $(midcom_grid_resize.containment).length === 0) {
163
            return;
164
        }
165
166
        var grids_content_height = 0,
167
            container_height = $(midcom_grid_resize.containment).height(),
168
            container_nongrid_height = 0,
169
            visible_grids = 0,
170
            grid_heights = {},
171
            minimum_height = 21;
172
173
        if ($('#org_openpsa_resize_marker_end').length === 0) {
174
            $(midcom_grid_resize.containment)
175
                .append('<div id="org_openpsa_resize_marker_end"></div>')
176
                .prepend('<div id="org_openpsa_resize_marker_start"></div>');
177
        }
178
        container_nongrid_height = $('#org_openpsa_resize_marker_end').position().top - $('#org_openpsa_resize_marker_start').position().top;
179
180
        items.each(function() {
181
            var grid_body = $("table.ui-jqgrid-btable", $(this));
182
            if (grid_body.length > 0) {
183
                var grid_height = grid_body.parent().parent().height(),
184
                    content_height = grid_body.outerHeight();
185
                if (    content_height === 0
186
                    && (   grid_body.jqGrid('getGridParam', 'datatype') !== 'local'
187
                        || (   grid_body.jqGrid('getGridParam', 'treeGrid') === true
188
                            && grid_body.jqGrid('getGridParam', 'treedatatype') !== 'local'))) {
189
                    content_height = 100;
190
                }
191
192
                if (   grid_body.jqGrid('getGridParam', 'gridstate') === 'visible'
193
                    && $(this).is(':visible')) {
194
                    grid_heights[grid_body.attr('id')] = content_height;
195
                    grids_content_height += content_height;
196
                    container_nongrid_height -= grid_height;
197
                    visible_grids++;
198
                }
199
            }
200
        });
201
202
        var available_space = container_height - container_nongrid_height;
203
204
        if (   grids_content_height === 0
205
            || available_space <= minimum_height * visible_grids) {
206
            return;
207
        }
208
209
        if (available_space > grids_content_height && mode !== 'fill') {
210
            $.each(grid_heights, function(grid_id, content_height) {
211
                set_param(grid_id, content_height);
212
            });
213
            return;
214
        }
215
216
        $.each(grid_heights, function(grid_id, content_height) {
217
            var new_height = available_space * (content_height / grids_content_height);
218
            if (new_height < minimum_height) {
219
                available_space -= minimum_height;
220
                grids_content_height -= content_height;
221
                set_param(grid_id, minimum_height);
222
                delete grid_heights[grid_id];
223
            }
224
        });
225
226
        $.each(grid_heights, function(grid_id, content_height) {
227
            var new_height = Math.floor(available_space * (content_height / grids_content_height));
228
            set_param(grid_id, new_height);
229
        });
230
231
        function set_param(grid_id, value) {
232
            let grid = $("#" + grid_id);
233
            if (grid.parent().parent().height() !== value) {
234
                try {
235
                    grid.jqGrid().setGridHeight(value);
236
                } catch(e){}
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
237
                if (grid.data('vScroll')) {
238
                    grid.closest(".ui-jqgrid-bdiv").scrollTop(grid.data('vScroll'));
239
                    grid.removeData('vScroll');
240
                }
241
            }
242
        }
243
    },
244
    maximize_height: function(part) {
245
        var part_height = part.outerHeight(true),
246
            grid_height = $("table.ui-jqgrid-btable", part).parent().parent().outerHeight(),
247
            new_height = $(midcom_grid_resize.containment).height() + grid_height - part_height;
248
249
        try {
250
            $("table.ui-jqgrid-btable", part).jqGrid().setGridHeight(new_height);
251
        }
252
        catch(e){}
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
253
    }
254
};
255
$(window).resize(midcom_grid_resize.event_handler);
256
257
const midcom_grid_editable = {
258
    grid_id: '',
259
    last_added_row: 0,
260
    default_options: {
261
        keys: true,
262
        afterrestorefunc: function(id) {
263
            midcom_grid_editable.toggle(id, false);
264
        },
265
        aftersavefunc: function(id, response) {
266
            //if saved row was new_... then refresh tr-id
267
            if (response.responseText !== undefined) {
268
                var return_values = JSON.parse(response.responseText),
269
                    oldId = return_values.oldid;
270
                if (oldId.substring(0, 4) === 'new_') {
271
                    var pos = $('#' + midcom_grid_editable.grid_id + ' tr[id="' + oldId + '"]').prevAll().length,
272
                        newrow = $('#' + oldId);
273
                    id = return_values.id;
274
275
                    midcom_grid_editable.saveSingleItemPosition(id, pos);
276
277
                    newrow.attr('id', id);
278
                    newrow.find('.row_edit, .row_save, .row_cancel, .row_delete').data('row-id', id);
279
                }
280
            }
281
282
            midcom_grid_editable.toggle(id, false);
283
        },
284
        oneditfunc: function(id) {
285
            midcom_grid_editable.toggle(id, true);
286
        },
287
        successfunc: function(data) {
288
            var return_values = JSON.parse(data.responseText);
289
            return [true, return_values, return_values.id];
290
        },
291
        enable_sorting: false,
292
        enable_create: true
293
    },
294
    toggle: function(id, edit_mode) {
295
        $("#" + id).find(".row_edit, .row_delete").toggleClass('hidden', edit_mode);
296
        $("#" + id).find(".row_save, .row_cancel").toggleClass('hidden', !edit_mode);
297
        $('#' + id).toggleClass('jqgrid-editing', edit_mode);
298
299
        this.toggle_mouselistener();
300
    },
301
302
    enable_inline: function (grid_id, custom_options) {
303
        var lastsel,
304
            self = this;
305
        self.options = $.extend({}, self.default_options, custom_options);
306
        self.grid_id = grid_id;
307
        $('#' + grid_id).jqGrid('setGridParam', {
308
            onSelectRow: function(id) {
309
                if (id && id !== lastsel) {
310
                    $('#' + id).restoreRow(lastsel);
311
                    lastsel = id;
312
                }
313
                if (!$('#' + id).hasClass('jqgrid-editing')) {
314
                    self.editRow(id);
315
                }
316
            }
317
        });
318
319
        self.add_inline_controls();
320
        
321
        if (self.options.enable_create) {            
322
            var create_button_parameters = {
323
                caption: self.options.button_label || "",
324
                buttonicon: "fa-plus",
325
                onClickButton: function() {
326
                    var new_id = 'new_' + self.last_added_row++,
327
                        params = {};
328
    
329
                    if (self.options.enable_sorting) {
330
                        params.position = $('#' + grid_id + ' td[aria-describedby="invoice_items_position"]').length + 1;
331
                    }
332
                    //create new row; now with a position-value
333
                    $('#' + self.grid_id).jqGrid('addRowData', new_id, params, 'last');
334
    
335
                    self.render_buttons(new_id);
336
                }
337
            };
338
            $('#' + grid_id)
339
                .jqGrid('navGrid', "#p_" + grid_id, {add: false, del: false, refresh: false, edit: false, search: false})
340
                .jqGrid('navButtonAdd', "#p_" + grid_id, create_button_parameters);
341
        }
342
343
        if (self.options.enable_sorting) {
344
            $('#' + grid_id)
345
                .on("sortstop", function() {
346
                    self.refreshItemPositions();
347
                    //Refresh the rows alternately with the style from the class even
348
                    $(this).find("tbody tr.jqgrow").removeClass('even');
349
                    $(this).find("tbody tr.jqgrow:visible:odd").addClass('even');
350
                })
351
                .jqGrid("sortableRows", {helper: "clone"});
352
        }
353
    },
354
    /**
355
     * This function works only if enable_sorting is set true
356
     */
357
    toggle_mouselistener: function() {
358
        if (this.options.enable_sorting) {
359
            var isEdit = $('#' + this.grid_id + ' tr.jqgrid-editing').length > 0;
360
361
            if (isEdit) {
362
                $('#' + this.grid_id).sortable("disable");
363
                $('#' + this.grid_id + ' tbody > .jqgrow').enableSelection();
364
            } else {
365
                $('#' + this.grid_id).sortable("enable");
366
                $('#' + this.grid_id + ' tbody > .jqgrow').disableSelection();
367
            }
368
        }
369
    },
370
    editRow: function(id) {
371
        $('#' + this.grid_id).jqGrid('editRow', id, this.options);
372
        $('#cancel_button_' + id).closest("tr")
373
            .find('textarea, input[type="text"]').filter(':visible').first().focus();
374
    },
375
    saveRow: function(id) {
376
        $('#' + this.grid_id).jqGrid('saveRow', id, this.options);
377
    },
378
    restoreRow: function(id) {
379
        $('#' + this.grid_id).jqGrid('restoreRow', id, this.options);
380
    },
381
    deleteRow: function(id) {
382
        var edit_url = $('#' + this.grid_id).jqGrid('getGridParam', 'editurl'),
383
            rowdata = $('#' + this.grid_id).jqGrid('getRowData', id),
384
            self = this,
385
            callAfterSave = function() {
386
                $('#' + self.grid_id).jqGrid('delRowData', id);
387
                if (typeof self.options.afterdeletefunc === 'function') {
388
                    self.options.afterdeletefunc();
389
                }
390
                if (self.options.enable_sorting) {
391
                    self.refreshItemPositions();
392
                }
393
            };
394
        rowdata.oper = 'del';
395
396
        if (rowdata.id == '') {
397
            callAfterSave();
398
        } else {
399
            $.post(edit_url, rowdata, function() {
400
                callAfterSave();
401
            });
402
        }
403
    },
404
    refreshItemPositions: function() {
405
        var self = this;
406
        $('#' + this.grid_id + ' td[aria-describedby="invoice_items_position"]').each(function(index) {
407
            var idx = index + 1,
408
                oldPos = parseInt($(this).text()),
409
                trId = this.parentNode.id;
410
411
            if (idx !== oldPos) {
412
                // Set new Position-Number in this td
413
                $(this).html(idx);
414
415
                if (trId.substring(0, 4) !== 'new_') {
416
                    self.saveSingleItemPosition(trId, idx);
417
                }
418
            }
419
        });
420
    },
421
    saveSingleItemPosition: function(id, pos) {
422
        $.ajax({
423
            type: 'POST',
424
            url: this.options.position_url,
425
            data: {id: id, position: pos}
426
        });
427
    },
428
    render_buttons: function(rowid) {
429
        var be = "<i class='row_button row_edit fa fa-pencil' data-row-id='" + rowid + "'></i>",
430
            bs = "<i class='row_button row_save hidden fa fa-check' data-row-id='" + rowid + "'></i>",
431
            bc = "<i class='row_button row_cancel hidden fa fa-ban' data-row-id='" + rowid + "'></i>",
432
            bd = "<i class='row_button row_delete fa fa-trash' data-row-id='" + rowid + "'></i>";
433
        $("#" + this.grid_id).jqGrid('setRowData', rowid, {actions: be + bs + bc + bd});
434
    },
435
    add_inline_controls: function() {
436
        var rowids = $("#" + this.grid_id).jqGrid('getDataIDs'),
437
            self = this,
438
            i;
439
440
        for (i = 0; i < rowids.length; i++) {
441
            this.render_buttons(rowids[i]);
442
        }
443
444
        $("#" + this.grid_id).on('click', ".row_edit", function() {
445
            self.editRow(this.dataset.rowId);
446
        });
447
        $("#" + this.grid_id).on('click', ".row_delete", function(e) {
448
            e.stopPropagation();
449
            self.deleteRow(this.dataset.rowId);
450
        });
451
        $("#" + this.grid_id).on('click', ".row_save", function(e) {
452
            e.stopPropagation();
453
            self.saveRow(this.dataset.rowId);
454
        });
455
        $("#" + this.grid_id).on('click', ".row_cancel", function(e) {
456
            e.stopPropagation();
457
            self.restoreRow(this.dataset.rowId);
458
        });
459
    }
460
};
461
462
const midcom_grid_footer = {
0 ignored issues
show
Unused Code introduced by
The constant midcom_grid_footer seems to be never used. Consider removing it.
Loading history...
463
    set_field: function(grid_id, colname, operation) {
464
        let footerdata = {};
465
        footerdata[colname] = $('#' + grid_id).jqGrid('getCol', colname, false, operation);
466
        $('#' + grid_id).jqGrid('footerData', 'set', footerdata);
467
    }
468
};
469
470
const midcom_grid_helper = {
471
    event_handler_added: false,
472
    active_grids: [],
473
    maximized_grid: '',
474
    bind_grouping_switch: function(grid_id) {
475
        var grid = $("#" + grid_id),
476
            group_conf = grid.jqGrid('getGridParam', 'groupingView'),
477
            active = grid.jqGrid('getGridParam', 'grouping'),
478
            expand = false,
479
            toggle = $('<input type="button" value="-">')
480
                .on('click', function() {
481
                    var idPrefix = grid_id + "ghead_0_";
482
483
                    grid.find('.jqgroup').each(function(index, element) {
484
                        if (   (!expand && $(element).find('.tree-wrap').hasClass(group_conf.minusicon))
485
                            || (expand && $(element).find('.tree-wrap').hasClass(group_conf.plusicon))) {
486
                                     grid.jqGrid('groupingToggle', idPrefix + index);
487
                        }
488
                    });
489
                    expand = !expand;
490
                    toggle.val(expand ? '+' : '-');
491
                });
492
493
        $("#chgrouping_" + grid_id)
494
            .val((active) ? group_conf.groupField[0] : 'clear')
495
            .on('change', function() {
496
                var selection = $(this).val(),
497
                    previous = group_conf.groupField[0];
498
499
                if (selection) {
500
                    if (selection == "clear") {
501
                        grid.jqGrid('groupingRemove', true);
502
                    } else {
503
                        grid.jqGrid('groupingGroupBy', selection);
504
                    }
505
506
                    if (   selection !== previous
507
                        && !$(this).find('[value="' + previous + '"]').data('hidden')) {
508
                        // Workaround for https://github.com/tonytomov/jqGrid/issues/431
509
                        grid.jqGrid('showCol', previous);
510
                    }
511
                    $(window).trigger('resize');
512
                }
513
            })
514
            .after(toggle);
515
    },
516
    setup_grid: function (grid_id, config_orig) {
517
        var identifier = 'openpsa-jqgrid#' + grid_id,
518
            saved_values = {},
519
            config = $.extend(true, {}, config_orig);
520
521
        if (   typeof window.localStorage !== 'undefined'
522
            && window.localStorage) {
523
            midcom_grid_helper.active_grids.push(grid_id);
524
            saved_values = JSON.parse(window.localStorage.getItem(identifier));
525
            if (saved_values) {
526
                if (typeof saved_values.custom_keys !== 'undefined') {
527
                    var keys = saved_values.custom_keys;
528
                    delete saved_values.custom_keys;
529
                    $('#' + grid_id).data('vScroll', keys.vScroll);
530
531
                    //only allow one maximized
532
                    if (keys.maximized && midcom_grid_helper.maximized_grid == '') {
533
                        midcom_grid_helper.maximized_grid = grid_id;
534
                    } else {
535
                        keys.maximized = false;
536
                    }
537
                    $('#' + grid_id).data('maximized', keys.maximized);
538
                }
539
                config = $.extend(config, saved_values);
540
            }
541
            if (config.data) {
542
                // if data was removed since last visit, decrease page number
543
                if (config.data.length <= (config.rowNum * config.page)) {
544
                    config.page = Math.ceil(config.data.length / config.rowNum);
545
                }
546
                // if data was added to grid that was empty on last visit, increase page number
547
                else if (config.page === 0) {
548
                    config.page = 1;
549
                }
550
            }
551
            if (midcom_grid_helper.event_handler_added === false) {
552
                $(window).on('unload', midcom_grid_helper.save_grid_data);
553
                midcom_grid_helper.event_handler_added = true;
554
            }
555
        }
556
557
        try {
558
            $('#' + grid_id).jqGrid(config);
559
        } catch (exception) {
560
            if (!$.isEmptyObject(saved_values)) {
561
                $('#' + grid_id).jqGrid('GridUnload');
562
                $('#' + grid_id).jqGrid(config_orig);
563
            } else {
564
                throw exception;
565
            }
566
        }
567
    },
568
    save_grid_data: function() {
569
        var grid_maximized = false;
570
        midcom_grid_helper.active_grids.forEach(function(grid_id) {
571
            if (typeof $('#' + grid_id).jqGrid === 'undefined') {
572
                return;
573
            }
574
            var identifier = 'openpsa-jqgrid#' + grid_id,
575
                grid = $('#' + grid_id),
576
                data = {
577
                    page: grid.jqGrid('getGridParam', 'page'),
578
                    sortname: grid.jqGrid('getGridParam', 'sortname'),
579
                    sortorder: grid.jqGrid('getGridParam', 'sortorder'),
580
                    hiddengrid: grid.closest('.ui-jqgrid-view').find('.ui-jqgrid-titlebar-close .ui-icon').hasClass('ui-icon-circle-triangle-s'),
581
                    custom_keys: {
582
                        vScroll: grid.closest(".ui-jqgrid-bdiv").scrollTop(),
583
                        //only allow one maximized
584
                        maximized: (grid.closest('.ui-jqgrid-maximized').length > 0) && (grid_maximized == grid_id || grid_maximized == false)
0 ignored issues
show
Best Practice introduced by
Comparing grid_maximized to false using the == operator is not safe. Consider using === instead.
Loading history...
585
                    }
586
                };
587
588
            if ($("#chgrouping_" + grid_id).length > 0) {
589
                data.grouping = grid.jqGrid('getGridParam', 'grouping');
590
                data.groupingView = grid.jqGrid('getGridParam', 'groupingView');
591
592
                delete data.groupingView.groups;
593
                delete data.groupingView.lastvalues;
594
            }
595
596
            if (data.custom_keys.maximized) {
597
                grid_maximized = grid_id;
598
            }
599
600
            if (   grid.jqGrid('getGridParam', 'scroll') === 1
601
                && data.custom_keys.vScroll < grid.height()) {
602
                data.page = 1;
603
            }
604
            window.localStorage.setItem(identifier, JSON.stringify(data));
605
        });
606
    }
607
};
608
609
const midcom_grid_csv = {
610
    configs: {},
611
    separator: ';',
612
    add: function (config) {
613
        this.configs[config.id] = config;
614
615
        $('button#' + config.id + '_export').on('click', function(e) {
616
            midcom_grid_csv.prepare_data(config);
617
            e.preventDefault();
618
        });
619
    },
620
    prepare_data: function(config) {
621
        var rows = $('#' + config.id).jqGrid('getRowData'),
622
            field,
623
            data = '';
624
625
        function trim(input) {
626
            let sepExp = new RegExp(midcom_grid_csv.separator),
627
                converted = input
628
                .replace(/\n|\r/g, " ") // remove line breaks
629
                .replace(/\s+/g, " ") // Shorten long whitespace
630
                .replace(/^\s+/g, "") // strip leading ws
631
                .replace(/\s+$/g, "") // strip trailing ws
632
                .replace(/<\/?([a-z][a-z0-9]*)\b[^>]*>/gi, ''); //strip HTML tags
633
634
            if (converted.match(sepExp)) {
635
                return '"' + converted + '"';
636
            }
637
            return converted;
638
        }
639
640
        for (field in config.fields) {
641
            data += trim(config.fields[field]) + this.separator;
642
        }
643
644
        data += '\n';
645
646
        rows.forEach(function(row) {
647
            for (field in config.fields) {
648
                if (typeof row[field] !== 'undefined') {
0 ignored issues
show
introduced by
The variable field is changed by the for-each loop on line 647. Only the value of the last iteration will be visible in this function if it is called outside of the loop.
Loading history...
649
                    data += trim(row[field]) + midcom_grid_csv.separator;
0 ignored issues
show
Bug introduced by
The variable data is changed as part of the for-each loop for example by trim(row.field) + midcom_grid_csv.separator on line 649. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
650
                }
651
            }
652
            data += '\n';
653
        });
654
655
        var blob = new Blob([data], {type: "application/csv;charset=utf-8"});
656
        saveAs(blob, config.filename + ".csv");
657
    }
658
};
659
660
const midcom_grid_batch_processing = {
0 ignored issues
show
Unused Code introduced by
The constant midcom_grid_batch_processing seems to be never used. Consider removing it.
Loading history...
661
    initialize: function(config) {
662
        $('#form_' + config.id).hide();
663
664
        var widgets_to_add = [],
665
            label = config.submit || 'Go',
666
            //build action form and associated widgets
667
            action_select = '<div class="action_select_div" id="' + config.id + '_batch">';
668
        action_select += '<select id="' + config.id + '_batch_select" class="action_select" name="action" size="1">';
669
670
        $.each(config.options, function(key, value) {
671
            action_select += '<option value="' + key + '" >' + value.label + '</option>';
672
            if (typeof value.widget_config !== 'undefined') {
673
                var widget_id = config.id + '__' + key;
674
                widgets_to_add.push({id: widget_id, insertAfter: '#' + config.id + '_batch_select', widget_config: value.widget_config});
675
            }
676
        });
677
        action_select += '</select><input type="submit" name="send" value="' + label + '" style="display: none" /></div>';
678
        $(action_select).appendTo($('#form_' + config.id));
679
680
        widgets_to_add.forEach(function(widget_conf) {
681
            midcom_helper_datamanager2_autocomplete.create_widget(widget_conf);
682
        });
683
684
        $('#' + config.id + '_batch_select').on('change', function(event) {
685
            var selected_option = $(event.target).val();
686
            if (selected_option === 'none') {
687
                $(event.target).nextAll('input[type="submit"]').hide();
688
            } else {
689
                $(event.target).nextAll('input[type="submit"]').show();
690
            }
691
            $('.ui-autocomplete-input').hide();
692
            $('#' + config.id + '_batch').css('display', 'inline');
693
            $('#' + config.id + '__' + selected_option + '_search_input').show();
694
        });
695
696
        //hook action select into grid so that it'll get shown when necessary
697
        $('#' + config.id).jqGrid('setGridParam', {
698
            onSelectRow: function(id, selected, event) {
699
                if ($('#' + config.id).jqGrid('getGridParam', 'selarrrow').length === 0) {
700
                    $('#' + config.id + '_batch').parent().hide();
701
                } else {
702
                    $('#' + config.id + '_batch').parent().show();
703
                }
704
705
                if (selected && event.hasOwnProperty('originalEvent') && event.originalEvent.shiftKey) {
706
707
                    function shift_select(rows) {
0 ignored issues
show
Bug introduced by
The function shift_select is declared conditionally. This is not supported by all runtimes. Consider moving it to root scope or using var shift_select = function() { /* ... */ }; instead.
Loading history...
708
                        let started = false;
709
                        rows.get().reverse().forEach(function(row) {
710
                            if (started) {
711
                                if (!$(row).hasClass('ui-state-highlight')) {
712
                                    $(row).find('td.td_cbox input').trigger('click');
713
                                }
714
                            } else {
715
                                started = $(row).hasClass('ui-state-highlight');
716
                            }
717
                        });
718
                    }
719
720
                    let clicked_row = $('#' + config.id + ' tr#' + id);
721
                    if (clicked_row.prevAll('.ui-state-highlight').length > 0) {
722
                        shift_select(clicked_row.prevAll(':not(.jqgroup)'));
723
                    } else if (clicked_row.nextAll('.ui-state-highlight').length > 0) {
724
                        shift_select(clicked_row.nextAll(':not(.jqgroup)'));
725
                    }
726
                }
727
728
                $(window).trigger('resize');
729
            },
730
            onSelectAll: function(rowids, status) {
731
                if (!status) {
732
                    $('#' + config.id + '_batch').parent().hide();
733
                } else {
734
                    $('#' + config.id + '_batch').parent().show();
735
                }
736
                $(window).trigger('resize');
737
            }
738
        });
739
740
        // We use regular post instead of ajax to get browser's busy indicator
741
        $("#form_" + config.id).on('submit', function() {
742
            function add_array(field, data) {
743
                for (var i = 0; i < data.length; i++) {
744
                    $('<input type="hidden" name="' + field + '[]" value="' + data[i] + '" />')
745
                        .appendTo('#form_' + config.id);
746
                }
747
            }
748
            add_array('entries', $("#" + config.id).jqGrid('getGridParam', 'selarrrow'));
749
750
            var action = $("#form_" + config.id + ' select[name="action"]').val(),
751
                autocomplete = $("#" + config.id + '__' + action + '_selection');
752
753
            if (autocomplete.length > 0 && autocomplete.val().length) {
754
                add_array('selection', JSON.parse(autocomplete.val()));
755
            } else if (config.options[action].value) {
756
                $('<input type="hidden" name="value" value="' + config.options[action].value + '" />')
757
                    .appendTo('#form_' + config.id);
758
            }
759
        });
760
    }
761
};
762
763
const midcom_grid_row_actions = {
764
    update_totals: function(table, config) {
765
        var total = 0,
766
            row_sum,
767
            totals_field = table.closest('.ui-jqgrid-view').find('.ui-jqgrid-ftable .' + config.totals_field);
768
769
        table.find('tbody tr').not('.jqgfirstrow').each(function() {
770
            row_sum = parseFloat($(this).find('.' + config.totals_field).prev().text());
771
            if (isNaN(row_sum)) {
772
                return;
773
            }
774
775
            total += row_sum;
776
        });
777
778
        totals_field.text($.fn.fmatter.number(total, $.jgrid.locales[$.jgrid.defaults.locale].formatter));
779
    },
780
781
    process: function(button, action, config) {
782
        button.attr('disabled', 'disabled');
783
        var id = button.parent().parent().attr('id');
784
        $.post(config.url + action + '/', {id: id}, function(data) {
785
            if (data.success !== false) {
786
                var old_grid = button.closest('.ui-jqgrid-btable'),
787
                    regex = new RegExp(data.old_status),
788
                    row_data = old_grid.getRowData(id),
789
                    new_grid = $('#' + old_grid.attr('id').replace(regex, data.new_status));
790
791
                old_grid.delRowData(id);
792
                midcom_grid_row_actions.update_totals(old_grid, config);
793
794
                if (new_grid.length < 1) {
795
                    // Grid is not present yet, reload
796
                    window.location.reload();
797
                    return;
798
                }
799
800
                if (new_grid.jqGrid('getGridParam', 'datatype') === 'local') {
801
                    row_data.action = data.action;
802
                    data.updated.forEach(function(item) {
803
                        row_data[item[0]] = item[1];
804
                    });
805
                    new_grid.addRowData(row_data.id, row_data, "last");
806
                    midcom_grid_row_actions.update_totals(new_grid, config);
807
                } else {
808
                    new_grid.trigger('reloadGrid');
809
                }
810
                $(window).trigger('resize');
811
            }
812
813
            data.messages.forEach(function(message) {
814
                $.midcom_services_uimessage_add(message);
815
            });
816
        })
817
            .fail(function(response) {
818
                if (response.status === 403) {
819
                    // most probably our login session expired. reload
820
                    location.href = location.href;
821
                } else {
822
                    $.midcom_services_uimessage_add({
823
                        type: 'error',
824
                        title: response.statusText,
825
                        message: response.responseText
826
                    });
827
                }
828
            });
829
    },
830
831
    init: function(config) {
832
        config.actions.forEach(function(action) {
833
            $('#' + config.identifier + '.ui-jqgrid-btable')
834
                .on('click', 'button.' + action, function() {
835
                    midcom_grid_row_actions.process($(this), action, config);
836
                });
837
        });
838
    }
839
};
840