2 * Copyright 2016-2017 ZTE Corporation.
\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
8 * http://www.apache.org/licenses/LICENSE-2.0
\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
16 /* jqBootstrapValidation
\r
17 * A plugin for automating validation on Twitter Bootstrap formatted forms.
\r
21 * License: MIT <http://opensource.org/licenses/mit-license.php> - see LICENSE file
\r
23 * http://ReactiveRaven.github.com/jqBootstrapValidation/
\r
28 var createdElements = [];
\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
41 filter: function () {
\r
42 // return $(this).is(":visible"); // only validate elements you can see
\r
43 return true; // validate everything
\r
47 init: function (options) {
\r
49 var settings = $.extend(true, {}, defaults);
\r
51 settings.options = $.extend(true, settings.options, options);
\r
53 var $siblingElements = this;
\r
55 var uniqueForms = $.unique(
\r
56 $siblingElements.map(function () {
\r
57 return $(this).parents("form")[0];
\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
67 $inputs.each(function (i, el) {
\r
69 $controlGroup = $this.parents(".control-group").first();
\r
71 $controlGroup.hasClass("warning")
\r
73 $controlGroup.removeClass("warning").addClass("error");
\r
78 $inputs.trigger("validationLostFocus.validation");
\r
80 if (warningsFound) {
\r
81 if (settings.options.preventSubmit) {
\r
84 $form.addClass("error");
\r
85 if ($.isFunction(settings.options.submitError)) {
\r
86 settings.options.submitError($form, e, $inputs.jqBootstrapValidation("collectErrors", true));
\r
89 $form.removeClass("error");
\r
90 if ($.isFunction(settings.options.submitSuccess)) {
\r
91 settings.options.submitSuccess($form, e);
\r
96 return this.each(function () {
\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
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
112 // =============================================================
\r
113 // SNIFF HTML FOR VALIDATORS
\r
114 // =============================================================
\r
116 // *snort sniff snuffle*
\r
118 if (settings.options.sniffHtml) {
\r
120 // ---------------------------------------------------------
\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
128 $this.data("validationPatternMessage", message);
\r
129 $this.data("validationPatternRegex", $this.attr("pattern"));
\r
131 // ---------------------------------------------------------
\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
140 $this.data("validationMaxMessage", message);
\r
141 $this.data("validationMaxMax", max);
\r
143 // ---------------------------------------------------------
\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
152 $this.data("validationMinMessage", message);
\r
153 $this.data("validationMinMin", min);
\r
155 // ---------------------------------------------------------
\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
163 $this.data("validationMaxlengthMessage", message);
\r
164 $this.data("validationMaxlengthMaxlength", $this.attr("maxlength"));
\r
166 // ---------------------------------------------------------
\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
174 $this.data("validationMinlengthMessage", message);
\r
175 $this.data("validationMinlengthMinlength", $this.attr("minlength"));
\r
177 // ---------------------------------------------------------
\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
185 $this.data("validationRequiredMessage", message);
\r
187 // ---------------------------------------------------------
\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
195 $this.data("validationNumberMessage", message);
\r
197 // ---------------------------------------------------------
\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
207 $this.data("validationValidemailMessage", message);
\r
209 // ---------------------------------------------------------
\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
217 $this.data("validationMincheckedMessage", message);
\r
218 $this.data("validationMincheckedMinchecked", $this.attr("minchecked"));
\r
220 // ---------------------------------------------------------
\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
228 $this.data("validationMaxcheckedMessage", message);
\r
229 $this.data("validationMaxcheckedMaxchecked", $this.attr("maxchecked"));
\r
233 // =============================================================
\r
234 // COLLECT VALIDATOR NAMES
\r
235 // =============================================================
\r
237 // Get named validators
\r
238 if ($this.data("validation") !== undefined) {
\r
239 validatorNames = $this.data("validation").split(",");
\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
250 // =============================================================
\r
251 // NORMALISE VALIDATOR NAMES
\r
252 // =============================================================
\r
254 var validatorNamesToInspect = validatorNames;
\r
255 var newValidatorNamesToInspect = [];
\r
257 do // repeatedly expand 'shortcut' validators into their real validators
\r
259 // Uppercase only the first letter of each name
\r
260 $.each(validatorNames, function (i, el) {
\r
261 validatorNames[i] = formatValidatorName(el);
\r
264 // Remove duplicate validator names
\r
265 validatorNames = $.unique(validatorNames);
\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
273 $.each($this.data("validation" + el + "Shortcut").split(","), function (i2, el2) {
\r
274 newValidatorNamesToInspect.push(el2);
\r
276 } else if (settings.builtInValidators[el.toLowerCase()]) {
\r
277 // Is this a recognised built-in?
\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
290 validatorNamesToInspect = newValidatorNamesToInspect;
\r
292 } while (validatorNamesToInspect.length > 0)
\r
294 // =============================================================
\r
295 // SET UP VALIDATOR ARRAYS
\r
296 // =============================================================
\r
298 var validators = {};
\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
309 : "'" + el + "' validation failed <!-- Add attribute 'data-validation-" + el.toLowerCase() + "-message' to input to change this message -->"
\r
314 settings.validatorTypes,
\r
315 function (validatorType, validatorTemplate) {
\r
316 if (validators[validatorType] === undefined) {
\r
317 validators[validatorType] = [];
\r
319 if (!foundValidator && $this.data("validation" + el + formatValidatorName(validatorTemplate.name)) !== undefined) {
\r
320 validators[validatorType].push(
\r
324 name: formatValidatorName(validatorTemplate.name),
\r
327 validatorTemplate.init($this, el)
\r
330 foundValidator = true;
\r
335 if (!foundValidator && settings.builtInValidators[el.toLowerCase()]) {
\r
337 var validator = $.extend(true, {}, settings.builtInValidators[el.toLowerCase()]);
\r
338 if (hasOverrideMessage) {
\r
339 validator.message = message;
\r
341 var validatorType = validator.type.toLowerCase();
\r
343 if (validatorType === "shortcut") {
\r
344 foundValidator = true;
\r
347 settings.validatorTypes,
\r
348 function (validatorTemplateType, validatorTemplate) {
\r
349 if (validators[validatorTemplateType] === undefined) {
\r
350 validators[validatorTemplateType] = [];
\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
357 validatorTemplate.init($this, el)
\r
360 foundValidator = true;
\r
367 if (!foundValidator) {
\r
368 $.error("Cannot find validation info for '" + el + "'");
\r
372 // =============================================================
\r
373 // STORE FALLBACK VALUES
\r
374 // =============================================================
\r
377 "original-contents",
\r
379 $helpBlock.data("original-contents")
\r
380 ? $helpBlock.data("original-contents")
\r
381 : $helpBlock.html()
\r
388 $helpBlock.data("original-role")
\r
389 ? $helpBlock.data("original-role")
\r
390 : $helpBlock.attr("role")
\r
394 $controlGroup.data(
\r
395 "original-classes",
\r
397 $controlGroup.data("original-clases")
\r
398 ? $controlGroup.data("original-classes")
\r
399 : $controlGroup.attr("class")
\r
404 "original-aria-invalid",
\r
406 $this.data("original-aria-invalid")
\r
407 ? $this.data("original-aria-invalid")
\r
408 : $this.attr("aria-invalid")
\r
412 // =============================================================
\r
414 // =============================================================
\r
417 "validation.validation",
\r
418 function (event, params) {
\r
420 var value = getValue($this);
\r
422 // Get a list of the errors to apply
\r
423 var errorsFound = [];
\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
435 return errorsFound;
\r
440 "getValidators.validation",
\r
446 // =============================================================
\r
447 // WATCH FOR CHANGES
\r
448 // =============================================================
\r
450 "submit.validation",
\r
452 return $this.triggerHandler("change.validation", {submitting: true});
\r
464 ].join(".validation ") + ".validation",
\r
465 function (e, params) {
\r
467 var value = getValue($this);
\r
469 var errorsFound = [];
\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
476 if (errorsFound.length > oldCount) {
\r
477 $(el).attr("aria-invalid", "true");
\r
479 var original = $this.data("original-aria-invalid");
\r
480 $(el).attr("aria-invalid", (original !== undefined ? original : false));
\r
484 $form.find("input,select,textarea").not($this).not("[name=\"" + $this.attr("name") + "\"]").trigger("validationLostFocus.validation");
\r
486 errorsFound = $.unique(errorsFound.sort());
\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
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
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
504 $controlGroup.removeClass("warning error success");
\r
505 if (value.length > 0) {
\r
506 $controlGroup.addClass("success");
\r
508 $helpBlock.html($helpBlock.data("original-contents"));
\r
511 if (e.type === "blur") {
\r
512 $controlGroup.removeClass("success");
\r
516 $this.bind("validationLostFocus.validation", function () {
\r
517 $controlGroup.removeClass("success");
\r
521 destroy: function () {
\r
528 $controlGroup = $this.parents(".control-group").first(),
\r
529 $helpBlock = $controlGroup.find(".help-block").first();
\r
531 // remove our events
\r
532 $this.unbind('.validation'); // events are namespaced.
\r
534 $helpBlock.html($helpBlock.data("original-contents"));
\r
536 $controlGroup.attr("class", $controlGroup.data("original-classes"));
\r
538 $this.attr("aria-invalid", $this.data("original-aria-invalid"));
\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
550 collectErrors: function (includeEmpty) {
\r
552 var errorMessages = {};
\r
553 this.each(function (i, 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
560 $.each(errorMessages, function (i, el) {
\r
561 if (el.length === 0) {
\r
562 delete errorMessages[i];
\r
566 return errorMessages;
\r
569 hasErrors: function () {
\r
571 var errorMessages = [];
\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
579 return (errorMessages.length > 0);
\r
581 override: function (newDefaults) {
\r
582 defaults = $.extend(true, defaults, newDefaults);
\r
588 init: function ($this, name) {
\r
590 validatorName: name,
\r
591 callback: $this.data("validation" + name + "Callback"),
\r
592 lastValue: $this.val(),
\r
597 validate: function ($this, value, validator) {
\r
598 if (validator.lastValue === value && validator.lastFinished) {
\r
599 return !validator.lastValid;
\r
602 if (validator.lastFinished === true) {
\r
603 validator.lastValue = value;
\r
604 validator.lastValid = true;
\r
605 validator.lastFinished = false;
\r
607 var rrjqbvValidator = validator;
\r
608 var rrjqbvThis = $this;
\r
609 executeFunctionByName(
\r
610 validator.callback,
\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
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
637 init: function ($this, name) {
\r
639 validatorName: name,
\r
640 url: $this.data("validation" + name + "Ajax"),
\r
641 lastValue: $this.val(),
\r
646 validate: function ($this, value, validator) {
\r
647 if ("" + validator.lastValue === "" + value && validator.lastFinished === true) {
\r
648 return validator.lastValid === false;
\r
651 if (validator.lastFinished === true) {
\r
652 validator.lastValue = value;
\r
653 validator.lastValid = true;
\r
654 validator.lastFinished = false;
\r
656 url: validator.url,
\r
657 data: "value=" + value + "&field=" + $this.attr("name"),
\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
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
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
692 init: function ($this, name) {
\r
693 return {regex: regexFromString($this.data("validation" + name + "Regex"))};
\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
702 init: function ($this, name) {
\r
705 validate: function ($this, value, validator) {
\r
706 return !!(value.length === 0 && !validator.negative)
\r
707 || !!(value.length > 0 && validator.negative);
\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
718 return {"element": element};
\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
728 init: function ($this, name) {
\r
729 return {max: $this.data("validation" + name + "Max")};
\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
738 init: function ($this, name) {
\r
739 return {min: $this.data("validation" + name + "Min")};
\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
748 init: function ($this, name) {
\r
749 return {maxlength: $this.data("validation" + name + "Maxlength")};
\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
758 init: function ($this, name) {
\r
759 return {minlength: $this.data("validation" + name + "Minlength")};
\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
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
773 return {maxchecked: $this.data("validation" + name + "Maxchecked"), elements: elements};
\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
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
788 return {minchecked: $this.data("validation" + name + "Minchecked"), elements: elements};
\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
797 builtInValidators: {
\r
801 shortcut: "validemail"
\r
804 name: "Validemail",
\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
810 name: "Passwordagain",
\r
813 message: "Does not match the given password<!-- data-validator-paswordagain-message to override -->"
\r
818 shortcut: "number,positivenumber"
\r
823 shortcut: "number,negativenumber"
\r
828 regex: "([+-]?\\\d+(\\\.\\\d*)?([eE][+-]?[0-9]+)?)?",
\r
829 message: "Must be a number<!-- data-validator-number-message to override -->"
\r
834 regex: "[+-]?\\\d+",
\r
835 message: "No decimal places allowed<!-- data-validator-integer-message to override -->"
\r
838 name: "Positivenumber",
\r
841 message: "Must be a positive number<!-- data-validator-positivenumber-message to override -->"
\r
844 name: "Negativenumber",
\r
847 message: "Must be a negative number<!-- data-validator-negativenumber-message to override -->"
\r
852 message: "This is required<!-- data-validator-required-message to override -->"
\r
856 type: "minchecked",
\r
858 message: "Check at least one option<!-- data-validation-checkone-message to override -->"
\r
863 var formatValidatorName = function (name) {
\r
868 function (m, p1, p2) {
\r
869 return p1 + p2.toUpperCase();
\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
882 if (type === "radio") {
\r
883 value = ($('input[name="' + $this.attr("name") + '"]:checked').length > 0 ? value : "");
\r
888 function regexFromString(inputstring) {
\r
889 return new RegExp("^" + inputstring + "$");
\r
893 * Thanks to Jason Bunting via StackOverflow.com
\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
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
905 return context[func].apply(this, args);
\r
908 $.fn.jqBootstrapValidation = function (method) {
\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
915 $.error('Method ' + method + ' does not exist on jQuery.jqBootstrapValidation');
\r
921 $.jqBootstrapValidation = function (options) {
\r
922 $(":input").not("[type=image],[type=submit]").jqBootstrapValidation.apply(this, arguments);
\r