/* ===== VESSEL/TYPIC.JS ===== */

function $(elem_id)
{
	return document.getElementById(elem_id);
}

if (!window.console) // Define dummy for IE
{
	var console = new Object();
	console.debug = function() {}
	console.error = function() {}
	console.log = function() {}
}

String.prototype.trim = String.prototype.trim || function() {
    return this.replace(/^\s+/,'').replace(/\s+$/,'');
}

Array.prototype.indexOf = Array.prototype.indexOf || function(item, start) {
    for (var i = (start || 0); i < this.length; i++) {
        if (this[i] == item) {
            return i;
        }
    }
    return -1;
}

Array.prototype.push = Array.prototype.push || function() {
    for (var i = 0; i < arguments.length; i++) {
        this[this.length] = arguments[i];
    }
    return this.length;
}


Array.prototype.splice = Array.prototype.splice || function(start, deleteCount) {
    var beg = this.slice(0, start);
    var del = this.slice(start, start + deleteCount);
    var end = this.slice(start + deleteCount);

    var ins = [];
    for (var i = 2; i < arguments.length; i++) {
    	ins[i-2] = arguments[i];
    }
    
    this.length = 0;
    var tmp = this.concat(beg, ins, end);
    for (var i = 0; i < tmp.length; i++) {
    	this[i] = tmp[i];
    }

    return del;
}

// typic.get_element - protypic - actyvic


/* .... TYPIC OBJECT ... */

var Typic = new Object();

function typic_get_elem(elem)
// Deprecated
{
	return Typic._elem(elem);
}

function typic_add_item(elem, vars)
// Takes the item prototype (elem) and makes a copy with the provided parameters (vars)
{
	return Typic.insert(elem, vars);
}
	
function typic_clone_item(elem1, elem2, vars)
// Like add_item, but inserts the new item into a different list
{
	var elem1 = typic_get_elem(elem1);
	var elem2 = typic_get_elem(elem2);
	if (typeof(vars) == "array")
	{
		var vars = cynic_compose_query_string(vars);
	}
	var new_elem = elem1.cloneNode(true);
	new_elem.style.display = "";
	new_elem = elem2.parentNode.appendChild(new_elem);
	
	prototype_id = elem2.getAttribute("id");
	var new_elem_id = prototype_id + ":" + typic_extract_var("id", vars);
	new_elem.setAttribute("id", new_elem_id);
	new_elem.setAttribute("typic_vars", vars);
	typic_set_elem(new_elem, vars);
	return new_elem;
}

Typic._elem = function(elem)
// Takes an element id or element and returns the element
{
	if (typeof(elem) == "string")
	{
		var x = $(elem);
		if (x)
			return x;
		else
			return null;
	}
	else if (typeof(elem) == "object")
		return elem;
	else
		return null;
}

Typic.insert = function(elem, vars)
// Insert a new element with the given parameters (vars)
{
	var elem = typic_get_elem(elem);
	if (typeof(vars) == "array")
	{
		var vars = cynic_compose_query_string(vars);
	}
	var new_elem = elem.cloneNode(true);
	new_elem.style.display = "";
	new_elem = elem.parentNode.appendChild(new_elem);
	
	prototype_id = elem.getAttribute("id");
	var new_elem_id = prototype_id + ":" + typic_extract_var("id", vars);
	new_elem.setAttribute("id", new_elem_id);
	new_elem.setAttribute("typic_vars", vars);
	typic_set_elem(new_elem, vars);
	Typic.removeClass(new_elem, "typic_proto");
	return new_elem;
}

Typic.copy = function(source_elem, proto_elem)
// Copies the data of a list element and inserts it into another list
{
	typic_add_item(proto_elem, typic_get_item_vars(source_elem));
}

Typic.move = function(source_elem, proto_elem)
{
	Typic.copy(source_elem, proto_elem);
	Typic.remove(source_elem);	
}

Typic.remove = function(elem)
{
	if (elem = Typic._elem(elem))
		elem.parentNode.removeChild(elem);
}

