//##############################################################
// form interigator
// author: Scott Ingram
//
// Workaround for Jato's field naming behavior.
// Finds the  <FORM> with an id of "pes_form".
// Traverses its elements[] array.
// Stores a reference to each element (ie, textfield, checkbox, etc)
// into PES_FORM under the original name of the obj.

// Don't access PES_FORM directly!
// use get_pes_obj() instead - it guarantees proper initialization.

var PES_FORM = { initialized:false } ;
var DEBUG = true;

//##############################################################
// 12-may-2005 SI - now allows you to use functions to turn DEBUG on or off
function set_debug_off() { DEBUG = false; }
function set_debug_on()  { DEBUG = true; }

function is_keypress_equal_enter(event)
//##############################################################
{
	var keynum;

	if(window.event) // IE
	{
		keynum = event.keyCode;
	}
	else if(event.which) // Netscape/Firefox/Opera
	{
		keynum = event.which;
	}

	return (keynum == 13);
}

function debug(msg)
//##############################################################
// 11-may-2005 SI - now allows you to interactively turn DEBUG off
{
	if(DEBUG)
	{
		DEBUG = confirm ("DEBUG: " + msg);
	}
}

function un_muck_name(name)
//##############################################################
// 11-may-2005 SI - pulled out of initialize_pes_dom
{
        if (name==null) return name;
	var dot = name.lastIndexOf(".");
	var start = (dot == -1) ? 0 : dot+1;
	var end = name.length;
	return name.substr(start,end);
}

function is_app_info(name)
//##############################################################
// 23-Feb-2006 SI - used to ignore hidden tags created by AppInfo
{
        if (name==null) return false;
	return ( name.indexOf("appinfo:") == 0 );
}

function initialize_pes_dom()
//##############################################################
// called automatically by get_pes_obj()
{
	if (PES_FORM.initialized) return;

	var i;
	var my_form;
	var n = document.forms.length;
	for(i=0; i<n; i++)
	{
		my_form = document.forms[i];
		if (my_form.id == "pes_form") { break; }

		var first = my_form.elements[0];
		if (first && first.name == "pes_form_marker") { break; }

		my_form = null;
	}

	if(my_form == null)
	{	debug ("Cannot locate any FORM with id='pes_form' or with a first element named 'pes_form_marker'");
		return;
	}

	PES_FORM.root = my_form;

	n = my_form.elements.length;
	for(i=0; i<n; i++)
	{
		var obj = my_form[i];
		var name = obj.name;

		var un_mucked_name = is_app_info(name) ? name : un_muck_name(name);

		// skip unnamed fields
		if (! un_mucked_name) { continue; }

		// skip Jato 2.1.4's checkbox peer hidden fields 
		if (un_mucked_name == "jato_boolean") { continue; }

		// Special code for radio button & checkbox problem...
		// document.form.radio_x
		// 	is an array of all radio buttons named "radio_x"
		// document.form.elements[]
		// 	contains individual elements for all radio buttons named "radio_x"
		// As such, get_pes_obj("radio_x") would return the
		// last instance of "radio_x", not an array.
		// But with the following code, it simulates the in-built browser array boxing.
		// TODO - SI - solve problem of tiled views producing multiple copies of same field
		// TODO - SI - solve problem of multi vals that aren't radio / checkbox types

		var exists = PES_FORM[un_mucked_name];

		if (exists)
		{
			if (exists.constructor == Array)
			{	// push the new obj into the existing array[]
				// TODO -
				// make sure objecs in array are same type as obj
				exists[exists.length] = obj;
			}
			else if
			(	(exists.type.toLowerCase() == "radio") ||
				(exists.type.toLowerCase() == "checkbox")
			)
			{	// replace existing entry with an array 
				// containing both it and the new obj
				PES_FORM[un_mucked_name] = [exists,obj];
			}
			else
			{	var type = exists.type;
				// 28-JAN-2009 SI
				// this debug message is causing more problems than it is solving
				//debug ("DEBUG: Problem in form! Incompatible objects share name.  name(" + un_mucked_name + ") type("+type+")");
			}
		}
		else
		{	PES_FORM[un_mucked_name] = obj;
		}

		if ( ! PES_FORM.first_field )
		{
			var type = obj.type.toLowerCase();
			if (type == "text")
			{
				PES_FORM.first_field = obj;
			}
			//debug("first_field = " + name + "   type="+type);
		}

	}

	PES_FORM.initialized = true;
}

function exists_pes_obj(name)
//##############################################################
{
	// turn off DEBUG warnings
	var tmp = DEBUG;
	DEBUG = false;

	// get the object, or null if it's not there
	var x = get_pes_obj(name);

	// restore DEBUG warnings
	DEBUG = tmp;

	return (x != null);
}

