/*   ========================================================================
Name:		Form.js

Notes:		This Javascript file contains commonly used functions for forms.

Functions provided: (clear_text|popupWindow|popupWindowURL|popupFullWindow|SelectRadio|ToggleChecked|SubmitFormAction|SubmitAction|ValueChangeSubmit|AutoTab|TextCounter|FilterSet|FilterClear|FilterButtons|FilterClearAll|FilterInit|FormElementCopy)
========================================================================    */
var ns4 = (document.layers);
var ie4 = (document.all && !document.getElementById);
var ie5 = (document.all && document.getElementById);
var ns6 = (!document.all && document.getElementById);

//
// Clears a form.  Give it the number of the form on the page
//
function clear_text() {
	var k = 0;
	var n = 0;

	if (clear_text.arguments.length == 0) {
		k = 0;
	}
	else if (clear_text.arguments[0] < document.forms.length) { 
		k = clear_text.arguments[0];
	}
	else {  
		k = document.forms.length - 1;
	}
	for(n = 0; n < document.forms[k].elements.length; n++) { 
		if (document.forms[k].elements[n].type == "text") 
			  document.forms[k].elements[n].value = "";
	}
}	


//
// Popup Window Functions
//
// Pops up a child window with the given window name and dimensions.
// Takes the optional arguments to set the menubar, resize, and scrollbars attributes of Window.
function popupWindow(winname,  w, h, menu, resize, scroll) {
	popupWindowURL("", winname,  w, h, menu, resize, scroll);
	return;
}
function popupWindowURL(url, winname,  w, h, menu, resize, scroll, x, y) {
	var cwin       = "";
	var menutype   = "nomenubar";
	var resizetype = "noresizable";
	var scrolltype = "noscrollbars";
	
	if (winname == null) winname = "newWindow";
	if (w == null) w = 600;
	if (h == null) h = 600;
	if (resize == null) resize = 1;
	
	if (menu) menutype = "menubar";
	if (resize) resizetype = "resizable";
	if (scroll) scrolltype = "scrollbars";
	
	if (x == null || y == null) {
		cwin=window.open(url,winname, + "status," + menutype + "," + scrolltype + "," + resizetype + ",width=" + w + ",height=" + h);
	}
	else {
		cwin=window.open(url,winname,"top=" + y + ",left=" + x + ",screenX=" + x + ",screenY=" + y + "," + "status," + menutype + "," + scrolltype + "," + resizetype + ",width=" + w + ",height=" + h);
	}
	if (!cwin.opener) cwin.opener=self;
	cwin.focus();

	return;
}
//need to eventually delete this function and make the features available in popupwindowURL()
function popupFullWindow(url, winname,  w, h) {
	var cwin       = "";
	
	if (winname == null) winname = "newWindow";
	if (w == null) w = 600;
	if (h == null) h = 600;
	
	cwin=window.open(url,winname,"status,menubar,resizable,scrollbars,toolbar,location" + ",width=" + w + ",height=" + h);
	
	if (!cwin.opener) cwin.opener=self;
	cwin.focus();

	return;
}

//given a form radio name, this function will "check" the radio button of the name specified which matches the value passed
function SelectRadio(RadioField, RadioValue, CheckedValue) {
	if (CheckedValue == null) CheckedValue = true;
	if (RadioField.length > 1) {
		for (var i=0; i < RadioField.length; i++) {
			if (RadioField[i].value == RadioValue) RadioField[i].checked = CheckedValue;
	 	}
	} else {
		if (RadioField.value == RadioValue) RadioField.checked = CheckedValue;
	}
}

//Toggles a checkbox that matches a value "CheckBoxValue" for checkbox object "CheckBox"
function ToggleChecked(CheckBox,CheckBoxValue) {
	if (CheckBox.length > 1) {
		for (var i=0; i < CheckBox.length; i++) {
			if (CheckBox[i].value == CheckBoxValue) {
				if (CheckBox[i].checked) {
					CheckBox[i].checked = false;
				} else {
					CheckBox[i].checked = true;
				}
				break;
			}
	 	}
	} else {
		if (CheckBox.value == CheckBoxValue) {
			if (CheckBox.checked) {
				CheckBox.checked = false;
			} else {
				CheckBox.checked = true;
			}
		}
	}
	return true;
}

