// jslib - minimal javascript library
// copyright (c) Mathieu Gosset (mathieu at devandco dot net)

function register_namespace(namespace)
{
	var parts = namespace.split(".");
	var node = window;
	for (var i = 0; i < parts.length; ++i) {
		if(node[parts[i]] == undefined)
			node[parts[i]] = new Object();
		node = node[parts[i]];
	}
}

// dom helpers ----------------------------------------------------------------

register_namespace("dom");

dom.bind = function(object, method)
{
	return function() {object[method].apply(object, arguments);}
}

dom.queue_load_event = function(fn)
{
	var prev_event = window.onload;
	window.onload = (typeof window.onload != 'function') ? fn : function() {
		if (prev_event)
			prev_event();  
		fn(); 
	};
}  

dom.add_listener = function(obj, type, fn)
{
	var wrapped = function(ev) {return fn(ev == undefined ? window.event : ev);};
	if (obj.addEventListener) {
		obj.addEventListener(type, wrapped, false);
		return wrapped;
	} else if (obj.attachEvent) {
		obj.attachEvent("on" + type, wrapped);
		return wrapped;
	} else
		return false;
}

dom.remove_event = function(obj, type, fn, useCapture)
{
	if (obj.removeEventListener) {
		obj.removeEventListener(type, fn, useCapture);
		return true;
	} else if (obj.detachEvent)
		return obj.detachEvent("on" + type, fn);
	else
		throw "handler could not be removed";
}

dom.client_height = function()
{
	if (window.innerHeight != window.undefined)
		return window.innerHeight;
	else if (document.compatMode == 'CSS1Compat')
		return document.documentElement.clientHeight;
	else
		return document.body ? document.body.clientHeight : undefined;
}

dom.client_width = function()
{
	if (window.innerWidth != window.undefined)
		return window.innerWidth; 
	else if (document.compatMode == 'CSS1Compat')
		return document.documentElement.clientWidth; 
	else
		return document.body ? document.body.clientWidth: undefined;
}

dom.scroll_top = function()
{
	var top = undefined;
	if (window.pageYOffset)
		top = window.pageYOffset;
	else if (document.documentElement && document.documentElement.scrollTop)
		top = document.documentElement.scrollTop;
	else if (document.body)
		top = document.body.scrollTop;
	return top != undefined ? parseInt(top, 10) : 0;
}

dom.scroll_left = function()
{
	var left = undefined;
	if (window.pageXOffset)
		left = window.pageXOffset;
	else if (document.documentElement && document.documentElement.scrollLeft)
		left = document.documentElement.scrollLeft;
	else if (document.body)
		left = document.body.scrollLeft;
	return left != undefined ? parseInt(left, 10): 0;
}

 function findPosX(obj)
  {
    var curleft = 0;
    if(obj.offsetParent)
        while(1) 
        {
          curleft += obj.offsetLeft;
          if(!obj.offsetParent)
            break;
          obj = obj.offsetParent;
        }
    else if(obj.x)
        curleft += obj.x;
    return curleft;
  }

dom.position = function(el)
{
	var x = 0, y = 0;
	var w = el.style.pixelWidth ? el.style.pixelWidth : el.offsetWidth;
	var h = el.style.pixelHeight ? el.style.pixelHeight : el.offsetHeight;
	if (el.offsetParent) {
		do {
			x += el.offsetLeft;
			y += el.offsetTop;
		} while (el = el.offsetParent);
	}
	return {'x' : x, 'y' : y, 'w' : w, 'h' : h};
}

function fmt_numval(val)
{
	return isNaN(Number(val)) ? val : val + "px";
}

dom.move = function(el, x, y, w, h)
{
	if (x) el.style.left = fmt_numval(x);
	if (y) el.style.top = fmt_numval(y);
	if (w) el.style.width = fmt_numval(w);
	if (h) el.style.height = fmt_numval(h);
}

dom.show = function(el, visible)
{
	el.style.display = visible ? "" : "none";
}

