/**
 * (c) mobilware.com 2001-2006 All rights reserved
 * Portions Copyright 2005 massimocorner.com
 *  
 *	mwvalidate.js-	The Mobilware browser form validation JavaScript helpers
 *
 *	Platform	-	Browsers with JavaScript support
 *
 *	Author		-	Dean Quanne
 *
 *	Date		-	16:17 24 April 2006
 *
 *	Comments	-	Provides the logic to validate client-side forms using Javascript
 * 
 *	Assumption	-	None yet.	
 * 
 *	Tabs		-	4
 */

// This function deliberately avoid using innerHTML (a non-standard shortcut)
// since we want to have the sample working even if served with a xml mime-type. 
// So we stick with 100% standard DOM

function mwDisplayError(formNode, validators, errorMsg)
{
	var displayNode = document.getElementById("mwvalidateerrors");
	if ( displayNode == null ) // no error display section found
	{
		alert ( errorMsg );	// just display a dialog
		return;
	}
	var listNode = document.createElement("ul");
	for(var i=0;i<validators.length;i++){
	   var itemNode = document.createElement("li");
	   itemNode.appendChild(document.createTextNode(validators[i].message));
	   listNode.appendChild(itemNode);
	}

	displayNode.style.display = "block";
	displayNode.replaceChild(listNode, displayNode.firstChild);
	mwContainerHeight();
}

// Create all the validator objects required inside the document
function mwValidatorInit()
{
	var formNodes = document.getElementsByTagName("form");
	for(var i=0; i<formNodes.length; i++){
			// Attach a validator object to each form that requires it
			formNodes[i].mwValidator = new mwFormValidator(formNodes[i]);
			// Set the form node's onsubmit event 
			formNodes[i].onsubmit = function()
			{
				return mwValidateForm(this);
			}
	}
}

// Perform the validation
function mwValidateForm ( formNode )
{
	var errorMsg = "";
	var formValidator = formNode.mwValidator;
	// Be sure the form contains a validator object
	if ( formValidator )
	{
		var focusGiven = false;
		// This array will store all the field validators that contains errors
		// They may be required by the callback
		var invalidFields = new Array();
		// Validate all the fields
		for(var i=0; i<formValidator.validators.length; i++)
		{
			if(formValidator.validators[i].validate())
			{
				// Append to the global error string
				errorMsg += formValidator.validators[i].message + "\n";
				invalidFields[invalidFields.length] = formValidator.validators[i];
				// Give focus to the first invalid text/textarea field
				if(!focusGiven && (formValidator.validators[i].type == "text"))
				{
					formValidator.validators[i].getFocus();
					focusGiven = true;
				}
			}
		}
		if(errorMsg != "")
		{
			
			// We have errors, display them
			if(!formValidator.callback)
			{
				// We don't have callbacks, just display an alert
				alert(errorMsg);
			}
			else
			{
				// Invoke the callbak, it will take care of displaying the errors
				// eval(formValidator.callback + "(formNode, invalidFields, errorMsg)");
				mwDisplayError (formNode, invalidFields, errorMsg);
			}
		}
		else
		{
			// Everything is fine, disable form submission to avoid multiple submits
			// MW: disabled -- 	formValidator.blockSubmit();
		}
	}
 	return errorMsg.length == 0; 
}

/* Object constructors */

// Form validator
function mwFormValidator(formNode)
{
	// Store all the validator objects inside an array
	this.validators = new Array();
	// Add the specified callback only if the function is currently defined
	if(formNode.getAttribute("mwcallback") && window[formNode.getAttribute("mwcallback")]){
		this.callback = formNode.getAttribute("mwcallback");
	}
	else
	{
		this.callback = mwDisplayError;
	}
	var fieldsArray = mwGetTextfieldNodes(formNode);
	for(var i=0; i<fieldsArray.length; i++){

		// Create a validator for each text field
		this.validators[this.validators.length] = mwTextValidatorFactory(fieldsArray[i]);
		
		if(fieldsArray[i].getAttribute("type")){
			// Set the onchange event for each image upload validation
			if((fieldsArray[i].getAttribute("type").toLowerCase() == "file") &&	(fieldsArray[i].getAttribute("mwimage") == "true")){
				fieldsArray[i].onchange = function(){
					mwValidateImg(this);
				}
			}
		}
		if(fieldsArray[i].getAttribute("mwfilters")){
			// Call the filters on the onkeyup and onblur events
			fieldsArray[i].onkeyup = function(){
				mwFilterField(this);
			}
			fieldsArray[i].onblur = function(){
					//mwFilterField(this);
			}
		}
	}
	var selectNodes = formNode.getElementsByTagName("select");
	for(var j=0; j<selectNodes.length; j++){
		// Create a validator for each select element
		this.validators[this.validators.length] = mwSelectValidatorFactory(selectNodes[j]);
	}
	var boxTable = mwGetNodesTable(formNode, "checkbox");
	for(var boxName in boxTable){
		// Create a validator for each group of checkboxes
		this.validators[this.validators.length] = mwBoxValidatorFactory(boxTable[boxName]);
	}
	var radioTable = mwGetNodesTable(formNode, "radio");
	for(var radioName in radioTable){
		// Create a validator for each group of radios
		this.validators[this.validators.length] = mwRadioValidatorFactory(radioTable[radioName]);
	}
	// Store all the submit buttons
	this.buttons = mwGetSubmitNodes(formNode);
	// Define a method that can block multiple submits
	this.blockSubmit = function(){
		// Check to see if we want to disable submit buttons
		if(!formNode.getAttribute("mwblocksubmit") && !(formNode.getAttribute("mwblocksubmit") == "false")){
			// Disable each submit button
			for(var i=0; i<this.buttons.length; i++){
				if(this.buttons[i].getAttribute("mwwaitmessage")){
					this.buttons[i].value = this.buttons[i].getAttribute("mwwaitmessage");
				}
				this.buttons[i].disabled = true;
			}
		}
	}
}

// Abstract field validator constructor
function mwAbstractValidator(fieldNode)
{
	this.message = "";
	this.name = fieldNode.name;

	if(fieldNode.getAttribute("mwmessage"))
	{
		this.message = fieldNode.getAttribute("mwmessage");
	}
	var errorClass = "";
	if(fieldNode.getAttribute("mwerrorclass"))
	{
		errorClass = fieldNode.getAttribute("mwerrorclass");
	}
	this.flagInvalid = function()
	{
		// Append the CSS class to the existing one
		if(errorClass)
		{
			// Flag only if it's not already flagged
			if(fieldNode.className.indexOf(errorClass) == -1)
			{
				fieldNode.className = fieldNode.className + " " + errorClass;
			}
		}
		// Set the title attribute in order to show a tootip
		fieldNode.setAttribute("title", this.message);
	}
	this.flagValid = function()
	{
		// Remove the CSS class
		if(errorClass)
		{
			var regClass = new RegExp("\\b" + errorClass);
			fieldNode.className = fieldNode.className.replace(regClass, "");
		}
		fieldNode.removeAttribute("title");
	}
	this.validate = function()
	{
		// If the field contains error, flag it as invalid and return the error message
		if ( !this.isValid() )
		{
			this.flagInvalid();
			return true;
		}
		else
		{
			this.flagValid();
			return false;
		}
	}
}

// Create a validator for text and texarea fields
function mwTextValidatorFactory(fieldNode){
	// Create a generic validator, than add specific properties and methods as needed
	var obj = new mwAbstractValidator(fieldNode);
	obj.type = "text";
	var required = false;
	if(fieldNode.getAttribute("mwrequired")){
		required = fieldNode.getAttribute("mwrequired");
	}
	// Put focus and cursor inside the field
	obj.getFocus = function(){
		// This try block is required to solve an obscure issue with IE and hidden fields
		try{
			fieldNode.focus();
			fieldNode.select();
		}
		catch(exception){
		}
	}
	// Check if the field is empty
	obj.isEmpty = function(){
		return fieldNode.value == "";
	}
	// Check if the field is required
	obj.isRequired = function(){
		return required;
	}
	// Check if the field satisfy the rules associated with it
	// Be careful, this method contains multiple exit points!!!
	obj.isValid = function(){
		// The mwrequired="conditional" attribute has a special meaning. 
		// The field isn't strictly required, so it may sometimes be empty, 
		// but before we let it go, we need to check any rule that may apply to it
		if(obj.isEmpty() && (required != "conditional")){
			if(obj.isRequired()){
				return false;
			}
			else{
				return true;
			}
		}
		else{
			// Loop over all the available rules
			for(var rule in mwGlobalRules){
				// Check if the current rule is required for the field
				if(fieldNode.getAttribute("mw" + rule)){
					// Invoke the rule
					if(!eval("mwGlobalRules." + rule + "(fieldNode)")){
						return false;
					}
				}
			}
		}
		return true;
	}
	return obj;
}

