UNPKG

13.6 kBJavaScriptView Raw
1
2// /!\ DEPRECATED AND WILL BE REMOVED IN 1.0 - USE src/Validation INSTEAD
3// Examples available on bunnyjs.com
4
5export var Validate = {
6
7 /* public properties */
8
9 errorClass: 'has-danger', // class to be applied on form-group
10 formGroupClass: 'form-group', // main container selector which includes label, input, help text etc.
11 formLabelClass: 'form-control-label', // label to pick innerHTML from to insert field name into error message
12 errorContainerTag: 'small', // tag name of error message container
13 errorContainerClass: 'text-help', // class to add when creating error message container
14 lang: { // error messages, keys must be same as validator names
15 required: "Field '%s' ir required!",
16 tel: "Field '%s' is not a valid telephone number!",
17 email: "Field '%s' should be a valid e-mail address!",
18 //image: "Uploaded file '%s' should be an image (jpeg, png, bmp, gif, or svg)",
19 fileMaxSize: 'Max file size must be < %maxsizeMB, uploaded file with %filesizeMB',
20 maxlength: "Input '%s' length is too long, must be < '%maxlength'",
21 minlength: "Input '%s' length is too short, must be > '%minlength'"
22 },
23
24 /* error container methods */
25
26 insertErrorContainer: function(form_group_el, error_container) { // where to insert error message container
27 return form_group_el.appendChild(error_container);
28 },
29
30 toggleErrorClass: function(form_group_el) { // where to add/remove error class
31 if (form_group_el.classList.contains(this.errorClass)) {
32 form_group_el.classList.remove(this.errorClass);
33 } else {
34 form_group_el.classList.add(this.errorClass);
35 }
36 },
37
38 createErrorContainer() {
39 var el = document.createElement(this.errorContainerTag);
40 el.setAttribute('class', this.errorContainerClass);
41 return el;
42 },
43
44 getErrorContainer(form_group_el) {
45 return form_group_el.querySelector('.' + this.errorContainerClass);
46 },
47
48 /**
49 * Removes error container and class if exists
50 * @param form_group_el
51 */
52 removeErrorContainer(form_group_el) {
53 var el = this.getErrorContainer(form_group_el);
54 if (el !== null) {
55 el.parentNode.removeChild(el);
56 this.toggleErrorClass(form_group_el);
57 }
58 },
59
60 /**
61 * Creates and includes into DOM error container or updates error message
62 * @param form_group_el_or_id
63 * @param msg
64 */
65 setErrorMessage(form_group_el_or_id, msg) {
66 if (typeof form_group_el_or_id === 'string') {
67 var form_group = document.getElementById(form_group_el_or_id);
68 } else {
69 var form_group = form_group_el_or_id;
70 }
71
72 var error_container = this.getErrorContainer(form_group);
73
74 if (error_container === null) {
75 // container for error msg doesn't exists, create new
76 var el = this.createErrorContainer();
77 this.toggleErrorClass(form_group);
78 el.innerHTML = msg;
79 this.insertErrorContainer(form_group, el)
80 } else {
81 // container exists, update msg
82 error_container.innerHTML = msg;
83 }
84 },
85
86 /* validators */
87
88 validators: {
89
90 maxlength: function(input) {
91 if (input.getAttribute('maxlength') !== null && input.value.length > input.getAttribute('maxlength')) {
92 return {maxlength: input.getAttribute('maxlength')};
93 }
94 return true;
95 },
96
97 minlength: function(input) {
98 if (input.getAttribute('minlength') !== null && input.value.length < input.getAttribute('minlength')) {
99 return {minlength: input.getAttribute('minlength')};
100 }
101 return true;
102 },
103
104 // TODO: add mindimensions, maxdimensions validators
105 // TODO (form): add _processor to file input to allow custom file processing layer, for example, to resize big images
106
107 // TODO: remake Validate component to use Promise
108 // TODO: Use BunnyFile.getSignature() to parse real MIME-type
109 /*image: function(input) {
110 if (input.getAttribute('type') === 'file' && input.getAttribute('accept') === 'image/!*') {
111 if (input.files.length !== 0) {
112 var mime_types = [
113 'image/jpeg',
114 'image/png',
115 'image/bmp',
116 'image/gif',
117 'image/svg+xml'
118 ];
119 if (mime_types.indexOf(input.files[0].type) > -1) {
120 return true;
121 }
122 return false;
123 }
124 return true;
125 }
126 return true;
127 },*/
128
129 fileMaxSize: function(input) {
130 if (input.getAttribute('type') === 'file' && input.hasAttribute('maxfilesize')) {
131 var max_file_size = parseInt(input.getAttribute('maxfilesize')); // in MB
132 if (input.files.length !== 0) {
133 var file_size = Math.round(input.files[0].size / 1000000).toFixed(2); // in MB
134 if (file_size <= max_file_size) {
135 return true;
136 }
137 return {maxsize: max_file_size, filesize: file_size};
138 }
139 return true;
140 }
141 return true;
142 },
143
144 email: function(input) {
145 if (input.value.length > 0 && input.getAttribute('type') === 'email') {
146 // input is email, parse string to match email regexp
147 var Regex = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;
148 return Regex.test(input.value);
149 }
150 return true;
151 },
152
153 tel: function(input){
154 if (input.value.length > 0 && input.getAttribute('type') === 'tel') {
155 // input is tel, parse string to match tel regexp
156 var Regex = /^[0-9\-\+\(\)\#\ \*]{6,20}$/;
157 return Regex.test(input.value);
158 }
159 return true;
160 },
161
162 required: function(input){
163 if (input.getAttribute('required') !== null) {
164 // input is required, check value
165 if (input.value === '') {
166 return false;
167 } else {
168 return true;
169 }
170 }
171 return true;
172 }
173 },
174
175 /**
176 * Validate form
177 * @param form_el
178 * @param events
179 * @param submit_handler
180 */
181 validate: function(form_el, events = {}, submit_handler) {
182
183 var form = form_el;
184 var self = this;
185
186 form.setAttribute('novalidate', '');
187
188 // add event listener on form submit
189 form.addEventListener("submit", function(e){
190 e.preventDefault();
191 var is_valid = true;
192 var is_focused = false;
193 form.querySelectorAll('.' + self.formGroupClass).forEach(function(form_group){
194
195 if (self.isFormGroupForInput(form_group)) {
196 var res = self.checkInput(form_group);
197
198 if (res.valid === false) {
199 is_valid = false;
200 self.setErrorMessage(form_group, res.msg);
201
202 if (!is_focused) {
203 if (events['on_focus'] !== undefined) {
204 events['on_focus'](res.inputElements.input, form_group);
205 } else {
206 self.focus(res.inputElements.input);
207 }
208 is_focused = true;
209 }
210
211 } else {
212 self.removeErrorContainer(form_group);
213 }
214 }
215
216 });
217
218 if (is_valid) {
219 if (submit_handler === undefined) {
220 form.submit();
221 } else {
222 submit_handler();
223 }
224 }
225 }, false);
226 },
227
228 /**
229 * Return form group element, input element and label element
230 * @param form_group_el_or_id
231 * @returns {object} 3 keys: formGroup, input, label
232 */
233 getInputElementsByFormGroup(form_group_el_or_id) {
234 if (typeof form_group_el_or_id === 'string') {
235 var form_group = document.getElementById(form_group_el_or_id);
236 } else {
237 var form_group = form_group_el_or_id;
238 }
239 var input = form_group.querySelector('[name]');
240 var label = form_group.getElementsByTagName('label')[0];
241 if (label === undefined) {
242 label = null;
243 }
244 return {
245 formGroup: form_group,
246 input: input,
247 label: label
248 }
249 },
250
251 isFormGroupForInput(form_group_el_or_id) {
252 var input_elements = this.getInputElementsByFormGroup(form_group_el_or_id);
253 if (input_elements.input === null) {
254 return false;
255 }
256 return true;
257 },
258
259 _checkInputAgainstValidator(input, label, validator) {
260 if (this.validators[validator] === undefined) {
261 console.error('Bunny Validate error: validator "' + validator + '" not found.');
262 return {valid: false, msg: 'ERROR: Validator not found'};
263 }
264 var validator_result = this.validators[validator](input);
265 var valid = false;
266 var validator_data = {};
267 var input_valid = true;
268 var msg = '';
269
270 if (typeof validator_result !== 'boolean') {
271 for (var k in validator_result) {
272 valid = false;
273 validator_data[k] = validator_result[k];
274 }
275 } else {
276 valid = validator_result;
277 }
278
279 if (!valid) {
280 // form_input is NOT valid
281 var input_title = '';
282 if (label === null) {
283 var placeholder = input.getAttribute('placeholder');
284 if (placeholder !== null) {
285 input_title = placeholder;
286 }
287 } else {
288 input_title = label.innerHTML;
289 }
290
291 msg = this.lang[validator].replace('%s', input_title);
292 for (var d in validator_data) {
293 msg = msg.replace('%'+d, validator_data[d]);
294 }
295
296 input_valid = false;
297 }
298
299 return {
300 valid: input_valid,
301 msg: msg
302 };
303 },
304
305 checkInputAgainstValidator(form_group_el_or_id, validator) {
306 var input_elements = this.getInputElementsByFormGroup(form_group_el_or_id);
307 return this._checkInputAgainstValidator(input_elements.input, input_elements.label, validator);
308 },
309
310 /**
311 * Check if input is valid or not, return object containing two keys: valid and msg
312 * If input is invalid valid key will be false and msg will contain error message
313 * If input is valid, valid key will be true and msg empty string
314 * @param {string} form_group_el_or_id
315 * @returns {object} valid: boolean, msg: string
316 */
317 checkInput(form_group_el_or_id) {
318 if (typeof form_group_el_or_id === 'string') {
319 var form_group = document.getElementById(form_group_el_or_id);
320 } else {
321 var form_group = form_group_el_or_id;
322 }
323 var input_elements = this.getInputElementsByFormGroup(form_group);
324 var input_valid = true;
325 var msg = '';
326 for (var validator in this.validators) {
327 var res = this._checkInputAgainstValidator(input_elements.input, input_elements.label, validator);
328 if (res.valid === false) {
329 input_valid = false;
330 msg = res.msg;
331 break;
332 }
333 }
334 return {
335 valid: input_valid,
336 msg: msg,
337 inputElements: input_elements
338 };
339 },
340
341 validateSection(section_el, events = {}) {
342 var self = this;
343 var section_valid = true;
344 var is_focused = false;
345
346 section_el.querySelectorAll('.' + this.formGroupClass).forEach(function(form_group) {
347 if (self.isFormGroupForInput(form_group)) {
348 var res = self.checkInput(form_group);
349
350 if (res.valid === false) {
351 section_valid = false;
352 self.setErrorMessage(form_group, res.msg);
353
354 if (!is_focused) {
355 if (events['on_focus'] !== undefined) {
356 events['on_focus'](res.inputElements.input, form_group);
357 } else {
358 self.focus(res.inputElements.input);
359 }
360 is_focused = true;
361 }
362
363 } else {
364 self.removeErrorContainer(form_group);
365 }
366 }
367 });
368
369 return section_valid;
370 },
371
372 focus(input) {
373 input.focus();
374 input.scrollIntoView(false);
375 }
376};