function typic_set_elem(elem, vars)
{
	var elem = typic_get_elem(elem);
	if (!elem)
		return;
	
	if (elem.nodeType == "1") // Normal element (HTML tag)
	{
		for (var i = 0; i < elem.attributes.length; i++)
		{
			var value = elem.attributes[i].value;
			var name = elem.attributes[i].name;
			if (name.match(/typic_.+/i))
			{
				name = name.replace(/typic_(.+)/i, "$1");
				new_value = typic_replace_vars(value, vars);
				elem.setAttribute(name, new_value);
				if (name.match(/on.+/i)) // IE bug - events wont be set by setting attributes
					elem[name] = new Function(new_value);
				if (name.match("class")) // IE bug - class wont be set by setting attributes
					elem.className = new_value;
			}
		}
		for (var i = 0; i < elem.childNodes.length; i++)
		{
			typic_set_elem(elem.childNodes[i], vars);
		}
	}
	else if (elem.nodeType == "3") // Text element (not HTML tag)
	{
		var text = typic_replace_vars(elem.nodeValue, vars);
		var tmp = document.createElement("div");
		tmp.innerHTML = text;
		elem.nodeValue = tmp.innerHTML;
	}	
}

function typic_replace_vars(txt, vars)
{
	var vars = vars.split("&");
	for (var i = 0; i < vars.length; i++)
	{
		var z = vars[i].split("=");
		var name = z[0];
		var value = decodeURIComponent(z[1]);
		var match = "{" + name + "}";
		txt = txt.replace(match, value);
		match = "^" + name + "^";
		txt = txt.replace(match, value);
	}
	return txt;
}

function typic_set_var(name, value, vars)
	{
	vars = vars.split("&");
	for (var i=0; i<vars.length; i++)
		{
		var z = vars[i].split("=");
		if (name == z[0])
			z[1] = value;
		vars[i] = z.join("=");
		}
	vars = vars.join("&");
	return vars;
	}

function typic_remove_item(elem)
{
	elem = typic_get_elem(elem);
	elem.parentNode.removeChild(elem);
}

function typic_get_item_vars(elem)
	{
	elem = typic_get_elem(elem);
	if (!elem)
		return "";
	vars = elem.getAttribute("typic_vars");
	return vars;
	}
	
function typic_extract_var(name, vars)
	{
	vars = vars.split("&");
	for (var i=0; i<vars.length; i++)
		{
		var z = vars[i].split("=");
		if (z[0] == name)
			return z[1];
		}
	}

function typic_get_parameters(elem)
{
	var vars = typic_get_item_vars(elem);
	return cynic_parse_query_string(vars);
}

function typic_swap_items(elem1,elem2)
	{
	elem1 = typic_get_elem(elem1);
	elem2 = typic_get_elem(elem2);
	elem1.parentNode.insertBefore(elem2, elem1);
	}

function typic_flash_item(item_id, c)
	{
	return;
	elem = typic_get_elem(item_id);
	vars = "color="+color[c];
	typic_set_elem(elem, vars);
	c++;
	if (c < color.length)
		setTimeout('typic_flash_item("'+item_id+'",'+c+')', 25);
	else
		{
		vars = typic_get_item_vars(elem);
		typic_set_elem(elem, vars);
		}
	}
	
//var color = new Array("#505050","#a0a020","#ffff00","#c0a000","#a05000");
var color = new Array("#a0a020", "#ffff00");

var last_push_time = new Date();

function typic_push_item(prototype_id, vars)
	{
	// The time procedures are for when more items are pushed at the same time.
	// Then they will be scheduled for pushing with an interval.
	push_time = new Date();	
	time_dif = push_time.getTime() - last_push_time.getTime();
	last_push_time.setTime(push_time.getTime());
	time_dif_min = 25;
	time_wait = time_dif_min - time_dif;
	if (time_wait < 0) time_wait = 0;
	last_push_time.setTime(push_time.getTime() + time_wait);
	setTimeout("typic_push_item_now('"+prototype_id+"', '"+vars+"')", time_wait);
	}
	
