/* ===== 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)
	{
		x.style.overflow = "";
		x.style.filter = "";
		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";
		li[i].style.zIndex = 1;
	}
	
	
	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))
	{
		console.log(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)
{
	if (window.dojo)
	{
		return dojo.query(".typic_clue[name='" + 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);
}

Typic.showElem = function(selector, root)
// Showes the nodes by css selector
{
	if (!root) root = window.document;
	dojo.query(selector, root).forEach(function(elem){
		{
			dojo.removeClass(elem, "hidden");
		}
	});
}

Typic.hideElem = function(selector, root)
// Hides the nodes by css selector
{
	if (!root) root = window.document;
	dojo.query(selector, root).forEach(function(elem){
		{
			dojo.addClass(elem, "hidden");
		}
	});
}




	/* ===== CYNIC.JS ===== */

Cynic = new Object();
	
Cynic.maxTime = 25000;
Cynic.script = new Array();
Cynic.par = new Array();
Cynic.call = function(url, callback, updateElements)
// Calls a socket specified by url
// Pass a callback funtion name to return data
// Callback function has to take 2 parameters: xx (the dataobject) and script_id - in case you are using it for something
// Returns the script_id which can be used to track the call
{
	var script_element = document.createElement('script');
	script_element.type = "text/javascript";
	var script_id = this.script.push(script_element) - 1;
	
	if (this.par.callback)
		callback = this.par.callback;
	this.par.callback = null;
	if (!callback)
		callback = "";
	
	this.script[script_id].callback = callback;
	var qs = "cynic[id]=" + script_id;
	if (url.indexOf("?") > 0)
		url = url + "&" + qs;
	else
		url = url + "?" + qs;
	
	if (!updateElements)
		updateElements = "";
	if (this.par.update)
		updateElements += this.par.update;
	if (this.par.append)
		updateElements += this.par.append + ".=" + this.par.append;
	this.par.update = null;
	
	if (updateElements)
	{
		var e = cynic_parse_query_string(updateElements);
		for (var i in e)
		{	
			if (!e[i])
				e[i] = "/var/www/sites/hoytocoyo/hoytocoyo.com/subdomains/www/html/index.php/" + i;
			url = url + "&cynic_update["+i+"]=" + e[i];
		}
	}
	
	if (this.par.execute)
	{
		url = url + "&cynic_execute=" + this.par.execute;
	}
	
	this.script[script_id].src = url;
	
	document.getElementsByTagName('head')[0].appendChild(this.script[script_id]);
	setTimeout("Cynic.timeout(" + script_id + ")", this.maxTime);
	return script_id;
}

Cynic.update_elem = function(elem)
{
	if (jQuery(elem).html().trim() == '')
	{
		jQuery(elem).html(decodeURIComponent('%3Cspan%20class%3D%22loading-message%22%3ELoading%26hellip%3B%3C%2Fspan%3E%0D%0A%09%0D%0A%09%3Cstyle%20type%3D%22text%2Fcss%22%3E%0D%0A%09%09.loading-message%0D%0A%09%09%7B%0D%0A%09%09%09display%3A%20block%3B%0D%0A%09%09%09padding-left%3A%2023px%3B%0D%0A%09%09%09min-height%3A%2019px%3B%20_height%3A%2019px%3B%0D%0A%09%09%09background%3A%20url%28http%3A%2F%2Fwww.hoytocoyo.com%2Fimages%2Ficons%2Ficon_loading2.gif%29%20no-repeat%20left%20center%3B%0D%0A%09%09%7D%0D%0A%09%3C%2Fstyle%3E%0A'));
		Cynic.call(document.location.href, null, jQuery(elem).attr('id'));
	}
}

Cynic.post = function(url, form, callback, updateElements)
// Calls a socket specified by url
// Pass a callback funtion name to return data
// Callback function has to take 2 parameters: xx (the dataobject) and script_id - in case you are using it for something
// Returns the script_id which can be used to track the call
{
	var script_element = document.createElement('script');
	script_element.type = "text/javascript";
	var script_id = this.script.push(script_element) - 1;
	
	if (this.par.callback)
		callback = this.par.callback;
	this.par.callback = null;
	if (!callback)
		callback = "";
	
	this.script[script_id].callback = callback;
	var qs = "cynic[id]=" + script_id;
	if (url.indexOf("?") > 0)
		url = url + "&" + qs;
	else
		url = url + "?" + qs;
	
	if (!updateElements)
		updateElements = "";
	if (this.par.update)
		updateElements += this.par.update;
	this.par.update = null;
	
	if (updateElements)
	{
		var e = cynic_parse_query_string(updateElements);
		for (var i in e)
		{	
			if (!e[i])
				e[i] = "/var/www/sites/hoytocoyo/hoytocoyo.com/subdomains/www/html/index.php/" + i;
			url = url + "&cynic_update["+i+"]=" + e[i];
		}
	}
	
	dojo.xhrPost({
		url: url,
		form: form,
		load: Cynic.post_exec
	});

	setTimeout("Cynic.timeout(" + script_id + ")", this.maxTime);
	return script_id;
}

Cynic.post_exec = function(data, ioArgs)
{
	eval(data);
}

Cynic.callback = function(xx, script_id)
{
	if (this.script[script_id])
	{	
		//document.getElementsByTagName('head')[0].removeChild(this.script[script_id]);
		if (xx && xx.html)
		{
			for (i in xx.html)
			{
				if (i.substr(i.length-1, 1) == ".")
				{	
					j = i.substring(0, i.length-1);
					if ($(j))
						$(j).innerHTML += xx.html[i];
					else
						console.error("No element with id = '" + j + "' found for cynic-update");
				}
				else
				{
					if ($(i))
						$(i).innerHTML = xx.html[i];
					else
						console.error("No element with id = '" + i + "' found for cynic-update");
				}

				if (window.dojo && dojo.publish)
				{
					dojo.publish("update:" + i);
					dojo.publish("update:page_frontend");
				}
			}
		}

		var callback = this.script[script_id].callback;
		if (callback)
		{
			if (typeof(callback) == "string")
				eval(this.script[script_id].callback + "(xx, script_id)");
			else if (typeof(callback) == "function")
				callback(xx, script_id);
		}
		this.script[script_id] = null;
	}
}

Cynic.timeout = function(script_id)
{
	this.callback(false, script_id);
}