function has_pes_form()
//##############################################################
{
	// silence debug messages
	var tmp = DEBUG;
	DEBUG = false;

	// initialize the DOM
	initialize_pes_dom();

	// restore debug state
	DEBUG = tmp;

	//if the PES_FORM.root field is not null, then there is a form
	return (PES_FORM.root != null);
}

function get_pes_form()
//##############################################################
{	initialize_pes_dom();
	return PES_FORM.root;
}

function get_first_field()
//##############################################################
{	initialize_pes_dom();
        
        if (PES_FORM) {
            return PES_FORM.first_field;
        }
}

function get_pes_obj(name)
//##############################################################
{	initialize_pes_dom();
	var obj = PES_FORM[name];
	if (obj == null) 
	{	// Since the user can start manipulating the form
		// before the page is completely loaded,
		// we must short circuit the caching mechanism.
		// Force a reinitialization, and try again!
		PES_FORM = { initialized:false };
		initialize_pes_dom();

		// 14-SEP-2005 - WOW, can't believe this line wasn't here until now!
		obj = PES_FORM[name];
	}
	if (obj == null) { debug ("DEBUG: get_pes_obj(" +name+ ") is null"); }
	return obj;
}

function get_pes_val(name)
//##############################################################
{	initialize_pes_dom();
	var obj = get_pes_obj(name);
	if (obj == null) { return "" };

	var type = (obj.type) ? obj.type.toLowerCase() : "";
	var value = "";

	// for arrays of radios and checkboxes,
	// return the value of the first checked item.
	if (obj.constructor == Array)
	{	var n = obj.length;
		for(var i=0; i<n; i++)
		{	var item = obj[i];
			if (item.checked)
			{	value = item.value;
				break;
			};
		}
	}
	else if
	(	(type == "radio") ||
		(type == "checkbox")
	)
	{	if (obj.checked) { value = obj.value };
	}
	else if (type.substring(0,6) == "select")
	{	var picked = obj.selectedIndex;
		if (picked == -1) { return ""; }
		value = obj[picked].value;
	}
	else
	{	value = obj.value;
	}

	return value;
}

var multi_val_sep = "~CUT~";

function set_pes_val(name, value)
//##############################################################
// sets the value of ANY form field, including radios, menus, etc.
// If the "value" param is actually an array, all of its elements
// will be set into checkboxes or SELECT OPTION fields as appropriate.
// If value is a flat string that is the result of concatenating
// several values together, with the  multi_val_sep in between each,
// it will be split into an array, and treated as above.
{
	initialize_pes_dom();
	var obj = get_pes_obj(name);
	if (obj == null) { return };

	//var input_is_array = (value.constructor == Array);
	var input_not_string = (value.constructor != String);
	var values = (input_not_string) ? [value] : value.split(multi_val_sep);

	// if value == "" then values will no elements.
	// make sure that we have atleast one element
	if(values.length == 0) values = [""];

	var type = (obj.type) ? obj.type.toLowerCase() : "";

	var is_select = (type.substring(0,6) == "select");
	var is_array  = (obj.constructor == Array);
	var is_multi  = (is_array || type == "select-multiple")

	// for multi-selects or arrays of radios and checkboxes
	// initialize to none-selected
	if (is_array)
	{
		var n = obj.length;
		for(var i=0; i<n; i++)
		{
			obj[i].checked = false;
		}
	}
	else if (is_select || is_multi)
	{
		obj.selectedIndex = -1;
	}

	// create a loop to support multiple values
	for (var val_index=0; val_index<values.length; val_index++)
	{
		value = values[val_index];

		// for arrays of radios and checkboxes,
		// set the item(s) that match(es) value
		if (is_array)
		{
			var option_num = obj.length;

			// loop through all checkboxes / radios in the group
			BOX_LOOP:
			for(var i=0; i<option_num; i++)
			{	var item = obj[i];
				if (value == item.value)
				{	item.checked = true;
					break BOX_LOOP;
				}
			}
		}
		else if (is_select)
		{
			var found = false;

			// loop through all possible choices in the menu
			OPT_LOOP:
			for(var i=0; i<obj.length; i++)
			{	var item_val = obj[i].value;
				if (value == item_val)
				{	obj.selectedIndex = i;
					found = true;
					break OPT_LOOP;
				}
			}

			// otherwise, set to NONE SELECTED
			if (! found)
			{
				obj.selectedIndex = -1;
				debug("DEBUG: value=(" + value + ") does not exist in menu=(" + name + ")" );
			}
		}
		else if
		(	(type == "radio") ||
			(type == "checkbox")
		)
		{	if (value = obj.value) { obj.checked = true; };
		}
		else
		{	obj.value = value;
		}
	}

	return value;
}