function typic_push_item_now(prototype_id, vars)
	{
	elem_id = typic_extract_var('id', vars);
	item_id = prototype_id + "_" + elem_id;
	if (elem = document.getElementById(item_id))
		{
		vars_old = typic_get_item_vars(elem);
		count_old = typic_extract_var("count", vars_old);
		count = parseInt(count_old) + parseInt(typic_extract_var("count", vars));
		vars = typic_set_var("count",count, vars);
		typic_set_item(elem, vars);
		}
	else
		{
		typic_add_item(prototype_id, vars);
		}
	typic_flash_item(prototype_id + "_" + elem_id, 0);
	setTimeout("typic_sort_item_list('"+prototype_id+"', 'count')", 200);
	}

function typic_sort_item_list(elem_id, order_by)
	{
	elem = typic_get_elem(elem_id);
	item_list = elem.parentNode.childNodes;
	for (i = 0; i < item_list.length - 1; i++)
		{
		elem1 = item_list[i];
		elem2 = item_list[i+1];
		if (elem1.nodeType == "1")
			{
			vars1 = typic_get_item_vars(elem1);
			if (vars1)
					{
				vars2 = typic_get_item_vars(elem2);
				count1 = typic_extract_var(order_by, vars1);
				count2 = typic_extract_var(order_by, vars2);
				if (parseInt(count2) > parseInt(count1))
					{
					typic_swap_items(elem1, elem2);
					id = elem2.getAttribute("id");
					typic_flash_item(id, 0);
					setTimeout("typic_sort_item_list('"+elem_id+"', '"+order_by+"')", 200);
					return;
					}
				}
			}
		}
	}
	
function typic_flush_list(elem, n) // Truncates list (optional: to n elements)
{
	if (elem == "typic:alertbox")
	{
		Alertbox.hide();
		return;
	}
	
	if (!n) n = 0;
	var elem = typic_get_elem(elem);
	var elem_id = elem.getAttribute("id");
	var item_list = elem.parentNode.childNodes;
	for (i = 0; i < item_list.length; i++)
	{
		elem = item_list[i];
		if (elem.nodeType == "1")
		{
			id = elem.getAttribute("id");
			if ((id) && (id.match(elem_id + ".+")))
			{
				if (n == 0)
				{					
					typic_remove_item(elem);
					i--;
				}
				else
					n--;
			}
		}
	}
}

function typic_expand_collapse(elem, img)
	{
	elem = typic_get_elem(elem);
	//elem = elem.parentNode;
	if (elem.getAttribute("typic_display") == "collapsed")
		{
		typic_expand(elem, img);
		}
	else
		{
		typic_collapse(elem, img);
		}
	}

function show_html(elem)
{
	alert(elem.parentElement.innerHTML);
}

var typic_flowbox = new Array();

function typic_flowbox_add_item(flowbox, elem, vars)
{
	// works with an element like this: <div typic_max_height="300" style="_height: 0px">
	elem = typic_get_elem(elem);
	new_elem = typic_add_item(elem, vars);

	if (typic_flowbox_overflowed(flowbox))
	{
		typic_remove_item(new_elem);
		return 0;
	}
	else
		return 1;
}

function typic_flowbox_overflowed(flowbox)
{
	flowbox = typic_get_elem(flowbox);
	if ((document.all) && (!flowbox.style.height))
		flowbox.style.height = 0;
	if (flowbox.clientHeight > flowbox.getAttribute("typic_max_height"))
		return 1
	else
		return 0
}

function typic_expand(elem)
{
	y = $(elem + ":collapsed");
	x = $(elem + ":expanded");
	if (!x)
		x = $(elem);
	
	x.style.visibility = "hidden";
	x.style.position = "absolute";
	x.style.display = "";
	max = x.clientHeight;
	
	x.style.overflow = "hidden";
	x.style.height = "20px";
	x.style.position = "relative";
	x.style.visibility = "visible";
	
	if (y)
		y.style.display = "none";
	
	typic_smooth_expand(elem, 20, max);
}

function typic_collapse(elem)
{
	x = document.getElementById(elem + ":expanded");
	x.style.display = "none";
	x = document.getElementById(elem + ":collapsed");
	x.style.display = "";
}

function typic_smooth_expand(elem, h, max)
{
	h = parseInt(h);
	max = parseInt(max);
	var x = $(elem + ":expanded");
	if (!x)
		x = $(elem);
	x.style.height = h + "px";
	x.style.opacity = h / max;
	x.style.filter = "alpha(opacity=" + (h / max) * 100 + ")";
	if (h == max)
		return;
	h = h + 1 + (max - h) / 10;
	if (h > max)
		h = max;
	setTimeout("typic_smooth_expand('" + elem + "', " + h + ", " + max + ")", 20);
}