Cynic.parse_query_string = function(qs)
{
	if (!qs)
		qs = decodeURIComponent(document.location.hash.substr(1) + "&" + document.location.search.substr(1));
	var par = qs.split("&");
	var x = Array();
	var set;
	for (var i = 0; i < par.length; i++)
	{
		set = par[i].split("=");
		if (!set[1])
			set[1] = "";
		if (set[0].indexOf("[]") > -1)
		{
			set[0] = set[0].split("[]");
			set[0] = set[0][0];
			if (!x[set[0]])
			{
				eval("x['" + set[0] + "'] = Array();");
			}
			var j = x[set[0]].length + 1;
			eval("x['" + set[0] + "'].push(unescape('" + escape(set[1]) + "'))");
			//eval("x['" + set[0] + "'][" + j + "] = unescape('" + escape(set[1]) + "');");
		}
		else
		{
			eval("x['" + set[0] + "'] = unescape('" + escape(set[1]) + "');");
		}
	}
	
	return x;
}

Cynic.parse_query_string_simple = function(qs)
{
	if (!qs)
		qs = decodeURIComponent(document.location.hash.substr(1) + "&" + document.location.search.substr(1));
	var par = qs.split("&");
	var x = Object();
	var set;
	for (var i = 0; i < par.length; i++)
	{
		set = par[i].split("=");
		if (!set[1])
			set[1] = "";

		eval("x." + set[0] + " = unescape('" + escape(set[1]) + "');");
	}
	
	return x;
}

Cynic.compose_query_string = function(x)
// Composes a one-dimensional query string of the (non-function) properties of object x
// ex: a=1&b=2&c=3
// Encodes values so that they are safe to send as a query string part of a url
{
	var qs = new Array();
	for (var key in x)
	{
		if ((key) && (typeof(x[key]) != "function"))
		{
			qs.push(key + "=" + encodeURIComponent(x[key]));
		}
	}
	
	return qs.join("&");
}

Cynic.get_form_values = function(form)
{
	var x = new Array();
	for (var i = 0; i < form.elements.length; i++)
	{
		if (form.elements[i].type == "select-multiple")
		{
			for (var j = 0; j < form.elements[i].options.length; j++)
			{
				if (form.elements[i].options[j].selected)
				x.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].options[j].value));
			}
		}
		else if ((form.elements[i].type != "checkbox" && form.elements[i].type != "radio") || form.elements[i].checked)
			x.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
	}
	return x;
}
	
Cynic.form_to_query_string = function(form)
// Composes a query string of the form elements and their values
{
	var x = Cynic.get_form_values(form);
	return x.join("&");
}

Cynic.form_to_url = function(form)
{
	var join = form.action.match(/\?/) ? "&" : "?";
	return form.action + join + Cynic.form_to_query_string(form);
}

Cynic.form_submit = function(form)
{
	//var url = Cynic.form_to_url(form);
	var join = form.action.match(/\?/) ? "&" : "?";
	var url = form.action + join;
	dojo.query("form.cynic_persistent_form").forEach(function(form)
	{
		var x = Cynic.get_form_values(form);
		for (var i = 0; i < x.length; i++)
		{
			if (x[i].match(/^postback=/i))
				x[i] = "";
		}
		url = url + "&" + x.join("&");
	});
	
	Cynic.post(url, form);
}

Cynic.bookmark_query_string = function(qs)
{
	location.href = location.pathname + location.search + "#" + qs;
}

Cynic.hyperlink_activate = function(elem, callback, update)
{
	Cynic.call(elem.href, callback, update);
}

/* --------------------- */


function cynic_call(url, callback)
// Deprecated
{
	return Cynic.call(url, callback);
} 



function cynic_parse_query_string(qs)
{
	return Cynic.parse_query_string(qs);
}

function cynic_compose_query_string(x)
{
	return Cynic.compose_query_string(x);
}

function cynic_compose_query_string_simple(x, key)
// Composes a querystring of the form "a=2&a=4&a=5"
{
	for (var i = 0; i < x.length; i++)
	{
		x[i] = key + "=" + encodeURIComponent(x[i]);
	}
	return x.join("&");
}

function cynic_bookmark_query_string(qs)
{
	Cynic.bookmark_query_string(qs);
}

var _cynic_watch_qs_interval_id;
function cynic_watch_query_string(callback)
// Call this function in the beginning of your script (on a page that uses ajax)
// to initiate a timer/interval that checks wheter the query string has changed
// If it has changed it will check if it is still changing (i.e. if you are typing in a keyword...)
// and then call the callback function once a new value seems permanent.
{
	// TODO: Rewrite this to use Timeout instead of Interval
	cynic_watch_query_string_reset();
	if (!_cynic_watch_qs_interval_id)
		_cynic_watch_qs_interval_id = setInterval("_cynic_watch_qs('"+callback+"')", 500);
}

var _cynic_qs = new Array();
_cynic_qs.current = "";
_cynic_qs.old = "";
function _cynic_watch_qs(callback)
{
	var changed = (_cynic_qs.old != _cynic_qs.current);
	_cynic_qs.old = _cynic_qs.current;
	_cynic_qs.current = document.location.hash.substr(1);
	if ((changed) && (_cynic_qs.current == _cynic_qs.old))
		eval(callback + "()");
}

function cynic_watch_query_string_reset()
{
	_cynic_qs.current = document.location.hash.substr(1);
	_cynic_qs.old = _cynic_qs.current;
}

function cynic_submit(form, callback, updateElements)
{
	var x = new Array();
	for (var i = 0; i < form.elements.length; i++)
	{
		x.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
	}
	x = x.join("&");
	Cynic.call(form.action + "?" + x, callback, updateElements);
}

function clear_error_messages(name, form)
{
	for (var i = 0; i < form.elements.length; i++)
	{
		var match = new RegExp(name + "\\[(.*?)\\]", "i");
		var e = document.getElementById("error_" + name + "_" + form.elements[i].name.replace(match, "$1"));
		if (e)
			typic_flush_list(e);
	}
}	
	
function display_error_messages(name, errors)
{
	for (var i in errors)
	{	
		if (typeof(errors[i]) == "string")
		{
			var elem_id = "error_" + name + "_" + i;
			if ($(elem_id))
			{
				var message = text[elem_id + "_" + errors[i]];
				if (!message)
					message = errors[i];
				typic_clone_item("error", elem_id, "id="+i+"&message="+message);
			}
		}
	}
}

	function phantom_change_language(language)
{
	Cynic.call("socket.phantom.php?language=" + language, "phantom_change_language_callback");
}

function phantom_change_language_callback(language)
{
	location.reload();
}

	/* vessel.js */

document.onkeydown = function(event)
{
	var keynum;
	
	if (window.event && window.event.keyCode) // IE
		keynum = window.event.keyCode;
	else if (event.which)
		keynum = event.which;
	else
		return;
		
	this.setKeyPressed(keynum);
}

document.onkeyup = function(event)
{
	var keynum;
	
	if (window.event && window.event.keyCode) // IE
		keynum = window.event.keyCode;
	else if (event.which)
		keynum = event.which;
	else
		return;
		
	this.clearKeyPressed(keynum);
}

document.setKeyPressed = function(keynum)
{
	if (!this.keyPressed)
		this.keyPressed = new Array();
	this.keyPressed[keynum] = true;
	
	dojo.query("body").addClass("keydown_" + keynum);
}

