// ------------------------------------------------------------------------------------------ // Form Validation Behavior // ------------------------------------------------------------------------------------------ if(wFORMS) { // Component properties // wFORMS.functionName_formValidation is defined at the bottom of this file // Those should be moved inside wFORMS.behaviors['validation']. Stays here for now for backward compatibility wFORMS.preventSubmissionOnEnter = false; // prevents submission when pressing the 'enter' key. Set to true if pagination behavior is used. wFORMS.showAlertOnError = true; // sets to false to not show the alert when a validation error occurs. wFORMS.className_required = "required"; wFORMS.className_validationError_msg = "errMsg"; wFORMS.className_validationError_fld = "errFld"; wFORMS.classNamePrefix_validation = "validate"; wFORMS.idSuffix_fieldError = "-E"; wFORMS.behaviors['validation'] = { // Error messages. This may be overwritten in a separate js file for localization or customization purposes. errMsg_required : "This field is required. ", errMsg_alpha : "The text must use alphabetic characters only (a-z, A-Z). Numbers are not allowed.", errMsg_email : "This does not appear to be a valid email address.", errMsg_integer : "Please enter an integer.", errMsg_float : "Please enter a number (ex. 1.9).", errMsg_password : "Unsafe password. Your password should be between 4 and 12 characters long and use a combinaison of upper-case and lower-case letters.", errMsg_alphanum : "Please use alpha-numeric characters only [a-z 0-9].", errMsg_date : "This does not appear to be a valid date.", errMsg_notification : "%% error(s) detected. Your form has not been submitted yet.\nPlease check the information you provided.", // %% will be replaced by the actual number of errors. errMsg_custom : "Please enter a valid value.", // Class Names className_allRequired : "allrequired", // first page w/ error in a multi-page form jumpToErrorOnPage : null, currentPageIndex : -1, // do not submit fields turned off by switch behavior submitSwitchedOffFields : false, switchedOffFields : [], // ------------------------------------------------------------------------------------------ // evaluate: check if the behavior applies to the given node. Adds event handlers if appropriate // ------------------------------------------------------------------------------------------ evaluate: function(node) { if(node.tagName.toUpperCase()=="FORM") { // functionName_formValidation can be a reference to a function, or a string with the name of the function. // avoid using typeof if(wFORMS.functionName_formValidation.toString()==wFORMS.functionName_formValidation) { // this is a string, not a function wFORMS.functionName_formValidation = eval(wFORMS.functionName_formValidation); } wFORMS.helpers.addEvent(node,'submit',wFORMS.functionName_formValidation); //wFORMS.debug('validation/evaluate: FORM '+ node.id,3); } }, // ------------------------------------------------------------------------------------------ // init: executed once evaluate has been applied to all elements // ------------------------------------------------------------------------------------------ init: function() { }, // ------------------------------------------------------------------------------------------ // run: executed when the behavior is activated // ------------------------------------------------------------------------------------------ run: function(e) { var element = wFORMS.helpers.getSourceElement(e); if(!element) element = e; //wFORMS.debug('validation/run: ' + element.id , 5); var currentPageOnly = arguments.length>1 ? arguments[1]:false; // arguments[1] : (wFORMS.hasBehavior('paging') && wFORMS.behaviors['paging'].behaviorInUse); wFORMS.behaviors['validation'].switchedOffFields = []; wFORMS.behaviors['validation'].jumpToErrorOnPage = null; // on multi-page forms we need to prevent the submission when the 'enter' key is pressed // (doesn't work in Opera. Further tests needed in IE and Safari) if(wFORMS.preventSubmissionOnEnter) { if(element.type && element.type.toLowerCase()=='text') // source element is a text field, the form was submitted with the 'enter' key. return wFORMS.preventEvent(e); } // make sure we have the form element while (element && element.tagName.toUpperCase() != 'FORM') { element = element.parentNode; } var nbErrors = wFORMS.behaviors['validation'].validateElement(element, currentPageOnly, true); // save the value in a property if someone else needs it. wFORMS.behaviors['validation'].errorCount = nbErrors; if (nbErrors > 0) { if(wFORMS.behaviors['validation'].jumpToErrorOnPage) { wFORMS.behaviors['paging'].gotoPage(wFORMS.behaviors['validation'].jumpToErrorOnPage); } if(wFORMS.showAlertOnError){ wFORMS.behaviors['validation'].showAlert(nbErrors); } return wFORMS.helpers.preventEvent(e); } // Remove switched-off content if any // Note: in multi-page behavior the validation is run on "page next" without submitting the form. // In this situation (currentPageOnly==true) switched-off conditionals should not be removed. if(!wFORMS.behaviors['validation'].submitSwitchedOffFields && !currentPageOnly) { for(var i=0; i < wFORMS.behaviors['validation'].switchedOffFields.length; i++) { var element = wFORMS.behaviors['validation'].switchedOffFields[i]; while(element.childNodes[0]) element.removeChild(element.childNodes[0]); } } return true; }, // ------------------------------------------------------------------------------------------ // remove: executed if the behavior should not be applied anymore // ------------------------------------------------------------------------------------------ remove: function() { }, // ------------------------------------------------------------------------------------------ // validation functions // ------------------------------------------------------------------------------------------ validateElement: function(element /*, currentPageOnly, deep */) { var deep = arguments.length>2 ? arguments[2] : true; // used in multi-page forms var currentPageOnly = arguments[1] ? arguments[1] : false; var wBehavior = wFORMS.behaviors['validation']; // shortcut // do not validate elements that are in a OFF-Switch // Note: what happens if an element is the target of 2+ switches, some ON and some OFF ? if(wFORMS.hasBehavior('switch') && wFORMS.helpers.hasClassPrefix(element,wFORMS.classNamePrefix_offState)) { if(!wBehavior.submitSwitchedOffFields) { wBehavior.switchedOffFields.push(element); } return 0; } // do not validate elements that are not in the current page (Paging Behavior) if(wFORMS.hasBehavior('paging') && wFORMS.helpers.hasClass(element,wFORMS.className_paging)) { if(!wFORMS.helpers.hasClass(element,wFORMS.className_pagingCurrent) && currentPageOnly) return 0; wBehavior.currentPageIndex = wFORMS.behaviors['paging'].getPageIndex(element); } var nbErrors = 0; // check if required if(!wBehavior.checkRequired(element)) { wBehavior.showError(element, wBehavior.errMsg_required); nbErrors++; //wFORMS.debug('validation/error: [required]' + element.id + '('+nbErrors+')' , 5); } else { // input format validation if (wFORMS.helpers.hasClassPrefix(element,wFORMS.classNamePrefix_validation)) { var arrClasses = element.className.split(" "); for (j=0;j0 && !wBehavior.jumpToErrorOnPage) { wBehavior.jumpToErrorOnPage = wBehavior.currentPageIndex; } } // recursive loop if(deep) { for(var i=0; i < element.childNodes.length; i++) { if(element.childNodes[i].nodeType==1) { // Element Nodes only nbErrors += wBehavior.validateElement(element.childNodes[i], currentPageOnly, deep); } } } return nbErrors; }, // ------------------------------------------------------------------------------------------ checkRequired: function(element) { var wBehavior = wFORMS.behaviors['validation']; // shortcut if(wFORMS.helpers.hasClass(element,wFORMS.className_required)) { switch(element.tagName.toUpperCase()) { case "INPUT": var inputType = element.getAttribute("type"); if(!inputType) inputType = 'text'; // handles lame markup switch(inputType.toLowerCase()) { case "checkbox": return element.checked; break; case "radio": return element.checked; break; default: return !wBehavior.isEmpty(element.value); } break; case "SELECT": if(element.selectedIndex==-1) { // multiple select with no selection return false; } else return !wBehavior.isEmpty(element.options[element.selectedIndex].value); break; case "TEXTAREA": return !wBehavior.isEmpty(element.value); break; default: return wBehavior.checkOneRequired(element); break; } } else if(wFORMS.helpers.hasClass(element,wBehavior.className_allRequired)) { return wBehavior.checkAllRequired(element); } return true; }, checkOneRequired: function(element) { if(element.nodeType != 1) return false; var tagName = element.tagName.toUpperCase(); var wBehavior = wFORMS.behaviors['validation']; if(tagName == "INPUT" || tagName == "SELECT" || tagName == "TEXTAREA" ) { var value = wBehavior.getFieldValue(element); if(!wBehavior.isEmpty(value)) { return true; } } for(var i=0; i