treport 1.1.1 → 1.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/models/connect.rb +1 -0
- data/app/models/db.rb +1 -1
- data/app/models/map.rb +1 -0
- data/app/models/map_requirement.rb +1 -0
- data/app/models/report.rb +17 -9
- data/app/models/requirement.rb +1 -0
- data/public/treport/plugins/datePicker/My97DatePicker.htm +48 -48
- data/public/treport/plugins/datePicker/WdatePicker.js +52 -52
- data/public/treport/plugins/datePicker/calendar.js +4 -4
- data/public/treport/plugins/datePicker/config.js +16 -16
- data/public/treport/plugins/datePicker/lang/en.js +13 -13
- data/public/treport/plugins/datePicker/lang/zh-cn.js +13 -13
- data/public/treport/plugins/datePicker/lang/zh-tw.js +13 -13
- data/public/treport/plugins/datePicker/skin/WdatePicker.css +9 -9
- data/public/treport/plugins/datePicker/skin/areo/datepicker.css +301 -301
- data/public/treport/plugins/datePicker/skin/armyGreen/datepicker.css +301 -301
- data/public/treport/plugins/datePicker/skin/blue/datepicker.css +114 -114
- data/public/treport/plugins/datePicker/skin/blueGreen/datepicker.css +301 -301
- data/public/treport/plugins/datePicker/skin/darkBlue/datepicker.css +308 -308
- data/public/treport/plugins/datePicker/skin/darkYellow/datepicker.css +114 -114
- data/public/treport/plugins/datePicker/skin/deepBlue/datepicker.css +300 -300
- data/public/treport/plugins/datePicker/skin/default/datepicker.css +245 -245
- data/public/treport/plugins/datePicker/skin/green/datepicker.css +114 -114
- data/public/treport/plugins/datePicker/skin/lightBlue/datepicker.css +114 -114
- data/public/treport/plugins/datePicker/skin/modernBlue/datepicker.css +301 -301
- data/public/treport/plugins/datePicker/skin/orange/datepicker.css +114 -114
- data/public/treport/plugins/datePicker/skin/red/datepicker.css +114 -114
- data/public/treport/plugins/datePicker/skin/whyGreen/datepicker.css +255 -255
- data/public/treport/plugins/datePicker/skin/yellowGreen/datepicker.css +114 -114
- data/public/treport/plugins/validationEngine/jquery.validationEngine-zh_CN.js +181 -181
- data/public/treport/plugins/validationEngine/jquery.validationEngine.js +2160 -2160
- data/public/treport/plugins/validationEngine/template.css +124 -124
- data/public/treport/plugins/validationEngine/validationEngine.jquery.css +182 -182
- data/public/treport/plugins/zDialog/dialog.js +1312 -1312
- data/public/treport/plugins/zDialog/drag.js +91 -91
- data/public/treport/plugins/zDialog/skins/blue/dir.txt +24 -24
- data/public/treport/plugins/zDialog/skins/darkBlue/dir.txt +24 -24
- data/public/treport/plugins/zDialog/skins/darkYellow/dir.txt +24 -24
- data/public/treport/plugins/zDialog/skins/green/dir.txt +24 -24
- data/public/treport/plugins/zDialog/skins/lightBlue/dir.txt +24 -24
- data/public/treport/plugins/zDialog/skins/red/dir.txt +24 -24
- data/public/treport/plugins/zDialog/skins/yellowGreen/dir.txt +24 -24
- data/public/treport/plugins/zDialog/zDialog.js +763 -763
- 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);
|