// Create a validator for <select> fields
function PreviousmwSelectValidatorFactory(selectNode){
	// Create a generic validator, than add specific properties and methods as needed
	var obj = new mwAbstractValidator(selectNode);
	obj.type = "select";
	var invalidIndex;
	if(selectNode.getAttribute("mwinvalidindex")){
		invalidIndex = selectNode.getAttribute("mwinvalidindex");
	}
	var invalidValue;
	if(selectNode.getAttribute("mwinvalidvalue") != null){
		invalidValue = selectNode.getAttribute("mwinvalidvalue");
	}
	// Check if the select validate
	obj.isValid = function(){
		// Check for index
		if(selectNode.selectedIndex == invalidIndex){
			return false;
		}
		// Check for value
		if(selectNode.value == invalidValue){
			return false;
		}
		return true;
	}
	return obj;
}

// Create a validator for <select> fields
function mwSelectValidatorFactory(selectNode){
	// Create a generic validator, than add specific properties and methods as needed
	var obj = new mwAbstractValidator(selectNode);
	obj.type = "select";
	var invalidIndex;
	if(selectNode.getAttribute("mwinvalidindex")){
		invalidIndex = selectNode.getAttribute("mwinvalidindex");
	}
	var invalidValue;
	if(selectNode.getAttribute("mwinvalidvalue") != null){
		invalidValue = selectNode.getAttribute("mwinvalidvalue");
	}
	// Check if the select validate
	obj.isValid = function(){
	
		// Check if the start of the name indicates the field is disabled
		if ( selectNode.name.substring (0,11) == "mwdisabled-" )
			return true;
	
		// Check for index
		if(selectNode.selectedIndex == invalidIndex){
			return false;
		}
		// Check for value
		if(selectNode.value == invalidValue){
			return false;
		}
		return true;
	}
	return obj;
}

// Generic validator for grouped fields (radio and checkboxes)
function mwGroupValidatorFactory(buttonGroup){
	this.name = buttonGroup.name;
	this.message = "";
	this.errorClass = "";
	// Since fields from the same group can have conflicting attribute values, the last one win
	for(var i=0; i<buttonGroup.elements.length; i++){
		if(buttonGroup.elements[i].getAttribute("mwmessage")){
			this.message = buttonGroup.elements[i].getAttribute("mwmessage");
		}
		if(buttonGroup.elements[i].getAttribute("mwerrorclass")){
			this.errorClass = buttonGroup.elements[i].getAttribute("mwerrorclass");
		}
	}
	this.flagInvalid = function(){
		// Append the CSS class to the existing one
		if(this.errorClass){
			for(var i=0; i<buttonGroup.elements.length; i++){
				// Flag only if it's not already flagged
				if(buttonGroup.elements[i].className.indexOf(this.errorClass) == -1){
					buttonGroup.elements[i].className = buttonGroup.elements[i].className + " " + this.errorClass;
				}
				buttonGroup.elements[i].setAttribute("title", this.message);
			}
		}
	}
	this.flagValid = function(){
		// Remove the CSS class
		if(this.errorClass){
			var regClass = new RegExp("\\b" + this.errorClass);
			for(var i=0; i<buttonGroup.elements.length; i++){
				buttonGroup.elements[i].className = buttonGroup.elements[i].className.replace(regClass, "");
				buttonGroup.elements[i].removeAttribute("title");
			}
		}
	}
	this.validate = function(){
		var errorMsg = "";
		// If the field group contains error, flag it as invalid and return the error message
		if(!this.isValid()){
			errorMsg += this.message;
			this.flagInvalid();
		}
		else{
			this.flagValid();
		}
		return errorMsg;
	}
}

// Checkbox validator (one for each group of boxes sharing the same name)
function mwBoxValidatorFactory(boxGroup){
	var obj = new mwGroupValidatorFactory(boxGroup);
	obj.type = "box";
	var minchecked = 0;
	var maxchecked = boxGroup.elements.length;
	// Since checkboxes from the same group can have conflicting attribute values, the last one win
	for(var i=0; i<boxGroup.elements.length; i++){
		if(boxGroup.elements[i].getAttribute("mwminchecked")){
			minchecked = boxGroup.elements[i].getAttribute("mwminchecked");
		}
		if(boxGroup.elements[i].getAttribute("mwmaxchecked")){
			maxchecked = boxGroup.elements[i].getAttribute("mwmaxchecked");
		}
	}
	// Check if the boxes validate
	obj.isValid = function(){
		var checkCounter = 0;
		for(var i=0; i<boxGroup.elements.length; i++){
		    // For each checked box, increase the counter
			if(boxGroup.elements[i].checked){
				checkCounter++;
			}
		}
		return (checkCounter >=  minchecked) && (checkCounter <= maxchecked);
	}
	return obj;
}

// Radio validator (one for each group of radios sharing the same name)
function mwRadioValidatorFactory(radioGroup){
	var obj = new mwGroupValidatorFactory(radioGroup);
	obj.type = "radio";
	obj.required = false;
	// Since radios from the same group can have conflicting attribute values, the last one win
	for(var i=0; i<radioGroup.elements.length; i++){
		if(radioGroup.elements[i].getAttribute("mwrequired")){
			obj.required = radioGroup.elements[i].getAttribute("mwrequired");
		}
	}
	// Check if the radio validate
	obj.isValid = function(){
		if(obj.required){
			for(var i=0; i<radioGroup.elements.length; i++){
				// As soon as one is checked, we are fine
				if(radioGroup.elements[i].checked){
					return true;
				}
			}
			return false;
		}
		// It's not required, so it's fine
		else{
			return true;
		}	
	}
	return obj;
}

// This global objects store all the validation rules
// Every rule is stored as a method that accepts the field node as argument and return a boolean
var mwGlobalRules = new Object;
mwGlobalRules.datepattern = function(fieldNode){
	var globalObj = mwGlobalDatePatterns[fieldNode.getAttribute("mwdatepattern")];
	if(globalObj){
		// Split the date into 3 different bits using the separator
		var dateBits = fieldNode.value.split(globalObj.s);
		// First try to create a new date out of the bits
		var testDate = new Date(dateBits[globalObj.y], (dateBits[globalObj.m]-1), dateBits[globalObj.d]);
		// Make sure values match after conversion
		var isDate = (testDate.getFullYear() == dateBits[globalObj.y])
				 && (testDate.getMonth() == dateBits[globalObj.m]-1)
				 && (testDate.getDate() == dateBits[globalObj.d]);
		// If it's a date and it matches the RegExp, it's a go
		return isDate && globalObj.rex.test(fieldNode.value);
	}
}
mwGlobalRules.equalto = function(fieldNode){
	var twinNode = document.getElementById(fieldNode.getAttribute("mwequalto"));
	return twinNode.value == fieldNode.value;
}
mwGlobalRules.maxlength = function(fieldNode){
	if(fieldNode.value.length > fieldNode.getAttribute("mwmaxlength")){
		return false;
	}
	return true;
}
mwGlobalRules.maxnumber = function(fieldNode){
	if(parseFloat(fieldNode.value) > fieldNode.getAttribute("mwmaxnumber")){
		return false;
	}
	return true;
}
mwGlobalRules.minlength = function(fieldNode){
	if(fieldNode.value.length < fieldNode.getAttribute("mwminlength")){
		return false;
	}
	return true;
}
mwGlobalRules.minnumber = function(fieldNode){
	if(parseFloat(fieldNode.value) < fieldNode.getAttribute("mwminnumber")){
		return false;
	}
	return true;
}
mwGlobalRules.pattern = function(fieldNode){
	var patternText = fieldNode.getAttribute("mwpattern");
	var reg = mwGlobalPatterns[patternText];
	
	//alert ("mwGlobalules.pattern, patternText["+patternText+"]");
	//alert ( "substring == ["+patternText.substring ( 0, 2 )+"]" );
	if ( patternText.substring ( 0, 2 ) == "cc" ) // creditcard pattern validator
	{
			//alert ("entered if");
			// when mwpattern starts with cc, its format is "cc, card-type-field"
			// with the second comma seperated name being the credit card type
			// field name.
			var ccArray = patternText.split(",");
			//alert("ccArray["+ccArray+"]");
			//alert("ccArray[1]["+ccArray[1]+"]");
			var ccType = document.getElementById(ccArray[1]).value;
			var ccNumber = fieldNode.value;

			//alert ("mwGlobalules.pattern, ccNumber["+ccNumber+"], ccType["+ccType+"]");
			return mwCC ( ccNumber, ccType );
	}
	else
	{
		if ( reg )
		{
				return reg.test(fieldNode.value);
		}
		else{
			// If the pattern is missing, skip it
			return true;	
		}
	}
}

