
function get_radio_value(elem)
{
	// radio with only 1 option doesn't have length?!
	if (!elem.length)
	{
		if (elem.checked && elem.value) return elem.value;
		return null;
	}
	for (var i = 0; i < elem.length; ++i)
	{
		if (elem[i].checked) return elem[i].value;
	}
	return null;
}

function get_radio_elem(elem)
{
	var i, radio_elem;
	for (i = 0; i < elem.length; ++i)
	{
		radio_elem = elem[i];
		if (radio_elem.checked) return radio_elem;
	}
	return null;
}

function set_radio(elem, index)
{
	if (!elem) return;
	for (var i = 0; i < elem.length; ++i)
		elem[i].checked = (i == index);
}

function trim(s)
{
	var re_start, re_end;
	
	if (arguments.length > 1)
	{
		re_start = new RegExp("^"+arguments[1]+"+");
		re_end = new RegExp(arguments[1]+"+$");
	}
	// default is trim whitespace
	else
	{
		re_start = new RegExp("^\\s+");
		re_end = new RegExp("\\s+$");
	}
	s = s.replace(re_start, "");
	return s.replace(re_end, "");
}

function get_number(s)
{
	var matches;
	
	if (matches = s.match(/(\d+)/)) return Number(matches[1]);
	return null;
}

function ucfirst(str)
{
	if (str && str.length)
	{
		switch (str.length)
		{
			case (0): return str;
			case (1): return str[0].toUpperCase();
			default:  return str[0].toUpperCase() + str.substr(1);
		}
	}
	return str;
}

function format(n, decimals)
{
	var i, d;
	
	n = String(Math.round(n*Math.pow(10,decimals))*Math.pow(10,-decimals));
	
	d = n.indexOf(".");
	
	if (d == -1)
	{
		n += ".";
		for(i = 0; i < decimals; i++) n += "0";
		return n;
	}
	
	if (d == 0)
	{
		n = "0" + n;
		d++;
	}
	
	if (d == 1 && n.substring(0, 1) == "-")
	{
		n = "-0" + n.substring(1, n.length);
		d++;
	}
	
	n = n.substring(0, d + decimals + 1);
	
	while (n.length <= d + decimals) n += "0";
	return n;
}

function format_dollars(n)
{
	var i, lang, thousands_separator, decimal_symbol, currency_symbol;
	
	if (isNaN(n)) return n;
	n = format(n, 2);
	
	// check for language so we can format currency
	lang = doc_elem("lang");
	if (lang && lang.value) lang = lang.value;
	switch (lang)
	{
		case ("de"):
			thousands_separator = ".";
			decimal_symbol = ",";
			currency_symbol = "&euro;";
			break;
			
		default:
			thousands_separator = ",";
			decimal_symbol = ".";
			currency_symbol = "$";
			break;
	}
	
	n = n.replace(/\./, decimal_symbol);
	for (i = n.indexOf(decimal_symbol) - 3; i > 0; i -= 3)
	{
		n = n.substring(0, i) + thousands_separator + n.substr(i);
	}
	return currency_symbol + n;
}

function simple_text(str)
{
	return str.toLowerCase().replace(/ /, "_");
}

function select_submit(event)
{
	var select;
	
	select = get_event_src(event);
	if (!empty(select.value) || get_attr(select, "allow_empty", "getAttribute")) f.submit();
}

function select_add_option(select, value, display)
{
	select[select.options.length] = new Option(display, value);
}

function select_remove_option(select, value)
{
	var i, option;
	
	for (i = 0; i < select.options.length; ++i)
	{
		if (select.options[i].value == value)
		{
			select.remove(i);
			return;
		}
	}
}

function select_has_option(select, value)
{
	var i, option;
	
	for (i = 0; i < select.options.length; ++i)
	{
		if (select.options[i].value == value) return true;
	}
	return false;
}

function doc_elem(id)
{
	return document.getElementById(id);
}

