Skip to content

Commit e1fbd7c

Browse files
committed
netteForms: modernized code
1 parent 2614e13 commit e1fbd7c

File tree

1 file changed

+83
-135
lines changed

1 file changed

+83
-135
lines changed

src/assets/netteForms.js

Lines changed: 83 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
} else if (typeof module === 'object' && typeof module.exports === 'object') {
2121
module.exports = factory(global);
2222
} else {
23-
let init = !global.Nette || !global.Nette.noInit;
23+
let init = !global.Nette?.noInit;
2424
global.Nette = factory(global);
2525
if (init) {
2626
global.Nette.initOnLoad();
@@ -79,49 +79,39 @@
7979
* @return {*}
8080
*/
8181
Nette.getValue = function (elem) {
82-
if (!elem) {
83-
return null;
84-
85-
} else if (!elem.tagName) { // RadioNodeList
86-
return elem[0] ? Nette.getValue(elem[0]) : null;
87-
88-
} else if (elem.type === 'radio') {
89-
return expandRadioElement(elem)
90-
.find((input) => input.checked)
91-
?.value ?? null;
92-
93-
} else if (elem.type === 'file') {
94-
return elem.files || elem.value;
82+
if (elem instanceof HTMLInputElement) {
83+
if (elem.type === 'radio') {
84+
return expandRadioElement(elem)
85+
.find((input) => input.checked)
86+
?.value ?? null;
87+
88+
} else if (elem.type === 'file') {
89+
return elem.files;
90+
91+
} else if (elem.type === 'checkbox') {
92+
return elem.name.endsWith('[]') // checkbox list
93+
? expandRadioElement(elem)
94+
.filter((input) => input.checked)
95+
.map((input) => input.value)
96+
: elem.checked;
9597

96-
} else if (elem.tagName.toLowerCase() === 'select') {
97-
let index = elem.selectedIndex,
98-
options = elem.options,
99-
values = [];
100-
101-
if (elem.type === 'select-one') {
102-
return index < 0 ? null : options[index].value;
103-
}
104-
105-
for (let i = 0; i < options.length; i++) {
106-
if (options[i].selected) {
107-
values.push(options[i].value);
108-
}
98+
} else {
99+
return elem.value.trim();
109100
}
110-
return values;
111101

112-
} else if (elem.name && elem.name.endsWith('[]')) { // multiple elements []
113-
return expandRadioElement(elem)
114-
.filter((input) => input.checked)
115-
.map((input) => input.value);
102+
} else if (elem instanceof HTMLSelectElement) {
103+
return elem.multiple
104+
? Array.from(elem.selectedOptions, (option) => option.value)
105+
: elem.selectedOptions[0]?.value ?? null;
116106

117-
} else if (elem.type === 'checkbox') {
118-
return elem.checked;
107+
} else if (elem instanceof HTMLTextAreaElement) {
108+
return elem.value;
119109

120-
} else if (elem.tagName.toLowerCase() === 'textarea') {
121-
return elem.value.replace('\r', '');
110+
} else if (elem instanceof RadioNodeList) {
111+
return Nette.getValue(elem[0]);
122112

123113
} else {
124-
return elem.value.replace('\r', '').replace(/^\s+|\s+$/g, '');
114+
return null;
125115
}
126116
};
127117

@@ -132,7 +122,7 @@
132122
* @param {boolean} filter
133123
* @return {*}
134124
*/
135-
Nette.getEffectiveValue = function (elem, filter) {
125+
Nette.getEffectiveValue = function (elem, filter = false) {
136126
let val = Nette.getValue(elem);
137127
if (val === elem.getAttribute('data-nette-empty-value')) {
138128
val = '';
@@ -157,14 +147,13 @@
157147
* @param {?boolean} emptyOptional
158148
* @return {boolean}
159149
*/
160-
Nette.validateControl = function (elem, rules, onlyCheck, value, emptyOptional) {
161-
rules = rules || JSON.parse(elem.getAttribute('data-nette-rules') || '[]');
162-
value = value === undefined ? {value: Nette.getEffectiveValue(elem)} : value;
163-
emptyOptional = emptyOptional === undefined ? !Nette.validateRule(elem, ':filled', null, value) : emptyOptional;
164-
165-
for (let id = 0, len = rules.length; id < len; id++) {
166-
let rule = rules[id],
167-
op = rule.op.match(/(~)?([^?]+)/),
150+
Nette.validateControl = function (elem, rules, onlyCheck = false, value = null, emptyOptional = null) {
151+
rules ??= JSON.parse(elem.getAttribute('data-nette-rules') ?? '[]');
152+
value ??= {value: Nette.getEffectiveValue(elem)};
153+
emptyOptional ??= !Nette.validateRule(elem, ':filled', null, value);
154+
155+
for (let rule of rules) {
156+
let op = rule.op.match(/(~)?([^?]+)/),
168157
curElem = rule.control ? getFormElement(elem.form, rule.control) : elem;
169158

170159
rule.neg = op[1];
@@ -214,14 +203,14 @@
214203
* @param {boolean} onlyCheck
215204
* @return {boolean}
216205
*/
217-
Nette.validateForm = function (sender, onlyCheck) {
218-
let form = sender.form || sender,
206+
Nette.validateForm = function (sender, onlyCheck = false) {
207+
let form = sender.form ?? sender,
219208
scope;
220209

221210
Nette.formErrors = [];
222211

223212
if (form['nette-submittedBy'] && form['nette-submittedBy'].getAttribute('formnovalidate') !== null) {
224-
let scopeArr = JSON.parse(form['nette-submittedBy'].getAttribute('data-nette-validation-scope') || '[]');
213+
let scopeArr = JSON.parse(form['nette-submittedBy'].getAttribute('data-nette-validation-scope') ?? '[]');
225214
if (scopeArr.length) {
226215
scope = new RegExp('^(' + scopeArr.join('-|') + '-)');
227216
} else {
@@ -290,15 +279,12 @@
290279
let messages = [],
291280
focusElem;
292281

293-
for (let i = 0; i < errors.length; i++) {
294-
let elem = errors[i].element,
295-
message = errors[i].message;
296-
297-
if (messages.indexOf(message) < 0) {
298-
messages.push(message);
282+
for (let error of errors) {
283+
if (messages.indexOf(error.message) < 0) {
284+
messages.push(error.message);
299285

300-
if (!focusElem && elem.focus) {
301-
focusElem = elem;
286+
if (!focusElem && error.element.focus) {
287+
focusElem = error.element;
302288
}
303289
}
304290
}
@@ -357,24 +343,22 @@
357343
return op === ':filled';
358344
}
359345

360-
value = value === undefined ? {value: Nette.getEffectiveValue(elem, true)} : value;
346+
value ??= {value: Nette.getEffectiveValue(elem, true)};
361347

362-
if (op.charAt(0) === ':') {
363-
op = op.substring(1);
364-
}
365-
op = op.replace('::', '_');
366-
op = op.replace(/\\/g, '');
367-
368-
let arr = Array.isArray(arg) ? arg.slice(0) : [arg];
369-
for (let i = 0, len = arr.length; i < len; i++) {
370-
if (arr[i] && arr[i].control) {
371-
let control = getFormElement(elem.form, arr[i].control);
372-
arr[i] = control === elem ? value.value : Nette.getEffectiveValue(control, true);
348+
let method = op.charAt(0) === ':' ? op.substring(1) : op;
349+
method = method.replace('::', '_').replaceAll('\\', '');
350+
351+
let args = Array.isArray(arg) ? arg : [arg];
352+
args = args.map((arg) => {
353+
if (arg?.control) {
354+
let control = getFormElement(elem.form, arg.control);
355+
return control === elem ? value.value : Nette.getEffectiveValue(control, true);
373356
}
374-
}
357+
return arg;
358+
});
375359

376-
return Nette.validators[op]
377-
? Nette.validators[op](elem, Array.isArray(arg) ? arr : arr[0], value.value, value)
360+
return Nette.validators[method]
361+
? Nette.validators[method](elem, Array.isArray(arg) ? args : args[0], value.value, value)
378362
: null;
379363
};
380364

@@ -410,9 +394,9 @@
410394
val = Array.isArray(val) ? val : [val];
411395
arg = Array.isArray(arg) ? arg : [arg];
412396
loop:
413-
for (let i1 = 0, len1 = val.length; i1 < len1; i1++) {
414-
for (let i2 = 0, len2 = arg.length; i2 < len2; i2++) {
415-
if (toString(val[i1]) === toString(arg[i2])) {
397+
for (let a of val) {
398+
for (let b of arg) {
399+
if (toString(a) === toString(b)) {
416400
continue loop;
417401
}
418402
}
@@ -476,17 +460,9 @@
476460
regExp = new RegExp('^(?:' + arg + ')$', caseInsensitive ? 'i' : '');
477461
}
478462

479-
if (val instanceof FileList) {
480-
for (let i = 0; i < val.length; i++) {
481-
if (!regExp.test(val[i].name)) {
482-
return false;
483-
}
484-
}
485-
486-
return true;
487-
}
488-
489-
return regExp.test(val);
463+
return val instanceof FileList
464+
? Array.from(val).every((file) => regExp.test(file.name))
465+
: regExp.test(val);
490466
} catch {} // eslint-disable-line no-empty
491467
},
492468

@@ -544,36 +520,19 @@
544520
},
545521

546522
fileSize: function (elem, arg, val) {
547-
for (let i = 0; i < val.length; i++) {
548-
if (val[i].size > arg) {
549-
return false;
550-
}
551-
}
552-
return true;
523+
return Array.from(val).every((file) => file.size <= arg);
553524
},
554525

555-
mimeType: function (elem, arg, val) {
526+
mimeType: function (elem, args, val) {
556527
let re = [];
557-
arg = Array.isArray(arg) ? arg : [arg];
558-
for (let i = 0, len = arg.length; i < len; i++) {
559-
re.push('^' + arg[i].replace(/([^\w])/g, '\\$1').replace('\\*', '.*') + '$');
560-
}
528+
args = Array.isArray(args) ? args : [args];
529+
args.forEach((arg) => re.push('^' + arg.replace(/([^\w])/g, '\\$1').replace('\\*', '.*') + '$'));
561530
re = new RegExp(re.join('|'));
562-
563-
if (val instanceof FileList) {
564-
for (let i = 0; i < val.length; i++) {
565-
if (val[i].type && !re.test(val[i].type)) {
566-
return false;
567-
} else if (elem.validity.badInput) {
568-
return null;
569-
}
570-
}
571-
}
572-
return true;
531+
return Array.from(val).every((file) => !file.type || re.test(file.type));
573532
},
574533

575534
image: function (elem, arg, val) {
576-
return Nette.validators.mimeType(elem, arg || ['image/gif', 'image/png', 'image/jpeg', 'image/webp'], val);
535+
return Nette.validators.mimeType(elem, arg ?? ['image/gif', 'image/png', 'image/jpeg', 'image/webp'], val);
577536
},
578537

579538
'static': function (elem, arg) {
@@ -587,7 +546,7 @@
587546
* @param {HTMLFormElement} form
588547
* @param {?Event} event
589548
*/
590-
Nette.toggleForm = function (form, event) {
549+
Nette.toggleForm = function (form, event = null) {
591550
formToggles = {};
592551
for (let elem of Array.from(form.elements)) {
593552
if (elem.getAttribute('data-nette-rules')) {
@@ -611,18 +570,16 @@
611570
* @param {?boolean} emptyOptional
612571
* @return {boolean}
613572
*/
614-
Nette.toggleControl = function (elem, rules, success, firsttime, value, emptyOptional) {
615-
rules = rules || JSON.parse(elem.getAttribute('data-nette-rules') || '[]');
616-
value = value === undefined ? {value: Nette.getEffectiveValue(elem)} : value;
617-
emptyOptional = emptyOptional === undefined ? !Nette.validateRule(elem, ':filled', null, value) : emptyOptional;
573+
Nette.toggleControl = function (elem, rules, success, firsttime, value = null, emptyOptional = null) {
574+
rules ??= JSON.parse(elem.getAttribute('data-nette-rules') ?? '[]');
575+
value ??= {value: Nette.getEffectiveValue(elem)};
576+
emptyOptional ??= !Nette.validateRule(elem, ':filled', null, value);
618577

619578
let has = false,
620-
handler = (e) => Nette.toggleForm(elem.form, e),
621579
curSuccess;
622580

623-
for (let id = 0, len = rules.length; id < len; id++) {
624-
let rule = rules[id],
625-
op = rule.op.match(/(~)?([^?]+)/),
581+
for (let rule of rules) {
582+
let op = rule.op.match(/(~)?([^?]+)/),
626583
curElem = rule.control ? getFormElement(elem.form, rule.control) : elem;
627584

628585
rule.neg = op[1];
@@ -655,13 +612,12 @@
655612
expandRadioElement(curElem)
656613
.filter((el) => !toggleListeners.has(el))
657614
.forEach((el) => {
658-
el.addEventListener('change', handler);
615+
el.addEventListener('change', (e) => Nette.toggleForm(elem.form, e));
659616
toggleListeners.set(el, null);
660617
});
661618
}
662-
for (let toggleId in rule.toggle || []) {
663-
formToggles[toggleId] = formToggles[toggleId] || {elem: elem};
664-
formToggles[toggleId].state = formToggles[toggleId].state || (rule.toggle[toggleId] ? curSuccess : !curSuccess);
619+
for (let id in rule.toggle ?? []) {
620+
formToggles[id] ??= {elem: elem, state: rule.toggle[id] ? curSuccess : !curSuccess};
665621
}
666622
}
667623
}
@@ -680,10 +636,8 @@
680636
if (/^\w[\w.:-]*$/.test(selector)) { // id
681637
selector = '#' + selector;
682638
}
683-
let elems = document.querySelectorAll(selector);
684-
for (let i = 0; i < elems.length; i++) {
685-
elems[i].hidden = !visible;
686-
}
639+
Array.from(document.querySelectorAll(selector))
640+
.forEach((elem) => elem.hidden = !visible);
687641
};
688642

689643

@@ -718,12 +672,7 @@
718672
form.addEventListener('formdata', (e) => Nette.compactCheckboxes(form, e.formData));
719673
}
720674

721-
check: {
722-
for (let i = 0; i < form.elements.length; i++) {
723-
if (form.elements[i].getAttribute('data-nette-rules')) {
724-
break check;
725-
}
726-
}
675+
if (!Array.from(form.elements).some((elem) => elem.getAttribute('data-nette-rules'))) {
727676
return;
728677
}
729678

@@ -752,9 +701,8 @@
752701
*/
753702
Nette.initOnLoad = function () {
754703
Nette.onDocumentReady(() => {
755-
for (let i = 0; i < document.forms.length; i++) {
756-
Nette.initForm(document.forms[i]);
757-
}
704+
Array.from(document.forms)
705+
.forEach((form) => Nette.initForm(form));
758706

759707
document.body.addEventListener('click', (e) => {
760708
let target = e.target;

0 commit comments

Comments
 (0)