dom.set_opacity = function(el, opacity)
{
	el.style.opacity = (opacity / 100);
	el.style.MozOpacity = (opacity / 100);
	el.style.KhtmlOpacity = (opacity / 100);
	el.style.filter = "alpha(opacity=" + opacity + ")";
}

dom.set_classname = function(el, classname)
{
	el.setAttribute("class", classname);
	el.setAttribute("className", classname);
}

dom.css_add_selector = function(el, selector)
{
	if (el.className.indexOf(selector) == -1)
		dom.set_classname(el, selector + " " + el.className);	
}

dom.css_remove_selector = function(el, selector)
{
	dom.set_classname(el, el.className.replace(selector, ""));	
}

dom.element = function(id)
{
	return document.getElementById(id);
}

dom.redirect = function(url)
{
	document.location = url;
}

dom.ev_target = function(ev)
{
	if (ev) {
		var target = ev.target ? ev.target : ev.srcElement;
		if (target.nodeType == 3) target = target.parentNode;
		return target;
	} else {
		return null;
	}
}

dom.ev_keycode = function(ev)
{
	return ev.which != undefined ? ev.which : ev.keyCode;
}

dom.is_child = function(parent, child)
{
	for(; child != undefined; child = child.parentNode)
		if (child == parent)
			return true;
	return false;
}

dom.index_of_node = function(node_list, node)
{
	for(var i = 0; i < node_list.length; ++i)
		if (node_list[i] == node)
			return i;
	return -1;
}

// asynchronous request -------------------------------------------------------

register_namespace("rpc");

rpc.execute = function(method, url, completion_handler, data)
{
	var request = window.XMLHttpRequest ? new XMLHttpRequest() : 
		new ActiveXObject("Microsoft.XMLHTTP");
	if (request == undefined)
		return false;
	request.onreadystatechange = function() {
		if (request.readyState == 4)
			completion_handler(request.status, request.responseText);
	};
	request.open(method, url, true);
	request.setRequestHeader('Content-Type', 'text/xml; charset=iso-8859-1');
	request.send(data);
	return true;
}

// form utilities -------------------------------------------------------------

register_namespace("formutils");

formutils.enable = function(form, enabled, field_classname)
{
	for (var i = 0; i < form.elements.length; ++i) {
		var el = form.elements[i];
		if (el != undefined) {
			el.readOnly = !enabled;
			if (field_classname != undefined)
				dom.set_classname(el, field_classname);
		}
	}
}

formutils.reset = function(form)
{
	for (var i = 0; i < form.elements.length; ++i) {
		var el = form.elements[i];
		if (el.type != "radio")
			el.value = "";
	}
}

formutils.serialize = function(form)
{
	var output = '{';
	var re = new RegExp("\"", 'g');
	for (var i = 0; i < form.elements.length; ++i) {
		var el = form.elements[i];
		if (el.type == "radio" && el.checked == false)
			continue;
		if (el.value != undefined)
			output += (output.length > 1 ? ', ' : '' ) + 
				'"' + el.name.replace(re, "\\\"") + '" : "'
				 + el.value.replace(re, "\\\"") + '"';
	}
	output += '}';
	return output;
}

formutils.radio_value = function(form, name)
{
	var el = form.elements[name];
	if (!el)
		return '';
	if (el.length == undefined)
		return el.checked ? el.value : '';
	for(var i = 0; i < el.length; ++i)
		if(el[i].checked)
			return el[i].value;
	return '';
}

formutils.populate = function(form, form_data)
{
	for (var i = 0; i < form.elements.length; ++i) {
		var el = form.elements[i];
		var parts = el.name.split(".");
		var src = form_data;
		for (var j = 0; j < parts.length && src != undefined; ++j)
			src = src[parts[j]];
		if (src != undefined) {
			if (el.type == "radio"){
				if (el.value == src)
					el.checked = true;				
			} else
				el.value = unescape(src);
		}
	}
}