function doc_create(elem_type)
{
	return document.createElement(elem_type);
}

function dbg(text)
{
	var elem;
	
	elem = doc_create("p");
	elem.innerHTML = text;
	document.body.appendChild(elem);
}

function set_link_handler(container, handler)
{
	var i, link, links;
	
	container = doc_elem(container);
	if (empty(container)) return;
	links = container.getElementsByTagName("A");
	for (i = 0; link = links[i]; ++i)
		link.onclick = handler;
}

function Point(_x, _y)
{
	if (arguments.length > 2)
	{
		this[arguments[2]] = _x;
		this[arguments[3]] = _y;
	}
	else
	{
		this.x = _x;
		this.y = _y;
	}
}

function empty(v)
{
	var i, type;
	
	type = typeof(v);
	switch (type)
	{
		case ("string"): return (v.match(/^\s*$/gi) != null);
		case ("number"): return (v == 0);
		case ("boolean"): return !v;
		case ("undefined"): return true;
		case ("object"):
			for (i in v) return false;
			return true;
	}
	
	// some unknown type, return false
	return false;
}

function include_js(path)
{
	var js;
	
	js = doc_create("script");
	js.setAttribute("type", "text/javascript");
	js.setAttribute("src", f.url_base.value + path);
	document.getElementsByTagName("head")[0].appendChild(js);
}

function get_attr(elem)
{
	var func, attr;
	
	if (!elem) return null;
	
	attr = arguments[1];
	if (arguments.length > 2)
	{
		func = arguments[2];
		return ((elem[func]) ? elem[func](attr) : null);
	}
	return elem.attr;
}

function set_attr(elem, key, val)
{
	dbg(elem+","+key+","+val);
	if (!elem) return;
	elem.setAttribute(key, val);
}

function get_cell_loc(cell)
{
	var table, row, tmp, row_index, cell_index;
	
	row = cell.parentNode;
	table = row.parentNode;
	
	// find the row
	for (row_index = 0; row_index < table.rows.length && row != table.rows[row_index]; ++row_index);
	
	// find the cell
	for (cell_index = 0; cell_index < row.cells.length && cell != row.cells[cell_index]; ++cell_index);
	
	return (new Point(cell_index, row_index, "cell", "row"));
}

function get_child_index(parent, target_child)
{
	var i, child;
	
	for (i = 0; i < parent.childNodes.length; ++i)
	{
		child = parent.childNodes[i];
		if (child == target_child) return i;
	}
	return -1;
}


function get_event_src(event)
{
	var src_elem;
	
	if (!event) event = window.event;
	src_elem = (event.currentTarget) ? event.currentTarget : event.srcElement;
	if (src_elem.nodeType == 3) src_elem = src_elem.parentNode;
	
	return src_elem;
}

function add_hidden_field(field_name, field_value)
{
	var input;
	
	if (empty(field_name)) return false;
	input = doc_create("input");
	input.type = "hidden";
	input.name = field_name;
	input.value = (empty(field_value)) ? "true" : field_value;
	f.appendChild(input);
	return true;
}

function event_stop(event)
{
	if (event) event.stopPropagation();
}

function date_month(month_index)
{
	var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
	return months[month_index];
}

function date_str_to_js(d)
{
	var matches;
	
	matches = d.match(/^(\d\d\d\d)\-(\d\d)\-(\d\d)$/);
	if (matches) return new Date(matches[1], matches[2]-1, matches[3]);
	return false;
}

function date_js_to_str(d)
{
	return d.getFullYear()+"-"+str_pad(d.getMonth()+1, 2, "0", "LEFT")+"-"+str_pad(d.getDate(), 2, "0", "LEFT");
}

function date_add_month(time, delta_m)
{
	var y, m, d, temp_date;
	
	temp_date = new Date(time);
	y = temp_date.getFullYear();
	m = temp_date.getMonth();
	d = temp_date.getDate();
	
	m += delta_m;
	
	if (m < 0)
	{
		y--;
		m = 11;
	}
	else if (m > 11)
	{
		y++;
		m = 0;
	}
	
	return new Date(y, m, 15, 12, 0, 0);
}

