Skip to content

Commit 6145061

Browse files
Merge pull request #37 from michelegiorgi/development
release 1.4.2
2 parents c73e7fb + 2455895 commit 6145061

21 files changed

+303
-504
lines changed

assets/scripts/public/core/conditional.js

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { el, uid } from './helpers'
2-
import 'parsleyjs'
32

43
export default {
54
init() {
@@ -43,7 +42,7 @@ export default {
4342
valid = true;
4443
} else if (index == 0 && (typeof rule[1] !== 'undefined') && rule[1].operator == "&&" ) {
4544
valid = false;
46-
break;
45+
break;
4746
} else if((rule[index].operator=="&&") && (rule[index]._key > 1)) {
4847
valid = false;
4948
break;
@@ -85,18 +84,12 @@ export default {
8584
},
8685
validation($field, disable=true) {
8786
//reset validation if required
88-
const $required = $field.find("[required]")
89-
if($required) {
90-
const navlink = ' li[data-name="' + $required.attr("id") + '"]'
91-
if(disable) {
92-
$required.attr("data-parsley-excluded", "true")
93-
$(el("nav_list", true, navlink)).addClass("disabled")
94-
} else {
95-
$required.attr("data-parsley-excluded", "false")
96-
$(el("nav_list", true, navlink)).removeClass("disabled")
97-
}
98-
uid($field)
99-
$(el("form", "uid")).parsley().refresh()
87+
const $input = $field.find("[required]")
88+
if(disable) {
89+
$field[0].setAttribute('data-excluded','')
90+
} else {
91+
$field[0].removeAttribute('data-excluded')
10092
}
93+
$(el("nav_list", true, ' li[data-name="' + $input.attr("name") + '"]')).toggleClass("disabled", disable)
10194
},
102-
}
95+
}

assets/scripts/public/core/nav.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ export default {
6363
$(el("button", "uid", "--prev")).toggle(false)
6464
$(el("button", "uid", "--next")).toggle(false)
6565
}
66-
validate.form()
6766
}
6867
})
6968
},
@@ -87,7 +86,8 @@ export default {
8786
})
8887
function gotoStep(index) {
8988
const currentstep = current();
90-
if(validate.checkstep(currentstep, index)) {
89+
const form = document.querySelector(el("form", "uid"))
90+
if(validate.validateStep(form, currentstep, index)) {
9191
const $steps = $(el("section", "uid"))
9292
const $nav = $(el("nav_section", "uid"))
9393
const atTheEnd = index >= $steps.length - 1

assets/scripts/public/core/submit.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
import { el, uid } from './helpers'
22
import hooks from './hooks'
3+
import validate from './validate'
34

45
/* eslint-disable no-unused-vars */
56

67
export default {
78
init() {
89
//init form submit
9-
var submit = this
10-
window.Parsley.on('form:init', function() {
11-
$(this.$element).submit(function(e){
12-
e.preventDefault()
10+
let submit = this
11+
let forms = document.querySelectorAll(el('form'))
12+
forms.forEach(function(form) {
13+
form.addEventListener("submit", function(e) {
14+
e.preventDefault();
15+
if(!validate.validateForm(form)) { return false; }
1316
uid($(this))
1417
submit.token()
1518
hooks.event('FormSubmit')

assets/scripts/public/core/uiux.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,9 @@ export default {
127127
if($(el("button", "uid", "--next")).is(":visible")) {
128128
$(el("button", "uid", "--next")).click()
129129
} else {
130-
$(el("form", "uid")).submit()
130+
let form = document.querySelector(el("form", "uid"))
131+
let event = new Event('submit', { 'bubbles': true, 'cancelable': true });
132+
form.dispatchEvent(event);
131133
}
132134
} else {
133135
//
Lines changed: 179 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,197 @@
11
import { el, uid } from './helpers'
2-
const { __ } = wp.i18n
3-
import 'parsleyjs'
2+
const { __, sprintf } = wp.i18n
3+
let fieldOptions = {
4+
text: {
5+
multiple: false,
6+
},
7+
textarea: {
8+
multiple: false,
9+
},
10+
email: {
11+
multiple: false,
12+
rules: {
13+
email: __("This value should be a valid email", "formality"),
14+
}
15+
},
16+
number: {
17+
multiple: false,
18+
rules: {
19+
number: __("This value should be a valid number", "formality"),
20+
number_min: /* translators: validation */ __("This value should be greater than or equal to %s", "formality"),
21+
number_max: /* translators: validation */ __("This value should be lower than or equal to %s", "formality"),
22+
}
23+
},
24+
select: {
25+
multiple: false,
26+
},
27+
multiple: {
28+
multiple: true,
29+
},
30+
rating: {
31+
multiple: true,
32+
},
33+
switch: {
34+
multiple: false,
35+
},
36+
upload: {
37+
multiple: false,
38+
rules: {
39+
file: __("This is not a valid file", "formality"),
40+
file_ext: /* translators: validation */ __('%s file extension is not allowed', 'formality'),
41+
file_size: __('Your file exceeds the size limit', 'formality'),
42+
}
43+
},
44+
}
445

546
export default {
647
init() {
748
//init validation
8-
$(el("form")).each(function() {
9-
uid($(this))
10-
$(el("section", "uid")).each(function(index, section) {
11-
$(section).find(':input').attr('data-parsley-group', 'step-' + index)
49+
let validate = this;
50+
const forms = document.querySelectorAll(el("form"))
51+
forms.forEach(function(form){
52+
validate.addStepIndexes(form)
53+
const inputs = form.querySelectorAll('input, select, textarea')
54+
inputs.forEach(function(input){
55+
validate.liveUpdate(input)
1256
})
1357
})
14-
this.field_error()
15-
this.field_success()
16-
this.form_error()
17-
this.i18n()
18-
},
19-
checkstep(index, newindex) {
20-
//validate single step
21-
let valid = false
22-
let options = this.parsley_options()
23-
if(index > newindex) {
24-
valid = true
25-
} else {
26-
$(el("form", "uid")).parsley(options).whenValidate({
27-
group: 'step-' + index,
28-
}).done(function() {
29-
valid = true
30-
$(el("nav_section", "uid")).eq(index).addClass(el("nav_section", false, "--validated"))
58+
},
59+
addStepIndexes(form) {
60+
const sections = form.querySelectorAll(el("section"))
61+
sections.forEach(function(section, index){
62+
const fields = section.querySelectorAll(el("field"))
63+
fields.forEach(function(field){
64+
field.setAttribute('data-step', index)
3165
})
66+
})
67+
},
68+
liveUpdate(input) {
69+
let validate = this;
70+
input.addEventListener('input', function(){
71+
let field = input.closest(el("field"))
72+
validate.validateField(field, true)
73+
})
74+
},
75+
validateStep(form, index, newindex) {
76+
if(index > newindex) { return true }
77+
const valid = this.validateForm(form, index)
78+
if(valid) {
79+
const sections = form.querySelectorAll(el("nav_section", "uid"))
80+
sections[index].classList.add(el("nav_section", false, "--validated"))
3281
}
3382
return valid
3483
},
35-
form() {
36-
//validate standard form (1 step)
37-
let options = this.parsley_options()
38-
$(el("form", "uid")).parsley(options)
39-
},
40-
parsley_options() {
41-
//create parsley options array
42-
let options = {
43-
classHandler: function (element) {
44-
return element.$element.closest(el("field"))
45-
},
46-
errorClass: el("field_error", false),
47-
errorsContainer: function(element) {
48-
return element.$element.closest(el("input")).find(el("input", true, "__status"))
49-
},
50-
successClass: el("field_success", false),
51-
errorsWrapper: '<ul class="'+el("input_errors", false)+'"></ul>',
84+
checkRule(input, rule) {
85+
let result = {
86+
valid: false,
87+
placeholder: '',
5288
}
53-
return options
89+
switch(rule) {
90+
case 'required':
91+
if(NodeList.prototype.isPrototypeOf(input)){
92+
input.forEach(function(single, i){ if(single.checked) { result.valid = true; } })
93+
} else {
94+
result.valid = input.value !== ''
95+
}
96+
break
97+
case 'email':
98+
result.valid = input.value.match(/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/)
99+
break
100+
case 'checked':
101+
result.valid = input.checked
102+
break
103+
case 'notchecked':
104+
result.valid = !input.checked
105+
break
106+
case 'number':
107+
result.valid = !isNaN(input.value)
108+
break
109+
case 'number_min':
110+
result.placeholder = input.min
111+
result.valid = parseFloat(input.value) >= result.placeholder
112+
break
113+
case 'number_max':
114+
result.placeholder = input.max
115+
result.valid = parseFloat(input.value) <= result.placeholder
116+
break
117+
case 'file':
118+
result.valid = input.files.length ? true : false
119+
break
120+
case 'file_ext':
121+
result.file = input.files.length ? input.files[0] : false
122+
if(result.file && result.file.type !== '') {
123+
result.formats = input.getAttribute('accept').split(", ")
124+
result.placeholder = ('.' + result.file.name.split('.').pop()).toLowerCase()
125+
result.valid = result.formats.indexOf(result.placeholder) !== -1
126+
}
127+
break
128+
case 'file_size':
129+
result.file = input.files.length ? input.files[0] : false
130+
if(result.file && result.file.size > 0) {
131+
result.valid = result.file.size <= parseInt(input.getAttribute('data-max-size'))
132+
}
133+
break
134+
}
135+
return result;
54136
},
55-
form_error() {
56-
window.Parsley.on('form:error', function() {
57-
58-
})
137+
changeFieldStatus(field, name, valid=true, error='') {
138+
const form = field.closest(el('form'))
139+
const status = field.querySelector(el('input_status'))
140+
const legend = form.querySelector(el('nav_legend', true, ' li[data-name="' + name + '"]'))
141+
field.classList.toggle(el("field", false, "--error"), !valid);
142+
status.innerHTML = !error ? '' : ('<div class="' + el("input_errors", false) + '">' + error + '</div>')
143+
if(legend) { legend.classList.toggle("error", !valid) }
144+
if(!valid) {
145+
const section = form.querySelector(el("nav_section", "uid", "--active"))
146+
if(section) { section.classList.remove(el("nav_section", false, "--validated")) }
147+
}
148+
field.classList.add(el("field", false, "--validated"));
59149
},
60-
field_error() {
61-
//field error event
62-
window.Parsley.on('field:error', function() {
63-
const id = $(this.$element).attr("id")
64-
uid($(this.$element))
65-
$(el("nav_legend", 'uid', ' li[data-name="' + id + '"]')).addClass("error")
66-
const index = $(el("nav_section", "uid")).index(el("nav_section", "uid", "--active"))
67-
$(el("nav_section", "uid")).eq(index).removeClass(el("nav_section", false, "--validated"))
68-
})
150+
validateField(field, soft=false) {
151+
if(field.hasAttribute('data-excluded')) { return true }
152+
let validate = this;
153+
const type = field.getAttribute('data-type')
154+
const required = field.classList.contains(el("field", false, "--required"))
155+
const validated = field.classList.contains(el("field", false, "--validated"))
156+
let rules = 'rules' in fieldOptions[type] ? Object.keys(fieldOptions[type]['rules']) : []
157+
const multiple = fieldOptions[type]['multiple']
158+
if(required) { rules.unshift('required') }
159+
const input = multiple ? field.querySelectorAll('input, select, textarea') : field.querySelector('input, select, textarea')
160+
const name = multiple ? input[0].name : input.name
161+
let valid = true;
162+
let error = '';
163+
if(!rules.includes('required') && !multiple && !input.value) {
164+
//skip validation
165+
} else {
166+
rules.forEach(function(rule){
167+
if(valid) {
168+
const check = validate.checkRule(input, rule)
169+
if(!check.valid) {
170+
error = rule == 'required' ? __("This value is required", "formality") : sprintf(fieldOptions[type]['rules'][rule], check.placeholder);
171+
valid = false;
172+
}
173+
}
174+
})
175+
}
176+
if(!soft || (soft && validated)) {
177+
validate.changeFieldStatus(field, name, valid, error)
178+
}
179+
return valid;
69180
},
70-
field_success() {
71-
//field success event
72-
window.Parsley.on('field:success', function() {
73-
const id = $(this.$element).attr("id")
74-
uid($(this.$element))
75-
$(el("nav_legend", "uid", ' li[data-name="' + id + '"]')).removeClass("error")
181+
validateForm(form, step=null) {
182+
let validate = this
183+
let errors = false
184+
const selector = step == null ? el("field") : el("field", true, '[data-step="'+step+'"]')
185+
let fields = form.querySelectorAll(selector)
186+
let firsterror = false
187+
fields.forEach(function(field, i){
188+
const error = !validate.validateField(field)
189+
if(!errors && error) {
190+
errors = true
191+
firsterror = field.querySelector('input, select, textarea')
192+
}
76193
})
77-
},
78-
i18n() {
79-
window.Parsley.addMessages('en', {
80-
defaultMessage: __("This value seems to be invalid", "formality"),
81-
type: {
82-
email: __("This value should be a valid email", "formality"),
83-
url: __("This value should be a valid url", "formality"),
84-
number: __("This value should be a valid number", "formality"),
85-
integer: __("This value should be a valid integer", "formality"),
86-
digits: __("This value should be digits", "formality"),
87-
alphanum: __("This value should be alphanumeric", "formality"),
88-
},
89-
required: __("This value is required", "formality"),
90-
pattern: __("This value seems to be invalid", "formality"),
91-
min: /* translators: validation */ __("This value should be greater than or equal to %s", "formality"),
92-
max: /* translators: validation */ __("This value should be lower than or equal to %s", "formality"),
93-
range: /* translators: validation */ __("This value should be between %s and %s", "formality"),
94-
minlength: /* translators: validation */ __("This value is too short. It should have %s characters or more", "formality"),
95-
maxlength: /* translators: validation */ __("This value is too long. It should have %s characters or fewer", "formality"),
96-
length: /* translators: validation */ __("This value length is invalid. It should be between %s and %s characters long", "formality"),
97-
check: /* translators: validation */ __("You must select between %s and %s choices", "formality"),
98-
});
99-
window.Parsley.setLocale('en');
194+
if(firsterror) { firsterror.focus() }
195+
return !errors
100196
}
101197
}

0 commit comments

Comments
 (0)