document.clearKeyPressed = function(keynum)
{
	if (!this.keyPressed)
		this.keyPressed = new Array();
	this.keyPressed[keynum] = false;
	
	dojo.query("body").removeClass("keydown_" + keynum);
}

document.isKeyPressed = function(keynum)
{
	if (this.keyPressed && this.keyPressed[keynum])
		return true;
	else
		return false;
}

document.getKeysPressed = function()
{
	if (!this.keyPressed)
		this.keyPressed = new Array();
	
	return this.keyPressed;
}

document.onblur = function()
{
	var keysPressed = this.getKeysPressed()
	for (key in keysPressed)
	{
		this.clearKeyPressed(key);
	}
}

strrot13 = function(str)
{
	var rot13 = "";
	var x, y;
	for (var i = 0; i < str.length; i++)
	{
		x = str.substr(i, 1);
		if (x.match(/[a-m]/i))
		{
			y = String.fromCharCode(x.charCodeAt(0) + 13);
		}
		else if (x.match(/[n-z]/i))
		{
			y = String.fromCharCode(x.charCodeAt(0) - 13);
		}
		else
		{
			y = x;
		}
		rot13 = rot13 + y;
	}
	return rot13;
}

function switch_tab(elem)
// Switches to tab, identified by href attr of anchor element
// Selected tab gets display: block, other in same container gets display: none
{
	var id = jQuery(elem).attr('href');
	var tab_panes = jQuery(id).parent();
	jQuery('.tab_pane', tab_panes).css({display: 'none'});
	jQuery(id).css({display: 'block', position: 'absolute', left: 0, top: 0});
	jQuery(elem).closest('ul').children('li').removeClass("active");
	jQuery(elem).closest('li').addClass("active");
}

input_field_helper = function(elem)
{
	jQuery(elem).attr('value', jQuery(elem).attr('title')).addClass('dimmed');	

	jQuery(elem).focus(function(){		
		if (jQuery(this).attr('value') == jQuery(this).attr('title'))
		{
			jQuery(this).attr('value', '').removeClass('dimmed');
		}		
	});
	
	jQuery(elem).blur(function(){
		if (jQuery(this).attr('value') == '')
		{
			jQuery(elem).attr('value', jQuery(elem).attr('title')).addClass('dimmed');
		}
	});
}


ExpandCollapseBox = function(elem)
{
	var Obj = this;
	this.container_elem = elem;
	this.expand_elem = jQuery(".expand", this.elem)[0];
	this.collapse_elem = jQuery(".collapse", this.elem)[0];
	this.expand_collapse_area = jQuery(".expand-collapse-area", this.elem)[0];
	
	jQuery(this.expand_elem).click(function(event){
		event.preventDefault();
		jQuery(Obj.expand_collapse_area).slideToggle('fast', function(){
			jQuery(Obj.container_elem).toggleClass('expanded');
		});
		
	});
}

	
	/**
*
*  Secure Hash Algorithm (SHA1)
*  http://www.webtoolkit.info/
*
**/

function SHA1 (msg) {

    function rotate_left(n,s) {
        var t4 = ( n<<s ) | (n>>>(32-s));
        return t4;
    };

    function lsb_hex(val) {
        var str="";
        var i;
        var vh;
        var vl;

        for( i=0; i<=6; i+=2 ) {
            vh = (val>>>(i*4+4))&0x0f;
            vl = (val>>>(i*4))&0x0f;
            str += vh.toString(16) + vl.toString(16);
        }
        return str;
    };

    function cvt_hex(val) {
        var str="";
        var i;
        var v;

        for( i=7; i>=0; i-- ) {
            v = (val>>>(i*4))&0x0f;
            str += v.toString(16);
        }
        return str;
    };


    function Utf8Encode(string) {
        string = string.replace(/\r\n/g,"\n");
        var utftext = "";

        for (var n = 0; n < string.length; n++) {

            var c = string.charCodeAt(n);

            if (c < 128) {
                utftext += String.fromCharCode(c);
            }
            else if((c > 127) && (c < 2048)) {
                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);
            }
            else {
                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);
            }

        }

        return utftext;
    };

    var blockstart;
    var i, j;
    var W = new Array(80);
    var H0 = 0x67452301;
    var H1 = 0xEFCDAB89;
    var H2 = 0x98BADCFE;
    var H3 = 0x10325476;
    var H4 = 0xC3D2E1F0;
    var A, B, C, D, E;
    var temp;

    msg = Utf8Encode(msg);

    var msg_len = msg.length;

    var word_array = new Array();
    for( i=0; i<msg_len-3; i+=4 ) {
        j = msg.charCodeAt(i)<<24 | msg.charCodeAt(i+1)<<16 |
        msg.charCodeAt(i+2)<<8 | msg.charCodeAt(i+3);
        word_array.push( j );
    }

    switch( msg_len % 4 ) {
        case 0:
            i = 0x080000000;
        break;
        case 1:
            i = msg.charCodeAt(msg_len-1)<<24 | 0x0800000;
        break;

        case 2:
            i = msg.charCodeAt(msg_len-2)<<24 | msg.charCodeAt(msg_len-1)<<16 | 0x08000;
        break;

        case 3:
            i = msg.charCodeAt(msg_len-3)<<24 | msg.charCodeAt(msg_len-2)<<16 | msg.charCodeAt(msg_len-1)<<8    | 0x80;
        break;
    }

    word_array.push( i );

    while( (word_array.length % 16) != 14 ) word_array.push( 0 );

    word_array.push( msg_len>>>29 );
    word_array.push( (msg_len<<3)&0x0ffffffff );


    for ( blockstart=0; blockstart<word_array.length; blockstart+=16 ) {

        for( i=0; i<16; i++ ) W[i] = word_array[blockstart+i];
        for( i=16; i<=79; i++ ) W[i] = rotate_left(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1);

        A = H0;
        B = H1;
        C = H2;
        D = H3;
        E = H4;

        for( i= 0; i<=19; i++ ) {
            temp = (rotate_left(A,5) + ((B&C) | (~B&D)) + E + W[i] + 0x5A827999) & 0x0ffffffff;
            E = D;
            D = C;
            C = rotate_left(B,30);
            B = A;
            A = temp;
        }

        for( i=20; i<=39; i++ ) {
            temp = (rotate_left(A,5) + (B ^ C ^ D) + E + W[i] + 0x6ED9EBA1) & 0x0ffffffff;
            E = D;
            D = C;
            C = rotate_left(B,30);
            B = A;
            A = temp;
        }

        for( i=40; i<=59; i++ ) {
            temp = (rotate_left(A,5) + ((B&C) | (B&D) | (C&D)) + E + W[i] + 0x8F1BBCDC) & 0x0ffffffff;
            E = D;
            D = C;
            C = rotate_left(B,30);
            B = A;
            A = temp;
        }

        for( i=60; i<=79; i++ ) {
            temp = (rotate_left(A,5) + (B ^ C ^ D) + E + W[i] + 0xCA62C1D6) & 0x0ffffffff;
            E = D;
            D = C;
            C = rotate_left(B,30);
            B = A;
            A = temp;
        }

        H0 = (H0 + A) & 0x0ffffffff;
        H1 = (H1 + B) & 0x0ffffffff;
        H2 = (H2 + C) & 0x0ffffffff;
        H3 = (H3 + D) & 0x0ffffffff;
        H4 = (H4 + E) & 0x0ffffffff;

    }

    var temp = cvt_hex(H0) + cvt_hex(H1) + cvt_hex(H2) + cvt_hex(H3) + cvt_hex(H4);

    return temp.toLowerCase();

}

	function header2image(node, url)
