treport 1.1.1 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/app/models/connect.rb +1 -0
  3. data/app/models/db.rb +1 -1
  4. data/app/models/map.rb +1 -0
  5. data/app/models/map_requirement.rb +1 -0
  6. data/app/models/report.rb +17 -9
  7. data/app/models/requirement.rb +1 -0
  8. data/public/treport/plugins/datePicker/My97DatePicker.htm +48 -48
  9. data/public/treport/plugins/datePicker/WdatePicker.js +52 -52
  10. data/public/treport/plugins/datePicker/calendar.js +4 -4
  11. data/public/treport/plugins/datePicker/config.js +16 -16
  12. data/public/treport/plugins/datePicker/lang/en.js +13 -13
  13. data/public/treport/plugins/datePicker/lang/zh-cn.js +13 -13
  14. data/public/treport/plugins/datePicker/lang/zh-tw.js +13 -13
  15. data/public/treport/plugins/datePicker/skin/WdatePicker.css +9 -9
  16. data/public/treport/plugins/datePicker/skin/areo/datepicker.css +301 -301
  17. data/public/treport/plugins/datePicker/skin/armyGreen/datepicker.css +301 -301
  18. data/public/treport/plugins/datePicker/skin/blue/datepicker.css +114 -114
  19. data/public/treport/plugins/datePicker/skin/blueGreen/datepicker.css +301 -301
  20. data/public/treport/plugins/datePicker/skin/darkBlue/datepicker.css +308 -308
  21. data/public/treport/plugins/datePicker/skin/darkYellow/datepicker.css +114 -114
  22. data/public/treport/plugins/datePicker/skin/deepBlue/datepicker.css +300 -300
  23. data/public/treport/plugins/datePicker/skin/default/datepicker.css +245 -245
  24. data/public/treport/plugins/datePicker/skin/green/datepicker.css +114 -114
  25. data/public/treport/plugins/datePicker/skin/lightBlue/datepicker.css +114 -114
  26. data/public/treport/plugins/datePicker/skin/modernBlue/datepicker.css +301 -301
  27. data/public/treport/plugins/datePicker/skin/orange/datepicker.css +114 -114
  28. data/public/treport/plugins/datePicker/skin/red/datepicker.css +114 -114
  29. data/public/treport/plugins/datePicker/skin/whyGreen/datepicker.css +255 -255
  30. data/public/treport/plugins/datePicker/skin/yellowGreen/datepicker.css +114 -114
  31. data/public/treport/plugins/validationEngine/jquery.validationEngine-zh_CN.js +181 -181
  32. data/public/treport/plugins/validationEngine/jquery.validationEngine.js +2160 -2160
  33. data/public/treport/plugins/validationEngine/template.css +124 -124
  34. data/public/treport/plugins/validationEngine/validationEngine.jquery.css +182 -182
  35. data/public/treport/plugins/zDialog/dialog.js +1312 -1312
  36. data/public/treport/plugins/zDialog/drag.js +91 -91
  37. data/public/treport/plugins/zDialog/skins/blue/dir.txt +24 -24
  38. data/public/treport/plugins/zDialog/skins/darkBlue/dir.txt +24 -24
  39. data/public/treport/plugins/zDialog/skins/darkYellow/dir.txt +24 -24
  40. data/public/treport/plugins/zDialog/skins/green/dir.txt +24 -24
  41. data/public/treport/plugins/zDialog/skins/lightBlue/dir.txt +24 -24
  42. data/public/treport/plugins/zDialog/skins/red/dir.txt +24 -24
  43. data/public/treport/plugins/zDialog/skins/yellowGreen/dir.txt +24 -24
  44. data/public/treport/plugins/zDialog/zDialog.js +763 -763
  45. metadata +2 -2
