// *****************************************************************************
// ** Survey System Functions Library (Client Side) (C) 2004 Intersoft Technologies Inc.
// **
// ** Version 1.0 (June 9, 2004)
// *****************************************************************************


// *************************
// * General Functions & Constants
// *******

/* ===================== *
 * Objects
 * ===================== */

// onevent - Allows scripts to be attached which will be executed when a specific function is called
// PRE: none
// POST: onevent object is created
// NOTE: All attached code must be valid when the event is fired.
//       ie. Functions declared, variables declared, etc.
function onevent()
{
	///////////////////////////////////////////////////////////////////////////////
	// Sample Usage
	///////////////////////////////////////////////////////////////////////////////
	//	eg. In document:
	//	var onEventObj = new onevent(); // Creates new onevent object
	//  onEventObj.attachEvent("<code>"); // Attaches Code to object to be called later
	//  onEventObj.fireEvent(); // Executes all attached save code

	///////////////////////////////////////////////////////////////////////////////
	// Objects Structure Standards
	///////////////////////////////////////////////////////////////////////////////
	// onevent:
	//		Properties
	//
	//		Methods
	//			attachEvent(code)   - Attaches code to event
	//			fireEvent()	        - Executes all attached code
	//

	// Public Functions
	this.attachEvent = attachEvnt;
	this.fireEvent = fireEvnt;

	// Private Functions
	this.constructor = constructor;

	// Private Properties
	this.attachedCode = new Array(); // Attached Code to be called

	//////
	// Constructor Code
	//////
	this.constructor();

	// Construct & Initialize the OnSave Object
	function constructor()
	{
		this.attachedCode = new Array();
	}

	/////////////////////////////////////////////////
	// Public Functions
	/////////////////////////////////////////////////

	// attachEvnt - Attach JScript code to be executed when Event is fired
	// PRE: none
	// POST: code is attached to the Save Event Object
	// INPUT: code - Valid JScript Code to be executed
	// RETURNS: none
	function attachEvnt(code)
	{
		this.attachedCode[this.attachedCode.length] = code;
	}

	// fireEvnt - Executes all attached JScript code
	// PRE: none
	// POST: All attached code is executed
	// INPUT: none
	// RETURNS: none
	function fireEvnt()
	{
		for(var i=0;i<this.attachedCode.length;i++)
		{
			eval(this.attachedCode[i]);
		}
	}
}


// flag - Creates a flag and provides functions to toggle it
// PRE: none
// POST: flag object is created
function flag()
{
	///////////////////////////////////////////////////////////////////////////////
	// Sample Usage
	///////////////////////////////////////////////////////////////////////////////
	//	eg. In document:
	//	var LIB_FLAG_DIRTY = new flag(); // Creates new flag object
	//  LIB_FLAG_DIRTY.set(); // Sets flag to true
	//  LIB_FLAG_DIRTY.unset(); // Sets flag to false
	//  LIB_FLAG_DIRTY.isSet(); // Checks flag if it is set or unset; returns true if it is; false otherwise

	///////////////////////////////////////////////////////////////////////////////
	// Objects Structure Standards
	///////////////////////////////////////////////////////////////////////////////
	// onevent:
	//		Properties
	//
	//		Methods
	//			set()            - Sets flag
	//			unset()	        - Unsets flag
	//			isSet()	        - Checks flag if it is set or unset; returns true if it is; false otherwise
	//
	
	// Public Functions
	this.set = set;
	this.unset = unset;
	this.isSet = isSet;

	// Private Functions
	this.constructor = constructor;

	// Private Properties
	this.theFlag = false; // The Flag

	//////
	// Constructor Code
	//////
	this.constructor();

	// Construct & Initialize the OnSave Object
	function constructor()
	{
		this.theFlag = false;
	}	


	/////////////////////////////////////////////////
	// Public Functions
	/////////////////////////////////////////////////

	// set - Sets the flag to true
	// PRE: none
	// POST: flag is set
	// INPUT: none
	// RETURNS: none
	function set()
	{
		this.theFlag = true;
	}

	// unset - Sets the flag to false
	// PRE: none
	// POST: flag is unset
	// INPUT: none
	// RETURNS: none
	function unset()
	{
		this.theFlag = false;
	}


	// isSet - Predicate - Checks if flag is set or not
	// PRE: none
	// POST: Returns true if it is set; false otherwise
	// INPUT: none
	// RETURNS: none
	function isSet()
	{
		return this.theFlag;
	}
}