Typic.smooth_expand = function(elem, time, start_height, end_height, fade_in)
{
	elem = Typic._elem(elem);
	if (start_height)
		elem.h = start_height;
	if (end_height)
		elem.max = end_height;
	if (fade_in)
		elem.fade_in = fade_in;
	if (time)
		elem.time = time;
	var h = elem.h ? elem.h : 20;
	var max = elem.max ? elem.max : elem.clientHeight; //parseInt(Typic.get_style(elem, "height").replace(/[^\d]/, ""));
	
	elem.style.height = h + "px";
	if (elem.fade_in)
	{
		elem.style.opacity = h / max;
		elem.style.filter = "alpha(opacity=" + (h / max) * 100 + ")";
	}
	
	if (h == max)
	{
		elem.h = null;
		return;
	}
	h = h + 1 + (max - h) / 5;
	if (h > max)
		h = max;
	elem.h = h;
	elem.max = max;
	setTimeout("Typic.smooth_expand('" + Typic.get_id(elem) + "')", elem.time || 40);
}

function typic_alertbox(cla, message, callback, url)
{
	if (cla == "error")
	{
		Alertbox.error(message);
		return;
	}
	if (cla == "ok")
	{
		Alertbox.ok(message);
		return;
	}
	if (cla == "wait")
	{
		Alertbox.wait(message);
		return;
	}
	if (cla == "confirm")
	{
		Alertbox.confirm(message, callback);
		return;
	}
	if (cla == "window")
	{
		Alertbox.window(url);
		return;
	}
	
	typic_flush_list("typic:alertbox");
	if (!url) url = "";
	message = encodeURIComponent(message);
	typic_add_item("typic:alertbox", "id=1&message=" + message + "&class=" + cla + "&callback=" + callback + "&url=" + url);
	if ((cla == "ok") || (cla == "error"))
	{
		setTimeout("typic_flush_list('typic:alertbox')", 1000);
		if (callback)
			setTimeout(callback + "()", 1100);
	}
}


Typic.confirm = function(message, callback)
{
	Alertbox.confirm(message, callback);
	/*
	if (typeof(callback) == "function")
	{
		Typic.callback = callback;
		callback = "Typic.callback";
	}
	typic_alertbox("confirm", message, callback);*/
}

Typic.wait = function(message)
{
	Alertbox.wait(message);
	//typic_alertbox("wait", message);
}

Typic.ok = function(message)
{
	Alertbox.ok(message);
	//typic_alertbox("ok", message);
}

// ............... TYPIC_CLUE .................. //

function typic_clue_init(init_elem)
{
	var li = Typic.getElementsByClass("typic_clue_field");
	for (var i = 0; i < li.length; i++)
	{
		var elem = li[i];
		elem.onkeydown = function(event)
		{
			return typic_clue_keydown(event, this.name);
		}
		elem.onfocus = function()
		{
			return typic_clue_show_list(this.name);
		}
		elem.onclick = elem.onfocus;
		elem.onblur = function()
		{
			return typic_clue_hide_list(this.name);
		}
	}
	
	var li = Typic.getElementsByClass("typic_clue");
	for (var i = 0; i < li.length; i++)
	{
		var elem = li[i];
		elem.onmouseover = function()
		{
			return typic_clue_mouse_over(this);
		}
		elem.onmousedown = function()
		{
			return typic_clue_select(this.getAttribute("name"));
		}
	}
	
	var li = Typic.getElementsByClass("typic_clue_list");
	for (var i = 0; i < li.length; i++)
	{
		li[i].style.display = "none";
		li[i].style.position = "absolute";
	}
	
	
	return typic_clue_show_list(init_elem.name);
}

function typic_clue_show_list(name)
{
	var elem = typic_clue_get_list_elem(name);
	elem.style.display = "block";
	
	if (!typic_clue_get_selected(name))
	{
		typic_clue_focus(typic_clue_get_clue_elems(name)[0]);
	}
}