/* Image upload validation */

mwGlobalRules.image = function(fieldNode){
	// If the flag isn't defined we assume things are fine
	if(!fieldNode.isValidImg){
		fieldNode.isValidImg = "true";
	}
	return fieldNode.isValidImg == "true";
}

// Check the currently selected image and set a validity flag
function mwValidateImg(fieldNode){
	var imgURL = "file:///" + fieldNode.value;
	var img = new Image();
	img.maxSize =  fieldNode.getAttribute("mwimagemaxsize");
	img.maxWidth = fieldNode.getAttribute("mwimagemaxwidth");
	img.minWidth = fieldNode.getAttribute("mwimageminwidth");
	img.maxHeight = fieldNode.getAttribute("mwimagemaxheight");
	img.minHeight = fieldNode.getAttribute("mwimageminheight");
	// Store a reference to the input field
	img.fieldNode = fieldNode;
	// The image's data can be read only after loading. That's why we need a callback
	img.onload = mwValidateImgCallback;
	img.src = imgURL;
}

function mwValidateImgCallback(){
	var errorsCount = 0;
	// Check every constrain and increment the error counter accordingly
	if(this.fileSize && this.maxSize && (this.fileSize/1024) > this.maxSize){
		errorsCount ++;
	}
	if(this.maxWidth && (this.width > this.maxWidth)){
		errorsCount ++;
	}
	if(this.minWidth && (this.width < this.minWidth)){
		errorsCount ++;
	}
	if(this.maxHeight && (this.height > this.maxHeight)){
		errorsCount ++;
	}
	if(this.minHeight && (this.height < this.minHeight)){
		errorsCount ++;
	}
	// Store the valid flag inside the DOM node itself
	this.fieldNode.isValidImg = (errorsCount != 0) ? "false" : "true";
}

// This global objects store all the RegExp patterns for strings
var mwGlobalPatterns = new Object;
mwGlobalPatterns.email = new RegExp("^([\\w\\.=-]+@[\\w\\.-]+\\.[\\w\\.-]{2,4}[\;]*)*$");
mwGlobalPatterns.lettersonly = new RegExp("^[a-zA-Z]*$");
mwGlobalPatterns.alphanumeric = new RegExp("^\\w*$");
mwGlobalPatterns.integer = new RegExp("^-?\\d\\d*$");
mwGlobalPatterns.positiveinteger = new RegExp("^\\d\\d*$");
mwGlobalPatterns.number = new RegExp("^-?(\\d\\d*\\.\\d*$)|(^-?\\d\\d*$)|(^-?\\.\\d\\d*$)");
mwGlobalPatterns.filepath_pdf = new RegExp("\\\\[\\w_]*\\.([pP][dD][fF])$");
mwGlobalPatterns.filepath_jpg_gif = new RegExp("\\\\[\\w_]*\\.([gG][iI][fF])|([jJ][pP][eE]?[gG])$");
mwGlobalPatterns.filepath_jpg = new RegExp("\\\\[\\w_]*\\.([jJ][pP][eE]?[gG])$");
mwGlobalPatterns.filepath_zip = new RegExp("\\\\[\\w_]*\\.([zZ][iI][pP])$");
mwGlobalPatterns.filepath = new RegExp("\\\\[\\w_]*\\.\\w{3}$");
mwGlobalPatterns.ip = new RegExp("^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$");
mwGlobalPatterns.username = new RegExp("^[*]{6,15}$");


// This global objects store all the info required for date validation
var mwGlobalDatePatterns = new Object;
mwGlobalDatePatterns["YYYY-MM-DD"] = mwDateInfo("^\([0-9]{4}\)\\-\([0-1][0-9]\)\\-\([0-3][0-9]\)$", 0, 1, 2, "-");
mwGlobalDatePatterns["YYYY-M-D"] = mwDateInfo("^\([0-9]{4}\)\\-\([0-1]?[0-9]\)\\-\([0-3]?[0-9]\)$", 0, 1, 2, "-");
mwGlobalDatePatterns["MM.DD.YYYY"] = mwDateInfo("^\([0-1][0-9]\)\\.\([0-3][0-9]\)\\.\([0-9]{4}\)$", 2, 0, 1, ".");
mwGlobalDatePatterns["M.D.YYYY"] = mwDateInfo("^\([0-1]?[0-9]\)\\.\([0-3]?[0-9]\)\\.\([0-9]{4}\)$", 2, 0, 1, ".");
mwGlobalDatePatterns["MM/DD/YYYY"] = mwDateInfo("^\([0-1][0-9]\)\/\([0-3][0-9]\)\/\([0-9]{4}\)$", 2, 0, 1, "/");
mwGlobalDatePatterns["M/D/YYYY"] = mwDateInfo("^\([0-1]?[0-9]\)\/\([0-3]?[0-9]\)\/\([0-9]{4}\)$", 2, 0, 1, "/");
mwGlobalDatePatterns["MM-DD-YYYY"] = mwDateInfo("^\([0-21][0-9]\)\\-\([0-3][0-9]\)\\-\([0-9]{4}\)$", 2, 0, 1, "-");
mwGlobalDatePatterns["M-D-YYYY"] = mwDateInfo("^\([0-1]?[0-9]\)\\-\([0-3]?[0-9]\)\\-\([0-9]{4}\)$", 2, 0, 1, "-");
mwGlobalDatePatterns["DD.MM.YYYY"] = mwDateInfo("^\([0-3][0-9]\)\\.\([0-1][0-9]\)\\.\([0-9]{4}\)$", 2, 1, 0, ".");
mwGlobalDatePatterns["D.M.YYYY"] = mwDateInfo("^\([0-3]?[0-9]\)\\.\([0-1]?[0-9]\)\\.\([0-9]{4}\)$", 2, 1, 0, ".");
mwGlobalDatePatterns["DD/MM/YYYY"] = mwDateInfo("^\([0-3][0-9]\)\/\([0-1][0-9]\)\/\([0-9]{4}\)$", 2, 1, 0, "/");
mwGlobalDatePatterns["D/M/YYYY"] = mwDateInfo("^\([0-3]?[0-9]\)\/\([0-1]?[0-9]\)\/\([0-9]{4}\)$", 2, 1, 0, "/");
mwGlobalDatePatterns["DD-MM-YYYY"] = mwDateInfo("^\([0-3][0-9]\)\\-\([0-1][0-9]\)\\-\([0-9]{4}\)$", 2, 1, 0, "-");
mwGlobalDatePatterns["D-M-YYYY"] = mwDateInfo("^\([0-3]?[0-9]\)\\-\([0-1]?[0-9]\)\\-\([0-9]{4}\)$", 2, 1, 0, "-");

// Create an object that stores date validation's info
function mwDateInfo(rex, year, month, day, separator){
	var infoObj = new Object;
	infoObj.rex = new RegExp(rex);
	infoObj.y = year;
	infoObj.m = month;
	infoObj.d = day;
	infoObj.s = separator;
	return infoObj;
}

/* Filters */

