').addClass("formErrorContent").html(promptText).appendTo(prompt);
// create the css arrow pointing at the field
// note that there is no triangle on max-checkbox and radio
if (options.showArrow) {
var arrow = $('
').addClass("formErrorArrow");
switch (options.promptPosition) {
case "bottomLeft":
case "bottomRight":
prompt.find(".formErrorContent").before(arrow);
arrow.addClass("formErrorArrowBottom").html('
');
break;
case "topLeft":
case "topRight":
arrow.html('
');
prompt.append(arrow);
break;
}
}
//Cedric: Needed if a container is in position:relative
// insert prompt in the form or in the overflown container?
if (options.isOverflown)
field.before(prompt);
else
$("body").append(prompt);
var pos = methods._calculatePosition(field, prompt, options);
prompt.css({
"top": pos.callerTopPosition,
"left": pos.callerleftPosition,
"marginTop": pos.marginTopSize,
"opacity": 0
});
return prompt.animate({
"opacity": 0.87
});
},
/**
* Updates the prompt text field - the field for which the prompt
* @param {jqObject} field
* @param {String} promptText html text to display type
* @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
* @param {boolean} ajaxed - use to mark fields than being validated with ajax
* @param {Map} options user options
*/
_updatePrompt: function(field, prompt, promptText, type, ajaxed, options) {
if (prompt) {
if (type == "pass")
prompt.addClass("greenPopup");
else
prompt.removeClass("greenPopup");
if (type == "load")
prompt.addClass("blackPopup");
else
prompt.removeClass("blackPopup");
if (ajaxed)
prompt.addClass("ajaxed");
else
prompt.removeClass("ajaxed");
prompt.find(".formErrorContent").html(promptText);
var pos = methods._calculatePosition(field, prompt, options);
prompt.animate({
"top": pos.callerTopPosition,
"left": pos.callerleftPosition,
"marginTop": pos.marginTopSize
});
}
},
/**
* Closes the prompt associated with the given field
*
* @param {jqObject}
* field
*/
_closePrompt: function(field) {
var prompt = methods._getPrompt(field);
if (prompt)
prompt.fadeTo("fast", 0, function() {
prompt.remove();
});
},
closePrompt: function(field) {
return methods._closePrompt(field);
},
/**
* Returns the error prompt matching the field if any
*
* @param {jqObject}
* field
* @return undefined or the error prompt (jqObject)
*/
_getPrompt: function(field) {
var className = field.attr("id").replace(":","_") + "formError";
var match = $("." + methods._escapeExpression(className))[0];
if (match)
return $(match);
},
/**
* Returns the escapade classname
*
* @param {selector}
* className
*/
_escapeExpression: function (selector) {
return selector.replace(/([#;&,\.\+\*\~':"\!\^$\[\]\(\)=>\|])/g, "\\$1");
},
/**
* Calculates prompt position
*
* @param {jqObject}
* field
* @param {jqObject}
* the prompt
* @param {Map}
* options
* @return positions
*/
_calculatePosition: function (field, promptElmt, options) {
var promptTopPosition, promptleftPosition, marginTopSize;
var fieldWidth = field.width();
var promptHeight = promptElmt.height();
var overflow = options.isOverflown;
if (overflow) {
// is the form contained in an overflown container?
promptTopPosition = promptleftPosition = 0;
// compensation for the arrow
marginTopSize = -promptHeight;
} else {
var offset = field.offset();
promptTopPosition = offset.top;
promptleftPosition = offset.left;
marginTopSize = 0;
}
switch (options.promptPosition) {
default:
case "topRight":
if (overflow)
// Is the form contained in an overflown container?
promptleftPosition += fieldWidth - 30;
else {
promptleftPosition += fieldWidth - 30;
promptTopPosition += -promptHeight -2;
}
break;
case "topLeft":
promptTopPosition += -promptHeight - 10;
break;
case "centerRight":
promptleftPosition += fieldWidth + 13;
break;
case "bottomLeft":
promptTopPosition = promptTopPosition + field.height() + 15;
break;
case "bottomRight":
promptleftPosition += fieldWidth - 30;
promptTopPosition += field.height() + 5;
}
return {
"callerTopPosition": promptTopPosition + "px",
"callerleftPosition": promptleftPosition + "px",
"marginTopSize": marginTopSize + "px"
};
},
/**
* Saves the user options and variables in the form.data
*
* @param {jqObject}
* form - the form where the user option should be saved
* @param {Map}
* options - the user options
* @return the user options (extended from the defaults)
*/
_saveOptions: function(form, options) {
// is there a language localisation ?
if ($.validationEngineLanguage)
var allRules = $.validationEngineLanguage.allRules;
else
$.error("jQuery.validationEngine rules are not loaded, plz add localization files to the page");
// --- Internals DO NOT TOUCH or OVERLOAD ---
// validation rules and i18
$.validationEngine.defaults.allrules = allRules;
var userOptions = $.extend({},$.validationEngine.defaults, options);
form.data('jqv', userOptions);
return userOptions;
},
/**
* Removes forbidden characters from class name
* @param {String} className
*/
_getClassName: function(className) {
return className.replace(":","_").replace(".","_");
}
};
/**
* Plugin entry point.
* You may pass an action as a parameter or a list of options.
* if none, the init and attach methods are being called.
* Remember: if you pass options, the attached method is NOT called automatically
*
* @param {String}
* method (optional) action
*/
$.fn.validationEngine = function(method) {
var form = $(this);
if(!form[0]) return false; // stop here if the form does not exist
if (typeof(method) == 'string' && method.charAt(0) != '_' && methods[method]) {
// make sure init is called once
if(method != "showPrompt" && method != "hidePrompt" && method != "hide" && method != "hideAll")
methods.init.apply(form);
return methods[method].apply(form, Array.prototype.slice.call(arguments, 1));
} else if (typeof method == 'object' || !method) {
// default constructor with or without arguments
methods.init.apply(form, arguments);
return methods.attach.apply(form);
} else {
$.error('Method ' + method + ' does not exist in jQuery.validationEngine');
}
};
// LEAK GLOBAL OPTIONS
$.validationEngine= {defaults:{
// Name of the event triggering field validation
validationEventTrigger: "blur",
// Automatically scroll viewport to the first error
scroll: true,
// Opening box position, possible locations are: topLeft,
// topRight, bottomLeft, centerRight, bottomRight
promptPosition: "topRight",
bindMethod:"bind",
// internal, automatically set to true when it parse a _ajax rule
inlineAjax: false,
// if set to true, the form data is sent asynchronously via ajax to the form.action url (get)
ajaxFormValidation: false,
// Ajax form validation callback method: boolean onComplete(form, status, errors, options)
// retuns false if the form.submit event needs to be canceled.
ajaxFormValidationURL: false,
// The url to send the submit ajax validation (default to action)
onAjaxFormComplete: $.noop,
// called right before the ajax call, may return false to cancel
onBeforeAjaxFormValidation: $.noop,
// Stops form from submitting and execute function assiciated with it
onValidationComplete: false,
// Used when the form is displayed within a scrolling DIV
isOverflown: false,
overflownDIV: "",
// true when form and fields are binded
binded: false,
// set to true, when the prompt arrow needs to be displayed
showArrow: true,
// did one of the validation fail ? kept global to stop further ajax validations
isError: false,
// Caches field validation status, typically only bad status are created.
// the array is used during ajax form validation to detect issues early and prevent an expensive submit
ajaxValidCache: {}
}}
})(jQuery);