// modal ui -------------------------------------------------------------------

register_namespace("modal");

modal.initialize = function(mask_id)
{
	this.tab_indices = new Array();
	this.popup_el = null;
	this.mask_el = dom.element(mask_id);
	this.navigable_tags = new Array("A", "BUTTON", "TEXTAREA", "INPUT", "IFRAME");

	var browser_version = parseInt(window.navigator.appVersion.charAt(0));
	if (browser_version <= 6 && window.navigator.userAgent.indexOf("MSIE") > -1)
		this.hide_selects = true;
	else
		this.hide_selects = false;

	dom.add_listener(window, "resize", dom.bind(this, "center"));
	dom.add_listener(window, "scroll", dom.bind(this, "center"));
}

modal.show = function(popup_id)
{
	if (this.popup_el != null)
		this.popup_el.style.display = "none";

	this.popup_el = dom.element(popup_id);
	if (this.popup_el == undefined)
		return null;

	document.body.style.overflow = "hidden";
	this.mask_el.style.display = "block";
	this.popup_el.style.display = "block";
	//this.enable_navigation(false);
	this.center();
}

modal.hide = function()
{
	if (this.popup_el == null || this.mask_el == null)
		return;

	var body_el = document.getElementsByTagName("BODY")[0];
	this.enable_navigation(true);
	this.mask_el.style.display = "none";
	this.popup_el.style.display = "none";
	document.body.style.overflow = "";

	// display all select boxes
	if (this.hide_selects == true)
		this.show_select_controls(true);

	this.popup_el = null;
}

modal.center = function()
{
	if (this.popup_el == null || this.mask_el == null)
		return;
	dom.move(this.mask_el, dom.scroll_left(), dom.
		scroll_top(), dom.client_width(), dom.client_height());
	dom.move(this.popup_el, dom.scroll_left() + (dom.
		client_width() - this.popup_el.offsetWidth) / 2, dom.scroll_top()
		+ (dom.client_height() - this.popup_el.offsetHeight) / 2);
}

modal.create_focus_handler = function(i)
{
	var self = this;
	return function() {
		self.current_focus = i;
		return true;
	};
}

modal.enable_navigation = function(enable)
{
	var self = this;
	var keydown_handler = function(evt) {
		var ev = evt ? evt : event;
		if (ev.keyCode == 9) {
			if ((ev.shiftKey && self.current_focus == 0) ||
				(!ev.shiftKey && self.current_focus >= self.total_count)) {
				if (ev.preventDefault) {
					ev.preventDefault();
					ev.stopPropagation();
				}
				return false;
			}
			else
				return true;
		} else
			return true;
	}
	//dom.add_listener(document, "keydown", keydown_handler);

	var i = 0;
	for (var j = 0; j < this.navigable_tags.length; ++j) {
		var elements = this.popup_el.getElementsByTagName(this.
			navigable_tags[j]);
		for (var k = 0; k < elements.length; ++k) {
			var element = elements[k];
			element.onfocus = this.create_focus_handler(i);
			if (!j && !k)
				element.focus();
			++i;
		}
	}
	this.current_focus = 0;
	this.total_count = i - 1;
}

modal.show_select_controls = function(visible)
{
	var x = document.getElementsByTagName("SELECT");
	for (var i = 0; x && i < x.length; ++i)
		x[i].style.visibility = visible ? "visible" : "hidden";
}


register_namespace("utils");

utils.clone = function(src)
{
    if(typeof(src) != 'object' || src == null)
        return src;
    var cloned = src.constructor();
    for(var i in src)
        cloned[i] = clone(src[i]);
    return clone;
}

utils.format = function() { 
	var out = arguments[0];   
	for (var i = 1; i < arguments.length; ++i) { 
		var re = new RegExp("\\{" + (i - 1) + "\\}", "g"); 
		out = out.replace(re, arguments[i]); 
	} 
	return out;
}