function typic_clue_hide_list(name, now)
{
	var elem = typic_clue_get_list_elem(name);
	if ((!now) && (elem.style.display == "block"))
	{
		setTimeout("typic_clue_hide_list('"+name+"', true)", 100);
		return;
	}
	var elem = typic_clue_get_list_elem(name);
	elem.style.display = "none";
}

function typic_clue_focus(elem)
{
	elem.className = elem.className.replace("typic_clue", "typic_clue_focus");
}

function typic_clue_unfocus(elem)
{
	elem.className = elem.className.replace("typic_clue_focus", "typic_clue");
}

function typic_clue_get_list_elem(name)
{
	var li = Typic.getElementsByClass("typic_clue_list");
	for (var i = 0; i < li.length; i++)
	{
		if (li[i].getAttribute("name") == name)
			return li[i];
	}
}

function typic_clue_get_field_elem(name)
{
	var li = Typic.getElementsByClass("typic_clue_field");
	for (var i = 0; i < li.length; i++)
	{
		if (li[i].getAttribute("name") == name)
			return li[i];
	}
}

function typic_clue_get_clue_elems(name)
{
	var a = new Array();
	var li = document.getElementsByTagName("*");
	for (var i = 0; i < li.length; i++)
	{
		if (li[i].getAttribute("name") == name)
			if (li[i].className.match(new RegExp("(^|\\s)typic_clue(_focus)?(\\s|$)")))
				a.push(li[i]);;
	}
	return a;
}

function typic_clue_get_selected(name)
{
	var li = Typic.getElementsByClass("typic_clue_focus");
	for (var i = 0; i < li.length; i++)
	{
		if (li[i].getAttribute("name") == name)
			return li[i];
	}
}

function typic_clue_mouse_over(elem)
{
	var name = elem.getAttribute("name");
	var selected = typic_clue_get_selected(name);
	if (selected)
		typic_clue_unfocus(selected);
	typic_clue_focus(elem);
}

function typic_clue_select(name)
{
	var selected = typic_clue_get_selected(name);
	var value = selected.innerHTML.trim();
	var fieldelem = typic_clue_get_field_elem(name);
	fieldelem.value = value;
	fieldelem.focus();
	return false;
}

function typic_clue_keydown(event, name)
{
	if (event.which == "40")
	{	
		var li = typic_clue_get_clue_elems(name);
		for (var i = 0; i < li.length; i++)
		{
			if (li[i].className.match(new RegExp("(^|\\s)typic_clue_focus(\\s|$)")))
			{
				if (i + 1 < li.length)
				{
					typic_clue_unfocus(li[i]);
					typic_clue_focus(li[i+1]);
					i = li.length;
				}
			}
		}		
		return false;
	}
	if (event.which == "38")
	{
		var li = typic_clue_get_clue_elems(name);
		for (var i = 0; i < li.length; i++)
		{
			if (li[i].className.match(new RegExp("(^|\\s)typic_clue_focus(\\s|$)")))
			{
				if (i > 0)
				{
					typic_clue_unfocus(li[i]);
					typic_clue_focus(li[i-1]);
					i = li.length;
				}
			}
		}		
		return false;
	}
	if (event.which == "13")
	{
		typic_clue_select(name);
		return false;
	}
	
}

Typic.elementExistsInStringList = function(element, stringList, separator)
{
	// separator might need regexp escaping first...
	return stringList.match(new RegExp("(^|"+separator+")" + element + "("+separator+"|$)", "i"));
}

Typic.mouseover_init = function(elem_id)
{
	if (typeof(elem_id) == "object")
	{
		Typic.mouseover_init_element(elem_id);
		return;
	}
	var li = Typic.getElementsByClass("typic_mouseover", elem_id);
	for (var i = 0; i < li.length; i++)
	{
		var elem = li[i];
		elem.onmouseover = function()
		{
			if (this.mouseout_delay_timer)
				clearTimeout(this.mouseout_delay_timer);
			Typic.addClass(this, "mouseover");
		}
		elem.onmouseout = function()
		{
			elem_id = Typic.get_id(this);
			this.mouseout_delay_timer = setTimeout("Typic.removeClass(document.getElementById('" + elem_id + "'), 'mouseover'", 1000);
		}
		Typic.removeClass(elem, "typic_mouseover");
	}
	
	var li = Typic.getElementsByClass("typic_click");
	for (var i = 0; i < li.length; i++)
	{
		var elem = li[i];
		var att_old = elem.getAttribute("onclick");
		var att_new = "Typic.toggleClassName(this, 'click'); Typic.removeClass(this, 'mouseover')";
		if (att_old != "")
			att_new = att_old + "; " + att_new;
		elem.setAttribute("onclick", att_new);
		Typic.removeClass(elem, "typic_click");
	}
}