// To be used with our "Action" forms
function SubmitFormAction(myForm,myAction) {
	var tmpFormAction = null;
	var myField = 0;

	for (myField = 0; myField < myForm.length; myField++) {
		if (myForm[myField].name == "Action") {
			if (myForm[myField].type == "hidden") {
				tmpFormAction = myForm[myField];
			} else if (myForm[myField].value == myAction && (myForm[myField].type == "submit" || myForm[myField].type == "button")) {
				tmpFormAction = myForm[myField];
				break;
			}
		}
	}

	if (tmpFormAction != null) {
		if (tmpFormAction.type == "hidden") {
			if (myAction != null) tmpFormAction.value = myAction;
			myForm.submit();
		} else {
			tmpFormAction.onclick();
		}
		return true;
	}

	return false;
}

function SubmitAction(myFormName,myActionValue,myWindowName,mySilent) {
	var thisForm = null;

	thisForm = (myWindowName == null) ?
		window.document[myFormName] : top[myWindowName].document[myFormName];

	if (thisForm == null) {
		if (!mySilent) alert('Form not found: ' + myWindowName + '.' + myFormName);
		return false;
	} else if (!SubmitFormAction(thisForm,myActionValue)) {
		if (!mySilent) alert('Action hidden field not found!');
		return false;
	}
	
	return true;
}

function ValueChangeSubmit(FormName) {
	var Form = document[FormName];
	var FieldName = '';
	var Value = '';
	var i = 0;
	for (i=1; i < ValueChangeSubmit.arguments.length; i=i+2) {
		FieldName = ValueChangeSubmit.arguments[i];
		Value = (i+1 < ValueChangeSubmit.arguments.length) ? ValueChangeSubmit.arguments[i+1] : '';
		Form[FieldName].value = Value;
	}
	Form.submit();
	return false;
}

// Given a form input object, this function will set focus to the next input object when the max has been reached
function AutoTab(ThisInput,NextInput) {
	var Action="";
	if (ThisInput.value.length >= ThisInput.maxLength) {
		Action='document.' + ThisInput.form.name + '.' + NextInput + '.focus()';
		eval(Action);
	}
}

// This function will validate the length of the text in a HTML textarea field.
function checkTextLength(myTextArea,maxLength) {
	if (myTextArea.value.length > maxLength) {
		var msg = 'The text in this field is ' + myTextArea.value.length + ' characters long. '
		        + 'The maximun allowed is ' + maxLength	+ '.\nPlease modify your text and try again.';
		alert(msg);
		myTextArea.focus();
		return false;
	}
	return true;
}

function TextCounter(focusfield, field1, field2, countfield, maxlimit, CutoffText) {
	if (CutoffText == null) CutoffText=1;
	//if both fields are filled in assume there's gonna be a space in between
	if (field1.value.length > 0 && field2.value.length > 0) {
		if ((field1.value.length+field2.value.length+1) > maxlimit) {
			if (focusfield == 'field1') {
				if (CutoffText) field1.value = field1.value.substring(0, maxlimit-field2.value.length-1);
				countfield.value = maxlimit - (field1.value.length+field2.value.length+1);
				if (countfield.value < 0) {
					countfield.style.backgroundColor='#FFCCCC';
				} else {
					countfield.style.backgroundColor='#FFFFFF';
				}
			} else if (focusfield == 'field2') {
				if (CutoffText) field2.value = field2.value.substring(0, maxlimit-field1.value.length-1);
				countfield.value = maxlimit - (field1.value.length+field2.value.length+1);
				if (countfield.value < 0) {
					countfield.style.backgroundColor='#FFCCCC';
				} else {
					countfield.style.backgroundColor='#FFFFFF';
				}
			}
		// update our character counter
		} else {
			countfield.value = maxlimit - (field1.value.length+field2.value.length+1);
			if (countfield.value < 0) {
				countfield.style.backgroundColor='#FFCCCC';
			} else {
				countfield.style.backgroundColor='#FFFFFF';
			}
		}
	// no assumed space in between cause they're not both filled in, adjust accordingly
	} else {
		if ((field1.value.length+field2.value.length) > maxlimit) {
			if (focusfield == 'field1') {
				if (CutoffText) field1.value = field1.value.substring(0, maxlimit-field2.value.length);
				countfield.value = maxlimit - (field1.value.length+field2.value.length);
				if (countfield.value < 0) {
					countfield.style.backgroundColor='#FFCCCC';
				} else {
					countfield.style.backgroundColor='#FFFFFF';
				}
			} else if (focusfield == 'field2') {
				if (CutoffText) field2.value = field2.value.substring(0, maxlimit-field1.value.length);
				countfield.value = maxlimit - (field1.value.length+field2.value.length);
				if (countfield.value < 0) {
					countfield.style.backgroundColor='#FFCCCC';
				} else {
					countfield.style.backgroundColor='#FFFFFF';
				}
			}
		// update our character counter
		} else {
			countfield.value = maxlimit - (field1.value.length+field2.value.length);
			if (countfield.value < 0) {
				countfield.style.backgroundColor='#FFCCCC';
			} else {
				countfield.style.backgroundColor='#FFFFFF';
			}
		}
	}
}