// Pass element node and image url
{
	if (!node)
		return;
	var image = document.createElement('img');
	
	if (node.firstChild && node.firstChild.nodeValue)
	{
		image.alt = node.firstChild.nodeValue;
	}

	image.title_node = node;
	image.onload = function()
	{
		if (this.title_node.firstChild)
			this.title_node.replaceChild(this, this.title_node.firstChild);
		else
			this.title_node.appendChild(this);
	}
	
	image.src = url;
}

	
	window.onload = function()
	{
		/* ===== component.alertbox.js ===== */

dojo.require("dijit.Dialog");

Alertbox = new dijit.Dialog({duration: 100});

Alertbox.wait = function(message)
{
	this.hide();
	if (!message) message = "wait";
	var content = unescape("%3Cdiv%20id%3D%22alertbox%22%20class%3D%22%7Bclass%7D%22%3E%0D%0A%09%09%3Cp%3E%7Bmessage%7D%3C%2Fp%3E%0D%0A%09%3C%2Fdiv%3E%0A");
	content = content.replace(/\{message\}/, message);
	content = content.replace(/\{class\}/, "wait");
	this.setContent(content);
	this.show();
}

Alertbox.ok = function(message)
{
	this.hide();
	if (!message) message = "ok";
	var content = unescape("%3Cdiv%20id%3D%22alertbox%22%20class%3D%22%7Bclass%7D%22%3E%0D%0A%09%09%3Cp%3E%7Bmessage%7D%3C%2Fp%3E%0D%0A%09%3C%2Fdiv%3E%0A");
	content = content.replace(/\{message\}/, message);
	content = content.replace(/\{class\}/, "ok");
	this.setContent(content);
	this.show();
	setTimeout("Alertbox.hide()", 1400);
}

Alertbox.error = function(message)
{
	this.hide();
	if (!message) message = "error";
	var content = unescape("%3Cdiv%20id%3D%22alertbox%22%20class%3D%22%7Bclass%7D%22%3E%0D%0A%09%09%3Cp%3E%7Bmessage%7D%3C%2Fp%3E%0D%0A%09%3C%2Fdiv%3E%0A");
	content = content.replace(/\{message\}/, message);
	content = content.replace(/\{class\}/, "error");
	this.setContent(content);
	this.show();
	setTimeout("Alertbox.hide()", 1400);
}

Alertbox.confirm = function(message, callback)
{
	this.hide();
	if (!message) message = "confirm";
	var content = unescape("%3Cdiv%20id%3D%22alertbox%22%20class%3D%22%7Bclass%7D%22%3E%0D%0A%09%09%3Cp%3E%7Bmessage%7D%3C%2Fp%3E%0D%0A%09%09%3Cdiv%20class%3D%22buttons%22%3E%0D%0A%09%09%09%3Cbutton%20class%3D%22yes%22%20onclick%3D%22%7Bcallback%7D%28true%29%22%3E%0D%0A%09%09%09%09Yes%0D%0A%09%09%09%3C%2Fbutton%3E%0D%0A%09%09%09%3Cbutton%20class%3D%22no%22%20onclick%3D%22%7Bcallback%7D%28false%29%22%3E%0D%0A%09%09%09%09No%0D%0A%09%09%09%3C%2Fbutton%3E%0D%0A%09%09%3C%2Fdiv%3E%0D%0A%09%3C%2Fdiv%3E%0A");
	content = content.replace(/\{message\}/, message);
	content = content.replace(/\{class\}/, "confirm");
	content = content.replace(/\{callback\}/g, callback);
	this.setContent(content);
	this.show();
}

Alertbox.window = function(url)
{
	var content = unescape("%3Cdiv%20id%3D%22alertbox%22%20class%3D%22window%22%3E%0D%0A%09%09%3Ciframe%20src%3D%22%7Burl%7D%22%20allowtransparency%3D%22true%22%3E%3C%2Fiframe%3E%0D%0A%09%3C%2Fdiv%3E%0A");
	content = content.replace(/\{url\}/, url);
	this.setContent(content);
	this.resize(800,600);
	this.show();
}

Alertbox.popup = function(url, callback)
{
	var content = unescape("%3Cdiv%20class%3D%22popup-header%22%3E%0D%0A%09%09%3Cspan%20class%3D%22close%22%3EClose%3C%2Fspan%3E%0D%0A%09%3C%2Fdiv%3E%0D%0A%09%3Cdiv%20id%3D%22alertbox%22%20class%3D%22popup%22%3E%0D%0A%0D%0A%09%3C%2Fdiv%3E%0A");
	this.setContent(content);
	this.resize(800,600);
	this.show();
	this.onUnload = callback;
	
	Cynic.par.update = "alertbox=popup_content";
	Cynic.par.execute = "javascript";
	Cynic.call(url);
}

dojo.subscribe("update:page_frontend", null, onupdate_page_frontend);
		dojo.publish("update:page_frontend");

		window.jQuery && jQuery("#share-this").cycle({fx: 'scrollUp', timeout: 5000, pause: true});
objectSwap();
if (window._gat)
	{
		pageTracker = _gat._getTracker("UA-1360421-2");
		pageTracker._setAllowHash(false);
		pageTracker._setAllowLinker(true);
		pageTracker._initData();
		pageTracker._trackPageview();
	}

myJsslideshow.autoStart();

		
		if (!window.prevent_update)
		{
			Cynic.par.update = null;
			Cynic.par.callback = null;
			Cynic.call("http://www.hoytocoyo.com/en/barcelona/cron/update.php");
		}
		
		document.cookie = 'js_active=1;';
	}
	
	dojo.addOnLoad(function()
	{
		
	});

	onupdate_page_frontend = function()
	{
		
		latestNewsSlideshow = new Jsslideshow("latestNewsSlideshow");
	latestNewsSlideshow.stackSlides();
	latestNewsSlideshow.fadeInDelay = 400;
	latestNewsSlideshow.autoStart();
myPlayer = new Player("myFlashMovie", "myPlayer");

	dojo.addOnUnload(function()
	{
		Listener.page_changing();
	});
// Assigning javascript behaviors to elements

	dojo.query("html").forEach(
		function(elem, i)
		{
			if (!elem.behaviors_assigned)
			{
				dojo.addClass(elem, 'js-active');

				elem.behaviors_assigned = true;
			}
		}
	);
dojo.query("#site-navigation li.level1").forEach(
		function(elem, i)
		{
			if (!elem.behaviors_assigned)
			{
				dojo.connect(elem, 'onmouseover', function(event){dojo.addClass(elem, 'hover')});
dojo.connect(elem, 'onmouseout', function(event){dojo.removeClass(elem, 'hover')});

				elem.behaviors_assigned = true;
			}
		}
	);
dojo.query("#share-this a.facebook").forEach(
		function(elem, i)
		{
			if (!elem.behaviors_assigned)
			{
				dojo.connect(elem, 'onclick', function(event){trackEvent('Share', 'Click', 'Facebook')});

				elem.behaviors_assigned = true;
			}
		}
	);
dojo.query("#share-this a.myspace").forEach(
		function(elem, i)
		{
			if (!elem.behaviors_assigned)
			{
				dojo.connect(elem, 'onclick', function(event){trackEvent('Share', 'Click', 'MySpace')});

				elem.behaviors_assigned = true;
			}
		}
	);
dojo.query(".star-this a").forEach(
		function(elem, i)
		{
			if (!elem.behaviors_assigned)
			{
				dojo.connect(elem, 'onclick', function(event){jQuery(elem).parent('.star-this').toggleClass('starred')});
dojo.connect(elem, 'onclick', function(event){Cynic.call(elem.href)});
dojo.connect(elem, 'onclick', function(event){dojo.stopEvent(event)});

				elem.behaviors_assigned = true;
			}
		}
	);
dojo.query("#related").forEach(
		function(elem, i)
		{
			if (!elem.behaviors_assigned)
			{
				Cynic.update_elem(elem);

				elem.behaviors_assigned = true;
			}
		}
	);
dojo.query("#tracks li a.play").forEach(
		function(elem, i)
		{
			if (!elem.behaviors_assigned)
			{
				index_to_track_id(elem, i);
dojo.connect(elem, 'onclick', function(event){myPlayer.play(i)});
dojo.connect(elem, 'onclick', function(event){dojo.stopEvent(event)});

				elem.behaviors_assigned = true;
			}
		}
	);
dojo.query("form.login").forEach(
		function(elem, i)
		{
			if (!elem.behaviors_assigned)
			{
				dojo.connect(elem, 'onsubmit', function(event){login_submit(elem)});
dojo.connect(elem, 'onsubmit', function(event){dojo.stopEvent(event)});

				elem.behaviors_assigned = true;
			}
		}
	);
dojo.query("form.login button.submit").forEach(
		function(elem, i)
		{
			if (!elem.behaviors_assigned)
			{
				dojo.addClass(elem, 'hidden');

				elem.behaviors_assigned = true;
			}
		}
	);
dojo.query("form.login .password input").forEach(
		function(elem, i)
		{
			if (!elem.behaviors_assigned)
			{
				dojo.connect(elem, 'onkeyup', function(event){on_password_type(elem)});

				elem.behaviors_assigned = true;
			}
		}
	);
dojo.query("a.obeman").forEach(
		function(elem, i)
		{
			if (!elem.behaviors_assigned)
			{
				unobem(elem);

				elem.behaviors_assigned = true;
			}
		}
	);
dojo.query(".popup-header .close").forEach(
		function(elem, i)
		{
			if (!elem.behaviors_assigned)
			{
				dojo.connect(elem, 'onclick', function(event){Alertbox.hide()});

				elem.behaviors_assigned = true;
			}
		}
	);


	}

	/* ===== COMPONENT.USER.JS ===== */

