Passed
Push — master ( edbfbd...89a048 )
by Alexey
05:17
created

system/modules/Ui/static/js/Ui.js   F

Complexity

Total Complexity 80
Complexity/F 1.95

Size

Lines of Code 362
Function Count 41

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 0
nc 32
dl 0
loc 362
rs 3.12
c 0
b 0
f 0
wmc 80
mnd 3
bc 78
fnc 41
bpm 1.9024
cpm 1.9512
noi 15

14 Functions

Rating   Name   Duplication   Size   Complexity  
A Editors.loadAll 0 3 1
B Editors.loadIn 0 36 2
A Editors.beforeSubmit 0 12 2
A Ui.js ➔ Editors 0 10 1
A Editors.checkEditors 0 5 3
B Modals.show 0 38 5
A Ui.js ➔ Forms 0 4 1
A Ui.js ➔ Modals 0 3 1
B Forms.submitAjax 0 44 5
A Forms.delRowFromList 0 3 1
B Forms.checkAditionals 0 22 5
A Forms.popUp 0 23 3
A Forms.addRowToList 0 7 1
A Ui.js ➔ ActiveForm 0 69 1

How to fix   Complexity   

Complexity

Complex classes like system/modules/Ui/static/js/Ui.js 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
/**
2
 * Main Ui object
3
 * 
4
 * @returns {Ui}
5
 */
6
inji.Ui = new function () {
7
  inji.onLoad(function () {
8
    inji.Ui.bindMenu($('.nav-list-categorys'));
9
    inji.Ui.modals = new Modals();
10
    inji.Ui.forms = new Forms();
11
    inji.Ui.editors = new Editors();
12
  });
13
14
  this.bindMenu = function (container) {
15
    container.find('.nav-left-ml').toggle();
16
    container.find('label.nav-toggle span').click(function () {
17
      $(this).parent().parent().children('ul.nav-left-ml').toggle(300);
18
      var cs = $(this).attr("class");
19
      if (cs == 'nav-toggle-icon glyphicon glyphicon-chevron-right') {
20
        $(this).removeClass('glyphicon-chevron-right').addClass('glyphicon-chevron-down');
21
      }
22
      if (cs == 'nav-toggle-icon glyphicon glyphicon-chevron-down') {
23
        $(this).removeClass('glyphicon-chevron-down').addClass('glyphicon-chevron-right');
24
      }
25
    });
26
  };
27
  this.requestInfo = function (options, callback) {
28
    var id = 'resultForm' + inji.randomString();
29
    var body = '<form id ="' + id + '">';
30
    body += '<h2>' + options.header + '</h2>';
31
    for (var key in options.inputs) {
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...
32
      body += '<div class = "form-group">';
33
      body += '<label>' + options.inputs[key].label + '</label>';
34
      body += '<input type = "' + options.inputs[key].type + '" name = "' + key + '" class ="form-control" />';
35
      body += '</div>';
36
    }
37
    body += '<button class = "btn btn-primary">' + options.btn + '</button>';
38
    body += '</form>';
39
    var modal = inji.Ui.modals.show('', body);
40
    $('#' + id).on('submit', function () {
41
      callback($('#' + id).serializeArray());
42
      modal.modal('hide');
43
      return false;
44
    });
45
  }
46
}
47
48
49
50
/**
51
 * Editors
52
 * 
53
 */
