// detect the browser
var ie  = /MSIE/.test(navigator.userAgent);
var moz = !ie && navigator.product == "Gecko";

/**
 * Gecko-based browsers only implement the click function for elements of tyep input.
 * This is used to implement click() on all HTMLElement's (the behavior that
 * Internet Explorer has).
 */
if (moz)
//if (HTMLElement && !HTMLElement.click && HTMLElement.prototype && !HTMLElement.prototype.click)
{
	HTMLElement.prototype.click = function() {
		var evt = this.ownerDocument.createEvent('MouseEvents');
		evt.initMouseEvent('click', true, true, this.ownerDocument.defaultView, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
		this.dispatchEvent(evt);
	}
} // end if we don't have a click() function for HTMLElement

/**
 * Gets an element's children, by tag name
 *
 * @param {Object} element the parent element
 * @param {String} tag_name the type of children to get (tag name)
 * @return {Array} an array of elements
 */
function getChildrenByTagName(element, tag_name)
{
	var child_array      = new Array();
	var tag_name         = tag_name.toLowerCase();
	var element_children = element.childNodes;
	
	// loop through the child elements
	for (var i = 0; i < element_children.length; i++) {
		
		// check if the element has a tag name
		if (element_children[i].tagName != undefined) {
			
			// check if the element is the type that we are looking for
			if (element_children[i].tagName.toLowerCase() == tag_name) {
				
				child_array.push(element_children[i]);
			} // end if the element is the type that we are looking for
		} // end if the element has a tag name
	} // end loop through the child elements
	
	return child_array;
} // end function getChildrenByTagName()

/**
 * Gets the values of all descendant nodes with a given tag name
 * 
 * @param {Object} node node to get descendant values from
 * @param {String} tag_name descendant tag name
 * @return {String|Array} value(s) of the descendant(s)
 */
function getDescendantValues(node, tag_name)
{
	var node_values = new Array();
	var descendants = node.getElementsByTagName(tag_name);
	
	// loop through the descendants and get the values
	for (var i = 0; i < descendants.length; i++)
	{
		// get the current value
		var node_value = descendants[i].firstChild.nodeValue;
		
		// if only one descendant was found, return the value, not an array
		if (descendants.length == 1)
		{
			return node_value;
		}
		
		// add the value to the array
		node_values.push(node_value);
	} // end loop through the descendants
	
	return node_values;
} // end function getDescendantValues()

/**
 * Adds an event listener to an element
 * 
 * Implements the functionality of addEventListener in all browsers.
 * 
 * @link http://developer.mozilla.org/en/docs/DOM:element.addEventListener
 * 
 * @param {Object} element element to attach the event listener to
 * @param {String} event_type a string representing the event type to listen for
 * @param {EventListener} function_ref the object that receives a notification
 * when an event of the specified type occurs
 * @param {Boolean} capture whether the user wishes to initiate capture
 */
function attachEventListener(element, event_type, function_ref, capture)
{
	if (undefined == capture)
	{
		capture = false;
	}
	
	// standards compliant (supports addEventListener)
	if (typeof element.addEventListener != 'undefined')
	{
		element.addEventListener(event_type, function_ref, capture);
	} // end if standards compliant
	// IE
	else if (typeof element.attachEvent != 'undefined')
	{
		event_type = "on"+event_type;
		element.attachEvent(event_type, function_ref);
	} // end if IE
	// non-DOM
	else
	{
		event_type = "on"+event_type;
		
		// check if we have a function for this event already
		if (typeof element[event_type] == 'function')
		{
			// make the new function run the old function and the new function
			var old_listener = element[event_type];
			element[event_type] = function()
			{
				old_listener();
				return function_ref();
			}
		} // end if we have a function for this event already
		// we don't have a function for this event yet
		// just set it normally
		else
		{
			element[event_type] = function_ref;
		} // end if we don't have a function for this event yet
	} // end if non-DOM
	
	return true;
} // end function attachEventListener()