function on_password_type(elem)
// replaces register link with submitbutton
{
	dojo.query("button.submit", elem.parentNode.parentNode).removeClass("hidden");
	dojo.query("a.register", elem.parentNode.parentNode.parentNode).addClass("hidden");
	dojo.query(".remember", elem.parentNode.parentNode.parentNode).removeClass("hidden");
}

/* login */

function login_submit(form)
{
	form.elements["login[pw_digest]"].value = SHA1(form.elements["_salt"].value + form.elements["login[password]"].value);
	form.elements["login[password]"].value = "";
	form.elements["_salt"].value = "";
	Alertbox.wait(unescape("Logging%20in%2C%20please%20wait..."));
	
	Cynic.par.callback = login_callback;
	Cynic.par.update = "page_frontend";
	Cynic.form_submit(form);
}

function login_callback(xx, id)
{
	if (xx)
	{
		if (dojo.query("p.error.login").length > 0)
		{
			Alertbox.error(unescape("Wrong%20username%20or%20password.%26nbsp%3B"));
		}
		else
		{
			Alertbox.hide();
		}
	}
	else
	{
		Alertbox.error(unescape("Server%20not%20responding...%26nbsp%3B"));
	}
}

function trackEvent(a, b, c, d)
	{
		if (window.pageTracker)
		{
			if (!d) d = 0;
			var success = pageTracker._trackEvent(a, b, c, parseInt(d));
		}
	}
Cufon.replace('h2');
function text_edit(event, id, lan_code)
{
	if (document.isKeyPressed(17))
	{
		Alertbox.window("http://www.hoytocoyo.com/en/barcelona/components/text/edit.php?id=" + id + "&lan_code=" + lan_code);
		dojo.stopEvent(event);
	}
}


	
/* ObjectSwap - Bypasses the new ActiveX Activation requirement in Internet Explorer by swapping existing ActiveX objects on the page with the same objects. Can also be used for Flash version detection by adding the param:
<param name="flashVersion" value="8" /> to the object tag.

MODIFIED by Anton on 2009-10-14:
	Fixed broken IE-detection code

MODIFIED by Jakob on 2008-04-07:
	Removed the attempt to attach automatically to onload event ()

ORIGINAL META:
Author: Karina Steffens, www.neo-archaic.net
Created: April 2006
Changes and bug fixes: May 2006
Bug fixes: June 2006
*/

//Check if the browser is InternetExplorer
var ie = /*@cc_on !@*/false;

//Hide the object to prevent it from loading twice
if (ie){
	document.write ("<style id='hideObject'> object{display:none;} </style>");
}