function FilterSet (ElementName) {
	$('input#'+ElementName).each(function() {
		if (this.maxLength < 9 && (!this.value.length || 'filter by'.substr(0, this.value.length) == this.value)){ this.maxLength=9; }
		if (!this.value.length || 'filter by'.substr(0, this.value.length) == this.value) { this.value='filter by'; this.className='FilterTextOn'; }
	});
	$('select#'+ElementName).each(function() { if (!this.value.length || this.value == 'filter by') { this.value='filter by'; this.className='FilterTextOn'; } });
}

function FilterClear (ElementName) {
	$('input#'+ElementName).each(function() { if (this.value.length && 'filter by'.substr(0, this.value.length) == this.value) { this.value=''; this.maxLength=this.realMaxLength; } this.className='FilterTextOff'; });
	$('select#'+ElementName).each(function() { this.className='FilterTextOff'; });
}

function FilterButtons () {
	var FilterCount = 0;
	$('input.FilterTextOff,select.FilterTextOff').each( function() { if(this.value.length && this.value != 'filter by'){FilterCount++;} } );
	if (FilterCount) {
		$(":button[name='ApplyFilter']").each(function() {this.disabled=false;});
	} else {
		$(":button[name='ApplyFilter']").each(function() {this.disabled=true;});
	}
}

function FilterClearAll () {
	$('input.FilterTextOff,select.FilterTextOff').each( function() {
		if (this.maxLength < 9){ this.maxLength=9; }
		this.value='filter by'; this.className='FilterTextOn';
	} );
	FilterButtons();
}

function FilterInit () {
	$('input.FilterTextOn,input.FilterTextOff').each( function() {
		this.realMaxLength=this.maxLength;
		if(this.maxLength < 9 && (!this.value.length || 'filter by'.substr(0, this.value.length) == this.value)){this.maxLength=9;this.value='filter by';}	
		if(this.value.length && this.value != 'filter by'){this.className='FilterTextOff';}
		else{this.className='FilterTextOn';this.value='filter by';}
	} );
	$('select.FilterTextOn,select.FilterTextOff').each( function() {
		if(this.value.length && this.value != 'filter by'){this.className='FilterTextOff';}else{this.className='FilterTextOn';this.value='filter by';}
	} );
	FilterButtons();
}

function FormElementCopy(SourceFormId,TargetFormId) {
	var Source = $('#'+SourceFormId);
	var Target = $('#'+TargetFormId);
	var i=0;
	var j=0;
	
	// Remove identical names to prevent duplicates
	for (i=0; i < Source[0].elements.length; i=i+1) {
		for (j=Target[0].elements.length-1; j >= 0; j=j-1) {
			if (Source[0].elements[i].name == Target[0].elements[j].name) {
				$(Target[0].elements[j]).remove();
			}
		}
	}
	// Add
	$(Target).append($(Source[0].elements).clone());
}

