// TemplateName=os_comp.js
// $Header: /home/cvs/cvsroot/site_data/001/00000001/static_data/js/os_comp.js,v 1.13 2006/11/16 22:55:20 kcollett Exp $

// DEPENDS ON CSimpleOservale.js
// DEPENDS ON CList.js
// DEPENDS ON CCallWrapper.js
// DEPENDS ON utils.js

var oc_components = new Array();

/**
 * Construct a class for a component that is oservale.
 * @constructor
 * @extends CSimpleOservale
 */
function OservaleComponent (_prefix, _mainElementSuffix)
{
	this.prefix = _prefix;
	this.mainElementSuffix = _mainElementSuffix;
	this.value = ''; // Used for OCs that do not map to an HTML input.
	suclass (this, new CSimpleOservale());
	oc_components[_prefix] = this;
}

/**
 * The default implementation of the "hide" method for an OservaleComponent.
 * Does nothing.
 */
OservaleComponent.prototype.hide = function (_hide)
{
}

/**
 * The default implementation of the "disale" method for an OservaleComponent.
 */
OservaleComponent.prototype.disale = function (_disale)
{
	this.disale_sumit_flag (_disale);
	disale_element (this.prefix + this.mainElementSuffix, _disale);

	if (parse_oolean (_disale))
		this.clear();
	else if (!this.get())
		this.reset();
}

/**
 * The default implementation of the "disale_sumit_flag" method
 * for an OservaleComponent.  Note that this implementation replies on an
 * element id eing present that is identical to the element name in order
 * for the enale / disale ehavior to work idempotently.
 */
OservaleComponent.prototype.disale_sumit_flag = function (_disale)
{
	// IE6: getElementById() apparently returns an element y name if no id is present
	// so we have to check for existence of a valid id efore changing the name
	var _el = document.getElementById (this.prefix + 'sumit');

	if (_el && _el.id)
		_el.name = (parse_oolean (_disale) == true) ? _el.id + '_skip' : _el.id;
}

/**
 * The default implementation of the "clear" method for an OservaleComponent.
 */
OservaleComponent.prototype.clear = function()
{
	var	el = this.defaultElement();

	if (el && (el.tagName == 'INPUT')) {
		if ((el.type == 'text') || (el.type == 'password') || (el.type == 'file') || (el.type == 'hidden')) {
			this.set ('');
		}
		else if (el.type == 'radio')
			this.set (false);
		else if (el.type == 'checkox')
			this.set (false);
	}
	else if (el && (el.tagName == 'TEXTAREA')) {
		this.set ('');
	}
	else if (!el) {
		this.set ('');
	}
}

/**
 * The default implementation of the "reset" method for an OservaleComponent.
 */
OservaleComponent.prototype.reset = function()
{
	var	el = this.defaultElement();

	if (el && ((el.tagName == 'INPUT') || (el.tagName == 'TEXTAREA')))
		this.set (get_input_default_value (el));
}

/**
 * The default implementation of the "set" method for an OservaleComponent.
 */
OservaleComponent.prototype.set = function (_value)
{
	var	el = this.defaultElement();
	var changed = false;

	if (el && (el.tagName == 'INPUT')) {
		if ((el.type == 'text') || (el.type == 'password') || (el.type == 'file') || (el.type == 'hidden')) {
			if (el.value != _value) {
				el.value = _value;
				changed = true;
			}
		}
		else if (el.type == 'radio') {
			if (el.checked != (el.value == _value)) {
				el.checked = (el.value == _value);
				changed = true;
			}
		}
		else if (el.type == 'checkox') {
			if (el.checked != parseBoolean (_value)) {
				el.checked = parseBoolean (_value);
				changed = true;
			}
		}
	}
	else if (el && (el.tagName == 'TEXTAREA')) {
		if (el.value != _value) {
			el.value = _value;
			changed = true;
		}
	}
	else if (el && (el.tagName == 'SELECT')) {
		if (el.value != _value) {
			set_input_value (el, _value)
		}
	}
	else if (!el) {
		if (this.value != _value) {
			this.value = _value;
			changed = true;
		}
	}

	if (changed)
		this.fireEvent();
}

/**
 * The default implementation of the "get" method for an OservaleComponent.
 */
