//<script language="javascript">
/*=============================================================================
 WebSolvers Framework Library
 Copyright 2003, WebSolvers, Inc., All Rights Reserved.

 Library Validation
 Cross-Browser/Platform common Validation library
 
 Revision History:
 6-4-03 Created

 Provides
 The following validation types are provided
	skip
	req([if variable][, [if value]])
	join([string])
	label('[string]')	- overrides the label provided in the form.
	read				- Sets the field to read only (does not
						allow input from user.
	onclick('[code]')	- Sets the onclick event handler
	onchange('[code]')	- Sets the onchange event handler
	end([string],[string],...) - value must end with one of the following.

  Notes:
=============================================================================

 The WebSolvers Framework Library may be used and/or modified by anyone owning
 the original work as it was incorporated into an original development project
 so long as this copyright notice and the comments above remain intact.  

 By using this code you agree to indemnify WebSolvers, Inc. from any liability
 that might arise from its use.

 This code may not be sold exclusively or as a part of other code without prior 
 written consent and is expressly forbidden.

 Obtain permission before redistributing this software over the Internet or 
 in any other medium. In all cases the copyright and header must remain intact. 
============================================================================= */

if(!window.dhtml) {
	alert("WFL Libraries not installed, or installed after Forms!");
}

function processForm() {
  var i = 0;
  var frm = null;
  var strID = "";
  for(i = 0 ; i < processForm.arguments.length; i++) {
    strID = processForm.arguments[i];
    if(strID && strID.elements)
      frm = strID;
    else if(strID && strID.length)
      frm = document.forms[strID];

    if(frm)
      validate._procForm(frm, document);
  }
}

//======================================================================================
//                                 Internal Routines
//======================================================================================
function validate() {
  var i = 0, strArgs = "";
  
  for(i = 0; i < validate.arguments.length; i++) {
    strArgs += ",validate.arguments[" + i + "]";
  }
  
  if(strArgs && strArgs.length) {
    eval("processForm("+strArgs.substring(1,strArgs.length)+");");
  }
  
  return this._toValue();
}

validate._init = function() {
  if(this.__inited)
    return;

  this._validTag = new Array();  
  this._valid = new Array();  
    
  this.typeID = "valid";
  this.labelID = "label";
  this.noticeID = "notice";
  this.defaultID = "default";
	this.validateID = "validate";
	this.confirmID = "confirm";
  
  this.reqField = "_REQ";
  this.reqMessage = "A required field is missing.";    
    
  this.__inited = 1;
}

validate._resync = function() {
  this._init();

  this.procType = this._procType;
  
  this.getType = this._getType;
  this.getLabel = this._getLabel;
  this.getNotice = this._getNotice;
  this.getDefault = this._getDefault;
  this.getValidate = this._getValidate;
  this.getConfirm = this._getConfirm;
  this.notify = this._notify;
  
  this.addValidator = this._addValidator;
}

