Test Failed
Push — master ( c9e883...d4b66a )
by Alexey
05:06
created

DataManager.groupAction   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 0
loc 24
rs 8.9713
c 0
b 0
f 0
1
/**
2
 * Data Manager objects
3
 *
4
 * @author Alexey Krupskiy <[email protected]>
5
 * @link http://inji.ru/
6
 * @copyright 2015 Alexey Krupskiy
7
 * @license https://github.com/injitools/cms-Inji/blob/master/LICENSE
8
 */
9
inji.Ui.dataManagers = {
10
  instances: {},
11
  get: function (element) {
12
    if ($(element).hasClass('dataManager')) {
13
      if (typeof (this.instances[$(element).attr('id')]) != 'undefined') {
14
        return this.instances[$(element).attr('id')];
15
      } else {
16
        return this.instances[$(element).attr('id')] = new DataManager($(element));
17
      }
18
    } else {
19
      if ($(element).closest('.dataManager').length == 1 && typeof (this.instances[$(element).closest('.dataManager').attr('id')]) != 'undefined') {
20
        return this.instances[$(element).closest('.dataManager').attr('id')];
21
      } else if ($(element).closest('.dataManager').length == 1) {
22
        return this.instances[$(element).closest('.dataManager').attr('id')] = new DataManager($(element).closest('.dataManager'));
23
      }
24
    }
25
    return null
26
  },
27
  popUp: function (item, params) {
28
    var code = item;
29
30
    if (typeof (params.relation) != 'undefined') {
31
      code += params.relation;
32
    }
33
    code = code.replace(/\:/g, '_').replace(/\\/g, '_');
34
    var modal = inji.Ui.modals.show('', '<div class = "text-center"><img src = "' + inji.options.appRoot + 'static/moduleAsset/Ui/images/ajax-loader.gif" /></div>', code, 'modal-lg');
35
    inji.Server.request({
36
      url: 'ui/dataManager/',
37
      dataType: 'json',
38
      data: {item: item, params: params},
39
      success: function (data) {
40
        modal.find('.modal-body').html(data);
41
        $.each(modal.find('.modal-body .dataManager'), function () {
42
          inji.Ui.dataManagers.instances[$(this).attr('id')] = new DataManager($(this));
43
        });
44
      }
45
    });
46
  },
47
  reloadAll: function () {
48
    for (var key in this.instances) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
49
      this.instances[key].reload();
50
    }
51
  }
52
}
53
54
55
function DataManager(element) {
56
  this.element = element;
57
  this.params = element.data('params');
58
  this.filters = this.params.filters ? this.params.filters : {};
59
  this.modelName = element.data('modelname');
60
  this.managerName = element.data('managername');
61
  this.options = element.data('options');
62
63
  this.categoryModel = this.options.categorys && this.options.categorys.model ? this.options.categorys.model : '';
64
  this.categoryPath = '/';
65
  this.categoryId = 0;
66
67
  this.limit = 30;
68
  this.page = 1;
69
  this.sortered = {};
70
  this.categoryIndex = '';
71
  this.mode = '';
72
  this.all = 0;
73
  this.ajaxUrl = 'ui/dataManager/loadRows';
74
  if (this.options.ajaxUrl) {
75
    this.ajaxUrl = this.options.ajaxUrl;
76
  }
77
  var instance = this;
78
  $(this.element).find('thead [type="checkbox"],tfoot [type="checkbox"]').click(function () {
79
    var index = $(this).closest('th').index();
80
    if (!this.checked) {
81
      $(instance.element).find('.datamanagertable tbody tr').each(function () {
82
        $($(this).find('td').get(index)).find('[type="checkbox"]')[0].checked = false;
83
      });
84
    } else {
85
      $(instance.element).find('.datamanagertable tbody tr').each(function () {
86
        $($(this).find('td').get(index)).find('[type="checkbox"]')[0].checked = true;
87
      });
88
    }
89
  });
90
  if (this.options.sortMode) {
91
    $(this.element).find('.modeBtn').on('click', function () {
92
      if (instance.mode != $(this).data('mode')) {
93
        instance.mode = $(this).data('mode');
94
        instance.all = 1;
95
        instance.page = 1;
96
        instance.load();
97
      } else {
98
        instance.mode = '';
99
        instance.all = 0;
100
        instance.page = 1;
101
        instance.load();
102
      }
103
    });
104
  }
105
  $(this.element).find('.pagesContainer').on('click', 'a', function () {
106
    instance.page = $(this).attr('href').match(/page\=(\d+)\&?/)[1];
107
    instance.limit = $(this).attr('href').match(/limit\=(\d+)\&?/)[1];
108
    instance.load();
109
    return false;
110
  });
111
  var self = this;
112
  $(document).on('scroll', function () {
113
    self.flowPanel();
114
  });
115
  $(window).on('resize', function () {
116
    self.flowPanel();
117
  });
118
  self.flowPanel();
119
120
  if (window.location.hash && window.location.hash != '#') {
121
    var windowsHash = JSON.parse(decodeURIComponent(window.location.hash.substr(1)));
122
    if (windowsHash[this.modelName + ':' + this.managerName]) {
123
      var hashData = windowsHash[this.modelName + ':' + this.managerName];
124
      this.limit = hashData.params.limit;
125
      this.page = hashData.params.page;
126
      this.sortered = hashData.sortered;
127
      this.all = hashData.all;
128
      this.filters = hashData.filters;
129
      if (hashData.filters && this.element.find('.dataManagerFilters [name^="datamanagerFilters"]').length > 0) {
130
        this.element.find('.dataManagerFilters [name^="datamanagerFilters"]').each(function () {
131
          var maths = $(this).attr('name').match(/\[([^\]]+)\]/g);
132
          for (var key in maths) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
133
            maths[key] = maths[key].replace(/([\[\]])/g, '');
134
          }
135
          if (hashData.filters[maths[0]]) {
136
            if (typeof maths[2] != 'undefined') {
137
              $(this).val(hashData.filters[maths[0]][maths[1]][maths[2]]);
138
            } else {
139
              if ($(this).attr('type') == 'checkbox') {
140
                $(this)[0].checked = hashData.filters[maths[0]][maths[1]];
141
              } else {
142
                $(this).val(hashData.filters[maths[0]][maths[1]]);
143
              }
144
            }
145
          }
146
        });
147
      }
148
149
150
      // var data = {params: params, modelName: this.modelName, managerName: this.managerName, filters: filters, sortered: this.sortered, mode: this.mode, all: this.all};
151
    }