/* ===================== *
 * Common Event Handlers
 * ===================== */

// LIB_attachDisableEnter - Disables 
// PRE: none
// POST: Enter Key Disabled for fiObj
// INPUT: fiObj is a valid Form Item Object
// RETURN: none
function LIB_attachDisableEnter(fiObj)
{
	fiObj.attachEvent("onkeydown",LIB_disableEnterKey);
}


// LIB_attachChangeDetection - Monitor all form elements & set FLAG_DIRTY if changes detected
// Usage: (Place at end of HTML document) LIB_attachChangeDetection(FORM_NAME, LIB_FLAG_DIRTY.set);
// PRE: none
// POST: An onChange event handler is added that will set FLAG_DIRTY if a change is detected
// INPUT: formObj is a valid FORM Object
//        flagSetFcn is a valid Function
// RETURN: none
function LIB_attachChangeDetection(formObj,flagSetFcn)
{
	for(var i=0;i<formObj.length;i++)
	{
		LIB_attachChangeEvent(formObj.elements[i],flagSetFcn)
	}
}



/* ===================== *
 * Event Handler Helper Functions
 * ===================== */

// LIB_disableEnterKey - Disables the Enter Key
// PRE: none
// POST: Enter Key Disabled
// INPUT: none
// RETURN: none
function LIB_disableEnterKey()
{
	if (event.keyCode == 13) 
	{
		event.returnValue = false;
		return false;
	}
	event.returnValue = true;
	return true;
}

// LIB_disableEnterKeyFor - Disables the enter key for a specific document object (ie. form item)
// PRE: none
// POST: document object does not fire default actions when enter key is pressed
// INPUT: docObj = Document Object (ie. Form Item Object)
// RETURN: none
function LIB_disableEnterKeyFor(docObj)
{
	docObj.attachEvent("onkeydown",LIB_disableEnterKey);
}

// LIB_attachChangeEvent - Attaches a onchange function to a given form item object
// PRE: none
// POST: OnChange event handler attached to given form item object
// INPUT: formObj is a valid FORM ITEM Object
//        flagSetFcn is a valid Function
// RETURNS: none
function LIB_attachChangeEvent(fiObj,flagSetFcn)
{
	fiObj.attachEvent("onchange",flagSetFcn);
}

// setDirtyFlag - Set the Dirty Flag
function LIB_setDirtyFlag() { LIB_FLAG_DIRTY.set();}


/* ===================== *
 * Administrative Functions (Open Window, Save, Close, Preview, Validate)
 * ===================== */

// PAGE_close - Close the Page
// PRE: LIB_FLAG_DIRTY Object must exist
// POST: Asks Confirmation to close page if change detected; Window is closed if confirmed
// INPUT: none
// RETURNS: none
function PAGE_close()
{
	var temp_confirm = true;
	
	// Ask for confirmation if the page has been dirtied
	if (LIB_FLAG_DIRTY.isSet())
	{
		temp_confirm = confirm('Close without saving?');
	}
	
	// Close the window if yes
	if (temp_confirm)
	{
		// Execute other queued events
		LIB_ONCLOSE.fireEvent();

		self.close();
	}
}


// PAGE_print - Prints the page
// PRE: none
// POST: Pops up Print dialogue box.
// INPUT: none
// RETURNS: none
function PAGE_print()
{
	window.print();
}


// Executes Validation Code for a page
// PRE: LIB_ONVALIDATE must be initialized
// POST: Validation of form executed.
// INPUT: none
// RETURNS: true if passed; false if failed
function PAGE_validate()
{
	try
	{
		LIB_ONVALIDATE.fireEvent();
	}
	catch(e)
	{
		alert(""+e);
		return false;
	}

	return true;
}

/* ===================== *
 * General Form Manipulation
 * ===================== */


// Moves Form Select Elements up in the list.
// PRE: none
// POST: Selected List Element is moved up 1 position
// INPUT: sObj is a valid Selection Form Object
//        rangeTop is the # of elements from the top of list to prevent reordering
//        rangeBottom is the # of elements from the bottom of list to prevent reordering
// RETURN: none
function LIB_formSelectMoveUp(sObj,rangeTop,rangeBottom)
{
	var listSelectedPos = sObj.selectedIndex; // Selected Index
	var listLength = sObj.length; // List Length
	var temp_OptionObjPred = null;
	var temp_OptionObjSucc = null;

	if ((listSelectedPos > rangeTop)&&(listSelectedPos < listLength - rangeBottom))
	{
		// Copy of ListItems to be moved
		temp_OptionObjPred = sObj.options[listSelectedPos - 1];
		temp_OptionObjSucc = sObj.options[listSelectedPos];

		// Swap the ListItems
		sObj.options[listSelectedPos] = new Option(temp_OptionObjPred.text,temp_OptionObjPred.value);
		sObj.options[listSelectedPos - 1] = new Option(temp_OptionObjSucc.text,temp_OptionObjSucc.value);;
		
		// Select the moved item
		sObj.options.selectedIndex = listSelectedPos - 1;
		
		return true;
	}
	return false;
}