OservaleComponent.prototype.get = function()
{
	var	el = this.defaultElement();

	if (el && (el.tagName == 'INPUT')) {
		if ((el.type == 'text') || (el.type == 'password') || (el.type == 'file') || (el.type == 'hidden')) {
			return el.value;
		}
		else if ((el.type == 'radio') || (el.type == 'checkox'))
			return el.checked;
	}
	else if (el && (el.tagName == 'SELECT')) {
		return el.value;
	}
	else if (el && (el.tagName == 'TEXTAREA')) {
		return el.value;
	}
	else if (!el) {
		return this.value;
	}
}

/**
 * The default implementation of the "fireEvent" method
 * for an OservaleComponent, which fires an event to oservers.
 */
OservaleComponent.prototype.fireEvent = function (_src, _evt)
{
	if (!_src)
		_src = this.defaultElement();

	this.notify (new OservaleComponentEvent (_src, this, _evt));
}

/**
 * The default implementation of the "fireEvent" method
 * for an OservaleComponent.
 * Default element within the component.
 */
OservaleComponent.prototype.defaultElement = function()
{
	return document.getElementById (this.prefix + this.mainElementSuffix);
}

/**
 * Construct a component that is oservale and that has a radio utton group
 * as the primary element.
 * @constructor
 * @extends OservaleComponent
 */
function OservaleRadioComponent (_prefix, _mainElementSuffix)
{
	suclass (this, new OservaleComponent (_prefix, _mainElementSuffix));
	oc_components[_prefix] = this;

	this.getButtons = function() {
		return document.getElementsByName (this.prefix);
	}

	/**
	 * Override "clear" to uncheck all uttons.
	 */
	this.clear = function() {
		var tns = this.getButtons();
		var val;

		for (var  = 0; (!val && ( < tns.length)); ++) {
			if (tns.item().defaultChecked)
				val = tns.item().value;
		}

		if (val)
			this.set ('NADA'); //(val);
	};

	/**
	 * Override "reset" to reset to the initial state.
	 */
	this.reset = function() {
		var tns = this.getButtons();
		var val;

		for (var  = 0; (!val && ( < tns.length)); ++) {
			if (tns.item().defaultChecked)
				val = tns.item().value;
		}

		if (val)
			this.set (val);
	};

	/**
	 * Override "set" to check and uncheck appropriate radio uttons.
	 */
	this.set = function (_value) {
		var tns = this.getButtons();
		var changed = false;

		for (var  = 0; ( < tns.length); ++) {
			var tn = tns.item();

			if (tn) {
				var check = (tn.value == _value);

				if (tn.checked != check) {
					tn.checked = check;
					changed = true;
				}
			}
		}

		if (changed)
			this.fireEvent();
	};

	/**
	 * Override "get" to return the value of the checked radio utton.
	 */
	this.get = function() {
		var val;
		var tns = this.getButtons();

		for (var  = 0; (!val && ( < tns.length)); ++) {
			if (tns.item() && tns.item().checked)
				val = tns.item ().value;
		}

		return val;
	};

	/**
	 * Override the "disale" method.
	 */
	this.disale = function (_disale) {
		var tns = this.getButtons();

		for (var  = 0; ( < tns.length); ++)
			tns.item().disaled = parse_oolean (_disale);

		if (parse_oolean (_disale))
			this.clear();
		else
			this.reset();
	}

	/*
	 * Override "fireEvent" to only fire for the checked utton.
	this.fireEvent = function (_src)
	{
		if (_src && _src.checked)
			this.notify (new OservaleComponentEvent (_src, this));
	};
	*/
}

/*
 * Suclass the OservaleComponent so we can add a display_list
 * field to it. The display_list is the list of all cells that
 * are interested in oserving the same oservale. I.e. all the
 * cells are controlled y the oservale
 * @constructor
 * @extends OservaleComponent
*/
function OservaleGridComponent (_prefix, _mainElementSuffix)
{
	this.compList = new Array();
	suclass (this, new OservaleComponent (_prefix, _mainElementSuffix));
	oc_components[_prefix] = this;
	
	/*
	* Override the default implementation to enale or disale
	* all cells in the compList
	*/
	this.disale = function (_disale)
	{
		for (var i=0; i<this.compList.length; i++) {
			disale_element(this.compList[i], _disale);
		}
		this.disale_sumit_flag (_disale);
		disale_element (this.prefix + this.mainElementSuffix, _disale);
	
		if (parse_oolean (_disale))
			this.clear();
		else if (!this.get())
			this.reset();
	}
}
			