152
  }
153
154
  this.load();
155
}
156
157
DataManager.prototype.newItem = function (model, options) {
158
  if (this.categoryId) {
159
    if (!options.preset) {
160
      options.preset = {};
161
    }
162
    options.preset['category_id'] = this.categoryId;
163
  }
164
  inji.Ui.forms.popUp(model, options);
165
}
166
DataManager.prototype.newCategory = function () {
167
  var options = {preset: {}};
168
  options.preset['parent_id'] = this.categoryId;
169
  inji.Ui.forms.popUp(this.categoryModel, options);
170
}
171
DataManager.prototype.delRow = function (key) {
172
  if (confirm('Вы уверены, что хотите удалить элемент?')) {
173
    inji.Server.request({
174
      url: 'ui/dataManager/delRow',
175
      data: {params: this.params, modelName: this.modelName, key: key, managerName: this.managerName},
176
      success: function () {
177
        inji.Ui.dataManagers.reloadAll();
178
      }
179
    });
180
  }
181
}
182
DataManager.prototype.delCategory = function (key) {
183
  if (confirm('Вы уверены, что хотите удалить элемент?')) {
184
    inji.Server.request({
185
      url: 'ui/dataManager/delCategory',
186
      data: {params: this.params, modelName: this.modelName, key: key, managerName: this.managerName},
187
      success: function () {
188
        inji.Ui.dataManagers.reloadAll();
189
      }
190
    });
191
  }
192
}
193
DataManager.prototype.reload = function () {
194
  this.load();
195
}
196
DataManager.prototype.load = function (options) {
197
  if ($('#' + this.element.attr('id')).length == 0) {
198
    delete inji.Ui.dataManagers[this.element.attr('id')];
199
    return;
200
  }
201
  var dataManager = this;
202
  if (typeof this.params == 'string') {
203
    var params = JSON.parse(this.params);
204
  }
205
  if (Object.prototype.toString.call(this.params) === '[object Array]') {
206
    var params = {};
207
  } else {
208
    var params = this.params;
209
  }
210
  params.limit = this.limit;
211
  params.page = this.page;
212
  params.categoryPath = this.categoryPath;
213
  var filters = this.filters;
214
  if (this.element.find('.dataManagerFilters [name^="datamanagerFilters"]').length > 0) {
215
    this.element.find('.dataManagerFilters [name^="datamanagerFilters"]').each(function () {
216
      var maths = $(this).attr('name').match(/\[([^\]]+)\]/g);
217
      for (var key in maths) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
218
        maths[key] = maths[key].replace(/([\[\]])/g, '');
219
      }
220
      if (!filters[maths[0]]) {
221
        filters[maths[0]] = {};
222
      }
223
      if (typeof maths[2] != 'undefined') {
224
        if (!filters[maths[0]][maths[1]]) {
225
          filters[maths[0]][maths[1]] = {};
226
        }
227
        filters[maths[0]][maths[1]][maths[2]] = $(this).val();
228
      } else {
229
        if ($(this).attr('type') == 'checkbox' && !$(this)[0].checked) {
230
          filters[maths[0]][maths[1]] = 0;
231
        } else {
232
          filters[maths[0]][maths[1]] = $(this).val();
233
        }
234
      }
235
    });
