@osimatic/helpers-js 1.5.3 → 1.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/form_helper.js CHANGED
@@ -1,62 +1,70 @@
1
1
  class FormHelper {
2
2
  static init(form, onSubmitCallback, submitButton=null) {
3
3
  FormHelper.reset(form, submitButton);
4
- submitButton = null != submitButton ? submitButton : form.find('button[name="validate"]');
5
- submitButton.off('click').click(function(e) {
4
+ submitButton = null != submitButton ? submitButton : form.querySelector('button[name="validate"]');
5
+ submitButton.onclick = function(e) {
6
6
  e.preventDefault();
7
- FormHelper.buttonLoader($(this), 'loading');
7
+ FormHelper.buttonLoader(this, 'loading');
8
8
  FormHelper.hideFormErrors(form);
9
9
  if (typeof onSubmitCallback == 'function') {
10
10
  onSubmitCallback(form, submitButton);
11
11
  }
12
- });
12
+ };
13
13
  return form;
14
14
  }
15
15
 
16
16
  static reset(form, submitButton=null) {
17
- submitButton = null != submitButton ? submitButton : form.find('button[name="validate"]');
18
- form.find('input[name]:not([type="checkbox"], [type="radio"]), select:not(.selectpicker), textarea').each((idx, el) => $(el).val('')).off('change');
19
- form.find('select.selectpicker').each((idx, el) => $(el).val(''));
17
+ submitButton = null != submitButton ? submitButton : form.querySelector('button[name="validate"]');
18
+ form.querySelectorAll('input[name]:not([type="checkbox"]):not([type="radio"]), select:not(.selectpicker), textarea').forEach(el => {
19
+ el.value = '';
20
+ el.onchange = null;
21
+ });
22
+ form.querySelectorAll('select.selectpicker').forEach(el => el.value = '');
20
23
  FormHelper.buttonLoader(submitButton, 'reset');
21
24
  FormHelper.hideFormErrors(form);
22
25
  return form;
23
26
  }
24
27
 
25
28
  static populateForm(form, data) {
26
- form.find('[name="employees_display_type"][value="NONE"]').prop('checked', true); //todo à retirer
29
+ const employeesDisplayType = form.querySelector('[name="employees_display_type"][value="NONE"]');
30
+ if (employeesDisplayType) employeesDisplayType.checked = true; //todo à retirer
27
31
 
28
- $.each(data, function(key, value) {
32
+ Object.entries(data).forEach(([key, value]) => {
29
33
  if (value == null) {
30
34
  return;
31
35
  }
32
36
 
33
37
  if (typeof value == 'object') {
34
- let select = form.find('[name="'+key+'[]"]');
35
- select.find('option').prop('selected', false);
36
- select.data('default_id', value.join(','));
37
- $.each(value, function(key, val) {
38
- select.find('option[value="'+val+'"]').prop('selected', true);
39
- });
38
+ let select = form.querySelector('[name="'+key+'[]"]');
39
+ if (select) {
40
+ select.querySelectorAll('option').forEach(o => o.selected = false);
41
+ select.dataset.default_id = value.join(',');
42
+ value.forEach(val => {
43
+ const opt = select.querySelector('option[value="'+val+'"]');
44
+ if (opt) opt.selected = true;
45
+ });
46
+ }
40
47
  return;
41
48
  }
42
49
 
43
- let input = form.find('[name="'+key+'"]');
50
+ const inputs = form.querySelectorAll('[name="'+key+'"]');
51
+ if (!inputs.length) return;
44
52
 
45
- if (input.prop('type') === 'radio' || input.prop('type') === 'checkbox') {
46
- input.prop('checked', false);
47
- input.filter('[value="'+value+'"]').prop('checked', true);
53
+ if (inputs[0].type === 'radio' || inputs[0].type === 'checkbox') {
54
+ inputs.forEach(i => i.checked = false);
55
+ const target = form.querySelector('[name="'+key+'"][value="'+value+'"]');
56
+ if (target) target.checked = true;
48
57
  return;
49
58
  }
50
59
 
51
- input.val(value);
52
- // console.log(form.find('[name="'+key+'"]').length);
60
+ inputs[0].value = value;
61
+ // console.log(form.querySelectorAll('[name="'+key+'"]').length);
53
62
  });
54
63
  }
55
64
 
56
65
 
57
66
  static getFormData(form) {
58
- // var formElement = document.getElementById("myFormElement");
59
- return new FormData(form[0]);
67
+ return new FormData(form);
60
68
  }
61
69
 
62
70
  static getDataFromFormData(formData) {
@@ -69,14 +77,7 @@ class FormHelper {
69
77
  }
70
78
 
71
79
  static getFormDataQueryString(form) {
72
- return form.serialize();
73
- // cette soluce marche pas pour les clés sous forme de tableau : ids[]=1&ids[]=2
74
- /*
75
- return form.serializeArray().reduce(function(obj, item) {
76
- obj[item.name] = item.value;
77
- return obj;
78
- }, {});
79
- */
80
+ return new URLSearchParams(new FormData(form)).toString();
80
81
  }
81
82
 
82
83
 
@@ -86,10 +87,10 @@ class FormHelper {
86
87
  // ------------------------------------------------------------
87
88
 
88
89
  static getInputValue(input) {
89
- if (typeof input == 'undefined') {
90
+ if (typeof input == 'undefined' || input == null) {
90
91
  return null;
91
92
  }
92
- let value = $(input).val();
93
+ let value = input.value;
93
94
  if (value === null || value === '') {
94
95
  return null;
95
96
  }
@@ -97,7 +98,7 @@ class FormHelper {
97
98
  }
98
99
 
99
100
  static getLinesOfTextarea(textarea) {
100
- return textarea.val().replace(/(\r\n|\n|\r)/g, "\n").split("\n").filter(word => word.length > 0);
101
+ return textarea.value.replace(/(\r\n|\n|\r)/g, "\n").split("\n").filter(word => word.length > 0);
101
102
  }
102
103
 
103
104
  static setOnInputChange(input, callback, doneTypingInterval=700) {
@@ -105,18 +106,18 @@ class FormHelper {
105
106
  let typingTimer; // timer identifier
106
107
 
107
108
  // on keyup, start the countdown
108
- input.on('keyup', function () {
109
+ input.addEventListener('keyup', function () {
109
110
  clearTimeout(typingTimer);
110
111
  typingTimer = setTimeout(callback, doneTypingInterval); // time in ms
111
112
  });
112
113
 
113
114
  // on keydown, clear the countdown
114
- input.on('keydown', function () {
115
+ input.addEventListener('keydown', function () {
115
116
  clearTimeout(typingTimer);
116
117
  });
117
118
 
118
119
  // on focusout, clear the countdown and call callback
119
- input.on('focusout', function () {
120
+ input.addEventListener('focusout', function () {
120
121
  clearTimeout(typingTimer);
121
122
  callback();
122
123
  });
@@ -127,26 +128,27 @@ class FormHelper {
127
128
  // ------------------------------------------------------------
128
129
 
129
130
  static resetSelectOption(form, selectName) {
130
- form.find('select[name="'+selectName+'"] option').prop('disabled', false).prop('selected', false);
131
+ form.querySelectorAll('select[name="'+selectName+'"] option').forEach(o => {
132
+ o.disabled = false;
133
+ o.selected = false;
134
+ });
131
135
  }
132
136
  static setSelectedSelectOption(form, selectName, optionValue) {
133
- form.find('select[name="'+selectName+'"] option[value="'+optionValue+'"]').prop('selected', true);
137
+ const opt = form.querySelector('select[name="'+selectName+'"] option[value="'+optionValue+'"]');
138
+ if (opt) opt.selected = true;
134
139
  }
135
140
  static setSelectedSelectOptions(form, selectName, optionValues) {
136
- $.each(optionValues, function(idx, id) {
137
- FormHelper.setSelectedSelectOption(form, selectName, id);
138
- });
141
+ optionValues.forEach(id => FormHelper.setSelectedSelectOption(form, selectName, id));
139
142
  }
140
143
  static disableSelectOption(form, selectName, optionValue) {
141
- form.find('select[name="'+selectName+'"] option[value="'+optionValue+'"]').prop('disabled', true);
144
+ const opt = form.querySelector('select[name="'+selectName+'"] option[value="'+optionValue+'"]');
145
+ if (opt) opt.disabled = true;
142
146
  }
143
147
  static disableSelectOptions(form, selectName, optionValues) {
144
- $.each(optionValues, function(idx, id) {
145
- FormHelper.disableSelectOption(form, selectName, id);
146
- });
148
+ optionValues.forEach(id => FormHelper.disableSelectOption(form, selectName, id));
147
149
  }
148
150
  static countSelectOptions(form, selectName) {
149
- return form.find('select[name="'+selectName+'"] option:not([disabled])').length;
151
+ return form.querySelectorAll('select[name="'+selectName+'"] option:not([disabled])').length;
150
152
  }
151
153
 
152
154
 
@@ -155,23 +157,21 @@ class FormHelper {
155
157
  // ------------------------------------------------------------
156
158
 
157
159
  static getCheckedValues(inputs) {
158
- return inputs.map(function() {
159
- if (this.checked) {
160
- return this.value;
161
- }
162
- }).get();
160
+ return [...inputs].filter(i => i.checked).map(i => i.value);
163
161
  }
164
162
 
165
163
  static setCheckedValues(inputs, defaultValues) {
166
- $.each(defaultValues, function(idx, value) {
167
- inputs.parent().find('[value="'+value+'"]').prop('checked', true);
164
+ const parent = inputs[0]?.parentElement;
165
+ defaultValues.forEach(value => {
166
+ if (parent) {
167
+ const t = parent.querySelector('[value="'+value+'"]');
168
+ if (t) t.checked = true;
169
+ }
168
170
  });
169
171
  }
170
172
 
171
173
  static getInputListValues(inputs) {
172
- return inputs.map(function() {
173
- return this.value;
174
- }).get().filter(word => word.length > 0);
174
+ return [...inputs].map(i => i.value).filter(word => word.length > 0);
175
175
  }
176
176
 
177
177
 
@@ -180,54 +180,42 @@ class FormHelper {
180
180
  // ------------------------------------------------------------
181
181
 
182
182
  static initTypeFields(form) {
183
- //if ( $('[type="date"]').prop('type') != 'date' ) {
184
- // $('[type="date"]').datepicker();
185
- //}
186
183
  if (typeof Modernizr != 'undefined') {
187
184
  if (!Modernizr.inputtypes.date) {
188
- // $.fn.datepicker.defaults.language = 'fr';
189
- // $.datepicker.setDefaults( $.datepicker.regional["fr"]);
190
- form.find('input[type="date"]')
191
- .css('max-width', '120px')
192
- // 28/06/2021 : désactivation du datepicker car safari le gere en natif
193
- /*
194
- .datepicker({
195
- dateFormat: 'yy-mm-dd',
196
- changeMonth: true,
197
- changeYear: true,
198
- showOn: "both",
199
- buttonImage: ROOT_PATH+'images/icons/calendar-alt.png',
200
- buttonImageOnly: true,
201
- })
202
- */
203
- ;
204
- //form.find('input[type="date"]').datepicker({dateFormat: 'yy-mm-dd', minDate: "-10Y", maxDate: "+3Y"});
205
- // $("#date_conf").datepicker("option", $.datepicker.regional["fr"]);
206
- // $("#date_conf").datepicker("option", "dateFormat", "yy-mm-dd");
185
+ form.querySelectorAll('input[type="date"]').forEach(el => el.style.maxWidth = '120px');
207
186
  }
208
187
  if (!Modernizr.inputtypes.time) {
209
- form.find('input[type="time"]')
210
- .css('max-width', '100px')
211
- .attr('placeholder', 'hh:mm')
212
- ;
213
- form.find('input[type="time"][step="1"]').attr('placeholder', 'hh:mm:ss');
188
+ form.querySelectorAll('input[type="time"]').forEach(el => {
189
+ el.style.maxWidth = '100px';
190
+ el.placeholder = 'hh:mm';
191
+ });
192
+ form.querySelectorAll('input[type="time"][step="1"]').forEach(el => el.placeholder = 'hh:mm:ss');
214
193
  }
215
194
  }
216
195
 
217
196
  // Show/Hide password
218
- let linkTogglePassword = $('<span class="input-group-text"><i class="fas fa-eye toggle_password"></i></span>');
219
- linkTogglePassword.find('i').click(function(e) {
220
- e.preventDefault();
221
- let input = $(this).closest('.input-group').find('input');
222
- let passwordHidden = input.attr('type') === 'password';
223
- input.attr('type', passwordHidden ? 'text' : 'password');
224
- $(this).removeClass('fa-eye fa-eye-slash').addClass(passwordHidden ? 'fa-eye-slash' : 'fa-eye');
197
+ form.querySelectorAll('input[type="password"]').forEach(inputEl => {
198
+ const wrapper = document.createElement('div');
199
+ wrapper.className = 'input-group password';
200
+ inputEl.parentNode.insertBefore(wrapper, inputEl);
201
+ wrapper.appendChild(inputEl);
202
+ const span = document.createElement('span');
203
+ span.className = 'input-group-text';
204
+ span.innerHTML = '<i class="fas fa-eye toggle_password"></i>';
205
+ span.querySelector('i').addEventListener('click', function(e) {
206
+ e.preventDefault();
207
+ const inp = this.closest('.input-group').querySelector('input');
208
+ const passwordHidden = inp.type === 'password';
209
+ inp.type = passwordHidden ? 'text' : 'password';
210
+ this.classList.remove('fa-eye', 'fa-eye-slash');
211
+ this.classList.add(passwordHidden ? 'fa-eye-slash' : 'fa-eye');
212
+ });
213
+ wrapper.appendChild(span);
225
214
  });
226
- form.find('input[type="password"]').wrap('<div class="input-group password"></div>').after(linkTogglePassword);
227
215
  }
228
216
 
229
217
  static hideField(inputOrSelect) {
230
- inputOrSelect.closest('.form-group').addClass('hide');
218
+ inputOrSelect.closest('.form-group')?.classList.add('hide');
231
219
  }
232
220
 
233
221
  // ------------------------------------------------------------
@@ -283,7 +271,7 @@ class FormHelper {
283
271
  }
284
272
 
285
273
  static hideFormErrors(form) {
286
- form.find('div.form_errors').remove();
274
+ form.querySelectorAll('div.form_errors').forEach(el => el.remove());
287
275
  return form;
288
276
  }
289
277
 
@@ -311,11 +299,6 @@ class FormHelper {
311
299
  this.displayFormErrorsFromText(form, this.getFormErrorText(errors), errorWrapperDiv);
312
300
  if (btnSubmit != null) {
313
301
  FormHelper.buttonLoader(btnSubmit, 'reset');
314
- //if (btnSubmit.buttonLoader != null) {
315
- // btnSubmit.buttonLoader('reset');
316
- //} else {
317
- // btnSubmit.attr('disabled', false).button('reset');
318
- //}
319
302
  }
320
303
  }
321
304
 
@@ -323,32 +306,34 @@ class FormHelper {
323
306
  let errorDiv = '<div class="alert alert-danger form_errors">'+errorLabels+'</div>';
324
307
 
325
308
  if (null != errorWrapperDiv) {
326
- errorWrapperDiv.append(errorDiv);
309
+ errorWrapperDiv.insertAdjacentHTML('beforeend', errorDiv);
327
310
  return;
328
311
  }
329
312
 
330
- if (form.find('.form_errors_content').length) {
331
- form.find('.form_errors_content').append(errorDiv);
313
+ const formErrorsContent = form.querySelector('.form_errors_content');
314
+ if (formErrorsContent) {
315
+ formErrorsContent.insertAdjacentHTML('beforeend', errorDiv);
332
316
  return;
333
317
  }
334
318
 
335
319
  let errorsParentDiv = form;
336
- if (form.find('.modal-body').length) {
337
- errorsParentDiv = form.find('.modal-body');
320
+ const modalBody = form.querySelector('.modal-body');
321
+ if (modalBody) {
322
+ errorsParentDiv = modalBody;
338
323
  }
339
324
 
340
- let firstFormGroup = errorsParentDiv.find('.form-group:first');
341
- if (firstFormGroup.length) {
342
- if (firstFormGroup.parent().parent().hasClass('row')) {
343
- firstFormGroup.parent().parent().before(errorDiv);
325
+ const firstFormGroup = errorsParentDiv.querySelector('.form-group');
326
+ if (firstFormGroup) {
327
+ if (firstFormGroup.parentElement?.parentElement?.classList.contains('row')) {
328
+ firstFormGroup.parentElement.parentElement.insertAdjacentHTML('beforebegin', errorDiv);
344
329
  }
345
330
  else {
346
- errorsParentDiv.find('.form-group:first').before(errorDiv);
331
+ firstFormGroup.insertAdjacentHTML('beforebegin', errorDiv);
347
332
  }
348
333
  return;
349
334
  }
350
335
 
351
- errorsParentDiv.prepend(errorDiv);
336
+ errorsParentDiv.insertAdjacentHTML('afterbegin', errorDiv);
352
337
  }
353
338
 
354
339
 
@@ -357,33 +342,31 @@ class FormHelper {
357
342
  // ------------------------------------------------------------
358
343
 
359
344
  static buttonLoader(button, action) {
360
- button = $(button);
361
345
  if (action === 'start' || action === 'loading') {
362
- if (button.attr('disabled')) {
363
- return self;
346
+ if (button.disabled) {
347
+ return button;
364
348
  }
365
- button.attr('disabled', true);
366
- button.data('btn-text', button.html());
349
+ button.disabled = true;
350
+ button.dataset.btnText = button.innerHTML;
367
351
  //let text = '<span class="spinner"><i class=\'fa fa-circle-notch fa-spin\'></i></span>Traitement en cours…';
368
352
  let text = '<i class=\'fa fa-circle-notch fa-spin\'></i> Traitement en cours…';
369
- if (button.data('load-text') != null && button.data('load-text') !== '') {
370
- text = button.data('load-text');
353
+ if (button.dataset.loadText != null && button.dataset.loadText !== '') {
354
+ text = button.dataset.loadText;
371
355
  }
372
- if (button.data('loading-text') != null && button.data('loading-text') !== '') {
373
- text = button.data('loading-text');
356
+ if (button.dataset.loadingText != null && button.dataset.loadingText !== '') {
357
+ text = button.dataset.loadingText;
374
358
  }
375
- button.html(text);
376
- button.addClass('disabled');
359
+ button.innerHTML = text;
360
+ button.classList.add('disabled');
377
361
  }
378
362
  if (action === 'stop' || action === 'reset') {
379
- button.html(button.data('btn-text'));
380
- button.removeClass('disabled');
381
- button.attr('disabled', false);
382
- //button.removeAttr("disabled");
363
+ button.innerHTML = button.dataset.btnText;
364
+ button.classList.remove('disabled');
365
+ button.disabled = false;
383
366
  }
384
367
  return button;
385
368
  }
386
-
369
+
387
370
 
388
371
  }
389
372
 
@@ -408,35 +391,44 @@ class ArrayField {
408
391
  return typeof options[optionName] != 'undefined' && null !== options[optionName];
409
392
  }
410
393
 
394
+ function createElement(html) {
395
+ const tmpDiv = document.createElement('div');
396
+ tmpDiv.innerHTML = html.trim();
397
+ return tmpDiv.firstElementChild;
398
+ }
399
+
411
400
  let itemsList = defaultValues;
412
401
 
413
- if (!formGroupDiv.find('table').length) {
414
- formGroupDiv.append($('<table class="table table-sm"><tbody></tbody></table>'));
402
+ if (!formGroupDiv.querySelector('table')) {
403
+ formGroupDiv.insertAdjacentHTML('beforeend', '<table class="table table-sm"><tbody></tbody></table>');
415
404
  }
416
- if (!formGroupDiv.find('.list_empty').length) {
417
- formGroupDiv.append($('<div class="list_empty">'+(isOptionDefined('list_empty_text') ? options['list_empty_text'] : '<em>aucun</em>')+'</div>'));
405
+ if (!formGroupDiv.querySelector('.list_empty')) {
406
+ formGroupDiv.insertAdjacentHTML('beforeend', '<div class="list_empty">'+(isOptionDefined('list_empty_text') ? options['list_empty_text'] : '<em>aucun</em>')+'</div>');
418
407
  }
419
- if (!options['entering_field_in_table'] && !formGroupDiv.find('.add_one, .add_multi').length) {
420
- let divLinks = formGroupDiv.find('.links');
421
- if (!divLinks.length) {
422
- divLinks = $('<div class="links text-center"></div>');
423
- formGroupDiv.append(divLinks);
408
+ if (!options['entering_field_in_table'] && !formGroupDiv.querySelector('.add_one, .add_multi')) {
409
+ let divLinks = formGroupDiv.querySelector('.links');
410
+ if (!divLinks) {
411
+ divLinks = createElement('<div class="links text-center"></div>');
412
+ formGroupDiv.appendChild(divLinks);
424
413
  }
425
414
 
426
415
  if (options['add_one_button_enabled']) {
427
- divLinks.append($('<a href="#" class="add_one btn btn-sm btn-success">'+(isOptionDefined('add_one_button_label') ? options['add_one_button_label'] : 'Ajouter')+'</a>'));
416
+ divLinks.insertAdjacentHTML('beforeend', '<a href="#" class="add_one btn btn-sm btn-success">'+(isOptionDefined('add_one_button_label') ? options['add_one_button_label'] : 'Ajouter')+'</a>');
428
417
  }
429
418
  if (options['add_multi_button_enabled']) {
430
- divLinks.append($('<a href="#" class="add_multi btn btn-sm btn-success">'+(isOptionDefined('add_multi_button_label') ? options['add_multi_button_label'] : 'Ajout multiple')+'</a>'));
419
+ divLinks.insertAdjacentHTML('beforeend', '<a href="#" class="add_multi btn btn-sm btn-success">'+(isOptionDefined('add_multi_button_label') ? options['add_multi_button_label'] : 'Ajout multiple')+'</a>');
431
420
  }
432
- formGroupDiv.append(divLinks);
421
+ formGroupDiv.appendChild(divLinks);
433
422
  }
434
423
 
435
424
  function addLine(item) {
436
- const table = formGroupDiv.find('table').removeClass('hide');
425
+ const table = formGroupDiv.querySelector('table');
426
+ table.classList.remove('hide');
437
427
  let tr;
438
- if (table.find('tbody tr.base').length) {
439
- tr = table.find('tbody tr.base').clone().removeClass('hide').removeClass('base');
428
+ const baseTr = table.querySelector('tbody tr.base');
429
+ if (baseTr) {
430
+ tr = baseTr.cloneNode(true);
431
+ tr.classList.remove('hide', 'base');
440
432
  }
441
433
  else {
442
434
  let links = '';
@@ -445,7 +437,7 @@ class ArrayField {
445
437
  }
446
438
  links += '<a href="#" title="Supprimer" class="remove btn btn-sm btn-danger ms-1"><i class="fas fa-times"></i></a>';
447
439
 
448
- tr = $(
440
+ tr = createElement(
449
441
  '<tr>' +
450
442
  '<td class="table-input" style="vertical-align: middle">' +
451
443
  (options['entering_field_in_table'] ? '<input type="text" name="'+options['input_name']+'" class="form-control pt-1 pb-1">' : '<input type="hidden" name="'+options['input_name']+'"> <span class="value"></span>') +
@@ -455,62 +447,85 @@ class ArrayField {
455
447
  );
456
448
  }
457
449
 
458
- tr.find('a.add').click(function () {
459
- const tr = $(this).closest('tr');
460
- const tableBody = tr.closest('tbody');
450
+ const addLink = tr.querySelector('a.add');
451
+ if (addLink) {
452
+ addLink.onclick = function () {
453
+ const trEl = this.closest('tr');
454
+ const tableBody = trEl.closest('tbody');
461
455
 
462
- if (isOptionDefined('nb_max_lines') && tableBody.find('tr').length >= options['nb_max_lines']) {
463
- return false;
464
- }
465
- addLine();
466
- onUpdateList();
467
- return false;
468
- });
469
- tr.find('a.remove').click(function () {
470
- const tr = $(this).closest('tr');
471
- const tableBody = tr.closest('tbody');
472
- if (options['entering_field_in_table'] && tableBody.find('tr').length <= 1) {
456
+ if (isOptionDefined('nb_max_lines') && tableBody.querySelectorAll('tr').length >= options['nb_max_lines']) {
457
+ return false;
458
+ }
459
+ addLine();
460
+ onUpdateList();
473
461
  return false;
474
- }
462
+ };
463
+ }
464
+ const removeLink = tr.querySelector('a.remove');
465
+ if (removeLink) {
466
+ removeLink.onclick = function () {
467
+ const trEl = this.closest('tr');
468
+ const tableBody = trEl.closest('tbody');
469
+ if (options['entering_field_in_table'] && tableBody.querySelectorAll('tr').length <= 1) {
470
+ return false;
471
+ }
475
472
 
476
- if (!options['entering_field_in_table'] || '' !== tr.data('item')) {
477
- itemsList.unsetVal(tr.data('item'));
478
- }
473
+ if (!options['entering_field_in_table'] || '' !== trEl.dataset.item) {
474
+ itemsList.unsetVal(trEl.dataset.item);
475
+ }
479
476
 
480
- tr.remove();
481
- onUpdateList();
482
- return false;
483
- });
477
+ trEl.remove();
478
+ onUpdateList();
479
+ return false;
480
+ };
481
+ }
484
482
 
485
483
  if (typeof item != 'undefined' && null !== item) {
486
- tr.data('item', item);
487
- tr.find('input').val(item);
488
- tr.find('span.value').text(item);
484
+ tr.dataset.item = item ?? '';
485
+ const inputEl = tr.querySelector('input');
486
+ if (inputEl) inputEl.value = item;
487
+ const spanEl = tr.querySelector('span.value');
488
+ if (spanEl) spanEl.textContent = item;
489
489
  }
490
490
 
491
- table.find('tbody').append(tr);
491
+ table.querySelector('tbody').appendChild(tr);
492
492
  return tr;
493
493
  }
494
494
 
495
495
  function onUpdateList() {
496
- formGroupDiv.find('.list_empty, table').addClass('hide');
496
+ formGroupDiv.querySelectorAll('.list_empty, table').forEach(el => el.classList.add('hide'));
497
497
 
498
498
  // Maj tableau
499
- let table = formGroupDiv.find('table');
500
- const tableLines = table.find('tbody tr:not(.base)');
499
+ let table = formGroupDiv.querySelector('table');
500
+ const tableLines = [...table.querySelectorAll('tbody tr:not(.base)')];
501
501
  if ((options['entering_field_in_table'] && tableLines.length ) || (!options['entering_field_in_table'] && itemsList.length)) {
502
- table.removeClass('hide');
502
+ table.classList.remove('hide');
503
503
  }
504
504
  else {
505
- formGroupDiv.find('.list_empty').removeClass('hide');
505
+ formGroupDiv.querySelector('.list_empty')?.classList.remove('hide');
506
506
  }
507
507
 
508
- tableLines.find('a').prop('disabled', false).removeClass('disabled');
508
+ tableLines.forEach(line => {
509
+ line.querySelectorAll('a').forEach(a => {
510
+ a.disabled = false;
511
+ a.classList.remove('disabled');
512
+ });
513
+ });
509
514
  if (isOptionDefined('nb_max_lines') && tableLines.length >= options['nb_max_lines']) {
510
- tableLines.find('a.add').prop('disabled', true).addClass('disabled');
515
+ tableLines.forEach(line => {
516
+ line.querySelectorAll('a.add').forEach(a => {
517
+ a.disabled = true;
518
+ a.classList.add('disabled');
519
+ });
520
+ });
511
521
  }
512
522
  if (options['entering_field_in_table'] && tableLines.length <= 1) {
513
- tableLines.find('a.remove').prop('disabled', true).addClass('disabled');
523
+ tableLines.forEach(line => {
524
+ line.querySelectorAll('a.remove').forEach(a => {
525
+ a.disabled = true;
526
+ a.classList.add('disabled');
527
+ });
528
+ });
514
529
  }
515
530
 
516
531
  if (typeof options['update_list_callback'] == 'function') {
@@ -521,14 +536,20 @@ class ArrayField {
521
536
  }
522
537
 
523
538
  function startAdd() {
524
- formGroupDiv.find('a.add_one, a.add_multi').addClass('hide').closest('.links').addClass('hide');
525
- formGroupDiv.find('.item_add_one, .item_add_multi').addClass('hide');
526
- formGroupDiv.find('.item_add_one, .item_add_multi').find('input[type="text"], textarea').val('');
527
- formGroupDiv.find('.item_add_one, .item_add_multi').find('.errors').addClass('hide');
539
+ formGroupDiv.querySelectorAll('a.add_one, a.add_multi').forEach(el => {
540
+ el.classList.add('hide');
541
+ el.closest('.links')?.classList.add('hide');
542
+ });
543
+ formGroupDiv.querySelectorAll('.item_add_one, .item_add_multi').forEach(el => el.classList.add('hide'));
544
+ formGroupDiv.querySelectorAll('.item_add_one input[type="text"], .item_add_multi textarea').forEach(el => el.value = '');
545
+ formGroupDiv.querySelectorAll('.item_add_one .errors, .item_add_multi .errors').forEach(el => el.classList.add('hide'));
528
546
  }
529
547
  function cancelAdd() {
530
- formGroupDiv.find('a.add_one, a.add_multi').removeClass('hide').closest('.links').removeClass('hide');
531
- formGroupDiv.find('.item_add_one, .item_add_multi').addClass('hide');
548
+ formGroupDiv.querySelectorAll('a.add_one, a.add_multi').forEach(el => {
549
+ el.classList.remove('hide');
550
+ el.closest('.links')?.classList.remove('hide');
551
+ });
552
+ formGroupDiv.querySelectorAll('.item_add_one, .item_add_multi').forEach(el => el.classList.add('hide'));
532
553
  }
533
554
 
534
555
  function addItemsInList(items) {
@@ -568,17 +589,21 @@ class ArrayField {
568
589
  if (!Array.isArray(errors)) {
569
590
  errors = [errors];
570
591
  }
571
- divAdd.find('.errors').text(errors.join('<br/>')).removeClass('hide');
592
+ const errorsEl = divAdd.querySelector('.errors');
593
+ if (errorsEl) {
594
+ errorsEl.textContent = errors.join('<br/>');
595
+ errorsEl.classList.remove('hide');
596
+ }
572
597
  }
573
598
 
574
599
  function initLinkAddOne() {
575
- if (!formGroupDiv.find('a.add_one').length || !formGroupDiv.find('a.add_one:not([disabled])').length) {
600
+ if (!formGroupDiv.querySelector('a.add_one') || !formGroupDiv.querySelector('a.add_one:not([disabled])')) {
576
601
  return;
577
602
  }
578
603
 
579
- let divAdd = formGroupDiv.find('.item_add_one');
580
- if (!divAdd.length) {
581
- divAdd = $(
604
+ let divAdd = formGroupDiv.querySelector('.item_add_one');
605
+ if (!divAdd) {
606
+ divAdd = createElement(
582
607
  '<div class="item_add_one">' +
583
608
  '<div class="alert alert-danger pt-1 pb-1 errors hide"></div>' +
584
609
  '<div class="form-inline">' +
@@ -589,33 +614,33 @@ class ArrayField {
589
614
  (isOptionDefined('form_desc')?'<br><span class="form-text">'+options['form_desc']+'</span>':'') +
590
615
  '</div>'
591
616
  );
592
- formGroupDiv.append(divAdd);
617
+ formGroupDiv.appendChild(divAdd);
593
618
  }
594
619
 
595
- divAdd.find('a.cancel').off('click').click(function () {
620
+ divAdd.querySelector('a.cancel').onclick = function () {
596
621
  cancelAdd();
597
622
  return false;
598
- });
599
- divAdd.find('a.add').off('click').click(function () {
600
- submitAddNewItem(divAdd.find('input.form-control[type="text"]').val(), divAdd);
623
+ };
624
+ divAdd.querySelector('a.add').onclick = function () {
625
+ submitAddNewItem(divAdd.querySelector('input.form-control[type="text"]').value, divAdd);
601
626
  return false;
602
- });
627
+ };
603
628
 
604
- formGroupDiv.find('a.add_one').off('click').click(function () {
629
+ formGroupDiv.querySelector('a.add_one').onclick = function () {
605
630
  startAdd();
606
- formGroupDiv.find('.item_add_one').removeClass('hide');
631
+ formGroupDiv.querySelector('.item_add_one').classList.remove('hide');
607
632
  return false;
608
- });
633
+ };
609
634
  }
610
635
 
611
636
  function initLinkAddMulti() {
612
- if (!formGroupDiv.find('a.add_multi').length || !formGroupDiv.find('a.add_multi:not([disabled])').length) {
637
+ if (!formGroupDiv.querySelector('a.add_multi') || !formGroupDiv.querySelector('a.add_multi:not([disabled])')) {
613
638
  return;
614
639
  }
615
640
 
616
- let divAdd = formGroupDiv.find('.item_add_multi');
617
- if (!divAdd.length) {
618
- divAdd = $(
641
+ let divAdd = formGroupDiv.querySelector('.item_add_multi');
642
+ if (!divAdd) {
643
+ divAdd = createElement(
619
644
  '<div class="item_add_multi">' +
620
645
  '<div class="alert alert-danger pt-1 pb-1 errors hide"></div>' +
621
646
  '<div class="form-group">' +
@@ -629,24 +654,24 @@ class ArrayField {
629
654
  '</div>' +
630
655
  '</div>'
631
656
  );
632
- formGroupDiv.append(divAdd);
657
+ formGroupDiv.appendChild(divAdd);
633
658
  }
634
659
 
635
- divAdd.find('a.cancel').off('click').click(function () {
660
+ divAdd.querySelector('a.cancel').onclick = function () {
636
661
  cancelAdd();
637
662
  return false;
638
- });
639
- divAdd.find('a.add').off('click').click(function () {
640
- const items = divAdd.find('textarea').val().normalizeBreaks("\n").split(/\n/ms).filter(value => value.length > 0);
663
+ };
664
+ divAdd.querySelector('a.add').onclick = function () {
665
+ const items = divAdd.querySelector('textarea').value.normalizeBreaks("\n").split(/\n/ms).filter(value => value.length > 0);
641
666
  submitAddNewItem(items, divAdd);
642
667
  return false;
643
- });
668
+ };
644
669
 
645
- formGroupDiv.find('a.add_multi').off('click').click(function () {
670
+ formGroupDiv.querySelector('a.add_multi').onclick = function () {
646
671
  startAdd();
647
- formGroupDiv.find('.item_add_multi').removeClass('hide');
672
+ formGroupDiv.querySelector('.item_add_multi').classList.remove('hide');
648
673
  return false;
649
- });
674
+ };
650
675
  }
651
676
 
652
677
  initLinkAddOne();
@@ -669,44 +694,70 @@ class ArrayField {
669
694
 
670
695
  class EditValue {
671
696
  static init(valueDiv, onSubmitCallback, getInputCallback) {
672
- let link = $('<a href="#" class="text-warning"><i class="fas fa-pencil-alt"></i></a>');
673
- valueDiv.parent().append('&nbsp;').append(link);
697
+ const link = document.createElement('a');
698
+ link.href = '#';
699
+ link.className = 'text-warning';
700
+ link.innerHTML = '<i class="fas fa-pencil-alt"></i>';
701
+ valueDiv.parentElement.insertAdjacentHTML('beforeend', '&nbsp;');
702
+ valueDiv.parentElement.appendChild(link);
674
703
 
675
704
  function cancelEdit(valueParentDiv) {
676
- valueParentDiv.find('a, span').removeClass('hide');
677
- valueParentDiv.find('form').remove();
705
+ valueParentDiv.querySelectorAll('a, span').forEach(el => el.classList.remove('hide'));
706
+ const formEl = valueParentDiv.querySelector('form');
707
+ if (formEl) formEl.remove();
678
708
  }
679
709
 
680
- link.click(function (e) {
710
+ link.addEventListener('click', function (e) {
681
711
  e.preventDefault();
682
712
 
683
- let parent = $(this).parent();
684
-
685
- parent.find('a, span').addClass('hide');
686
-
687
- let form = $('<form class="form-inline"></form>');
688
-
689
- let value = parent.find('span').data('value') || parent.find('span').text();
690
- let input = $( typeof getInputCallback == 'function' ? getInputCallback(value) : '<input type="text" />');
691
- form.append(input);
692
- form.find('input').addClass('form-control').css('width', 'auto').val(value);
693
-
694
- let button = $('<button type="submit" class="btn btn-success ms-2" data-loading-text="<i class=\'fa fa-circle-notch fa-spin\'></i>" style="vertical-align: baseline;"><i class="fas fa-check"></i></button>');
695
- button.click(function (e) {
696
- FormHelper.buttonLoader(parent.find('button'), 'loading');
697
- let newValue = parent.find('input').val();
713
+ let parent = this.parentElement;
714
+
715
+ parent.querySelectorAll('a, span').forEach(el => el.classList.add('hide'));
716
+
717
+ let form = document.createElement('form');
718
+ form.className = 'form-inline';
719
+
720
+ const spanEl = parent.querySelector('span');
721
+ let value = spanEl?.dataset.value || spanEl?.textContent || '';
722
+ let inputEl;
723
+ if (typeof getInputCallback == 'function') {
724
+ const tmpDiv = document.createElement('div');
725
+ tmpDiv.innerHTML = getInputCallback(value).trim();
726
+ inputEl = tmpDiv.firstElementChild;
727
+ } else {
728
+ inputEl = document.createElement('input');
729
+ inputEl.type = 'text';
730
+ }
731
+ inputEl.classList.add('form-control');
732
+ inputEl.style.width = 'auto';
733
+ inputEl.value = value;
734
+ form.appendChild(inputEl);
735
+
736
+ let button = document.createElement('button');
737
+ button.type = 'submit';
738
+ button.className = 'btn btn-success ms-2';
739
+ button.dataset.loadingText = '<i class=\'fa fa-circle-notch fa-spin\'></i>';
740
+ button.style.verticalAlign = 'baseline';
741
+ button.innerHTML = '<i class="fas fa-check"></i>';
742
+ button.addEventListener('click', function (e) {
743
+ FormHelper.buttonLoader(parent.querySelector('button'), 'loading');
744
+ let newValue = parent.querySelector('input').value;
698
745
  onSubmitCallback(newValue, parent,
699
746
  (isSuccess, valueFormatCallback) => {
700
747
  cancelEdit(parent);
701
748
  if (isSuccess) {
702
- parent.find('span').data('value', newValue).text(typeof valueFormatCallback == 'function' ? valueFormatCallback(newValue) : newValue);
749
+ const sp = parent.querySelector('span');
750
+ if (sp) {
751
+ sp.dataset.value = newValue;
752
+ sp.textContent = typeof valueFormatCallback == 'function' ? valueFormatCallback(newValue) : newValue;
753
+ }
703
754
  }
704
755
  }
705
756
  );
706
757
  });
707
- form.append(button);
758
+ form.appendChild(button);
708
759
 
709
- parent.append(form);
760
+ parent.appendChild(form);
710
761
  return false;
711
762
  });
712
763
  }