Typic.mouseover_init_element = function(elem)
{
	if (elem.mouseout_delay_timer) // If mouseover shortly after mouseout... cancel the pending mouseout event and do nothing
		clearTimeout(elem.mouseout_delay_timer);
	else
	{

		if (!elem.onmouseout)
			elem.onmouseout = function()
			{
				elem_id = Typic.get_id(this);
				this.mouseout_delay_timer = setTimeout("Typic.removeClass(document.getElementById('" + elem_id + "'), 'mouseover'); document.getElementById('" + elem_id + "').mouseout_delay_timer = null", 20);
			}
		
		Typic.addClass(elem, "mouseover");
		
		// The following only applies to top level navigation elements
		if (Typic.hasClass(elem, "level1") && Typic.hasClass(elem, "smooth-expand-submenu"))
		{
			var sub = elem.getElementsByTagName("ul")[0];
			if (sub)
			{	
				Typic.smooth_expand(sub);
			}
		}
	}
}

// .................. TYPIC POPUP ................. //

Typic.popup_init = function(source_elem, target_elem)
// Associates a popup menu to an element and attaches event handlers to open and close it.
// Usage: <div id="elem_id" onclick="Typic.popup_init(this)">
// The popup element should have id="popup@elem_id", unless the target id is passed as second parameter
{
	source_elem = Typic._elem(source_elem);
	if (source_elem.typic_popup_target_elem) // Event already attached
	{
		Typic.popup_open(source_elem);
		return;
	}
	
	if (!target_elem)
		target_elem = "popup@" + Typic.get_id(source_elem);
	target_elem = Typic._elem(target_elem);

	// We need to create an element, that can recieve focus. This element should not be seen.
	var focus_elem = document.createElement("input");
	Typic.addClass(focus_elem, "blind");
	
	target_elem.appendChild(focus_elem);
	target_elem.typic_popup_focus_elem = focus_elem;
	focus_elem.onblur = function()
	{
		// Closing the popup menu needs to be delayed, or it might close before a click is received
		setTimeout("Typic.popup_close('" + Typic.get_id(this.parentNode) + "')", 100);
	}
	
	source_elem.typic_popup_target_elem = target_elem;
	Typic.popup_open(source_elem);
}

Typic.popup_open = function(elem)
{
	elem = Typic._elem(elem);
	var target_elem = elem.typic_popup_target_elem;
	Typic.removeClass(target_elem, "blind");
	target_elem.typic_popup_focus_elem.focus();
}

Typic.popup_close = function(elem)
{
	elem = Typic._elem(elem);
	if (elem)
		Typic.addClass(elem, "blind");
}


/* ------------------ */

Typic.get_id = function(elem)
// This function will return the elements unique id attribute
// If it doesn't have one already set, it will apply a unique one
// (The purpose is to be able to reference the element later)
{
	if (elem.id)
		return elem.id;
	var i = 1;
	while ($("typic" + i))
		i++;
	elem.id = "typic" + i;
	return elem.id;
}

Typic.onkeyup_delay = function(elem)
// This will execute the elements onchange event handler 
// half a second after the keyupevent, if no more keys are pressed
// assign to element's onkeyup event [onkeyup="Typic.onkeyup_delay(this)"]
{
	var id = Typic.get_id(elem);
	elem.value2 = elem.value;
	if (elem.timer)
		clearTimeout(elem.timer);
	elem.timer = setTimeout("$('"+id+"').onchange()", 500);
}

