function addEvent(el, action, handler)
{
	if (el.addEventListener)
	{
		el.addEventListener(action, handler, false);
	} 
	else if(el.attachEvent)
	{
		el.attachEvent('on'+action, handler);
	}
}

/**
 * Ideally, we could pass objects to addEventListener, and object.handleEvent would automatically be called (like the spec).
 * This method allows us to refrence 'this' as the handling method's parent, not the event.
 * The event is then passed to the method as it's first property.
 *
 * @XXX Does this anonymous function cause memory problems?
 * 
 * @param object
 * @param objectMethod
 * @param allow_bubble - by default, bubbling is cancelled for performance gain. Set to true to allow bubbling.
 * 
 * @return
 */
function delegateHandler(object, objectMethod, allow_bubble)
{
	return function(e)
	{
		if(!e) var e = window.event;
		if(!e.target)
		{
			e.target = e.srcElement;
		}
		
		if(!allow_bubble)
		{
			e.cancelBubble = true;
			if (e.stopPropagation) e.stopPropagation();
		}

		return objectMethod.call(object, e); 
	}
}

// Wrapper for document.getElementById()
$ = function(element_id)
{
	//Check if is already an element
	if(element_id.nodeName)
	{
		return element_id;
	}
	return (document.getElementById(element_id));
}

// Method for getting an array of objects with a given class name.
// Optionally make this faster by passing in a tag_name (i.e. td, span)
// And / Or a parent element
$$ = function(class_name, tag_name, parent_element)
{
	var tag_name = tag_name ? tag_name : '*';
	var parent = parent_element ? $(parent_element) : document.body;
	
	if(!parent) return;
	
	var children = parent.getElementsByTagName(tag_name);
	
	var matches = [];
	
	// Loop over all elements
	for(var i in children)
	{
		if(typeof children[i] == 'undefined') continue;
		if(!children[i].className) continue;

		var classes = children[i].className.split(' ');

		// Loop over class names
		for(var x in classes)
		{
			if(classes[x] == class_name)
			{
				matches.push(children[i]);
			}
		}
	}

	return matches;
}

//Toggle the visibility of an element.
toggleVisi = function(elem_id)
{
	$(elem_id).style.visibility = ($(elem_id).style.visibility == 'visible') ? 'hidden' : 'visible';
}

toggleDisplay = function(elem_id, type)
{
	var type = (type) ? type : 'block';
	$(elem_id).style.display = ($(elem_id).style.display == 'none') ? type : 'none';
}

// Hides the error notices
hide_error_notices = function()
{
	toggleVisi('error_shroud');
	toggleVisi('notices');
}

//New popup, returns the window's reference for further actions.
newWindow = function(url, width, height, other_attributes, return_object)
{
	var attribute_string = (other_attributes) ? ',' +  other_attributes : '';

	// Variable variable name, so new popups don't overwrite old ones. (var name is the same as url itself.)
	window[url] = window.open(url, window[url], 'width='+width + ',' + 'height=' + height + attribute_string);
	
	if(return_object)
	{
		return window[url];
	}
}

autoComplete = function(input_elem_id, data_source)
{
	var input_elem = $(input_elem_id);
	var suggestions_ul = document.createElement('ul');
	
	var form = input_elem.form;
	var count = 0;
	
	var tmout;

	suggestions_ul.style.display = 'none';
	suggestions_ul.className = 'auto_complete';
	input_elem.parentNode.insertBefore(suggestions_ul, input_elem.nextSibling);
	
	function submitParent(value)
	{
		input_elem.value = value;
		suggestions_ul.style.display = 'none';
		if(form.onsubmit)
		{
			form.onsubmit();
			return;
		}
		
		form.submit();
	}
	
	function requestDropDownData(event)
	{
		makeRequest = function()
		{
			var params = new Array;
			params[input_elem.id] = input_elem.value;

			new ajaxRequest({
				method: 'post',
				url: data_source,
				params: params,
				onSuccess: populateDropDown		
			});
			clearTimeout(tmout);
		}
		
		var keycode = event.which ? event.which : event.keyCode;

		if(input_elem.value.length < 3 || (keycode != 8 && input_elem.value.length > 3 && suggestions_ul.getElementsByTagName('li').length < 1) )
		{
			suggestions_ul.style.display = 'none';
			return;
		}

		if(tmout != undefined)
		{
			clearTimeout(tmout);
		}
		tmout = setTimeout('makeRequest()',350);
	}

	
	
	function populateDropDown(response)
	{
		suggestions_ul.innerHTML = '';

		var drop_down_result = response.view_data[form.name];

		var row_count = 0;
		
		for(var i in drop_down_result)
		{
			var li = document.createElement('li');
			li.innerHTML = '<a>' + drop_down_result[i] + '</a>';
			li.onclick = function(){submitParent(this.getElementsByTagName('a')[0].innerHTML)};
			li.setAttribute('class', (row_count % 2 ? 'even' : 'odd'));
			suggestions_ul.appendChild(li);
			row_count++;
		}

		if(drop_down_result && drop_down_result.length > 0)
		{
			suggestions_ul.style.display = 'block';
		}
		else
		{
			suggestions_ul.style.display = 'none';
		}
	}

	addEvent(input_elem, 'keyup', requestDropDownData);
}

reloadGameTopScores = function(response)
{
	$('game_top_scores_inner').innerHTML = response.elements.game_top_scores_inner;
}


function getCookie(name)
{
	if (document.cookie.length>0)
	{
		var start = document.cookie.indexOf(name + "=");
		if (start != -1)
		{
			start = start + name.length+1;
			var end = document.cookie.indexOf(";",start);
			if (end == -1) end = document.cookie.length;
			return unescape(document.cookie.substring(start, end));
		}
	}
	return false;
}

function setCookie(name, value, cookie_duration)
{
	var expiry = new Date();
	expiry.setDate(expiry.getDate() + cookie_duration);
	document.cookie = name+ "=" +escape(value) + ((cookie_duration == null) ? "" : ";expires=" + expiry.toUTCString());
}