

/**
* HGFormElement
*
* A single input element for an HGForm
*
* @param t: The type of input element
* @param v: An initial value of the input element
*           For a drop down selection, v would expect a 2D array of the following form
*           [ [ selection value ], [ selection description ] ]
* @param n: The name of the input element
* @param w: The width of the input element
* @param h: The height of the input element
* @param mw: The max width of the input element
* @param stc: The command to be called upon a state change event
* @param vpc: The command to be called upon generation of the form element to populate an initial value
* @param verbose_description: A more english text to be displayed during rendering
* @param tool_tip_content: Text to be displayed as a tool tip
**/
function HGFormElement( 
	t ,
	v ,
	n ,
	w ,
	h ,
	mw ,
	stc ,
	vpc ,
	verbose_description ,
	tool_tip_content
) { 

	//check to see if t is within the valid types 
	if ( 
		t != "text" &&
		t != "password" &&
		t != "textArea" &&
		t != "selection"
	) { 
		throw ( "HGFormElement->constructor: Invalid HGFormElement type exception" );
	}

	this.type = t;
	this.initial_value = v;
	this.name = n;
	this.width = w;
	this.height = h;
	this.max_width = mw;
	this.state_change_command = stc;
	this.value_population_command = vpc;
	
	this.verbose_description = verbose_description;
	this.tool_tip_content = tool_tip_content;

	switch( this.type ) { 

		case "text": 
			this.form_element = document.createElement( 'input' );
			this.form_element.type = "text";
			if ( this.width != null ) 
				this.form_element.size = this.width;
			else
				this.form_element.size = 20;
			if ( this.max_width != null ) 
				this.form_element.maxLength = this.max_width;
			if ( this.initial_value != null ) 
				this.form_element.value = this.initial_value;
			break;

		case "password":
			this.form_element = document.createElement( 'input' );
			this.form_element.type = "password";
			if ( this.width != null ) 
				this.form_element.size = this.width;
			else
				this.form_element.size = 20;
			if ( this.max_width != null ) 
				this.form_element.maxLength = this.max_width;
			
			break;

		case "textArea":
			this.form_element = document.createElement( 'textArea' );
			if ( this.width != null ) 
				this.form_element.cols = this.width;
			else
				this.form_element.cols = 200;
			if ( this.height != null ) 
				this.form_element.rows = this.height;
			else
				this.form_element.rows = 20;
			if ( this.initial_value != null ) 
				this.form_element.value = this.initial_value;
			
			break;

		case "selection":
			this.form_element = document.createElement( 'select' );
			
			if ( this.initial_value != null ) { 
				for ( var i=0; i<this.initial_value.length; i++ ) { 
					this.form_element.options.add( new Option( this.initial_value[i][1], this.initial_value[i][0] ) );
				}
				this.form_element.options[0].defaultSelected = true;
			}
			
			break;

	}

	if ( this.form_element ) {
		this.form_element.name = this.name;
		
		//make sure the object is accessable from the DOM form object
		this.form_element.associatedHGFormElement = this;
	}

	//create and execute the value population command if it is non null
	if ( this.value_population_command != null ) {
		var mvpn = new HGFormValuePopulationCommand( this );
		mvpn.execute();
	}

	//if the state change function is present, set up the on state change listener
	if ( this.state_change_command ) { 
		//this.state_change_command_object = new this.state_change_command( this );
		CBAddEventListener( this.form_element, "change", StateChangeCommandClosureFactory( this, this.state_change_command ) );
	}

	return true;

}

/**
* HGFormElement.getValue
*
* Returns the current value of the form element
**/
HGFormElement.prototype.getValue = function() { 

	return this.form_element.value;

}

/**
* HGFormElement.repopulate
*
* Clears any current value within the HGForm and calls a new population command.  Currently implemented for selection only.
*
* @param c The new command to call
**/
HGFormElement.prototype.repopulate = function( c ) { 

	//clear options 
	this.form_element.options.length = 0;

	//change the value population command
	this.value_population_command = c;

	//run the new population command
	var mvpn = new HGFormValuePopulationCommand( this );
	mvpn.execute();
	
}

/**
* HGFormValuePopulationCommand
*
* Call the value population command defined within the HGFormElement 
* 
* @param f: The HGFormElement
**/
function HGFormValuePopulationCommand( f ) {

	this.hgFormElement = f;

}

new HGFormValuePopulationCommand( null );

HGFormValuePopulationCommand.prototype.execute = function() { 

	this.hgFormElement.value_population_command.execute( this.hgFormElement );

	return true;

}

/**
* StateChangeCommandClosureFactory
*
* Create a closure containing information necessary and instructions to build the appropriate state change command for a form element
*
* @param f: The form element we are building the state change command for
* @param stc: The state change command we are building
**/
function StateChangeCommandClosureFactory( f, stc ) { 
	
	var form_element = f;
	var state_change_command = stc;

	var rf = function() { 

		var stc_object = new state_change_command( form_element );
		stc_object.execute();

	}

	return rf;

}



