jqBootstrapValidation 1.3.6

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