// This global objects store all the info required for filters
var mwGlobalFilters = new Object;
mwGlobalFilters.ltrim = mwFilterInfo("^(\\s*)(\\b[\\w\\W]*)$", "$2");
mwGlobalFilters.rtrim = mwFilterInfo("^([\\w\\W]*)(\\b\\s*)$", "$1");
mwGlobalFilters.nospaces = mwFilterInfo("\\s*", "");
mwGlobalFilters.nocommas = mwFilterInfo(",", "");
mwGlobalFilters.nodots = mwFilterInfo("\\.", "");
mwGlobalFilters.noquotes = mwFilterInfo("'", "");
mwGlobalFilters.nodoublequotes = mwFilterInfo('"', "");
mwGlobalFilters.nohtml = mwFilterInfo("<[^>]*>", "");
mwGlobalFilters.alphanumericonly = mwFilterInfo("[^\\w]", "");
mwGlobalFilters.numbersonly = mwFilterInfo("[^\\d]", "");
mwGlobalFilters.lettersonly = mwFilterInfo("[^a-zA-Z]", "");
mwGlobalFilters.commastodots = mwFilterInfo(",", ".");
mwGlobalFilters.dotstocommas = mwFilterInfo("\\.", ",");
mwGlobalFilters.numberscommas = mwFilterInfo("[^\\d,]", "");
mwGlobalFilters.numbersdots = mwFilterInfo("[\\-]+[^\\d\\.]", "");
mwGlobalFilters.currency = mwFilterInfo("^\d{1,3}(,\d{3})*\.\d{2}$", "");
mwGlobalFilters.phone = mwFilterInfo("[^\\d\\.\\-\\+\\(\\) ]", "");


// Create an object that stores filters's info
function mwFilterInfo(rex, replaceStr){
	var infoObj = new Object;
	infoObj.rex = new RegExp(rex, "g");
	infoObj.str = replaceStr;
	return infoObj;
}

// Clean up the field based on filter's info
function mwFilterField(fieldNode){
	var filtersArray = fieldNode.getAttribute("mwfilters").split(",");
	for(var i=0; i<filtersArray.length; i++){
		var filtObj = mwGlobalFilters[filtersArray[i]];
		// Be sure we have the filter's data, then clean up
		if(filtObj)
		{
			var cursorPos = 0;
			// Microsoft IE always jumps the cursor to the end after an insert
			// we check for IE, save the cursor position, insert and restore cursor position
			//IE support
			if (document.selection)
			{
				cursorPos = mwGetCaretPosition(fieldNode).start;
			}
			fieldNode.value = fieldNode.value.replace(filtObj.rex, filtObj.str)
			if (document.selection)
			{
				mwSetCaretPosition(fieldNode, cursorPos, cursorPos );
			}
		}
		// We handle demoroziner as a special case
		if(filtersArray[i] == "demoronizer"){
			fieldNode.value = mwFilterDemoronizer(fieldNode.value);
		}
	}
}

// Clean up the field based on filter's info
function mwFromTo(fieldNode, copyValues)
{
	var fieldArray = fieldNode.getAttribute("mwfromto").split(",");
	for(var i=0; i<fieldArray.length; i = i +2)
	{
		if ( !copyValues )
		{
			document.getElementById(fieldArray[i+1]).value = "";
		}
		else
		{
			document.getElementById(fieldArray[i+1]).value = 
					document.getElementById(fieldArray[i]).value;	
		}
	}
}

// Used to set toggle the visibility of an element
function mwToggleVisibility(element)
{
	var current_element = document.getElementById(element);
	
	if ( current_element == null )
		return;
		
	var current_state = current_element.style.visibility;
	
	// alert("Current State of ["+element+"] is ["+current_state+"]");
	
	if ( current_state == "hidden" )
		current_element.style.visibility = "visible";
	else
		current_element.style.visibility = "hidden";
}

// Used to set a text field's text
function mwSetText(element, text)
{
	document.getElementById(element).value = text;
}


// Replace MS Word's non-ISO characters with plausible substitutes
function mwFilterDemoronizer(str){
	str = str.replace(new RegExp(String.fromCharCode(710), "g"), "^");
	str = str.replace(new RegExp(String.fromCharCode(732), "g"), "~");
	// Evil "smarty" quotes
	str = str.replace(new RegExp(String.fromCharCode(8216), "g"), "'");
	str = str.replace(new RegExp(String.fromCharCode(8217), "g"), "'");
	str = str.replace(new RegExp(String.fromCharCode(8220), "g"), '"');
	str = str.replace(new RegExp(String.fromCharCode(8221), "g"), '"');
	// More MS Word's garbage
	str = str.replace(new RegExp(String.fromCharCode(8211), "g"), "-");
	str = str.replace(new RegExp(String.fromCharCode(8212), "g"), "--");
	str = str.replace(new RegExp(String.fromCharCode(8218), "g"), ",");
	str = str.replace(new RegExp(String.fromCharCode(8222), "g"), ",,");
	str = str.replace(new RegExp(String.fromCharCode(8226), "g"), "*");
	str = str.replace(new RegExp(String.fromCharCode(8230), "g"), "...");
	str = str.replace(new RegExp(String.fromCharCode(8364), "g"), "€");
	return str;
}

/* Helper functions */

// Get an array of submit button nodes contained inside a given node
function mwGetSubmitNodes(startNode){
	var submitArray = new Array();
	var inputNodes = startNode.getElementsByTagName("input");
	// Get an array of submit nodes
	for(var i=0; i<inputNodes.length; i++){
		if(inputNodes[i].getAttribute("type").toLowerCase() == "submit"){
			// DQ alert("submit node["+i+"]["+inputNodes[i].name+"]");
			if ( inputNodes[i].id.indexOf ("p_ctl", 0 ) != 0 )
			{
				submitArray[submitArray.length] = inputNodes[i];
			}
			else
			{
				// alert("i blocked submit["+inputNodes[i].id+"]");
			}
		}
	}
	return submitArray;
}

// Get an array of input and textarea nodes contained inside a given node
function mwGetTextfieldNodes(startNode){
	var inputsArray = new Array();
	var inputNodes = startNode.getElementsByTagName("input");
	var areaNodes = startNode.getElementsByTagName("textarea");
	// Get an array of text, password and file nodes
	for(var i=0; i<inputNodes.length; i++){
		if(!inputNodes[i].getAttribute("type")){
			inputNodes[i].setAttribute("type", "text");
		}
		var fieldType = inputNodes[i].getAttribute("type").toLowerCase();

		// Check if the start of the name indicates the field is disabled
		if ( inputNodes[i].name.substring (0,11) != "mwdisabled-" )
			if((fieldType == "text") || (fieldType == "password") || (fieldType == "file") || (fieldType == "hidden")){
				inputsArray[inputsArray.length] = inputNodes[i];
		}
	}
	// Append textarea nodes too
	for(var j=0; j<areaNodes.length; j++){
	    inputsArray[inputsArray.length] = areaNodes[j];
	}
	return inputsArray;
}

// Return an object (sort of an hashtable) containing checkboxes/radios data
// The returned object has two properties:
// name: the group name
// boxes: an array containing the DOM node of each checkbox/radio that share the same name
function mwGetNodesTable(formNode, type){
	// This object will store data fields, just as an hash table
	var boxHolder = new Object;
	var boxNodes = formNode.getElementsByTagName("input");
	for(var i=0; i<boxNodes.length; i++){
		if(boxNodes[i].getAttribute("type") && (boxNodes[i].getAttribute("type").toLowerCase() == type)){
			// Store the reference to make it easier to read the code
			var boxName = boxNodes[i].name;
			if(boxHolder[boxName]){
				// We already have an entry with the same name
				// Append the DOM node to the relevant entry inside the object
				boxHolder[boxName].elements[boxHolder[boxName].elements.length] = boxNodes[i];
			}
			else{
				// Create a brand new entry inside the object
				boxHolder[boxName] = new Object;
				boxHolder[boxName].name = boxName;
				// Initialize the array that will store all the DOM nodes that share the same name
				boxHolder[boxName].elements = new Array;
				boxHolder[boxName].elements[0] = boxNodes[i];
			}
		}
	}
	return boxHolder;
}

// This handy piece of code comes from:
// http://www.sitepoint.com/blog-post-view.php?id=171578
function addLoadEvent(func)
{
	var oldonload = window.onload;
	if(typeof window.onload != "function")
	{
		window.onload = func;
	} 
	else
	{
		window.onload = function()
		{
			oldonload();
			func();
		}
	}
}


//
// Misc Library Functions
//

// Toggles the visibility "expansion" of (div) items especially for FAQs
function mwExpand(item)
{
  if ( document.getElementById(item).style.display == "none")
    document.getElementById(item).style.display = "block";
  else
    document.getElementById(item).style.display = "none";
}