236
  }
237
  if (this.options.sortable) {
238
    for (var key2 in this.options.cols) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
239
      var colname;
240
      if (typeof this.options.cols[key2] == 'object') {
241
        colname = key2;
242
      } else {
243
        colname = this.options.cols[key2];
244
      }
245
      if (this.options.sortable.indexOf(colname) == -1) {
246
        continue;
247
      }
248
      var th = $('.' + dataManager.element.attr('id') + '_colname_' + colname.replace(/\:/g, '\\:'));
249
      if (!th.hasClass('sortable')) {
250
        th.html('<a href = "#">' + th.html() + '</a>');
251
        th.addClass('sortable');
252
        if (this.options.preSort && this.options.preSort[colname]) {
253
          if (this.options.preSort[colname] == 'asc') {
254
            th.addClass('sorted-asc');
255
            this.sortered[colname] = 'asc';
256
          } else if (this.options.preSort[colname] == 'desc') {
257
            th.addClass('sorted-desc');
258
            this.sortered[colname] = 'desc';
259
          }
260
        }
261
        //sorted-desc
262
        th.click(function () {
263
          var colname = $(this).data('colname');
264
          $(this).addClass('clickedsort');
265
          dataManager.element.find('.sortable').not('.clickedsort').removeClass('sorted-asc').removeClass('sorted-desc');
266
          $(this).removeClass('clickedsort');
267
          dataManager.sortered = {};
268
          if (!$(this).hasClass('sorted-desc') && !$(this).hasClass('sorted-asc')) {
269
            $(this).addClass('sorted-desc');
270
            dataManager.sortered[colname] = 'desc';
271
            dataManager.reload();
272
          } else if ($(this).hasClass('sorted-desc')) {
273
            $(this).removeClass('sorted-desc');
274
            $(this).addClass('sorted-asc');
275
            dataManager.sortered[colname] = 'asc';
276
            dataManager.reload();
277
          } else if ($(this).hasClass('sorted-asc')) {
278
            $(this).removeClass('sorted-asc');
279
            delete dataManager.sortered[colname];
280
            dataManager.reload();
281
          }
282
          return false;
283
        })
284
      }
285
    }
286
  }
287
  var data = {
288
    params: params,
289
    modelName: this.modelName,
290
    managerName: this.managerName,
291
    filters: filters,
292
    sortered: this.sortered,
293
    mode: this.mode,
294
    all: this.all
295
  };
296
  if (options && options.download) {
297
    data.download = true;
298
    var url = this.ajaxUrl;
299
    if (url.indexOf(inji.options.appRoot) !== 0) {
300
      url = inji.options.appRoot + url;
301
    }
302
    window.location = url + '?' + $.param(data);
303
    return;
304
  }
305
  dataManager.element.find('.datamanagertable tbody').html('<tr><td colspan="' + dataManager.element.find('thead tr th').length + '"><div class = "text-center"><img src = "' + inji.options.appRoot + 'static/moduleAsset/Ui/images/ajax-loader.gif" /></div></td></tr>');
306
  var instance = this;
307
308
309
  var windowHash = {};
310
  if (window.location.hash && window.location.hash != '#') {
311
    windowHash = JSON.parse(decodeURIComponent(window.location.hash.substr(1)));
312
  }
313
  windowHash[data.modelName + ':' + data.managerName] = data;
314
  window.location.hash = JSON.stringify(windowHash);
