CLIENT GUI Framework
[vnfsdk/refrepo.git] / openo-portal / portal-extsys / src / main / webapp / extsys / vim / js / jqBootstrapValidation.js
1 /*\r
2  * Copyright 2016-2017 ZTE Corporation.\r
3  *\r
4  * Licensed under the Apache License, Version 2.0 (the "License");\r
5  * you may not use this file except in compliance with the License.\r
6  * You may obtain a copy of the License at\r
7  *\r
8  *     http://www.apache.org/licenses/LICENSE-2.0\r
9  *\r
10  * Unless required by applicable law or agreed to in writing, software\r
11  * distributed under the License is distributed on an "AS IS" BASIS,\r
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  * See the License for the specific language governing permissions and\r
14  * limitations under the License.\r
15  */\r
16 /* jqBootstrapValidation\r
17  * A plugin for automating validation on Twitter Bootstrap formatted forms.\r
18  *\r
19  * v1.3.6\r
20  *\r
21  * License: MIT <http://opensource.org/licenses/mit-license.php> - see LICENSE file\r
22  *\r
23  * http://ReactiveRaven.github.com/jqBootstrapValidation/\r
24  */\r
25 \r
26 (function ($) {\r
27 \r
28     var createdElements = [];\r
29 \r
30     var defaults = {\r
31         options: {\r
32             prependExistingHelpBlock: false,\r
33             sniffHtml: true, // sniff for 'required', 'maxlength', etc\r
34             preventSubmit: true, // stop the form submit event from firing if validation fails\r
35             submitError: false, // function called if there is an error when trying to submit\r
36             submitSuccess: false, // function called just before a successful submit event is sent to the server\r
37             semanticallyStrict: false, // set to true to tidy up generated HTML output\r
38             autoAdd: {\r
39                 helpBlocks: true\r
40             },\r
41             filter: function () {\r
42                 // return $(this).is(":visible"); // only validate elements you can see\r
43                 return true; // validate everything\r
44             }\r
45         },\r
46         methods: {\r
47             init: function (options) {\r
48 \r
49                 var settings = $.extend(true, {}, defaults);\r
50 \r
51                 settings.options = $.extend(true, settings.options, options);\r
52 \r
53                 var $siblingElements = this;\r
54 \r
55                 var uniqueForms = $.unique(\r
56                     $siblingElements.map(function () {\r
57                         return $(this).parents("form")[0];\r
58                     }).toArray()\r
59                 );\r
60 \r
61                 $(uniqueForms).bind("submit", function (e) {\r
62                     var $form = $(this);\r
63                     var warningsFound = 0;\r
64                     var $inputs = $form.find("input,textarea,select").not("[type=submit],[type=image]").filter(settings.options.filter);\r
65                     $inputs.trigger("submit.validation").trigger("validationLostFocus.validation");\r
66 \r
67                     $inputs.each(function (i, el) {\r
68                         var $this = $(el),\r
69                             $controlGroup = $this.parents(".control-group").first();\r
70                         if (\r
71                             $controlGroup.hasClass("warning")\r
72                         ) {\r
73                             $controlGroup.removeClass("warning").addClass("error");\r
74                             warningsFound++;\r
75                         }\r
76                     });\r
77 \r
78                     $inputs.trigger("validationLostFocus.validation");\r
79 \r
80                     if (warningsFound) {\r
81                         if (settings.options.preventSubmit) {\r
82                             e.preventDefault();\r
83                         }\r
84                         $form.addClass("error");\r
85                         if ($.isFunction(settings.options.submitError)) {\r
86                             settings.options.submitError($form, e, $inputs.jqBootstrapValidation("collectErrors", true));\r
87                         }\r
88                     } else {\r
89                         $form.removeClass("error");\r
90                         if ($.isFunction(settings.options.submitSuccess)) {\r
91                             settings.options.submitSuccess($form, e);\r
92                         }\r
93                     }\r
94                 });\r
95 \r
96                 return this.each(function () {\r
97 \r
98                     // Get references to everything we're interested in\r
99                     var $this = $(this),\r
100                         $controlGroup = $this.parents(".control-group").first(),\r
101                         $helpBlock = $controlGroup.find(".help-block").first(),\r
102                         $form = $this.parents("form").first(),\r
103                         validatorNames = [];\r
104 \r
105                     // create message container if not exists\r
106                     if (!$helpBlock.length && settings.options.autoAdd && settings.options.autoAdd.helpBlocks) {\r
107                         $helpBlock = $('<div class="help-block" />');\r
108                         $controlGroup.find('.controls').append($helpBlock);\r
109                         createdElements.push($helpBlock[0]);\r
110                     }\r
111 \r
112                     // =============================================================\r
113                     //                                     SNIFF HTML FOR VALIDATORS\r
114                     // =============================================================\r
115 \r
116                     // *snort sniff snuffle*\r
117 \r
118                     if (settings.options.sniffHtml) {\r
119                         var message = "";\r
120                         // ---------------------------------------------------------\r
121                         //                                                   PATTERN\r
122                         // ---------------------------------------------------------\r
123                         if ($this.attr("pattern") !== undefined) {\r
124                             message = "Not in the expected format<!-- data-validation-pattern-message to override -->";\r
125                             if ($this.data("validationPatternMessage")) {\r
126                                 message = $this.data("validationPatternMessage");\r
127                             }\r
128                             $this.data("validationPatternMessage", message);\r
129                             $this.data("validationPatternRegex", $this.attr("pattern"));\r
130                         }\r
131                         // ---------------------------------------------------------\r
132                         //                                                       MAX\r
133                         // ---------------------------------------------------------\r
134                         if ($this.attr("max") !== undefined || $this.attr("aria-valuemax") !== undefined) {\r
135                             var max = ($this.attr("max") !== undefined ? $this.attr("max") : $this.attr("aria-valuemax"));\r
136                             message = "Too high: Maximum of '" + max + "'<!-- data-validation-max-message to override -->";\r
137                             if ($this.data("validationMaxMessage")) {\r
138                                 message = $this.data("validationMaxMessage");\r
139                             }\r
140                             $this.data("validationMaxMessage", message);\r
141                             $this.data("validationMaxMax", max);\r
142                         }\r
143                         // ---------------------------------------------------------\r
144                         //                                                       MIN\r
145                         // ---------------------------------------------------------\r
146                         if ($this.attr("min") !== undefined || $this.attr("aria-valuemin") !== undefined) {\r
147                             var min = ($this.attr("min") !== undefined ? $this.attr("min") : $this.attr("aria-valuemin"));\r
148                             message = "Too low: Minimum of '" + min + "'<!-- data-validation-min-message to override -->";\r
149                             if ($this.data("validationMinMessage")) {\r
150                                 message = $this.data("validationMinMessage");\r
151                             }\r
152                             $this.data("validationMinMessage", message);\r
153                             $this.data("validationMinMin", min);\r
154                         }\r
155                         // ---------------------------------------------------------\r
156                         //                                                 MAXLENGTH\r
157                         // ---------------------------------------------------------\r
158                         if ($this.attr("maxlength") !== undefined) {\r
159                             message = "Too long: Maximum of '" + $this.attr("maxlength") + "' characters<!-- data-validation-maxlength-message to override -->";\r
160                             if ($this.data("validationMaxlengthMessage")) {\r
161                                 message = $this.data("validationMaxlengthMessage");\r
162                             }\r
163                             $this.data("validationMaxlengthMessage", message);\r
164                             $this.data("validationMaxlengthMaxlength", $this.attr("maxlength"));\r
165                         }\r
166                         // ---------------------------------------------------------\r
167                         //                                                 MINLENGTH\r
168                         // ---------------------------------------------------------\r
169                         if ($this.attr("minlength") !== undefined) {\r
170                             message = "Too short: Minimum of '" + $this.attr("minlength") + "' characters<!-- data-validation-minlength-message to override -->";\r
171                             if ($this.data("validationMinlengthMessage")) {\r
172                                 message = $this.data("validationMinlengthMessage");\r
173                             }\r
174                             $this.data("validationMinlengthMessage", message);\r
175                             $this.data("validationMinlengthMinlength", $this.attr("minlength"));\r
176                         }\r
177                         // ---------------------------------------------------------\r
178                         //                                                  REQUIRED\r
179                         // ---------------------------------------------------------\r
180                         if ($this.attr("required") !== undefined || $this.attr("aria-required") !== undefined) {\r
181                             message = settings.builtInValidators.required.message;\r
182                             if ($this.data("validationRequiredMessage")) {\r
183                                 message = $this.data("validationRequiredMessage");\r
184                             }\r
185                             $this.data("validationRequiredMessage", message);\r
186                         }\r
187                         // ---------------------------------------------------------\r
188                         //                                                    NUMBER\r
189                         // ---------------------------------------------------------\r
190                         if ($this.attr("type") !== undefined && $this.attr("type").toLowerCase() === "number") {\r
191                             message = settings.builtInValidators.number.message;\r
192                             if ($this.data("validationNumberMessage")) {\r
193                                 message = $this.data("validationNumberMessage");\r
194                             }\r
195                             $this.data("validationNumberMessage", message);\r
196                         }\r
197                         // ---------------------------------------------------------\r
198                         //                                                     EMAIL\r
199                         // ---------------------------------------------------------\r
200                         if ($this.attr("type") !== undefined && $this.attr("type").toLowerCase() === "email") {\r
201                             message = "Not a valid email address<!-- data-validator-validemail-message to override -->";\r
202                             if ($this.data("validationValidemailMessage")) {\r
203                                 message = $this.data("validationValidemailMessage");\r
204                             } else if ($this.data("validationEmailMessage")) {\r
205                                 message = $this.data("validationEmailMessage");\r
206                             }\r
207                             $this.data("validationValidemailMessage", message);\r
208                         }\r
209                         // ---------------------------------------------------------\r
210                         //                                                MINCHECKED\r
211                         // ---------------------------------------------------------\r
212                         if ($this.attr("minchecked") !== undefined) {\r
213                             message = "Not enough options checked; Minimum of '" + $this.attr("minchecked") + "' required<!-- data-validation-minchecked-message to override -->";\r
214                             if ($this.data("validationMincheckedMessage")) {\r
215                                 message = $this.data("validationMincheckedMessage");\r
216                             }\r
217                             $this.data("validationMincheckedMessage", message);\r
218                             $this.data("validationMincheckedMinchecked", $this.attr("minchecked"));\r
219                         }\r
220                         // ---------------------------------------------------------\r
221                         //                                                MAXCHECKED\r
222                         // ---------------------------------------------------------\r
223                         if ($this.attr("maxchecked") !== undefined) {\r
224                             message = "Too many options checked; Maximum of '" + $this.attr("maxchecked") + "' required<!-- data-validation-maxchecked-message to override -->";\r
225                             if ($this.data("validationMaxcheckedMessage")) {\r
226                                 message = $this.data("validationMaxcheckedMessage");\r
227                             }\r
228                             $this.data("validationMaxcheckedMessage", message);\r
229                             $this.data("validationMaxcheckedMaxchecked", $this.attr("maxchecked"));\r
230                         }\r
231                     }\r
232 \r
233                     // =============================================================\r
234                     //                                       COLLECT VALIDATOR NAMES\r
235                     // =============================================================\r
236 \r
237                     // Get named validators\r
238                     if ($this.data("validation") !== undefined) {\r
239                         validatorNames = $this.data("validation").split(",");\r
240                     }\r
241 \r
242                     // Get extra ones defined on the element's data attributes\r
243                     $.each($this.data(), function (i, el) {\r
244                         var parts = i.replace(/([A-Z])/g, ",$1").split(",");\r
245                         if (parts[0] === "validation" && parts[1]) {\r
246                             validatorNames.push(parts[1]);\r
247                         }\r
248                     });\r
249 \r
250                     // =============================================================\r
251                     //                                     NORMALISE VALIDATOR NAMES\r
252                     // =============================================================\r
253 \r
254                     var validatorNamesToInspect = validatorNames;\r
255                     var newValidatorNamesToInspect = [];\r
256 \r
257                     do // repeatedly expand 'shortcut' validators into their real validators\r
258                     {\r
259                         // Uppercase only the first letter of each name\r
260                         $.each(validatorNames, function (i, el) {\r
261                             validatorNames[i] = formatValidatorName(el);\r
262                         });\r
263 \r
264                         // Remove duplicate validator names\r
265                         validatorNames = $.unique(validatorNames);\r
266 \r
267                         // Pull out the new validator names from each shortcut\r
268                         newValidatorNamesToInspect = [];\r
269                         $.each(validatorNamesToInspect, function (i, el) {\r
270                             if ($this.data("validation" + el + "Shortcut") !== undefined) {\r
271                                 // Are these custom validators?\r
272                                 // Pull them out!\r
273                                 $.each($this.data("validation" + el + "Shortcut").split(","), function (i2, el2) {\r
274                                     newValidatorNamesToInspect.push(el2);\r
275                                 });\r
276                             } else if (settings.builtInValidators[el.toLowerCase()]) {\r
277                                 // Is this a recognised built-in?\r
278                                 // Pull it out!\r
279                                 var validator = settings.builtInValidators[el.toLowerCase()];\r
280                                 if (validator.type.toLowerCase() === "shortcut") {\r
281                                     $.each(validator.shortcut.split(","), function (i, el) {\r
282                                         el = formatValidatorName(el);\r
283                                         newValidatorNamesToInspect.push(el);\r
284                                         validatorNames.push(el);\r
285                                     });\r
286                                 }\r
287                             }\r
288                         });\r
289 \r
290                         validatorNamesToInspect = newValidatorNamesToInspect;\r
291 \r
292                     } while (validatorNamesToInspect.length > 0)\r
293 \r
294                     // =============================================================\r
295                     //                                       SET UP VALIDATOR ARRAYS\r
296                     // =============================================================\r
297 \r
298                     var validators = {};\r
299 \r
300                     $.each(validatorNames, function (i, el) {\r
301                         // Set up the 'override' message\r
302                         var message = $this.data("validation" + el + "Message");\r
303                         var hasOverrideMessage = (message !== undefined);\r
304                         var foundValidator = false;\r
305                         message =\r
306                             (\r
307                                 message\r
308                                     ? message\r
309                                     : "'" + el + "' validation failed <!-- Add attribute 'data-validation-" + el.toLowerCase() + "-message' to input to change this message -->"\r
310                             )\r
311                         ;\r
312 \r
313                         $.each(\r
314                             settings.validatorTypes,\r
315                             function (validatorType, validatorTemplate) {\r
316                                 if (validators[validatorType] === undefined) {\r
317                                     validators[validatorType] = [];\r
318                                 }\r
319                                 if (!foundValidator && $this.data("validation" + el + formatValidatorName(validatorTemplate.name)) !== undefined) {\r
320                                     validators[validatorType].push(\r
321                                         $.extend(\r
322                                             true,\r
323                                             {\r
324                                                 name: formatValidatorName(validatorTemplate.name),\r
325                                                 message: message\r
326                                             },\r
327                                             validatorTemplate.init($this, el)\r
328                                         )\r
329                                     );\r
330                                     foundValidator = true;\r
331                                 }\r
332                             }\r
333                         );\r
334 \r
335                         if (!foundValidator && settings.builtInValidators[el.toLowerCase()]) {\r
336 \r
337                             var validator = $.extend(true, {}, settings.builtInValidators[el.toLowerCase()]);\r
338                             if (hasOverrideMessage) {\r
339                                 validator.message = message;\r
340                             }\r
341                             var validatorType = validator.type.toLowerCase();\r
342 \r
343                             if (validatorType === "shortcut") {\r
344                                 foundValidator = true;\r
345                             } else {\r
346                                 $.each(\r
347                                     settings.validatorTypes,\r
348                                     function (validatorTemplateType, validatorTemplate) {\r
349                                         if (validators[validatorTemplateType] === undefined) {\r
350                                             validators[validatorTemplateType] = [];\r
351                                         }\r
352                                         if (!foundValidator && validatorType === validatorTemplateType.toLowerCase()) {\r
353                                             $this.data("validation" + el + formatValidatorName(validatorTemplate.name), validator[validatorTemplate.name.toLowerCase()]);\r
354                                             validators[validatorType].push(\r
355                                                 $.extend(\r
356                                                     validator,\r
357                                                     validatorTemplate.init($this, el)\r
358                                                 )\r
359                                             );\r
360                                             foundValidator = true;\r
361                                         }\r
362                                     }\r
363                                 );\r
364                             }\r
365                         }\r
366 \r
367                         if (!foundValidator) {\r
368                             $.error("Cannot find validation info for '" + el + "'");\r
369                         }\r
370                     });\r
371 \r
372                     // =============================================================\r
373                     //                                         STORE FALLBACK VALUES\r
374                     // =============================================================\r
375 \r
376                     $helpBlock.data(\r
377                         "original-contents",\r
378                         (\r
379                             $helpBlock.data("original-contents")\r
380                                 ? $helpBlock.data("original-contents")\r
381                                 : $helpBlock.html()\r
382                         )\r
383                     );\r
384 \r
385                     $helpBlock.data(\r
386                         "original-role",\r
387                         (\r
388                             $helpBlock.data("original-role")\r
389                                 ? $helpBlock.data("original-role")\r
390                                 : $helpBlock.attr("role")\r
391                         )\r
392                     );\r
393 \r
394                     $controlGroup.data(\r
395                         "original-classes",\r
396                         (\r
397                             $controlGroup.data("original-clases")\r
398                                 ? $controlGroup.data("original-classes")\r
399                                 : $controlGroup.attr("class")\r
400                         )\r
401                     );\r
402 \r
403                     $this.data(\r
404                         "original-aria-invalid",\r
405                         (\r
406                             $this.data("original-aria-invalid")\r
407                                 ? $this.data("original-aria-invalid")\r
408                                 : $this.attr("aria-invalid")\r
409                         )\r
410                     );\r
411 \r
412                     // =============================================================\r
413                     //                                                    VALIDATION\r
414                     // =============================================================\r
415 \r
416                     $this.bind(\r
417                         "validation.validation",\r
418                         function (event, params) {\r
419 \r
420                             var value = getValue($this);\r
421 \r
422                             // Get a list of the errors to apply\r
423                             var errorsFound = [];\r
424 \r
425                             $.each(validators, function (validatorType, validatorTypeArray) {\r
426                                 if (value || value.length || (params && params.includeEmpty) || (!!settings.validatorTypes[validatorType].blockSubmit && params && !!params.submitting)) {\r
427                                     $.each(validatorTypeArray, function (i, validator) {\r
428                                         if (settings.validatorTypes[validatorType].validate($this, value, validator)) {\r
429                                             errorsFound.push(validator.message);\r
430                                         }\r
431                                     });\r
432                                 }\r
433                             });\r
434 \r
435                             return errorsFound;\r
436                         }\r
437                     );\r
438 \r
439                     $this.bind(\r
440                         "getValidators.validation",\r
441                         function () {\r
442                             return validators;\r
443                         }\r
444                     );\r
445 \r
446                     // =============================================================\r
447                     //                                             WATCH FOR CHANGES\r
448                     // =============================================================\r
449                     $this.bind(\r
450                         "submit.validation",\r
451                         function () {\r
452                             return $this.triggerHandler("change.validation", {submitting: true});\r
453                         }\r
454                     );\r
455                     $this.bind(\r
456                         [\r
457                             "keyup",\r
458                             "focus",\r
459                             "blur",\r
460                             "click",\r
461                             "keydown",\r
462                             "keypress",\r
463                             "change"\r
464                         ].join(".validation ") + ".validation",\r
465                         function (e, params) {\r
466 \r
467                             var value = getValue($this);\r
468 \r
469                             var errorsFound = [];\r
470 \r
471                             $controlGroup.find("input,textarea,select").each(function (i, el) {\r
472                                 var oldCount = errorsFound.length;\r
473                                 $.each($(el).triggerHandler("validation.validation", params), function (j, message) {\r
474                                     errorsFound.push(message);\r
475                                 });\r
476                                 if (errorsFound.length > oldCount) {\r
477                                     $(el).attr("aria-invalid", "true");\r
478                                 } else {\r
479                                     var original = $this.data("original-aria-invalid");\r
480                                     $(el).attr("aria-invalid", (original !== undefined ? original : false));\r
481                                 }\r
482                             });\r
483 \r
484                             $form.find("input,select,textarea").not($this).not("[name=\"" + $this.attr("name") + "\"]").trigger("validationLostFocus.validation");\r
485 \r
486                             errorsFound = $.unique(errorsFound.sort());\r
487 \r
488                             // Were there any errors?\r
489                             if (errorsFound.length) {\r
490                                 // Better flag it up as a warning.\r
491                                 $controlGroup.removeClass("success error").addClass("warning");\r
492 \r
493                                 // How many errors did we find?\r
494                                 if (settings.options.semanticallyStrict && errorsFound.length === 1) {\r
495                                     // Only one? Being strict? Just output it.\r
496                                     $helpBlock.html(errorsFound[0] +\r
497                                         ( settings.options.prependExistingHelpBlock ? $helpBlock.data("original-contents") : "" ));\r
498                                 } else {\r
499                                     // Multiple? Being sloppy? Glue them together into an UL.\r
500                                     $helpBlock.html("<ul role=\"alert\"><li>" + errorsFound.join("</li><li>") + "</li></ul>" +\r
501                                         ( settings.options.prependExistingHelpBlock ? $helpBlock.data("original-contents") : "" ));\r
502                                 }\r
503                             } else {\r
504                                 $controlGroup.removeClass("warning error success");\r
505                                 if (value.length > 0) {\r
506                                     $controlGroup.addClass("success");\r
507                                 }\r
508                                 $helpBlock.html($helpBlock.data("original-contents"));\r
509                             }\r
510 \r
511                             if (e.type === "blur") {\r
512                                 $controlGroup.removeClass("success");\r
513                             }\r
514                         }\r
515                     );\r
516                     $this.bind("validationLostFocus.validation", function () {\r
517                         $controlGroup.removeClass("success");\r
518                     });\r
519                 });\r
520             },\r
521             destroy: function () {\r
522 \r
523                 return this.each(\r
524                     function () {\r
525 \r
526                         var\r
527                             $this = $(this),\r
528                             $controlGroup = $this.parents(".control-group").first(),\r
529                             $helpBlock = $controlGroup.find(".help-block").first();\r
530 \r
531                         // remove our events\r
532                         $this.unbind('.validation'); // events are namespaced.\r
533                         // reset help text\r
534                         $helpBlock.html($helpBlock.data("original-contents"));\r
535                         // reset classes\r
536                         $controlGroup.attr("class", $controlGroup.data("original-classes"));\r
537                         // reset aria\r
538                         $this.attr("aria-invalid", $this.data("original-aria-invalid"));\r
539                         // reset role\r
540                         $helpBlock.attr("role", $this.data("original-role"));\r
541                         // remove all elements we created\r
542                         if (createdElements.indexOf($helpBlock[0]) > -1) {\r
543                             $helpBlock.remove();\r
544                         }\r
545 \r
546                     }\r
547                 );\r
548 \r
549             },\r
550             collectErrors: function (includeEmpty) {\r
551 \r
552                 var errorMessages = {};\r
553                 this.each(function (i, el) {\r
554                     var $el = $(el);\r
555                     var name = $el.attr("name");\r
556                     var errors = $el.triggerHandler("validation.validation", {includeEmpty: true});\r
557                     errorMessages[name] = $.extend(true, errors, errorMessages[name]);\r
558                 });\r
559 \r
560                 $.each(errorMessages, function (i, el) {\r
561                     if (el.length === 0) {\r
562                         delete errorMessages[i];\r
563                     }\r
564                 });\r
565 \r
566                 return errorMessages;\r
567 \r
568             },\r
569             hasErrors: function () {\r
570 \r
571                 var errorMessages = [];\r
572 \r
573                 this.each(function (i, el) {\r
574                     errorMessages = errorMessages.concat(\r
575                         $(el).triggerHandler("getValidators.validation") ? $(el).triggerHandler("validation.validation", {submitting: true}) : []\r
576                     );\r
577                 });\r
578 \r
579                 return (errorMessages.length > 0);\r
580             },\r
581             override: function (newDefaults) {\r
582                 defaults = $.extend(true, defaults, newDefaults);\r
583             }\r
584         },\r
585         validatorTypes: {\r
586             callback: {\r
587                 name: "callback",\r
588                 init: function ($this, name) {\r
589                     return {\r
590                         validatorName: name,\r
591                         callback: $this.data("validation" + name + "Callback"),\r
592                         lastValue: $this.val(),\r
593                         lastValid: true,\r
594                         lastFinished: true\r
595                     };\r
596                 },\r
597                 validate: function ($this, value, validator) {\r
598                     if (validator.lastValue === value && validator.lastFinished) {\r
599                         return !validator.lastValid;\r
600                     }\r
601 \r
602                     if (validator.lastFinished === true) {\r
603                         validator.lastValue = value;\r
604                         validator.lastValid = true;\r
605                         validator.lastFinished = false;\r
606 \r
607                         var rrjqbvValidator = validator;\r
608                         var rrjqbvThis = $this;\r
609                         executeFunctionByName(\r
610                             validator.callback,\r
611                             window,\r
612                             $this,\r
613                             value,\r
614                             function (data) {\r
615                                 if (rrjqbvValidator.lastValue === data.value) {\r
616                                     rrjqbvValidator.lastValid = data.valid;\r
617                                     if (data.message) {\r
618                                         rrjqbvValidator.message = data.message;\r
619                                     }\r
620                                     rrjqbvValidator.lastFinished = true;\r
621                                     rrjqbvThis.data("validation" + rrjqbvValidator.validatorName + "Message", rrjqbvValidator.message);\r
622                                     // Timeout is set to avoid problems with the events being considered 'already fired'\r
623                                     setTimeout(function () {\r
624                                         rrjqbvThis.trigger("change.validation");\r
625                                     }, 1); // doesn't need a long timeout, just long enough for the event bubble to burst\r
626                                 }\r
627                             }\r
628                         );\r
629                     }\r
630 \r
631                     return false;\r
632 \r
633                 }\r
634             },\r
635             ajax: {\r
636                 name: "ajax",\r
637                 init: function ($this, name) {\r
638                     return {\r
639                         validatorName: name,\r
640                         url: $this.data("validation" + name + "Ajax"),\r
641                         lastValue: $this.val(),\r
642                         lastValid: true,\r
643                         lastFinished: true\r
644                     };\r
645                 },\r
646                 validate: function ($this, value, validator) {\r
647                     if ("" + validator.lastValue === "" + value && validator.lastFinished === true) {\r
648                         return validator.lastValid === false;\r
649                     }\r
650 \r
651                     if (validator.lastFinished === true) {\r
652                         validator.lastValue = value;\r
653                         validator.lastValid = true;\r
654                         validator.lastFinished = false;\r
655                         $.ajax({\r
656                             url: validator.url,\r
657                             data: "value=" + value + "&field=" + $this.attr("name"),\r
658                             dataType: "json",\r
659                             success: function (data) {\r
660                                 if ("" + validator.lastValue === "" + data.value) {\r
661                                     validator.lastValid = !!(data.valid);\r
662                                     if (data.message) {\r
663                                         validator.message = data.message;\r
664                                     }\r
665                                     validator.lastFinished = true;\r
666                                     $this.data("validation" + validator.validatorName + "Message", validator.message);\r
667                                     // Timeout is set to avoid problems with the events being considered 'already fired'\r
668                                     setTimeout(function () {\r
669                                         $this.trigger("change.validation");\r
670                                     }, 1); // doesn't need a long timeout, just long enough for the event bubble to burst\r
671                                 }\r
672                             },\r
673                             failure: function () {\r
674                                 validator.lastValid = true;\r
675                                 validator.message = "ajax call failed";\r
676                                 validator.lastFinished = true;\r
677                                 $this.data("validation" + validator.validatorName + "Message", validator.message);\r
678                                 // Timeout is set to avoid problems with the events being considered 'already fired'\r
679                                 setTimeout(function () {\r
680                                     $this.trigger("change.validation");\r
681                                 }, 1); // doesn't need a long timeout, just long enough for the event bubble to burst\r
682                             }\r
683                         });\r
684                     }\r
685 \r
686                     return false;\r
687 \r
688                 }\r
689             },\r
690             regex: {\r
691                 name: "regex",\r
692                 init: function ($this, name) {\r
693                     return {regex: regexFromString($this.data("validation" + name + "Regex"))};\r
694                 },\r
695                 validate: function ($this, value, validator) {\r
696                     return (!validator.regex.test(value) && !validator.negative)\r
697                         || (validator.regex.test(value) && validator.negative);\r
698                 }\r
699             },\r
700             required: {\r
701                 name: "required",\r
702                 init: function ($this, name) {\r
703                     return {};\r
704                 },\r
705                 validate: function ($this, value, validator) {\r
706                     return !!(value.length === 0 && !validator.negative)\r
707                         || !!(value.length > 0 && validator.negative);\r
708                 },\r
709                 blockSubmit: true\r
710             },\r
711             match: {\r
712                 name: "match",\r
713                 init: function ($this, name) {\r
714                     var element = $this.parents("form").first().find("[name=\"" + $this.data("validation" + name + "Match") + "\"]").first();\r
715                     element.bind("validation.validation", function () {\r
716                         $this.trigger("change.validation", {submitting: true});\r
717                     });\r
718                     return {"element": element};\r
719                 },\r
720                 validate: function ($this, value, validator) {\r
721                     return (value !== validator.element.val() && !validator.negative)\r
722                         || (value === validator.element.val() && validator.negative);\r
723                 },\r
724                 blockSubmit: true\r
725             },\r
726             max: {\r
727                 name: "max",\r
728                 init: function ($this, name) {\r
729                     return {max: $this.data("validation" + name + "Max")};\r
730                 },\r
731                 validate: function ($this, value, validator) {\r
732                     return (parseFloat(value, 10) > parseFloat(validator.max, 10) && !validator.negative)\r
733                         || (parseFloat(value, 10) <= parseFloat(validator.max, 10) && validator.negative);\r
734                 }\r
735             },\r
736             min: {\r
737                 name: "min",\r
738                 init: function ($this, name) {\r
739                     return {min: $this.data("validation" + name + "Min")};\r
740                 },\r
741                 validate: function ($this, value, validator) {\r
742                     return (parseFloat(value) < parseFloat(validator.min) && !validator.negative)\r
743                         || (parseFloat(value) >= parseFloat(validator.min) && validator.negative);\r
744                 }\r
745             },\r
746             maxlength: {\r
747                 name: "maxlength",\r
748                 init: function ($this, name) {\r
749                     return {maxlength: $this.data("validation" + name + "Maxlength")};\r
750                 },\r
751                 validate: function ($this, value, validator) {\r
752                     return ((value.length > validator.maxlength) && !validator.negative)\r
753                         || ((value.length <= validator.maxlength) && validator.negative);\r
754                 }\r
755             },\r
756             minlength: {\r
757                 name: "minlength",\r
758                 init: function ($this, name) {\r
759                     return {minlength: $this.data("validation" + name + "Minlength")};\r
760                 },\r
761                 validate: function ($this, value, validator) {\r
762                     return ((value.length < validator.minlength) && !validator.negative)\r
763                         || ((value.length >= validator.minlength) && validator.negative);\r
764                 }\r
765             },\r
766             maxchecked: {\r
767                 name: "maxchecked",\r
768                 init: function ($this, name) {\r
769                     var elements = $this.parents("form").first().find("[name=\"" + $this.attr("name") + "\"]");\r
770                     elements.bind("click.validation", function () {\r
771                         $this.trigger("change.validation", {includeEmpty: true});\r
772                     });\r
773                     return {maxchecked: $this.data("validation" + name + "Maxchecked"), elements: elements};\r
774                 },\r
775                 validate: function ($this, value, validator) {\r
776                     return (validator.elements.filter(":checked").length > validator.maxchecked && !validator.negative)\r
777                         || (validator.elements.filter(":checked").length <= validator.maxchecked && validator.negative);\r
778                 },\r
779                 blockSubmit: true\r
780             },\r
781             minchecked: {\r
782                 name: "minchecked",\r
783                 init: function ($this, name) {\r
784                     var elements = $this.parents("form").first().find("[name=\"" + $this.attr("name") + "\"]");\r
785                     elements.bind("click.validation", function () {\r
786                         $this.trigger("change.validation", {includeEmpty: true});\r
787                     });\r
788                     return {minchecked: $this.data("validation" + name + "Minchecked"), elements: elements};\r
789                 },\r
790                 validate: function ($this, value, validator) {\r
791                     return (validator.elements.filter(":checked").length < validator.minchecked && !validator.negative)\r
792                         || (validator.elements.filter(":checked").length >= validator.minchecked && validator.negative);\r
793                 },\r
794                 blockSubmit: true\r
795             }\r
796         },\r
797         builtInValidators: {\r
798             email: {\r
799                 name: "Email",\r
800                 type: "shortcut",\r
801                 shortcut: "validemail"\r
802             },\r
803             validemail: {\r
804                 name: "Validemail",\r
805                 type: "regex",\r
806                 regex: "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\\.[A-Za-z]{2,4}",\r
807                 message: "Not a valid email address<!-- data-validator-validemail-message to override -->"\r
808             },\r
809             passwordagain: {\r
810                 name: "Passwordagain",\r
811                 type: "match",\r
812                 match: "password",\r
813                 message: "Does not match the given password<!-- data-validator-paswordagain-message to override -->"\r
814             },\r
815             positive: {\r
816                 name: "Positive",\r
817                 type: "shortcut",\r
818                 shortcut: "number,positivenumber"\r
819             },\r
820             negative: {\r
821                 name: "Negative",\r
822                 type: "shortcut",\r
823                 shortcut: "number,negativenumber"\r
824             },\r
825             number: {\r
826                 name: "Number",\r
827                 type: "regex",\r
828                 regex: "([+-]?\\\d+(\\\.\\\d*)?([eE][+-]?[0-9]+)?)?",\r
829                 message: "Must be a number<!-- data-validator-number-message to override -->"\r
830             },\r
831             integer: {\r
832                 name: "Integer",\r
833                 type: "regex",\r
834                 regex: "[+-]?\\\d+",\r
835                 message: "No decimal places allowed<!-- data-validator-integer-message to override -->"\r
836             },\r
837             positivenumber: {\r
838                 name: "Positivenumber",\r
839                 type: "min",\r
840                 min: 0,\r
841                 message: "Must be a positive number<!-- data-validator-positivenumber-message to override -->"\r
842             },\r
843             negativenumber: {\r
844                 name: "Negativenumber",\r
845                 type: "max",\r
846                 max: 0,\r
847                 message: "Must be a negative number<!-- data-validator-negativenumber-message to override -->"\r
848             },\r
849             required: {\r
850                 name: "Required",\r
851                 type: "required",\r
852                 message: "This is required<!-- data-validator-required-message to override -->"\r
853             },\r
854             checkone: {\r
855                 name: "Checkone",\r
856                 type: "minchecked",\r
857                 minchecked: 1,\r
858                 message: "Check at least one option<!-- data-validation-checkone-message to override -->"\r
859             }\r
860         }\r
861     };\r
862 \r
863     var formatValidatorName = function (name) {\r
864         return name\r
865             .toLowerCase()\r
866             .replace(\r
867                 /(^|\s)([a-z])/g,\r
868                 function (m, p1, p2) {\r
869                     return p1 + p2.toUpperCase();\r
870                 }\r
871             )\r
872             ;\r
873     };\r
874 \r
875     var getValue = function ($this) {\r
876         // Extract the value we're talking about\r
877         var value = $this.val();\r
878         var type = $this.attr("type");\r
879         if (type === "checkbox") {\r
880             value = ($this.is(":checked") ? value : "");\r
881         }\r
882         if (type === "radio") {\r
883             value = ($('input[name="' + $this.attr("name") + '"]:checked').length > 0 ? value : "");\r
884         }\r
885         return value;\r
886     };\r
887 \r
888     function regexFromString(inputstring) {\r
889         return new RegExp("^" + inputstring + "$");\r
890     }\r
891 \r
892     /**\r
893      * Thanks to Jason Bunting via StackOverflow.com\r
894      *\r
895      * http://stackoverflow.com/questions/359788/how-to-execute-a-javascript-function-when-i-have-its-name-as-a-string#answer-359910\r
896      * Short link: http://tinyurl.com/executeFunctionByName\r
897      **/\r
898     function executeFunctionByName(functionName, context /*, args*/) {\r
899         var args = Array.prototype.slice.call(arguments).splice(2);\r
900         var namespaces = functionName.split(".");\r
901         var func = namespaces.pop();\r
902         for (var i = 0; i < namespaces.length; i++) {\r
903             context = context[namespaces[i]];\r
904         }\r
905         return context[func].apply(this, args);\r
906     }\r
907 \r
908     $.fn.jqBootstrapValidation = function (method) {\r
909 \r
910         if (defaults.methods[method]) {\r
911             return defaults.methods[method].apply(this, Array.prototype.slice.call(arguments, 1));\r
912         } else if (typeof method === 'object' || !method) {\r
913             return defaults.methods.init.apply(this, arguments);\r
914         } else {\r
915             $.error('Method ' + method + ' does not exist on jQuery.jqBootstrapValidation');\r
916             return null;\r
917         }\r
918 \r
919     };\r
920 \r
921     $.jqBootstrapValidation = function (options) {\r
922         $(":input").not("[type=image],[type=submit]").jqBootstrapValidation.apply(this, arguments);\r
923     };\r
924 \r
925 })(jQuery);\r