//
// This function shifts a selected Option in a Drop Down either up or down.
// Offers up an Alert if there was no selection made in the drop down.
// "DropDown" is the object reference to the Drop Down
// "Direction" is which way the option is being shifted("up" or "down")
// "AlertMessage" is what shows up in the Alert window.
//
function DropDownItemShift(DropDown, Direction, AlertMessage) 
{ if (AlertMessage == null) AlertMessage = "Please select an item to shift Up or Down first.";
  if (Direction == null) Direction = "up";
  var SelectedPosition = DropDown.selectedIndex;
  var SelectedText  = '';
  var SelectedValue = '';
  if (SelectedPosition != -1 && DropDown.options[SelectedPosition].value > "") {
    SelectedText = DropDown.options[SelectedPosition].text;
    SelectedValue = DropDown.options[SelectedPosition].value;
    if (DropDown.options[SelectedPosition].value > "" && SelectedPosition > 0 && Direction == "up") {
      DropDown.options[SelectedPosition].text = DropDown.options[SelectedPosition-1].text;
      DropDown.options[SelectedPosition].value = DropDown.options[SelectedPosition-1].value;
      DropDown.options[SelectedPosition-1].text = SelectedText;
      DropDown.options[SelectedPosition-1].value = SelectedValue;
      DropDown.selectedIndex--;
    } else if (SelectedPosition < DropDown.length-1 && DropDown.options[SelectedPosition+1].value > "" && Direction == "down") {
      DropDown.options[SelectedPosition].text = DropDown.options[SelectedPosition+1].text;
      DropDown.options[SelectedPosition].value = DropDown.options[SelectedPosition+1].value;
      DropDown.options[SelectedPosition+1].text = SelectedText;
      DropDown.options[SelectedPosition+1].value = SelectedValue;
      DropDown.selectedIndex++;
    }
  } else {
    alert(AlertMessage);
  }
}

function DropDownItemTransfer(SrcDropDown, DstDropDown, Move, AlertMessage) 
{ if (AlertMessage == null) AlertMessage = "Please select an item first.";
  if (Move == null) Move = 1;
  var SrcIndex  = 0;
  var DstLength = 0;
  var Text      = '';
  var Value     = '';
  for (SrcIndex=0; SrcIndex < SrcDropDown.length; SrcIndex++) {
	  if (SrcDropDown.options[SrcIndex].selected)  {
		  //SrcIndex = SrcDropDown.selectedIndex;
		  DstLength = DstDropDown.length;
		  if (SrcIndex != -1 && SrcDropDown.options[SrcIndex].value > "") {
		    Text = SrcDropDown.options[SrcIndex].text;
		    Value = SrcDropDown.options[SrcIndex].value;
		    if (Move) {
				SrcDropDown.options[SrcIndex] = null;
				SrcIndex--;
			}
			DstDropDown.options[DstLength] = new Option (Text, Value, false, true);
		  } else {
		    alert(AlertMessage);
		  }
	  }
  }
  if (SrcDropDown.length > 0) SrcDropDown.options[0].selected=true;
}

function SelectToList(theSelect, getAll, Sep) {
	var ValueList = "";
	var loop = 0;

	if (getAll == null) getAll = false;
	if (Sep == null) Sep = ";";
	for (loop=0; loop < theSelect.options.length; loop++) {
		if (theSelect.options[loop].selected == true || getAll) {
			ValueList += theSelect.options[loop].value + Sep;
		}
	}
	return ValueList;
}

function setUseShowErrors(obj,val) {
	obj.useShowErrors = val;
}

///// Start of Refactoring /////
/* All methods above should migrate to this section */

// Establish the HNL app namespace
if (typeof HNL == "undefined") { HNL = {}; }