// Moves Form Select Elements down in the list.
// PRE: none
// POST: Selected List Element is moved down 1 position
// INPUT: sObj is a valid Selection Form Object
//        rangeTop is the # of elements from the top of list to prevent reordering
//        rangeBottom is the # of elements from the bottom of list to prevent reordering
// RETURN: none
function LIB_formSelectMoveDown(sObj, rangeTop, rangeBottom)
{
	var listSelectedPos = sObj.selectedIndex; // Selected Index
	var listLength = sObj.length; // List Length
	var temp_OptionObjPred = null;
	var temp_OptionObjSucc = null;

	if ((listSelectedPos >= rangeTop)&&(listSelectedPos < listLength - 1 - rangeBottom))
	{
		// Copy of ListItems to be moved
		temp_OptionObjPred = sObj.options[listSelectedPos];
		temp_OptionObjSucc = sObj.options[listSelectedPos + 1];

		// Swap the List Items
		sObj.options[listSelectedPos] = new Option(temp_OptionObjSucc.text,temp_OptionObjSucc.value);
		sObj.options[listSelectedPos + 1] = new Option(temp_OptionObjPred.text,temp_OptionObjPred.value);;
		
		// Select the moved item
		sObj.options.selectedIndex = listSelectedPos + 1;

		return true;
	}
	return false;
}


// Inserts Element to Selection List before the selected item
// PRE: none
// POST: Element is inserted into the Selection List before the selected item (if one is selected)
//       SelectedItem remains selected
// INPUT: sObj is a valid Selection Form Object
//        sText is the visible text value for the element
//        sValue is the associated value for the element
// RETURN: none
function LIB_formSelectInsertBefore(sObj,sText,sValue)
{
	var listSelectedPos = sObj.selectedIndex; // Selected Index
	var listLength = sObj.length; // List Length
	var itemOption = new Option(sText,sValue); // Element to be inserted
	var listNew = new Array(); // Array of the New List

	// Check if selected position is valid
	if (!((listSelectedPos >= 0)&&(listSelectedPos < listLength)))
	{
		// If not valid; place selected pos as the last item in list
		listSelectedPos = listLength - 1;
		
		// If the adjusted position is still invalid, use default position
		if ((listSelectedPos < 0)||(listSelectedPos >= listLength)) listSelectedPos = 0;
	}

	var FLAG_inserted = false;
	var TEMP_buffer = null;
	var TEMP_buffer2 = null;
	for(var i=0;i<listLength+1;i++)
	{
		// Insert New Item
		if ((i == listSelectedPos)&&(!FLAG_inserted))
		{
			TEMP_buffer = sObj.options[i];
			sObj.options[i] = new Option(" "+sText,sValue);

			FLAG_inserted = true; // Flag that the item has been inserted
		}
		else if (FLAG_inserted) // Shift Other Items
		{
			if (TEMP_buffer != null)
			{	// Swap Items
				TEMP_buffer2 = sObj.options[i];
				sObj.options[i] = new Option(TEMP_buffer.text,TEMP_buffer.value);
				TEMP_buffer = TEMP_buffer2;
			}
		}
	}

	// Select Newly Inserted Item
	sObj.selectedIndex = listSelectedPos + 1;
	
	return true;
}


// Remove Selected Element from Selection List
// PRE: none
// POST: Selected Element is removed from list
//       Previous item in list is selected
// INPUT: sObj is a valid Selection Form Object
//        rangeTop is the # of elements from the top of list to prevent removal
//        rangeBottom is the # of elements from the bottom of list to prevent removal
// RETURN: none
function LIB_formSelectRemoveSelected(sObj, rangeTop, rangeBottom)
{
	var listSelectedPos = sObj.selectedIndex; // Selected Index
	var listLength = sObj.length; // List Length

	// Check if selected position is valid
	if ((listSelectedPos >= rangeTop)&&(listSelectedPos < listLength - rangeBottom))
	{
		sObj.options[listSelectedPos] = null;
	} else return false;

	// Select Previous Item
	sObj.selectedIndex = listSelectedPos;
	
	return true;
}