function mwHide(item)
{
    document.getElementById(item).style.display = "none";
}
function mwShow(item)
{
    document.getElementById(item).style.display = "block";
}

/*

This routine checks the credit card number. The following checks are made:

1. A number has been provided
2. The number is a right length for the card
3. The number has an appropriate prefix for the card
4. The number has a valid modulus 10 number check digit if required

If the validation fails an error is reported.

The structure of credit card formats was gleaned from a variety of sources on 
the web.

Parameters:
            cardnumber           number on the card
            cardname             name of card as defined in the card list below

Author:     John Gardner
Date:       1st November 2003
Updated:    26th Feb. 2005      Additional cards added by request

*/

/*
   If a credit card number is invalid, an error reason is loaded into the 
   global ccErrorNo variable. This can be be used to index into the global error  
   string array to report the reason to the user if required:
   
   e.g. if (!checkCreditCard (number, name) alert (ccErrors(ccErrorNo);
*/

var ccErrorNo = 0;
var ccErrors = new Array ()

ccErrors [0] = "Unknown card type";
ccErrors [1] = "No card number provided";
ccErrors [2] = "Credit card number is in invalid format";
ccErrors [3] = "Credit card number is invalid";
ccErrors [4] = "Credit card number has an inappropriate number of digits";

function mwCC ( cardnumber, cardname ) {

     
  // Array to hold the permitted card characteristics
  var cards = new Array();

  // Define the cards we support. You may add addtional card types.
  
  //  Name:      As in the selection box of the form - must be same as user's
  //  Length:    List of possible valid lengths of the card number for the card
  //  prefixes:  List of possible prefixes for the card
  //  checkdigit Boolean to say whether there is a check digit
  
  // Visa
  cards [0] = {name: "V", 
               length: "13,16", 
               prefixes: "4",
               checkdigit: true};
  //Master Card
  cards [1] = {name: "MC", 
               length: "16", 
               prefixes: "51,52,53,54,55",
               checkdigit: true};
  // Diners Club
  cards [2] = {name: "DC", 
               length: "14,", 
               prefixes: "300,301,302,303,304,305,36,38",
               checkdigit: true};
  // Carte Blanche
  cards [3] = {name: "CB", 
               length: "14", 
               prefixes: "300,301,302,303,304,305,36,38",
               checkdigit: true};
  // American Express
  cards [4] = {name: "AE", 
               length: "15", 
               prefixes: "34,37",
               checkdigit: true};
  // Discover
  cards [5] = {name: "DS", 
               length: "16", 
               prefixes: "6011",
               checkdigit: true};
  cards [6] = {name: "JCB", 
               length: "15,16", 
               prefixes: "3,1800,2131",
               checkdigit: true};
  // Enroute
  cards [7] = {name: "EN", 
               length: "15", 
               prefixes: "2014,2149",
               checkdigit: true};
               
  // Establish card type
  var cardType = -1;
  for (var i=0; i<cards.length; i++) {

    // See if it is this card (ignoring the case of the string)
    if (cardname.toLowerCase () == cards[i].name.toLowerCase()) {
      cardType = i;
      break;
    }
  }
  
  // If card type not found, report an error
  if (cardType == -1) {
     ccErrorNo = 0;
     return false; 
  }
   
  // Ensure that the user has provided a credit card number
  if (cardnumber.length == 0)  {
     ccErrorNo = 1;
     return false; 
  }
  
  // Check that the number is numeric, although we do permit a space to occur  
  // every four digits. 
  var cardNo = cardnumber
  var cardexp = /^([0-9]{4})\s?([0-9]{4})\s?([0-9]{4})\s?([0-9]{1,4})$/;
  if (!cardexp.exec(cardNo))  {
     ccErrorNo = 2;
     return false; 
  }
    
  // Now remove any spaces from the credit card number
  cardexp.exec(cardNo);
  cardNo = RegExp.$1 + RegExp.$2 + RegExp.$3 + RegExp.$4;
       
  // Now check the modulus 10 check digit - if required
  if (cards[cardType].checkdigit) {
    var checksum = 0;                                  // running checksum total
    var mychar = "";                                   // next char to process
    var j = 1;                                         // takes value of 1 or 2
  
    // Process each digit one by one starting at the right
    var calc;
    for (i = cardNo.length - 1; i >= 0; i--) {
    
      // Extract the next digit and multiply by 1 or 2 on alternative digits.
      calc = Number(cardNo.charAt(i)) * j;
    
      // If the result is in two digits add 1 to the checksum total
      if (calc > 9) {
        checksum = checksum + 1;
        calc = calc - 10;
      }
    
      // Add the units element to the checksum total
      checksum = checksum + calc;
    
      // Switch the value of j
      if (j ==1) {j = 2} else {j = 1};
    } 
  
    // All done - if checksum is divisible by 10, it is a valid modulus 10.
    // If not, report an error.
    if (checksum % 10 != 0)  {
     ccErrorNo = 3;
     return false; 
    }
  }  

  // The following are the card-specific checks we undertake.
  var LengthValid = false;
  var PrefixValid = false; 
  var undefined; 

  // We use these for holding the valid lengths and prefixes of a card type
  var prefix = new Array ();
  var lengths = new Array ();
    
  // Load an array with the valid prefixes for this card
  prefix = cards[cardType].prefixes.split(",");
      
  // Now see if any of them match what we have in the card number
  for (i=0; i<prefix.length; i++) {
    var exp = new RegExp ("^" + prefix[i]);
    if (exp.test (cardNo)) PrefixValid = true;
  }
      
  // If it isn't a valid prefix there's no point at looking at the length
  if (!PrefixValid) {
     ccErrorNo = 3;
     return false; 
  }
    
  // See if the length is valid for this card
  lengths = cards[cardType].length.split(",");
  for (j=0; j<lengths.length; j++) {
    if (cardNo.length == lengths[j]) LengthValid = true;
  }
  
  // See if all is OK by seeing if the length was valid. We only check the 
  // length if all else was hunky dory.
  if (!LengthValid) {
     ccErrorNo = 4;
     return false; 
  };   
  
  // The credit card is in the required format.
  return true;
}

/*
 * FORM CONTROLS
 */
/* 
function mwSelectReplacement ( obj )
{
	// DQ alert ( 'meSelectReplacement [' + obj + '] called' ); 
	obj.className += ' replaced';
	var ul = document.createElement('ul');
	ul.className = 'mwSelectReplacement';
	var opts = obj.options;
	var selectedOpt = (!obj.selectedIndex) ? 0 : obj.selectedIndex;

	for (var i=0; i<opts.length; i++)
	{
		var li = document.createElement('li');
		var txt = document.createTextNode(opts[i].text);
		li.appendChild(txt);
		li.selIndex = i;
		li.selectID = obj.id;
		li.onclick = function()
		{
			selectMe(this);
		};
		
		if (i == selectedOpt)
		{
			li.className = 'mwSelected';
			li.onclick = function()
			{
				this.parentNode.className += ' mwSelectOpen';
				this.onclick = function()
				{
					selectMe(this);
				};
			};
		}
		if (window.attachEvent) 
		{
			li.onmouseover = function()
			{
				this.className += ' hover';
			};
			li.onmouseout = function()
			{
				this.className = 
					this.className.replace(new RegExp(" hover\\b"), '');
			};
		}
		ul.appendChild(li);
	}
	obj.onfocus = function() 
	{
		ul.className += ' mwSelectFocused';
	};
	obj.onblur = function() 
	{
		ul.className = 'mwSelectReplacement';
	};
	obj.onchange = function()
	{
		var idx = this.selectedIndex;
		selectMe(ul.childNodes[idx]);
	};
	obj.onkeypress = obj.onchange;
	obj.parentNode.insertBefore(ul,obj);
}
function selectMe ( obj ) 
{
	var lis = obj.parentNode.getElementsByTagName('li');
	for (var i=0; i<lis.length; i++)
	{
		if (lis[i] != obj) 
		{
			lis[i].className='';
			lis[i].onclick = function() 
			{
				selectMe(this);
			};
		}
		else
		{
			mwSetValue(obj.selectID, obj.selIndex);
			obj.className='mwSelected';
			obj.parentNode.className = 
			obj.parentNode.className.replace(new RegExp(" mwSelectOpen\\b"), '');
			obj.onclick = function()
			{
				obj.parentNode.className += ' mwSelectOpen';
				this.onclick = function() 
				{
					selectMe(this);
				};
			};
		}
	}
}

function mwSetValue(objID,val)
{
	var obj = document.getElementById(objID);
	obj.selectedIndex = val;
}
    
function mwSetForm()
{
	var s = document.getElementsByTagName('select');
	
	for (var i=0; i<s.length; i++) 
	{
		mwSelectReplacement(s[i]);
	}
}
*/

