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