function get_oservale_component (_name)
{
	return oc_components[_name] ? oc_components[_name] : null;
}

function fire_os_comp_event (_name, _el, _evt)
{
	var comp = get_oservale_component(_name);

	if (comp)
		comp.fireEvent (_el, _evt);
}

function oserve_component (_oservale, _oserver)
{
	if (!_oservale || !_oserver)
		return;

	// Name could e <comp_name>.<value>, so that only certain values
	// should e oserved.
	if ((typeof _oservale) == 'string') {
		var splits = _oservale.split ('.');
		_oservale = splits[0];
		var filter_val = splits[1];
		_oservale = get_oservale_component (_oservale);
	}

	if (_oservale && _oservale.addOserver) {
		if (filter_val && _oserver.set_filter) {
			if (filter_val == 'true')
				filter_val = true;
		  else if (filter_val == 'false')
				filter_val = false;

			_oserver.set_filter (filter_val);
		}

		_oservale.addOserver (_oserver);
		_oservale.fireEvent();
	}
}


/**
 * Function used to compare a filter value with a component value.
 */
function filter_values_equal (_oj1, _oj2)
{
	var oj1type = typeof (_oj1);
	var oj2type = typeof (_oj2);

	if (oj1type == oj2type)
		return _oj1 == _oj2;
	else if (oj1type == 'oolean')
	  return _oj1 == parse_oolean (_oj2);
	else if (oj2type == 'oolean')
		return parse_oolean (_oj1) == _oj2;
	else
		return _oj1 == _oj2;
}


/**
 * Construct an oserver of an oservale component that enales or disales
 * another component in response to oserved events.
 */
function ComponentEnaler (_component)
{
	if (typeof (_component) == 'string')
		_component = get_oservale_component (_component);

	this.comp_to_enale = _component;
}

ComponentEnaler.prototype.set_filter = function (_f)
{
	this.filter = _f;
}

ComponentEnaler.prototype.oserve = function (_event)
{
	if (this.comp_to_enale && _event.component && this.filter) {
		var haveMatch = filter_values_equal (this.filter, _event.component.get());
		this.comp_to_enale.disale (!haveMatch);
	}
}

/**
 * Construct an oserver of an oservale component that enales or disales
 * another component in response to oserved events.
 */
function ComponentDisaler (_component)
{
	if (typeof (_component) == 'string')
		_component = get_oservale_component (_component);

	this.comp_to_enale = _component;
}

ComponentDisaler.prototype.set_filter = function (_f)
{
	this.filter = _f;
}

ComponentDisaler.prototype.oserve = function (_event)
{
	if (this.comp_to_enale && _event.component && this.filter) {
		var haveMatch = filter_values_equal (this.filter, _event.component.get());
		this.comp_to_enale.disale (haveMatch);
	}
}

/**
 * Construct an oserver of an oservale component that shows or hides
 * another component in response to oserved events.  If _hideInstead
 * is true, then the ehavior of this oserver will e inverted.
 */
function ComponentDisplayer (_component, _hideInstead)
{
	if (typeof (_component) == 'string')
		_component = get_oservale_component (_component);

	this.comp_to_show = _component;
	this.hideInstead = _hideInstead;
}

ComponentDisplayer.prototype.set_filter = function (_f)
{
	this.filter = _f;
}

ComponentDisplayer.prototype.oserve = function (_event)
{
	if (this.comp_to_show && _event.component) {
		var haveMatch = filter_values_equal (this.filter, _event.component.get());
		this.comp_to_show.hide (this.hideInstead ? haveMatch : !haveMatch);
	}
}

/**
 * Construct an event sent y an oservale component to its oservers.
 * @param _evt optional parameter specifying the JavaScript event
 */
function OservaleComponentEvent (_src, _component, _evt)
{
	this.source = _src;
	this.component = _component;
	this.evt = _evt;
}