function mwContainerHeight()
{
	var div_left = document.getElementById ( "left" );
	var div_right = document.getElementById ( "right" );
	var div_content = document.getElementById ( "content" );
	var div_container = document.getElementById ( "container" );

	var max_height = 0;
	
	if ( div_container == null )
    return;
    
	if ( div_container.offsetHeight ) // IE
	{
		max_height = Math.max ( max_height, div_left == null? 0: div_left.offsetHeight );
		max_height = Math.max ( max_height, div_right == null? 0: div_right.offsetHeight );
		max_height = Math.max ( max_height, div_content == null? 0: div_content.offsetHeight );
	}
	else if ( div_container.style.pixelHeight ) // ???
	{
		max_height = Math.max ( max_height, div_left == null? 0: div_left.style.pixelHeight );
		max_height = Math.max ( max_height, div_right == null? 0: div_right.style.pixelHeight );
		max_height = Math.max ( max_height, div_content == null? 0: div_content.style.pixelHeight );
	}
	else	// dont know, set sensible default
	{
		if ( div_container != null )
			div_container.style.height = "800px";
		return;
	}
	
	//alert ("max_height["+max_height+"] container offset ["+div_container.offsetHeight+"] content offset["+div_content.offsetHeight+"]");
	//div_container.style.height = (div_container.offsetHeight + max_height) + "px"; //div_container.offsetHeight + max_height;
	var ie_fix = Math.max ( div_container.offsetTop, div_content.offsetTop );
	if ( div_container != null )
		div_container.style["height"] = (max_height + ie_fix ) + "px";
	
}


// Text Caret Position functions...

// CaretPosition object
function CaretPosition()
{
 var start = null;
 var end = null;
}

function mwGetCaretPosition(oField)
{
 // Initialise the CaretPosition object
 var oCaretPos = new CaretPosition();

 // IE support
 if(document.selection)
 {
  // Focus on the text box
  //oField.focus();

  // This returns us an object containing
  // information about the currently selected text
  var oSel = document.selection.createRange();

  // Find out the length of the selected text
  // (you'll see why below)
  var selectionLength = oSel.text.length;

  // Move the selection start to 0 position.
  //
  // This is where it gets interesting, and this is why
  // some have claimed you can't get the caret positions
  // in IE.
  //
  // IE has no 'selectionStart' or 'selectionEnd' property,
  // so we can not get or set this value directly. We can
  // only move the caret positions relative to where they
  // currently are (this should make more sense when you read
  // the next line of code).
  //
  // Note, that even though we have moved the start
  // position on our object in memory, this is not reflected
  // in the browser until we call oSel.select() (which we're
  // not going to do here).
  //
  // Also note, the start position will never be a negative
  // number, no matter how far we try to move it back.
  oSel.moveStart ('character', -oField.value.length);

  // This is where it should start to make sense. We now know
  // our start caret position is the length of the currently
  // selected text minus the original selection length
  // (think about it).
  oCaretPos.start = oSel.text.length - selectionLength;

  // Since the start of the selection is at the start of the
  // text, we know that the length of the selection is also
  // the index of the end caret position.
  oCaretPos.end = oSel.text.length;
 }
 // Firefox support
 else if(oField.selectionStart || oField.selectionStart == '0')
 {
  // This is a whole lot easier in Firefox
  oCaretPos.start = oField.selectionStart;
  oCaretPos.end = oField.selectionEnd;
 }

 // Return results
 return (oCaretPos);
}

// mwSetCaretPosition

function mwSetCaretPosition(oField, iCaretStart, iCaretEnd)
{
 // IE Support
 if (document.selection)
 {
  // Focus on the text box
  oField.focus();

  // This returns us an object containing
  // information about the currently selected text
  var oSel = document.selection.createRange();

  // Since we don't know where the caret positions
  // currently are (see comments in getCaretPosition() for
  // further information on this), move them to position 0.
  //
  // Note, the caret positions will never be a negative
  // number, no matter how far we try to move them back.
  oSel.moveStart ('character', -oField.value.length);
  oSel.moveEnd ('character', -oField.value.length);

  // Now we know the caret positions are at index 0, move
  // them forward to the desired position (move end caret
  // position first - actually not sure if moving start
  // caret position first affects the end caret position -
  // it might).
  //
  // Note, we allow for a null end caret position and just
  // default it to the same as the start caret position.
  if(iCaretEnd != null)
   oSel.moveEnd ('character', iCaretEnd);
  else
   oSel.moveEnd ('character', iCaretStart);

  oSel.moveStart ('character', iCaretStart);

  // Everything thus far has just been on our object in
  // memory - this line actually updates the browser
  oSel.select();
 }
 // Firefox support
 else if(oField.selectionStart || oField.selectionStart == '0')
 {
  oField.selectionStart = iCaretStart;

  if(iCaretEnd != null)
   oField.selectionEnd = iCaretEnd;
  else
   oField.selectionEnd = iCaretStart;

  oField.focus();
 }
}


function mwSelectName(oField)
{
 // Use our previous method to get the current caret positions
 var caretPos = getCaretPosition(oField);

 // Use a handful of string functions to find out where the last
 // and next '[' and ']' characters are. Obviously, this can be
 // any character you like that suits your purpose.
 var text = oField.value;
 var prevText = oField.value.substring(0, caretPos.start);
 var nextText = oField.value.substring(caretPos.end);
 var prevCloseBracket = prevText.lastIndexOf("]");
 var prevOpenBracket = prevText.lastIndexOf("[");
 var nextCloseBracket = nextText.indexOf("]");

 // This basically asks - is our caret currently positioned in
 // the middle of a cell name?
 if(prevOpenBracket > prevCloseBracket && nextCloseBracket != -1)
 {
  // IE Support
  if (document.selection)
  {
   // This returns us an object containing
   // information about the currently selected text
   var oSel = document.selection.createRange();

   // Since we don't know where the start caret position
   // currently is (see comments in getCaretPosition() for
   // further information on this), move it to position 0.
   //
   // Note, the caret position will never be a negative
   // number, no matter how far we try to move it back.
   oSel.moveStart('character', -oField.value.length);

   // Move selection start and end to desired position
   oSel.moveStart('character', prevOpenBracket);
   oSel.moveEnd('character', nextCloseBracket+1);

   // Apply the selection
   oSel.select();
  }
  // Firefox support
  else if(oField.selectionStart || oField.selectionStart == '0')
  {
   oField.selectionStart = prevOpenBracket;
   oField.selectionEnd = caretPos.end + nextCloseBracket+1;
   oField.focus();
  }
 }
}


var mwCountDownInterval=180;
var mwCountDownTime=mwCountDownInterval;

function mwCountDown()
{
    --mwCountDownTime;
    if (mwCountDownTime < 0)
    {
        mwCountDownTime=mwCountDownInterval;
    }
    // document.all.mwCountDownText.innerText = mwCountDownTime;
    document.getElementById('mwCountDownText').innerHTML = mwCountDownTime;
    setTimeout("mwCountDown()", 1000);
    if (mwCountDownTime == 0)
    {
        location.reload();
    }
}

function mwPrintPreview()
{
	var OLECMDID = 7;
	/* OLECMDID values:
	* 6 - print
	* 7 - print preview
	* 1 - open window
	* 4 - Save As
	*/
	var PROMPT = 2; // 2 DONTPROMPTUSER
	var WebBrowser = '<OBJECT ID="WebBrowser1" WIDTH=0 HEIGHT=0 CLASSID="CLSID:8856F961-340A-11D0-A96B-00C04FD705A2"></OBJECT>';
	document.body.insertAdjacentHTML('beforeEnd', WebBrowser);
	WebBrowser1.ExecWB(OLECMDID, PROMPT);
	WebBrowser1.outerHTML = "";
}