// Clear Selection List
// PRE: none
// POST: All Items Removed from list
// INPUT: sObj is a valid Selection Form Object
//        rangeTop is the # of elements from the top of list to prevent removal
//        rangeBottom is the # of elements from the bottom of list to prevent removal
// RETURN: none
function LIB_formSelectRemoveAll(sObj, rangeTop, rangeBottom)
{
	var listLength = sObj.length; // List Length

	// Process in range
	for (var i=rangeTop;i<(listLength-rangeBottom);i++)
	{
		sObj.options[rangeTop] = null; // Remove Item
	}
	

	// Select First Item in list (if exists)
	sObj.selectedIndex = 0;
}

// LIB_formSelectReplaceSelected - Replace value of a selected item
// PRE: item selected
// POST: Selected item is replaced with sText & sValue
// INPUT: sObj is a valid Selection Form Object
//        sText is the visible text value for the element to replace with
//        sValue is the associated value for the element to replace with
//        rangeTop is the # of elements from the top of list to prevent replacement
//        rangeBottom is the # of elements from the bottom of list to prevent replacement
// RETURN: true if successful; false otherwise
function LIB_formSelectReplaceSelected(sObj,sText,sValue, rangeTop, rangeBottom)
{
	var listSelectedPos = sObj.selectedIndex; // Selected Index
	var listLength = sObj.length; // List Length

	// Check if selected position is valid
	if ((listSelectedPos >= rangeTop)&&(listSelectedPos < listLength - rangeBottom))
	{
		sObj.options[listSelectedPos] = new Option(" "+sText,sValue);
	} else return false;

	// Select Previous Item
	sObj.selectedIndex = listSelectedPos;
	
	return true;
}


// LIB_formSelectRadio - Select Radio Item with value 'val'
// PRE: none
// POST: Radio Item with value 'val' is selected; if not exist, then no change
// INPUT: sObj - Radio Button Form Element
//        val - String: Value of item to be selected
// RETURNS: none
function LIB_formSelectRadio(sObj, val)
{
	for(var i=0;i<sObj.length;i++)
	{
		var currType = sObj[i].value;
		if (currType.toLowerCase() == val.toLowerCase())
		{
			sObj[i].checked = true; // Select Desired Item
		}
	}
}

function LIB_formRadioSelectedIndex(sObj)
{
	for(var i=0;i<sObj.length;i++)
	{
		if (sObj[i].checked)
		{
			return i;
		}
	}
	return -1;
}

// LIB_formRadioAttachDblClickDeselect - Allows Radio buttons to be deselected by double clicking on them
// PRE: none
// POST: all radio buttons on given form can be deselected by double clicking
// INPUTS: fObj - Form Object where radio buttons are to be double click deselect enabled
// RETURNS: none
function LIB_formRadioAttachDblClickDeselect(fObj)
{
	// *** Check each form item if it is a radio button
	for (var i=0; i< fObj.length; i++)
	{
		var fiObj = fObj[i];

		// *** attach doubleClick deselection, if it is a radio button
		if (fiObj.type.toLowerCase() == "radio")
		{
			fiObj.ondblclick = function() { if (this.checked == true) {this.checked = false;} }
		}
	}
}

/* ===================== *
 * General Layers Manipulation
 * ===================== */

// LIB_pageHideLayers - Hides all layers given in list
// PRE: listed layers must exist
// POST: all layers listed in the list is hidden
// INPUT: layerList is an array of layerID strings
// RETURN: none
function LIB_pageHideLayers(layerList)
{
	for(var i=0;i<layerList.length;i++)
	{
		try
		{
			document.getElementById(layerList[i]).style.visibility = 'hidden';
			document.getElementById(layerList[i]).style.position = 'absolute';
		} catch(e) {}
	}
}

// LIB_pageShowLayer - Displays a layer (Unhides)
// PRE: Given layer must exist
// POST: Given layer is displayed
// INPUT: layerID is the name of the layer to display as a string
// RETURN: none
function LIB_pageShowLayer(layerID)
{
	try
	{
		document.getElementById(layerID).style.visibility = 'visible';
		document.getElementById(layerID).style.position = 'relative';
	} catch(e) {}
}

