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