|
<!--
VALIDATE_FORM.JS
Comprehensive solution for validating HTML forms.
Copyright (C) 2002, Jeff Epstein, jeff_epstein@yahoo.com, http://www.jeffyjeffy.com#download
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-->
<HTML>
<HEAD>
<TITLE>validate_form.js -- Example: Illegal Sub-Strings (2/2)</TITLE>
<SCRIPT LANGUAGE="JavaScript" TYPE='text/javascript'>
/**
VALIDATE_FORM.JS
Comprehensive solution for validating HTML forms.
Copyright (C) 2002, Jeff Epstein, jeff_epstein@yahoo.com, http://www.jeffyjeffy.com#download
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**/
/**
See validate_form_documentation.html for information.
NOTES TO SELF
//alert("The CODE for getRCBSMTrackerArrIdx=" + getRCBSMTrackerArrIdx);
I would like to add a function to get the number of elements that have a (any) value.
**/
//GLOBAL VARIABLES...start (do not alter this section)
var sDBG_INDENT = " ";
var asRCBSM_TRACKER_NAME = '';
var aiRCBSM_TRACKER_SEL_COUNT = '';
var aiRCBSM_TRACKER_ARR_IDX = '';
var iELEMENT_COUNT = -1;
var bFIRST_DEBUG_SCREEN_SEEN = false;
var sCURRENT_LENGTH_FOR_TA = '~CURRLEN~';
var bPHONE_ZIP_FORMATS_VALIDATED = false;
//GLOBAL VARIABLES...end
/**
All messages must be at least one character in length. If they are empty string, its as if they do not exist.
**/
function getFormErrorMsgs(f_orm, s_userErrorPrefix, i_debugPerScreen) {
//This initialization function must be the very first line.
initializeLocalVars();
if(!arePhoneZipFormatsValid()) {
return;
}
crashIfBadConfiguration(f_orm);
if(hasCrashed()) {
//For whatever reason utility.crash() was called, indicating
//an error has occured. Get out. Get out while you still
//can.
return;
}
outputDebugging(f_orm, i_debugPerScreen);
return getUserErrors(f_orm, s_userErrorPrefix);
}
/**
PRIVATE FUNCTIONS...start
**/
function arePhoneZipFormatsValid() {
if(bPHONE_ZIP_FORMATS_VALIDATED) {
//Phone and zip code formats are checked only once.
//They've already been checked once and are all were
//found to be valid.
return true;
}
//The formats have not yet been checked, or they were, but
//were found to be invalid.
var i = -1;
var siPMin = "";
var siPMax = "";
for(i = 1; i < 11; i++) {
siPMin = eval("siPHONE_" + i + "_MINIMUM");
siPMax = eval("siPHONE_" + i + "_MAXIMUM");
if(!isPhoneFormatValid('false', siPMin, siPMax)) {
alert("--- validate_form.js ERROR ---\n\nPhone number format invalid:\n\tsiPHONE_" + i + "_MINIMUM='" + eval("siPHONE_" + i + "_MINIMUM") + "'\n\tsiPHONE_" + i + "_MAXIMUM='" + eval("siPHONE_" + i + "_MAXIMUM") + "'\n\nThe specific error message follows...");
isPhoneFormatValid('true', siPMin, siPMax);
return false;
}
}
var siZRMin = "";
var siZRMax = "";
var siZAMin = "";
var siZAMax = "";
for(i = 1; i < 11; i++) {
siZRMin = eval("siZIP_" + i + "_RQD_MINIMUM");
siZRMax = eval("siZIP_" + i + "_RQD_MAXIMUM");
siZAMin = eval("siZIP_" + i + "_ALT_MINIMUM");
siZAMax = eval("siZIP_" + i + "_ALT_MAXIMUM");
if(!isZipFormatValid('false', siZRMin, siZRMax, siZAMin, siZAMax)) {
alert("--- validate_form.js ERROR ---\n\nZip code format invalid:\n\tsiZIP_" + i + "_RQD_MINIMUM='" + eval("siZIP_" + i + "_RQD_MINIMUM") + "'\n\tsiZIP_" + i + "_RQD_MAXIMUM='" + eval("siZIP_" + i + "_RQD_MAXIMUM") + "'\n\tsiZIP_" + i + "_ALT_MINIMUM='" + eval("siZIP_" + i + "_ALT_MINIMUM") + "'\n\tsiZIP_" + i + "_ALT_MAXIMUM='" + eval("siZIP_" + i + "_ALT_MAXIMUM") + "'\n\nThe specific error message follows...");
isZipFormatValid('true', siZRMin, siZRMax, siZAMin, siZAMax)
return false;
}
}
bPHONE_ZIP_FORMATS_VALIDATED = true;
return true;
}
function crashIfBadConfiguration(f_orm) {
crashIfMissing(f_orm, 'f_orm', 'validate_form.getFormErrorMsgs');
crashIfBadBSSA('f_orm.asGlobalBadSubStrs', f_orm.asGlobalBadSubStrs);
f_orm.bsGlobalTrimSpaces = getOptBooleanStringVF(f_orm.bsGlobalTrimSpaces, "f_orm.bsGlobalTrimSpaces");
if(hasCrashed()) {
return;
}
for(var i = 0; i < f_orm.length; i++) {
if(f_orm[i].type == "text" || f_orm[i].type == "password") {
crashIfBadCfg_text(f_orm, f_orm[i]);
} else if(f_orm[i].type == "textarea") {
crashIfBadCfg_textarea(f_orm, f_orm[i]);
} else if(f_orm[i].type == "checkbox" || f_orm[i].type == "select-multiple") {
crashIfBadCfg_cbsm(f_orm, i);
} else if(f_orm[i].type == "radio" || f_orm[i].type == "select-one") {
crashIfBadCfg_rso(f_orm, i);
}
}
}
function outputDebugging(f_orm, i_debugPerScreen) {
if(!i_debugPerScreen || i_debugPerScreen == -1) {
//No debugging is requested
return;
}
if(typeof(i_debugPerScreen) != "number" || i_debugPerScreen < 1) {
return crashVF("i_debugPerScreen is not required (currently '" + i_debugPerScreen + "'), but when provided, it must be a number (currently '" + typeof(i_debugPerScreen) + "') either equal to -1, or greater than zero.");
}
var iDebugItemsTotal = 0;
var iDebugItemsThisRound = 0;
var sDebugBuffer = '';
var sDebugThisItem = '';
for(var i = 0; i < f_orm.length; i++) {
if(f_orm[i].type == "text" || f_orm[i].type == "password") {
sDebugThisItem = getDebugging_text(f_orm, f_orm[i]);
} else if(f_orm[i].type == "textarea") {
sDebugThisItem = getDebugging_textarea(f_orm, f_orm[i]);
} else if(f_orm[i].type == "checkbox" || f_orm[i].type == "select-multiple") {
sDebugThisItem = getDebugging_cbsm(f_orm, i);
} else if(f_orm[i].type == "radio" || f_orm[i].type == "select-one") {
sDebugThisItem = getDebugging_rso(f_orm, i);
}
if(sDebugThisItem) {
iDebugItemsTotal++;
iDebugItemsThisRound++;
sDebugBuffer += sDebugThisItem + "\n";
if(iDebugItemsThisRound >= i_debugPerScreen) {
sDebugBuffer = getGlobalDebugging(sDebugBuffer, f_orm);
alert("--- validate_form.js DEBUGGING (" + (iDebugItemsTotal - iDebugItemsThisRound + 1) + " to " + iDebugItemsTotal + " of " + iELEMENT_COUNT + ") ---\n\n" + sDebugBuffer);
iDebugItemsThisRound = 0;
sDebugBuffer = '';
}
sDebugThisItem = '';
}
}
if(sDebugBuffer) {
sDebugBuffer = getGlobalDebugging(sDebugBuffer, f_orm);
alert("--- validate_form.js DEBUGGING (" + (iDebugItemsTotal - iDebugItemsThisRound + 1) + " to " + iDebugItemsTotal + " of " + iELEMENT_COUNT + ") ---\n\n" + sDebugBuffer);
}
}
function getGlobalDebugging(s_debugBuffer, f_orm) {
if(!bFIRST_DEBUG_SCREEN_SEEN) {
bFIRST_DEBUG_SCREEN_SEEN = true;
var sGlobalDebug = '';
if(f_orm.asGlobalBadSubStrs) {
sGlobalDebug = sDBG_INDENT + "f_orm.asGlobalBadSubStrs= [ " + f_orm.asGlobalBadSubStrs + " ]\n";
}
if(f_orm.bsGlobalTrimSpaces == 'true') {
sGlobalDebug += sDBG_INDENT + "f_orm.bsGlobalTrimSpaces= 'true'\n";
}
if(sGlobalDebug) {
return "--- GLOBAL SETTINGS ---\n" + sGlobalDebug + "\n\n" + s_debugBuffer;
}
}
//Either the first debugging screen has already been displayed, or
//this is the first screen, but there is no global settings
return s_debugBuffer;
}
function getUserErrors(f_orm, s_prefix) {
var sUserErrors = '';
for(var i = 0; i < f_orm.length; i++) {
if(f_orm[i].type == "text" || f_orm[i].type == "password") {
sUserErrors += getUserErrors_text(f_orm, i, s_prefix);
} else if(f_orm[i].type == "textarea") {
sUserErrors += getUserErrors_textarea(f_orm, i, s_prefix);
} else if(f_orm[i].type == "checkbox" || f_orm[i].type == "select-multiple") {
sUserErrors += getUserErrors_cbsm(f_orm, i, s_prefix);
} else if(f_orm[i].type == "radio" || f_orm[i].type == "select-one") {
sUserErrors += getUserErrors_rso(f_orm, i, s_prefix);
}
}
return sUserErrors;
}
/**
form_element must be provided, and a form element...START
**/
function getDebuggingNameType(form_element) {
return "--- " + form_element.name + " --- [" + form_element.type + "]\n";
}
function getDebuggingMsgRequired(s_msgRequired) {
if(s_msgRequired) {
return sDBG_INDENT + "sMsgRequired: '" + s_msgRequired + "'\n";
}
return '';
}
function getDebuggingValue(s_value) {
if(s_value) {
return sDBG_INDENT + "VALUE: '" + s_value + "'\n";
}
return '';
}
/**
form_element must be provided, and a form element...END
**/
/**
Do not call this function without first calling crashIfBadCfg_cbsm for the form-and-form-element.
**/
function getUserErrors_cbsm(f_orm, i_arrIdx, s_prefix) {
var feCbsm = f_orm[i_arrIdx];
var sMsgRequired = '';
var sMsgMCRange = '';
var iMCMin = '';
var iMCMax = '';
if(feCbsm.type == "checkbox") {
if(getFirstArrIdx(feCbsm.name) != i_arrIdx) {
//This checkbox has already had its user errors retrieved.
return '';
}
//This checkbox has not yet had its user errors retrieved.
sMsgRequired = f_orm[feCbsm.name + ".sMsgRequired"];
sMsgMCRange = f_orm[feCbsm.name + ".sMsgMCRange"];
iMCMin = f_orm[feCbsm.name + ".iMCMin"];
iMCMax = f_orm[feCbsm.name + ".iMCMax"];
} else {
//this is a select-multiple type...which has not yet had its
//user errors retrieved.
sMsgRequired = feCbsm.sMsgRequired
sMsgMCRange = feCbsm.sMsgMCRange
iMCMin = feCbsm.iMCMin
iMCMax = feCbsm.iMCMax
}
var iMCSelCount = getMCSelectedCount(feCbsm.name);
if(sMsgRequired && iMCSelCount < 1) {
return s_prefix + sMsgRequired + "\n";
}
//If its required, a value has been selected.
if(iMCSelCount < 1) {
//Its not required, and no value has been selected,
//which is okay.
return '';
}
if((iMCMin && iMCMin > iMCSelCount) ||
(iMCMax && iMCMax < iMCSelCount)) {
return s_prefix + sMsgMCRange + "\n";
}
return '';
}
/**
Do not call this function without first calling crashIfBadCfg_cbsm for the form-and-form-element.
**/
function getDebugging_cbsm(f_orm, i_arrIdx) {
var feCbsm = f_orm[i_arrIdx];
var sMsgRequired = '';
var sMsgMCRange = '';
var iMCMin = '';
var iMCMax = '';
if(feCbsm.type == "checkbox") {
if(getFirstArrIdx(feCbsm.name) != i_arrIdx) {
//This checkbox has already been debugged.
return '';
}
//This checkbox has not yet been debugged
sMsgRequired = f_orm[feCbsm.name + ".sMsgRequired"];
sMsgMCRange = f_orm[feCbsm.name + ".sMsgMCRange"];
iMCMin = f_orm[feCbsm.name + ".iMCMin"];
iMCMax = f_orm[feCbsm.name + ".iMCMax"];
} else {
//this is a select-multiple type...which has not yet been debugged.
sMsgRequired = feCbsm.sMsgRequired
sMsgMCRange = feCbsm.sMsgMCRange
iMCMin = feCbsm.iMCMin
iMCMax = feCbsm.iMCMax
}
var s = getDebuggingNameType(feCbsm) + getDebuggingMsgRequired(sMsgRequired);
if(sMsgMCRange) {
s += sDBG_INDENT + "sMsgMCRange: '" + sMsgMCRange + "'\n";
if(iMCMin) {
s += sDBG_INDENT + sDBG_INDENT + "iMCMin: " + iMCMin + "\n";
}
if(iMCMax) {
s += sDBG_INDENT + sDBG_INDENT + "iMCMax: " + iMCMax + "\n";
}
}
var iMCSelCount = getMCSelectedCount(feCbsm.name);
if(iMCSelCount > 0) {
s += sDBG_INDENT + "NUMBER OF CHOICES SELECTED: " + iMCSelCount + "\n";
}
return s;
}
function crashIfBadCfg_cbsm(f_orm, i_arrIdx) {
conditionallyAddRCBSM(f_orm, i_arrIdx);
var feCbsm = f_orm[i_arrIdx];
var sMsgMCRange = '';
var iMCMin = '';
var iMCMax = '';
var iTotalOptions = -1;
var sErrVarPre = '';
var sErrVarPost = '';
if(feCbsm.type == "checkbox") {
if(getFirstArrIdx(feCbsm.name) != i_arrIdx) {
//This checkbox has already been validated.
return '';
}
//This checkbox has not yet been validated
sMsgMCRange = f_orm[feCbsm.name + ".sMsgMCRange"];
iMCMin = f_orm[feCbsm.name + ".iMCMin"];
iMCMax = f_orm[feCbsm.name + ".iMCMax"];
iTotalOptions = f_orm[feCbsm.name].length;
sErrVarPre = "f_orm['" + feCbsm.name;
sErrVarPost = "']";
} else {
//this is a select-multiple type...which has not yet been validated.
sMsgMCRange = feCbsm.sMsgMCRange;
iMCMin = feCbsm.iMCMin;
iMCMax = feCbsm.iMCMax;
iTotalOptions = feCbsm.length;
sErrVarPre = feCbsm.name;
sErrVarPost = "";
}
if(sMsgMCRange) {
if(!iMCMin && !iMCMax) {
return crashVF(sErrVarPre + ".sMsgMCRange" + sErrVarPost + " has been provided (currently '" + sMsgMCRange + "'), but neither " + sErrVarPre + ".iMCMin" + sErrVarPost + " nor " + sErrVarPre + ".iMCMax" + sErrVarPost + " have been provided. At least one of these bounds are required.");
}
if(iMCMin) {
if(!isInteger(iMCMin)) {
return crashVF(sErrVarPre + ".iMCMin" + sErrVarPost + " has been provided, but is not of type number. Currently of type '" + typeof(iMCMin) + "' and equal to '" + iMCMin + "'.");
}
if(iMCMin < 1 || iMCMin > iTotalOptions) {
return crashVF(sErrVarPre + ".iMCMin" + sErrVarPost + " has been provided (currently " + iMCMin + "), but is either less than one, or greater than the total number of options (" + iTotalOptions + ").");
}
}
if(iMCMax) {
if(!isInteger(iMCMax)) {
return crashVF(sErrVarPre + ".iMCMax" + sErrVarPost + " has been provided, but is not of type number. Currently of type '" + typeof(iMCMax) + "' and equal to '" + iMCMax + "'.");
}
if(iMCMax < 1 || iMCMax > iTotalOptions) {
return crashVF(sErrVarPre + ".iMCMax" + sErrVarPost + " has been provided (currently " + iMCMax + "), but is either less than one, or greater than the total number of options (" + iTotalOptions + ").");
}
}
if(iMCMin && iMCMax && iMCMin > iMCMax) {
return crashVF(sErrVarPre + ".sMsgMCRange" + sErrVarPost + " has been provided (currently '" + sMsgMCRange + "'), and both " + sErrVarPre + ".iMCMin" + sErrVarPost + " (currently " + iMCMin + ") and " + sErrVarPre + ".iMCMax" + sErrVarPost + " (currently " + iMCMax + ") have been provided. However, iMCMin must be less than or equal to iMCMax, which it is not.");
}
} else if(iMCMin || iMCMax) {
return crashVF(sErrVarPre + ".sMsgMCRange" + sErrVarPost + " has *not* been provided, but at least one of " + sErrVarPre + ".iMCMin" + sErrVarPost + " (currently '" + iMCMin + "') or " + sErrVarPre + ".iMCMax" + sErrVarPost + " (currently '" + iMCMax + "') has been provided.");
}
}
/**
Do not call this function without first calling crashIfBadCfg_rso for the form-and-form-element.
**/
function getUserErrors_rso(f_orm, i_arrIdx, s_prefix) {
var feRso = f_orm[i_arrIdx];
var sValue = '';
var sMsgRequired = '';
if(feRso.type == "radio") {
if(getFirstArrIdx(feRso.name) != i_arrIdx) {
//We already debugged this radio element.
return '';
}
sMsgRequired = f_orm[feRso.name + ".sMsgRequired"];
sValue = getRadioValue(f_orm, feRso.name);
} else if(feRso.selectedIndex > -1) {
sMsgRequired = feRso.sMsgRequired;
sValue = feRso[feRso.selectedIndex].value;
}
if(sMsgRequired && !sValue) {
return s_prefix + sMsgRequired + "\n";
}
//If its required, a value has been provided.
return '';
}
/**
Do not call this function without first calling crashIfBadCfg_rso for the form-and-form-element.
**/
function getDebugging_rso(f_orm, i_arrIdx) {
var feRso = f_orm[i_arrIdx];
var sValue = '';
var sMsgRequired = '';
if(feRso.type == "radio") {
if(getFirstArrIdx(feRso.name) != i_arrIdx) {
//We already debugged this radio element.
return '';
}
sMsgRequired = f_orm[feRso.name + ".sMsgRequired"];
sValue = getRadioValue(f_orm, feRso.name);
} else if(feRso.selectedIndex > -1) {
sMsgRequired = feRso.sMsgRequired;
sValue = feRso[feRso.selectedIndex].value;
}
return getDebuggingNameType(feRso) + getDebuggingMsgRequired(sMsgRequired) + getDebuggingValue(sValue);
}
function getRadioValue(f_orm, s_radioName) {
var feRadio = f_orm[s_radioName];
for(var i = 0; i < feRadio.length; i++) {
if(feRadio[i].checked) {
return feRadio[i].value;
}
}
return '';
}
function crashIfBadCfg_rso(f_orm, i_arrIdx) {
var feRso = f_orm[i_arrIdx];
if(feRso.type == "radio") {
conditionallyAddRCBSM(f_orm, i_arrIdx);
} else {
iELEMENT_COUNT++;
}
//Nothing to validate. The only attribute that
//can be associated to a radio or select-one type
//is sMsgRequired... Which either is or isn't...
//doesn't matter which.
}
function conditionallyAddRCBSM(f_orm, i_arrIdx) {
var feCbsm = f_orm[i_arrIdx];
if(wasRCBSMalreadyFound(feCbsm.name)) {
//We already analyzed this element.
return;
}
iELEMENT_COUNT++;
addRCBSMtoTracker(f_orm, feCbsm, i_arrIdx);
}
/**
Do not call this function without first calling crashIfBadCfg_textarea for the form-and-form-element.
**/
function getUserErrors_textarea(f_orm, i_arrIdx, s_prefix) {
var feTA = f_orm[i_arrIdx];
if(feTA.sMsgRequired && !feTA.value) {
return s_prefix + feTA.sMsgRequired + "\n";
}
if(!feTA.value) {
return '';
}
if(needsToBeTrimmed(f_orm, feTA)) {
feTA.value = trimSpaces(feTA.value);
}
if(feTA.sMsgBadLength &&
(feTA.value.length < feTA.iMinLength ||
feTA.value.length > feTA.iMaxLength)) {
return s_prefix + getBadLengthMsg(feTA) + '\n';
}
return getBadSubStrMessage(feTA.value, f_orm, feTA.asBadSubStrs, feTA.bsNoBadSubStrings, s_prefix, feTA.sMsgBadSubStr);
}
function getBadLengthMsg(fe_tta) {
var sMsg = fe_tta.sMsgBadLength;
var iCLArrIdx = sMsg.indexOf(sCURRENT_LENGTH_FOR_TA);
if(iCLArrIdx != -1) {
sMsg = sMsg.substring(0, iCLArrIdx) + fe_tta.value.length + sMsg.substring((iCLArrIdx + sCURRENT_LENGTH_FOR_TA.length), (sMsg.length + 1));
}
return sMsg;
}
function getBadSubStrMessage(s_value, f_orm, as_badSubStrs, bs_noBadSubStrings, s_prefix, s_errorMessage) {
if(!s_value) {
//Theres no value, so it can't have any illegal sub-string.
return '';
}
if(bs_noBadSubStrings == 'true') {
//This element is exempt.
return '';
}
//"x" is important...1/2
var asBadSubStrs = "x";
if(f_orm.asGlobalBadSubStrs) {
asBadSubStrs = f_orm.asGlobalBadSubStrs;
}
if(as_badSubStrs) {
asBadSubStrs = as_badSubStrs;
}
//"x" is important...2/2
if(asBadSubStrs == "x"
|