// timer

var o3_events = new Array();
function o3_stash_event(func, arg)
{
	var event = new Object();
	event.func = func;
	event.arg = arg;
	o3_events.push(event);
	return o3_events.length-1;
}

function o3_set_timer(id, interval)
{
	setTimeout("o3_call_timer("+id+")", interval);
}

function o3_call_timer(id)
{
	var event = o3_events[id];
	event.func(event.arg);
	return true;
}

// logging

function log(msg)
{
	var body = document.getElementById("log");
	body.appendChild(document.createTextNode(msg));
	body.appendChild(document.createElement("br"));
}

// compatability

//function add_array_push()
//{
//	if (!Array.prototype.push)
//	{
//		Array.prototype.push = function() 
//		{
//			for(i=0; i<arguments.length; ++i)
//			{
//				this[this.length] = arguments[i];
//			}
//			return this.length;
//		}
//	}
//}

function add_document_getElementById()
{
	if (!document.getElementById && (document.all || document.layers))
		{ document.getElementById = get_element_by_id; }
}

function get_element_by_id(id)
{
	if (this.getElementById)
		{ return this.getElementById(id); }

	var obj;
	if (this.all)
	{
		obj = this.all[id];
	}
	else if (this.layers)
	{
		obj = getObjNN4(document, id);
		obj.style = obj;
	}

	obj.getElementById = get_element_by_id;
	return obj;
}

function get_layerelement_by_id(parent, id)
{
	var base = parent.layers;
	var found;
	for (var i=0; i < x.length; ++i)
	{
		if (base[i].id == id)
			{ found = base[i]; }
		else if (base[i].layers.length)
			{ found = get_layerelement_by_id(base[i], id); }
		if (found) { break; }
	}
	
	return found;
}

function get_all_children(e) 
{
	return e.all ? e.all : e.getElementsByTagName('*');
}

function for_each(elements, func)
{
	for (var i=0; i<elements.length; ++i)
	{
		func(elements[i]);
	}
}

function event_get_target(event)
{
	if (!event) var event = window.event;

	var target = event.target ? event.target : event.srcElement;
	if (target.nodeType == 3) // Safari bug
		{ target = target.parentNode; }

	return target;
}

function event_get_keycode(event)
{
	if (!event) var event = window.event;

	var code = event.keyCode ? event.keyCode : event.which;
	return code;
}

function event_stop_propogation(event)
{
	event.cancelBubble = true;
	if (event.stopPropagation) event.stopPropagation();
}

function sum_offsets(element, attr)
{
	var sum = 0;
	while(element)
	{
		sum += element[attr];
		element = element.offsetParent
	}

	return sum;
}

function element_set_selection(element, start, end)
{
	if (element.createTextRange)
	{
		var r = element.createTextRange();
		if (start >= 0)
			{ r.moveStart("character", start); }
		if (end >= 0)
			{ r.moveEnd("character", end); }
		r.select();
	}
	else if (element.setSelectionRange)
	{
		if (end < 0) { end = element.selectionEnd; }
		if (start < 0) { start = element.selectionStart; }
		element.setSelectionRange(start, end);
	}
}

function O3TextRange(element)
{
	this.element = element;
	this.start = 0; 
	this.end = element.value.length;
}

O3TextRange.prototype.moveStart = function(noise, length)
{
	this.start += length;
}

O3TextRange.prototype.moveEnd = function(noise, length)
{
	this.end += length;
}

O3TextRange.prototype.select = function()
{
	this.element.setSelectionRange(this.start, this.end);
}

// o3_utility

var o3e_post_setup = new Array();
function o3_post_setup_add(func)
{
	o3e_post_setup[o3e_post_setup.length] = func;
}

function o3_setup()
{
	for_each(get_all_children(document), o3_install_triggers);
	for_each(o3e_post_setup, function(func) { func(); });
}

function o3_install_triggers(element)
{
	var attrs = element.className.split(' ');
	for (var i=0; attrs[i]; ++i)
	{
		if (attrs[i].indexOf('o3i_') != 0) { continue; }

		var obj = window[attrs[i]];
		if (!obj) { return; }
		if (obj._oninstall) { obj._oninstall(element); }
		for (var meth in obj)
		{
			if (meth.charAt(0) == '_') { continue; }
			if (!element['o3m_' + meth])
			{ 
				element['o3m_' + meth] = new Array(); 
				element[meth] = o3_run_triggers;
			}
			var marr = element['o3m_' + meth]; 
			marr[marr.length] = obj[meth];
		}
	}
}

function o3_run_triggers(event)
{
	if (!event) var event = window.event;
	var marr = this['o3m_on'+event.type];

	var ret = true;
	for (var i=0; ret && marr[i]; ++i)
	{ 
		this.o3m_temp = marr[i];
		ret = this.o3m_temp(event);
		this.o3m_temp = null;
	}
	return ret;
}

var o3e_next_id = 0;
function o3_assign_id(element)
{
	if (!element.id)
		{ element.id = "o3e_" + ++o3e_next_id; }
}

function o3_reparent(element)
{
	var parent = element.parentNode;
	if (parent.tagName != 'SPAN')
	{
		parent = document.createElement("SPAN");
		element.parentNode.replaceChild(parent, element);
		parent.appendChild(element);
	}
	return parent;
}

function o3_append_class(element, name)
{
	if (element.className && element.className != "")
	{
		name = " " + name;
	}
	element.className += name;
}

function o3_element_add_suggestions(element)
{
	if (!element.o3_suggestions)
	{
		element.o3_suggestions = new O3DataSource(element.id);
	}
}