315
  inji.Server.request({
316
    url: this.ajaxUrl,
317
    data: data,
318
    success: function (data) {
319
      dataManager.element.find('.datamanagertable tbody').html(data.rows);
320
      dataManager.element.find('.pagesContainer').html(data.pages);
321
      if (data.summary.length > 0) {
322
        var summaryText = '<h5>Итого:</h5><ul>';
323
        for (var k in data.summary) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
324
          summaryText += '<li>' + data.summary[k].name + ': <b>' + data.summary[k].summary + '</b></li>';
325
        }
326
        summaryText += '</ul>'
327
        dataManager.element.find('.summary').html(summaryText);
328
      }
329
330
      if (dataManager.options.options && dataManager.options.options.formOnPage) {
331
        $('.' + dataManager.modelName.replace(/\\/g, '_') + '_' + dataManager.managerName + '_create_btn').each(function () {
332
          var createBtn = $(this);
333
          var btnHref = createBtn.attr('href');
334
          btnHref = btnHref.substr(0, btnHref.indexOf('redirectUrl='));
335
          btnHref += 'redirectUrl=' + window.location.pathname;
336
          createBtn.attr('href', btnHref + '&dataManagerHash=' + window.location.hash.substr(1));
337
        });
338
      }
339
340
      //dataManager.flowPages();
341
      if (dataManager.options.sortMode) {
342
        if (dataManager.mode != 'sort') {
343
          dataManager.element.find('.modeBtn').removeClass('active');
344
        } else {
345
          dataManager.element.find('.modeBtn').addClass('active');
346
        }
347
      }
348
      $(instance.element).find('.datamanagertable tbody').sortable().sortable("disable");
349
      if (dataManager.mode == 'sort') {
350
        $(instance.element).find('.datamanagertable tbody').sortable({
351
          stop: function (event, ui) {
352
            var ids = $(instance.element).find('.datamanagertable tbody tr');
353
            var i = 0;
354
            while (ids[i]) {
355
              var key = $($(ids[i++]).find('td').get(1)).text();
356
              inji.Server.request({
357
                url: 'ui/dataManager/updateRow',
358
                data: {
359
                  params: instance.params,
360
                  modelName: instance.modelName,
361
                  key: key,
362
                  col: 'weight',
363
                  col_value: i,
364
                  managerName: instance.managerName,
365
                  silence: true
366
                },
367
              });
368
            }
369
          }
370
        }).sortable("enable");
371
      }
372
      dataManager.flowPanel();
373
    }
374
  });
375
  if (dataManager.element.find('.categoryTree').length > 0) {
376
    dataManager.element.find('.categoryTree').html('<img class ="img-responsive" src = "' + inji.options.appRoot + 'static/moduleAsset/Ui/images/ajax-loader.gif" />');
377
    inji.Server.request({
378
      url: 'ui/dataManager/loadCategorys',
379
      data: {params: params, modelName: this.modelName, managerName: this.managerName},
380
      success: function (data) {
381
        dataManager.element.find('.categoryTree').html(data);
382
        dataManager.element.find('.categoryTree [data-path="' + instance.categoryPath + '"]').parent().addClass('active');
383
        dataManager.element.find('.treeview').treeview();
384
        $(instance.element).find('.categoryTree').sortable().sortable("disable");
385
        if (dataManager.mode == 'sort') {
386
          $(instance.element).find('.categoryTree ul a[data-path]').map(function () {
387
            this.onclick = null
388
          });
389
          $(instance.element).find('.categoryTree ul').sortable({
390
            stop: function (event, ui) {
391
              var ids = $(instance.element).find('li');
392
              var i = 0;
393
              while (ids[i]) {
394
                var key = $(ids[i]).find('>a').data('id');
395
                var model = $(ids[i]).find('>a').data('model');
396
                if (key && model) {
397
                  inji.Server.request({
398
                    url: 'ui/dataManager/updateRow',
399
                    data: {
400
                      params: instance.params,
401
                      modelName: model,
402
                      key: key,
403
                      col: 'weight',
404
                      col_value: i,
405
                      managerName: instance.managerName,
406
                      silence: true
407
                    },
408
                  });
409
                }
410
                i++;
411
              }
412
            }
413
          }).sortable("enable");
414
        }
415
      }
416
    });
417
  }