@@ -1,2160 +1,2160 @@
1
- /*
2
- * Inline Form Validation Engine 2.6.2, jQuery plugin
3
- *
4
- * Copyright(c) 2010, Cedric Dugas
5
- * http://www.position-absolute.com
6
- *
7
- * 2.0 Rewrite by Olivier Refalo
8
- * http://www.crionics.com
9
- *
10
- * Form validation engine allowing custom regex rules to be added.
11
- * Licensed under the MIT License
12
- */
13
- (function($) {
14
-
15
- "use strict";
16
-
17
- var methods = {
18
-
19
- /**
20
- * Kind of the constructor, called before any action
21
- * @param {Map} user options
22
- */
23
- init: function(options) {
24
- var form = this;
25
- if (!form.data('jqv') || form.data('jqv') == null ) {
26
- options = methods._saveOptions(form, options);
27
- // bind all formError elements to close on click
28
- $(document).on("click", ".formError", function() {
29
- $(this).fadeOut(150, function() {
30
- // remove prompt once invisible
31
- $(this).closest('.formError').remove();
32
- });
33
- });
34
- }
35
- return this;
36
- },
37
- /**
38
- * Attachs jQuery.validationEngine to form.submit and field.blur events
39
- * Takes an optional params: a list of options
40
- * ie. jQuery("#formID1").validationEngine('attach', {promptPosition : "centerRight"});
41
- */
42
- attach: function(userOptions) {
43
-
44
- var form = this;
45
- var options;
46
-
47
- if(userOptions)
48
- options = methods._saveOptions(form, userOptions);
49
- else
50
- options = form.data('jqv');
51
-
52
- options.validateAttribute = (form.find("[data-validation-engine*=validate]").length) ? "data-validation-engine" : "class";
53
- if (options.binded) {
54
-
55
- // delegate fields
56
- form.on(options.validationEventTrigger, "["+options.validateAttribute+"*=validate]:not([type=checkbox]):not([type=radio]):not(.datepicker)", methods._onFieldEvent);
57
- form.on("click", "["+options.validateAttribute+"*=validate][type=checkbox],["+options.validateAttribute+"*=validate][type=radio]", methods._onFieldEvent);
58
- form.on(options.validationEventTrigger,"["+options.validateAttribute+"*=validate][class*=datepicker]", {"delay": 300}, methods._onFieldEvent);
59
- }
60
- if (options.autoPositionUpdate) {
61
- $(window).bind("resize", {
62
- "noAnimation": true,
63
- "formElem": form
64
- }, methods.updatePromptsPosition);
65
- }
66
- form.on("click","a[data-validation-engine-skip], a[class*='validate-skip'], button[data-validation-engine-skip], button[class*='validate-skip'], input[data-validation-engine-skip], input[class*='validate-skip']", methods._submitButtonClick);
67
- form.removeData('jqv_submitButton');
68
-
69
- // bind form.submit
70
- form.on("submit", methods._onSubmitEvent);
71
- return this;
72
- },
73
- /**
74
- * Unregisters any bindings that may point to jQuery.validaitonEngine
75
- */
76
- detach: function() {
77
-
78
- var form = this;
79
- var options = form.data('jqv');
80
-
81
- // unbind fields
82
- form.off(options.validationEventTrigger, "["+options.validateAttribute+"*=validate]:not([type=checkbox]):not([type=radio]):not(.datepicker)", methods._onFieldEvent);
83
- form.off("click", "["+options.validateAttribute+"*=validate][type=checkbox],["+options.validateAttribute+"*=validate][type=radio]", methods._onFieldEvent);
84
- form.off(options.validationEventTrigger,"["+options.validateAttribute+"*=validate][class*=datepicker]", methods._onFieldEvent);
85
-
86
- // unbind form.submit
87
- form.off("submit", methods._onSubmitEvent);
88
- form.removeData('jqv');
89
-
90
- form.off("click", "a[data-validation-engine-skip], a[class*='validate-skip'], button[data-validation-engine-skip], button[class*='validate-skip'], input[data-validation-engine-skip], input[class*='validate-skip']", methods._submitButtonClick);
91
- form.removeData('jqv_submitButton');
92
-
93
- if (options.autoPositionUpdate)
94
- $(window).off("resize", methods.updatePromptsPosition);
95
-
96
- return this;
97
- },
98
- /**
99
- * Validates either a form or a list of fields, shows prompts accordingly.
100
- * Note: There is no ajax form validation with this method, only field ajax validation are evaluated
101
- *
102
- * @return true if the form validates, false if it fails
103
- */
104
- validate: function(userOptions) {
105
- var element = $(this);
106
- var valid = null;
107
- var options;
108
-
109
- if (element.is("form") || element.hasClass("validationEngineContainer")) {
110
- if (element.hasClass('validating')) {
111
- // form is already validating.
112
- // Should abort old validation and start new one. I don't know how to implement it.
113
- return false;
114
- } else {
115
- element.addClass('validating');
116
- if(userOptions)
117
- options = methods._saveOptions(element, userOptions);
118
- else
119
- options = element.data('jqv');
120
- var valid = methods._validateFields(this);
121
-
122
- // If the form doesn't validate, clear the 'validating' class before the user has a chance to submit again
123
- setTimeout(function(){
124
- element.removeClass('validating');
125
- }, 100);
126
- if (valid && options.onSuccess) {
127
- options.onSuccess();
128
- } else if (!valid && options.onFailure) {
129
- options.onFailure();
130
- }
131
- }
132
- } else if (element.is('form') || element.hasClass('validationEngineContainer')) {
133
- element.removeClass('validating');
134
- } else {
135
- // field validation
136
- var form = element.closest('form, .validationEngineContainer');
137
- options = (form.data('jqv')) ? form.data('jqv') : $.validationEngine.defaults;
138
- valid = methods._validateField(element, options);
139
-
140
- if (valid && options.onFieldSuccess)
141
- options.onFieldSuccess();
142
- else if (options.onFieldFailure && options.InvalidFields.length > 0) {
143
- options.onFieldFailure();
144
- }
145
-
146
- return !valid;
147
- }
148
- if(options.onValidationComplete) {
149
- // !! ensures that an undefined return is interpreted as return false but allows a onValidationComplete() to possibly return true and have form continue processing
150
- return !!options.onValidationComplete(form, valid);
151
- }
152
- return valid;
153
- },
154
- /**
155
- * Redraw prompts position, useful when you change the DOM state when validating
156
- */
157
- updatePromptsPosition: function(event) {
158
-
159
- if (event && this == window) {
160
- var form = event.data.formElem;
161
- var noAnimation = event.data.noAnimation;
162
- }
163
- else
164
- var form = $(this.closest('form, .validationEngineContainer'));
165
-
166
- var options = form.data('jqv');
167
- // No option, take default one
168
- if (!options)
169
- options = methods._saveOptions(form, options);
170
- form.find('['+options.validateAttribute+'*=validate]').not(":disabled").each(function(){
171
- var field = $(this);
172
- if (options.prettySelect && field.is(":hidden"))
173
- field = form.find("#" + options.usePrefix + field.attr('id') + options.useSuffix);
174
- var prompt = methods._getPrompt(field);
175
- var promptText = $(prompt).find(".formErrorContent").html();
176
-
177
- if(prompt)
178
- methods._updatePrompt(field, $(prompt), promptText, undefined, false, options, noAnimation);
179
- });
180
- return this;
181
- },
182
- /**
183
- * Displays a prompt on a element.
184
- * Note that the element needs an id!
185
- *
186
- * @param {String} promptText html text to display type
187
- * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
188
- * @param {String} possible values topLeft, topRight, bottomLeft, centerRight, bottomRight
189
- */
190
- showPrompt: function(promptText, type, promptPosition, showArrow) {
191
- var form = this.closest('form, .validationEngineContainer');
192
- var options = form.data('jqv');
193
- // No option, take default one
194
- if(!options)
195
- options = methods._saveOptions(this, options);
196
- if(promptPosition)
197
- options.promptPosition=promptPosition;
198
- options.showArrow = showArrow==true;
199
-
200
- methods._showPrompt(this, promptText, type, false, options);
201
- return this;
202
- },
203
- /**
204
- * Closes form error prompts, CAN be invidual
205
- */
206
- hide: function() {
207
- var form = $(this).closest('form, .validationEngineContainer');
208
- var options = form.data('jqv');
209
- // No option, take default one
210
- if (!options)
211
- options = methods._saveOptions(form, options);
212
- var fadeDuration = (options && options.fadeDuration) ? options.fadeDuration : 0.3;
213
- var closingtag;
214
-
215
- if(form.is("form") || form.hasClass("validationEngineContainer")) {
216
- closingtag = "parentForm"+methods._getClassName($(form).attr("id"));
217
- } else {
218
- closingtag = methods._getClassName($(form).attr("id")) +"formError";
219
- }
220
- $('.'+closingtag).fadeTo(fadeDuration, 0, function() {
221
- $(this).closest('.formError').remove();
222
- });
223
- return this;
224
- },
225
- /**
226
- * Closes all error prompts on the page
227
- */
228
- hideAll: function() {
229
- var form = this;
230
- var options = form.data('jqv');
231
- var duration = options ? options.fadeDuration:300;
232
- $('.formError').fadeTo(duration, 0, function() {
233
- $(this).closest('.formError').remove();
234
- });
235
- return this;
236
- },
237
- /**
238
- * Typically called when user exists a field using tab or a mouse click, triggers a field
239
- * validation
240
- */
241
- _onFieldEvent: function(event) {
242
- var field = $(this);
243
- var form = field.closest('form, .validationEngineContainer');
244
- var options = form.data('jqv');
245
- // No option, take default one
246
- if (!options)
247
- options = methods._saveOptions(form, options);
248
- options.eventTrigger = "field";
249
-
250
- if (options.notEmpty == true){
251
-
252
- if(field.val().length > 0){
253
- // validate the current field
254
- window.setTimeout(function() {
255
- methods._validateField(field, options);
256
- }, (event.data) ? event.data.delay : 0);
257
-
258
- }
259
-
260
- }else{
261
-
262
- // validate the current field
263
- window.setTimeout(function() {
264
- methods._validateField(field, options);
265
- }, (event.data) ? event.data.delay : 0);
266
-
267
- }
268
-
269
-
270
-
271
-
272
- },
273
- /**
274
- * Called when the form is submited, shows prompts accordingly
275
- *
276
- * @param {jqObject}
277
- * form
278
- * @return false if form submission needs to be cancelled
279
- */
280
- _onSubmitEvent: function() {
281
- var form = $(this);
282
- var options = form.data('jqv');
283
-
284
- //check if it is trigger from skipped button
285
- if (form.data("jqv_submitButton")){
286
- var submitButton = $("#" + form.data("jqv_submitButton"));
287
- if (submitButton){
288
- if (submitButton.length > 0){
289
- if (submitButton.hasClass("validate-skip") || submitButton.attr("data-validation-engine-skip") == "true")
290
- return true;
291
- }
292
- }
293
- }
294
-
295
- options.eventTrigger = "submit";
296
-
297
- // validate each field
298
- // (- skip field ajax validation, not necessary IF we will perform an ajax form validation)
299
- var r=methods._validateFields(form);
300
-
301
- if (r && options.ajaxFormValidation) {
302
- methods._validateFormWithAjax(form, options);
303
- // cancel form auto-submission - process with async call onAjaxFormComplete
304
- return false;
305
- }
306
-
307
- if(options.onValidationComplete) {
308
- // !! ensures that an undefined return is interpreted as return false but allows a onValidationComplete() to possibly return true and have form continue processing
309
- return !!options.onValidationComplete(form, r);
310
- }
311
- return r;
312
- },
313
- /**
314
- * Return true if the ajax field validations passed so far
315
- * @param {Object} options
316
- * @return true, is all ajax validation passed so far (remember ajax is async)
317
- */
318
- _checkAjaxStatus: function(options) {
319
- var status = true;
320
- $.each(options.ajaxValidCache, function(key, value) {
321
- if (!value) {
322
- status = false;
323
- // break the each
324
- return false;
325
- }
326
- });
327
- return status;
328
- },
329
-
330
- /**
331
- * Return true if the ajax field is validated
332
- * @param {String} fieldid
333
- * @param {Object} options
334
- * @return true, if validation passed, false if false or doesn't exist
335
- */
336
- _checkAjaxFieldStatus: function(fieldid, options) {
337
- return options.ajaxValidCache[fieldid] == true;
338
- },
339
- /**
340
- * Validates form fields, shows prompts accordingly
341
- *
342
- * @param {jqObject}
343
- * form
344
- * @param {skipAjaxFieldValidation}
345
- * boolean - when set to true, ajax field validation is skipped, typically used when the submit button is clicked
346
- *
347
- * @return true if form is valid, false if not, undefined if ajax form validation is done
348
- */
349
- _validateFields: function(form) {
350
- var options = form.data('jqv');
351
-
352
- // this variable is set to true if an error is found
353
- var errorFound = false;
354
-
355
- // Trigger hook, start validation
356
- form.trigger("jqv.form.validating");
357
- // first, evaluate status of non ajax fields
358
- var first_err=null;
359
- form.find('['+options.validateAttribute+'*=validate]').not(":disabled").each( function() {
360
- var field = $(this);
361
- var names = [];
362
- if ($.inArray(field.attr('name'), names) < 0) {
363
- errorFound |= methods._validateField(field, options);
364
- if (errorFound && first_err==null)
365
- if (field.is(":hidden") && options.prettySelect)
366
- first_err = field = form.find("#" + options.usePrefix + methods._jqSelector(field.attr('id')) + options.useSuffix);
367
- else {
368
-
369
- //Check if we need to adjust what element to show the prompt on
370
- //and and such scroll to instead
371
- if(field.data('jqv-prompt-at') instanceof jQuery ){
372
- field = field.data('jqv-prompt-at');
373
- } else if(field.data('jqv-prompt-at')) {
374
- field = $(field.data('jqv-prompt-at'));
375
- }
376
- first_err=field;
377
- }
378
- if (options.doNotShowAllErrosOnSubmit)
379
- return false;
380
- names.push(field.attr('name'));
381
-
382
- //if option set, stop checking validation rules after one error is found
383
- if(options.showOneMessage == true && errorFound){
384
- return false;
385
- }
386
- }
387
- });
388
-
389
- // second, check to see if all ajax calls completed ok
390
- // errorFound |= !methods._checkAjaxStatus(options);
391
-
392
- // third, check status and scroll the container accordingly
393
- form.trigger("jqv.form.result", [errorFound]);
394
-
395
- if (errorFound) {
396
- if (options.scroll) {
397
- var destination=first_err.offset().top;
398
- var fixleft = first_err.offset().left;
399
-
400
- //prompt positioning adjustment support. Usage: positionType:Xshift,Yshift (for ex.: bottomLeft:+20 or bottomLeft:-20,+10)
401
- var positionType=options.promptPosition;
402
- if (typeof(positionType)=='string' && positionType.indexOf(":")!=-1)
403
- positionType=positionType.substring(0,positionType.indexOf(":"));
404
-
405
- if (positionType!="bottomRight" && positionType!="bottomLeft") {
406
- var prompt_err= methods._getPrompt(first_err);
407
- if (prompt_err) {
408
- destination=prompt_err.offset().top;
409
- }
410
- }
411
-
412
- // Offset the amount the page scrolls by an amount in px to accomodate fixed elements at top of page
413
- if (options.scrollOffset) {
414
- destination -= options.scrollOffset;
415
- }
416
-
417
- // get the position of the first error, there should be at least one, no need to check this
418
- //var destination = form.find(".formError:not('.greenPopup'):first").offset().top;
419
- if (options.isOverflown) {
420
- var overflowDIV = $(options.overflownDIV);
421
- if(!overflowDIV.length) return false;
422
- var scrollContainerScroll = overflowDIV.scrollTop();
423
- var scrollContainerPos = -parseInt(overflowDIV.offset().top);
424
-
425
- destination += scrollContainerScroll + scrollContainerPos - 5;
426
- var scrollContainer = $(options.overflownDIV).filter(":not(:animated)");
427
-
428
- scrollContainer.animate({ scrollTop: destination }, 1100, function(){
429
- if(options.focusFirstField) first_err.focus();
430
- });
431
-
432
- } else {
433
- $("html, body").animate({
434
- scrollTop: destination
435
- }, 1100, function(){
436
- if(options.focusFirstField) first_err.focus();
437
- });
438
- $("html, body").animate({scrollLeft: fixleft},1100)
439
- }
440
-
441
- } else if(options.focusFirstField)
442
- first_err.focus();
443
- return false;
444
- }
445
- return true;
446
- },
447
- /**
448
- * This method is called to perform an ajax form validation.
449
- * During this process all the (field, value) pairs are sent to the server which returns a list of invalid fields or true
450
- *
451
- * @param {jqObject} form
452
- * @param {Map} options
453
- */
454
- _validateFormWithAjax: function(form, options) {
455
-
456
- var data = form.serialize();
457
- var type = (options.ajaxFormValidationMethod) ? options.ajaxFormValidationMethod : "GET";
458
- var url = (options.ajaxFormValidationURL) ? options.ajaxFormValidationURL : form.attr("action");
459
- var dataType = (options.dataType) ? options.dataType : "json";
460
- $.ajax({
461
- type: type,
462
- url: url,
463
- cache: false,
464
- dataType: dataType,
465
- data: data,
466
- form: form,
467
- methods: methods,
468
- options: options,
469
- beforeSend: function() {
470
- return options.onBeforeAjaxFormValidation(form, options);
471
- },
472
- error: function(data, transport) {
473
- if (options.onFailure) {
474
- options.onFailure(data, transport);
475
- } else {
476
- methods._ajaxError(data, transport);
477
- }
478
- },
479
- success: function(json) {
480
- if ((dataType == "json") && (json !== true)) {
481
- // getting to this case doesn't necessary means that the form is invalid
482
- // the server may return green or closing prompt actions
483
- // this flag helps figuring it out
484
- var errorInForm=false;
485
- for (var i = 0; i < json.length; i++) {
486
- var value = json[i];
487
-
488
- var errorFieldId = value[0];
489
- var errorField = $($("#" + errorFieldId)[0]);
490
-
491
- // make sure we found the element
492
- if (errorField.length == 1) {
493
-
494
- // promptText or selector
495
- var msg = value[2];
496
- // if the field is valid
497
- if (value[1] == true) {
498
-
499
- if (msg == "" || !msg){
500
- // if for some reason, status==true and error="", just close the prompt
501
- methods._closePrompt(errorField);
502
- } else {
503
- // the field is valid, but we are displaying a green prompt
504
- if (options.allrules[msg]) {
505
- var txt = options.allrules[msg].alertTextOk;
506
- if (txt)
507
- msg = txt;
508
- }
509
- if (options.showPrompts) methods._showPrompt(errorField, msg, "pass", false, options, true);
510
- }
511
- } else {
512
- // the field is invalid, show the red error prompt
513
- errorInForm|=true;
514
- if (options.allrules[msg]) {
515
- var txt = options.allrules[msg].alertText;
516
- if (txt)
517
- msg = txt;
518
- }
519
- if(options.showPrompts) methods._showPrompt(errorField, msg, "", false, options, true);
520
- }
521
- }
522
- }
523
- options.onAjaxFormComplete(!errorInForm, form, json, options);
524
- } else
525
- options.onAjaxFormComplete(true, form, json, options);
526
-
527
- }
528
- });
529
-
530
- },
531
- /**
532
- * Validates field, shows prompts accordingly
533
- *
534
- * @param {jqObject}
535
- * field
536
- * @param {Array[String]}
537
- * field's validation rules
538
- * @param {Map}
539
- * user options
540
- * @return false if field is valid (It is inversed for *fields*, it return false on validate and true on errors.)
541
- */
542
- _validateField: function(field, options, skipAjaxValidation) {
543
- if (!field.attr("id")) {
544
- field.attr("id", "form-validation-field-" + $.validationEngine.fieldIdCounter);
545
- ++$.validationEngine.fieldIdCounter;
546
- }
547
-
548
- if(field.hasClass(options.ignoreFieldsWithClass))
549
- return false;
550
-
551
- if (!options.validateNonVisibleFields && (field.is(":hidden") && !options.prettySelect || field.parent().is(":hidden")))
552
- return false;
553
-
554
- var rulesParsing = field.attr(options.validateAttribute);
555
- var getRules = /validate\[(.*)\]/.exec(rulesParsing);
556
-
557
- if (!getRules)
558
- return false;
559
- var str = getRules[1];
560
- var rules = str.split(/\[|,|\]/);
561
-
562
- // true if we ran the ajax validation, tells the logic to stop messing with prompts
563
- var isAjaxValidator = false;
564
- var fieldName = field.attr("name");
565
- var promptText = "";
566
- var promptType = "";
567
- var required = false;
568
- var limitErrors = false;
569
- options.isError = false;
570
- options.showArrow = options.showArrow ==true;
571
-
572
- // If the programmer wants to limit the amount of error messages per field,
573
- if (options.maxErrorsPerField > 0) {
574
- limitErrors = true;
575
- }
576
-
577
- var form = $(field.closest("form, .validationEngineContainer"));
578
- // Fix for adding spaces in the rules
579
- for (var i = 0; i < rules.length; i++) {
580
- rules[i] = rules[i].toString().replace(" ", "");//.toString to worked on IE8
581
- // Remove any parsing errors
582
- if (rules[i] === '') {
583
- delete rules[i];
584
- }
585
- }
586
-
587
- for (var i = 0, field_errors = 0; i < rules.length; i++) {
588
-
589
- // If we are limiting errors, and have hit the max, break
590
- if (limitErrors && field_errors >= options.maxErrorsPerField) {
591
- // If we haven't hit a required yet, check to see if there is one in the validation rules for this
592
- // field and that it's index is greater or equal to our current index
593
- if (!required) {
594
- var have_required = $.inArray('required', rules);
595
- required = (have_required != -1 && have_required >= i);
596
- }
597
- break;
598
- }
599
-
600
-
601
- var errorMsg = undefined;
602
- switch (rules[i]) {
603
-
604
- case "required":
605
- required = true;
606
- errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._required);
607
- break;
608
- case "custom":
609
- errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._custom);
610
- break;
611
- case "groupRequired":
612
- // Check is its the first of group, if not, reload validation with first field
613
- // AND continue normal validation on present field
614
- var classGroup = "["+options.validateAttribute+"*=" +rules[i + 1] +"]";
615
- var firstOfGroup = form.find(classGroup).eq(0);
616
- if(firstOfGroup[0] != field[0]){
617
-
618
- methods._validateField(firstOfGroup, options, skipAjaxValidation);
619
- options.showArrow = true;
620
-
621
- }
622
- errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._groupRequired);
623
- if(errorMsg) required = true;
624
- options.showArrow = false;
625
- break;
626
- case "ajax":
627
- // AJAX defaults to returning it's loading message
628
- errorMsg = methods._ajax(field, rules, i, options);
629
- if (errorMsg) {
630
- promptType = "load";
631
- }
632
- break;
633
- case "minSize":
634
- errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._minSize);
635
- break;
636
- case "maxSize":
637
- errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._maxSize);
638
- break;
639
- case "min":
640
- errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._min);
641
- break;
642
- case "max":
643
- errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._max);
644
- break;
645
- case "past":
646
- errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._past);
647
- break;
648
- case "future":
649
- errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._future);
650
- break;
651
- case "dateRange":
652
- var classGroup = "["+options.validateAttribute+"*=" + rules[i + 1] + "]";
653
- options.firstOfGroup = form.find(classGroup).eq(0);
654
- options.secondOfGroup = form.find(classGroup).eq(1);
655
-
656
- //if one entry out of the pair has value then proceed to run through validation
657
- if (options.firstOfGroup[0].value || options.secondOfGroup[0].value) {
658
- errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._dateRange);
659
- }
660
- if (errorMsg) required = true;
661
- options.showArrow = false;
662
- break;
663
-
664
- case "dateTimeRange":
665
- var classGroup = "["+options.validateAttribute+"*=" + rules[i + 1] + "]";
666
- options.firstOfGroup = form.find(classGroup).eq(0);
667
- options.secondOfGroup = form.find(classGroup).eq(1);
668
-
669
- //if one entry out of the pair has value then proceed to run through validation
670
- if (options.firstOfGroup[0].value || options.secondOfGroup[0].value) {
671
- errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._dateTimeRange);
672
- }
673
- if (errorMsg) required = true;
674
- options.showArrow = false;
675
- break;
676
- case "maxCheckbox":
677
- field = $(form.find("input[name='" + fieldName + "']"));
678
- errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._maxCheckbox);
679
- break;
680
- case "minCheckbox":
681
- field = $(form.find("input[name='" + fieldName + "']"));
682
- errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._minCheckbox);
683
- break;
684
- case "equals":
685
- errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._equals);
686
- break;
687
- case "funcCall":
688
- errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._funcCall);
689
- break;
690
- case "creditCard":
691
- errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._creditCard);
692
- break;
693
- case "condRequired":
694
- errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._condRequired);
695
- if (errorMsg !== undefined) {
696
- required = true;
697
- }
698
- break;
699
- case "funcCallRequired":
700
- errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._funcCallRequired);
701
- if (errorMsg !== undefined) {
702
- required = true;
703
- }
704
- break;
705
-
706
- default:
707
- }
708
-
709
- var end_validation = false;
710
-
711
- // If we were passed back an message object, check what the status was to determine what to do
712
- if (typeof errorMsg == "object") {
713
- switch (errorMsg.status) {
714
- case "_break":
715
- end_validation = true;
716
- break;
717
- // If we have an error message, set errorMsg to the error message
718
- case "_error":
719
- errorMsg = errorMsg.message;
720
- break;
721
- // If we want to throw an error, but not show a prompt, return early with true
722
- case "_error_no_prompt":
723
- return true;
724
- break;
725
- // Anything else we continue on
726
- default:
727
- break;
728
- }
729
- }
730
-
731
- //funcCallRequired, first in rules, and has error, skip anything else
732
- if( i==0 && str.indexOf('funcCallRequired')==0 && errorMsg !== undefined ){
733
- if(promptText != '') {
734
- promptText += "<br/>";
735
- }
736
- promptText += errorMsg;
737
- options.isError=true;
738
- field_errors++;
739
- end_validation=true;
740
- }
741
-
742
- // If it has been specified that validation should end now, break
743
- if (end_validation) {
744
- break;
745
- }
746
-
747
- // If we have a string, that means that we have an error, so add it to the error message.
748
- if (typeof errorMsg == 'string') {
749
- if(promptText != '') {
750
- promptText += "<br/>";
751
- }
752
- promptText += errorMsg;
753
- options.isError = true;
754
- field_errors++;
755
- }
756
- }
757
- // If the rules required is not added, an empty field is not validated
758
- //the 3rd condition is added so that even empty password fields should be equal
759
- //otherwise if one is filled and another left empty, the "equal" condition would fail
760
- //which does not make any sense
761
- if(!required && !(field.val()) && field.val().length < 1 && $.inArray('equals', rules) < 0) options.isError = false;
762
-
763
- // Hack for radio/checkbox group button, the validation go into the
764
- // first radio/checkbox of the group
765
- var fieldType = field.prop("type");
766
- var positionType=field.data("promptPosition") || options.promptPosition;
767
-
768
- if ((fieldType == "radio" || fieldType == "checkbox") && form.find("input[name='" + fieldName + "']").length > 1) {
769
- if(positionType === 'inline') {
770
- field = $(form.find("input[name='" + fieldName + "'][type!=hidden]:last"));
771
- } else {
772
- field = $(form.find("input[name='" + fieldName + "'][type!=hidden]:first"));
773
- }
774
- options.showArrow = options.showArrowOnRadioAndCheckbox;
775
- }
776
-
777
- if(field.is(":hidden") && options.prettySelect) {
778
- field = form.find("#" + options.usePrefix + methods._jqSelector(field.attr('id')) + options.useSuffix);
779
- }
780
-
781
- if (options.isError && options.showPrompts){
782
- methods._showPrompt(field, promptText, promptType, false, options);
783
- }else{
784
- if (!isAjaxValidator) methods._closePrompt(field);
785
- }
786
-
787
- if (!isAjaxValidator) {
788
- field.trigger("jqv.field.result", [field, options.isError, promptText]);
789
- }
790
-
791
- /* Record error */
792
- var errindex = $.inArray(field[0], options.InvalidFields);
793
- if (errindex == -1) {
794
- if (options.isError)
795
- options.InvalidFields.push(field[0]);
796
- } else if (!options.isError) {
797
- options.InvalidFields.splice(errindex, 1);
798
- }
799
-
800
- methods._handleStatusCssClasses(field, options);
801
-
802
- /* run callback function for each field */
803
- if (options.isError && options.onFieldFailure)
804
- options.onFieldFailure(field);
805
-
806
- if (!options.isError && options.onFieldSuccess)
807
- options.onFieldSuccess(field);
808
-
809
- return options.isError;
810
- },
811
- /**
812
- * Handling css classes of fields indicating result of validation
813
- *
814
- * @param {jqObject}
815
- * field
816
- * @param {Array[String]}
817
- * field's validation rules
818
- * @private
819
- */
820
- _handleStatusCssClasses: function(field, options) {
821
- /* remove all classes */
822
- if(options.addSuccessCssClassToField)
823
- field.removeClass(options.addSuccessCssClassToField);
824
-
825
- if(options.addFailureCssClassToField)
826
- field.removeClass(options.addFailureCssClassToField);
827
-
828
- /* Add classes */
829
- if (options.addSuccessCssClassToField && !options.isError)
830
- field.addClass(options.addSuccessCssClassToField);
831
-
832
- if (options.addFailureCssClassToField && options.isError)
833
- field.addClass(options.addFailureCssClassToField);
834
- },
835
-
836
- /********************
837
- * _getErrorMessage
838
- *
839
- * @param form
840
- * @param field
841
- * @param rule
842
- * @param rules
843
- * @param i
844
- * @param options
845
- * @param originalValidationMethod
846
- * @return {*}
847
- * @private
848
- */
849
- _getErrorMessage:function (form, field, rule, rules, i, options, originalValidationMethod) {
850
- // If we are using the custon validation type, build the index for the rule.
851
- // Otherwise if we are doing a function call, make the call and return the object
852
- // that is passed back.
853
- var rule_index = jQuery.inArray(rule, rules);
854
- if (rule === "custom" || rule === "funcCall" || rule === "funcCallRequired") {
855
- var custom_validation_type = rules[rule_index + 1];
856
- rule = rule + "[" + custom_validation_type + "]";
857
- // Delete the rule from the rules array so that it doesn't try to call the
858
- // same rule over again
859
- delete(rules[rule_index]);
860
- }
861
- // Change the rule to the composite rule, if it was different from the original
862
- var alteredRule = rule;
863
-
864
-
865
- var element_classes = (field.attr("data-validation-engine")) ? field.attr("data-validation-engine") : field.attr("class");
866
- var element_classes_array = element_classes.split(" ");
867
-
868
- // Call the original validation method. If we are dealing with dates or checkboxes, also pass the form
869
- var errorMsg;
870
- if (rule == "future" || rule == "past" || rule == "maxCheckbox" || rule == "minCheckbox") {
871
- errorMsg = originalValidationMethod(form, field, rules, i, options);
872
- } else {
873
- errorMsg = originalValidationMethod(field, rules, i, options);
874
- }
875
-
876
- // If the original validation method returned an error and we have a custom error message,
877
- // return the custom message instead. Otherwise return the original error message.
878
- if (errorMsg != undefined) {
879
- var custom_message = methods._getCustomErrorMessage($(field), element_classes_array, alteredRule, options);
880
- if (custom_message) errorMsg = custom_message;
881
- }
882
- return errorMsg;
883
-
884
- },
885
- _getCustomErrorMessage:function (field, classes, rule, options) {
886
- var custom_message = false;
887
- var validityProp = /^custom\[.*\]$/.test(rule) ? methods._validityProp["custom"] : methods._validityProp[rule];
888
- // If there is a validityProp for this rule, check to see if the field has an attribute for it
889
- if (validityProp != undefined) {
890
- custom_message = field.attr("data-errormessage-"+validityProp);
891
- // If there was an error message for it, return the message
892
- if (custom_message != undefined)
893
- return custom_message;
894
- }
895
- custom_message = field.attr("data-errormessage");
896
- // If there is an inline custom error message, return it
897
- if (custom_message != undefined)
898
- return custom_message;
899
- var id = '#' + field.attr("id");
900
- // If we have custom messages for the element's id, get the message for the rule from the id.
901
- // Otherwise, if we have custom messages for the element's classes, use the first class message we find instead.
902
- if (typeof options.custom_error_messages[id] != "undefined" &&
903
- typeof options.custom_error_messages[id][rule] != "undefined" ) {
904
- custom_message = options.custom_error_messages[id][rule]['message'];
905
- } else if (classes.length > 0) {
906
- for (var i = 0; i < classes.length && classes.length > 0; i++) {
907
- var element_class = "." + classes[i];
908
- if (typeof options.custom_error_messages[element_class] != "undefined" &&
909
- typeof options.custom_error_messages[element_class][rule] != "undefined") {
910
- custom_message = options.custom_error_messages[element_class][rule]['message'];
911
- break;
912
- }
913
- }
914
- }
915
- if (!custom_message &&
916
- typeof options.custom_error_messages[rule] != "undefined" &&
917
- typeof options.custom_error_messages[rule]['message'] != "undefined"){
918
- custom_message = options.custom_error_messages[rule]['message'];
919
- }
920
- return custom_message;
921
- },
922
- _validityProp: {
923
- "required": "value-missing",
924
- "custom": "custom-error",
925
- "groupRequired": "value-missing",
926
- "ajax": "custom-error",
927
- "minSize": "range-underflow",
928
- "maxSize": "range-overflow",
929
- "min": "range-underflow",
930
- "max": "range-overflow",
931
- "past": "type-mismatch",
932
- "future": "type-mismatch",
933
- "dateRange": "type-mismatch",
934
- "dateTimeRange": "type-mismatch",
935
- "maxCheckbox": "range-overflow",
936
- "minCheckbox": "range-underflow",
937
- "equals": "pattern-mismatch",
938
- "funcCall": "custom-error",
939
- "funcCallRequired": "custom-error",
940
- "creditCard": "pattern-mismatch",
941
- "condRequired": "value-missing"
942
- },
943
- /**
944
- * Required validation
945
- *
946
- * @param {jqObject} field
947
- * @param {Array[String]} rules
948
- * @param {int} i rules index
949
- * @param {Map}
950
- * user options
951
- * @param {bool} condRequired flag when method is used for internal purpose in condRequired check
952
- * @return an error string if validation failed
953
- */
954
- _required: function(field, rules, i, options, condRequired) {
955
- switch (field.prop("type")) {
956
- case "radio":
957
- case "checkbox":
958
- // new validation style to only check dependent field
959
- if (condRequired) {
960
- if (!field.prop('checked')) {
961
- return options.allrules[rules[i]].alertTextCheckboxMultiple;
962
- }
963
- break;
964
- }
965
- // old validation style
966
- var form = field.closest("form, .validationEngineContainer");
967
- var name = field.attr("name");
968
- if (form.find("input[name='" + name + "']:checked").length == 0) {
969
- if (form.find("input[name='" + name + "']:visible").length == 1)
970
- return options.allrules[rules[i]].alertTextCheckboxe;
971
- else
972
- return options.allrules[rules[i]].alertTextCheckboxMultiple;
973
- }
974
- break;
975
- case "text":
976
- case "password":
977
- case "textarea":
978
- case "file":
979
- case "select-one":
980
- case "select-multiple":
981
- default:
982
- var field_val = $.trim( field.val() );
983
- var dv_placeholder = $.trim( field.attr("data-validation-placeholder") );
984
- var placeholder = $.trim( field.attr("placeholder") );
985
- if (
986
- ( !field_val )
987
- || ( dv_placeholder && field_val == dv_placeholder )
988
- || ( placeholder && field_val == placeholder )
989
- ) {
990
- return options.allrules[rules[i]].alertText;
991
- }
992
- break;
993
- }
994
- },
995
- /**
996
- * Validate that 1 from the group field is required
997
- *
998
- * @param {jqObject} field
999
- * @param {Array[String]} rules
1000
- * @param {int} i rules index
1001
- * @param {Map}
1002
- * user options
1003
- * @return an error string if validation failed
1004
- */
1005
- _groupRequired: function(field, rules, i, options) {
1006
- var classGroup = "["+options.validateAttribute+"*=" +rules[i + 1] +"]";
1007
- var isValid = false;
1008
- // Check all fields from the group
1009
- field.closest("form, .validationEngineContainer").find(classGroup).each(function(){
1010
- if(!methods._required($(this), rules, i, options)){
1011
- isValid = true;
1012
- return false;
1013
- }
1014
- });
1015
-
1016
- if(!isValid) {
1017
- return options.allrules[rules[i]].alertText;
1018
- }
1019
- },
1020
- /**
1021
- * Validate rules
1022
- *
1023
- * @param {jqObject} field
1024
- * @param {Array[String]} rules
1025
- * @param {int} i rules index
1026
- * @param {Map}
1027
- * user options
1028
- * @return an error string if validation failed
1029
- */
1030
- _custom: function(field, rules, i, options) {
1031
- var customRule = rules[i + 1];
1032
- var rule = options.allrules[customRule];
1033
- var fn;
1034
- if(!rule) {
1035
- alert("jqv:custom rule not found - "+customRule);
1036
- return;
1037
- }
1038
-
1039
- if(rule["regex"]) {
1040
- var ex=rule.regex;
1041
- if(!ex) {
1042
- alert("jqv:custom regex not found - "+customRule);
1043
- return;
1044
- }
1045
- var pattern = new RegExp(ex);
1046
-
1047
- if (!pattern.test(field.val())) return options.allrules[customRule].alertText;
1048
-
1049
- } else if(rule["func"]) {
1050
- fn = rule["func"];
1051
-
1052
- if (typeof(fn) !== "function") {
1053
- alert("jqv:custom parameter 'function' is no function - "+customRule);
1054
- return;
1055
- }
1056
-
1057
- if (!fn(field, rules, i, options))
1058
- return options.allrules[customRule].alertText;
1059
- } else {
1060
- alert("jqv:custom type not allowed "+customRule);
1061
- return;
1062
- }
1063
- },
1064
- /**
1065
- * Validate custom function outside of the engine scope
1066
- *
1067
- * @param {jqObject} field
1068
- * @param {Array[String]} rules
1069
- * @param {int} i rules index
1070
- * @param {Map}
1071
- * user options
1072
- * @return an error string if validation failed
1073
- */
1074
- _funcCall: function(field, rules, i, options) {
1075
- var functionName = rules[i + 1];
1076
- var fn;
1077
- if(functionName.indexOf('.') >-1)
1078
- {
1079
- var namespaces = functionName.split('.');
1080
- var scope = window;
1081
- while(namespaces.length)
1082
- {
1083
- scope = scope[namespaces.shift()];
1084
- }
1085
- fn = scope;
1086
- }
1087
- else
1088
- fn = window[functionName] || options.customFunctions[functionName];
1089
- if (typeof(fn) == 'function')
1090
- return fn(field, rules, i, options);
1091
-
1092
- },
1093
- _funcCallRequired: function(field, rules, i, options) {
1094
- return methods._funcCall(field,rules,i,options);
1095
- },
1096
- /**
1097
- * Field match
1098
- *
1099
- * @param {jqObject} field
1100
- * @param {Array[String]} rules
1101
- * @param {int} i rules index
1102
- * @param {Map}
1103
- * user options
1104
- * @return an error string if validation failed
1105
- */
1106
- _equals: function(field, rules, i, options) {
1107
- var equalsField = rules[i + 1];
1108
-
1109
- if (field.val() != $("#" + equalsField).val())
1110
- return options.allrules.equals.alertText;
1111
- },
1112
- /**
1113
- * Check the maximum size (in characters)
1114
- *
1115
- * @param {jqObject} field
1116
- * @param {Array[String]} rules
1117
- * @param {int} i rules index
1118
- * @param {Map}
1119
- * user options
1120
- * @return an error string if validation failed
1121
- */
1122
- _maxSize: function(field, rules, i, options) {
1123
- var max = rules[i + 1];
1124
- var len = field.val().length;
1125
-
1126
- if (len > max) {
1127
- var rule = options.allrules.maxSize;
1128
- return rule.alertText + max + rule.alertText2;
1129
- }
1130
- },
1131
- /**
1132
- * Check the minimum size (in characters)
1133
- *
1134
- * @param {jqObject} field
1135
- * @param {Array[String]} rules
1136
- * @param {int} i rules index
1137
- * @param {Map}
1138
- * user options
1139
- * @return an error string if validation failed
1140
- */
1141
- _minSize: function(field, rules, i, options) {
1142
- var min = rules[i + 1];
1143
- var len = field.val().length;
1144
-
1145
- if (len < min) {
1146
- var rule = options.allrules.minSize;
1147
- return rule.alertText + min + rule.alertText2;
1148
- }
1149
- },
1150
- /**
1151
- * Check number minimum value
1152
- *
1153
- * @param {jqObject} field
1154
- * @param {Array[String]} rules
1155
- * @param {int} i rules index
1156
- * @param {Map}
1157
- * user options
1158
- * @return an error string if validation failed
1159
- */
1160
- _min: function(field, rules, i, options) {
1161
- var min = parseFloat(rules[i + 1]);
1162
- var len = parseFloat(field.val());
1163
-
1164
- if (len < min) {
1165
- var rule = options.allrules.min;
1166
- if (rule.alertText2) return rule.alertText + min + rule.alertText2;
1167
- return rule.alertText + min;
1168
- }
1169
- },
1170
- /**
1171
- * Check number maximum value
1172
- *
1173
- * @param {jqObject} field
1174
- * @param {Array[String]} rules
1175
- * @param {int} i rules index
1176
- * @param {Map}
1177
- * user options
1178
- * @return an error string if validation failed
1179
- */
1180
- _max: function(field, rules, i, options) {
1181
- var max = parseFloat(rules[i + 1]);
1182
- var len = parseFloat(field.val());
1183
-
1184
- if (len >max ) {
1185
- var rule = options.allrules.max;
1186
- if (rule.alertText2) return rule.alertText + max + rule.alertText2;
1187
- //orefalo: to review, also do the translations
1188
- return rule.alertText + max;
1189
- }
1190
- },
1191
- /**
1192
- * Checks date is in the past
1193
- *
1194
- * @param {jqObject} field
1195
- * @param {Array[String]} rules
1196
- * @param {int} i rules index
1197
- * @param {Map}
1198
- * user options
1199
- * @return an error string if validation failed
1200
- */
1201
- _past: function(form, field, rules, i, options) {
1202
-
1203
- var p=rules[i + 1];
1204
- var fieldAlt = $(form.find("*[name='" + p.replace(/^#+/, '') + "']"));
1205
- var pdate;
1206
-
1207
- if (p.toLowerCase() == "now") {
1208
- pdate = new Date();
1209
- } else if (undefined != fieldAlt.val()) {
1210
- if (fieldAlt.is(":disabled"))
1211
- return;
1212
- pdate = methods._parseDate(fieldAlt.val());
1213
- } else {
1214
- pdate = methods._parseDate(p);
1215
- }
1216
- var vdate = methods._parseDate(field.val());
1217
-
1218
- if (vdate > pdate ) {
1219
- var rule = options.allrules.past;
1220
- if (rule.alertText2) return rule.alertText + methods._dateToString(pdate) + rule.alertText2;
1221
- return rule.alertText + methods._dateToString(pdate);
1222
- }
1223
- },
1224
- /**
1225
- * Checks date is in the future
1226
- *
1227
- * @param {jqObject} field
1228
- * @param {Array[String]} rules
1229
- * @param {int} i rules index
1230
- * @param {Map}
1231
- * user options
1232
- * @return an error string if validation failed
1233
- */
1234
- _future: function(form, field, rules, i, options) {
1235
-
1236
- var p=rules[i + 1];
1237
- var fieldAlt = $(form.find("*[name='" + p.replace(/^#+/, '') + "']"));
1238
- var pdate;
1239
-
1240
- if (p.toLowerCase() == "now") {
1241
- pdate = new Date();
1242
- } else if (undefined != fieldAlt.val()) {
1243
- if (fieldAlt.is(":disabled"))
1244
- return;
1245
- pdate = methods._parseDate(fieldAlt.val());
1246
- } else {
1247
- pdate = methods._parseDate(p);
1248
- }
1249
- var vdate = methods._parseDate(field.val());
1250
-
1251
- if (vdate < pdate ) {
1252
- var rule = options.allrules.future;
1253
- if (rule.alertText2)
1254
- return rule.alertText + methods._dateToString(pdate) + rule.alertText2;
1255
- return rule.alertText + methods._dateToString(pdate);
1256
- }
1257
- },
1258
- /**
1259
- * Checks if valid date
1260
- *
1261
- * @param {string} date string
1262
- * @return a bool based on determination of valid date
1263
- */
1264
- _isDate: function (value) {
1265
- var dateRegEx = new RegExp(/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$|^(?:(?:(?:0?[13578]|1[02])(\/|-)31)|(?:(?:0?[1,3-9]|1[0-2])(\/|-)(?:29|30)))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^(?:(?:0?[1-9]|1[0-2])(\/|-)(?:0?[1-9]|1\d|2[0-8]))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^(0?2(\/|-)29)(\/|-)(?:(?:0[48]00|[13579][26]00|[2468][048]00)|(?:\d\d)?(?:0[48]|[2468][048]|[13579][26]))$/);
1266
- return dateRegEx.test(value);
1267
- },
1268
- /**
1269
- * Checks if valid date time
1270
- *
1271
- * @param {string} date string
1272
- * @return a bool based on determination of valid date time
1273
- */
1274
- _isDateTime: function (value){
1275
- var dateTimeRegEx = new RegExp(/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])\s+(1[012]|0?[1-9]){1}:(0?[1-5]|[0-6][0-9]){1}:(0?[0-6]|[0-6][0-9]){1}\s+(am|pm|AM|PM){1}$|^(?:(?:(?:0?[13578]|1[02])(\/|-)31)|(?:(?:0?[1,3-9]|1[0-2])(\/|-)(?:29|30)))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^((1[012]|0?[1-9]){1}\/(0?[1-9]|[12][0-9]|3[01]){1}\/\d{2,4}\s+(1[012]|0?[1-9]){1}:(0?[1-5]|[0-6][0-9]){1}:(0?[0-6]|[0-6][0-9]){1}\s+(am|pm|AM|PM){1})$/);
1276
- return dateTimeRegEx.test(value);
1277
- },
1278
- //Checks if the start date is before the end date
1279
- //returns true if end is later than start
1280
- _dateCompare: function (start, end) {
1281
- return (new Date(start.toString()) < new Date(end.toString()));
1282
- },
1283
- /**
1284
- * Checks date range
1285
- *
1286
- * @param {jqObject} first field name
1287
- * @param {jqObject} second field name
1288
- * @return an error string if validation failed
1289
- */
1290
- _dateRange: function (field, rules, i, options) {
1291
- //are not both populated
1292
- if ((!options.firstOfGroup[0].value && options.secondOfGroup[0].value) || (options.firstOfGroup[0].value && !options.secondOfGroup[0].value)) {
1293
- return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
1294
- }
1295
-
1296
- //are not both dates
1297
- if (!methods._isDate(options.firstOfGroup[0].value) || !methods._isDate(options.secondOfGroup[0].value)) {
1298
- return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
1299
- }
1300
-
1301
- //are both dates but range is off
1302
- if (!methods._dateCompare(options.firstOfGroup[0].value, options.secondOfGroup[0].value)) {
1303
- return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
1304
- }
1305
- },
1306
- /**
1307
- * Checks date time range
1308
- *
1309
- * @param {jqObject} first field name
1310
- * @param {jqObject} second field name
1311
- * @return an error string if validation failed
1312
- */
1313
- _dateTimeRange: function (field, rules, i, options) {
1314
- //are not both populated
1315
- if ((!options.firstOfGroup[0].value && options.secondOfGroup[0].value) || (options.firstOfGroup[0].value && !options.secondOfGroup[0].value)) {
1316
- return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
1317
- }
1318
- //are not both dates
1319
- if (!methods._isDateTime(options.firstOfGroup[0].value) || !methods._isDateTime(options.secondOfGroup[0].value)) {
1320
- return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
1321
- }
1322
- //are both dates but range is off
1323
- if (!methods._dateCompare(options.firstOfGroup[0].value, options.secondOfGroup[0].value)) {
1324
- return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
1325
- }
1326
- },
1327
- /**
1328
- * Max number of checkbox selected
1329
- *
1330
- * @param {jqObject} field
1331
- * @param {Array[String]} rules
1332
- * @param {int} i rules index
1333
- * @param {Map}
1334
- * user options
1335
- * @return an error string if validation failed
1336
- */
1337
- _maxCheckbox: function(form, field, rules, i, options) {
1338
-
1339
- var nbCheck = rules[i + 1];
1340
- var groupname = field.attr("name");
1341
- var groupSize = form.find("input[name='" + groupname + "']:checked").length;
1342
- if (groupSize > nbCheck) {
1343
- options.showArrow = false;
1344
- if (options.allrules.maxCheckbox.alertText2)
1345
- return options.allrules.maxCheckbox.alertText + " " + nbCheck + " " + options.allrules.maxCheckbox.alertText2;
1346
- return options.allrules.maxCheckbox.alertText;
1347
- }
1348
- },
1349
- /**
1350
- * Min number of checkbox selected
1351
- *
1352
- * @param {jqObject} field
1353
- * @param {Array[String]} rules
1354
- * @param {int} i rules index
1355
- * @param {Map}
1356
- * user options
1357
- * @return an error string if validation failed
1358
- */
1359
- _minCheckbox: function(form, field, rules, i, options) {
1360
-
1361
- var nbCheck = rules[i + 1];
1362
- var groupname = field.attr("name");
1363
- var groupSize = form.find("input[name='" + groupname + "']:checked").length;
1364
- if (groupSize < nbCheck) {
1365
- options.showArrow = false;
1366
- return options.allrules.minCheckbox.alertText + " " + nbCheck + " " + options.allrules.minCheckbox.alertText2;
1367
- }
1368
- },
1369
- /**
1370
- * Checks that it is a valid credit card number according to the
1371
- * Luhn checksum algorithm.
1372
- *
1373
- * @param {jqObject} field
1374
- * @param {Array[String]} rules
1375
- * @param {int} i rules index
1376
- * @param {Map}
1377
- * user options
1378
- * @return an error string if validation failed
1379
- */
1380
- _creditCard: function(field, rules, i, options) {
1381
- //spaces and dashes may be valid characters, but must be stripped to calculate the checksum.
1382
- var valid = false, cardNumber = field.val().replace(/ +/g, '').replace(/-+/g, '');
1383
-
1384
- var numDigits = cardNumber.length;
1385
- if (numDigits >= 14 && numDigits <= 16 && parseInt(cardNumber) > 0) {
1386
-
1387
- var sum = 0, i = numDigits - 1, pos = 1, digit, luhn = new String();
1388
- do {
1389
- digit = parseInt(cardNumber.charAt(i));
1390
- luhn += (pos++ % 2 == 0) ? digit * 2 : digit;
1391
- } while (--i >= 0)
1392
-
1393
- for (i = 0; i < luhn.length; i++) {
1394
- sum += parseInt(luhn.charAt(i));
1395
- }
1396
- valid = sum % 10 == 0;
1397
- }
1398
- if (!valid) return options.allrules.creditCard.alertText;
1399
- },
1400
- /**
1401
- * Ajax field validation
1402
- *
1403
- * @param {jqObject} field
1404
- * @param {Array[String]} rules
1405
- * @param {int} i rules index
1406
- * @param {Map}
1407
- * user options
1408
- * @return nothing! the ajax validator handles the prompts itself
1409
- */
1410
- _ajax: function(field, rules, i, options) {
1411
-
1412
- var errorSelector = rules[i + 1];
1413
- var rule = options.allrules[errorSelector];
1414
- var extraData = rule.extraData;
1415
- var extraDataDynamic = rule.extraDataDynamic;
1416
- var data = {
1417
- "fieldId" : field.attr("id"),
1418
- "fieldValue" : field.val()
1419
- };
1420
-
1421
- if (typeof extraData === "object") {
1422
- $.extend(data, extraData);
1423
- } else if (typeof extraData === "string") {
1424
- var tempData = extraData.split("&");
1425
- for(var i = 0; i < tempData.length; i++) {
1426
- var values = tempData[i].split("=");
1427
- if (values[0] && values[0]) {
1428
- data[values[0]] = values[1];
1429
- }
1430
- }
1431
- }
1432
-
1433
- if (extraDataDynamic) {
1434
- var tmpData = [];
1435
- var domIds = String(extraDataDynamic).split(",");
1436
- for (var i = 0; i < domIds.length; i++) {
1437
- var id = domIds[i];
1438
- if ($(id).length) {
1439
- var inputValue = field.closest("form, .validationEngineContainer").find(id).val();
1440
- var keyValue = id.replace('#', '') + '=' + escape(inputValue);
1441
- data[id.replace('#', '')] = inputValue;
1442
- }
1443
- }
1444
- }
1445
-
1446
- // If a field change event triggered this we want to clear the cache for this ID
1447
- if (options.eventTrigger == "field") {
1448
- delete(options.ajaxValidCache[field.attr("id")]);
1449
- }
1450
-
1451
- // If there is an error or if the the field is already validated, do not re-execute AJAX
1452
- if (!options.isError && !methods._checkAjaxFieldStatus(field.attr("id"), options)) {
1453
- $.ajax({
1454
- type: options.ajaxFormValidationMethod,
1455
- url: rule.url,
1456
- cache: false,
1457
- dataType: "json",
1458
- data: data,
1459
- field: field,
1460
- rule: rule,
1461
- methods: methods,
1462
- options: options,
1463
- beforeSend: function() {},
1464
- error: function(data, transport) {
1465
- if (options.onFailure) {
1466
- options.onFailure(data, transport);
1467
- } else {
1468
- methods._ajaxError(data, transport);
1469
- }
1470
- },
1471
- success: function(json) {
1472
-
1473
- // asynchronously called on success, data is the json answer from the server
1474
- var errorFieldId = json[0];
1475
- //var errorField = $($("#" + errorFieldId)[0]);
1476
- var errorField = $("#"+ errorFieldId).eq(0);
1477
-
1478
- // make sure we found the element
1479
- if (errorField.length == 1) {
1480
- var status = json[1];
1481
- // read the optional msg from the server
1482
- var msg = json[2];
1483
- if (!status) {
1484
- // Houston we got a problem - display an red prompt
1485
- options.ajaxValidCache[errorFieldId] = false;
1486
- options.isError = true;
1487
-
1488
- // resolve the msg prompt
1489
- if(msg) {
1490
- if (options.allrules[msg]) {
1491
- var txt = options.allrules[msg].alertText;
1492
- if (txt) {
1493
- msg = txt;
1494
- }
1495
- }
1496
- }
1497
- else
1498
- msg = rule.alertText;
1499
-
1500
- if (options.showPrompts) methods._showPrompt(errorField, msg, "", true, options);
1501
- } else {
1502
- options.ajaxValidCache[errorFieldId] = true;
1503
-
1504
- // resolves the msg prompt
1505
- if(msg) {
1506
- if (options.allrules[msg]) {
1507
- var txt = options.allrules[msg].alertTextOk;
1508
- if (txt) {
1509
- msg = txt;
1510
- }
1511
- }
1512
- }
1513
- else
1514
- msg = rule.alertTextOk;
1515
-
1516
- if (options.showPrompts) {
1517
- // see if we should display a green prompt
1518
- if (msg)
1519
- methods._showPrompt(errorField, msg, "pass", true, options);
1520
- else
1521
- methods._closePrompt(errorField);
1522
- }
1523
-
1524
- // If a submit form triggered this, we want to re-submit the form
1525
- if (options.eventTrigger == "submit")
1526
- field.closest("form").submit();
1527
- }
1528
- }
1529
- errorField.trigger("jqv.field.result", [errorField, options.isError, msg]);
1530
- }
1531
- });
1532
-
1533
- return rule.alertTextLoad;
1534
- }
1535
- },
1536
- /**
1537
- * Common method to handle ajax errors
1538
- *
1539
- * @param {Object} data
1540
- * @param {Object} transport
1541
- */
1542
- _ajaxError: function(data, transport) {
1543
- if(data.status == 0 && transport == null)
1544
- alert("The page is not served from a server! ajax call failed");
1545
- else if(typeof console != "undefined")
1546
- console.log("Ajax error: " + data.status + " " + transport);
1547
- },
1548
- /**
1549
- * date -> string
1550
- *
1551
- * @param {Object} date
1552
- */
1553
- _dateToString: function(date) {
1554
- return date.getFullYear()+"-"+(date.getMonth()+1)+"-"+date.getDate();
1555
- },
1556
- /**
1557
- * Parses an ISO date
1558
- * @param {String} d
1559
- */
1560
- _parseDate: function(d) {
1561
-
1562
- var dateParts = d.split("-");
1563
- if(dateParts==d)
1564
- dateParts = d.split("/");
1565
- if(dateParts==d) {
1566
- dateParts = d.split(".");
1567
- return new Date(dateParts[2], (dateParts[1] - 1), dateParts[0]);
1568
- }
1569
- return new Date(dateParts[0], (dateParts[1] - 1) ,dateParts[2]);
1570
- },
1571
- /**
1572
- * Builds or updates a prompt with the given information
1573
- *
1574
- * @param {jqObject} field
1575
- * @param {String} promptText html text to display type
1576
- * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
1577
- * @param {boolean} ajaxed - use to mark fields than being validated with ajax
1578
- * @param {Map} options user options
1579
- */
1580
- _showPrompt: function(field, promptText, type, ajaxed, options, ajaxform) {
1581
- //Check if we need to adjust what element to show the prompt on
1582
- if(field.data('jqv-prompt-at') instanceof jQuery ){
1583
- field = field.data('jqv-prompt-at');
1584
- } else if(field.data('jqv-prompt-at')) {
1585
- field = $(field.data('jqv-prompt-at'));
1586
- }
1587
-
1588
- var prompt = methods._getPrompt(field);
1589
- // The ajax submit errors are not see has an error in the form,
1590
- // When the form errors are returned, the engine see 2 bubbles, but those are ebing closed by the engine at the same time
1591
- // Because no error was found befor submitting
1592
- if(ajaxform) prompt = false;
1593
- // Check that there is indded text
1594
- if($.trim(promptText)){
1595
- if (prompt)
1596
- methods._updatePrompt(field, prompt, promptText, type, ajaxed, options);
1597
- else
1598
- methods._buildPrompt(field, promptText, type, ajaxed, options);
1599
- }
1600
- },
1601
- /**
1602
- * Builds and shades a prompt for the given field.
1603
- *
1604
- * @param {jqObject} field
1605
- * @param {String} promptText html text to display type
1606
- * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
1607
- * @param {boolean} ajaxed - use to mark fields than being validated with ajax
1608
- * @param {Map} options user options
1609
- */
1610
- _buildPrompt: function(field, promptText, type, ajaxed, options) {
1611
-
1612
- // create the prompt
1613
- var prompt = $('<div>');
1614
- prompt.addClass(methods._getClassName(field.attr("id")) + "formError");
1615
- // add a class name to identify the parent form of the prompt
1616
- prompt.addClass("parentForm"+methods._getClassName(field.closest('form, .validationEngineContainer').attr("id")));
1617
- prompt.addClass("formError");
1618
-
1619
- switch (type) {
1620
- case "pass":
1621
- prompt.addClass("greenPopup");
1622
- break;
1623
- case "load":
1624
- prompt.addClass("blackPopup");
1625
- break;
1626
- default:
1627
- /* it has error */
1628
- //alert("unknown popup type:"+type);
1629
- }
1630
- if (ajaxed)
1631
- prompt.addClass("ajaxed");
1632
-
1633
- // create the prompt content
1634
- var promptContent = $('<div>').addClass("formErrorContent").html(promptText).appendTo(prompt);
1635
-
1636
- // determine position type
1637
- var positionType=field.data("promptPosition") || options.promptPosition;
1638
-
1639
- // create the css arrow pointing at the field
1640
- // note that there is no triangle on max-checkbox and radio
1641
- if (options.showArrow) {
1642
- var arrow = $('<div>').addClass("formErrorArrow");
1643
-
1644
- //prompt positioning adjustment support. Usage: positionType:Xshift,Yshift (for ex.: bottomLeft:+20 or bottomLeft:-20,+10)
1645
- if (typeof(positionType)=='string')
1646
- {
1647
- var pos=positionType.indexOf(":");
1648
- if(pos!=-1)
1649
- positionType=positionType.substring(0,pos);
1650
- }
1651
-
1652
- switch (positionType) {
1653
- case "bottomLeft":
1654
- case "bottomRight":
1655
- prompt.find(".formErrorContent").before(arrow);
1656
- arrow.addClass("formErrorArrowBottom").html('<div class="line1"><!-- --></div><div class="line2"><!-- --></div><div class="line3"><!-- --></div><div class="line4"><!-- --></div><div class="line5"><!-- --></div><div class="line6"><!-- --></div><div class="line7"><!-- --></div><div class="line8"><!-- --></div><div class="line9"><!-- --></div><div class="line10"><!-- --></div>');
1657
- break;
1658
- case "topLeft":
1659
- case "topRight":
1660
- arrow.html('<div class="line10"><!-- --></div><div class="line9"><!-- --></div><div class="line8"><!-- --></div><div class="line7"><!-- --></div><div class="line6"><!-- --></div><div class="line5"><!-- --></div><div class="line4"><!-- --></div><div class="line3"><!-- --></div><div class="line2"><!-- --></div><div class="line1"><!-- --></div>');
1661
- prompt.append(arrow);
1662
- break;
1663
- }
1664
- }
1665
- // Add custom prompt class
1666
- if (options.addPromptClass)
1667
- prompt.addClass(options.addPromptClass);
1668
-
1669
- // Add custom prompt class defined in element
1670
- var requiredOverride = field.attr('data-required-class');
1671
- if(requiredOverride !== undefined) {
1672
- prompt.addClass(requiredOverride);
1673
- } else {
1674
- if(options.prettySelect) {
1675
- if($('#' + field.attr('id')).next().is('select')) {
1676
- var prettyOverrideClass = $('#' + field.attr('id').substr(options.usePrefix.length).substring(options.useSuffix.length)).attr('data-required-class');
1677
- if(prettyOverrideClass !== undefined) {
1678
- prompt.addClass(prettyOverrideClass);
1679
- }
1680
- }
1681
- }
1682
- }
1683
-
1684
- prompt.css({
1685
- "opacity": 0
1686
- });
1687
- if(positionType === 'inline') {
1688
- prompt.addClass("inline");
1689
- if(typeof field.attr('data-prompt-target') !== 'undefined' && $('#'+field.attr('data-prompt-target')).length > 0) {
1690
- prompt.appendTo($('#'+field.attr('data-prompt-target')));
1691
- } else {
1692
- field.after(prompt);
1693
- }
1694
- } else {
1695
- field.before(prompt);
1696
- }
1697
-
1698
- var pos = methods._calculatePosition(field, prompt, options);
1699
- // Support RTL layouts by @yasser_lotfy ( Yasser Lotfy )
1700
- if ($('body').hasClass('rtl')) {
1701
- prompt.css({
1702
- 'position': positionType === 'inline' ? 'relative' : 'absolute',
1703
- "top": pos.callerTopPosition,
1704
- "left": "initial",
1705
- "right": pos.callerleftPosition,
1706
- "marginTop": pos.marginTopSize,
1707
- "opacity": 0
1708
- }).data("callerField", field);
1709
- } else {
1710
- prompt.css({
1711
- 'position': positionType === 'inline' ? 'relative' : 'absolute',
1712
- "top": pos.callerTopPosition,
1713
- "left": pos.callerleftPosition,
1714
- "right": "initial",
1715
- "marginTop": pos.marginTopSize,
1716
- "opacity": 0
1717
- }).data("callerField", field);
1718
- }
1719
-
1720
-
1721
- if (options.autoHidePrompt) {
1722
- setTimeout(function(){
1723
- prompt.animate({
1724
- "opacity": 0
1725
- },function(){
1726
- prompt.closest('.formError').remove();
1727
- });
1728
- }, options.autoHideDelay);
1729
- }
1730
- return prompt.animate({
1731
- "opacity": 0.87
1732
- });
1733
- },
1734
- /**
1735
- * Updates the prompt text field - the field for which the prompt
1736
- * @param {jqObject} field
1737
- * @param {String} promptText html text to display type
1738
- * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
1739
- * @param {boolean} ajaxed - use to mark fields than being validated with ajax
1740
- * @param {Map} options user options
1741
- */
1742
- _updatePrompt: function(field, prompt, promptText, type, ajaxed, options, noAnimation) {
1743
-
1744
- if (prompt) {
1745
- if (typeof type !== "undefined") {
1746
- if (type == "pass")
1747
- prompt.addClass("greenPopup");
1748
- else
1749
- prompt.removeClass("greenPopup");
1750
-
1751
- if (type == "load")
1752
- prompt.addClass("blackPopup");
1753
- else
1754
- prompt.removeClass("blackPopup");
1755
- }
1756
- if (ajaxed)
1757
- prompt.addClass("ajaxed");
1758
- else
1759
- prompt.removeClass("ajaxed");
1760
-
1761
- prompt.find(".formErrorContent").html(promptText);
1762
-
1763
- var pos = methods._calculatePosition(field, prompt, options);
1764
- // Support RTL layouts by @yasser_lotfy ( Yasser Lotfy )
1765
- if ($('body').hasClass('rtl')) {
1766
- var css = {"top": pos.callerTopPosition,
1767
- "left": "initial",
1768
- "right": pos.callerleftPosition,
1769
- "marginTop": pos.marginTopSize,
1770
- "opacity": 0.87};
1771
- } else {
1772
- var css = {"top": pos.callerTopPosition,
1773
- "left": pos.callerleftPosition,
1774
- "right": "initial",
1775
- "marginTop": pos.marginTopSize,
1776
- "opacity": 0.87};
1777
- }
1778
-
1779
- prompt.css({
1780
- "opacity": 0,
1781
- "display": "block"
1782
- });
1783
-
1784
- if (noAnimation)
1785
- prompt.css(css);
1786
- else
1787
- prompt.animate(css);
1788
- }
1789
- },
1790
- /**
1791
- * Closes the prompt associated with the given field
1792
- *
1793
- * @param {jqObject}
1794
- * field
1795
- */
1796
- _closePrompt: function(field) {
1797
- var prompt = methods._getPrompt(field);
1798
- if (prompt)
1799
- prompt.fadeTo("fast", 0, function() {
1800
- prompt.closest('.formError').remove();
1801
- });
1802
- },
1803
- closePrompt: function(field) {
1804
- return methods._closePrompt(field);
1805
- },
1806
- /**
1807
- * Returns the error prompt matching the field if any
1808
- *
1809
- * @param {jqObject}
1810
- * field
1811
- * @return undefined or the error prompt (jqObject)
1812
- */
1813
- _getPrompt: function(field) {
1814
- var formId = $(field).closest('form, .validationEngineContainer').attr('id');
1815
- var className = methods._getClassName(field.attr("id")) + "formError";
1816
- var match = $("." + methods._escapeExpression(className) + '.parentForm' + methods._getClassName(formId))[0];
1817
- if (match)
1818
- return $(match);
1819
- },
1820
- /**
1821
- * Returns the escapade classname
1822
- *
1823
- * @param {selector}
1824
- * className
1825
- */
1826
- _escapeExpression: function (selector) {
1827
- return selector.replace(/([#;&,\.\+\*\~':"\!\^$\[\]\(\)=>\|])/g, "\\$1");
1828
- },
1829
- /**
1830
- * returns true if we are in a RTLed document
1831
- *
1832
- * @param {jqObject} field
1833
- */
1834
- isRTL: function(field)
1835
- {
1836
- var $document = $(document);
1837
- var $body = $('body');
1838
- var rtl =
1839
- (field && field.hasClass('rtl')) ||
1840
- (field && (field.attr('dir') || '').toLowerCase()==='rtl') ||
1841
- $document.hasClass('rtl') ||
1842
- ($document.attr('dir') || '').toLowerCase()==='rtl' ||
1843
- $body.hasClass('rtl') ||
1844
- ($body.attr('dir') || '').toLowerCase()==='rtl';
1845
- return Boolean(rtl);
1846
- },
1847
- /**
1848
- * Calculates prompt position
1849
- *
1850
- * @param {jqObject}
1851
- * field
1852
- * @param {jqObject}
1853
- * the prompt
1854
- * @param {Map}
1855
- * options
1856
- * @return positions
1857
- */
1858
- _calculatePosition: function (field, promptElmt, options) {
1859
-
1860
- var promptTopPosition, promptleftPosition, marginTopSize;
1861
- var fieldWidth = field.width();
1862
- var fieldLeft = field.position().left;
1863
- var fieldTop = field.position().top;
1864
- var fieldHeight = field.height();
1865
- var promptHeight = promptElmt.height();
1866
-
1867
-
1868
- // is the form contained in an overflown container?
1869
- promptTopPosition = promptleftPosition = 0;
1870
- // compensation for the arrow
1871
- marginTopSize = -promptHeight;
1872
-
1873
-
1874
- //prompt positioning adjustment support
1875
- //now you can adjust prompt position
1876
- //usage: positionType:Xshift,Yshift
1877
- //for example:
1878
- // bottomLeft:+20 means bottomLeft position shifted by 20 pixels right horizontally
1879
- // topRight:20, -15 means topRight position shifted by 20 pixels to right and 15 pixels to top
1880
- //You can use +pixels, - pixels. If no sign is provided than + is default.
1881
- var positionType=field.data("promptPosition") || options.promptPosition;
1882
- var shift1="";
1883
- var shift2="";
1884
- var shiftX=0;
1885
- var shiftY=0;
1886
- if (typeof(positionType)=='string') {
1887
- //do we have any position adjustments ?
1888
- if (positionType.indexOf(":")!=-1) {
1889
- shift1=positionType.substring(positionType.indexOf(":")+1);
1890
- positionType=positionType.substring(0,positionType.indexOf(":"));
1891
-
1892
- //if any advanced positioning will be needed (percents or something else) - parser should be added here
1893
- //for now we use simple parseInt()
1894
-
1895
- //do we have second parameter?
1896
- if (shift1.indexOf(",") !=-1) {
1897
- shift2=shift1.substring(shift1.indexOf(",") +1);
1898
- shift1=shift1.substring(0,shift1.indexOf(","));
1899
- shiftY=parseInt(shift2);
1900
- if (isNaN(shiftY)) shiftY=0;
1901
- };
1902
-
1903
- shiftX=parseInt(shift1);
1904
- if (isNaN(shift1)) shift1=0;
1905
-
1906
- };
1907
- };
1908
-
1909
-
1910
- switch (positionType) {
1911
- default:
1912
- case "topRight":
1913
- promptleftPosition += fieldLeft + fieldWidth - 27;
1914
- promptTopPosition += fieldTop;
1915
- break;
1916
-
1917
- case "topLeft":
1918
- promptTopPosition += fieldTop;
1919
- promptleftPosition += fieldLeft;
1920
- break;
1921
-
1922
- case "centerRight":
1923
- promptTopPosition = fieldTop+4;
1924
- marginTopSize = 0;
1925
- promptleftPosition= fieldLeft + field.outerWidth(true)+5;
1926
- break;
1927
- case "centerLeft":
1928
- promptleftPosition = fieldLeft - (promptElmt.width() + 2);
1929
- promptTopPosition = fieldTop+4;
1930
- marginTopSize = 0;
1931
-
1932
- break;
1933
-
1934
- case "bottomLeft":
1935
- promptTopPosition = fieldTop + field.height() + 5;
1936
- marginTopSize = 0;
1937
- promptleftPosition = fieldLeft;
1938
- break;
1939
- case "bottomRight":
1940
- promptleftPosition = fieldLeft + fieldWidth - 27;
1941
- promptTopPosition = fieldTop + field.height() + 5;
1942
- marginTopSize = 0;
1943
- break;
1944
- case "inline":
1945
- promptleftPosition = 0;
1946
- promptTopPosition = 0;
1947
- marginTopSize = 0;
1948
- };
1949
-
1950
-
1951
-
1952
- //apply adjusments if any
1953
- promptleftPosition += shiftX;
1954
- promptTopPosition += shiftY;
1955
-
1956
- return {
1957
- "callerTopPosition": promptTopPosition + "px",
1958
- "callerleftPosition": promptleftPosition + "px",
1959
- "marginTopSize": marginTopSize + "px"
1960
- };
1961
- },
1962
- /**
1963
- * Saves the user options and variables in the form.data
1964
- *
1965
- * @param {jqObject}
1966
- * form - the form where the user option should be saved
1967
- * @param {Map}
1968
- * options - the user options
1969
- * @return the user options (extended from the defaults)
1970
- */
1971
- _saveOptions: function(form, options) {
1972
-
1973
- // is there a language localisation ?
1974
- if ($.validationEngineLanguage)
1975
- var allRules = $.validationEngineLanguage.allRules;
1976
- else
1977
- $.error("jQuery.validationEngine rules are not loaded, plz add localization files to the page");
1978
- // --- Internals DO NOT TOUCH or OVERLOAD ---
1979
- // validation rules and i18
1980
- $.validationEngine.defaults.allrules = allRules;
1981
-
1982
- var userOptions = $.extend(true,{},$.validationEngine.defaults,options);
1983
-
1984
- form.data('jqv', userOptions);
1985
- return userOptions;
1986
- },
1987
-
1988
- /**
1989
- * Removes forbidden characters from class name
1990
- * @param {String} className
1991
- */
1992
- _getClassName: function(className) {
1993
- if(className)
1994
- return className.replace(/:/g, "_").replace(/\./g, "_");
1995
- },
1996
- /**
1997
- * Escape special character for jQuery selector
1998
- * http://totaldev.com/content/escaping-characters-get-valid-jquery-id
1999
- * @param {String} selector
2000
- */
2001
- _jqSelector: function(str){
2002
- return str.replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, '\\$1');
2003
- },
2004
- /**
2005
- * Conditionally required field
2006
- *
2007
- * @param {jqObject} field
2008
- * @param {Array[String]} rules
2009
- * @param {int} i rules index
2010
- * @param {Map}
2011
- * user options
2012
- * @return an error string if validation failed
2013
- */
2014
- _condRequired: function(field, rules, i, options) {
2015
- var idx, dependingField;
2016
-
2017
- for(idx = (i + 1); idx < rules.length; idx++) {
2018
- dependingField = jQuery("#" + rules[idx]).first();
2019
-
2020
- /* Use _required for determining wether dependingField has a value.
2021
- * There is logic there for handling all field types, and default value; so we won't replicate that here
2022
- * Indicate this special use by setting the last parameter to true so we only validate the dependingField on chackboxes and radio buttons (#462)
2023
- */
2024
- if (dependingField.length && methods._required(dependingField, ["required"], 0, options, true) == undefined) {
2025
- /* We now know any of the depending fields has a value,
2026
- * so we can validate this field as per normal required code
2027
- */
2028
- return methods._required(field, ["required"], 0, options);
2029
- }
2030
- }
2031
- },
2032
-
2033
- _submitButtonClick: function(event) {
2034
- var button = $(this);
2035
- var form = button.closest('form, .validationEngineContainer');
2036
- form.data("jqv_submitButton", button.attr("id"));
2037
- }
2038
- };
2039
-
2040
- /**
2041
- * Plugin entry point.
2042
- * You may pass an action as a parameter or a list of options.
2043
- * if none, the init and attach methods are being called.
2044
- * Remember: if you pass options, the attached method is NOT called automatically
2045
- *
2046
- * @param {String}
2047
- * method (optional) action
2048
- */
2049
- $.fn.validationEngine = function(method) {
2050
-
2051
- var form = $(this);
2052
- if(!form[0]) return form; // stop here if the form does not exist
2053
-
2054
- if (typeof(method) == 'string' && method.charAt(0) != '_' && methods[method]) {
2055
-
2056
- // make sure init is called once
2057
- if(method != "showPrompt" && method != "hide" && method != "hideAll")
2058
- methods.init.apply(form);
2059
-
2060
- return methods[method].apply(form, Array.prototype.slice.call(arguments, 1));
2061
- } else if (typeof method == 'object' || !method) {
2062
-
2063
- // default constructor with or without arguments
2064
- methods.init.apply(form, arguments);
2065
- return methods.attach.apply(form);
2066
- } else {
2067
- $.error('Method ' + method + ' does not exist in jQuery.validationEngine');
2068
- }
2069
- };
2070
-
2071
-
2072
-
2073
- // LEAK GLOBAL OPTIONS
2074
- $.validationEngine= {fieldIdCounter: 0,defaults:{
2075
-
2076
- // Name of the event triggering field validation
2077
- validationEventTrigger: "blur",
2078
- // Automatically scroll viewport to the first error
2079
- scroll: true,
2080
- // Focus on the first input
2081
- focusFirstField:true,
2082
- // Show prompts, set to false to disable prompts
2083
- showPrompts: true,
2084
- // Should we attempt to validate non-visible input fields contained in the form? (Useful in cases of tabbed containers, e.g. jQuery-UI tabs)
2085
- validateNonVisibleFields: false,
2086
- // ignore the validation for fields with this specific class (Useful in cases of tabbed containers AND hidden fields we don't want to validate)
2087
- ignoreFieldsWithClass: 'ignoreMe',
2088
- // Opening box position, possible locations are: topLeft,
2089
- // topRight, bottomLeft, centerRight, bottomRight, inline
2090
- // inline gets inserted after the validated field or into an element specified in data-prompt-target
2091
- promptPosition: "topRight",
2092
- bindMethod:"bind",
2093
- // internal, automatically set to true when it parse a _ajax rule
2094
- inlineAjax: false,
2095
- // if set to true, the form data is sent asynchronously via ajax to the form.action url (get)
2096
- ajaxFormValidation: false,
2097
- // The url to send the submit ajax validation (default to action)
2098
- ajaxFormValidationURL: false,
2099
- // HTTP method used for ajax validation
2100
- ajaxFormValidationMethod: 'get',
2101
- // Ajax form validation callback method: boolean onComplete(form, status, errors, options)
2102
- // retuns false if the form.submit event needs to be canceled.
2103
- onAjaxFormComplete: $.noop,
2104
- // called right before the ajax call, may return false to cancel
2105
- onBeforeAjaxFormValidation: $.noop,
2106
- // Stops form from submitting and execute function assiciated with it
2107
- onValidationComplete: false,
2108
-
2109
- // Used when you have a form fields too close and the errors messages are on top of other disturbing viewing messages
2110
- doNotShowAllErrosOnSubmit: false,
2111
- // Object where you store custom messages to override the default error messages
2112
- custom_error_messages:{},
2113
- // true if you want to validate the input fields on blur event
2114
- binded: true,
2115
- // set to true if you want to validate the input fields on blur only if the field it's not empty
2116
- notEmpty: false,
2117
- // set to true, when the prompt arrow needs to be displayed
2118
- showArrow: true,
2119
- // set to false, determines if the prompt arrow should be displayed when validating
2120
- // checkboxes and radio buttons
2121
- showArrowOnRadioAndCheckbox: false,
2122
- // did one of the validation fail ? kept global to stop further ajax validations
2123
- isError: false,
2124
- // Limit how many displayed errors a field can have
2125
- maxErrorsPerField: false,
2126
-
2127
- // Caches field validation status, typically only bad status are created.
2128
- // the array is used during ajax form validation to detect issues early and prevent an expensive submit
2129
- ajaxValidCache: {},
2130
- // Auto update prompt position after window resize
2131
- autoPositionUpdate: false,
2132
-
2133
- InvalidFields: [],
2134
- onFieldSuccess: false,
2135
- onFieldFailure: false,
2136
- onSuccess: false,
2137
- onFailure: false,
2138
- validateAttribute: "class",
2139
- addSuccessCssClassToField: "",
2140
- addFailureCssClassToField: "",
2141
-
2142
- // Auto-hide prompt
2143
- autoHidePrompt: false,
2144
- // Delay before auto-hide
2145
- autoHideDelay: 10000,
2146
- // Fade out duration while hiding the validations
2147
- fadeDuration: 300,
2148
- // Use Prettify select library
2149
- prettySelect: false,
2150
- // Add css class on prompt
2151
- addPromptClass : "",
2152
- // Custom ID uses prefix
2153
- usePrefix: "",
2154
- // Custom ID uses suffix
2155
- useSuffix: "",
2156
- // Only show one message per error prompt
2157
- showOneMessage: false
2158
- }};
2159
- $(function(){$.validationEngine.defaults.promptPosition = methods.isRTL()?'topLeft':"topRight"});
2160
- })(jQuery);
1
+ /*
2
+ * Inline Form Validation Engine 2.6.2, jQuery plugin
3
+ *
4
+ * Copyright(c) 2010, Cedric Dugas
5
+ * http://www.position-absolute.com
6
+ *
7
+ * 2.0 Rewrite by Olivier Refalo
8
+ * http://www.crionics.com
9
+ *
10
+ * Form validation engine allowing custom regex rules to be added.
11
+ * Licensed under the MIT License
12
+ */
13
+ (function($) {
14
+
15
+ "use strict";
16
+
17
+ var methods = {
18
+
19
+ /**
20
+ * Kind of the constructor, called before any action
21
+ * @param {Map} user options
22
+ */
23
+ init: function(options) {
24
+ var form = this;
25
+ if (!form.data('jqv') || form.data('jqv') == null ) {
26
+ options = methods._saveOptions(form, options);
27
+ // bind all formError elements to close on click
28
+ $(document).on("click", ".formError", function() {
29
+ $(this).fadeOut(150, function() {
30
+ // remove prompt once invisible
31
+ $(this).closest('.formError').remove();
32
+ });
33
+ });
34
+ }
35
+ return this;
36
+ },
37
+ /**
38
+ * Attachs jQuery.validationEngine to form.submit and field.blur events
39
+ * Takes an optional params: a list of options
40
+ * ie. jQuery("#formID1").validationEngine('attach', {promptPosition : "centerRight"});
41
+ */
42
+ attach: function(userOptions) {
43
+
44
+ var form = this;
45
+ var options;
46
+
47
+ if(userOptions)
48
+ options = methods._saveOptions(form, userOptions);
49
+ else
50
+ options = form.data('jqv');
51
+
52
+ options.validateAttribute = (form.find("[data-validation-engine*=validate]").length) ? "data-validation-engine" : "class";
53
+ if (options.binded) {
54
+
55
+ // delegate fields
56
+ form.on(options.validationEventTrigger, "["+options.validateAttribute+"*=validate]:not([type=checkbox]):not([type=radio]):not(.datepicker)", methods._onFieldEvent);
57
+ form.on("click", "["+options.validateAttribute+"*=validate][type=checkbox],["+options.validateAttribute+"*=validate][type=radio]", methods._onFieldEvent);
58
+ form.on(options.validationEventTrigger,"["+options.validateAttribute+"*=validate][class*=datepicker]", {"delay": 300}, methods._onFieldEvent);
59
+ }
60
+ if (options.autoPositionUpdate) {
61
+ $(window).bind("resize", {
62
+ "noAnimation": true,
63
+ "formElem": form
64
+ }, methods.updatePromptsPosition);
65
+ }
66
+ form.on("click","a[data-validation-engine-skip], a[class*='validate-skip'], button[data-validation-engine-skip], button[class*='validate-skip'], input[data-validation-engine-skip], input[class*='validate-skip']", methods._submitButtonClick);
67
+ form.removeData('jqv_submitButton');
68
+
69
+ // bind form.submit
70
+ form.on("submit", methods._onSubmitEvent);
71
+ return this;
72
+ },
73
+ /**
74
+ * Unregisters any bindings that may point to jQuery.validaitonEngine
75
+ */
76
+ detach: function() {
77
+
78
+ var form = this;
79
+ var options = form.data('jqv');
80
+
81
+ // unbind fields
82
+ form.off(options.validationEventTrigger, "["+options.validateAttribute+"*=validate]:not([type=checkbox]):not([type=radio]):not(.datepicker)", methods._onFieldEvent);
83
+ form.off("click", "["+options.validateAttribute+"*=validate][type=checkbox],["+options.validateAttribute+"*=validate][type=radio]", methods._onFieldEvent);
84
+ form.off(options.validationEventTrigger,"["+options.validateAttribute+"*=validate][class*=datepicker]", methods._onFieldEvent);
85
+
86
+ // unbind form.submit
87
+ form.off("submit", methods._onSubmitEvent);
88
+ form.removeData('jqv');
89
+
90
+ form.off("click", "a[data-validation-engine-skip], a[class*='validate-skip'], button[data-validation-engine-skip], button[class*='validate-skip'], input[data-validation-engine-skip], input[class*='validate-skip']", methods._submitButtonClick);
91
+ form.removeData('jqv_submitButton');
92
+
93
+ if (options.autoPositionUpdate)
94
+ $(window).off("resize", methods.updatePromptsPosition);
95
+
96
+ return this;
97
+ },
98
+ /**
99
+ * Validates either a form or a list of fields, shows prompts accordingly.
100
+ * Note: There is no ajax form validation with this method, only field ajax validation are evaluated
101
+ *
102
+ * @return true if the form validates, false if it fails
103
+ */
104
+ validate: function(userOptions) {
105
+ var element = $(this);
106
+ var valid = null;
107
+ var options;
108
+
109
+ if (element.is("form") || element.hasClass("validationEngineContainer")) {
110
+ if (element.hasClass('validating')) {
111
+ // form is already validating.
112
+ // Should abort old validation and start new one. I don't know how to implement it.
113
+ return false;
114
+ } else {
115
+ element.addClass('validating');
116
+ if(userOptions)
117
+ options = methods._saveOptions(element, userOptions);
118
+ else
119
+ options = element.data('jqv');
120
+ var valid = methods._validateFields(this);
121
+
122
+ // If the form doesn't validate, clear the 'validating' class before the user has a chance to submit again
123
+ setTimeout(function(){
124
+ element.removeClass('validating');
125
+ }, 100);
126
+ if (valid && options.onSuccess) {
127
+ options.onSuccess();
128
+ } else if (!valid && options.onFailure) {
129
+ options.onFailure();
130
+ }
131
+ }
132
+ } else if (element.is('form') || element.hasClass('validationEngineContainer')) {
133
+ element.removeClass('validating');
134
+ } else {
135
+ // field validation
136
+ var form = element.closest('form, .validationEngineContainer');
137
+ options = (form.data('jqv')) ? form.data('jqv') : $.validationEngine.defaults;
138
+ valid = methods._validateField(element, options);
139
+
140
+ if (valid && options.onFieldSuccess)
141
+ options.onFieldSuccess();
142
+ else if (options.onFieldFailure && options.InvalidFields.length > 0) {
143
+ options.onFieldFailure();
144
+ }
145
+
146
+ return !valid;
147
+ }
148
+ if(options.onValidationComplete) {
149
+ // !! ensures that an undefined return is interpreted as return false but allows a onValidationComplete() to possibly return true and have form continue processing
150
+ return !!options.onValidationComplete(form, valid);
151
+ }
152
+ return valid;
153
+ },
154
+ /**
155
+ * Redraw prompts position, useful when you change the DOM state when validating
156
+ */
157
+ updatePromptsPosition: function(event) {
158
+
159
+ if (event && this == window) {
160
+ var form = event.data.formElem;
161
+ var noAnimation = event.data.noAnimation;
162
+ }
163
+ else
164
+ var form = $(this.closest('form, .validationEngineContainer'));
165
+
166
+ var options = form.data('jqv');
167
+ // No option, take default one
168
+ if (!options)
169
+ options = methods._saveOptions(form, options);
170
+ form.find('['+options.validateAttribute+'*=validate]').not(":disabled").each(function(){
171
+ var field = $(this);
172
+ if (options.prettySelect && field.is(":hidden"))
173
+ field = form.find("#" + options.usePrefix + field.attr('id') + options.useSuffix);
174
+ var prompt = methods._getPrompt(field);
175
+ var promptText = $(prompt).find(".formErrorContent").html();
176
+
177
+ if(prompt)
178
+ methods._updatePrompt(field, $(prompt), promptText, undefined, false, options, noAnimation);
179
+ });
180
+ return this;
181
+ },
182
+ /**
183
+ * Displays a prompt on a element.
184
+ * Note that the element needs an id!
185
+ *
186
+ * @param {String} promptText html text to display type
187
+ * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
188
+ * @param {String} possible values topLeft, topRight, bottomLeft, centerRight, bottomRight
189
+ */
190
+ showPrompt: function(promptText, type, promptPosition, showArrow) {
191
+ var form = this.closest('form, .validationEngineContainer');
192
+ var options = form.data('jqv');
193
+ // No option, take default one
194
+ if(!options)
195
+ options = methods._saveOptions(this, options);
196
+ if(promptPosition)
197
+ options.promptPosition=promptPosition;
198
+ options.showArrow = showArrow==true;
199
+
200
+ methods._showPrompt(this, promptText, type, false, options);
201
+ return this;
202
+ },
203
+ /**
204
+ * Closes form error prompts, CAN be invidual
205
+ */
206
+ hide: function() {
207
+ var form = $(this).closest('form, .validationEngineContainer');
208
+ var options = form.data('jqv');
209
+ // No option, take default one
210
+ if (!options)
211
+ options = methods._saveOptions(form, options);
212
+ var fadeDuration = (options && options.fadeDuration) ? options.fadeDuration : 0.3;
213
+ var closingtag;
214
+
215
+ if(form.is("form") || form.hasClass("validationEngineContainer")) {
216
+ closingtag = "parentForm"+methods._getClassName($(form).attr("id"));
217
+ } else {
218
+ closingtag = methods._getClassName($(form).attr("id")) +"formError";
219
+ }
220
+ $('.'+closingtag).fadeTo(fadeDuration, 0, function() {
221
+ $(this).closest('.formError').remove();
222
+ });
223
+ return this;
224
+ },
225
+ /**
226
+ * Closes all error prompts on the page
227
+ */
228
+ hideAll: function() {
229
+ var form = this;
230
+ var options = form.data('jqv');
231
+ var duration = options ? options.fadeDuration:300;
232
+ $('.formError').fadeTo(duration, 0, function() {
233
+ $(this).closest('.formError').remove();
234
+ });
235
+ return this;
236
+ },
237
+ /**
238
+ * Typically called when user exists a field using tab or a mouse click, triggers a field
239
+ * validation
240
+ */
241
+ _onFieldEvent: function(event) {
242
+ var field = $(this);
243
+ var form = field.closest('form, .validationEngineContainer');
244
+ var options = form.data('jqv');
245
+ // No option, take default one
246
+ if (!options)
247
+ options = methods._saveOptions(form, options);
248
+ options.eventTrigger = "field";
249
+
250
+ if (options.notEmpty == true){
251
+
252
+ if(field.val().length > 0){
253
+ // validate the current field
254
+ window.setTimeout(function() {
255
+ methods._validateField(field, options);
256
+ }, (event.data) ? event.data.delay : 0);
257
+
258
+ }
259
+
260
+ }else{
261
+
262
+ // validate the current field
263
+ window.setTimeout(function() {
264
+ methods._validateField(field, options);
265
+ }, (event.data) ? event.data.delay : 0);
266
+
267
+ }
268
+
269
+
270
+
271
+
272
+ },
273
+ /**
274
+ * Called when the form is submited, shows prompts accordingly
275
+ *
276
+ * @param {jqObject}
277
+ * form
278
+ * @return false if form submission needs to be cancelled
279
+ */
280
+ _onSubmitEvent: function() {
281
+ var form = $(this);
282
+ var options = form.data('jqv');
283
+
284
+ //check if it is trigger from skipped button
285
+ if (form.data("jqv_submitButton")){
286
+ var submitButton = $("#" + form.data("jqv_submitButton"));
287
+ if (submitButton){
288
+ if (submitButton.length > 0){
289
+ if (submitButton.hasClass("validate-skip") || submitButton.attr("data-validation-engine-skip") == "true")
290
+ return true;
291
+ }
292
+ }
293
+ }
294
+
295
+ options.eventTrigger = "submit";
296
+
297
+ // validate each field
298
+ // (- skip field ajax validation, not necessary IF we will perform an ajax form validation)
299
+ var r=methods._validateFields(form);
300
+
301
+ if (r && options.ajaxFormValidation) {
302
+ methods._validateFormWithAjax(form, options);
303
+ // cancel form auto-submission - process with async call onAjaxFormComplete
304
+ return false;
305
+ }
306
+
307
+ if(options.onValidationComplete) {
308
+ // !! ensures that an undefined return is interpreted as return false but allows a onValidationComplete() to possibly return true and have form continue processing
309
+ return !!options.onValidationComplete(form, r);
310
+ }
311
+ return r;
312
+ },
313
+ /**
314
+ * Return true if the ajax field validations passed so far
315
+ * @param {Object} options
316
+ * @return true, is all ajax validation passed so far (remember ajax is async)
317
+ */
318
+ _checkAjaxStatus: function(options) {
319
+ var status = true;
320
+ $.each(options.ajaxValidCache, function(key, value) {
321
+ if (!value) {
322
+ status = false;
323
+ // break the each
324
+ return false;
325
+ }
326
+ });
327
+ return status;
328
+ },
329
+
330
+ /**
331
+ * Return true if the ajax field is validated
332
+ * @param {String} fieldid
333
+ * @param {Object} options
334
+ * @return true, if validation passed, false if false or doesn't exist
335
+ */
336
+ _checkAjaxFieldStatus: function(fieldid, options) {
337
+ return options.ajaxValidCache[fieldid] == true;
338
+ },
339
+ /**
340
+ * Validates form fields, shows prompts accordingly
341
+ *
342
+ * @param {jqObject}
343
+ * form
344
+ * @param {skipAjaxFieldValidation}
345
+ * boolean - when set to true, ajax field validation is skipped, typically used when the submit button is clicked
346
+ *
347
+ * @return true if form is valid, false if not, undefined if ajax form validation is done
348
+ */
349
+ _validateFields: function(form) {
350
+ var options = form.data('jqv');
351
+
352
+ // this variable is set to true if an error is found
353
+ var errorFound = false;
354
+
355
+ // Trigger hook, start validation
356
+ form.trigger("jqv.form.validating");
357
+ // first, evaluate status of non ajax fields
358
+ var first_err=null;
359
+ form.find('['+options.validateAttribute+'*=validate]').not(":disabled").each( function() {
360
+ var field = $(this);
361
+ var names = [];
362
+ if ($.inArray(field.attr('name'), names) < 0) {
363
+ errorFound |= methods._validateField(field, options);
364
+ if (errorFound && first_err==null)
365
+ if (field.is(":hidden") && options.prettySelect)
366
+ first_err = field = form.find("#" + options.usePrefix + methods._jqSelector(field.attr('id')) + options.useSuffix);
367
+ else {
368
+
369
+ //Check if we need to adjust what element to show the prompt on
370
+ //and and such scroll to instead
371
+ if(field.data('jqv-prompt-at') instanceof jQuery ){
372
+ field = field.data('jqv-prompt-at');
373
+ } else if(field.data('jqv-prompt-at')) {
374
+ field = $(field.data('jqv-prompt-at'));
375
+ }
376
+ first_err=field;
377
+ }
378
+ if (options.doNotShowAllErrosOnSubmit)
379
+ return false;
380
+ names.push(field.attr('name'));
381
+
382
+ //if option set, stop checking validation rules after one error is found
383
+ if(options.showOneMessage == true && errorFound){
384
+ return false;
385
+ }
386
+ }
387
+ });
388
+
389
+ // second, check to see if all ajax calls completed ok
390
+ // errorFound |= !methods._checkAjaxStatus(options);
391
+
392
+ // third, check status and scroll the container accordingly
393
+ form.trigger("jqv.form.result", [errorFound]);
394
+
395
+ if (errorFound) {
396
+ if (options.scroll) {
397
+ var destination=first_err.offset().top;
398
+ var fixleft = first_err.offset().left;
399
+
400
+ //prompt positioning adjustment support. Usage: positionType:Xshift,Yshift (for ex.: bottomLeft:+20 or bottomLeft:-20,+10)
401
+ var positionType=options.promptPosition;
402
+ if (typeof(positionType)=='string' && positionType.indexOf(":")!=-1)
403
+ positionType=positionType.substring(0,positionType.indexOf(":"));
404
+
405
+ if (positionType!="bottomRight" && positionType!="bottomLeft") {
406
+ var prompt_err= methods._getPrompt(first_err);
407
+ if (prompt_err) {
408
+ destination=prompt_err.offset().top;
409
+ }
410
+ }
411
+
412
+ // Offset the amount the page scrolls by an amount in px to accomodate fixed elements at top of page
413
+ if (options.scrollOffset) {
414
+ destination -= options.scrollOffset;
415
+ }
416
+
417
+ // get the position of the first error, there should be at least one, no need to check this
418
+ //var destination = form.find(".formError:not('.greenPopup'):first").offset().top;
419
+ if (options.isOverflown) {
420
+ var overflowDIV = $(options.overflownDIV);
421
+ if(!overflowDIV.length) return false;
422
+ var scrollContainerScroll = overflowDIV.scrollTop();
423
+ var scrollContainerPos = -parseInt(overflowDIV.offset().top);
424
+
425
+ destination += scrollContainerScroll + scrollContainerPos - 5;
426
+ var scrollContainer = $(options.overflownDIV).filter(":not(:animated)");
427
+
428
+ scrollContainer.animate({ scrollTop: destination }, 1100, function(){
429
+ if(options.focusFirstField) first_err.focus();
430
+ });
431
+
432
+ } else {
433
+ $("html, body").animate({
434
+ scrollTop: destination
435
+ }, 1100, function(){
436
+ if(options.focusFirstField) first_err.focus();
437
+ });
438
+ $("html, body").animate({scrollLeft: fixleft},1100)
439
+ }
440
+
441
+ } else if(options.focusFirstField)
442
+ first_err.focus();
443
+ return false;
444
+ }
445
+ return true;
446
+ },
447
+ /**
448
+ * This method is called to perform an ajax form validation.
449
+ * During this process all the (field, value) pairs are sent to the server which returns a list of invalid fields or true
450
+ *
451
+ * @param {jqObject} form
452
+ * @param {Map} options
453
+ */
454
+ _validateFormWithAjax: function(form, options) {
455
+
456
+ var data = form.serialize();
457
+ var type = (options.ajaxFormValidationMethod) ? options.ajaxFormValidationMethod : "GET";
458
+ var url = (options.ajaxFormValidationURL) ? options.ajaxFormValidationURL : form.attr("action");
459
+ var dataType = (options.dataType) ? options.dataType : "json";
460
+ $.ajax({
461
+ type: type,
462
+ url: url,
463
+ cache: false,
464
+ dataType: dataType,
465
+ data: data,
466
+ form: form,
467
+ methods: methods,
468
+ options: options,
469
+ beforeSend: function() {
470
+ return options.onBeforeAjaxFormValidation(form, options);
471
+ },
472
+ error: function(data, transport) {
473
+ if (options.onFailure) {
474
+ options.onFailure(data, transport);
475
+ } else {
476
+ methods._ajaxError(data, transport);
477
+ }
478
+ },
479
+ success: function(json) {
480
+ if ((dataType == "json") && (json !== true)) {
481
+ // getting to this case doesn't necessary means that the form is invalid
482
+ // the server may return green or closing prompt actions
483
+ // this flag helps figuring it out
484
+ var errorInForm=false;
485
+ for (var i = 0; i < json.length; i++) {
486
+ var value = json[i];
487
+
488
+ var errorFieldId = value[0];
489
+ var errorField = $($("#" + errorFieldId)[0]);
490
+
491
+ // make sure we found the element
492
+ if (errorField.length == 1) {
493
+
494
+ // promptText or selector
495
+ var msg = value[2];
496
+ // if the field is valid
497
+ if (value[1] == true) {
498
+
499
+ if (msg == "" || !msg){
500
+ // if for some reason, status==true and error="", just close the prompt
501
+ methods._closePrompt(errorField);
502
+ } else {
503
+ // the field is valid, but we are displaying a green prompt
504
+ if (options.allrules[msg]) {
505
+ var txt = options.allrules[msg].alertTextOk;
506
+ if (txt)
507
+ msg = txt;
508
+ }
509
+ if (options.showPrompts) methods._showPrompt(errorField, msg, "pass", false, options, true);
510
+ }
511
+ } else {
512
+ // the field is invalid, show the red error prompt
513
+ errorInForm|=true;
514
+ if (options.allrules[msg]) {
515
+ var txt = options.allrules[msg].alertText;
516
+ if (txt)
517
+ msg = txt;
518
+ }
519
+ if(options.showPrompts) methods._showPrompt(errorField, msg, "", false, options, true);
520
+ }
521
+ }
522
+ }
523
+ options.onAjaxFormComplete(!errorInForm, form, json, options);
524
+ } else
525
+ options.onAjaxFormComplete(true, form, json, options);
526
+
527
+ }
528
+ });
529
+
530
+ },
531
+ /**
532
+ * Validates field, shows prompts accordingly
533
+ *
534
+ * @param {jqObject}
535
+ * field
536
+ * @param {Array[String]}
537
+ * field's validation rules
538
+ * @param {Map}
539
+ * user options
540
+ * @return false if field is valid (It is inversed for *fields*, it return false on validate and true on errors.)
541
+ */
542
+ _validateField: function(field, options, skipAjaxValidation) {
543
+ if (!field.attr("id")) {
544
+ field.attr("id", "form-validation-field-" + $.validationEngine.fieldIdCounter);
545
+ ++$.validationEngine.fieldIdCounter;
546
+ }
547
+
548
+ if(field.hasClass(options.ignoreFieldsWithClass))
549
+ return false;
550
+
551
+ if (!options.validateNonVisibleFields && (field.is(":hidden") && !options.prettySelect || field.parent().is(":hidden")))
552
+ return false;
553
+
554
+ var rulesParsing = field.attr(options.validateAttribute);
555
+ var getRules = /validate\[(.*)\]/.exec(rulesParsing);
556
+
557
+ if (!getRules)
558
+ return false;
559
+ var str = getRules[1];
560
+ var rules = str.split(/\[|,|\]/);
561
+
562
+ // true if we ran the ajax validation, tells the logic to stop messing with prompts
563
+ var isAjaxValidator = false;
564
+ var fieldName = field.attr("name");
565
+ var promptText = "";
566
+ var promptType = "";
567
+ var required = false;
568
+ var limitErrors = false;
569
+ options.isError = false;
570
+ options.showArrow = options.showArrow ==true;
571
+
572
+ // If the programmer wants to limit the amount of error messages per field,
573
+ if (options.maxErrorsPerField > 0) {
574
+ limitErrors = true;
575
+ }
576
+
577
+ var form = $(field.closest("form, .validationEngineContainer"));
578
+ // Fix for adding spaces in the rules
579
+ for (var i = 0; i < rules.length; i++) {
580
+ rules[i] = rules[i].toString().replace(" ", "");//.toString to worked on IE8
581
+ // Remove any parsing errors
582
+ if (rules[i] === '') {
583
+ delete rules[i];
584
+ }
585
+ }
586
+
587
+ for (var i = 0, field_errors = 0; i < rules.length; i++) {
588
+
589
+ // If we are limiting errors, and have hit the max, break
590
+ if (limitErrors && field_errors >= options.maxErrorsPerField) {
591
+ // If we haven't hit a required yet, check to see if there is one in the validation rules for this
592
+ // field and that it's index is greater or equal to our current index
593
+ if (!required) {
594
+ var have_required = $.inArray('required', rules);
595
+ required = (have_required != -1 && have_required >= i);
596
+ }
597
+ break;
598
+ }
599
+
600
+
601
+ var errorMsg = undefined;
602
+ switch (rules[i]) {
603
+
604
+ case "required":
605
+ required = true;
606
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._required);
607
+ break;
608
+ case "custom":
609
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._custom);
610
+ break;
611
+ case "groupRequired":
612
+ // Check is its the first of group, if not, reload validation with first field
613
+ // AND continue normal validation on present field
614
+ var classGroup = "["+options.validateAttribute+"*=" +rules[i + 1] +"]";
615
+ var firstOfGroup = form.find(classGroup).eq(0);
616
+ if(firstOfGroup[0] != field[0]){
617
+
618
+ methods._validateField(firstOfGroup, options, skipAjaxValidation);
619
+ options.showArrow = true;
620
+
621
+ }
622
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._groupRequired);
623
+ if(errorMsg) required = true;
624
+ options.showArrow = false;
625
+ break;
626
+ case "ajax":
627
+ // AJAX defaults to returning it's loading message
628
+ errorMsg = methods._ajax(field, rules, i, options);
629
+ if (errorMsg) {
630
+ promptType = "load";
631
+ }
632
+ break;
633
+ case "minSize":
634
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._minSize);
635
+ break;
636
+ case "maxSize":
637
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._maxSize);
638
+ break;
639
+ case "min":
640
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._min);
641
+ break;
642
+ case "max":
643
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._max);
644
+ break;
645
+ case "past":
646
+ errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._past);
647
+ break;
648
+ case "future":
649
+ errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._future);
650
+ break;
651
+ case "dateRange":
652
+ var classGroup = "["+options.validateAttribute+"*=" + rules[i + 1] + "]";
653
+ options.firstOfGroup = form.find(classGroup).eq(0);
654
+ options.secondOfGroup = form.find(classGroup).eq(1);
655
+
656
+ //if one entry out of the pair has value then proceed to run through validation
657
+ if (options.firstOfGroup[0].value || options.secondOfGroup[0].value) {
658
+ errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._dateRange);
659
+ }
660
+ if (errorMsg) required = true;
661
+ options.showArrow = false;
662
+ break;
663
+
664
+ case "dateTimeRange":
665
+ var classGroup = "["+options.validateAttribute+"*=" + rules[i + 1] + "]";
666
+ options.firstOfGroup = form.find(classGroup).eq(0);
667
+ options.secondOfGroup = form.find(classGroup).eq(1);
668
+
669
+ //if one entry out of the pair has value then proceed to run through validation
670
+ if (options.firstOfGroup[0].value || options.secondOfGroup[0].value) {
671
+ errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._dateTimeRange);
672
+ }
673
+ if (errorMsg) required = true;
674
+ options.showArrow = false;
675
+ break;
676
+ case "maxCheckbox":
677
+ field = $(form.find("input[name='" + fieldName + "']"));
678
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._maxCheckbox);
679
+ break;
680
+ case "minCheckbox":
681
+ field = $(form.find("input[name='" + fieldName + "']"));
682
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._minCheckbox);
683
+ break;
684
+ case "equals":
685
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._equals);
686
+ break;
687
+ case "funcCall":
688
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._funcCall);
689
+ break;
690
+ case "creditCard":
691
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._creditCard);
692
+ break;
693
+ case "condRequired":
694
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._condRequired);
695
+ if (errorMsg !== undefined) {
696
+ required = true;
697
+ }
698
+ break;
699
+ case "funcCallRequired":
700
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._funcCallRequired);
701
+ if (errorMsg !== undefined) {
702
+ required = true;
703
+ }
704
+ break;
705
+
706
+ default:
707
+ }
708
+
709
+ var end_validation = false;
710
+
711
+ // If we were passed back an message object, check what the status was to determine what to do
712
+ if (typeof errorMsg == "object") {
713
+ switch (errorMsg.status) {
714
+ case "_break":
715
+ end_validation = true;
716
+ break;
717
+ // If we have an error message, set errorMsg to the error message
718
+ case "_error":
719
+ errorMsg = errorMsg.message;
720
+ break;
721
+ // If we want to throw an error, but not show a prompt, return early with true
722
+ case "_error_no_prompt":
723
+ return true;
724
+ break;
725
+ // Anything else we continue on
726
+ default:
727
+ break;
728
+ }
729
+ }
730
+
731
+ //funcCallRequired, first in rules, and has error, skip anything else
732
+ if( i==0 && str.indexOf('funcCallRequired')==0 && errorMsg !== undefined ){
733
+ if(promptText != '') {
734
+ promptText += "<br/>";
735
+ }
736
+ promptText += errorMsg;
737
+ options.isError=true;
738
+ field_errors++;
739
+ end_validation=true;
740
+ }
741
+
742
+ // If it has been specified that validation should end now, break
743
+ if (end_validation) {
744
+ break;
745
+ }
746
+
747
+ // If we have a string, that means that we have an error, so add it to the error message.
748
+ if (typeof errorMsg == 'string') {
749
+ if(promptText != '') {
750
+ promptText += "<br/>";
751
+ }
752
+ promptText += errorMsg;
753
+ options.isError = true;
754
+ field_errors++;
755
+ }
756
+ }
757
+ // If the rules required is not added, an empty field is not validated
758
+ //the 3rd condition is added so that even empty password fields should be equal
759
+ //otherwise if one is filled and another left empty, the "equal" condition would fail
760
+ //which does not make any sense
761
+ if(!required && !(field.val()) && field.val().length < 1 && $.inArray('equals', rules) < 0) options.isError = false;
762
+
763
+ // Hack for radio/checkbox group button, the validation go into the
764
+ // first radio/checkbox of the group
765
+ var fieldType = field.prop("type");
766
+ var positionType=field.data("promptPosition") || options.promptPosition;
767
+
768
+ if ((fieldType == "radio" || fieldType == "checkbox") && form.find("input[name='" + fieldName + "']").length > 1) {
769
+ if(positionType === 'inline') {
770
+ field = $(form.find("input[name='" + fieldName + "'][type!=hidden]:last"));
771
+ } else {
772
+ field = $(form.find("input[name='" + fieldName + "'][type!=hidden]:first"));
773
+ }
774
+ options.showArrow = options.showArrowOnRadioAndCheckbox;
775
+ }
776
+
777
+ if(field.is(":hidden") && options.prettySelect) {
778
+ field = form.find("#" + options.usePrefix + methods._jqSelector(field.attr('id')) + options.useSuffix);
779
+ }
780
+
781
+ if (options.isError && options.showPrompts){
782
+ methods._showPrompt(field, promptText, promptType, false, options);
783
+ }else{
784
+ if (!isAjaxValidator) methods._closePrompt(field);
785
+ }
786
+
787
+ if (!isAjaxValidator) {
788
+ field.trigger("jqv.field.result", [field, options.isError, promptText]);
789
+ }
790
+
791
+ /* Record error */
792
+ var errindex = $.inArray(field[0], options.InvalidFields);
793
+ if (errindex == -1) {
794
+ if (options.isError)
795
+ options.InvalidFields.push(field[0]);
796
+ } else if (!options.isError) {
797
+ options.InvalidFields.splice(errindex, 1);
798
+ }
799
+
800
+ methods._handleStatusCssClasses(field, options);
801
+
802
+ /* run callback function for each field */
803
+ if (options.isError && options.onFieldFailure)
804
+ options.onFieldFailure(field);
805
+
806
+ if (!options.isError && options.onFieldSuccess)
807
+ options.onFieldSuccess(field);
808
+
809
+ return options.isError;
810
+ },
811
+ /**
812
+ * Handling css classes of fields indicating result of validation
813
+ *
814
+ * @param {jqObject}
815
+ * field
816
+ * @param {Array[String]}
817
+ * field's validation rules
818
+ * @private
819
+ */
820
+ _handleStatusCssClasses: function(field, options) {
821
+ /* remove all classes */
822
+ if(options.addSuccessCssClassToField)
823
+ field.removeClass(options.addSuccessCssClassToField);
824
+
825
+ if(options.addFailureCssClassToField)
826
+ field.removeClass(options.addFailureCssClassToField);
827
+
828
+ /* Add classes */
829
+ if (options.addSuccessCssClassToField && !options.isError)
830
+ field.addClass(options.addSuccessCssClassToField);
831
+
832
+ if (options.addFailureCssClassToField && options.isError)
833
+ field.addClass(options.addFailureCssClassToField);
834
+ },
835
+
836
+ /********************
837
+ * _getErrorMessage
838
+ *
839
+ * @param form
840
+ * @param field
841
+ * @param rule
842
+ * @param rules
843
+ * @param i
844
+ * @param options
845
+ * @param originalValidationMethod
846
+ * @return {*}
847
+ * @private
848
+ */
849
+ _getErrorMessage:function (form, field, rule, rules, i, options, originalValidationMethod) {
850
+ // If we are using the custon validation type, build the index for the rule.
851
+ // Otherwise if we are doing a function call, make the call and return the object
852
+ // that is passed back.
853
+ var rule_index = jQuery.inArray(rule, rules);
854
+ if (rule === "custom" || rule === "funcCall" || rule === "funcCallRequired") {
855
+ var custom_validation_type = rules[rule_index + 1];
856
+ rule = rule + "[" + custom_validation_type + "]";
857
+ // Delete the rule from the rules array so that it doesn't try to call the
858
+ // same rule over again
859
+ delete(rules[rule_index]);
860
+ }
861
+ // Change the rule to the composite rule, if it was different from the original
862
+ var alteredRule = rule;
863
+
864
+
865
+ var element_classes = (field.attr("data-validation-engine")) ? field.attr("data-validation-engine") : field.attr("class");
866
+ var element_classes_array = element_classes.split(" ");
867
+
868
+ // Call the original validation method. If we are dealing with dates or checkboxes, also pass the form
869
+ var errorMsg;
870
+ if (rule == "future" || rule == "past" || rule == "maxCheckbox" || rule == "minCheckbox") {
871
+ errorMsg = originalValidationMethod(form, field, rules, i, options);
872
+ } else {
873
+ errorMsg = originalValidationMethod(field, rules, i, options);
874
+ }
875
+
876
+ // If the original validation method returned an error and we have a custom error message,
877
+ // return the custom message instead. Otherwise return the original error message.
878
+ if (errorMsg != undefined) {
879
+ var custom_message = methods._getCustomErrorMessage($(field), element_classes_array, alteredRule, options);
880
+ if (custom_message) errorMsg = custom_message;
881
+ }
882
+ return errorMsg;
883
+
884
+ },
885
+ _getCustomErrorMessage:function (field, classes, rule, options) {
886
+ var custom_message = false;
887
+ var validityProp = /^custom\[.*\]$/.test(rule) ? methods._validityProp["custom"] : methods._validityProp[rule];
888
+ // If there is a validityProp for this rule, check to see if the field has an attribute for it
889
+ if (validityProp != undefined) {
890
+ custom_message = field.attr("data-errormessage-"+validityProp);
891
+ // If there was an error message for it, return the message
892
+ if (custom_message != undefined)
893
+ return custom_message;
894
+ }
895
+ custom_message = field.attr("data-errormessage");
896
+ // If there is an inline custom error message, return it
897
+ if (custom_message != undefined)
898
+ return custom_message;
899
+ var id = '#' + field.attr("id");
900
+ // If we have custom messages for the element's id, get the message for the rule from the id.
901
+ // Otherwise, if we have custom messages for the element's classes, use the first class message we find instead.
902
+ if (typeof options.custom_error_messages[id] != "undefined" &&
903
+ typeof options.custom_error_messages[id][rule] != "undefined" ) {
904
+ custom_message = options.custom_error_messages[id][rule]['message'];
905
+ } else if (classes.length > 0) {
906
+ for (var i = 0; i < classes.length && classes.length > 0; i++) {
907
+ var element_class = "." + classes[i];
908
+ if (typeof options.custom_error_messages[element_class] != "undefined" &&
909
+ typeof options.custom_error_messages[element_class][rule] != "undefined") {
910
+ custom_message = options.custom_error_messages[element_class][rule]['message'];
911
+ break;
912
+ }
913
+ }
914
+ }
915
+ if (!custom_message &&
916
+ typeof options.custom_error_messages[rule] != "undefined" &&
917
+ typeof options.custom_error_messages[rule]['message'] != "undefined"){
918
+ custom_message = options.custom_error_messages[rule]['message'];
919
+ }
920
+ return custom_message;
921
+ },
922
+ _validityProp: {
923
+ "required": "value-missing",
924
+ "custom": "custom-error",
925
+ "groupRequired": "value-missing",
926
+ "ajax": "custom-error",
927
+ "minSize": "range-underflow",
928
+ "maxSize": "range-overflow",
929
+ "min": "range-underflow",
930
+ "max": "range-overflow",
931
+ "past": "type-mismatch",
932
+ "future": "type-mismatch",
933
+ "dateRange": "type-mismatch",
934
+ "dateTimeRange": "type-mismatch",
935
+ "maxCheckbox": "range-overflow",
936
+ "minCheckbox": "range-underflow",
937
+ "equals": "pattern-mismatch",
938
+ "funcCall": "custom-error",
939
+ "funcCallRequired": "custom-error",
940
+ "creditCard": "pattern-mismatch",
941
+ "condRequired": "value-missing"
942
+ },
943
+ /**
944
+ * Required validation
945
+ *
946
+ * @param {jqObject} field
947
+ * @param {Array[String]} rules
948
+ * @param {int} i rules index
949
+ * @param {Map}
950
+ * user options
951
+ * @param {bool} condRequired flag when method is used for internal purpose in condRequired check
952
+ * @return an error string if validation failed
953
+ */
954
+ _required: function(field, rules, i, options, condRequired) {
955
+ switch (field.prop("type")) {
956
+ case "radio":
957
+ case "checkbox":
958
+ // new validation style to only check dependent field
959
+ if (condRequired) {
960
+ if (!field.prop('checked')) {
961
+ return options.allrules[rules[i]].alertTextCheckboxMultiple;
962
+ }
963
+ break;
964
+ }
965
+ // old validation style
966
+ var form = field.closest("form, .validationEngineContainer");
967
+ var name = field.attr("name");
968
+ if (form.find("input[name='" + name + "']:checked").length == 0) {
969
+ if (form.find("input[name='" + name + "']:visible").length == 1)
970
+ return options.allrules[rules[i]].alertTextCheckboxe;
971
+ else
972
+ return options.allrules[rules[i]].alertTextCheckboxMultiple;
973
+ }
974
+ break;
975
+ case "text":
976
+ case "password":
977
+ case "textarea":
978
+ case "file":
979
+ case "select-one":
980
+ case "select-multiple":
981
+ default:
982
+ var field_val = $.trim( field.val() );
983
+ var dv_placeholder = $.trim( field.attr("data-validation-placeholder") );
984
+ var placeholder = $.trim( field.attr("placeholder") );
985
+ if (
986
+ ( !field_val )
987
+ || ( dv_placeholder && field_val == dv_placeholder )
988
+ || ( placeholder && field_val == placeholder )
989
+ ) {
990
+ return options.allrules[rules[i]].alertText;
991
+ }
992
+ break;
993
+ }
994
+ },
995
+ /**
996
+ * Validate that 1 from the group field is required
997
+ *
998
+ * @param {jqObject} field
999
+ * @param {Array[String]} rules
1000
+ * @param {int} i rules index
1001
+ * @param {Map}
1002
+ * user options
1003
+ * @return an error string if validation failed
1004
+ */
1005
+ _groupRequired: function(field, rules, i, options) {
1006
+ var classGroup = "["+options.validateAttribute+"*=" +rules[i + 1] +"]";
1007
+ var isValid = false;
1008
+ // Check all fields from the group
1009
+ field.closest("form, .validationEngineContainer").find(classGroup).each(function(){
1010
+ if(!methods._required($(this), rules, i, options)){
1011
+ isValid = true;
1012
+ return false;
1013
+ }
1014
+ });
1015
+
1016
+ if(!isValid) {
1017
+ return options.allrules[rules[i]].alertText;
1018
+ }
1019
+ },
1020
+ /**
1021
+ * Validate rules
1022
+ *
1023
+ * @param {jqObject} field
1024
+ * @param {Array[String]} rules
1025
+ * @param {int} i rules index
1026
+ * @param {Map}
1027
+ * user options
1028
+ * @return an error string if validation failed
1029
+ */
1030
+ _custom: function(field, rules, i, options) {
1031
+ var customRule = rules[i + 1];
1032
+ var rule = options.allrules[customRule];
1033
+ var fn;
1034
+ if(!rule) {
1035
+ alert("jqv:custom rule not found - "+customRule);
1036
+ return;
1037
+ }
1038
+
1039
+ if(rule["regex"]) {
1040
+ var ex=rule.regex;
1041
+ if(!ex) {
1042
+ alert("jqv:custom regex not found - "+customRule);
1043
+ return;
1044
+ }
1045
+ var pattern = new RegExp(ex);
1046
+
1047
+ if (!pattern.test(field.val())) return options.allrules[customRule].alertText;
1048
+
1049
+ } else if(rule["func"]) {
1050
+ fn = rule["func"];
1051
+
1052
+ if (typeof(fn) !== "function") {
1053
+ alert("jqv:custom parameter 'function' is no function - "+customRule);
1054
+ return;
1055
+ }
1056
+
1057
+ if (!fn(field, rules, i, options))
1058
+ return options.allrules[customRule].alertText;
1059
+ } else {
1060
+ alert("jqv:custom type not allowed "+customRule);
1061
+ return;
1062
+ }
1063
+ },
1064
+ /**
1065
+ * Validate custom function outside of the engine scope
1066
+ *
1067
+ * @param {jqObject} field
1068
+ * @param {Array[String]} rules
1069
+ * @param {int} i rules index
1070
+ * @param {Map}
1071
+ * user options
1072
+ * @return an error string if validation failed
1073
+ */
1074
+ _funcCall: function(field, rules, i, options) {
1075
+ var functionName = rules[i + 1];
1076
+ var fn;
1077
+ if(functionName.indexOf('.') >-1)
1078
+ {
1079
+ var namespaces = functionName.split('.');
1080
+ var scope = window;
1081
+ while(namespaces.length)
1082
+ {
1083
+ scope = scope[namespaces.shift()];
1084
+ }
1085
+ fn = scope;
1086
+ }
1087
+ else
1088
+ fn = window[functionName] || options.customFunctions[functionName];
1089
+ if (typeof(fn) == 'function')
1090
+ return fn(field, rules, i, options);
1091
+
1092
+ },
1093
+ _funcCallRequired: function(field, rules, i, options) {
1094
+ return methods._funcCall(field,rules,i,options);
1095
+ },
1096
+ /**
1097
+ * Field match
1098
+ *
1099
+ * @param {jqObject} field
1100
+ * @param {Array[String]} rules
1101
+ * @param {int} i rules index
1102
+ * @param {Map}
1103
+ * user options
1104
+ * @return an error string if validation failed
1105
+ */
1106
+ _equals: function(field, rules, i, options) {
1107
+ var equalsField = rules[i + 1];
1108
+
1109
+ if (field.val() != $("#" + equalsField).val())
1110
+ return options.allrules.equals.alertText;
1111
+ },
1112
+ /**
1113
+ * Check the maximum size (in characters)
1114
+ *
1115
+ * @param {jqObject} field
1116
+ * @param {Array[String]} rules
1117
+ * @param {int} i rules index
1118
+ * @param {Map}
1119
+ * user options
1120
+ * @return an error string if validation failed
1121
+ */
1122
+ _maxSize: function(field, rules, i, options) {
1123
+ var max = rules[i + 1];
1124
+ var len = field.val().length;
1125
+
1126
+ if (len > max) {
1127
+ var rule = options.allrules.maxSize;
1128
+ return rule.alertText + max + rule.alertText2;
1129
+ }
1130
+ },
1131
+ /**
1132
+ * Check the minimum size (in characters)
1133
+ *
1134
+ * @param {jqObject} field
1135
+ * @param {Array[String]} rules
1136
+ * @param {int} i rules index
1137
+ * @param {Map}
1138
+ * user options
1139
+ * @return an error string if validation failed
1140
+ */
1141
+ _minSize: function(field, rules, i, options) {
1142
+ var min = rules[i + 1];
1143
+ var len = field.val().length;
1144
+
1145
+ if (len < min) {
1146
+ var rule = options.allrules.minSize;
1147
+ return rule.alertText + min + rule.alertText2;
1148
+ }
1149
+ },
1150
+ /**
1151
+ * Check number minimum value
1152
+ *
1153
+ * @param {jqObject} field
1154
+ * @param {Array[String]} rules
1155
+ * @param {int} i rules index
1156
+ * @param {Map}
1157
+ * user options
1158
+ * @return an error string if validation failed
1159
+ */
1160
+ _min: function(field, rules, i, options) {
1161
+ var min = parseFloat(rules[i + 1]);
1162
+ var len = parseFloat(field.val());
1163
+
1164
+ if (len < min) {
1165
+ var rule = options.allrules.min;
1166
+ if (rule.alertText2) return rule.alertText + min + rule.alertText2;
1167
+ return rule.alertText + min;
1168
+ }
1169
+ },
1170
+ /**
1171
+ * Check number maximum value
1172
+ *
1173
+ * @param {jqObject} field
1174
+ * @param {Array[String]} rules
1175
+ * @param {int} i rules index
1176
+ * @param {Map}
1177
+ * user options
1178
+ * @return an error string if validation failed
1179
+ */
1180
+ _max: function(field, rules, i, options) {
1181
+ var max = parseFloat(rules[i + 1]);
1182
+ var len = parseFloat(field.val());
1183
+
1184
+ if (len >max ) {
1185
+ var rule = options.allrules.max;
1186
+ if (rule.alertText2) return rule.alertText + max + rule.alertText2;
1187
+ //orefalo: to review, also do the translations
1188
+ return rule.alertText + max;
1189
+ }
1190
+ },
1191
+ /**
1192
+ * Checks date is in the past
1193
+ *
1194
+ * @param {jqObject} field
1195
+ * @param {Array[String]} rules
1196
+ * @param {int} i rules index
1197
+ * @param {Map}
1198
+ * user options
1199
+ * @return an error string if validation failed
1200
+ */
1201
+ _past: function(form, field, rules, i, options) {
1202
+
1203
+ var p=rules[i + 1];
1204
+ var fieldAlt = $(form.find("*[name='" + p.replace(/^#+/, '') + "']"));
1205
+ var pdate;
1206
+
1207
+ if (p.toLowerCase() == "now") {
1208
+ pdate = new Date();
1209
+ } else if (undefined != fieldAlt.val()) {
1210
+ if (fieldAlt.is(":disabled"))
1211
+ return;
1212
+ pdate = methods._parseDate(fieldAlt.val());
1213
+ } else {
1214
+ pdate = methods._parseDate(p);
1215
+ }
1216
+ var vdate = methods._parseDate(field.val());
1217
+
1218
+ if (vdate > pdate ) {
1219
+ var rule = options.allrules.past;
1220
+ if (rule.alertText2) return rule.alertText + methods._dateToString(pdate) + rule.alertText2;
1221
+ return rule.alertText + methods._dateToString(pdate);
1222
+ }
1223
+ },
1224
+ /**
1225
+ * Checks date is in the future
1226
+ *
1227
+ * @param {jqObject} field
1228
+ * @param {Array[String]} rules
1229
+ * @param {int} i rules index
1230
+ * @param {Map}
1231
+ * user options
1232
+ * @return an error string if validation failed
1233
+ */
1234
+ _future: function(form, field, rules, i, options) {
1235
+
1236
+ var p=rules[i + 1];
1237
+ var fieldAlt = $(form.find("*[name='" + p.replace(/^#+/, '') + "']"));
1238
+ var pdate;
1239
+
1240
+ if (p.toLowerCase() == "now") {
1241
+ pdate = new Date();
1242
+ } else if (undefined != fieldAlt.val()) {
1243
+ if (fieldAlt.is(":disabled"))
1244
+ return;
1245
+ pdate = methods._parseDate(fieldAlt.val());
1246
+ } else {
1247
+ pdate = methods._parseDate(p);
1248
+ }
1249
+ var vdate = methods._parseDate(field.val());
1250
+
1251
+ if (vdate < pdate ) {
1252
+ var rule = options.allrules.future;
1253
+ if (rule.alertText2)
1254
+ return rule.alertText + methods._dateToString(pdate) + rule.alertText2;
1255
+ return rule.alertText + methods._dateToString(pdate);
1256
+ }
1257
+ },
1258
+ /**
1259
+ * Checks if valid date
1260
+ *
1261
+ * @param {string} date string
1262
+ * @return a bool based on determination of valid date
1263
+ */
1264
+ _isDate: function (value) {
1265
+ var dateRegEx = new RegExp(/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$|^(?:(?:(?:0?[13578]|1[02])(\/|-)31)|(?:(?:0?[1,3-9]|1[0-2])(\/|-)(?:29|30)))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^(?:(?:0?[1-9]|1[0-2])(\/|-)(?:0?[1-9]|1\d|2[0-8]))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^(0?2(\/|-)29)(\/|-)(?:(?:0[48]00|[13579][26]00|[2468][048]00)|(?:\d\d)?(?:0[48]|[2468][048]|[13579][26]))$/);
1266
+ return dateRegEx.test(value);
1267
+ },
1268
+ /**
1269
+ * Checks if valid date time
1270
+ *
1271
+ * @param {string} date string
1272
+ * @return a bool based on determination of valid date time
1273
+ */
1274
+ _isDateTime: function (value){
1275
+ var dateTimeRegEx = new RegExp(/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])\s+(1[012]|0?[1-9]){1}:(0?[1-5]|[0-6][0-9]){1}:(0?[0-6]|[0-6][0-9]){1}\s+(am|pm|AM|PM){1}$|^(?:(?:(?:0?[13578]|1[02])(\/|-)31)|(?:(?:0?[1,3-9]|1[0-2])(\/|-)(?:29|30)))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^((1[012]|0?[1-9]){1}\/(0?[1-9]|[12][0-9]|3[01]){1}\/\d{2,4}\s+(1[012]|0?[1-9]){1}:(0?[1-5]|[0-6][0-9]){1}:(0?[0-6]|[0-6][0-9]){1}\s+(am|pm|AM|PM){1})$/);
1276
+ return dateTimeRegEx.test(value);
1277
+ },
1278
+ //Checks if the start date is before the end date
1279
+ //returns true if end is later than start
1280
+ _dateCompare: function (start, end) {
1281
+ return (new Date(start.toString()) < new Date(end.toString()));
1282
+ },
1283
+ /**
1284
+ * Checks date range
1285
+ *
1286
+ * @param {jqObject} first field name
1287
+ * @param {jqObject} second field name
1288
+ * @return an error string if validation failed
1289
+ */
1290
+ _dateRange: function (field, rules, i, options) {
1291
+ //are not both populated
1292
+ if ((!options.firstOfGroup[0].value && options.secondOfGroup[0].value) || (options.firstOfGroup[0].value && !options.secondOfGroup[0].value)) {
1293
+ return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
1294
+ }
1295
+
1296
+ //are not both dates
1297
+ if (!methods._isDate(options.firstOfGroup[0].value) || !methods._isDate(options.secondOfGroup[0].value)) {
1298
+ return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
1299
+ }
1300
+
1301
+ //are both dates but range is off
1302
+ if (!methods._dateCompare(options.firstOfGroup[0].value, options.secondOfGroup[0].value)) {
1303
+ return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
1304
+ }
1305
+ },
1306
+ /**
1307
+ * Checks date time range
1308
+ *
1309
+ * @param {jqObject} first field name
1310
+ * @param {jqObject} second field name
1311
+ * @return an error string if validation failed
1312
+ */
1313
+ _dateTimeRange: function (field, rules, i, options) {
1314
+ //are not both populated
1315
+ if ((!options.firstOfGroup[0].value && options.secondOfGroup[0].value) || (options.firstOfGroup[0].value && !options.secondOfGroup[0].value)) {
1316
+ return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
1317
+ }
1318
+ //are not both dates
1319
+ if (!methods._isDateTime(options.firstOfGroup[0].value) || !methods._isDateTime(options.secondOfGroup[0].value)) {
1320
+ return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
1321
+ }
1322
+ //are both dates but range is off
1323
+ if (!methods._dateCompare(options.firstOfGroup[0].value, options.secondOfGroup[0].value)) {
1324
+ return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
1325
+ }
1326
+ },
1327
+ /**
1328
+ * Max number of checkbox selected
1329
+ *
1330
+ * @param {jqObject} field
1331
+ * @param {Array[String]} rules
1332
+ * @param {int} i rules index
1333
+ * @param {Map}
1334
+ * user options
1335
+ * @return an error string if validation failed
1336
+ */
1337
+ _maxCheckbox: function(form, field, rules, i, options) {
1338
+
1339
+ var nbCheck = rules[i + 1];
1340
+ var groupname = field.attr("name");
1341
+ var groupSize = form.find("input[name='" + groupname + "']:checked").length;
1342
+ if (groupSize > nbCheck) {
1343
+ options.showArrow = false;
1344
+ if (options.allrules.maxCheckbox.alertText2)
1345
+ return options.allrules.maxCheckbox.alertText + " " + nbCheck + " " + options.allrules.maxCheckbox.alertText2;
1346
+ return options.allrules.maxCheckbox.alertText;
1347
+ }
1348
+ },
1349
+ /**
1350
+ * Min number of checkbox selected
1351
+ *
1352
+ * @param {jqObject} field
1353
+ * @param {Array[String]} rules
1354
+ * @param {int} i rules index
1355
+ * @param {Map}
1356
+ * user options
1357
+ * @return an error string if validation failed
1358
+ */
1359
+ _minCheckbox: function(form, field, rules, i, options) {
1360
+
1361
+ var nbCheck = rules[i + 1];
1362
+ var groupname = field.attr("name");
1363
+ var groupSize = form.find("input[name='" + groupname + "']:checked").length;
1364
+ if (groupSize < nbCheck) {
1365
+ options.showArrow = false;
1366
+ return options.allrules.minCheckbox.alertText + " " + nbCheck + " " + options.allrules.minCheckbox.alertText2;
1367
+ }
1368
+ },
1369
+ /**
1370
+ * Checks that it is a valid credit card number according to the
1371
+ * Luhn checksum algorithm.
1372
+ *
1373
+ * @param {jqObject} field
1374
+ * @param {Array[String]} rules
1375
+ * @param {int} i rules index
1376
+ * @param {Map}
1377
+ * user options
1378
+ * @return an error string if validation failed
1379
+ */
1380
+ _creditCard: function(field, rules, i, options) {
1381
+ //spaces and dashes may be valid characters, but must be stripped to calculate the checksum.
1382
+ var valid = false, cardNumber = field.val().replace(/ +/g, '').replace(/-+/g, '');
1383
+
1384
+ var numDigits = cardNumber.length;
1385
+ if (numDigits >= 14 && numDigits <= 16 && parseInt(cardNumber) > 0) {
1386
+
1387
+ var sum = 0, i = numDigits - 1, pos = 1, digit, luhn = new String();
1388
+ do {
1389
+ digit = parseInt(cardNumber.charAt(i));
1390
+ luhn += (pos++ % 2 == 0) ? digit * 2 : digit;
1391
+ } while (--i >= 0)
1392
+
1393
+ for (i = 0; i < luhn.length; i++) {
1394
+ sum += parseInt(luhn.charAt(i));
1395
+ }
1396
+ valid = sum % 10 == 0;
1397
+ }
1398
+ if (!valid) return options.allrules.creditCard.alertText;
1399
+ },
1400
+ /**
1401
+ * Ajax field validation
1402
+ *
1403
+ * @param {jqObject} field
1404
+ * @param {Array[String]} rules
1405
+ * @param {int} i rules index
1406
+ * @param {Map}
1407
+ * user options
1408
+ * @return nothing! the ajax validator handles the prompts itself
1409
+ */
1410
+ _ajax: function(field, rules, i, options) {
1411
+
1412
+ var errorSelector = rules[i + 1];
1413
+ var rule = options.allrules[errorSelector];
1414
+ var extraData = rule.extraData;
1415
+ var extraDataDynamic = rule.extraDataDynamic;
1416
+ var data = {
1417
+ "fieldId" : field.attr("id"),
1418
+ "fieldValue" : field.val()
1419
+ };
1420
+
1421
+ if (typeof extraData === "object") {
1422
+ $.extend(data, extraData);
1423
+ } else if (typeof extraData === "string") {
1424
+ var tempData = extraData.split("&");
1425
+ for(var i = 0; i < tempData.length; i++) {
1426
+ var values = tempData[i].split("=");
1427
+ if (values[0] && values[0]) {
1428
+ data[values[0]] = values[1];
1429
+ }
1430
+ }
1431
+ }
1432
+
1433
+ if (extraDataDynamic) {
1434
+ var tmpData = [];
1435
+ var domIds = String(extraDataDynamic).split(",");
1436
+ for (var i = 0; i < domIds.length; i++) {
1437
+ var id = domIds[i];
1438
+ if ($(id).length) {
1439
+ var inputValue = field.closest("form, .validationEngineContainer").find(id).val();
1440
+ var keyValue = id.replace('#', '') + '=' + escape(inputValue);
1441
+ data[id.replace('#', '')] = inputValue;
1442
+ }
1443
+ }
1444
+ }
1445
+
1446
+ // If a field change event triggered this we want to clear the cache for this ID
1447
+ if (options.eventTrigger == "field") {
1448
+ delete(options.ajaxValidCache[field.attr("id")]);
1449
+ }
1450
+
1451
+ // If there is an error or if the the field is already validated, do not re-execute AJAX
1452
+ if (!options.isError && !methods._checkAjaxFieldStatus(field.attr("id"), options)) {
1453
+ $.ajax({
1454
+ type: options.ajaxFormValidationMethod,
1455
+ url: rule.url,
1456
+ cache: false,
1457
+ dataType: "json",
1458
+ data: data,
1459
+ field: field,
1460
+ rule: rule,
1461
+ methods: methods,
1462
+ options: options,
1463
+ beforeSend: function() {},
1464
+ error: function(data, transport) {
1465
+ if (options.onFailure) {
1466
+ options.onFailure(data, transport);
1467
+ } else {
1468
+ methods._ajaxError(data, transport);
1469
+ }
1470
+ },
1471
+ success: function(json) {
1472
+
1473
+ // asynchronously called on success, data is the json answer from the server
1474
+ var errorFieldId = json[0];
1475
+ //var errorField = $($("#" + errorFieldId)[0]);
1476
+ var errorField = $("#"+ errorFieldId).eq(0);
1477
+
1478
+ // make sure we found the element
1479
+ if (errorField.length == 1) {
1480
+ var status = json[1];
1481
+ // read the optional msg from the server
1482
+ var msg = json[2];
1483
+ if (!status) {
1484
+ // Houston we got a problem - display an red prompt
1485
+ options.ajaxValidCache[errorFieldId] = false;
1486
+ options.isError = true;
1487
+
1488
+ // resolve the msg prompt
1489
+ if(msg) {
1490
+ if (options.allrules[msg]) {
1491
+ var txt = options.allrules[msg].alertText;
1492
+ if (txt) {
1493
+ msg = txt;
1494
+ }
1495
+ }
1496
+ }
1497
+ else
1498
+ msg = rule.alertText;
1499
+
1500
+ if (options.showPrompts) methods._showPrompt(errorField, msg, "", true, options);
1501
+ } else {
1502
+ options.ajaxValidCache[errorFieldId] = true;
1503
+
1504
+ // resolves the msg prompt
1505
+ if(msg) {
1506
+ if (options.allrules[msg]) {
1507
+ var txt = options.allrules[msg].alertTextOk;
1508
+ if (txt) {
1509
+ msg = txt;
1510
+ }
1511
+ }
1512
+ }
1513
+ else
1514
+ msg = rule.alertTextOk;
1515
+
1516
+ if (options.showPrompts) {
1517
+ // see if we should display a green prompt
1518
+ if (msg)
1519
+ methods._showPrompt(errorField, msg, "pass", true, options);
1520
+ else
1521
+ methods._closePrompt(errorField);
1522
+ }
1523
+
1524
+ // If a submit form triggered this, we want to re-submit the form
1525
+ if (options.eventTrigger == "submit")
1526
+ field.closest("form").submit();
1527
+ }
1528
+ }
1529
+ errorField.trigger("jqv.field.result", [errorField, options.isError, msg]);
1530
+ }
1531
+ });
1532
+
1533
+ return rule.alertTextLoad;
1534
+ }
1535
+ },
1536
+ /**
1537
+ * Common method to handle ajax errors
1538
+ *
1539
+ * @param {Object} data
1540
+ * @param {Object} transport
1541
+ */
1542
+ _ajaxError: function(data, transport) {
1543
+ if(data.status == 0 && transport == null)
1544
+ alert("The page is not served from a server! ajax call failed");
1545
+ else if(typeof console != "undefined")
1546
+ console.log("Ajax error: " + data.status + " " + transport);
1547
+ },
1548
+ /**
1549
+ * date -> string
1550
+ *
1551
+ * @param {Object} date
1552
+ */
1553
+ _dateToString: function(date) {
1554
+ return date.getFullYear()+"-"+(date.getMonth()+1)+"-"+date.getDate();
1555
+ },
1556
+ /**
1557
+ * Parses an ISO date
1558
+ * @param {String} d
1559
+ */
1560
+ _parseDate: function(d) {
1561
+
1562
+ var dateParts = d.split("-");
1563
+ if(dateParts==d)
1564
+ dateParts = d.split("/");
1565
+ if(dateParts==d) {
1566
+ dateParts = d.split(".");
1567
+ return new Date(dateParts[2], (dateParts[1] - 1), dateParts[0]);
1568
+ }
1569
+ return new Date(dateParts[0], (dateParts[1] - 1) ,dateParts[2]);
1570
+ },
1571
+ /**
1572
+ * Builds or updates a prompt with the given information
1573
+ *
1574
+ * @param {jqObject} field
1575
+ * @param {String} promptText html text to display type
1576
+ * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
1577
+ * @param {boolean} ajaxed - use to mark fields than being validated with ajax
1578
+ * @param {Map} options user options
1579
+ */
1580
+ _showPrompt: function(field, promptText, type, ajaxed, options, ajaxform) {
1581
+ //Check if we need to adjust what element to show the prompt on
1582
+ if(field.data('jqv-prompt-at') instanceof jQuery ){
1583
+ field = field.data('jqv-prompt-at');
1584
+ } else if(field.data('jqv-prompt-at')) {
1585
+ field = $(field.data('jqv-prompt-at'));
1586
+ }
1587
+
1588
+ var prompt = methods._getPrompt(field);
1589
+ // The ajax submit errors are not see has an error in the form,
1590
+ // When the form errors are returned, the engine see 2 bubbles, but those are ebing closed by the engine at the same time
1591
+ // Because no error was found befor submitting
1592
+ if(ajaxform) prompt = false;
1593
+ // Check that there is indded text
1594
+ if($.trim(promptText)){
1595
+ if (prompt)
1596
+ methods._updatePrompt(field, prompt, promptText, type, ajaxed, options);
1597
+ else
1598
+ methods._buildPrompt(field, promptText, type, ajaxed, options);
1599
+ }
1600
+ },
1601
+ /**
1602
+ * Builds and shades a prompt for the given field.
1603
+ *
1604
+ * @param {jqObject} field
1605
+ * @param {String} promptText html text to display type
1606
+ * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
1607
+ * @param {boolean} ajaxed - use to mark fields than being validated with ajax
1608
+ * @param {Map} options user options
1609
+ */
1610
+ _buildPrompt: function(field, promptText, type, ajaxed, options) {
1611
+
1612
+ // create the prompt
1613
+ var prompt = $('<div>');
1614
+ prompt.addClass(methods._getClassName(field.attr("id")) + "formError");
1615
+ // add a class name to identify the parent form of the prompt
1616
+ prompt.addClass("parentForm"+methods._getClassName(field.closest('form, .validationEngineContainer').attr("id")));
1617
+ prompt.addClass("formError");
1618
+
1619
+ switch (type) {
1620
+ case "pass":
1621
+ prompt.addClass("greenPopup");
1622
+ break;
1623
+ case "load":
1624
+ prompt.addClass("blackPopup");
1625
+ break;
1626
+ default:
1627
+ /* it has error */
1628
+ //alert("unknown popup type:"+type);
1629
+ }
1630
+ if (ajaxed)
1631
+ prompt.addClass("ajaxed");
1632
+
1633
+ // create the prompt content
1634
+ var promptContent = $('<div>').addClass("formErrorContent").html(promptText).appendTo(prompt);
1635
+
1636
+ // determine position type
1637
+ var positionType=field.data("promptPosition") || options.promptPosition;
1638
+
1639
+ // create the css arrow pointing at the field
1640
+ // note that there is no triangle on max-checkbox and radio
1641
+ if (options.showArrow) {
1642
+ var arrow = $('<div>').addClass("formErrorArrow");
1643
+
1644
+ //prompt positioning adjustment support. Usage: positionType:Xshift,Yshift (for ex.: bottomLeft:+20 or bottomLeft:-20,+10)
1645
+ if (typeof(positionType)=='string')
1646
+ {
1647
+ var pos=positionType.indexOf(":");
1648
+ if(pos!=-1)
1649
+ positionType=positionType.substring(0,pos);
1650
+ }
1651
+
1652
+ switch (positionType) {
1653
+ case "bottomLeft":
1654
+ case "bottomRight":
1655
+ prompt.find(".formErrorContent").before(arrow);
1656
+ arrow.addClass("formErrorArrowBottom").html('<div class="line1"><!-- --></div><div class="line2"><!-- --></div><div class="line3"><!-- --></div><div class="line4"><!-- --></div><div class="line5"><!-- --></div><div class="line6"><!-- --></div><div class="line7"><!-- --></div><div class="line8"><!-- --></div><div class="line9"><!-- --></div><div class="line10"><!-- --></div>');
1657
+ break;
1658
+ case "topLeft":
1659
+ case "topRight":
1660
+ arrow.html('<div class="line10"><!-- --></div><div class="line9"><!-- --></div><div class="line8"><!-- --></div><div class="line7"><!-- --></div><div class="line6"><!-- --></div><div class="line5"><!-- --></div><div class="line4"><!-- --></div><div class="line3"><!-- --></div><div class="line2"><!-- --></div><div class="line1"><!-- --></div>');
1661
+ prompt.append(arrow);
1662
+ break;
1663
+ }
1664
+ }
1665
+ // Add custom prompt class
1666
+ if (options.addPromptClass)
1667
+ prompt.addClass(options.addPromptClass);
1668
+
1669
+ // Add custom prompt class defined in element
1670
+ var requiredOverride = field.attr('data-required-class');
1671
+ if(requiredOverride !== undefined) {
1672
+ prompt.addClass(requiredOverride);
1673
+ } else {
1674
+ if(options.prettySelect) {
1675
+ if($('#' + field.attr('id')).next().is('select')) {
1676
+ var prettyOverrideClass = $('#' + field.attr('id').substr(options.usePrefix.length).substring(options.useSuffix.length)).attr('data-required-class');
1677
+ if(prettyOverrideClass !== undefined) {
1678
+ prompt.addClass(prettyOverrideClass);
1679
+ }
1680
+ }
1681
+ }
1682
+ }
1683
+
1684
+ prompt.css({
1685
+ "opacity": 0
1686
+ });
1687
+ if(positionType === 'inline') {
1688
+ prompt.addClass("inline");
1689
+ if(typeof field.attr('data-prompt-target') !== 'undefined' && $('#'+field.attr('data-prompt-target')).length > 0) {
1690
+ prompt.appendTo($('#'+field.attr('data-prompt-target')));
1691
+ } else {
1692
+ field.after(prompt);
1693
+ }
1694
+ } else {
1695
+ field.before(prompt);
1696
+ }
1697
+
1698
+ var pos = methods._calculatePosition(field, prompt, options);
1699
+ // Support RTL layouts by @yasser_lotfy ( Yasser Lotfy )
1700
+ if ($('body').hasClass('rtl')) {
1701
+ prompt.css({
1702
+ 'position': positionType === 'inline' ? 'relative' : 'absolute',
1703
+ "top": pos.callerTopPosition,
1704
+ "left": "initial",
1705
+ "right": pos.callerleftPosition,
1706
+ "marginTop": pos.marginTopSize,
1707
+ "opacity": 0
1708
+ }).data("callerField", field);
1709
+ } else {
1710
+ prompt.css({
1711
+ 'position': positionType === 'inline' ? 'relative' : 'absolute',
1712
+ "top": pos.callerTopPosition,
1713
+ "left": pos.callerleftPosition,
1714
+ "right": "initial",
1715
+ "marginTop": pos.marginTopSize,
1716
+ "opacity": 0
1717
+ }).data("callerField", field);
1718
+ }
1719
+
1720
+
1721
+ if (options.autoHidePrompt) {
1722
+ setTimeout(function(){
1723
+ prompt.animate({
1724
+ "opacity": 0
1725
+ },function(){
1726
+ prompt.closest('.formError').remove();
1727
+ });
1728
+ }, options.autoHideDelay);
1729
+ }
1730
+ return prompt.animate({
1731
+ "opacity": 0.87
1732
+ });
1733
+ },
1734
+ /**
1735
+ * Updates the prompt text field - the field for which the prompt
1736
+ * @param {jqObject} field
1737
+ * @param {String} promptText html text to display type
1738
+ * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
1739
+ * @param {boolean} ajaxed - use to mark fields than being validated with ajax
1740
+ * @param {Map} options user options
1741
+ */
1742
+ _updatePrompt: function(field, prompt, promptText, type, ajaxed, options, noAnimation) {
1743
+
1744
+ if (prompt) {
1745
+ if (typeof type !== "undefined") {
1746
+ if (type == "pass")
1747
+ prompt.addClass("greenPopup");
1748
+ else
1749
+ prompt.removeClass("greenPopup");
1750
+
1751
+ if (type == "load")
1752
+ prompt.addClass("blackPopup");
1753
+ else
1754
+ prompt.removeClass("blackPopup");
1755
+ }
1756
+ if (ajaxed)
1757
+ prompt.addClass("ajaxed");
1758
+ else
1759
+ prompt.removeClass("ajaxed");
1760
+
1761
+ prompt.find(".formErrorContent").html(promptText);
1762
+
1763
+ var pos = methods._calculatePosition(field, prompt, options);
1764
+ // Support RTL layouts by @yasser_lotfy ( Yasser Lotfy )
1765
+ if ($('body').hasClass('rtl')) {
1766
+ var css = {"top": pos.callerTopPosition,
1767
+ "left": "initial",
1768
+ "right": pos.callerleftPosition,
1769
+ "marginTop": pos.marginTopSize,
1770
+ "opacity": 0.87};
1771
+ } else {
1772
+ var css = {"top": pos.callerTopPosition,
1773
+ "left": pos.callerleftPosition,
1774
+ "right": "initial",
1775
+ "marginTop": pos.marginTopSize,
1776
+ "opacity": 0.87};
1777
+ }
1778
+
1779
+ prompt.css({
1780
+ "opacity": 0,
1781
+ "display": "block"
1782
+ });
1783
+
1784
+ if (noAnimation)
1785
+ prompt.css(css);
1786
+ else
1787
+ prompt.animate(css);
1788
+ }
1789
+ },
1790
+ /**
1791
+ * Closes the prompt associated with the given field
1792
+ *
1793
+ * @param {jqObject}
1794
+ * field
1795
+ */
1796
+ _closePrompt: function(field) {
1797
+ var prompt = methods._getPrompt(field);
1798
+ if (prompt)
1799
+ prompt.fadeTo("fast", 0, function() {
1800
+ prompt.closest('.formError').remove();
1801
+ });
1802
+ },
1803
+ closePrompt: function(field) {
1804
+ return methods._closePrompt(field);
1805
+ },
1806
+ /**
1807
+ * Returns the error prompt matching the field if any
1808
+ *
1809
+ * @param {jqObject}
1810
+ * field
1811
+ * @return undefined or the error prompt (jqObject)
1812
+ */
1813
+ _getPrompt: function(field) {
1814
+ var formId = $(field).closest('form, .validationEngineContainer').attr('id');
1815
+ var className = methods._getClassName(field.attr("id")) + "formError";
1816
+ var match = $("." + methods._escapeExpression(className) + '.parentForm' + methods._getClassName(formId))[0];
1817
+ if (match)
1818
+ return $(match);
1819
+ },
1820
+ /**
1821
+ * Returns the escapade classname
1822
+ *
1823
+ * @param {selector}
1824
+ * className
1825
+ */
1826
+ _escapeExpression: function (selector) {
1827
+ return selector.replace(/([#;&,\.\+\*\~':"\!\^$\[\]\(\)=>\|])/g, "\\$1");
1828
+ },
1829
+ /**
1830
+ * returns true if we are in a RTLed document
1831
+ *
1832
+ * @param {jqObject} field
1833
+ */
1834
+ isRTL: function(field)
1835
+ {
1836
+ var $document = $(document);
1837
+ var $body = $('body');
1838
+ var rtl =
1839
+ (field && field.hasClass('rtl')) ||
1840
+ (field && (field.attr('dir') || '').toLowerCase()==='rtl') ||
1841
+ $document.hasClass('rtl') ||
1842
+ ($document.attr('dir') || '').toLowerCase()==='rtl' ||
1843
+ $body.hasClass('rtl') ||
1844
+ ($body.attr('dir') || '').toLowerCase()==='rtl';
1845
+ return Boolean(rtl);
1846
+ },
1847
+ /**
1848
+ * Calculates prompt position
1849
+ *
1850
+ * @param {jqObject}
1851
+ * field
1852
+ * @param {jqObject}
1853
+ * the prompt
1854
+ * @param {Map}
1855
+ * options
1856
+ * @return positions
1857
+ */
1858
+ _calculatePosition: function (field, promptElmt, options) {
1859
+
1860
+ var promptTopPosition, promptleftPosition, marginTopSize;
1861
+ var fieldWidth = field.width();
1862
+ var fieldLeft = field.position().left;
1863
+ var fieldTop = field.position().top;
1864
+ var fieldHeight = field.height();
1865
+ var promptHeight = promptElmt.height();
1866
+
1867
+
1868
+ // is the form contained in an overflown container?
1869
+ promptTopPosition = promptleftPosition = 0;
1870
+ // compensation for the arrow
1871
+ marginTopSize = -promptHeight;
1872
+
1873
+
1874
+ //prompt positioning adjustment support
1875
+ //now you can adjust prompt position
1876
+ //usage: positionType:Xshift,Yshift
1877
+ //for example:
1878
+ // bottomLeft:+20 means bottomLeft position shifted by 20 pixels right horizontally
1879
+ // topRight:20, -15 means topRight position shifted by 20 pixels to right and 15 pixels to top
1880
+ //You can use +pixels, - pixels. If no sign is provided than + is default.
1881
+ var positionType=field.data("promptPosition") || options.promptPosition;
1882
+ var shift1="";
1883
+ var shift2="";
1884
+ var shiftX=0;
1885
+ var shiftY=0;
1886
+ if (typeof(positionType)=='string') {
1887
+ //do we have any position adjustments ?
1888
+ if (positionType.indexOf(":")!=-1) {
1889
+ shift1=positionType.substring(positionType.indexOf(":")+1);
1890
+ positionType=positionType.substring(0,positionType.indexOf(":"));
1891
+
1892
+ //if any advanced positioning will be needed (percents or something else) - parser should be added here
1893
+ //for now we use simple parseInt()
1894
+
1895
+ //do we have second parameter?
1896
+ if (shift1.indexOf(",") !=-1) {
1897
+ shift2=shift1.substring(shift1.indexOf(",") +1);
1898
+ shift1=shift1.substring(0,shift1.indexOf(","));
1899
+ shiftY=parseInt(shift2);
1900
+ if (isNaN(shiftY)) shiftY=0;
1901
+ };
1902
+
1903
+ shiftX=parseInt(shift1);
1904
+ if (isNaN(shift1)) shift1=0;
1905
+
1906
+ };
1907
+ };
1908
+
1909
+
1910
+ switch (positionType) {
1911
+ default:
1912
+ case "topRight":
1913
+ promptleftPosition += fieldLeft + fieldWidth - 27;
1914
+ promptTopPosition += fieldTop;
1915
+ break;
1916
+
1917
+ case "topLeft":
1918
+ promptTopPosition += fieldTop;
1919
+ promptleftPosition += fieldLeft;
1920
+ break;
1921
+
1922
+ case "centerRight":
1923
+ promptTopPosition = fieldTop+4;
1924
+ marginTopSize = 0;
1925
+ promptleftPosition= fieldLeft + field.outerWidth(true)+5;
1926
+ break;
1927
+ case "centerLeft":
1928
+ promptleftPosition = fieldLeft - (promptElmt.width() + 2);
1929
+ promptTopPosition = fieldTop+4;
1930
+ marginTopSize = 0;
1931
+
1932
+ break;
1933
+
1934
+ case "bottomLeft":
1935
+ promptTopPosition = fieldTop + field.height() + 5;
1936
+ marginTopSize = 0;
1937
+ promptleftPosition = fieldLeft;
1938
+ break;
1939
+ case "bottomRight":
1940
+ promptleftPosition = fieldLeft + fieldWidth - 27;
1941
+ promptTopPosition = fieldTop + field.height() + 5;
1942
+ marginTopSize = 0;
1943
+ break;
1944
+ case "inline":
1945
+ promptleftPosition = 0;
1946
+ promptTopPosition = 0;
1947
+ marginTopSize = 0;
1948
+ };
1949
+
1950
+
1951
+
1952
+ //apply adjusments if any
1953
+ promptleftPosition += shiftX;
1954
+ promptTopPosition += shiftY;
1955
+
1956
+ return {
1957
+ "callerTopPosition": promptTopPosition + "px",
1958
+ "callerleftPosition": promptleftPosition + "px",
1959
+ "marginTopSize": marginTopSize + "px"
1960
+ };
1961
+ },
1962
+ /**
1963
+ * Saves the user options and variables in the form.data
1964
+ *
1965
+ * @param {jqObject}
1966
+ * form - the form where the user option should be saved
1967
+ * @param {Map}
1968
+ * options - the user options
1969
+ * @return the user options (extended from the defaults)
1970
+ */
1971
+ _saveOptions: function(form, options) {
1972
+
1973
+ // is there a language localisation ?
1974
+ if ($.validationEngineLanguage)
1975
+ var allRules = $.validationEngineLanguage.allRules;
1976
+ else
1977
+ $.error("jQuery.validationEngine rules are not loaded, plz add localization files to the page");
1978
+ // --- Internals DO NOT TOUCH or OVERLOAD ---
1979
+ // validation rules and i18
1980
+ $.validationEngine.defaults.allrules = allRules;
1981
+
1982
+ var userOptions = $.extend(true,{},$.validationEngine.defaults,options);
1983
+
1984
+ form.data('jqv', userOptions);
1985
+ return userOptions;
1986
+ },
1987
+
1988
+ /**
1989
+ * Removes forbidden characters from class name
1990
+ * @param {String} className
1991
+ */
1992
+ _getClassName: function(className) {
1993
+ if(className)
1994
+ return className.replace(/:/g, "_").replace(/\./g, "_");
1995
+ },
1996
+ /**
1997
+ * Escape special character for jQuery selector
1998
+ * http://totaldev.com/content/escaping-characters-get-valid-jquery-id
1999
+ * @param {String} selector
2000
+ */
2001
+ _jqSelector: function(str){
2002
+ return str.replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, '\\$1');
2003
+ },
2004
+ /**
2005
+ * Conditionally required field
2006
+ *
2007
+ * @param {jqObject} field
2008
+ * @param {Array[String]} rules
2009
+ * @param {int} i rules index
2010
+ * @param {Map}
2011
+ * user options
2012
+ * @return an error string if validation failed
2013
+ */
2014
+ _condRequired: function(field, rules, i, options) {
2015
+ var idx, dependingField;
2016
+
2017
+ for(idx = (i + 1); idx < rules.length; idx++) {
2018
+ dependingField = jQuery("#" + rules[idx]).first();
2019
+
2020
+ /* Use _required for determining wether dependingField has a value.
2021
+ * There is logic there for handling all field types, and default value; so we won't replicate that here
2022
+ * Indicate this special use by setting the last parameter to true so we only validate the dependingField on chackboxes and radio buttons (#462)
2023
+ */
2024
+ if (dependingField.length && methods._required(dependingField, ["required"], 0, options, true) == undefined) {
2025
+ /* We now know any of the depending fields has a value,
2026
+ * so we can validate this field as per normal required code
2027
+ */
2028
+ return methods._required(field, ["required"], 0, options);
2029
+ }
2030
+ }
2031
+ },
2032
+
2033
+ _submitButtonClick: function(event) {
2034
+ var button = $(this);
2035
+ var form = button.closest('form, .validationEngineContainer');
2036
+ form.data("jqv_submitButton", button.attr("id"));
2037
+ }
2038
+ };
2039
+
2040
+ /**
2041
+ * Plugin entry point.
2042
+ * You may pass an action as a parameter or a list of options.
2043
+ * if none, the init and attach methods are being called.
2044
+ * Remember: if you pass options, the attached method is NOT called automatically
2045
+ *
2046
+ * @param {String}
2047
+ * method (optional) action
2048
+ */
2049
+ $.fn.validationEngine = function(method) {
2050
+
2051
+ var form = $(this);
2052
+ if(!form[0]) return form; // stop here if the form does not exist
2053
+
2054
+ if (typeof(method) == 'string' && method.charAt(0) != '_' && methods[method]) {
2055
+
2056
+ // make sure init is called once
2057
+ if(method != "showPrompt" && method != "hide" && method != "hideAll")
2058
+ methods.init.apply(form);
2059
+
2060
+ return methods[method].apply(form, Array.prototype.slice.call(arguments, 1));
2061
+ } else if (typeof method == 'object' || !method) {
2062
+
2063
+ // default constructor with or without arguments
2064
+ methods.init.apply(form, arguments);
2065
+ return methods.attach.apply(form);
2066
+ } else {
2067
+ $.error('Method ' + method + ' does not exist in jQuery.validationEngine');
2068
+ }
2069
+ };
2070
+
2071
+
2072
+
2073
+ // LEAK GLOBAL OPTIONS
2074
+ $.validationEngine= {fieldIdCounter: 0,defaults:{
2075
+
2076
+ // Name of the event triggering field validation
2077
+ validationEventTrigger: "blur",
2078
+ // Automatically scroll viewport to the first error
2079
+ scroll: true,
2080
+ // Focus on the first input
2081
+ focusFirstField:true,
2082
+ // Show prompts, set to false to disable prompts
2083
+ showPrompts: true,
2084
+ // Should we attempt to validate non-visible input fields contained in the form? (Useful in cases of tabbed containers, e.g. jQuery-UI tabs)
2085
+ validateNonVisibleFields: false,
2086
+ // ignore the validation for fields with this specific class (Useful in cases of tabbed containers AND hidden fields we don't want to validate)
2087
+ ignoreFieldsWithClass: 'ignoreMe',
2088
+ // Opening box position, possible locations are: topLeft,
2089
+ // topRight, bottomLeft, centerRight, bottomRight, inline
2090
+ // inline gets inserted after the validated field or into an element specified in data-prompt-target
2091
+ promptPosition: "topRight",
2092
+ bindMethod:"bind",
2093
+ // internal, automatically set to true when it parse a _ajax rule
2094
+ inlineAjax: false,
2095
+ // if set to true, the form data is sent asynchronously via ajax to the form.action url (get)
2096
+ ajaxFormValidation: false,
2097
+ // The url to send the submit ajax validation (default to action)
2098
+ ajaxFormValidationURL: false,
2099
+ // HTTP method used for ajax validation
2100
+ ajaxFormValidationMethod: 'get',
2101
+ // Ajax form validation callback method: boolean onComplete(form, status, errors, options)
2102
+ // retuns false if the form.submit event needs to be canceled.
2103
+ onAjaxFormComplete: $.noop,
2104
+ // called right before the ajax call, may return false to cancel
2105
+ onBeforeAjaxFormValidation: $.noop,
2106
+ // Stops form from submitting and execute function assiciated with it
2107
+ onValidationComplete: false,
2108
+
2109
+ // Used when you have a form fields too close and the errors messages are on top of other disturbing viewing messages
2110
+ doNotShowAllErrosOnSubmit: false,
2111
+ // Object where you store custom messages to override the default error messages
2112
+ custom_error_messages:{},
2113
+ // true if you want to validate the input fields on blur event
2114
+ binded: true,
2115
+ // set to true if you want to validate the input fields on blur only if the field it's not empty
2116
+ notEmpty: false,
2117
+ // set to true, when the prompt arrow needs to be displayed
2118
+ showArrow: true,
2119
+ // set to false, determines if the prompt arrow should be displayed when validating
2120
+ // checkboxes and radio buttons
2121
+ showArrowOnRadioAndCheckbox: false,
2122
+ // did one of the validation fail ? kept global to stop further ajax validations
2123
+ isError: false,
2124
+ // Limit how many displayed errors a field can have
2125
+ maxErrorsPerField: false,
2126
+
2127
+ // Caches field validation status, typically only bad status are created.
2128
+ // the array is used during ajax form validation to detect issues early and prevent an expensive submit
2129
+ ajaxValidCache: {},
2130
+ // Auto update prompt position after window resize
2131
+ autoPositionUpdate: false,
2132
+
2133
+ InvalidFields: [],
2134
+ onFieldSuccess: false,
2135
+ onFieldFailure: false,
2136
+ onSuccess: false,
2137
+ onFailure: false,
2138
+ validateAttribute: "class",
2139
+ addSuccessCssClassToField: "",
2140
+ addFailureCssClassToField: "",
2141
+
2142
+ // Auto-hide prompt
2143
+ autoHidePrompt: false,
2144
+ // Delay before auto-hide
2145
+ autoHideDelay: 10000,
2146
+ // Fade out duration while hiding the validations
2147
+ fadeDuration: 300,
2148
+ // Use Prettify select library
2149
+ prettySelect: false,
2150
+ // Add css class on prompt
2151
+ addPromptClass : "",
2152
+ // Custom ID uses prefix
2153
+ usePrefix: "",
2154
+ // Custom ID uses suffix
2155
+ useSuffix: "",
2156
+ // Only show one message per error prompt
2157
+ showOneMessage: false
2158
+ }};
2159
+ $(function(){$.validationEngine.defaults.promptPosition = methods.isRTL()?'topLeft':"topRight"});
2160
+ })(jQuery);