validate._procForm = function(frm, doc) {
	var i = 0;
	var j = 0;
	var field = null;
	var fields = null;
	var req = null;
	var labels = null;

	if(frm.__validated)
		return true;
		
	frm.__validated = 1;

	var onsubmit = frm.onsubmit;
  frm.onsubmit = formObject_TmpOnSubmit;
  
	if(!frm.index && frm.index != 0)
		frm.index = i;

	req = frm.elements[validate.reqField];
	if(req && req.length && !req.name) {
		req = req[0];
	}
	if(req && req.value && req.value.length) {
		req = req.value.split(',');
	}
	
	labels = doc.getElementsByTagName("LABEL");
	for(i = 0; i < labels.length; i++) {
		if(labels[i].form == frm) {
				if(labels[i].htmlFor) {
					dhtml.quickNorm(labels[i], doc);
					field = frm.elements[labels[i].htmlFor];
					if(field)
						field.htmlLabel = labels[i];
				}
		}
	}
	
	if(frm.elements.length) {
		frm._firstElement = frm.elements[0];
		frm._lastElement = frm.elements[frm.elements.length-1];
		field = null;
		for(i = 0; i < frm.elements.length; i++) {
			frm.elements[i]._prevElement = field;
			if(field)
				field._nextElement = frm.elements[i];
			field = frm.elements[i];
			if(!field.index && field.index != 0)
				field.index = i;
			if(!field.__fields && field.__fields != 0) {
				if(field.name && field.name.length)
					fields = frm.elements[field.name];
				else
					fields = null;
					
				if(fields && fields.length && !fields.type) {
					for(j = 0; j < fields.length; j++) {
						fields[j]._firstName = fields[0];
						fields[j]._lastName = fields[fields.length-1];
						fields[j].nameIndex = j;
						fields[j].__fields = 1;
						if(j > 0)
							fields[j]._prevName = fields[j-1];
						if(j < fields.length-1)
							fields[j]._nextName = fields[j+1];
					}
				} else {
					field._firstName = field;
					field._lastName = field;
					field.nameIndex = 0;
					field._fields = 0;
				}
			}
			if(!field.__valdiated) {
				if(req && req.length && (j = req.indexOf(field.name)) > -1) {
					field[valdiate.typeID] = "req";
					field['_' + validate.labelID] = valdiate.reqMessage;
				}
				validate.procType(dhtml.quickNorm(field, doc));
				if(this.getConfirm(field).length) {
					field.__onClickAfterConfirm = field.onclick;
					field.onclick = function(e) {
						if(!confirm(validate.getConfirm(this)))
							return false;
						else if(this.__onClickAfterConfirm)
							return this.__onClickAfterConfirm(e);
						else
							return true;
					}
				}
				if(this.getValidate(field).length) {
					field.__onClickAfterValid = field.onclick;
					field.onclick = function(e) {
						if(!this.form.validate())
							return false;
						else if(this.__onClickAfterValid)
							return __onClickAfterValid;
						else
							return true;
					}
				}
				field.__validated = frm.__validated;
			}
		}
	}

	if(!frm.validate)
		frm.validate = formObject_Validate;

	if(!frm.lock)
		frm.lock = formObject_Lock;
	if(!frm.unlock)
		frm.unlock = formObject_Unlock;

	frm.onsubmit = onsubmit;

	return true;
}

validate._procType = function(fld) {
	var type = this.getType(fld);
	var st = 0;
	var lt = -1;
	var pos = 0;
	var str = "";
	var func = null;
	var param = null;
	var prefunc = null;
	var tag = null;
	var esc = "";
	var aryType = null;
	var aryOpt = null;
	//IE on the mac does not support passive sub-expressions or non-greedy quantifiers! AAHRRG!
//  var reType = /^(.+?)(?:\((.*?)\))?(?:\||$)/;
//  var reParam = /^(?:'((?:[^']*'')*.*?)')|(?:"((?:[^"]*"")*.*?)")|(.*?)(?:,|$)/;
	var reType = /^([^\(|]+)(\(([^\)]*)\))?(\||$)/;
	var reParam = /^(('(([^']*'')*[^']*)')|("(([^"]*"")*[^"]*)")|([^,]*))(,|$)/;

	var i = 0;

	if(fld.__validated)
	  return fld;

	fld.__validated = 1;

	this._resync();

	fld._valFunc = new Array();
	fld._valParam = new Array();
	
	fld.validate = fieldObject_Validate;
	fld.isValid = fieldObject_IsValid;

	if(!fld.type || !fld.type.length)
		return fld;

  while(type && type.length && reType.test(type)) {
    aryType = reType.exec(type);

    type = type.substring(0, aryType.index) + type.substring(aryType[0].length, type.length);

		i = this._validTag.indexOf(aryType[1]);
		if(i > -1) {
			tag = this._valid[i];
			func = tag.func;
			prefunc = tag.prefunc;
			param = new Array();
			if(tag.params) {
				str = aryType[3];

				while(str && str.length && reParam.test(str) && (tag.params == -1 || param.length < tag.params)) {
					aryOpt = reParam.exec(str);

					var pval = '';

					if(aryOpt[3] || aryOpt[3] == 0) {
						pval += aryOpt[3].toString();
					}

					if(aryOpt[6] || aryOpt[6] == 0) {
						pval += aryOpt[6].toString();
					}

					if(aryOpt[8] || aryOpt[8] == 0) {
						pval += aryOpt[8].toString();
					}

					param.push(pval);

					str = str.substring(0, aryOpt.index) + str.substring(aryOpt[0].length, str.length);
				}
				aryOpt = null;
			}

			if(prefunc)
					prefunc(fld, param);
			if(func) {
				if(fld.__fields && func.__values == -2)
					fld.__joined = 1;
				fld._valFunc[i = fld._valFunc.length] = func;
				fld._valParam[i] = param;
			}
		}
  }

  aryType = null;
	
	return fld;
}