HNL.Form = function() {

	var formDefaultValues = {};

	/**
	 * @param {String} formId
	 * @param {Input}  el
	 */
	function saveFieldValue (formId, el) {

		var inputId = el.id || el.name;

		if (el && formDefaultValues[formId]) {
			switch (el.type) {
				case 'checkbox':
				case 'radio':
					formDefaultValues[formId][inputId] = {
						value   : el.value,
						checked : el.checked
					};
					break;
				case 'button':
				case 'file':
				case 'hidden':
				case 'password':
				case 'reset':
				case 'submit':
				case 'text':
				case 'textarea':
					formDefaultValues[formId][inputId] = {
						value : el.value
					};
					break;
				case 'select-one':
				case 'select-multiple':
					formDefaultValues[formId][inputId] = {
						selected : el.selectedIndex
					};
				default:
					break;
			}
		}
	}
	
	/**
	 *
	 * @param {String} formId
	 * @param {Input}  el
	 */
	function removeFieldValue(formId, el) {
		
		var inputId = el.id || el.name;

		delete formDefaultValues[formId][inputId];
	}
	
	/**
	 * @param {object} savedState
	 * @param {Input}  el
	 * @return {Boolean}
	 */
	function compareFieldValue(savedState, el) {

		var match = true;

		switch (el.type) {
			case 'checkbox':
			case 'radio':
				match &= savedState.value === el.value;
				match &= savedState.checked === el.checked;
				break;
			case 'button':
			case 'file':
			case 'hidden':
			case 'password':
			case 'reset':
			case 'submit':
			case 'text':
			case 'textarea':
				match &= savedState.value === el.value;
				break;
			case 'select-one':
			case 'select-multiple':
				match &= savedState.selected === el.selectedIndex;
			default:
				break;
		}
		
		return match;
	}
	
	/**
	 * @param {Form}   form
	 * @param {String} elId
	 * @param {String} elName
	 * @param {String} elValue
	 */
	function addHiddenInput (form, elId, elName, elValue) {
		
		var jqForm = $(form);
		
		if (jqForm.length) {

			var formId = form.id;
			var input = jqForm.find('#'+elId);

			if (!input.length) {
				input = document.createElement('input');
				input.setAttribute('type', 'hidden');
				input.setAttribute('id', elId);
				input.setAttribute('name', elName);
				input.setAttribute('value', elValue);
				jqForm.append(input);
				saveFieldValue(formId, input);
			} else {
				input.attr('value', elValue);
				saveFieldValue(formId, input.get(0));
			}	
		}
	}
	
	return {
		
		/**
		 * Checks each of the fields in a form to see if they have been changed and returns the count.
		 * For this to work, the form must have been previously examined by setFormDefaultValues.
		 * 
		 * @param {string} formId The id of the form to check
		 * 
		 * @return {number} Number of fields modified
		 */
		isFormModified: function(formId) {

			var fields = $('#'+formId).find('input,textarea,select').not(':submit');
			var fieldsTracked = 0;
				for (var k in formDefaultValues[formId]) if (formDefaultValues[formId].hasOwnProperty(k)) fieldsTracked++;
			var fieldsChecked = fields.length;
			var fieldsModified = 0;

			fields.each(
				function() {
					var fieldId = this.id || this.name;

					if (!formDefaultValues[formId].hasOwnProperty(fieldId)) {

						fieldsChecked--;
						fieldsModified++;

					} else if (!compareFieldValue(formDefaultValues[formId][fieldId],this)) {

						fieldsModified++;

				    }
				}
			);

			if (fieldsTracked > fieldsChecked) {
				fieldsModified += fieldsTracked - fieldsChecked;
			}

			return fieldsModified;
		},
		
		/**
		 * Creates a snapshot of the current values of each input field in the specified form.
		 * If no forms are specified, then all Forms in the document are processed. These can 
		 * be compared later to see if the form has been modified (see isFormModified).
		 * 
		 * @param {Form} form
		 */
		saveFormDefaultValues: function(form) {
			
			var $form = form ? $(form) : $('form');
			
			$form.each(function() {
				var formId = this.id || '';
				if (formId.length) {
					formDefaultValues[formId] = {};
					$(this).find('input,textarea,select').not(':submit').each(function() {
						saveFieldValue(formId,this);
					});
				}
			});
		},
		
		setFormDefaultValue: function(formId,elId) {
			var el = $('#'+elId);
			if (el.length) {
				saveFieldValue(formId,el.get(0));
			}
		},		
	
		/**
		 * 
		 */
		addHiddenInputToForm: function(formId,elId,elValue) {
			addHiddenInput($('#'+formId).get(0), elId, elId, elValue);
		},
		
		/**
		 * @param {Form}   form
		 * @param {String} nextViewId
		 */
		submitViewTab: function(form,nextViewId) {

			$('input[id=NextViewId]').remove();
			addHiddenInput(form, 'NextViewId', 'NextViewId', nextViewId);
			$('input[id=DefaultAction]:first').click();
			
			return false;
		},
		
		/**
		 * 
		 */
		disableFormWhileAJAX: function(formId) {
		
			$('#'+formId).each(function(){
				var form = $(this);
				// Reference: http://docs.jquery.com/Ajax_Events
				// This event is broadcast if an Ajax request is started and no other Ajax requests are currently running.
				$(document).ajaxStart(function(){
					// The validation js should look for this input and require a value for it.
					var input = document.createElement('input');
					input.setAttribute('type','hidden');
					input.setAttribute('id','AJAXFinished');
					input.setAttribute('name','AJAXFinished');
					input.setAttribute('value','');
					form.prepend(input);
				});
				// This global event is triggered if there are no more Ajax requests being processed.
				$(document).ajaxStop(function(){
					// If an input specified in the validation script does not exist, it will be ignored.
					removeFieldValue(formId, $('#AJAXFinished').get(0));
					$('#AJAXFinished').remove();
				});
			});
		
			return true;
		}
	}

}(); // create singleton