/*Replace all flash objects on the page with the same flash object, 
by rewriting the outerHTML values
This bypasses the new IE ActiveX object activation issue*/
objectSwap = function(){
	if (!document.getElementsByTagName){
		return;
	}
	
	//An array of ids for flash detection
	var stripQueue = [];
	//Get a list of all ActiveX objects
	var objects = document.getElementsByTagName('object');
	for (var i=0; i<objects.length; i++){			
		var o = objects[i];	
		var h = o.outerHTML;
		//The outer html omits the param tags, so we must retrieve and insert these separately
		var params = "";
		var hasFlash = true;
		for (var j = 0; j<o.childNodes.length; j++) {
			var p = o.childNodes[j];
			if (p.tagName == "PARAM"){
				//Check for version first - applies to all browsers
				//For this to work, a new param needs to be included in the object with the name "flashVersion" eg:
				//<param name="flashVersion" value="7" />
				if (p.name == "flashVersion"){
					hasFlash = detectFlash(p.value);
					if (!hasFlash){
						//Add the objects id to the list (create a new id if there's isn't one already)
						o.id = (o.id == "") ? ("stripFlash"+i) : o.id;
						stripQueue.push(o.id);
						break;
					}
				} 
				params += p.outerHTML;		       
			}
		}	
		if (!hasFlash){
			continue;
		}		
		//Only target internet explorer
		if (!ie){
			continue;
		} 
		//Avoid specified objects, marked with a "noswap" classname
		if (o.className.toLowerCase().indexOf ("noswap") != -1){
			continue;
		}		
		//Get the tag and attributes part of the outer html of the object
		var tag = h.split(">")[0] + ">";			
		//Add up the various bits that comprise the object:
		//The tag with the attributes, the params and it's inner html
		var newObject = tag + params + o.innerHTML + " </OBJECT>";		
		//And rewrite the outer html of the tag 
		o.outerHTML = newObject;
	}
	//Strip flash objects
	if (stripQueue.length) {
		stripFlash(stripQueue)
	}
	//Make the objects visible again
	if (ie){
		document.getElementById("hideObject").disabled = true;
	}
}

detectFlash = function(version){
	if(navigator.plugins && navigator.plugins.length){
		//Non-IE flash detection.
		var plugin = navigator.plugins["Shockwave Flash"];
		if (plugin == undefined){
			return false;
		}
		var ver = navigator.plugins["Shockwave Flash"].description.split(" ")[2];
		return (Number(ver) >= Number(version))
	} else if (ie && typeof (ActiveXObject) == "function"){
	//IE flash detection.
		try{
			var flash = new ActiveXObject("ShockwaveFlash.ShockwaveFlash." + version);
			return true;
		}
		catch(e){
			return false;
		}
	}
	//Catchall - skip detection
	return true;
}

//Loop through an array of ids to strip
//Replace the object by a div tag containing the same innerHTML.
//To display an alternative image, message for the user or a link to the flash installation page, place it inside the object tag.  
//For the usual object/embed pairs it needs to be enclosed in comments to hide from gecko based browsers.
stripFlash = function (stripQueue){
	if (!document.createElement){
		return;
	}
	for (var i=0; i<stripQueue.length; i++){
		var o = document.getElementById(stripQueue[i]);
		var newHTML = o.innerHTML;	
		//Strip the comments
		newHTML = newHTML.replace(/<!--\s/g, "");
		newHTML = newHTML.replace(/\s-->/g, "");
		//Neutralise the embed tag
		newHTML = newHTML.replace(/<embed/gi, "<span");		
		//Create a new div element with properties from the object
		var d = document.createElement("div");
		d.innerHTML = newHTML;
		d.className = o.className;
		d.id = o.id;
		//And swap the object with the new div
		o.parentNode.replaceChild(d, o);
	}
}

/* REMOVED in MOD 1.1
//Initiate the function without conflicting with the window.onload event of any preceding scripts
var tempFunc = window.onload;
window.onload = function(){
	if (typeof (tempFunc) == "function"){
		try{
			tempFunc();
		} catch(e){}
	}
	objectSwap();
}*/

	function getFlashMovieObject(movieName)
{
  if (window.document[movieName]) 
  {
    return window.document[movieName];
  }
  if (navigator.appName.indexOf("Microsoft Internet")==-1)
  {
    if (document.embeds && document.embeds[movieName])
      return document.embeds[movieName]; 
  }
  else // if (navigator.appName.indexOf("Microsoft Internet")!=-1)
  {
    return document.getElementById(movieName);
  }
}

function StopFlashMovie()
{
	var flashMovie=getFlashMovieObject("myFlashMovie");
	flashMovie.StopPlay();
}

function PlayFlashMovie()
{
	var flashMovie=getFlashMovieObject("myFlashMovie");
	flashMovie.Play();
	//embed.nativeProperty.anotherNativeMethod();
}

function RewindFlashMovie()
{
	var flashMovie=getFlashMovieObject("myFlashMovie");
	flashMovie.Rewind();
}

function NextFrameFlashMovie()
{
	var flashMovie=getFlashMovieObject("myFlashMovie");
	// 4 is the index of the property for _currentFrame
	var currentFrame=flashMovie.TGetProperty("/", 4);
	var nextFrame=parseInt(currentFrame);
	if (nextFrame>=10)
		nextFrame=0;
	flashMovie.GotoFrame(nextFrame);		
}


function ZoominFlashMovie()
{
	var flashMovie=getFlashMovieObject("myFlashMovie");
	flashMovie.Zoom(90);
}

function ZoomoutFlashMovie()
{
	var flashMovie=getFlashMovieObject("myFlashMovie");
	flashMovie.Zoom(110);
}


function SendDataToFlashMovie()
{
	var flashMovie=getFlashMovieObject("myFlashMovie");
	flashMovie.SetVariable("/:message", document.controller.Data.value);
}

function ReceiveDataFromFlashMovie()
{
	var flashMovie=getFlashMovieObject("myFlashMovie");
	var message=flashMovie.GetVariable("/:message");
	document.controller.Data.value=message;
}

/* ===== COMPONENT.TRACKS.JS ===== */

/* USAGE:
var myPlayer = new Player("myFlashMovie");
myPlayer.play();
*/

Player = function(id, varname)
// The player object
{
	this.varname = varname; // varname is the name of the variable with wich we access it
	this.flash_elem_id = id; // The id attribute of the <object> element
	
	this.track_index = 0; // First track
	this.track_pos = 0; // Start of track. Position is in milli-seconds, or what?
	this.pause_pos = 0; // If positive, we're in pause mode
	this.vol = 100; // Initial volume
	this.version = null; // Will be set to the reported version of the swf
	this.playing = false;
	
	this.tracks = [];
	this._schedule_watch(1000);
}

Player.prototype.play = function(track)
// Starts playback of track no
{
	if (track == undefined)
		track = this.track_index;
	else
		this.track_index = track;
		
	this.swfSet("play_track", track);
}

Player.prototype.stop = function()
// Stops playback
{
	this.swfSet("play_track", false);
}