validate._prepField = function(field) {
	var fields = null;
	var i = 0;

  this._resync();

  validate.procType(field);

	if(!field.validate)
		return false;

	// we will cache results so we only need to
	// rebuild values is if the form was told to 
	// validate again. This also help protect against
	// infinite recursion
	if(field.__validated < field.form.__validated) {
		field._values = null;
		field._value = "";
	} else
		return true;

	if(!field.type || !field.type.length)
		return false;

	switch(field.type.substr(0,5).toLowerCase()) {
	case "selec":
		if(field.multiple) {
			field._values = new Array();
			for(i = 0; i < field.options.length; i++)
				if(field.options[i].selected)
					field._values[field._values.length] = field.options[i].value;
		} else if(field.selectedIndex > -1 && field.selectedIndex < field.options.length) {
			field._value = field.options[field.selectedIndex].value;
		}
		
		break;
	case "radio":;
		// We only test 1 value with radio buttons, since they can only return 1 value
		if(field != field._firstName)
			return false;

		while(field._nextName && !field.checked)
			field = field._nextName;
			
		if(field.checked)
			field._firstName._value = field.value
		else
			field._firstName._value = "";

		field = field._firstName;
	break;
	case "check":;
		// We only want to run check valid on the "root" field of a radio or check group
		if(field != field._firstName)
			return false;

		field._values = new Array();
		
		while(field._nextName) {
			if(field.checked)
				field._firstName._values[field._firstName._values.length] = field.value;
			field = field._nextName;
		}
		
		if(field.checked)
			field._firstName._values[field._firstName._values.length] = field.value;
			
		field = field._firstName;
		break;
	default:
		field._value = field.value;
		if(field.__joined && field.__fields && field == field._firstName) {
			field._values = new Array();
			field._values[0] = field.value;
			while(field._nextName) {
				field = field._nextName;
				field._firstName._values[field._firstName._values.length] = field.value;
			}
			field = field._firstName;
		} 
	}
	
	return true;
}

validate._notify = function(field) {
	var msg = "";
  this._resync();

	if(field._valError != " ") {
		if(field.type && field.type.length && field.type != "hidden" && field.focus)
			field.focus();
			
		if(field._cErr_func)
			msg = field._cErr_func(field._valError, field);
		else if(field._cErr_msg)
			msg = field._cErr_msg;
		else
		msg = field._valError;
		
		alert(this.getLabel(field, msg) + this.getNotice(field, "."));
	}
	
	return false;
}

validate._getType = function(field) {
  this._resync();

	var type = field.getAttribute(this.typeID);

	return (type && type.length ? type : "str");
}

validate._getLabel = function(field, msg) {
  this._resync();

	var label = field.getAttribute('_' + this.labelID);

	if(!label)
		label = field.getAttribute(this.labelID);

	if(!label && field.htmlLabel) 
		label = field.htmlLabel.getText();

	return (label && label.length ? label : field.name) + msg;
}