Typic.outline = function(elem)
{
	//var oe = document.createElement("div");
	
	elem.style.zoom = "1";
	oe = elem.cloneNode(false);
	
	oe = elem.offsetParent.appendChild(oe);
	
	oe.onmouseover = null;
	oe.style.position = "absolute";
	oe.style.top = parseInt(elem.offsetTop + 1) + "px";
	oe.style.left = parseInt(elem.offsetLeft + 1) + "px";
	oe.style.width = parseInt(elem.offsetWidth - 2) + "px";
	oe.style.height = parseInt(elem.offsetHeight - 2 ) + "px";
	oe.style.border = "1px dashed yellow";
	elem.style.zoom = "normal";
}

Typic.get_style = function (oElm, strCssRule)
{
	var strValue = "";
	if(document.defaultView && document.defaultView.getComputedStyle){
		strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule);
	}
	else if(oElm.currentStyle){
		strCssRule = strCssRule.replace(/-(w)/g, function (strMatch, p1){
			return p1.toUpperCase();
		});
		strValue = oElm.currentStyle[strCssRule];
	}
	return strValue;
}

Typic.get_absolute_offset = function (obj)
{
	var curleft = curtop = 0;
	if (obj.offsetParent) {
		curleft = obj.offsetLeft
		curtop = obj.offsetTop
		while (obj = obj.offsetParent) {
			curleft += obj.offsetLeft
			curtop += obj.offsetTop
		}
	}
	return [curleft,curtop];
}

Typic.activate_hasLayout = function(elem)
// Activates hasLayout for all block elements
{
	if (!elem)
	{
		var elems = document.getElementsByTagName("*");
		for (var i = 0; i < elems.length; i++)
			Typic.activate_hasLayout(elems[i]);
	}
	else
	{
		if (Typic.get_style(elem, "display") == "block")
			elem.style.zoom = "1";
	}
}

// ----------- STRING LISTS ------------- //


String.prototype.has = function(element)
{
	var separator = this._separator();
	
	// separator might need regexp escaping first...
	return this.match(new RegExp("(^|"+separator+")" + element + "("+separator+"|$)", "i"));
}

String.prototype.add = function(element)
{
	var separator = this._separator();
	if (!this.has(element))
	{
		if (this.length == 0)
			return element
		else
			return this.valueOf() + separator + element;
	}
}

String.prototype.remove = function(element)
{
	var separator = this._separator();
	var value = this.replace(new RegExp("(^|" + separator + ")(" + element + ")(" + separator + "|$)", "gi"), "$1$3");
	value = value.replace(new RegExp(separator + "+", "gi"), separator);
	return value.replace(new RegExp("(^" + separator + "|" + separator + "$)", "gi"), "");
}

String.prototype.toggle = function(element)
{
	if (this.has(element))
		this.remove(element);
	else
		this.add(element);
}

String.prototype._separator = function()
{
	if (!this.separator)
		this.separator = ",";
	if (this.separator == " ")
		this.separator = "\\s";
	return this.separator;
}

// -------------- NEW CLASS HANDLER ------------ //

Typic.getElementsByClass = function(searchClass,node,tag)
{
	var classElements = new Array();
	if ( node == null )
		node = document;
	if ( tag == null )
		tag = '*';
	var els = node.getElementsByTagName(tag);
	var elsLen = els.length;
	var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
	for (i = 0, j = 0; i < elsLen; i++) {
		if ( pattern.test(els[i].className) ) {
			classElements[j] = els[i];
			j++;
		}
	}
	return classElements;
}

Typic.getClasses = function(element)
{
    return (element && element.className) ? element.className.trim().split(/\s+/) : [];
}

Typic.addClass = function(element, c)
{
    var classes = Typic.getClasses(element);
    if (classes.indexOf(c) == -1)
    {
        classes.push(c);
        element.className = classes.join(' ');
    }
}

Typic.removeClass = function(element, c)
{
    var classes = Typic.getClasses(element);
    var idx = classes.indexOf(c);
    if (idx != -1)
    {
        classes.splice(idx, 1);
        element.className = classes.join(' ');
    }
}

Typic.hasClass = function(element, c)
{
    return Typic.getClasses(element).indexOf(c) != -1;
}

Typic.toggleClass = function(elem, className)
{
	if (Typic.hasClass(elem, className))
		Typic.removeClass(elem, className);
	else
		Typic.addClass(elem, className);
}