418
}
419
DataManager.prototype.switchCategory = function (categoryBtn) {
420
  this.categoryPath = $(categoryBtn).data('path');
421
  this.categoryId = $(categoryBtn).data('id');
422
  this.categoryIndex = $(categoryBtn).data('index');
423
  this.reload();
424
}
425
DataManager.prototype.flowPanel = function () {
426
427
  var managerHeight = $(this.element).height();
428
  var managerTop = $(this.element).offset().top;
429
  var managerBottom = managerTop + managerHeight;
430
431
  var scrollHeight = $(document).scrollTop() + $(window).height();
432
  var floater = $(this.element).find('.dataManager-bottomFloat');
433
434
  if (managerBottom > scrollHeight && managerTop < scrollHeight && scrollHeight < scrollHeight + floater.outerHeight()) {
435
    if (!floater.hasClass('floated')) {
436
      var floaterContainer = $(this.element).find('.dataManager-bottomFloat-container');
437
      floaterContainer.css('height', floater.outerHeight());
438
      floater.css('right', $(window).width() - ($(this.element).offset().left + $(this.element).width()) + 'px');
439
      floater.css('position', 'fixed');
440
      floater.addClass('floated');
441
    }
442
  } else {
443
    if (floater.hasClass('floated')) {
444
      var floaterContainer = $(this.element).find('.dataManager-bottomFloat-container');
445
      floater.css('right', 'auto');
446
      floater.css('position', 'relative');
447
      floater.removeClass('floated');
448
      floaterContainer.css('height', 'auto');
449
    }
450
  }
451
452
}
453
DataManager.prototype.groupAction = function (actionName) {
454
  var ids = '';
455
  var rows = {};
456
  $(this.element).find('.datamanagertable tbody tr').each(function () {
457
    if ($($(this).find('td').get(0)).find('[type="checkbox"]')[0].checked) {
458
      ids += ',' + $($(this).find('td').get(0)).find('[type="checkbox"]').val();
459
      rows[$($(this).find('td').get(0)).find('[type="checkbox"]').val()] = $(this);
460
    }
461
  });
462
  if (ids != '') {
463
    var action = this.options.actions[actionName];
464
    if (action.customJsChecker) {
465
      if (!window[action.customJsChecker](this, rows)) {
466
        return;
467
      }
468
    }
469
    if (action.aditionalInfo) {
470
      var id = inji.randomString();
471
      var html = '<form id ="' + id + '"><h3>Для этой груповой операции требуется дополнительная информация</h3>';
472
      for (var key in action.aditionalInfo) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
473
        var input = action.aditionalInfo[key];
474
        html += '<div class = "form-group"><label>' + input.label + '</label><input type="' + input.type + '" name ="' + key + '" class = "form-control" value = "" /></div>';
475
      }
476
      html += '<div class = "form-group"><button class="btn btn-primary" >' + action.name + '</button></div></form>';
477
      inji.Ui.modals.show('Дополнительная информация', html, 'modal' + id);
478
      var instance = this;
479
      $('#' + id).submit(function () {
480
        $(this).closest('.modal').modal('hide');
481
        var adInfo = {};
482
        if ($(this).find('input').length > 0) {
483
          $.each($(this).find('input'), function () {
484
            adInfo[$(this).attr('name')] = $(this).val();
485
          });
486
        }
487
        inji.Server.request({
488
          url: 'ui/dataManager/groupAction',
489
          data: {
490
            params: instance.params,
491
            modelName: instance.modelName,
492
            ids: ids,
493
            managerName: instance.managerName,
494
            action: actionName,
495
            adInfo: adInfo
496
          },
497
          success: function () {
498
            inji.Ui.dataManagers.reloadAll();
499
          }
500
        });
501
        return false;
502
      });
503
    } else {
504
      inji.Server.request({
505
        url: 'ui/dataManager/groupAction',
506
        data: {
507
          params: this.params,
508
          modelName: this.modelName,
509
          ids: ids,
510
          managerName: this.managerName,
511
          action: actionName
512
        },
513
        success: function () {
514
          inji.Ui.dataManagers.reloadAll();
515
        }
516
      });
517
    }
518
  }
519
}
520
DataManager.prototype.rowSelection = function (type) {
521
  $(this.element).find('.datamanagertable tbody tr').each(function () {
522
    if ($($(this).find('td').get(0)).find('[type="checkbox"]')[0].checked && (type == 'unSelectAll' || type == 'inverse')) {
523
      $($(this).find('td').get(0)).find('[type="checkbox"]')[0].checked = false;
524
    } else if (!$($(this).find('td').get(0)).find('[type="checkbox"]')[0].checked && (type == 'selectAll' || type == 'inverse')) {
525
      $($(this).find('td').get(0)).find('[type="checkbox"]')[0].checked = true;
526
    }
527
  });
528
}
529
530
inji.onLoad(function () {
531
  $.each($('.dataManager'), function () {
532
    inji.Ui.dataManagers.instances[$(this).attr('id')] = new DataManager($(this));
533
  });
534
});