validate._getNotice = function(field, msg) {
  this._resync();

	var notice = field.getAttribute(this.noticeID);

	return (notice && notice.length ? notice : "") + msg;
}

validate._getDefault = function(field) {
  this._resync();

	var def = field.getAttribute(this.defaultID);

	return (def && def.length ? def : "");
}

validate._getValidate = function(field) {
  this._resync();

	var val = field.getAttribute(this.validateID);

	return (val && val.length ? val : "");
}

validate._getConfirm = function(field) {
  this._resync();

	var conf = field.getAttribute(this.confirmID);

	return (conf && conf.length ? conf : "");
}

validate._addValidator = function(tag, func, prefunc, params, paramesc, list) {
	var idx = 0;
	var j = 0;
	var idx2 = 0;
	var start = 5;

	if(list && !isNaN(parseInt(list)) && func) {
		func.__values = list;
		start++;
	}

	var type = new validatorObject(tag, func, prefunc, params, paramesc);

  this._resync();
	
	this._valid[idx = this._valid.length] = type;
	this._validTag[idx] = tag;

	if(arguments.length > start)
		for(j = start; j < arguments.length; j++) {
			tag = arguments[j];
			type = new validatorObject(tag, func, prefunc, params, paramesc);
			this._valid[idx2 = this._valid.length] = type;
			this._validTag[idx2] = tag;
		}
}

function validatorObject(tag, func, prefunc, params, paramesc) {
	this.tag = tag;
	this.func = func;
	this.prefunc = prefunc;
	this.params = params;
	this.paramEsc = paramesc;
}

function formObject_TmpOnSubmit() {
	alert('Please wait for the page to finish loading before submitting this form.');
	return false;
}

function formObject_Validate() {
	var i = 0;
	var func = null;

	this.__validated = (new Date()).getTime();

	validate._resync()
	for(i = 0; i < this.elements.length; i++)
		if(!this.elements[i].validate())
			return false;

	func = this.onvalidate;
  if(!func)
    eval("func=window." + this.name + "_Validate;");
  if(!func)
    eval("func=window." + this.name + "_onValidate;");
  if(!func)
    eval("func=window." + this.name + "_OnValidate;");

  if(func && !func(this))
    return false;

	return true;
}

function formObject_Lock(strMsg, intSecs) {
	var cmd = "";
	
	if(this._locked) {
		alert(strMsg);
		return false;
	}
	
	this._locked = true;
	if(intSecs && intSecs > 0) {
		cmd = "document.forms[" + this.index + "].unlock();";
		window.setTimeout(cmd, intSecs * 1000);
	}
	
	return true;
}

function formObject_Unlock() {
	this._locked = false;
}

function fieldObject_Validate() {
	if(!this.isValid())
		return validate.notify(this);
	else
		return true;
}

function fieldObject_IsValid() {
	var i = 0;
	var j = 0;
	var func = null;
	var params = null;
	var values = null;

	// If preField returns false we need to skip
	// validation, this means it "validates"
	if(!validate._prepField(this))
		return true;

	// This protects ud form circular loops by
	// dropping with the last isValid status
	// form.__validated should be updated before isValid is run again.
	if(this.__validated == this.form.__validated)
		return !this._valError.length;

	this.__validated = this.form.__validated;
	
	this._valError = "";	

	for(i = this._valFunc.length-1; i > -1 && !this._valError.length; i--) {
		func = this._valFunc[i];
		params = this._valParam[i];

		if(this._values && func.__values) {
			this._valError = func(this._values, params, this);
			// 1 means we take in an array but return a flat value eg join
			if(func.__values == 1) {
				this._value = func._value;
				this._values = null;
			} else
				this._values = func._values;
		} else if(this._values) {
			for(j = 0; j < this._values.length && !this._valError.length; j++) {
				this._valError = func(this._values[j], params, this);
				this._values[j] = func._value;
			}
		} else if(func.__values) {
			values = new Array();
			values[0] = this._value;
			this._valError = func(values, params, this);
			// -2 means we take in an array and force output of an array
			if(func.__values == -2)  {
				this._values = func._values;
				this._value = null;
			} else if(func._values.length) 
				this._value = func._values[0];
			else
				this._value = "";
		} else {
			this._valError = func(this._value, params, this);
			this._value = func._value;
		}
	}
	
	return !this._valError.length;
}

