UNPKG

46.2 kBJavaScriptView Raw
1/*! validatorjs - v3.15.0 - - 2018-10-26 */
2(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Validator = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
3function AsyncResolvers(onFailedOne, onResolvedAll) {
4 this.onResolvedAll = onResolvedAll;
5 this.onFailedOne = onFailedOne;
6 this.resolvers = {};
7 this.resolversCount = 0;
8 this.passed = [];
9 this.failed = [];
10 this.firing = false;
11}
12
13AsyncResolvers.prototype = {
14
15 /**
16 * Add resolver
17 *
18 * @param {Rule} rule
19 * @return {integer}
20 */
21 add: function(rule) {
22 var index = this.resolversCount;
23 this.resolvers[index] = rule;
24 this.resolversCount++;
25 return index;
26 },
27
28 /**
29 * Resolve given index
30 *
31 * @param {integer} index
32 * @return {void}
33 */
34 resolve: function(index) {
35 var rule = this.resolvers[index];
36 if (rule.passes === true) {
37 this.passed.push(rule);
38 } else if (rule.passes === false) {
39 this.failed.push(rule);
40 this.onFailedOne(rule);
41 }
42
43 this.fire();
44 },
45
46 /**
47 * Determine if all have been resolved
48 *
49 * @return {boolean}
50 */
51 isAllResolved: function() {
52 return (this.passed.length + this.failed.length) === this.resolversCount;
53 },
54
55 /**
56 * Attempt to fire final all resolved callback if completed
57 *
58 * @return {void}
59 */
60 fire: function() {
61
62 if (!this.firing) {
63 return;
64 }
65
66 if (this.isAllResolved()) {
67 this.onResolvedAll(this.failed.length === 0);
68 }
69
70 },
71
72 /**
73 * Enable firing
74 *
75 * @return {void}
76 */
77 enableFiring: function() {
78 this.firing = true;
79 }
80
81};
82
83module.exports = AsyncResolvers;
84
85},{}],2:[function(require,module,exports){
86var replacements = {
87
88 /**
89 * Between replacement (replaces :min and :max)
90 *
91 * @param {string} template
92 * @param {Rule} rule
93 * @return {string}
94 */
95 between: function(template, rule) {
96 var parameters = rule.getParameters();
97 return this._replacePlaceholders(rule, template, {
98 min: parameters[0],
99 max: parameters[1]
100 });
101 },
102
103 /**
104 * Required_if replacement.
105 *
106 * @param {string} template
107 * @param {Rule} rule
108 * @return {string}
109 */
110 required_if: function(template, rule) {
111 var parameters = rule.getParameters();
112 return this._replacePlaceholders(rule, template, {
113 other: this._getAttributeName(parameters[0]),
114 value: parameters[1]
115 });
116 },
117
118 /**
119 * Required_unless replacement.
120 *
121 * @param {string} template
122 * @param {Rule} rule
123 * @return {string}
124 */
125 required_unless: function(template, rule) {
126 var parameters = rule.getParameters();
127 return this._replacePlaceholders(rule, template, {
128 other: this._getAttributeName(parameters[0]),
129 value: parameters[1]
130 });
131 },
132
133 /**
134 * Required_with replacement.
135 *
136 * @param {string} template
137 * @param {Rule} rule
138 * @return {string}
139 */
140 required_with: function(template, rule) {
141 var parameters = rule.getParameters();
142 return this._replacePlaceholders(rule, template, {
143 field: this._getAttributeName(parameters[0])
144 });
145 },
146
147 /**
148 * Required_with_all replacement.
149 *
150 * @param {string} template
151 * @param {Rule} rule
152 * @return {string}
153 */
154 required_with_all: function(template, rule) {
155 var parameters = rule.getParameters();
156 var getAttributeName = this._getAttributeName.bind(this);
157 return this._replacePlaceholders(rule, template, {
158 fields: parameters.map(getAttributeName).join(', ')
159 });
160 },
161
162 /**
163 * Required_without replacement.
164 *
165 * @param {string} template
166 * @param {Rule} rule
167 * @return {string}
168 */
169 required_without: function(template, rule) {
170 var parameters = rule.getParameters();
171 return this._replacePlaceholders(rule, template, {
172 field: this._getAttributeName(parameters[0])
173 });
174 },
175
176 /**
177 * Required_without_all replacement.
178 *
179 * @param {string} template
180 * @param {Rule} rule
181 * @return {string}
182 */
183 required_without_all: function(template, rule) {
184 var parameters = rule.getParameters();
185 var getAttributeName = this._getAttributeName.bind(this);
186 return this._replacePlaceholders(rule, template, {
187 fields: parameters.map(getAttributeName).join(', ')
188 });
189 },
190
191 /**
192 * After replacement.
193 *
194 * @param {string} template
195 * @param {Rule} rule
196 * @return {string}
197 */
198 after: function(template, rule) {
199 var parameters = rule.getParameters();
200 return this._replacePlaceholders(rule, template, {
201 after: this._getAttributeName(parameters[0])
202 });
203 },
204
205 /**
206 * Before replacement.
207 *
208 * @param {string} template
209 * @param {Rule} rule
210 * @return {string}
211 */
212 before: function(template, rule) {
213 var parameters = rule.getParameters();
214 return this._replacePlaceholders(rule, template, {
215 before: this._getAttributeName(parameters[0])
216 });
217 },
218
219 /**
220 * After_or_equal replacement.
221 *
222 * @param {string} template
223 * @param {Rule} rule
224 * @return {string}
225 */
226 after_or_equal: function(template, rule) {
227 var parameters = rule.getParameters();
228 return this._replacePlaceholders(rule, template, {
229 after_or_equal: this._getAttributeName(parameters[0])
230 });
231 },
232
233 /**
234 * Before_or_equal replacement.
235 *
236 * @param {string} template
237 * @param {Rule} rule
238 * @return {string}
239 */
240 before_or_equal: function(template, rule) {
241 var parameters = rule.getParameters();
242 return this._replacePlaceholders(rule, template, {
243 before_or_equal: this._getAttributeName(parameters[0])
244 });
245 },
246
247 /**
248 * Same replacement.
249 *
250 * @param {string} template
251 * @param {Rule} rule
252 * @return {string}
253 */
254 same: function(template, rule) {
255 var parameters = rule.getParameters();
256 return this._replacePlaceholders(rule, template, {
257 same: this._getAttributeName(parameters[0])
258 });
259 },
260};
261
262function formatter(attribute) {
263 return attribute.replace(/[_\[]/g, ' ').replace(/]/g, '');
264}
265
266module.exports = {
267 replacements: replacements,
268 formatter: formatter
269};
270
271},{}],3:[function(require,module,exports){
272var Errors = function() {
273 this.errors = {};
274};
275
276Errors.prototype = {
277 constructor: Errors,
278
279 /**
280 * Add new error message for given attribute
281 *
282 * @param {string} attribute
283 * @param {string} message
284 * @return {void}
285 */
286 add: function(attribute, message) {
287 if (!this.has(attribute)) {
288 this.errors[attribute] = [];
289 }
290
291 if (this.errors[attribute].indexOf(message) === -1) {
292 this.errors[attribute].push(message);
293 }
294 },
295
296 /**
297 * Returns an array of error messages for an attribute, or an empty array
298 *
299 * @param {string} attribute A key in the data object being validated
300 * @return {array} An array of error messages
301 */
302 get: function(attribute) {
303 if (this.has(attribute)) {
304 return this.errors[attribute];
305 }
306
307 return [];
308 },
309
310 /**
311 * Returns the first error message for an attribute, false otherwise
312 *
313 * @param {string} attribute A key in the data object being validated
314 * @return {string|false} First error message or false
315 */
316 first: function(attribute) {
317 if (this.has(attribute)) {
318 return this.errors[attribute][0];
319 }
320
321 return false;
322 },
323
324 /**
325 * Get all error messages from all failing attributes
326 *
327 * @return {Object} Failed attribute names for keys and an array of messages for values
328 */
329 all: function() {
330 return this.errors;
331 },
332
333 /**
334 * Determine if there are any error messages for an attribute
335 *
336 * @param {string} attribute A key in the data object being validated
337 * @return {boolean}
338 */
339 has: function(attribute) {
340 if (this.errors.hasOwnProperty(attribute)) {
341 return true;
342 }
343
344 return false;
345 }
346};
347
348module.exports = Errors;
349
350},{}],4:[function(require,module,exports){
351var Messages = require('./messages');
352
353require('./lang/en');
354
355var require_method = require;
356
357var container = {
358
359 messages: {},
360
361 /**
362 * Set messages for language
363 *
364 * @param {string} lang
365 * @param {object} rawMessages
366 * @return {void}
367 */
368 _set: function(lang, rawMessages) {
369 this.messages[lang] = rawMessages;
370 },
371
372 /**
373 * Set message for given language's rule.
374 *
375 * @param {string} lang
376 * @param {string} attribute
377 * @param {string|object} message
378 * @return {void}
379 */
380 _setRuleMessage: function(lang, attribute, message) {
381 this._load(lang);
382 if (message === undefined) {
383 message = this.messages[lang].def;
384 }
385
386 this.messages[lang][attribute] = message;
387 },
388
389 /**
390 * Load messages (if not already loaded)
391 *
392 * @param {string} lang
393 * @return {void}
394 */
395 _load: function(lang) {
396 if (!this.messages[lang]) {
397 try {
398 var rawMessages = require_method('./lang/' + lang);
399 this._set(lang, rawMessages);
400 } catch (e) {}
401 }
402 },
403
404 /**
405 * Get raw messages for language
406 *
407 * @param {string} lang
408 * @return {object}
409 */
410 _get: function(lang) {
411 this._load(lang);
412 return this.messages[lang];
413 },
414
415 /**
416 * Make messages for given language
417 *
418 * @param {string} lang
419 * @return {Messages}
420 */
421 _make: function(lang) {
422 this._load(lang);
423 return new Messages(lang, this.messages[lang]);
424 }
425
426};
427
428module.exports = container;
429
430},{"./lang/en":5,"./messages":6}],5:[function(require,module,exports){
431module.exports = {
432 accepted: 'The :attribute must be accepted.',
433 after: 'The :attribute must be after :after.',
434 after_or_equal: 'The :attribute must be equal or after :after_or_equal.',
435 alpha: 'The :attribute field must contain only alphabetic characters.',
436 alpha_dash: 'The :attribute field may only contain alpha-numeric characters, as well as dashes and underscores.',
437 alpha_num: 'The :attribute field must be alphanumeric.',
438 before: 'The :attribute must be before :before.',
439 before_or_equal: 'The :attribute must be equal or before :before_or_equal.',
440 between: 'The :attribute field must be between :min and :max.',
441 confirmed: 'The :attribute confirmation does not match.',
442 email: 'The :attribute format is invalid.',
443 date: 'The :attribute is not a valid date format.',
444 def: 'The :attribute attribute has errors.',
445 digits: 'The :attribute must be :digits digits.',
446 different: 'The :attribute and :different must be different.',
447 'in': 'The selected :attribute is invalid.',
448 integer: 'The :attribute must be an integer.',
449 hex: 'The :attribute field should have hexadecimal format',
450 min: {
451 numeric: 'The :attribute must be at least :min.',
452 string: 'The :attribute must be at least :min characters.'
453 },
454 max: {
455 numeric: 'The :attribute may not be greater than :max.',
456 string: 'The :attribute may not be greater than :max characters.'
457 },
458 not_in: 'The selected :attribute is invalid.',
459 numeric: 'The :attribute must be a number.',
460 present: 'The :attribute field must be present (but can be empty).',
461 required: 'The :attribute field is required.',
462 required_if: 'The :attribute field is required when :other is :value.',
463 required_unless: 'The :attribute field is required when :other is not :value.',
464 required_with: 'The :attribute field is required when :field is not empty.',
465 required_with_all: 'The :attribute field is required when :fields are not empty.',
466 required_without: 'The :attribute field is required when :field is empty.',
467 required_without_all: 'The :attribute field is required when :fields are empty.',
468 same: 'The :attribute and :same fields must match.',
469 size: {
470 numeric: 'The :attribute must be :size.',
471 string: 'The :attribute must be :size characters.'
472 },
473 string: 'The :attribute must be a string.',
474 url: 'The :attribute format is invalid.',
475 regex: 'The :attribute format is invalid.',
476 attributes: {}
477};
478
479},{}],6:[function(require,module,exports){
480var Attributes = require('./attributes');
481
482var Messages = function(lang, messages) {
483 this.lang = lang;
484 this.messages = messages;
485 this.customMessages = {};
486 this.attributeNames = {};
487};
488
489Messages.prototype = {
490 constructor: Messages,
491
492 /**
493 * Set custom messages
494 *
495 * @param {object} customMessages
496 * @return {void}
497 */
498 _setCustom: function(customMessages) {
499 this.customMessages = customMessages || {};
500 },
501
502 /**
503 * Set custom attribute names.
504 *
505 * @param {object} attributes
506 */
507 _setAttributeNames: function(attributes) {
508 this.attributeNames = attributes;
509 },
510
511 /**
512 * Set the attribute formatter.
513 *
514 * @param {fuction} func
515 * @return {void}
516 */
517 _setAttributeFormatter: function(func) {
518 this.attributeFormatter = func;
519 },
520
521 /**
522 * Get attribute name to display.
523 *
524 * @param {string} attribute
525 * @return {string}
526 */
527 _getAttributeName: function(attribute) {
528 var name = attribute;
529 if (this.attributeNames.hasOwnProperty(attribute)) {
530 return this.attributeNames[attribute];
531 } else if (this.messages.attributes.hasOwnProperty(attribute)) {
532 name = this.messages.attributes[attribute];
533 }
534
535 if (this.attributeFormatter) {
536 name = this.attributeFormatter(name);
537 }
538
539 return name;
540 },
541
542 /**
543 * Get all messages
544 *
545 * @return {object}
546 */
547 all: function() {
548 return this.messages;
549 },
550
551 /**
552 * Render message
553 *
554 * @param {Rule} rule
555 * @return {string}
556 */
557 render: function(rule) {
558 if (rule.customMessage) {
559 return rule.customMessage;
560 }
561 var template = this._getTemplate(rule);
562
563 var message;
564 if (Attributes.replacements[rule.name]) {
565 message = Attributes.replacements[rule.name].apply(this, [template, rule]);
566 } else {
567 message = this._replacePlaceholders(rule, template, {});
568 }
569
570 return message;
571 },
572
573 /**
574 * Get the template to use for given rule
575 *
576 * @param {Rule} rule
577 * @return {string}
578 */
579 _getTemplate: function(rule) {
580
581 var messages = this.messages;
582 var template = messages.def;
583 var customMessages = this.customMessages;
584 var formats = [rule.name + '.' + rule.attribute, rule.name];
585
586 for (var i = 0, format; i < formats.length; i++) {
587 format = formats[i];
588 if (customMessages.hasOwnProperty(format)) {
589 template = customMessages[format];
590 break;
591 } else if (messages.hasOwnProperty(format)) {
592 template = messages[format];
593 break;
594 }
595 }
596
597 if (typeof template === 'object') {
598 template = template[rule._getValueType()];
599 }
600
601 return template;
602 },
603
604 /**
605 * Replace placeholders in the template using the data object
606 *
607 * @param {Rule} rule
608 * @param {string} template
609 * @param {object} data
610 * @return {string}
611 */
612 _replacePlaceholders: function(rule, template, data) {
613 var message, attribute;
614
615 data.attribute = this._getAttributeName(rule.attribute);
616 data[rule.name] = data[rule.name] || rule.getParameters().join(',');
617
618 if (typeof template === 'string' && typeof data === 'object') {
619 message = template;
620
621 for (attribute in data) {
622 message = message.replace(new RegExp(':' + attribute, 'g'), data[attribute]);
623 }
624 }
625
626 return message;
627 }
628
629};
630
631module.exports = Messages;
632
633},{"./attributes":2}],7:[function(require,module,exports){
634function leapYear(year) {
635 return ((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0);
636}
637
638function isValidDate(inDate) {
639 var valid = true;
640
641 // reformat if supplied as mm.dd.yyyy (period delimiter)
642 if (typeof inDate === 'string') {
643 var pos = inDate.indexOf('.');
644 if ((pos > 0 && pos <= 6)) {
645 inDate = inDate.replace(/\./g, '-');
646 }
647 }
648
649 var testDate = new Date(inDate);
650 var yr = testDate.getFullYear();
651 var mo = testDate.getMonth();
652 var day = testDate.getDate();
653
654 var daysInMonth = [31, (leapYear(yr) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
655
656 if (yr < 1000) { return false; }
657 if (isNaN(mo)) { return false; }
658 if (mo + 1 > 12) { return false; }
659 if (isNaN(day)) { return false; }
660 if (day > daysInMonth[mo]) { return false; }
661
662 return valid;
663}
664
665var rules = {
666
667 required: function(val) {
668 var str;
669
670 if (val === undefined || val === null) {
671 return false;
672 }
673
674 str = String(val).replace(/\s/g, "");
675 return str.length > 0 ? true : false;
676 },
677
678 required_if: function(val, req, attribute) {
679 req = this.getParameters();
680 if (this.validator._objectPath(this.validator.input, req[0]) === req[1]) {
681 return this.validator.getRule('required').validate(val);
682 }
683
684 return true;
685 },
686
687 required_unless: function(val, req, attribute) {
688 req = this.getParameters();
689 if (this.validator._objectPath(this.validator.input, req[0]) !== req[1]) {
690 return this.validator.getRule('required').validate(val);
691 }
692
693 return true;
694 },
695
696 required_with: function(val, req, attribute) {
697 if (this.validator._objectPath(this.validator.input, req)) {
698 return this.validator.getRule('required').validate(val);
699 }
700
701 return true;
702 },
703
704 required_with_all: function(val, req, attribute) {
705
706 req = this.getParameters();
707
708 for(var i = 0; i < req.length; i++) {
709 if (!this.validator._objectPath(this.validator.input, req[i])) {
710 return true;
711 }
712 }
713
714 return this.validator.getRule('required').validate(val);
715 },
716
717 required_without: function(val, req, attribute) {
718
719 if (this.validator._objectPath(this.validator.input, req)) {
720 return true;
721 }
722
723 return this.validator.getRule('required').validate(val);
724 },
725
726 required_without_all: function(val, req, attribute) {
727
728 req = this.getParameters();
729
730 for(var i = 0; i < req.length; i++) {
731 if (this.validator._objectPath(this.validator.input, req[i])) {
732 return true;
733 }
734 }
735
736 return this.validator.getRule('required').validate(val);
737 },
738
739 'boolean': function (val) {
740 return (
741 val === true ||
742 val === false ||
743 val === 0 ||
744 val === 1 ||
745 val === '0' ||
746 val === '1' ||
747 val === 'true' ||
748 val === 'false'
749 );
750 },
751
752 // compares the size of strings
753 // with numbers, compares the value
754 size: function(val, req, attribute) {
755 if (val) {
756 req = parseFloat(req);
757
758 var size = this.getSize();
759
760 return size === req;
761 }
762
763 return true;
764 },
765
766 string: function(val, req, attribute) {
767 return typeof val === 'string';
768 },
769
770 sometimes: function(val) {
771 return true;
772 },
773
774 /**
775 * Compares the size of strings or the value of numbers if there is a truthy value
776 */
777 min: function(val, req, attribute) {
778 var size = this.getSize();
779 return size >= req;
780 },
781
782 /**
783 * Compares the size of strings or the value of numbers if there is a truthy value
784 */
785 max: function(val, req, attribute) {
786 var size = this.getSize();
787 return size <= req;
788 },
789
790 between: function(val, req, attribute) {
791 req = this.getParameters();
792 var size = this.getSize();
793 var min = parseFloat(req[0], 10);
794 var max = parseFloat(req[1], 10);
795 return size >= min && size <= max;
796 },
797
798 email: function(val) {
799 var re = /^(([^<>()[\]\\.,;:\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,}))$/;
800 return re.test(val);
801 },
802
803 numeric: function(val) {
804 var num;
805
806 num = Number(val); // tries to convert value to a number. useful if value is coming from form element
807
808 if (typeof num === 'number' && !isNaN(num) && typeof val !== 'boolean') {
809 return true;
810 } else {
811 return false;
812 }
813 },
814
815 array: function(val) {
816 return val instanceof Array;
817 },
818
819 url: function(url) {
820 return (/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-z]{2,63}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/i).test(url);
821 },
822
823 alpha: function(val) {
824 return (/^[a-zA-Z]+$/).test(val);
825 },
826
827 alpha_dash: function(val) {
828 return (/^[a-zA-Z0-9_\-]+$/).test(val);
829 },
830
831 alpha_num: function(val) {
832 return (/^[a-zA-Z0-9]+$/).test(val);
833 },
834
835 same: function(val, req) {
836 var val1 = this.validator._flattenObject(this.validator.input)[req];
837 var val2 = val;
838
839 if (val1 === val2) {
840 return true;
841 }
842
843 return false;
844 },
845
846 different: function(val, req) {
847 var val1 = this.validator._flattenObject(this.validator.input)[req];
848 var val2 = val;
849
850 if (val1 !== val2) {
851 return true;
852 }
853
854 return false;
855 },
856
857 "in": function(val, req) {
858 var list, i;
859
860 if (val) {
861 list = this.getParameters();
862 }
863
864 if (val && !(val instanceof Array)) {
865 var localValue = val;
866
867 for (i = 0; i < list.length; i++) {
868 if (typeof list[i] === 'string') {
869 localValue = String(val);
870 }
871
872 if (localValue === list[i]) {
873 return true;
874 }
875 }
876
877 return false;
878 }
879
880 if (val && val instanceof Array) {
881 for (i = 0; i < val.length; i++) {
882 if (list.indexOf(val[i]) < 0) {
883 return false;
884 }
885 }
886 }
887
888 return true;
889 },
890
891 not_in: function(val, req) {
892 var list = this.getParameters();
893 var len = list.length;
894 var returnVal = true;
895
896 for (var i = 0; i < len; i++) {
897 var localValue = val;
898
899 if (typeof list[i] === 'string') {
900 localValue = String(val);
901 }
902
903 if (localValue === list[i]) {
904 returnVal = false;
905 break;
906 }
907 }
908
909 return returnVal;
910 },
911
912 accepted: function(val) {
913 if (val === 'on' || val === 'yes' || val === 1 || val === '1' || val === true) {
914 return true;
915 }
916
917 return false;
918 },
919
920 confirmed: function(val, req, key) {
921 var confirmedKey = key + '_confirmation';
922
923 if (this.validator.input[confirmedKey] === val) {
924 return true;
925 }
926
927 return false;
928 },
929
930 integer: function(val) {
931 return String(parseInt(val, 10)) === String(val);
932 },
933
934 digits: function(val, req) {
935 var numericRule = this.validator.getRule('numeric');
936 if (numericRule.validate(val) && String(val).length === parseInt(req)) {
937 return true;
938 }
939
940 return false;
941 },
942
943 regex: function(val, req) {
944 var mod = /[g|i|m]{1,3}$/;
945 var flag = req.match(mod);
946 flag = flag ? flag[0] : "";
947 req = req.replace(mod, "").slice(1, -1);
948 req = new RegExp(req, flag);
949 return !!req.test(val);
950 },
951
952 date: function(val, format) {
953 return isValidDate(val);
954 },
955
956 present: function(val) {
957 return typeof val !== 'undefined';
958 },
959
960 after: function(val, req){
961 var val1 = this.validator.input[req];
962 var val2 = val;
963
964 if(!isValidDate(val1)){ return false;}
965 if(!isValidDate(val2)){ return false;}
966
967 if (new Date(val1).getTime() < new Date(val2).getTime()) {
968 return true;
969 }
970
971 return false;
972 },
973
974 after_or_equal: function(val, req){
975 var val1 = this.validator.input[req];
976 var val2 = val;
977
978 if(!isValidDate(val1)){ return false;}
979 if(!isValidDate(val2)){ return false;}
980
981 if (new Date(val1).getTime() <= new Date(val2).getTime()) {
982 return true;
983 }
984
985 return false;
986 },
987
988 before: function(val, req){
989 var val1 = this.validator.input[req];
990 var val2 = val;
991
992 if(!isValidDate(val1)){ return false;}
993 if(!isValidDate(val2)){ return false;}
994
995 if (new Date(val1).getTime() > new Date(val2).getTime()) {
996 return true;
997 }
998
999 return false;
1000 },
1001
1002 before_or_equal: function(val, req){
1003 var val1 = this.validator.input[req];
1004 var val2 = val;
1005
1006 if(!isValidDate(val1)){ return false;}
1007 if(!isValidDate(val2)){ return false;}
1008
1009 if (new Date(val1).getTime() >= new Date(val2).getTime()) {
1010 return true;
1011 }
1012
1013 return false;
1014 },
1015
1016 hex: function(val) {
1017 return (/^[0-9a-f]+$/i).test(val);
1018 }
1019};
1020
1021var missedRuleValidator = function() {
1022 throw new Error('Validator `' + this.name + '` is not defined!');
1023};
1024var missedRuleMessage;
1025
1026function Rule(name, fn, async) {
1027 this.name = name;
1028 this.fn = fn;
1029 this.passes = null;
1030 this._customMessage = undefined;
1031 this.async = async;
1032}
1033
1034Rule.prototype = {
1035
1036 /**
1037 * Validate rule
1038 *
1039 * @param {mixed} inputValue
1040 * @param {mixed} ruleValue
1041 * @param {string} attribute
1042 * @param {function} callback
1043 * @return {boolean|undefined}
1044 */
1045 validate: function(inputValue, ruleValue, attribute, callback) {
1046 var _this = this;
1047 this._setValidatingData(attribute, inputValue, ruleValue);
1048 if (typeof callback === 'function') {
1049 this.callback = callback;
1050 var handleResponse = function(passes, message) {
1051 _this.response(passes, message);
1052 };
1053
1054 if (this.async) {
1055 return this._apply(inputValue, ruleValue, attribute, handleResponse);
1056 } else {
1057 return handleResponse(this._apply(inputValue, ruleValue, attribute));
1058 }
1059 }
1060 return this._apply(inputValue, ruleValue, attribute);
1061 },
1062
1063 /**
1064 * Apply validation function
1065 *
1066 * @param {mixed} inputValue
1067 * @param {mixed} ruleValue
1068 * @param {string} attribute
1069 * @param {function} callback
1070 * @return {boolean|undefined}
1071 */
1072 _apply: function(inputValue, ruleValue, attribute, callback) {
1073 var fn = this.isMissed() ? missedRuleValidator : this.fn;
1074
1075 return fn.apply(this, [inputValue, ruleValue, attribute, callback]);
1076 },
1077
1078 /**
1079 * Set validating data
1080 *
1081 * @param {string} attribute
1082 * @param {mixed} inputValue
1083 * @param {mixed} ruleValue
1084 * @return {void}
1085 */
1086 _setValidatingData: function(attribute, inputValue, ruleValue) {
1087 this.attribute = attribute;
1088 this.inputValue = inputValue;
1089 this.ruleValue = ruleValue;
1090 },
1091
1092 /**
1093 * Get parameters
1094 *
1095 * @return {array}
1096 */
1097 getParameters: function() {
1098 var value = [];
1099
1100 if (typeof this.ruleValue === 'string') {
1101 value = this.ruleValue.split(',');
1102 }
1103
1104 if (typeof this.ruleValue === 'number') {
1105 value.push(this.ruleValue);
1106 }
1107
1108 if (this.ruleValue instanceof Array) {
1109 value = this.ruleValue;
1110 }
1111
1112 return value;
1113 },
1114
1115 /**
1116 * Get true size of value
1117 *
1118 * @return {integer|float}
1119 */
1120 getSize: function() {
1121 var value = this.inputValue;
1122
1123 if (value instanceof Array) {
1124 return value.length;
1125 }
1126
1127 if (typeof value === 'number') {
1128 return value;
1129 }
1130
1131 if (this.validator._hasNumericRule(this.attribute)) {
1132 return parseFloat(value, 10);
1133 }
1134
1135 return value.length;
1136 },
1137
1138 /**
1139 * Get the type of value being checked; numeric or string.
1140 *
1141 * @return {string}
1142 */
1143 _getValueType: function() {
1144
1145 if (typeof this.inputValue === 'number' || this.validator._hasNumericRule(this.attribute)) {
1146 return 'numeric';
1147 }
1148
1149 return 'string';
1150 },
1151
1152 /**
1153 * Set the async callback response
1154 *
1155 * @param {boolean|undefined} passes Whether validation passed
1156 * @param {string|undefined} message Custom error message
1157 * @return {void}
1158 */
1159 response: function(passes, message) {
1160 this.passes = (passes === undefined || passes === true);
1161 this._customMessage = message;
1162 this.callback(this.passes, message);
1163 },
1164
1165 /**
1166 * Set validator instance
1167 *
1168 * @param {Validator} validator
1169 * @return {void}
1170 */
1171 setValidator: function(validator) {
1172 this.validator = validator;
1173 },
1174
1175 /**
1176 * Check if rule is missed
1177 *
1178 * @return {boolean}
1179 */
1180 isMissed: function() {
1181 return typeof this.fn !== 'function';
1182 },
1183
1184 get customMessage() {
1185 return this.isMissed() ? missedRuleMessage : this._customMessage;
1186 }
1187};
1188
1189var manager = {
1190
1191 /**
1192 * List of async rule names
1193 *
1194 * @type {Array}
1195 */
1196 asyncRules: [],
1197
1198 /**
1199 * Implicit rules (rules to always validate)
1200 *
1201 * @type {Array}
1202 */
1203 implicitRules: ['required', 'required_if', 'required_unless', 'required_with', 'required_with_all', 'required_without', 'required_without_all', 'accepted', 'present'],
1204
1205 /**
1206 * Get rule by name
1207 *
1208 * @param {string} name
1209 * @param {Validator}
1210 * @return {Rule}
1211 */
1212 make: function(name, validator) {
1213 var async = this.isAsync(name);
1214 var rule = new Rule(name, rules[name], async);
1215 rule.setValidator(validator);
1216 return rule;
1217 },
1218
1219 /**
1220 * Determine if given rule is async
1221 *
1222 * @param {string} name
1223 * @return {boolean}
1224 */
1225 isAsync: function(name) {
1226 for (var i = 0, len = this.asyncRules.length; i < len; i++) {
1227 if (this.asyncRules[i] === name) {
1228 return true;
1229 }
1230 }
1231 return false;
1232 },
1233
1234 /**
1235 * Determine if rule is implicit (should always validate)
1236 *
1237 * @param {string} name
1238 * @return {boolean}
1239 */
1240 isImplicit: function(name) {
1241 return this.implicitRules.indexOf(name) > -1;
1242 },
1243
1244 /**
1245 * Register new rule
1246 *
1247 * @param {string} name
1248 * @param {function} fn
1249 * @return {void}
1250 */
1251 register: function(name, fn) {
1252 rules[name] = fn;
1253 },
1254
1255 /**
1256 * Register new implicit rule
1257 *
1258 * @param {string} name
1259 * @param {function} fn
1260 * @return {void}
1261 */
1262 registerImplicit: function(name, fn) {
1263 this.register(name, fn);
1264 this.implicitRules.push(name);
1265 },
1266
1267 /**
1268 * Register async rule
1269 *
1270 * @param {string} name
1271 * @param {function} fn
1272 * @return {void}
1273 */
1274 registerAsync: function(name, fn) {
1275 this.register(name, fn);
1276 this.asyncRules.push(name);
1277 },
1278
1279 /**
1280 * Register implicit async rule
1281 *
1282 * @param {string} name
1283 * @param {function} fn
1284 * @return {void}
1285 */
1286 registerAsyncImplicit: function(name, fn) {
1287 this.registerImplicit(name, fn);
1288 this.asyncRules.push(name);
1289 },
1290
1291 registerMissedRuleValidator: function(fn, message) {
1292 missedRuleValidator = fn;
1293 missedRuleMessage = message;
1294 }
1295};
1296
1297
1298
1299module.exports = manager;
1300
1301},{}],8:[function(require,module,exports){
1302var Rules = require('./rules');
1303var Lang = require('./lang');
1304var Errors = require('./errors');
1305var Attributes = require('./attributes');
1306var AsyncResolvers = require('./async');
1307
1308var Validator = function (input, rules, customMessages) {
1309 var lang = Validator.getDefaultLang();
1310 this.input = input || {};
1311
1312 this.messages = Lang._make(lang);
1313 this.messages._setCustom(customMessages);
1314 this.setAttributeFormatter(Validator.prototype.attributeFormatter);
1315
1316 this.errors = new Errors();
1317 this.errorCount = 0;
1318
1319 this.hasAsync = false;
1320 this.rules = this._parseRules(rules);
1321};
1322
1323Validator.prototype = {
1324
1325 constructor: Validator,
1326
1327 /**
1328 * Default language
1329 *
1330 * @type {string}
1331 */
1332 lang: 'en',
1333
1334 /**
1335 * Numeric based rules
1336 *
1337 * @type {array}
1338 */
1339 numericRules: ['integer', 'numeric'],
1340
1341 /**
1342 * Attribute formatter.
1343 *
1344 * @type {function}
1345 */
1346 attributeFormatter: Attributes.formatter,
1347
1348 /**
1349 * Run validator
1350 *
1351 * @return {boolean} Whether it passes; true = passes, false = fails
1352 */
1353 check: function () {
1354 var self = this;
1355
1356 for (var attribute in this.rules) {
1357 var attributeRules = this.rules[attribute];
1358 var inputValue = this._objectPath(this.input, attribute);
1359
1360 if (this._hasRule(attribute, ['sometimes']) && !this._suppliedWithData(attribute)) {
1361 continue;
1362 }
1363
1364 for (var i = 0, len = attributeRules.length, rule, ruleOptions, rulePassed; i < len; i++) {
1365 ruleOptions = attributeRules[i];
1366 rule = this.getRule(ruleOptions.name);
1367
1368 if (!this._isValidatable(rule, inputValue)) {
1369 continue;
1370 }
1371
1372 rulePassed = rule.validate(inputValue, ruleOptions.value, attribute);
1373 if (!rulePassed) {
1374 this._addFailure(rule);
1375 }
1376
1377 if (this._shouldStopValidating(attribute, rulePassed)) {
1378 break;
1379 }
1380 }
1381 }
1382
1383 return this.errorCount === 0;
1384 },
1385
1386 /**
1387 * Run async validator
1388 *
1389 * @param {function} passes
1390 * @param {function} fails
1391 * @return {void}
1392 */
1393 checkAsync: function (passes, fails) {
1394 var _this = this;
1395 passes = passes || function () {};
1396 fails = fails || function () {};
1397
1398 var failsOne = function (rule, message) {
1399 _this._addFailure(rule, message);
1400 };
1401
1402 var resolvedAll = function (allPassed) {
1403 if (allPassed) {
1404 passes();
1405 } else {
1406 fails();
1407 }
1408 };
1409
1410 var asyncResolvers = new AsyncResolvers(failsOne, resolvedAll);
1411
1412 var validateRule = function (inputValue, ruleOptions, attribute, rule) {
1413 return function () {
1414 var resolverIndex = asyncResolvers.add(rule);
1415 rule.validate(inputValue, ruleOptions.value, attribute, function () {
1416 asyncResolvers.resolve(resolverIndex);
1417 });
1418 };
1419 };
1420
1421 for (var attribute in this.rules) {
1422 var attributeRules = this.rules[attribute];
1423 var inputValue = this._objectPath(this.input, attribute);
1424
1425 if (this._hasRule(attribute, ['sometimes']) && !this._suppliedWithData(attribute)) {
1426 continue;
1427 }
1428
1429 for (var i = 0, len = attributeRules.length, rule, ruleOptions; i < len; i++) {
1430 ruleOptions = attributeRules[i];
1431
1432 rule = this.getRule(ruleOptions.name);
1433
1434 if (!this._isValidatable(rule, inputValue)) {
1435 continue;
1436 }
1437
1438 validateRule(inputValue, ruleOptions, attribute, rule)();
1439 }
1440 }
1441
1442 asyncResolvers.enableFiring();
1443 asyncResolvers.fire();
1444 },
1445
1446 /**
1447 * Add failure and error message for given rule
1448 *
1449 * @param {Rule} rule
1450 */
1451 _addFailure: function (rule) {
1452 var msg = this.messages.render(rule);
1453 this.errors.add(rule.attribute, msg);
1454 this.errorCount++;
1455 },
1456
1457 /**
1458 * Flatten nested object, normalizing { foo: { bar: 1 } } into: { 'foo.bar': 1 }
1459 *
1460 * @param {object} nested object
1461 * @return {object} flattened object
1462 */
1463 _flattenObject: function (obj) {
1464 var flattened = {};
1465
1466 function recurse(current, property) {
1467 if (!property && Object.getOwnPropertyNames(current).length === 0) {
1468 return;
1469 }
1470 if (Object(current) !== current || Array.isArray(current)) {
1471 flattened[property] = current;
1472 } else {
1473 var isEmpty = true;
1474 for (var p in current) {
1475 isEmpty = false;
1476 recurse(current[p], property ? property + "." + p : p);
1477 }
1478 if (isEmpty) {
1479 flattened[property] = {};
1480 }
1481 }
1482 }
1483 if (obj) {
1484 recurse(obj);
1485 }
1486 return flattened;
1487 },
1488
1489 /**
1490 * Extract value from nested object using string path with dot notation
1491 *
1492 * @param {object} object to search in
1493 * @param {string} path inside object
1494 * @return {any|void} value under the path
1495 */
1496 _objectPath: function (obj, path) {
1497 if (Object.prototype.hasOwnProperty.call(obj, path)) {
1498 return obj[path];
1499 }
1500
1501 var keys = path.replace(/\[(\w+)\]/g, ".$1").replace(/^\./, "").split(".");
1502 var copy = {};
1503 for (var attr in obj) {
1504 if (Object.prototype.hasOwnProperty.call(obj, attr)) {
1505 copy[attr] = obj[attr];
1506 }
1507 }
1508
1509 for (var i = 0, l = keys.length; i < l; i++) {
1510 if (Object.hasOwnProperty.call(copy, keys[i])) {
1511 copy = copy[keys[i]];
1512 } else {
1513 return;
1514 }
1515 }
1516 return copy;
1517 },
1518
1519 /**
1520 * Parse rules, normalizing format into: { attribute: [{ name: 'age', value: 3 }] }
1521 *
1522 * @param {object} rules
1523 * @return {object}
1524 */
1525 _parseRules: function (rules) {
1526
1527 var parsedRules = {};
1528 rules = this._flattenObject(rules);
1529
1530 for (var attribute in rules) {
1531
1532 var rulesArray = rules[attribute];
1533
1534 this._parseRulesCheck(attribute, rulesArray, parsedRules);
1535 }
1536 return parsedRules;
1537
1538
1539 },
1540
1541 _parseRulesCheck: function (attribute, rulesArray, parsedRules, wildCardValues) {
1542 if (attribute.indexOf('*') > -1) {
1543 this._parsedRulesRecurse(attribute, rulesArray, parsedRules, wildCardValues);
1544 } else {
1545 this._parseRulesDefault(attribute, rulesArray, parsedRules, wildCardValues);
1546 }
1547 },
1548
1549 _parsedRulesRecurse: function (attribute, rulesArray, parsedRules, wildCardValues) {
1550 var parentPath = attribute.substr(0, attribute.indexOf('*') - 1);
1551 var propertyValue = this._objectPath(this.input, parentPath);
1552
1553 if (propertyValue) {
1554 for (var propertyNumber = 0; propertyNumber < propertyValue.length; propertyNumber++) {
1555 var workingValues = wildCardValues ? wildCardValues.slice() : [];
1556 workingValues.push(propertyNumber);
1557 this._parseRulesCheck(attribute.replace('*', propertyNumber), rulesArray, parsedRules, workingValues);
1558 }
1559 }
1560 },
1561
1562 _parseRulesDefault: function (attribute, rulesArray, parsedRules, wildCardValues) {
1563 var attributeRules = [];
1564
1565 if (rulesArray instanceof Array) {
1566 rulesArray = this._prepareRulesArray(rulesArray);
1567 }
1568
1569 if (typeof rulesArray === 'string') {
1570 rulesArray = rulesArray.split('|');
1571 }
1572
1573 for (var i = 0, len = rulesArray.length, rule; i < len; i++) {
1574 rule = typeof rulesArray[i] === 'string' ? this._extractRuleAndRuleValue(rulesArray[i]) : rulesArray[i];
1575 if (rule.value) {
1576 rule.value = this._replaceWildCards(rule.value, wildCardValues);
1577 this._replaceWildCardsMessages(wildCardValues);
1578 }
1579
1580 if (Rules.isAsync(rule.name)) {
1581 this.hasAsync = true;
1582 }
1583 attributeRules.push(rule);
1584 }
1585
1586 parsedRules[attribute] = attributeRules;
1587 },
1588
1589 _replaceWildCards: function (path, nums) {
1590
1591 if (!nums) {
1592 return path;
1593 }
1594
1595 var path2 = path;
1596 nums.forEach(function (value) {
1597 if(Array.isArray(path2)){
1598 path2 = path2[0];
1599 }
1600 pos = path2.indexOf('*');
1601 if (pos === -1) {
1602 return path2;
1603 }
1604 path2 = path2.substr(0, pos) + value + path2.substr(pos + 1);
1605 });
1606 if(Array.isArray(path)){
1607 path[0] = path2;
1608 path2 = path;
1609 }
1610 return path2;
1611 },
1612
1613 _replaceWildCardsMessages: function (nums) {
1614 var customMessages = this.messages.customMessages;
1615 var self = this;
1616 Object.keys(customMessages).forEach(function (key) {
1617 if (nums) {
1618 var newKey = self._replaceWildCards(key, nums);
1619 customMessages[newKey] = customMessages[key];
1620 }
1621 });
1622
1623 this.messages._setCustom(customMessages);
1624 },
1625 /**
1626 * Prepare rules if it comes in Array. Check for objects. Need for type validation.
1627 *
1628 * @param {array} rulesArray
1629 * @return {array}
1630 */
1631 _prepareRulesArray: function (rulesArray) {
1632 var rules = [];
1633
1634 for (var i = 0, len = rulesArray.length; i < len; i++) {
1635 if (typeof rulesArray[i] === 'object') {
1636 for (var rule in rulesArray[i]) {
1637 rules.push({
1638 name: rule,
1639 value: rulesArray[i][rule]
1640 });
1641 }
1642 } else {
1643 rules.push(rulesArray[i]);
1644 }
1645 }
1646
1647 return rules;
1648 },
1649
1650 /**
1651 * Determines if the attribute is supplied with the original data object.
1652 *
1653 * @param {array} attribute
1654 * @return {boolean}
1655 */
1656 _suppliedWithData: function (attribute) {
1657 return this.input.hasOwnProperty(attribute);
1658 },
1659
1660 /**
1661 * Extract a rule and a value from a ruleString (i.e. min:3), rule = min, value = 3
1662 *
1663 * @param {string} ruleString min:3
1664 * @return {object} object containing the name of the rule and value
1665 */
1666 _extractRuleAndRuleValue: function (ruleString) {
1667 var rule = {},
1668 ruleArray;
1669
1670 rule.name = ruleString;
1671
1672 if (ruleString.indexOf(':') >= 0) {
1673 ruleArray = ruleString.split(':');
1674 rule.name = ruleArray[0];
1675 rule.value = ruleArray.slice(1).join(":");
1676 }
1677
1678 return rule;
1679 },
1680
1681 /**
1682 * Determine if attribute has any of the given rules
1683 *
1684 * @param {string} attribute
1685 * @param {array} findRules
1686 * @return {boolean}
1687 */
1688 _hasRule: function (attribute, findRules) {
1689 var rules = this.rules[attribute] || [];
1690 for (var i = 0, len = rules.length; i < len; i++) {
1691 if (findRules.indexOf(rules[i].name) > -1) {
1692 return true;
1693 }
1694 }
1695 return false;
1696 },
1697
1698 /**
1699 * Determine if attribute has any numeric-based rules.
1700 *
1701 * @param {string} attribute
1702 * @return {Boolean}
1703 */
1704 _hasNumericRule: function (attribute) {
1705 return this._hasRule(attribute, this.numericRules);
1706 },
1707
1708 /**
1709 * Determine if rule is validatable
1710 *
1711 * @param {Rule} rule
1712 * @param {mixed} value
1713 * @return {boolean}
1714 */
1715 _isValidatable: function (rule, value) {
1716 if (Rules.isImplicit(rule.name)) {
1717 return true;
1718 }
1719
1720 return this.getRule('required').validate(value);
1721 },
1722
1723 /**
1724 * Determine if we should stop validating.
1725 *
1726 * @param {string} attribute
1727 * @param {boolean} rulePassed
1728 * @return {boolean}
1729 */
1730 _shouldStopValidating: function (attribute, rulePassed) {
1731
1732 var stopOnAttributes = this.stopOnAttributes;
1733 if (typeof stopOnAttributes === 'undefined' || stopOnAttributes === false || rulePassed === true) {
1734 return false;
1735 }
1736
1737 if (stopOnAttributes instanceof Array) {
1738 return stopOnAttributes.indexOf(attribute) > -1;
1739 }
1740
1741 return true;
1742 },
1743
1744 /**
1745 * Set custom attribute names.
1746 *
1747 * @param {object} attributes
1748 * @return {void}
1749 */
1750 setAttributeNames: function (attributes) {
1751 this.messages._setAttributeNames(attributes);
1752 },
1753
1754 /**
1755 * Set the attribute formatter.
1756 *
1757 * @param {fuction} func
1758 * @return {void}
1759 */
1760 setAttributeFormatter: function (func) {
1761 this.messages._setAttributeFormatter(func);
1762 },
1763
1764 /**
1765 * Get validation rule
1766 *
1767 * @param {string} name
1768 * @return {Rule}
1769 */
1770 getRule: function (name) {
1771 return Rules.make(name, this);
1772 },
1773
1774 /**
1775 * Stop on first error.
1776 *
1777 * @param {boolean|array} An array of attributes or boolean true/false for all attributes.
1778 * @return {void}
1779 */
1780 stopOnError: function (attributes) {
1781 this.stopOnAttributes = attributes;
1782 },
1783
1784 /**
1785 * Determine if validation passes
1786 *
1787 * @param {function} passes
1788 * @return {boolean|undefined}
1789 */
1790 passes: function (passes) {
1791 var async = this._checkAsync('passes', passes);
1792 if (async) {
1793 return this.checkAsync(passes);
1794 }
1795 return this.check();
1796 },
1797
1798 /**
1799 * Determine if validation fails
1800 *
1801 * @param {function} fails
1802 * @return {boolean|undefined}
1803 */
1804 fails: function (fails) {
1805 var async = this._checkAsync('fails', fails);
1806 if (async) {
1807 return this.checkAsync(function () {}, fails);
1808 }
1809 return !this.check();
1810 },
1811
1812 /**
1813 * Check if validation should be called asynchronously
1814 *
1815 * @param {string} funcName Name of the caller
1816 * @param {function} callback
1817 * @return {boolean}
1818 */
1819 _checkAsync: function (funcName, callback) {
1820 var hasCallback = typeof callback === 'function';
1821 if (this.hasAsync && !hasCallback) {
1822 throw funcName + ' expects a callback when async rules are being tested.';
1823 }
1824
1825 return this.hasAsync || hasCallback;
1826 }
1827
1828};
1829
1830/**
1831 * Set messages for language
1832 *
1833 * @param {string} lang
1834 * @param {object} messages
1835 * @return {this}
1836 */
1837Validator.setMessages = function (lang, messages) {
1838 Lang._set(lang, messages);
1839 return this;
1840};
1841
1842/**
1843 * Get messages for given language
1844 *
1845 * @param {string} lang
1846 * @return {Messages}
1847 */
1848Validator.getMessages = function (lang) {
1849 return Lang._get(lang);
1850};
1851
1852/**
1853 * Set default language to use
1854 *
1855 * @param {string} lang
1856 * @return {void}
1857 */
1858Validator.useLang = function (lang) {
1859 this.prototype.lang = lang;
1860};
1861
1862/**
1863 * Get default language
1864 *
1865 * @return {string}
1866 */
1867Validator.getDefaultLang = function () {
1868 return this.prototype.lang;
1869};
1870
1871/**
1872 * Set the attribute formatter.
1873 *
1874 * @param {fuction} func
1875 * @return {void}
1876 */
1877Validator.setAttributeFormatter = function (func) {
1878 this.prototype.attributeFormatter = func;
1879};
1880
1881/**
1882 * Stop on first error.
1883 *
1884 * @param {boolean|array} An array of attributes or boolean true/false for all attributes.
1885 * @return {void}
1886 */
1887Validator.stopOnError = function (attributes) {
1888 this.prototype.stopOnAttributes = attributes;
1889};
1890
1891/**
1892 * Register custom validation rule
1893 *
1894 * @param {string} name
1895 * @param {function} fn
1896 * @param {string} message
1897 * @return {void}
1898 */
1899Validator.register = function (name, fn, message) {
1900 var lang = Validator.getDefaultLang();
1901 Rules.register(name, fn);
1902 Lang._setRuleMessage(lang, name, message);
1903};
1904
1905/**
1906 * Register custom validation rule
1907 *
1908 * @param {string} name
1909 * @param {function} fn
1910 * @param {string} message
1911 * @return {void}
1912 */
1913Validator.registerImplicit = function (name, fn, message) {
1914 var lang = Validator.getDefaultLang();
1915 Rules.registerImplicit(name, fn);
1916 Lang._setRuleMessage(lang, name, message);
1917};
1918
1919/**
1920 * Register asynchronous validation rule
1921 *
1922 * @param {string} name
1923 * @param {function} fn
1924 * @param {string} message
1925 * @return {void}
1926 */
1927Validator.registerAsync = function (name, fn, message) {
1928 var lang = Validator.getDefaultLang();
1929 Rules.registerAsync(name, fn);
1930 Lang._setRuleMessage(lang, name, message);
1931};
1932
1933/**
1934 * Register asynchronous validation rule
1935 *
1936 * @param {string} name
1937 * @param {function} fn
1938 * @param {string} message
1939 * @return {void}
1940 */
1941Validator.registerAsyncImplicit = function (name, fn, message) {
1942 var lang = Validator.getDefaultLang();
1943 Rules.registerAsyncImplicit(name, fn);
1944 Lang._setRuleMessage(lang, name, message);
1945};
1946
1947/**
1948 * Register validator for missed validation rule
1949 *
1950 * @param {string} name
1951 * @param {function} fn
1952 * @param {string} message
1953 * @return {void}
1954 */
1955Validator.registerMissedRuleValidator = function(fn, message) {
1956 Rules.registerMissedRuleValidator(fn, message);
1957};
1958
1959module.exports = Validator;
1960
1961},{"./async":1,"./attributes":2,"./errors":3,"./lang":4,"./rules":7}]},{},[8])(8)
1962});
\No newline at end of file