function XmwPrintPreview()
{
var inf = content.innerHTML;
win = window.open("print.htm", 'popup', 'toolbar = no, status = no');
win.document.write(inf);
win.document.close(); 
}
//addLoadEvent ( mwSetForm );
addLoadEvent ( mwValidatorInit );
addLoadEvent ( mwContainerHeight );


//v1.0
//Copyright 2006 Adobe Systems, Inc. All rights reserved.
function AC_AddExtension(src, ext)
{
  if (src.indexOf('?') != -1)
    return src.replace(/\?/, ext+'?'); 
  else
    return src + ext;
}

function AC_Generateobj(objAttrs, params, embedAttrs) 
{ 
  var str = '<object ';
  for (var i in objAttrs)
    str += i + '="' + objAttrs[i] + '" ';
  str += '>';
  for (var i in params)
    str += '<param name="' + i + '" value="' + params[i] + '" /> ';
  str += '<embed ';
  for (var i in embedAttrs)
    str += i + '="' + embedAttrs[i] + '" ';
  str += ' ></embed></object>';

  document.write(str);
}

function AC_FL_RunContent(){
  var ret = 
    AC_GetArgs
    (  arguments, ".swf", "movie", "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
     , "application/x-shockwave-flash"
    );
  AC_Generateobj(ret.objAttrs, ret.params, ret.embedAttrs);
}

function AC_SW_RunContent(){
  var ret = 
    AC_GetArgs
    (  arguments, ".dcr", "src", "clsid:166B1BCA-3F9C-11CF-8075-444553540000"
     , null
    );
  AC_Generateobj(ret.objAttrs, ret.params, ret.embedAttrs);
}

function AC_GetArgs(args, ext, srcParamName, classid, mimeType){
  var ret = new Object();
  ret.embedAttrs = new Object();
  ret.params = new Object();
  ret.objAttrs = new Object();
  for (var i=0; i < args.length; i=i+2){
    var currArg = args[i].toLowerCase();    

    switch (currArg){	
      case "classid":
        break;
      case "pluginspage":
        ret.embedAttrs[args[i]] = args[i+1];
        break;
      case "src":
      case "movie":	
        args[i+1] = AC_AddExtension(args[i+1], ext);
        ret.embedAttrs["src"] = args[i+1];
        ret.params[srcParamName] = args[i+1];
        break;
      case "onafterupdate":
      case "onbeforeupdate":
      case "onblur":
      case "oncellchange":
      case "onclick":
      case "ondblClick":
      case "ondrag":
      case "ondragend":
      case "ondragenter":
      case "ondragleave":
      case "ondragover":
      case "ondrop":
      case "onfinish":
      case "onfocus":
      case "onhelp":
      case "onmousedown":
      case "onmouseup":
      case "onmouseover":
      case "onmousemove":
      case "onmouseout":
      case "onkeypress":
      case "onkeydown":
      case "onkeyup":
      case "onload":
      case "onlosecapture":
      case "onpropertychange":
      case "onreadystatechange":
      case "onrowsdelete":
      case "onrowenter":
      case "onrowexit":
      case "onrowsinserted":
      case "onstart":
      case "onscroll":
      case "onbeforeeditfocus":
      case "onactivate":
      case "onbeforedeactivate":
      case "ondeactivate":
      case "type":
      case "codebase":
        ret.objAttrs[args[i]] = args[i+1];
        break;
      case "width":
      case "height":
      case "align":
      case "vspace": 
      case "hspace":
      case "class":
      case "title":
      case "accesskey":
      case "name":
      case "id":
      case "tabindex":
        ret.embedAttrs[args[i]] = ret.objAttrs[args[i]] = args[i+1];
        break;
      default:
        ret.embedAttrs[args[i]] = ret.params[args[i]] = args[i+1];
    }
  }
  ret.objAttrs["classid"] = classid;
  if (mimeType) ret.embedAttrs["type"] = mimeType;
  return ret;
}



function pageWidth()
{
return window.innerWidth != null? window.innerWidth: document.documentElement && document.documentElement.clientWidth ? document.documentElement.clientWidth:document.body != null? document.body.clientWidth:null;
}

function pageHeight()
{
return window.innerHeight != null? window.innerHeight: document.documentElement && document.documentElement.clientHeight ? document.documentElement.clientHeight:document.body != null? document.body.clientHeight:null;
}

function posLeft()
{
  return typeof window.pageXOffset != 'undefined' ? window.pageXOffset:document.documentElement && document.documentElement.scrollLeft? document.documentElement.scrollLeft:document.body.scrollLeft? document.body.scrollLeft:0;
}

function posTop()
{
  return typeof window.pageYOffset != 'undefined' ? window.pageYOffset:document.documentElement && document.documentElement.scrollTop? document.documentElement.scrollTop: document.body.scrollTop?document.body.scrollTop:0;
}


function __$__(x)
{
  return document.getElementById(x);
}


function scrollFix()
{
	var obol=$('#mw_overlay');
	obol.style.top=posTop()+'px';
	obol.style.left=posLeft()+'px'
}

function sizeFix()
{
	var obol=$('#mw_overlay');
	obol.style.height=pageHeight()+'px';
	obol.style.width=pageWidth()+'px';
}


function kp(e)
{
	ky=e?e.which:event.keyCode;
	if(ky==88||ky==120)hm();
		return false
}

function inf(h)
{
//	tag=document.getElementsByTagName('select');
//	for(i=tag.length-1;i>=0;i--)
//		tag[i].style.visibility=h;
    
	tag=document.getElementsByTagName('iframe');
    
	for(i=tag.length-1;i>=0;i--)
		tag[i].style.visibility=h;

	tag=document.getElementsByTagName('object');

	for(i=tag.length-1;i>=0;i--)
		tag[i].style.visibility=h;
}


function sm(obl, wd, ht)
{
	var h='hidden';
	var b='block';
	var p='px';
	var obol=$('mw_overlay');
	var obbxd = $('mw_mb_data');
	obbxd.innerHTML = $(obl).innerHTML;
	obol.style.height=pageHeight()+p;
	obol.style.width=pageWidth()+p;
	obol.style.top=posTop()+p;
	obol.style.left=posLeft()+p;
	obol.style.display=b;
	var tp=posTop()+((pageHeight()-ht)/2)-12;
	var lt=posLeft()+((pageWidth()-wd)/2)-12;
	var obbx=$('mw_dialog_box');
	
	obbx.style.top=(tp<0?0:tp)+p;
	obbx.style.left=(lt<0?0:lt)+p;
	obbx.style.width=wd+p;
	obbx.style.height=ht+p;
	inf(h);
	obbx.style.display=b;
	
	var page=$('html');
	
	
	return false;
}


function hm()
{
	var v='visible';
	var n='none';
	$('mw_overlay').style.display=n;
	$('mw_dialog_box').style.display=n;
	inf(v);document.onkeypress=''
}

function initmb()
{
	var ab='absolute';
	var n='none';
	var obody=document.getElementsByTagName('body')[0];
	var frag=document.createDocumentFragment();
	var obol=document.createElement('div');
	obol.setAttribute('id','mw_overlay');
	obol.style.display=n;
	obol.style.position=ab;
	obol.style.top=0;
	obol.style.left=0;
	obol.style.zIndex=998;
	obol.style.width='100%';
	frag.appendChild(obol);
	var obbx=document.createElement('div');
	obbx.setAttribute('id','mw_dialog_box');
	obbx.style.display=n;
	obbx.style.position=ab;
	obbx.style.zIndex=999;
	var obl=document.createElement('span');
	obbx.appendChild(obl);
	var obbxd=document.createElement('div');
	obbxd.setAttribute('id','mw_mb_data');
	obl.appendChild(obbxd);
	frag.insertBefore(obbx,obol.nextSibling);
	obody.insertBefore(frag,obody.firstChild);
	window.onscroll = scrollFix;
	window.onresize = sizeFix;
}

function mw_mm ()
{
}


function mw_system(category)
{
	mw_xxx_yyy ("mwsystem",category);
}