function str_pad(str, len, pad_char, left_right)
{
	str = String(str);
  while (str.length < len)
		str = (left_right == "LEFT") ? (pad_char + str) : (str + pad_char);
	
	return str;
}

function get_absolute_pos(elem)
{
	var pos, i, parents, ancestor_pos;
	
	pos = elem.position();
	parents = $(elem.parents());
	for (i = 0; i < parents.length; ++i)
	{
		ancestor_pos = $(parents[i]).position();
		pos.left += ancestor_pos.left;
		pos.top += ancestor_pos.top;
	}
	pos.left = Math.round(pos.left);
	pos.top = Math.round(pos.top);
	return pos;
}

function set_cookie(k, v, s)
{
	var d;
	
	if (s == 0)
	{
		document.cookie = k+"="+v+"; path=/";
	}
	else
	{
		d = new Date();
		d = new Date(d.getTime() + (s * 1000));
		document.cookie = k+"="+v+"; expires="+d.toUTCString()+"; path=/";
	}
}

function get_cookie(key)
{
	var cookie_str, i1, i2;
	
	cookie_str = document.cookie;
	i1 = cookie_str.indexOf(key + '=');
	if (i1 == -1) return null;
	if (i1 > 0 && cookie_str.charAt(i1 - 1) != " ") return null;
	i2 = cookie_str.indexOf(';', i1);
	if (i2 == -1) i2 = cookie_str.length;
	
	return cookie_str.substring(i1 + key.length + 1, i2);
}

function parse_query()
{
	var q, kv_pairs, kv_pair, i, r, loc;
	
	loc = (arguments.length > 0) ? arguments[0] : String(window.location);
	
	// check url for query
	i = loc.indexOf("?");
	if (i == -1) return {};
	
	q = loc.substr(i + 1);
	r = {};
	kv_pairs = q.split("&");
	for (i = 0; i < kv_pairs.length; ++i)
	{
		kv_pair = kv_pairs[i].split("=");
		r[kv_pair[0]] = unescape(kv_pair[1]);
	}
	return r;
}

function get_child(parent, test)
{
	var i, child, test_child;
	
	for (i = 0; child = parent.childNodes[i]; ++i)
	{
		if (test(child)) return child;
		test_child = get_child(child, test);
		if (test(test_child)) return test_child;
	}
	return null;
}

function get_parent(node, test)
{
	var parent;
	
	parent = node.parentNode;
	if (!parent) return null;
	if (test(parent)) return parent;
	return get_parent(parent, test);
}

function swap_elems(parent, src, dst)
{
	var i, j, node, num_nodes, n1, n2, next_node_after_first_node_that_isnt_second_node;
	
	n1 = n2 = next_node_after_first_node_that_isnt_second_node = null;
	for (i = 0, num_nodes = parent.childNodes.length; i < num_nodes; ++i)
	{
		node = parent.childNodes[i];
		if (node == src || node == dst)
		{
			// we found our first node
			if (n1 == null)
			{
				n1 = node;
				// look for 2nd node
				for (j = i + 1; j < num_nodes; ++j)
				{
					node = parent.childNodes[j];
					// only special case: nodes are next to each other
					// n2 will be set on next iteration of outer loop, next_nod... will not be set
					if (node == src || (node == dst && j == (i + 1))) break;
					if (node != src && node != dst)
					{
						next_node_after_first_node_that_isnt_second_node = node;
						break;
					}
				}
			}
			// found the 2nd node, we're done
			else
			{
				n2 = node;
				break;
			}
		}
	}
	
	// nodes are next to each other, just move 2nd to before 1st
	if (next_node_after_first_node_that_isnt_second_node == null)
	{
		parent.removeChild(n2);
		parent.insertBefore(n2, n1);
	}
	// nodes aren't next to each other
	// move 1st node to before 2nd and 2nd to before the node after the 1st
	else
	{
		parent.removeChild(n1);
		parent.insertBefore(n1, n2);
		
		parent.removeChild(n2);
		parent.insertBefore(n2, next_node_after_first_node_that_isnt_second_node);
	}
}

