treport 1.1.1 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
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);