function mw_category(category)
{
	mw_xxx_yyy ("mwcategory",category);
}
function mw_xxx_yyy(scope,category)
{
	var element;

	for ( var i = 0; i < document.getElementsByTagName ('*').length; i++ )
	{
		element = document.getElementsByTagName('*')[i];
		if ( element.getAttribute(scope) )
		{
      var _roles = category.split("|");
      // DQ
      for ( j = 0; j < _roles.length; j++) 
      {
        // if the role is not == "" or if its "" and the first item
        if ( _roles[j].length > 0 || (_roles[j].length == 0 && j == 0 ))
        {
          if ( element.getAttribute(scope).indexOf("|"+_roles[j]+"|") > -1)
          {
              element.disabled=false;
              element.style.display="block";

            if ( element.nodeName == "FIELDSET" )
            {
              element.style.display="block";
            }
            else
            {
              element.parentNode.style.display="block";

              if ( element.name.substring(0,11) == "mwdisabled-" )
              {
                element.name = element.name.substring(11);
                element.disabled=false;
              }
            }	
          }
          else
          {
              element.disabled=true;
              element.style.display="none";
          
            if ( element.nodeName == "FIELDSET" )
            {
              element.style.display="none";
            }
            else
            {
              element.parentNode.style.display="none";

              if ( element.name.substring(0,11) != "mwdisabled-" )
              {
                element.name = "mwdisabled-" + element.name;
                element.disabled=true;
              }
            }
          }
        }
      }
    }
  }
}

function mwPackageItems ( select, array )
{
	var _option = select.selectedIndex;
	var _value = select.options[_option].value;
	
	for ( i = 0; i < array.length; i++ )
	{
		if ( array[i][0] == _value )
		{
			if ( _value && _value.length > 0 )
				mw_category ( array[i][1] );
		}
	}
	mwValidatorInit();	
}
/**
 * Updates the field and fieldsets (groups) within a form, based on the value choosen in the select input.
 * All child fieldsets of this form are hidden and disabled as well as their children recursively.
 * Fields that match the current system but fail to match a category are hidden.
 */

function mwupdateform ( select, array )
{
	var _option = select.selectedIndex;
	var _value = select.options[_option].value;

	for ( i = 0; i < array.length; i++ )
	{
		if ( array[i][0] == _value )
		{
			if ( _value && _value.length > 0 )
				mw_select ( array[i][1] );
		}
	}
	mwValidatorInit();	
}


function mwmemberof ( member, group )
{
  var _array = group.split ("'");
  
}

// EXPANDABLE COLLAPSABLE DIV
var timerlen = 5;
var slideAniLen = 500;

var timerID = new Array();
var startTime = new Array();
var obj = new Array();
var endHeight = new Array();
var moving = new Array();
var dir = new Array();

function slidedown(objname){
        if(moving[objname])
                return;

        if(document.getElementById(objname).style.display != "none")
                return; // cannot slide down something that is already visible

        moving[objname] = true;
        dir[objname] = "down";
        startslide(objname);
}

function slideup(objname){
        if(moving[objname])
                return;

        if(document.getElementById(objname).style.display == "none")
                return; // cannot slide up something that is already hidden

        moving[objname] = true;
        dir[objname] = "up";
        startslide(objname);
}

function startslide(objname){
        obj[objname] = document.getElementById(objname);

        endHeight[objname] = parseInt(obj[objname].style.height);
        startTime[objname] = (new Date()).getTime();

        if(dir[objname] == "down"){
                obj[objname].style.height = "1px";
        }

        obj[objname].style.display = "block";

        timerID[objname] = setInterval('slidetick(\'' + objname + '\');',timerlen);
}

function old_slidetick(objname){
        var elapsed = (new Date()).getTime() - startTime[objname];

        if (elapsed > slideAniLen)
                endSlide(objname)
        else {
                var d =Math.round(elapsed / slideAniLen * endHeight[objname]);
                if(dir[objname] == "up")
                        d = endHeight[objname] - d;

                obj[objname].style.height = d + "px";
        }

        return;
}

function slidetick(objname)
{
  var elapsed = (new Date()).getTime() - startTime[objname];

  if (elapsed > slideAniLen)
    endSlide(objname)
  else
  {
    var d =Math.round(elapsed / slideAniLen * endHeight[objname]);
    var f =elapsed / slideAniLen;

    if(dir[objname] == "up")
    {
      d = endHeight[objname] - d;
      f = 1 - f;
    }

    obj[objname].style.height = d + "px";
    obj[objname].style.opacity = f;
    obj[objname].style.filter = "alpha(opacity="+(f*100)+")";
    //document.getElementById(’searchtextbox’).value=f;
  }

  return;
}

function endSlide(objname){
        clearInterval(timerID[objname]);

//        if(dir[objname] == "up")
//                obj[objname].style.display = "none";

if(dir[objname] == "up"){
obj[objname].style.display = "none";
obj[objname].style.opacity = 0;
obj[objname].style.filter = "alpha(opacity="+(0)+')';
}
else{
obj[objname].style.opacity = 1;
obj[objname].style.filter = '';
}

 //       obj[objname].style.height = endHeight[objname] + "px";
       obj[objname].style.height = endHeight[objname] + "%";

        delete(moving[objname]);
        delete(timerID[objname]);
        delete(startTime[objname]);
        delete(endHeight[objname]);
        delete(obj[objname]);
        delete(dir[objname]);

        return;
}

function toggleSlide(objname){
  if(document.getElementById(objname).style.display == "none"){
    // div is hidden, so let's slide down
    slidedown(objname);
  }else{
    // div is not hidden, so slide up
    slideup(objname);
  }
}// END EXPANDABLE COLLAPSABLE DIV



//Specify affected tags. Add or remove from list:
var tgs = new Array( 'div','td','tr', 'p', 'a', 'h3', 'h4', 'b','strong','th','span', 'select', 'input');

//Specify spectrum of different font sizes:
//var szs = new Array( 'xx-small','x-small','small','medium','large','x-large','xx-large' );
var szs = new Array( '65%', '75%','85%','100%','115%','125%','150%' );
var startSz = 4;

function ts( trgt,inc ) {
	if (!document.getElementById) return
	var d = document,cEl = null,sz = startSz,i,j,cTags;
	
	sz += inc;
	if ( sz < 0 ) sz = 0;
	if ( sz > 6 ) sz = 6;
	startSz = sz;
		
	if ( !( cEl = d.getElementById( trgt ) ) ) cEl = d.getElementsByTagName( trgt )[ 0 ];

	cEl.style.fontSize = szs[ sz ];

	for ( i = 0 ; i < tgs.length ; i++ ) {
		cTags = cEl.getElementsByTagName( tgs[ i ] );
		for ( j = 0 ; j < cTags.length ; j++ ) cTags[ j ].style.fontSize = szs[ sz ];
	}
}


/*
CSS Browser Selector v0.2.7
Rafael Lima (http://rafael.adm.br)
http://rafael.adm.br/css_browser_selector
License: http://creativecommons.org/licenses/by/2.5/
Contributors: http://rafael.adm.br/css_browser_selector#contributors
*/
var css_browser_selector = function() {var ua=navigator.userAgent.toLowerCase(),is=function(t){return ua.indexOf(t) != -1;},h=document.getElementsByTagName('html')[0],b=(!(/opera|webtv/i.test(ua))&&/msie (\d)/.test(ua))?('ie ie'+RegExp.$1):is('firefox/2')?'gecko ff2':is('firefox/3')?'gecko ff3':is('gecko/')?'gecko':is('opera/9')?'opera opera9':/opera (\d)/.test(ua)?'opera opera'+RegExp.$1:is('konqueror')?'konqueror':is('applewebkit/')?'webkit safari':is('mozilla/')?'gecko':'',os=(is('x11')||is('linux'))?' linux':is('mac')?' mac':is('win')?' win':'';var c=b+os+' js'; h.className += h.className?' '+c:c;}();




/*
 * Method capture the enter key and direct it to the supplied button
 */

// Sets default buttons.
// Originally created by Janus Kamp Hansen - http://www.kamp-hansen.dk
// Extended by Darrell Norton - http://dotnetjunkies.com/weblog/darrell.norton/ 
function fnTrapKD(btnID, event)
{
	var button = document.getElementById(btnID); // only recent browsers
	if (document.all) // IE
	{
		if (event.keyCode == 13)
		{
			event.returnValue = false;
			event.cancel = true;
			button.click();
		}
	}
	else if (document.getElementById)
	{
		if (event.which == 13) 
		{
			event.returnValue = false;
			event.cancel = true;
			button.focus();
			button.click();
		}
	}
}