function object_to_str(o)
{
	var str, i, separator;
	
	separator = (arguments.length > 1) ? arguments[1] : ", ";
	str = "";
	for (i in o)
	{
		if (!empty(str)) str += separator;
		str += i+"="+o[i];
	}
	return str;
}

function suicide(elem)
{
	elem.parentNode.removeChild(elem);
}

function remove_children(elem)
{
	while (elem.childNodes.length > 0) elem.removeChild(elem.childNodes[0]);
}

function form_set(elem_name, val)
{
	// only set if val is non-empty
	if (empty(val)) return;
	
	if (form_exists(elem_name)) f[elem_name].value = val;
	else if (arguments.length > 2) add_hidden_field(elem_name, val);
}

function form_exists(elem_name)
{
	return (typeof(f.elements[elem_name]) != "undefined");
}

function set_class(elem, class_name)
{
	elem.className = class_name;
}

// add one or more classes
function add_class(elem, class_name)
{
	var classes, i;
	
	classes = (typeof(class_name) == "object") ? class_name : [class_name];
	for (i = 0; class_name = classes[i]; ++i)
	{
		if (empty(elem.className)) elem.className = class_name;
		else elem.className += " "+class_name;
	}
}

function remove_class(elem, class_name)
{
	var re;
	
	re = new RegExp("(\\s|)"+class_name);
	elem.className = elem.className.replace(re, "");
}

function replace_class(elem, old_class, new_class)
{
	var re;
	
	re = new RegExp("(\\s|)"+old_class);
	elem.className = elem.className.replace(re, "$1"+new_class);
}

function has_class(elem, class_test)
{
	var re;
	
	re = new RegExp("\\b"+class_test+"\\b");
	return (elem.className && re.test(elem.className));
}

function get_key(the_event)
{
	if (the_event.keyCode)       return the_event.keyCode;
	else if (the_event.which)    return the_event.which;
	else if (the_event.charCode) return the_event.charCode;
	return false;
}

function query_clear()
{
	var i, loc;
	
	loc = String(window.location);
	
	// check url for query
	i = loc.indexOf("?");
	
	// no query, just add query and set x=y
	if (i == -1)
	{
		return loc;
	}
	else
	{
		return loc.substr(0, i);
	}
}

function query_set(q)
{
	var i, loc;
	
	loc = String(window.location);
	
	// check url for query
	i = loc.indexOf("?");
	
	// no query, just add query and set x=y
	if (i == -1)
	{
		return (loc+"?"+q);
	}
	else
	{
		return loc.substr(0, i + 1)+q;
	}
}

function query_replace(x, y)
{
	var q, i, loc, reg_exp, matches;
	
	loc = String(window.location);
	// check url for query
	i = loc.indexOf("?");
	
	// no query, just add query and set x=y
	if (i == -1)
	{
		return (loc+"?"+x+"="+escape(y));
	}
	else
	{
		reg_exp = new RegExp("(\\?|&)"+x+"=.*?(&|$)");
		matches = reg_exp.exec(loc);
		return (matches) ? loc.replace(matches[0], matches[1]+x+"="+escape(y)+matches[2]) : (loc + "&"+x+"="+escape(y));
	}
}

function add_onload_func(new_func)
{
	var cur_func;
	
	cur_func = window.onload;
	window.onload = function() {
		if (cur_func) cur_func();
		new_func();
	}
}

function add_onload_func(new_func)
{
	add_handler(window, "onload", new_func);
}

function add_handler(obj, event_name, new_func)
{
	var cur_func;
	
	cur_func = obj[event_name];
	obj[event_name] = function(event) {
		if (cur_func) cur_func(event);
		new_func(event);
	}
}