Player.prototype.seek_pos = function(pos)
// Moves a playing track to the specified position
{
	if (!pos)
		pos = this.track_pos;
	else
		this.track_pos = pos;
		
	this.swfSet("move_to_position", pos);
}

Player.prototype.swfSet = function(name, value)
{
	var swf = getFlashMovieObject(this.flash_elem_id);
	swf.SetVariable(name, value);
}

Player.prototype.swfGet = function(name)
{
	try 
	{
		var swf = getFlashMovieObject(this.flash_elem_id);
		return swf.GetVariable(name);
	}
	catch (e)
	{
		return;
	}
}

Player.prototype._schedule_watch = function(interval)
// Sets the timeout for the next execution of _watch_player
{
	if (interval)
		this._watch_interval = interval;
	else
		interval = this._watch_interval;
		
	this._watch_id = setTimeout(this.varname + "._watch_player()", interval);
}

Player.prototype._watch_player = function()
// Gets information from the swf and stores it
{
	this.track_index = this.swfGet("track_index");
	this.track_pos = this.swfGet("track_position");
	this.pause_pos = this.swfGet("pause_position");
	this.playing = (this.track_pos > 0 && this.track_pos != this.pause_pos);
	this.version = this.swfGet("modVer");
	this.vol = this.swfGet("volume_level");

	Listener.report(this.playing, this.track_index, this.track_pos / 1000, this._watch_interval / 1000);
	
	/*if (this.playing)
		console.log("Now playing: " + this.track_index + ", pos. " + this.track_pos);
	else
		console.log("Paused...");*/
		
	this._schedule_watch();
}

/* --- LISTENER STATS OBJECT --- */

Listener = function(){}

Listener.track_id_table = [];
Listener.track_id = 0;
Listener.playing_time = 0; // in seconds

Listener.assign_track_id = function(i, track_id)
// Maps playlist indexes to track ids
{
	this.track_id_table[i] = track_id;
}

Listener.report = function(playing, track_index, track_pos, interval)
// Receives report of current state from _watch_player
// track_pos in seconds here!
// Interval is the time between reports
{
	if (playing)
	{
		var track_id = this.track_id_table[track_index];
		if (track_id != this.track_id)
		{
			Listener.track_changed(track_id);
		}
		this.playing_time = this.playing_time + interval;
	}
	else if (track_pos == 0)
	{
		Listener.track_stopped();
	}
}

Listener.track_changed = function(track_id)
// Sends listener stats for the played track
{
	if (this.track_id > 0)
	{
		//console.log("Played track " + this.track_id + " for " + this.playing_time + " seconds.");
		if (this.playing_time > 10)
		{
			var par1 = strrot13(":track_idX" + this.track_id + ":");
			var par2 = strrot13(":playing_timeX" + this.playing_time + ":");
			Cynic.call("http://www.hoytocoyo.com/en/barcelona/tracks/listener.php?" + par1 + "&" + par2);
		}
	}
	if (track_id > 0)
	{
		//console.log("Now starting track " + track_id);
	}
	this.track_id = track_id;
	this.playing_time = 0;
}

Listener.track_stopped = function()
{
	this.track_changed(0);
}

Listener.page_changing = function()
{
	this.track_changed(0);
	//Cynic.call("http://www.hoytocoyo.com/en/barcelona/tracks/listener.php?cmd=store_position&track_id=" + this.track_id + "&track_pos" + this.track_pos);
}

/* --- INTERFACE TO LIST --- */

index_to_track_id = function(aelem, i)
{
	var elem = aelem.parentNode;
	var elem_id = elem.id;
	var track_id = elem_id.replace(/track:/i, "");
	Listener.assign_track_id(i, track_id);
}

/* ===== COMPONENT.NAVIGATION.JS ===== */

var navigation = new Object();

navigation.onmouseover = function(elem)
{
	navigation.mouseover(elem);
	var sub = elem.getElementsByTagName("ul")[0];
	if (sub && sub.style.display != "block")
	{
		sub.style.display = "block";
		console.log("opening");
		
		/*
		sub.style.visibility = "hidden";
		sub.style.display = "block";
		max = sub.clientHeight;
		
		sub.style.overflow = "hidden";
		sub.style.height = "20px";
		sub.style.visibility = "visible";
		
		typic_smooth_expand(Typic.get_id(sub), 20, max);*/
	}
	if (!elem.onmouseout)
		elem.onmouseout = function()
		{
			navigation.onmouseout(this);
		}
}

navigation.onmouseout = function(elem)
{
	navigation.mouseout(elem);
	var sub = elem.getElementsByTagName("ul")[0];
	if (sub)
	{
		setTimeout("navigation.hide($('" + Typic.get_id(sub) + "'))", 1000);
	}
	
}

navigation.hide = function(elem)
{
	if (!elem.is_mouseover)
	{
		console.log("hiding");
		elem.style.display = "none";
	}
}

navigation.show = function(elem)
{
	Typic.addClass(elem, 'jshover');
	var sub = elem.getElementsByTagName("ul")[0];
	if (sub)
	{	
		Typic.smooth_expand(sub);
	}
}
		
navigation.mouseover = function(elem)
{
	elem.is_mouseover = true;
}

navigation.mouseout = function(elem)
{
	elem.is_mouseover = false;
}

function MenuHoverManager(id, timeout)
{

	var ul2List = Typic.getElementsByClass('level1', document.getElementById(id), "li");
	var timeout = 100;
	var offCounter = 0;
	var resetCounter = 0;
	var that = this;

	function menuClearHovers() {
		for (var i=0; i<ul2List.length; ++i) {
			ul2 = ul2List[i];
			Typic.removeClass(ul2, 'jshover');
		}
	}

	this.init = function () {
		for (var i=0; i<ul2List.length; ++i) {
			ul2 = ul2List[i];
		
			ul2.onmouseover = function () {
				//menuClearHovers();
				Typic.addClass(this, 'jshover');
				//setTimeout("navigation.show($('"+Typic.get_id(this)+"'))", 20);
			};
		
			ul2.onmouseout = function ()	{
				++offCounter;
				this.timeoutid = setTimeout(function () {
								++resetCounter;
								if (offCounter==resetCounter)	{
									menuClearHovers();
								}
							}, timeout);
			};
		}
	}
}