function validator_Skip(values) {
	var l = new Array();
	for(var j = 0; j < values.length; j++) {
		if(values[j] && values[j].toString().length)
			l[l.length] = values[j];
	}

	validator_Skip._values = l;
	
	return "";
}

function validator_Req(values, params, elem) {
	var el = null;
	var val = null;
	var i = 0;
	var f = 0;

	validator_Req._values = values;
  //If we have a parameter at position 0 it
  //means that we are only required if the
  //specified parameter is valid	

	if(params.length > 0) {
	  //Store the element specified
	  el = elem.form.elements[params[0]];
		//If we cannot find the element we silently fail
		if(!el)
		  return '';
		if(el.length && !el.type)
			el = el[0];
  }

  //If we have an element we will validate
  //it and pull its values, since they will
  //be needed further
  if(el) {
    //If we have an parameter at position 1 it means
    //we need to compare our val to it, if we have
    // a match then we proceed. 
    if(params.length > 1) {
      if(el.isValid()) {
				if(el._values)
	        val = el._values;
				else {
					val = new Array();
					val[0] = el._value;
				}
      } else
        val = new Array();
        
      if(!params[1].toString().trim().length && !val.length)
        f = 1;
        
      //Loop through all returned values looking for
      //one that matches our requirement
      for(i = 0; i < val.length && !f; i++)
        if(val[i] != null)
          f = (val[i].toString().trim() == params[1].toString().trim());

      //If we did not find any matches, we are done.        
      if(!f)
				return '';

      //Otherwise the field is required and we can test that now.
    } else {
      if(el.isValid()) {
				if(el._values)
	        val = el._values;
				else {
					val = new Array();
					val[0] = el._value;
				}
			} else
        return ' ';

      //If we have no values, then there is no requirement.
      if(!val || !val.length || !val[0] || !val[0].length)
        return '';
    }
  }

  //If the value has no length then we stop with an error.
	if(!values || !values.length)
		return ' is required';

  //Now we loop through all values checking them as well.
	for(var i = 0; i < values.length; i++)
		if((!values[i] && values[i] != 0) || !values[i].toString().trim().length)
			return ' is required';

  //Goody we are done and everything is correct.			
	return '';
}

function validator_Match(value, params, elem) {
	var el = null;
	var val = null;
	
	validator_Match._value = value;
	if(params[0]) {
		el = elem.form.elements[params[0]];
		if(el.length && !el.type)
			el = el[0];
		if(el) {
			if(el.isValid()) {
				if(el._values && el._values.length)
					val = el._values[0];
				else
					val = el._value;
			} else 
				return ' ';
		}
	}
	if(!value.length && val.length)
		return ' do not match';

	if(value.toString() != val.toString())
		return ' do not match';
			
	return '';
}

function validator_Dupe(values, params, elem) {
	var el = null;
	var vals = null;
	var idx = -1;
	var idx2 = 0;

	validator_Dupe._values = values;
	if(params && params.length > 0 && params[0]) {
		el = elem.form.elements[params[0]];
		if(el.length && !el.type)
			el = el[0];
		if(el) {
			if(el.isValid()) {
				if(el._values && el._values.length)
					vals = el._values;
				else {
					vals = new Array();
					vals[0] = el._value;
				}
			} else 
				return ' ';
		}
	}

	if(params && params.length > 1) {
		idx = parseInt(params[1], 10);
	} else {
		validator_Dupe._values = vals;
		return '';
	}

	idx2 = 0;
	if(params && params.length > 2) {
		idx2 = parseInt(params[2], 10);
	}

	if(idx2 > -1 && idx2 < vals.length && vals[idx2] || vales[idx2] == 0) {
		if(idx < 0)
			values.unshift(vals[idx2]);
		else if(idx > values.length)
			values.push(vals[idx2]);
		else
			values[idx] = vals[idx2];
	}

	return '';
}