54
Editors = function () {
0 ignored issues
show
Bug introduced by
The variable Editors seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.Editors.
Loading history...
55
  this.ckeditor = false;
56
  this.checkEditors();
57
  inji.on('loadScript', function () {
58
    inji.Ui.editors.checkEditors();
59
  });
60
  inji.onLoad(function () {
61
    inji.Ui.editors.loadIn('.htmleditor');
62
  })
63
}
64
Editors.prototype.checkEditors = function () {
65
  if (!this.ckeditor && typeof CKEDITOR != 'undefined') {
66
    this.ckeditor = true;
67
  }
68
}
69
Editors.prototype.loadAll = function () {
70
71
}
72
Editors.prototype.loadIn = function (selector, search) {
73
  if (this.ckeditor) {
74
    setTimeout(function () {
75
      var instances;
76
      if (typeof search != 'undefined') {
77
        instances = $(selector).find(search);
78
      } else {
79
        instances = $(selector);
80
      }
81
      $.each(instances, function () {
82
        var editor;
83
        var _this = this;
84
        if ($(this).closest('.modal').length == 0 || $(this).closest('.modal').hasClass('in')) {
85
          editor = $(_this).ckeditor({customConfig: inji.options.appRoot + 'static/moduleAsset/libs/libs/ckeditor/program/userConfig.php'});
86
        }
87
        if ($(this).closest('.modal').length != 0) {
88
          $(this).closest('.modal').on('shown.bs.modal', function () {
89
            setTimeout(function () {
90
              editor = $(_this).ckeditor({customConfig: inji.options.appRoot + 'static/moduleAsset/libs/libs/ckeditor/program/userConfig.php'});
91
            }, 1000);
92
          })
93
          $(this).closest('.modal').on('hide.bs.modal', function () {
94
            if (editor.editor) {
0 ignored issues
show
Bug introduced by
The variable editor does not seem to be initialized in case $(this).closest(".modal"....modal").hasClass("in") on line 84 is false. Are you sure this can never be the case?
Loading history...
95
              editor.editor.updateElement();
96
              editor.editor.destroy();
97
              delete editor.editor
98
              $(this).closest('.modal').unbind('hide.bs.modal');
99
              $(this).closest('.modal').unbind('shown.bs.modal');
100
            }
101
102
          })
103
        }
104
      })
105
    }, 1000);
106
  }
107
}
108
Editors.prototype.beforeSubmit = function (form) {
109
  if (this.ckeditor) {
110
    $.each(CKEDITOR.instances, function () {
111
      this.updateElement();
112
    })
113
    $.each($(form).find('.cke'), function () {
114
      var instance = $(this).attr('id').replace('cke_', '');
115
      $(CKEDITOR.instances[instance].element).closest('.modal').unbind();
116
      CKEDITOR.instances[instance].destroy();
117
    });
118
  }
119
}
120
/**
121
 * Modals objects
122
 * 
123
 * @returns {Modals}
124
 */
125
Modals = function () {
0 ignored issues
show
Bug introduced by
The variable Modals seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.Modals.
Loading history...
126
  this.modals = 0;
127
}
128
Modals.prototype.show = function (title, body, code, size) {
129
  if (code == null) {
130
    code = 'modal' + (++this.modals);
131
  }
132
  if ($('#' + code).length == 0) {
133
    if (size == null) {
134
      size = '';
135
    }
136
    if (title) {
137
      title = '<div class="modal-header">\
138
                  <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>\
139
                  <h4 class="modal-title">' + title + '</h4>\
140
                </div>';
141
    } else {
142
      title = '';
143
    }
144
    var html = '\
145
          <div class="modal fade" id = "' + code + '" >\
146
            <div class="modal-dialog ' + size + '">\
147
              <div class="modal-content">\
148
                ' + title + '\
149
                <div class="modal-body">\
150
                ' + body + '\
151
                </div>\
152
                <div class="modal-footer">\
153
                  <button type="button" class="btn btn-default" data-dismiss="modal">Закрыть</button>\
154
                </div>\
155
              </div>\
156
            </div>\
157
          </div>';
158
    $('body').append(html);
159
160
  }
161
  var modal = $('#' + code);
162
  $('body').append(modal);
163
  modal.modal('show');
164
  return modal;
165
}
166
/**
167
 * Forms object
168
 * 
169
 * @returns {Forms}
170
 */
171
function Forms() {
172
  this.dataManagers = 0;
173
  this.formCallbacks = {};
174
}
175
Forms.prototype.popUp = function (item, params, callback) {
176
  var code = item;
177
178
  if (typeof params == 'undefined') {
179
    params = {};
180
  }
181
  if (typeof (params.relation) != 'undefined') {
182
    code += params.relation;
183
  }
184
  code = code.replace(/:/g, '_').replace(/\\/g, '_');
185
  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');
186
  inji.Server.request({
187
    url: 'ui/formPopUp/',
188
    data: {item: item, params: params},
189
    success: function (data) {
190
      modal.find('.modal-body').html(data);
191
      if (callback) {
192
        inji.Ui.forms.formCallbacks[modal.find('.form').attr('id')] = callback;
193
      }
194
      inji.Ui.editors.loadIn(modal.find('.modal-body'), '.htmleditor');
195
    }
196
  });
197
}
198
Forms.prototype.submitAjax = function (form, params) {
199
  inji.Ui.editors.beforeSubmit(form);
200
  var form = $(form);
201
  var container = form.parent().parent();
202
  var btn = form.find('button');
203
  btn.text('Подождите');
204
  btn[0].disabled = true;
205
  btn.data('loading-text', "Подождите");
206
207
  var url = form.attr('action');
208
  if (params) {
209
    var first = true;
210
    if (url.indexOf('?') >= 0) {
211
      first = false;
212
    }
213
    for (var key in params) {
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...
214
      url += (first ? '?' : '&') + key + '=' + params[key];
215
    }
216
  }
217
  var formData = new FormData(form[0]);
218
  inji.Server.request({
219
    url: url,
220
    type: 'POST',
221
    data: formData,
222
    processData: false,
223
    success: function (data) {
224
      if (inji.Ui.forms.formCallbacks[form.attr('id')]) {
225
        inji.Ui.forms.formCallbacks[form.attr('id')]();
226
        delete inji.Ui.forms.formCallbacks[form.attr('id')];
227
      }
228
      container.html(data);
229
      inji.Ui.editors.loadIn(container, '.htmleditor');
230
      inji.Ui.dataManagers.reloadAll();
231
      if (params && !params.notSave) {
232
        var btn = container.find('form button');
233
        var text = btn.text();
234
        btn.text('Изменения сохранены!');
235
        setTimeout(function () {
236
          btn.text(text)
237
        }, 3000);
238
      }
239
    }
240
  });
241
}
242
Forms.prototype.addRowToList = function (btn) {
243
  var container = $(btn).closest('.dynamicList');
244
  var counter = parseInt(container.find('.sourceRow').data('counter')) + 1;
245
  container.find('.sourceRow').data('counter', counter);
246
  var trHtml = container.find('.sourceRow script').html().replace(/^\/\*/g, '').replace(/\*\/$/g, '').replace(/\[counterPlaceholder\]/g, '[' + counter + ']');
247
  container.find('.listBody').append(trHtml);
248
}
249
Forms.prototype.checkAditionals = function (select) {
250
  var selectedInputAd = $(select).find('option:selected').attr('data-aditionalInput');
251
  var nextSelect = $(select).next();
252
  i = 0;
0 ignored issues
show
Bug introduced by
The variable i seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.i.
Loading history...
253
  if ($(select).data('aditionalEnabled') == 1) {
254
    $(select).data('aditionalEnabled', 0);
255
  }
256
  while (nextSelect.length) {
257
    if (i != selectedInputAd) {
258
      nextSelect[0].disabled = true;
259
      nextSelect.addClass('hidden');
260
    } else {
261
      if ($(select).data('aditionalEnabled') != 1) {
262
        $(select).data('aditionalEnabled', 1);
263
      }
264
      nextSelect[0].disabled = false;
265
      nextSelect.removeClass('hidden');
266
    }
267
    nextSelect = $(nextSelect).next();
268
    i++;
269
  }
270
}
271
Forms.prototype.delRowFromList = function (btn) {
272
  $(btn).closest('tr').remove();
273
};
274
275
inji.Ui.activeForms = new function () {
276
  this.activeForms = [];
277
  this.get = function (selector) {
278
    var element = inji.get(selector);
279
    if (element && element.data('activeFormIndex') !== null) {
280
      return this.activeForms[element.data('activeFormIndex')];
281
    }
282
    this.initial(element);
283
  };
284
  this.initial = function (element) {
285
    var activeForm = new ActiveForm();
286
    this.activeForms.push(activeForm);
287
288
    activeForm.index = this.activeForms.length - 1;
289
    activeForm.element = element;
290
    activeForm.modelName = element.data('modelname');
291
    activeForm.formName = element.data('formname');
292
    activeForm.inputs = element.data('inputs');
293
294
    element.element.setAttribute('activeFormIndex', activeForm.index);
295
296
    activeForm.load();
297
  }
298
}
299
function ActiveForm() {
300
  this.modelName;
0 ignored issues
show
introduced by
The result of the property access to this.modelName is not used.
Loading history...
301
  this.formName;
0 ignored issues
show
introduced by
The result of the property access to this.formName is not used.
Loading history...
302
  this.reqestProcess;
0 ignored issues
show
introduced by
The result of the property access to this.reqestProcess is not used.
Loading history...
303
  this.inputs = {};
304
  this.index;
0 ignored issues
show
introduced by
The result of the property access to this.index is not used.
Loading history...
305
  this.element;
0 ignored issues
show
introduced by
The result of the property access to this.element is not used.
Loading history...
306
  this.load = function () {
307
    for (var inputName in this.inputs) {
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...
308
      var inputParams = this.inputs[inputName];
309
      var self = this;
310
      if (this.inputHandlers[inputParams.type]) {
311
        var query = '#' + this.element.element.id + ' [name="query-ActiveForm_' + this.formName + '[' + this.modelName.replace(/\\/g, '\\\\') + '][' + inputName + ']"]';
312
        this.inputHandlers[inputParams.type](inji.get(query), inputName, this);
313
      }
314
      if (inputParams.onChange == 'reloadForm') {
315
        var query = '#' + this.element.element.id + ' [name="ActiveForm_' + this.formName + '[' + this.modelName.replace(/\\/g, '\\\\') + '][' + inputName + ']"]';
316
        $(query).on('change', function () {
317
          inji.Ui.forms.submitAjax($('#' + self.element.element.id + ' form')[0], {notSave: true});
0 ignored issues
show
Bug introduced by
The variable self is changed as part of the for-each loop for example by this on line 309. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
318
        })
319
      }
320
    }
321
  };
322
  this.inputHandlers = {
323
    search: function (element, inputName, activeForm) {
324
      element.element.onkeyup = function () {
325
        var inputContainer = element.element.parentNode;
326
        var selectedDiv = inputContainer.querySelector('.form-search-cur');
327
        var resultsDiv = inputContainer.querySelector('.form-search-results');
328
        resultsDiv.innerHTML = '<div class = "text-center"><img src = "' + inji.options.appRoot + 'static/moduleAsset/Ui/images/ajax-loader.gif" /></div>';
329
        if (this.reqestProcess) {
330
          this.reqestProcess.abort()
331
        }
332
        this.reqestProcess = inji.Server.request({
333
          url: 'ui/activeForm/search',
334
          data: {
335
            modelName: activeForm.modelName,
336
            formName: activeForm.formName,
337
            inputName: inputName,
338
            search: this.value
339
          },
340
          success: function (results) {
341
            resultsDiv.innerHTML = '';
342
            for (var key in results) {
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...
343
              var result = results[key];
344
              var resultElement = document.createElement("div");
345
              resultElement.setAttribute('objectid', key);
346
              resultElement.appendChild(document.createTextNode(result));
347
              resultElement.onclick = function () {
348
                var value = 0;
349
                for (key in this.attributes) {
350
                  if (this.attributes[key].name == 'objectid') {
0 ignored issues
show
introduced by
The variable key is changed by the for-each loop on line 349. Only the value of the last iteration will be visible in this function if it is called outside of the loop.
Loading history...
351
                    value = this.attributes[key].value;
352
                  }
353
                }
354
                inputContainer.querySelector('[type="hidden"]').value = value;
355
                inputContainer.querySelector('[type="text"]').value = this.innerHTML;
356
                selectedDiv.innerHTML = 'Выбрано: ' + this.innerHTML;
357
                resultsDiv.innerHTML = '';
358
              }
359
              resultsDiv.appendChild(resultElement);
360
            }
361
            resultsDiv.style.display = 'block';
362
          }
363
        })
364
      };
365
    }
366
  };
367
}