unobem = function(elem)
	{
		var qs = Cynic.parse_query_string(elem.href.match(/#(.*)$/)[1]);
		
		var obem = qs["obem"];
		var email = decrypt(obem, "goBabyGo8");
		elem.href = "mailto:" + email;
		elem.innerHTML = email;
	}
		
	function decrypt(enc_str, key)
	{
		if (!key) key = "mykey123";
		var str = "";
		var j = 0;
		var codes = enc_str.split("-");
		for (i = 0; i < codes.length-1; i++)
		{
			if (j == key.length)
				j = 0;
			str += String.fromCharCode((parseInt(codes[i]) - key.charCodeAt(j)));
			j++;
		}
		return str;
	}
function Jsslideshow(prefix, msec, max)
// Initialises a slide show - you only need to call this if you want to have more than one on a page, or if you need to change the id-prefix of the elements
{
	this.prefix = prefix ? prefix : "myJsslideshow";
	this.default_interval = msec ? parseInt(msec) : 3500;
	this.selected = 0;
	this.max = max ? parseInt(max) : 12;
	
	this.fadeInDelay = 200; // Setting this to 0 will suppress fade out. Positive values will issue fade in this amount of milliseconds after starting fade out.
	this.opacitySteps = 10; // 5 or 10 steps
	this.fadeInTime = 200; // Total time to fade in in milliseconds
	this.fadeOutTime = 400; // Total time to fade out in milliseconds
	
	this.autoSlide = false;
}

Jsslideshow.prototype.getElem = function(i)
{
	var elem = document.getElementById(this.prefix + ":" + i);
	return elem ? elem : false;
}

Jsslideshow.prototype.getVisible = function()
{
	for (var i = 0; i <= this.max; i++)
	{
		var elem = this.getElem(i);
		if (elem && !Typic.hasClass(elem, "hidden"))
		{
			return i;
		}
	}
	return false;
}

Jsslideshow.prototype.exists = function()
{
	for (var i = 0; i <= this.max; i++)
	{
		var elem = this.getElem(i);
		if (elem)
			return true;
	}
	return false;
}

Jsslideshow.prototype.stackSlides = function()
{
	var first = true;
	for (var i = 0; i <= this.max; i++)
	{
		var elem = this.getElem(i);
		if (elem)
		{
			Typic.addClass(elem, "slide_element");
			if (first)
			{
				Typic.addClass(elem.parentNode, "component_slides");
				first = false;
			}
			else
			{
				Typic.addClass(elem, "hidden");
			}
		}
	}
}

Jsslideshow.prototype.autoStart = function(msec)
// Starts the slideshow
// msec (optional) is the interval in milliseconds. Defaults to the value specified at the top
// NOTE: If the slideshow is already started, it will essentially continue, but with the new msec interval
{
	if (!this.exists())
	{
		return;
	}
	this.selected = this.getVisible();
	
	if (this.timer)
		this.autoStop();

	if (msec)
		this.default_interval = msec;
		
	this.autoSlide = true;
	
	this.autoNext();

}

Jsslideshow.prototype.autoNext = function()
{
	if (this.autoSlide)
		this.timer = setTimeout(this.prefix + ".showNext()", this.default_interval);
}

Jsslideshow.prototype.autoStop = function()
// Stops the slideshow
{
	if (this.timer)
		this.timer = clearTimeout(this.timer);
	this.autoSlide = false;
}

Jsslideshow.prototype.autoToggle = function()
// Starts or stops the slideshow
{
	if (this.autoSlide)
		this.autoStop();
	else
		this.autoStart();
}

Jsslideshow.prototype.showPrev = function(i)
// Shows the previous slide
{
	if (i == undefined)
		i = this.selected;
	else if (i == this.selected)
		return;
		
	if (i == 0)
		i = this.max;
	else
		i--;	
	
	if (!this.getElem(i))
		setTimeout(this.prefix + ".showPrev("+i+")", 10); 
	else
		this.show(i);
}

Jsslideshow.prototype.showNext = function(i)
// Shows the next slide
// Rewinds to the beginning when reaching the end
{
	if (i == undefined)
	{
		if (this.selected == undefined)
			this.selected = this.getVisible();
		i = this.selected;
	}
	else if (i == this.selected)
		return;
		
	if (i == this.max)
		i = 0;
	else
		i++;

	if (!this.getElem(i))
		setTimeout(this.prefix + ".showNext("+i+")", 10); 
	else
		this.show(i);
}

Jsslideshow.prototype.show = function(i)
// Shows a specific slide (fades in)
{
	if (i == this.selected)
		return;
	var elem = this.getElem(i);
	if (elem)
	{	
		if (this.fadeInDelay > 0)
			this.fadeOut(this.selected);
		setTimeout(this.prefix + ".fadeIn("+i+")", this.fadeInDelay);
		
		var nav_elem = document.getElementById("jsslideshow_navbar_select:" + this.selected);
		if (nav_elem)
			Typic.removeClass(nav_elem, "selected");
			
		var nav_elem = document.getElementById("jsslideshow_navbar_select:" + i);
		if (nav_elem)
			Typic.addClass(nav_elem, "selected");
	}
}

Jsslideshow.prototype.hide = function(i)
// Hides a specific slide (immediately)
{
	var elem = this.getElem(i);
	if (elem)
	{	
		if (!Typic.hasClass(elem, "hidden"))
			Typic.addClass(elem, "hidden");
	}
}

Jsslideshow.prototype.fadeIn = function(i)
{
	var elem = this.getElem(i);
	if (elem)
	{
		var opacity_match = elem.className.match(/opacity([^\s]+)/i);

		if (!opacity_match) // Starting fade in
		{
			Typic.addClass(elem, "opacity0");
			Typic.removeClass(elem, "hidden");
			Typic.addClass(elem, "on_top");
			this.fadeIn(i);
			return;
		}

		var opacity_class = opacity_match[0];
		var opacity = parseInt(opacity_match[1]);

		if (opacity > 90)	// Ending fade in
		{
			this.hide(this.selected);
	 		this.selected = i;
	 		Typic.removeClass(elem, opacity_class);
	 		Typic.removeClass(elem, "on_top");
	 		this.autoNext();
			return;
		}

		opacity = opacity + parseInt(100 / this.opacitySteps);
		Typic.addClass(elem, "opacity" + opacity);
		Typic.removeClass(elem, opacity_class);

		setTimeout(this.prefix + ".fadeIn("+i+")", parseInt(this.fadeInTime / this.opacitySteps));
	}			 	
}

Jsslideshow.prototype.fadeOut = function(i)
{
	var elem = this.getElem(i);
	if (elem)
	{
		var opacity_match = elem.className.match(/opacity([^\s]+)/i);

		if (!opacity_match) // Starting fade out
		{
			Typic.addClass(elem, "opacity100");
			this.fadeOut(i);
			return;
		}

		var opacity_class = opacity_match[0];
		var opacity = parseInt(opacity_match[1]);
		
		if (opacity < 10)
		{
			Typic.removeClass(elem, opacity_class);
			this.hide(i);
			return;
		}

		opacity = opacity - parseInt(100 / this.opacitySteps);
		Typic.addClass(elem, "opacity" + opacity);
		Typic.removeClass(elem, opacity_class);

		setTimeout(this.prefix + ".fadeOut("+i+")", parseInt(this.fadeOutTime / this.opacitySteps));
	}			 	
}

myJsslideshow = new Jsslideshow("myJsslideshow");