function validator_Join(values, params) {
	validator_Join._values = new Array();
	validator_Join._values[0] = values.join(params[0]);
	
	return '';
}

function validator_End(value, params, elem) {
	var i = 0, j = 0;
	var match = 0;
	
	validator_End._value = value;
	if(value && value.toString().length) {
		match = 0;
		for(j = 0; j < params.length && !match; j++)
			match = (value.toString().substring(value.length-params[j].length, value.length) == params[j]);
			
		if(!match)
			return ' must end in [' + params.join(' or ') + ']';
	}
					
	return '';
}

function validator_EndI(value, params, elem) {
	var i = 0, j = 0;
	var match = 0;

	validator_EndI._value = value;
	if(value && value.toString().length) {
		match = 0;
		for(j = 0; j < params.length && !match; j++)
			match = (value.toString().substring(value.length-params[j].length, value.length).toLowerCase() == params[j].toLowerCase());
			
		if(!match)
			return ' must end in [' + params.join(' or ') + ']';
	}
					
	return '';
}

validate._resync();

validate.addValidator('skip', validator_Skip, null, null, null, -1);
		
validate.addValidator('req', validator_Req, null, 2, "'", -1);

validate.addValidator('match', validator_Match, null, 1, "'");

validate.addValidator('join', validator_Join, null, 1, "'", 2);

validate.addValidator('dupe', validator_Dupe, null, 3, "'", -2);

validate.addValidator('endi', validator_EndI, null, -1, "'");

validate.addValidator('end', validator_End, null, -1, "'");

validate.addValidator('label', null, function(elem, params) {
		elem[validate.labelID] = params[0];
	}, 1, "'");

validate.addValidator('notice', null, function(elem, params) {
		elem[validate.noticeID] = params[0];
	}, 1, "'");

validate.addValidator('cerr', null, function(elem, params) {
		if(params.length > 1) {
			if(window[param[1]])
				elem._cErr_func = window[param[1]];
			else
				elem._cErr_func = eval("function(msg, field) { " + param[1] + "; }");
		} else if(params.length)
			elem._cErr_msg = params[0];
		else
			elem._cErr_msg = ' is invalid';
	}, 1, "'");

validate.addValidator('read', null, function(elem, params) {
		elem.readonly = true;
		if(elem.setEvent)
			elem.setEvent("focus", function(e) { this.blur(); });
	});
	
validate.addValidator('onchange', null, function(elem, params) {
		var func = null;
		eval("func = function anonymous(e) { " + params[0] + "};");
		if(elem.setEvent)
			elem.setEvent("change", func);
	}, 1, "'");

validate.addValidator('onclick', null, function(elem, params) {
		var func = null;
		eval("func = function anonymous(e) { " + params[0] + "};");
		if(elem.setEvent)
			elem.setEvent("click", func);
	}, 1, "'");

validate.addValidator('select', null, function(elem, params) {
		if(elem.setEvent)
			elem.setEvent("focus", function(e) { this.select(); });
	});

validate.addValidator('tab', null, function(elem, params) {
		if(elem.setEvent)
			elem.setEvent("keyup", function(e) {
					if(this.value.length == this.maxLength && this._nextElement)
						this._nextElement.focus();
				});
	 });

validate.addValidator('debug', function (values, params, elem) {
	arguments.callee._values = values;
	
	alert(elem.name + '.values[' + values + ']');
				
	return '';
}, null, null, null, -1);
