/* * Inline Form Validation Engine 1.6.2, jQuery plugin * * Copyright(c) 2009, Cedric Dugas * http://www.position-relative.net * * Form validation engine allowing custom regex rules to be added. * Thanks to Francois Duquette * Licenced under the MIT Licence */ (function ($) { $.fn.validationEngine = function (settings) { if ($.validationEngineLanguage) { // IS THERE A LANGUAGE LOCALISATION ? allRules = $.validationEngineLanguage.allRules; } else { $.validationEngine.debug("Validation engine rules are not loaded check your external file"); } settings = jQuery.extend({ allrules: allRules, validationEventTriggers: "blur", inlineValidation: true, returnIsValid: false, animateSubmit: true, unbindEngine: true, ajaxSubmit: false, promptPosition: "topRight", // OPENNING BOX POSITION, IMPLEMENTED: topLeft, topRight, bottomLeft, centerRight, bottomRight success: false, failure: function () {} }, settings); $.validationEngine.settings = settings; $.validationEngine.ajaxValidArray = new Array(); // ARRAY FOR AJAX: VALIDATION MEMORY if (settings.inlineValidation == true) { // Validating Inline ? if (!settings.returnIsValid) { // NEEDED FOR THE SETTING returnIsValid allowReturnIsvalid = false; $(this).find("[class*=validate]").not("[type=checkbox]").bind(settings.validationEventTriggers, function (caller) { _inlinEvent(this); }) $(this).find("[class*=validate][type=checkbox]").bind("click", function (caller) { _inlinEvent(this); }) firstvalid = false; } function _inlinEvent(caller) { $.validationEngine.settings = settings; if ($.validationEngine.intercept == false || !$.validationEngine.intercept) { // STOP INLINE VALIDATION THIS TIME ONLY $.validationEngine.onSubmitValid = false; $.validationEngine.loadValidation(caller); } else { $.validationEngine.intercept = false; } } } if (settings.returnIsValid) { // Do validation and return true or false, it bypass everything; if ($.validationEngine.submitValidation(this, settings)) { return false; } else { return true; } } $(this).bind("submit", function (caller) { // ON FORM SUBMIT, CONTROL AJAX FUNCTION IF SPECIFIED ON DOCUMENT READY $.validationEngine.onSubmitValid = true; $.validationEngine.settings = settings; if ($.validationEngine.submitValidation(this, settings) == false) { if ($.validationEngine.submitForm(this, settings) == true) { return false; } } else { settings.failure && settings.failure(); return false; } }) }; $.validationEngine = { defaultSetting: function (caller) { if ($.validationEngineLanguage) { // IS THERE A LANGUAGE LOCALISATION ? allRules = $.validationEngineLanguage.allRules; } else { $.validationEngine.debug("Validation engine rules are not loaded check your external file"); } settings = { allrules: allRules, validationEventTriggers: "blur", inlineValidation: true, returnIsValid: false, animateSubmit: true, unbindEngine: true, ajaxSubmit: false, promptPosition: "topRight", // OPENNING BOX POSITION, IMPLEMENTED: topLeft, topRight, bottomLeft, centerRight, bottomRight success: false, failure: function () {} } $.validationEngine.settings = settings; }, loadValidation: function (caller) { // GET VALIDATIONS TO BE EXECUTED if (!$.validationEngine.settings) { $.validationEngine.defaultSetting() } rulesParsing = $(caller).attr('class'); rulesRegExp = /\[(.*)\]/; getRules = rulesRegExp.exec(rulesParsing); str = getRules[1]; pattern = /\W+/; result = str.split(pattern); var validateCalll = $.validationEngine.validateCall(caller, result) return validateCalll; }, validateCall: function (caller, rules) { // EXECUTE VALIDATION REQUIRED BY THE USER FOR THIS FIELD var promptText = "" if (!$(caller).attr("id")) { $.validationEngine.debug("This field have no ID attribut( name & class displayed): " + $(caller).attr("name") + " " + $(caller).attr("class")) } caller = caller; ajaxValidate = false; var callerName = $(caller).attr("name"); $.validationEngine.isError = false; $.validationEngine.showTriangle = true; callerType = $(caller).attr("type"); for (i = 0; i < rules.length; i++) { switch (rules[i]) { case "optional": if (!$(caller).val()) { $.validationEngine.closePrompt(caller); return $.validationEngine.isError; } break; case "required": _required(caller, rules); break; case "custom": _customRegex(caller, rules, i); break; case "ajax": if (!$.validationEngine.onSubmitValid) { _ajax(caller, rules, i); } ; break; case "length": _length(caller, rules, i); break; case "maxCheckbox": _maxCheckbox(caller, rules, i); groupname = $(caller).attr("name"); caller = $("input[name='" + groupname + "']"); break; case "minCheckbox": _minCheckbox(caller, rules, i); groupname = $(caller).attr("name"); caller = $("input[name='" + groupname + "']"); break; case "confirm": _confirm(caller, rules, i); break; default : ; } ; } ; radioHack(); if ($.validationEngine.isError == true) { linkTofield = $.validationEngine.linkTofield(caller); ($("div." + linkTofield).size() == 0) ? $.validationEngine.buildPrompt(caller, promptText, "error") : $.validationEngine.updatePromptText(caller, promptText); } else { $.validationEngine.closePrompt(caller); } /* UNFORTUNATE RADIO AND CHECKBOX GROUP HACKS */ /* As my validation is looping input with id's we need a hack for my validation to understand to group these inputs */ function radioHack() { if ($("input[name='" + callerName + "']").size() > 1 && (callerType == "radio" || callerType == "checkbox")) { // Hack for radio/checkbox group button, the validation go the first radio/checkbox of the group caller = $("input[name='" + callerName + "'][type!=hidden]:first"); $.validationEngine.showTriangle = false; } } /* VALIDATION FUNCTIONS */ function _required(caller, rules) { // VALIDATE BLANK FIELD callerType = $(caller).attr("type"); if (callerType == "text" || callerType == "password" || callerType == "textarea") { if (!$(caller).val()) { $.validationEngine.isError = true; promptText += $.validationEngine.settings.allrules[rules[i]].alertText + "
"; } } if (callerType == "radio" || callerType == "checkbox") { callerName = $(caller).attr("name"); if ($("input[name='" + callerName + "']:checked").size() == 0) { $.validationEngine.isError = true; if ($("input[name='" + callerName + "']").size() == 1) { promptText += $.validationEngine.settings.allrules[rules[i]].alertTextCheckboxe + "
"; } else { promptText += $.validationEngine.settings.allrules[rules[i]].alertTextCheckboxMultiple + "
"; } } } if (callerType == "select-one") { // added by paul@kinetek.net for select boxes, Thank you if (!$(caller).val()) { $.validationEngine.isError = true; promptText += $.validationEngine.settings.allrules[rules[i]].alertText + "
"; } } if (callerType == "select-multiple") { // added by paul@kinetek.net for select boxes, Thank you if (!$(caller).find("option:selected").val()) { $.validationEngine.isError = true; promptText += $.validationEngine.settings.allrules[rules[i]].alertText + "
"; } } } function _customRegex(caller, rules, position) { // VALIDATE REGEX RULES customRule = rules[position + 1]; pattern = eval($.validationEngine.settings.allrules[customRule].regex); if (!pattern.test($(caller).attr('value'))) { $.validationEngine.isError = true; promptText += $.validationEngine.settings.allrules[customRule].alertText + "
"; } } function _ajax(caller, rules, position) { // VALIDATE AJAX RULES customAjaxRule = rules[position + 1]; postfile = $.validationEngine.settings.allrules[customAjaxRule].file; fieldValue = $(caller).val(); ajaxCaller = caller; fieldId = $(caller).attr("id"); ajaxValidate = true; ajaxisError = $.validationEngine.isError; if (!$.validationEngine.settings.allrules[customAjaxRule].extraData) { extraData = $.validationEngine.settings.allrules[customAjaxRule].extraData; } else { extraData = ""; } /* AJAX VALIDATION HAS ITS OWN UPDATE AND BUILD UNLIKE OTHER RULES */ if (!ajaxisError) { $.ajax({ type: "POST", url: postfile, async: true, data: "validateValue=" + fieldValue + "&validateId=" + fieldId + "&validateError=" + customAjaxRule + extraData, beforeSend: function () { // BUILD A LOADING PROMPT IF LOAD TEXT EXIST if ($.validationEngine.settings.allrules[customAjaxRule].alertTextLoad) { if (!$("div." + fieldId + "formError")[0]) { return $.validationEngine.buildPrompt(ajaxCaller, $.validationEngine.settings.allrules[customAjaxRule].alertTextLoad, "load"); } else { $.validationEngine.updatePromptText(ajaxCaller, $.validationEngine.settings.allrules[customAjaxRule].alertTextLoad, "load"); } } }, error: function (data, transport) { $.validationEngine.debug("error in the ajax: " + data.status + " " + transport) }, success: function (data) { // GET SUCCESS DATA RETURN JSON data = eval("(" + data + ")"); // GET JSON DATA FROM PHP AND PARSE IT ajaxisError = data.jsonValidateReturn[2]; customAjaxRule = data.jsonValidateReturn[1]; ajaxCaller = $("#" + data.jsonValidateReturn[0])[0]; fieldId = ajaxCaller; ajaxErrorLength = $.validationEngine.ajaxValidArray.length; existInarray = false; if (ajaxisError == false) { // DATA FALSE UPDATE PROMPT WITH ERROR; _checkInArray(false) // Check if ajax validation alreay used on this field if (!existInarray) { // Add ajax error to stop submit $.validationEngine.ajaxValidArray[ajaxErrorLength] = new Array(2); $.validationEngine.ajaxValidArray[ajaxErrorLength][0] = fieldId; $.validationEngine.ajaxValidArray[ajaxErrorLength][1] = false; existInarray = false; } $.validationEngine.ajaxValid = false; promptText += $.validationEngine.settings.allrules[customAjaxRule].alertText + "
"; $.validationEngine.updatePromptText(ajaxCaller, promptText, "", true); } else { _checkInArray(true); $.validationEngine.ajaxValid = true; if ($.validationEngine.settings.allrules[customAjaxRule].alertTextOk) { // NO OK TEXT MEAN CLOSE PROMPT $.validationEngine.updatePromptText(ajaxCaller, $.validationEngine.settings.allrules[customAjaxRule].alertTextOk, "pass", true); } else { ajaxValidate = false; $.validationEngine.closePrompt(ajaxCaller); } } function _checkInArray(validate) { for (x = 0; x < ajaxErrorLength; x++) { if ($.validationEngine.ajaxValidArray[x][0] == fieldId) { $.validationEngine.ajaxValidArray[x][1] = validate; existInarray = true; } } } } }); } } function _confirm(caller, rules, position) { // VALIDATE FIELD MATCH confirmField = rules[position + 1]; if ($(caller).attr('value') != $("#" + confirmField).attr('value')) { $.validationEngine.isError = true; promptText += $.validationEngine.settings.allrules["confirm"].alertText + "
"; } } function _length(caller, rules, position) { // VALIDATE LENGTH startLength = eval(rules[position + 1]); endLength = eval(rules[position + 2]); feildLength = $(caller).attr('value').length; if (feildLength < startLength || feildLength > endLength) { $.validationEngine.isError = true; promptText += $.validationEngine.settings.allrules["length"].alertText + startLength + $.validationEngine.settings.allrules["length"].alertText2 + endLength + $.validationEngine.settings.allrules["length"].alertText3 + "
" } } function _maxCheckbox(caller, rules, position) { // VALIDATE CHECKBOX NUMBER nbCheck = eval(rules[position + 1]); groupname = $(caller).attr("name"); groupSize = $("input[name='" + groupname + "']:checked").size(); if (groupSize > nbCheck) { $.validationEngine.showTriangle = false; $.validationEngine.isError = true; promptText += $.validationEngine.settings.allrules["maxCheckbox"].alertText + "
"; } } function _minCheckbox(caller, rules, position) { // VALIDATE CHECKBOX NUMBER nbCheck = eval(rules[position + 1]); groupname = $(caller).attr("name"); groupSize = $("input[name='" + groupname + "']:checked").size(); if (groupSize < nbCheck) { $.validationEngine.isError = true; $.validationEngine.showTriangle = false; promptText += $.validationEngine.settings.allrules["minCheckbox"].alertText + " " + nbCheck + " " + $.validationEngine.settings.allrules["minCheckbox"].alertText2 + "
"; } } return($.validationEngine.isError) ? $.validationEngine.isError : false; }, submitForm: function (caller) { if ($.validationEngine.settings.ajaxSubmit) { if ($.validationEngine.settings.ajaxSubmitExtraData) { extraData = $.validationEngine.settings.ajaxSubmitExtraData; } else { extraData = ""; } $.ajax({ type: "POST", url: $.validationEngine.settings.ajaxSubmitFile, async: true, data: $(caller).serialize() + "&" + extraData, error: function (data, transport) { $.validationEngine.debug("error in the ajax: " + data.status + " " + transport) }, success: function (data) { if (data == "true") { // EVERYTING IS FINE, SHOW SUCCESS MESSAGE $(caller).css("opacity", 1) $(caller).animate({opacity: 0, height: 0}, function () { $(caller).css("display", "none"); $(caller).before("
" + $.validationEngine.settings.ajaxSubmitMessage + "
"); $.validationEngine.closePrompt(".formError", true); $(".ajaxSubmit").show("slow"); if ($.validationEngine.settings.success) { // AJAX SUCCESS, STOP THE LOCATION UPDATE $.validationEngine.settings.success && $.validationEngine.settings.success(); return false; } }) } else { // HOUSTON WE GOT A PROBLEM (SOMETING IS NOT VALIDATING) data = eval("(" + data + ")"); if (!data.jsonValidateReturn) { $.validationEngine.debug("you are not going into the success fonction and jsonValidateReturn return nothing"); } errorNumber = data.jsonValidateReturn.length for (index = 0; index < errorNumber; index++) { fieldId = data.jsonValidateReturn[index][0]; promptError = data.jsonValidateReturn[index][1]; type = data.jsonValidateReturn[index][2]; $.validationEngine.buildPrompt(fieldId, promptError, type); } } } }) return true; } if ($.validationEngine.settings.success) { // AJAX SUCCESS, STOP THE LOCATION UPDATE if ($.validationEngine.settings.unbindEngine) { $(caller).unbind("submit") } $.validationEngine.settings.success && $.validationEngine.settings.success(); return true; } return false; }, buildPrompt: function (caller, promptText, type, ajaxed) { // ERROR PROMPT CREATION AND DISPLAY WHEN AN ERROR OCCUR if (!$.validationEngine.settings) { $.validationEngine.defaultSetting() } var divFormError = document.createElement('div'); var formErrorContent = document.createElement('div'); linkTofield = $.validationEngine.linkTofield(caller) $(divFormError).addClass("formError") if (type == "pass") { $(divFormError).addClass("greenPopup") } if (type == "load") { $(divFormError).addClass("blackPopup") } if (ajaxed) { $(divFormError).addClass("ajaxed") } $(divFormError).addClass(linkTofield); $(formErrorContent).addClass("formErrorContent"); $("body").append(divFormError); $(divFormError).append(formErrorContent); if ($.validationEngine.showTriangle != false) { // NO TRIANGLE ON MAX CHECKBOX AND RADIO var arrow = document.createElement('div'); $(arrow).addClass("formErrorArrow"); $(divFormError).append(arrow); if ($.validationEngine.settings.promptPosition == "bottomLeft" || $.validationEngine.settings.promptPosition == "bottomRight") { $(arrow).addClass("formErrorArrowBottom") $(arrow).html('
'); } if ($.validationEngine.settings.promptPosition == "topLeft" || $.validationEngine.settings.promptPosition == "topRight") { $(divFormError).append(arrow); $(arrow).html('
'); } } $(formErrorContent).html(promptText) callerTopPosition = $(caller).offset().top; callerleftPosition = $(caller).offset().left; callerWidth = $(caller).width(); inputHeight = $(divFormError).height(); /* POSITIONNING */ if ($.validationEngine.settings.promptPosition == "topRight") { callerleftPosition += callerWidth - 30; callerTopPosition += -inputHeight - 10; } if ($.validationEngine.settings.promptPosition == "topLeft") { callerTopPosition += -inputHeight - 10; } if ($.validationEngine.settings.promptPosition == "centerRight") { callerleftPosition += callerWidth + 13; } if ($.validationEngine.settings.promptPosition == "bottomLeft") { callerHeight = $(caller).height(); callerleftPosition = callerleftPosition; callerTopPosition = callerTopPosition + callerHeight + 15; } if ($.validationEngine.settings.promptPosition == "bottomRight") { callerHeight = $(caller).height(); callerleftPosition += callerWidth - 30; callerTopPosition += callerHeight + 15; } $(divFormError).css({ top: callerTopPosition, left: callerleftPosition, opacity: 0 }) return $(divFormError).animate({"opacity": 0.87}, function () { return true; }); }, updatePromptText: function (caller, promptText, type, ajaxed) { // UPDATE TEXT ERROR IF AN ERROR IS ALREADY DISPLAYED linkTofield = $.validationEngine.linkTofield(caller); var updateThisPrompt = "." + linkTofield; if (type == "pass") { $(updateThisPrompt).addClass("greenPopup") } else { $(updateThisPrompt).removeClass("greenPopup") } ; if (type == "load") { $(updateThisPrompt).addClass("blackPopup") } else { $(updateThisPrompt).removeClass("blackPopup") } ; if (ajaxed) { $(updateThisPrompt).addClass("ajaxed") } else { $(updateThisPrompt).removeClass("ajaxed") } ; $(updateThisPrompt).find(".formErrorContent").html(promptText); callerTopPosition = $(caller).offset().top; inputHeight = $(updateThisPrompt).height(); if ($.validationEngine.settings.promptPosition == "bottomLeft" || $.validationEngine.settings.promptPosition == "bottomRight") { callerHeight = $(caller).height(); callerTopPosition = callerTopPosition + callerHeight + 15; } if ($.validationEngine.settings.promptPosition == "centerRight") { callerleftPosition += callerWidth + 13; } if ($.validationEngine.settings.promptPosition == "topLeft" || $.validationEngine.settings.promptPosition == "topRight") { callerTopPosition = callerTopPosition - inputHeight - 10; } $(updateThisPrompt).animate({top: callerTopPosition}); }, linkTofield: function (caller) { linkTofield = $(caller).attr("id") + "formError"; linkTofield = linkTofield.replace(/\[/g, ""); linkTofield = linkTofield.replace(/\]/g, ""); return linkTofield; }, closePrompt: function (caller, outside) { // CLOSE PROMPT WHEN ERROR CORRECTED if (!$.validationEngine.settings) { $.validationEngine.defaultSetting() } if (outside) { $(caller).fadeTo("fast", 0, function () { $(caller).remove(); }); return false; } if (!ajaxValidate) { linkTofield = $.validationEngine.linkTofield(caller); closingPrompt = "." + linkTofield; $(closingPrompt).fadeTo("fast", 0, function () { $(closingPrompt).remove(); }); } }, debug: function (error) { if (!$("#debugMode")[0]) { $("body").append("
This is a debug mode, you got a problem with your form, it will try to help you, refresh when you think you nailed down the problem
"); } $(".debugError").append("
" + error + "
"); }, submitValidation: function (caller) { // FORM SUBMIT VALIDATION LOOPING INLINE VALIDATION var stopForm = false; $.validationEngine.ajaxValid = true; $(caller).find(".formError").remove(); var toValidateSize = $(caller).find("[class*=validate]").size(); $(caller).find("[class*=validate]").each(function () { linkTofield = $.validationEngine.linkTofield(this); if (!$("." + linkTofield).hasClass("ajaxed")) { // DO NOT UPDATE ALREADY AJAXED FIELDS (only happen if no normal errors, don't worry) var validationPass = $.validationEngine.loadValidation(this); return(validationPass) ? stopForm = true : ""; } ; }); ajaxErrorLength = $.validationEngine.ajaxValidArray.length; // LOOK IF SOME AJAX IS NOT VALIDATE for (x = 0; x < ajaxErrorLength; x++) { if ($.validationEngine.ajaxValidArray[x][1] == false) { $.validationEngine.ajaxValid = false; } } if (stopForm || !$.validationEngine.ajaxValid) { // GET IF THERE IS AN ERROR OR NOT FROM THIS VALIDATION FUNCTIONS if ($.validationEngine.settings.animateSubmit) { destination = $(".formError:not('.greenPopup'):first").offset().top; $(".formError:not('.greenPopup')").each(function () { testDestination = $(this).offset().top; if (destination > testDestination) { destination = $(this).offset().top; } }) $("html:not(:animated),body:not(:animated)").animate({scrollTop: destination}, 1100); } return true; } else { return false; } } } })(jQuery);