/* The DOM3K Framework to provide AJAX behaviour 
Eric Sadit Tellez Avila sadit@lsc.fie.umich.mx donsadit@gmail.com
3Kong Corp.
*/

function DOM3K_addEventListener(element, eventname, listener, usecapture)
{
    if (element.addEventListener) {
	element.addEventListener(eventname, listener, usecapture);
    } else {
	/* There is not usecapture to IE6*/
	element.attachEvent('on' + eventname, listener);
    }
}

function DOM3K_removeEventListener(element, eventname, listener, usecapture)
{
    if (element.removeEventListener) {
	element.removeEventListener(eventname, listener, usecapture);
    } else {
	/* There is not usecapture to IE6*/
	element.detachEvent('on' + eventname, listener);
    }
}

function DOM3K_debugObject(obj, deep)
{
    if (!deep) deep = 0;
    var x = '';
    var y;
    if (typeof(obj) == "object") {
        x += '{\n';
        for (y in obj) {
            x += "'" + y + "'=";
            if (deep < 0) {
                x += "'" + DOM3K_debugObject(obj[y], deep + 1) + "' recursive;\n";
            } else {
                x += "'" + obj[y] + "' recurtion's top;\n";
            }
        }
        x += '}\n';

    } else {
        x += '' + obj + "(scalar)";
    }
    return x;
}

function DOM3K_getElement(idTagOrObject)
{
	if (typeof(idTagOrObject) == 'string') {
		return document.getElementById(idTagOrObject);
	} else {
		return idTagOrObject;
	}
}
/*
function __DOM3K_appendBodyChild(element, elemid, elemstyle)

Append a child to the DOM

|element| is the element to be inserted
|elemid| is the id of |element|
|elemstyle| is a style to |elemement|
*/
function __DOM3K_appendBodyChild(element, elemid, elemstyle)
{
    element.setAttribute("id",elemid);
    element.setAttribute("style", elemstyle);
    if (DOM3K_getElement("DOM3K_Root") == null) {
	var body = document.getElementsByTagName("body");
	body.item(0).appendChild(element);
    } else {
	DOM3K_getElement("DOM3K_Root").appendChild(element);
    }
}

var DOM3K_DivResults = document.createElement("div");
var DOM3K_DivErrors = document.createElement("div");

/*
function DOM3K_createFrame(htmldata, options)

|htmldata| is an html string to put into the frame.
|options| a string to be evaluated, it must have at least the idTag variable i.e. "idTag='SomeId',name='SomeName',timeout='seconds'"
Where:

|idTag| is the Id of the frame inside the DOM.
|title| The title to display in the frame.
|timeout| Frame's Time to live.
|left| The position relative to the left.
|top| The position relative to the top.
|width| The width of the new frame.
|height| The height of the new frame.
|visibility| The initial visibility of the frame, visible is the default value

Creates and returns a new frame inside the window, the frame is an object with the following properties:

idTag. The id of the frame inside the DOM
container. An HTML div element that will be used as container of title bar and main div.
div. The div is the most important element of the frame, here is where all HTML elements must be placed.
controls. The controls of the frame
title. The html element that is used as title
top. The container of the title, and the frame controls.

It has the following methods:
setTitle(title). Set the title of the frame
setInnerHTML(htmldata, title). Set the content of the frame, if title is given it's set too.
setFrameOnTop(). Puts the frame always on the top
quitFrameOnTop(). Returns the frame to the normal level

CSS's classes used in frames (preffixed with DOM3K_Frame)

+--------------------------------------------+
|   Top                    |Title|Controls   |
+--------------------------------------------+
|                                            |
|          Div                               |
|                                            |
+--------------------------------------------+
And everything is contained into Container

function DOM3K_frameFinished(frame)

It is called when the frame is created and inserted in the DOM. It must be
overloaded to perform changes in the style of frames or any other change.


*/

var __DOM3K_Dragging = null;
var __DOM3K_Dragging_X = 0;
var __DOM3K_Dragging_Y = 0;
var __DOM3K_FrameUniqId = 0;
var __DOM3K_top_zIndex = 100;
var __DOM3K_top_zIndexOnTop = 100000000;

function DOM3K_frameFinished(frame)
{
}

function DOM3K_createFrame(htmldata, options)
{	        
	var idTag = "Dialog" + '_' + __DOM3K_FrameUniqId;
        __DOM3K_FrameUniqId += 1;
	var title = idTag;
	var timeout = 0;
	var left = (__DOM3K_FrameUniqId * 50) % 500 + 50;
	var top = (__DOM3K_FrameUniqId * 20) % 400 + 20;
	var width = null;
	var height = null;
	var visibility = null;
	eval(options);
	if (visibility == null) visibility = 'visible';
	var frame = new Object();
	var container = document.createElement('div');
	__DOM3K_appendBodyChild(container, idTag, "");
	container.setAttribute("class","DOM3K_FrameContainer");
	container.style.border = "1pt solid black";
	container.style.zIndex = __DOM3K_top_zIndex;
	__DOM3K_top_zIndex += 1;
	if (container.addEventListener) {
	    container.style.position = "fixed";
	} else {
	    container.style.position = "absolute";
	    top = document.body.scrollTop;
	    if (top == 0) top = 250;
	    width = "45%";
	}
	container.style.backgroundColor = "white";
	container.style.visibility = visibility;

	if (left) container.style.left = left;
	if (top) container.style.top = top;
	if (width) container.style.width = width;
	if (height) container.style.width = height;

	frame.idTag = idTag;
	frame.container = container;
	var top = document.createElement('div');
	frame.top = top;
	container.appendChild(top);
	top.style.borderBottom = "1pt solid black";
	top.style.height = "0.5cm";
	top.style.top = "0";
	top.style.right = "0";
	top.style.left = "0";
	top.style.width = "100%";
	top.style.textAlign = "right";
	top.setAttribute("class","DOM3K_FrameTop");
	var putover = function(event) {
	    if (parseInt(container.style.zIndex) > __DOM3K_top_zIndex + 100) {
		__DOM3K_top_zIndexOnTop += 1;
		container.style.zIndex = __DOM3K_top_zIndexOnTop;
	    } else {
		__DOM3K_top_zIndex += 1;
		container.style.zIndex = __DOM3K_top_zIndex;
	    }
	}
	DOM3K_addEventListener(container,'click',putover,false);
	var titlediv = document.createElement("span");
	titlediv.style.fontWeight = "bold";
	titlediv.setAttribute("class","DOM3K_FrameTitle");
	top.appendChild(titlediv);
	var controls = document.createElement('span');
	frame.controls = controls;
	frame.title = titlediv;
	controls.style.textAlign = "right";
	controls.style.top = "0";
	controls.style.right = "0";
	titlediv.setAttribute("class","DOM3K_FrameControls");
	DOM3K_appendListToElement([titlediv,controls],top);
	DOM3K_updateElement(title, titlediv);
	var closeelement = DOM3K_createElement(['X'],"span");
	var closeaction = function (event) {
	    DOM3K_deleteElement(idTag);
	};

	closeelement.style.textAlign = "right";
	closeelement.style.top = "0";
	closeelement.style.right = "0";
	closeelement.style.fontFamily = "sans-serif";
	closeelement.style.fontWeight = "bold";
	try {
	    closeelement.style.cursor = "pointer";
	} catch(e) {}
	closeelement.style.color = "blue";
	closeelement.style.textDecoration = "none";
	
	DOM3K_addEventListener(closeelement,"click",closeaction,false);
	DOM3K_appendListToElement([" ",closeelement],controls);
	var div = document.createElement('div');
	frame.div = div;
	container.appendChild(div);
	div.setAttribute("style","top: 0.5cm; left: 0; overflow: auto; max-height: 320pt; max-width: 700;");
	div.style.top = '0.5cm';
	div.style.left = "0";
	div.style.overflow = "auto";
	div.style.maxHeight = "320pt";
	div.style.maxWidth = "700pt";
	div.setAttribute("class","DOM3K_FrameDiv");

	if (htmldata == null) htmldata = '';
	DOM3K_updateElement(htmldata, div);
	var mousedown = function(_event) {
		__DOM3K_Dragging = container;
		__DOM3K_Dragging_X = _event.clientX;
		__DOM3K_Dragging_Y = _event.clientY;
		
		var mousemove = function(event) {
			if (__DOM3K_Dragging) {
				var changeY = __DOM3K_Dragging_Y - event.clientY;
				var changeX = __DOM3K_Dragging_X - event.clientX;
				container.style.top  = (parseInt(container.style.top)  - changeY);
				container.style.left = (parseInt(container.style.left) - changeX);
				__DOM3K_Dragging_Y = event.clientY;
				__DOM3K_Dragging_X = event.clientX;
			}
		}
		DOM3K_addEventListener(top,"mousemove",mousemove,true);
		DOM3K_addEventListener(document,"mousemove",mousemove,true);
		var mouseup = function(event) {
			__DOM3K_Dragging = null;
			DOM3K_removeEventListener(top,"mousemove",mousemove,true);
			DOM3K_removeEventListener(document,"mousemove",mousemove,true);
		}
		DOM3K_addEventListener(top,"mouseup",mouseup,true);
		DOM3K_addEventListener(document,"mouseup",mouseup,true);
	}
	DOM3K_addEventListener(top,"mousedown",mousedown,false);

	if (timeout) {
        	setTimeout(closeaction,timeout);
    	}

	/*methods: setInnerHTML, setTitle, quitFrameOnTop, setFrameOnTop*/
	frame.setFrameOnTop = function() {
	    frame.container.style.zIndex = __DOM3K_top_zIndexOnTop;
	}
	frame.quitFrameOnTop = function() {
	    frame.container.style.zIndex = __DOM3K_top_zIndex;
	}
	frame.setInnerHTML = function(_htmldata, _title) {
		DOM3K_updateElement(_htmldata, div);
		if (_title) DOM3K_updateElement(_title, titlediv);
	}


	frame.setTitle = function(_title) {
	   	DOM3K_updateElement(_title, titlediv);
	}
        
        frame.deleteFrame = function() {
                DOM3K_deleteElement(container);
        }
	DOM3K_frameFinished(frame);
	return frame;
}

/*
function DOM3K_init()
Initializes the DOM3K module

*/

function DOM3K_init()
{
    __DOM3K_appendBodyChild(DOM3K_DivResults,"DOM3K_DivResults", "visibility: hidden; ");
    DOM3K_DivResults.style.visibility = 'hidden';
    __DOM3K_appendBodyChild(DOM3K_DivErrors,"DOM3K_DivErrors", "visibility: hidden; position: fixed; right: 0; font-size: 10pt; top: 0; color: white; background-color: red; font-family: helvetica, monospace;");
    DOM3K_DivErrors.style.visibility = 'hidden';
    if (DOM3K_DivErrors.addEventListener) {
	DOM3K_DivErrors.style.position = 'fixed';
    } else {
	DOM3K_DivErrors.style.position = 'absolute';
    }
    DOM3K_DivErrors.style.right = '0';
    DOM3K_DivErrors.style.fontSize = '10pt';
    DOM3K_DivErrors.style.top = '0';
    DOM3K_DivErrors.style.color = 'white';
    DOM3K_DivErrors.style.backgroundColor = 'red';
    DOM3K_DivErrors.style.fontFamily = 'helvetica';
}

/*
function DOM3K_setDefaultDivResults(newdiv)
function DOM3K_getDefaultDivResults()

Accessors to DOM3K_DivResults

*/
function DOM3K_setDefaultDivResults(div)
{
    DOM3K_DivResults = DOM3K_getElement(div);
}

function DOM3K_getDefaultDivResults()
{
    return DOM3K_DivResults;
}
/*
function DOM3K_showError(data, timeout)

The DOM3K error output, it shows |data| in the errors output.
|timeout| is the amount of milliseconds that the result must be shown,
if it is null the result is not hidden
*/
function DOM3K_showError(data, timeout)
{
    if (timeout) {
        setTimeout("DOM3K_hideElement('DOM3K_DivErrors')",timeout);
    }
    DOM3K_updateElement(data, DOM3K_DivErrors);
    DOM3K_DivErrors.style.visibility = 'visible';
}

/*
function DOM3K_hideElement(idTag)

Hides an element
|idTag| can be the object to hide or the id of the element
*/

function DOM3K_hideElement(idTag)
{
    var elem = DOM3K_getElement(idTag);
    /*alert(idTag);*/
    elem.style.visibility = "hidden";
}

/* Redefinition of SPyRO info function */
function SPyRO_info(data)
{
    DOM3K_showError(data);
}

function SPyRO_infodone(data)
{
    DOM3K_hideElement('DOM3K_DivErrors');
}

/* Redefinition of SPyRO warning function */
function SPyRO_warning(data)
{
    DOM3K_showError("Warning: " + data, null);
}
/* Redefinition of SPyRO fatalError function */
function SPyRO_fatalError(data)
{
	DOM3K_showError("Fatal Error: " + data, null);
}

/*
function DOM3K_showResults(data, timeout)

Shows a result in the results canvas (@id='DOM3K_DivResults').
|timeout| is the amount of milliseconds that the result must be shown,
if it is null the result is not hidden. Additionally, hides the
Error Div
*/

function DOM3K_showResults(data, timeout)
{
    DOM3K_updateElement(data, DOM3K_DivResults);
    DOM3K_DivResults.style.visibility = 'visible';
    DOM3K_DivErrors.style.visibility = 'hidden';
    if (timeout) {
        setTimeout("DOM3K_hideElement('DOM3K_DivResults')",timeout);
    }
}

/* 
function DOM3K_readInput(idTag, castFunction)
Reads the value of an 'input' element with id=|idTag| (id can be the real object too),
If |castFunction| is not null, it is used to change the value to a new type
*/
function DOM3K_readInput(idTag, castFunction)
{
    var elem = DOM3K_getElement(idTag);
    var val = elem.value;
    if (castFunction) {
        return castFunction(val);
    }
    return val;
}

/* 
function DOM3K_readElement(idTag, castFunction)
Reads the value of an element with id=|idTag| the value is the text data
inside the element. idTag can be the html object too.
If |castFunction| is not null, it is used to change the value to a new type
*/
function DOM3K_readElement(idTag, castFunction)
{
    var elem = DOM3K_getElement(idTag);
    if (castFunction) {
        return castFunction(elem.data);
    }
    return getTextData(elem);
}

/* 
function DOM3K_updateInput(data, idTag)

Update the value of an input element to |data|, the id of the input is
passed as |idTag|. idTag can be the html object too.
*/

function DOM3K_updateInput(data, idTag)
{
    var elem = DOM3K_getElement(idTag);
    if (data == null) data = "";
    elem.value = "" + data;
}

/*
function DOM3K_clearElement(idTag)

Removes all children of element idTag (idTag can be and HTML DOM element or the element's id)
Returns the DOM object represented by idTag
*/
function DOM3K_clearElement(idTag)
{
	var elem = DOM3K_getElement(idTag);
	while(elem.firstChild) {
		elem.removeChild(elem.firstChild);
	}
	return elem;
}

/* 
function DOM3K_updateElement(data, idTag)

Update the value of an element (innerHTML) to |data|, the id of the input is
passed with |idTag|. idTag can be html object too.
If data is an HTML DOM object it's supposed to be an element that must be placed
as unique child of idTag.

Returns the HTML DOM object of idTag
*/

function DOM3K_updateElement(data, idTag)
{
    return DOM3K_appendToElement(data, DOM3K_clearElement(idTag));
}
/* 
function DOM3K_appendToElement(data, idTag)

Appends data to |idTag|. idTag can be html object.
If data is an HTML DOM object it's appended to |idTag|, if data is text
we create a TextNode first and then is appended to |idTag|

Returns the HTML DOM of idTag
*/

function DOM3K_appendToElement(data, idTag)
{
    var elem = DOM3K_getElement(idTag);
    if (data == null) return elem;
    try {
	if (data.tagName) {
	    elem.appendChild(data);
	    return elem;
	}
    } catch(e) {
	alert(idTag + e);
    }
    var s = document.createElement('span'); 
    s.innerHTML = data;
    elem.appendChild(s);
    return elem;
}

/*
function DOM3K_createElement(initialelements, tagname)

Creates an HTML DOM Element of type |tagname|, and appends every element in the list initialelements. This initial elements could be plain text of DOM objects

Returns the new element
*/
function DOM3K_createElement(initialelements, tagname)
{
	var elem = document.createElement(tagname);
	if (initialelements == null) {
		return elem;
	}
	DOM3K_appendListToElement(initialelements, elem);
	return elem;
}


/*
function DOM3K_appendListToElement(list,idTag)

Appends a list of elements (or text labels)  to the element idTag (idTag can be an HTML DOM object)

Returns the HTML DOM element of idTag
*/
function DOM3K_appendListToElement(list,idTag)
{
	var elem = DOM3K_getElement(idTag);
	for (var l in list) {
		DOM3K_appendToElement(list[l],elem);
	}
	return elem;
}
/*
function DOM3K_selectedValue(idTag)

Retrieves the selected value in a select element with id |idTag|. idTag can be the html object too.
*/
function DOM3K_selectedValue(idTag)
{
    var elem = DOM3K_getElement(idTag);
    return elem.options[elem.selectedIndex].value;
}

/*
function DOM3K_selectAnItem(idTag,value, castOption)
Select an item from a select form which id is idTag. idTag can be the html object too.
The argument |value| must match with the internal value option. The internal option value
will be casted with castOption if castOption != null.

 */

function DOM3K_selectAnItem(idTag, value, castOption)
{
    var elem = DOM3K_getElement(idTag);
    for(var i=0; i<elem.options.length;i++) {
        var elemvalue = elem.options[i].value;
        if (castOption) elemvalue = castOption(elemvalue);
	if (elemvalue == value) {
	    elem.selectedIndex = i;
	}
    }
}

/*
function DOM3K_insertListOptions(list, idTag)

Insert list items in a select element with id |idTag|. idTag can be the html object too.
|list| is a list of pairs (name,value) to create options
*/
function DOM3K_insertListOptions(list, idTag)
{
    var elem = DOM3K_getElement(idTag);
    var opt;
    for (l in list) {
        opt = document.createElement("option");
        opt.setAttribute("value",list[l][0]);
        opt.appendChild(document.createTextNode(list[l][1]));
        elem.appendChild(opt);
    }
}

/*
function DOM3K_replaceListOptions(list, idTag)

As DOM3K_insertListOptions but replaces the actual list, preserving the selected item if
it's possible.
*/
function DOM3K_replaceListOptions(list, idTag)
{
    var elem = DOM3K_getElement(idTag);
    var index = elem.selectedIndex;
    var value;
    if (index >= 0) value = elem.value;
    DOM3K_clearElement(elem);
    DOM3K_insertListOptions(list, idTag);
    if (index > 0) elem.value = value;
    /*                                                                        
    var e = document.createEvent("MouseEvents");                              
    e.initMouseEvent('click', true, true, window,                             
                     0, 0, 0, 0, 0,                                           
                     false, false, false, false,                              
                     0, null);                                                
    var f = function () {                                                     
            x = elem.dispatchEvent(e);                                        
            }*                                                                
    setTimeout(f,2000);                                                       
    */

}

/*
function DOM3K_insertDictOptions(list, idTag)

Insert list items in a select element with id |idTag|. idTag can be the html object too.
|list| is a dictionary where pairs (name,value) are used to create options

*/
function DOM3K_insertDictOptions(list, idTag)
{
    var elem = DOM3K_getElement(idTag);
    var opt;
    for (l in list) {
        opt = document.createElement("option");
        opt.setAttribute("value",l);
        opt.appendChild(document.createTextNode(list[l]));
        elem.appendChild(opt);
    }
}

/*
function DOM3K_replaceDictOptions(list, idTag)

As DOM3K_insertDictOptions but replaces the actual list, preserving the selected item if
it's possible.
*/

function DOM3K_replaceDictOptions(list, idTag)
{
    var elem = DOM3K_getElement(idTag);
    var value;
    var index = elem.selectedIndex;
    if (index >= 0) value = elem.value;
    DOM3K_clearElement(elem);
    DOM3K_insertDictOptions(list, idTag);
    if (index > 0) elem.value = value;
}


/*

function DOM3K_listToTableHTML(list, style, castFunction, castargs, headers)
Alias: function DOM3K_listToTable

Creates a table from |list| javascript array, and puts |style|
as the style of the table.
|castFunction| is used to cast every cell to some value;
It is called as castFunction(list, row, column, castArguments)
where
    |list| is the list
    |row| the row number (as string, i think so)
    |column| the column number of the cell
    |castargs| Additional arguments to castFunction
    If castFunction throws an exception the cell is ignored
It returns the HTML code (no DOM)
*/

function __DOM3K_tableCastFunction(list, row, column, castargs)
{
    return list[row][column];
}

var __DOM3K_DefaultTableStyle = "";
function DOM3K_setDefaultTableStyle(style)
{
	__DOM3K_DefaultTableStyle = style;
}

function DOM3K_listToTableHTML(list, style, castFunction, castargs, headers)
{
    if (!style) style = __DOM3K_DefaultTableStyle;
    if (!castFunction) castFunction = __DOM3K_tableCastFunction;
    var table = document.createElement("table");
    var tbody = document.createElement("tbody");
    table.appendChild(tbody);
    var tr;
    var td;

    table.setAttribute("style",style);
    if (headers) {
	tr = document.createElement("tr");
	tbody.appendChild(tr);
	for (var h in headers) {
	    td = document.createElement("th");
	    tr.appendChild(td);
	    DOM3K_updateElement(headers[h], td);
	}
    }
    for (trlist in list) {
	tr = document.createElement("tr");
	tbody.appendChild(tr);
        for (tdlist in list[trlist]) {
	    td = document.createElement("td");
	    try {
		var res = castFunction(list, trlist, tdlist, castargs);
		DOM3K_updateElement(res, td);
		tr.appendChild(td);
	    } catch (e) {
		/*alert("ERROR:" + e);*/
		/* DOM3K_updateElement(e, td); */
		/* do something to help debugging applications */
	    }
	}
    }
    return table;
}

var DOM3K_listToTable = DOM3K_listToTableHTML;

/*
function DOM3K_insertTable(list, idTag)
Create the table and insert in the container with id = |idTag|
*/
function DOM3K_insertTable(list, idTag)
{
    DOM3K_updateElement(DOM3K_listToTableHTML(list), idTag);
}

/*
function DOM3K_replaceChild(idTag,new_child)

Replace the child which id is idTag with the new_child. idTag can be the html object too.
*/

function DOM3K_replaceChild(idTag,new_child)
{
    var old = DOM3K_getElement(idTag);
    var father = old.parentNode;
    father.replaceChild(new_child,old);
}

/*
function DOM3K_deleteElement(idTag)

Delete the element which id is idTag from the dom. idTag can be the html object too.
 */

function DOM3K_deleteElement(idTag)
{
    var element = DOM3K_getElement(idTag);
    var father = element.parentNode;
    father.removeChild(element);
}

/*
function DOM3K_putInfoToInput(list,noarg)

Receive a double list (i.e. [[name,value]] and 
put the value in the corresponding input
 */

function DOM3K_putInfoToInput(list,noarg)
{
    var element = document.getElementsByTagName("input");
    for(var i=0;i<element.length;i++){
	var name = element[i].name;
	for(var j=0;j<list.length;j++)
	    if(list[j][0] == name) element[i].value=list[j][1];
    }
}

/*
function DOM3K_putInfoToSelect(list,noarg)

Do the same work that DOM3K_putInfoToInput
but this method put the values in the corresponding select
 */

function DOM3K_putInfoToSelect(list,noarg)
{
    var element = document.getElementsByTagName("select");
    for(var i=0;i < element.length;i++){
	var name = element[i].name;
	for(var j=0;j<list.length;j++){
	    if(list[j][0] == name) DOM3K_selectAnItem(name,list[j][1]);
	}
    }
}

/*
function __DOM3K_set_pair(elem, dict)

Retrieves name, value from the input element |elem|
and put into dict

Depending of the values and properties of |elem| the
value can be casted or omited
*/
function __DOM3K_set_pair(elem, dict)
{
    try { /* The radio button is not ok*/
        var name = elem.getAttribute("name");
        if (name == null || name == '') return;
        var val = elem.value;
        var etype = elem.getAttribute("type");
        if (etype == 'int') {
            val = parseInt(val);
        } else if (etype == 'float') {
            val = parseFloat(val);
        } else if (etype == 'radio' || etype == 'checkbox') {
            if (!elem.checked) return;
        }
        dict[name] = val;
    } catch(error) {
        DOM3K_showError(error + ", "+ elem , 1000);
    }
}

/*
function DOM3K_formToDict(idTag)

Retrieves all fields of the form with id = |idTag|. idTag can be the html object too.
Returns a javascript dictionary. Its primary purpose is
to be used directly with SPyRO calls.

*/
function DOM3K_formToDict(idTag)
{
    var elemroot = DOM3K_getElement(idTag);
    var res = new Array();
    var inputs = elemroot.getElementsByTagName("input");
    for (var e = 0; e < inputs.length; e++) { 
        __DOM3K_set_pair(inputs.item(e), res);
    }
    var inputs = elemroot.getElementsByTagName("textarea");
    for (var e = 0; e < inputs.length; e++) {
        __DOM3K_set_pair(inputs.item(e), res);
    }
    var selects = elemroot.getElementsByTagName("select");
    for (var s = 0; s < selects.length; s++) {
        var selElem = selects.item(s);
        var name = selElem.getAttribute("name");
        if (name == '') continue;
        if (selElem.getAttribute("multiple")) {
            var ops = selElem.options; /*getElementsByTagName("option");*/
            var selArray = new Array();
            for (var o = 0; o < ops.length; o++) {
                var option = ops.item(o);
                /*hasAttribute("selected") does not work, maybe the DOM is not modified when the options is selected*/
                if (option.selected) {
                    selArray[selArray.length] = option.value;
                }
            }
            res[name] = selArray;
        } else {
            if (selElem.selectedIndex >= 0) {
                res[name] = selElem.options[selElem.selectedIndex].value;
            }
        }
    }
    /* alert(DOM3K_debugObject(res)); */
    return res;
}


/* function DOM3K_dictToForm(idTag, dict, splitname)

Fills the form |idTag| (can be the element id or the element itself) with
the given information dictionary |dict|.
If |splitname| is given, it must be a string or character to split the name of
elements. The first field of the splitted array will be used as name. If splitname
is null the name will not be splitted.
*/
function __DOM3K_populate_pair(elem, dict, splitname)
{
    try {
        var name = elem.getAttribute("name");
        if (splitname != null) {
                name = name.split(splitname)[0]
        }
        if (name == null || name == '') return;
        var tagName = elem.tagName.toLowerCase();
        var dictvalue = dict[name];

        if (tagName == 'input') {
                var type = elem.getAttribute('type');
                var value = elem.getAttribute("value");
                if (type == 'radio') {
                        elem.checked = (value == dictvalue);
                } else if (type == 'checkbox') {
                        elem.checked = (dictvalue != null);
                }
                elem.value = dictvalue;
        } else if (tagName == 'select') {
                /* Multiple selection is not supported yet */
                DOM3K_selectAnItem(elem, dictvalue);
        } else if (tagName == 'textarea') {
                elem.value = dictvalue;
        } else {
                DOM3K_showError("Unknown input " + elem.tagName + elem);
        }
    } catch(error) {
        DOM3K_showError(error + ", "+ elem , 1000);
    }
}

/* 
function DOM3K_dictToForm(dict, idTag, splitname)

Fills the the form |idTag| (where idTag can be the DOM object or the id of the element)
with the values of dict. If |splitname| is given, the names of the elements will be
splitted (with the string |splitname|) and the first element will be used as name
*/
function DOM3K_dictToForm(dict, idTag, splitname)
{
    var elemroot = DOM3K_getElement(idTag);
    var inputs = elemroot.getElementsByTagName("input");
    for (var e = 0; e < inputs.length; e++) {
        __DOM3K_populate_pair(inputs.item(e), dict, splitname);
    }
    var inputs = elemroot.getElementsByTagName("textarea");
    for (var e = 0; e < inputs.length; e++) {
        __DOM3K_populate_pair(inputs.item(e), dict, splitname);
    }
    var inputs = elemroot.getElementsByTagName("select");
    for (var e = 0; e < inputs.length; e++) {
        __DOM3K_populate_pair(inputs.item(e), dict, splitname);
    }
}

/*
function DOM3K_printById(idTag,windowname)

Prepare to print a selected element with id = |idTag|. idTag can be the html DOM object too.
|windowname| is optional and is a identifier to the popup printer window.
*/
function DOM3K_printById(idTag,windowname)
{
  if (!windowname) windowname = "DOM3K printing dialog";
  var seccion= DOM3K_getElement(idTag);
  var impresion = window.open(' ', windowname);
  impresion.document.write( seccion.innerHTML );
  impresion.document.close();
  impresion.print( );
  impresion.close();
}


/* 
function DOM3K_findNextInput(element)
 
 This function walks through the tree until it finds an input. 

function DOM3K_walkUntilElement(element)
 walk in the tree until it finds and element
 */

function DOM3K_findNextInput(element)
{
    var hermano = element.nextSibling;
    if (hermano) {
	var resultado = DOM3K_walkUntilElement(hermano);
	if (resultado) return resultado;
	return DOM3K_findNextInput(hermano);
    }
    var padre = element.parentNode;
    if(!padre) return null;
    return DOM3K_findNextInput(padre);
}

function DOM3K_walkUntilElement(element)
{
    if(element.hasAttributes()){
	if (element.hasAttribute("name") || element.hasAttribute("id")){
	    return element;
	}
    }		
    var sons = element.childNodes;
    for(var i=0;i<sons.length;i++){
	var resultado = DOM3K_walkUntilElement(sons[i]);
	if(resultado) return resultado;
    }
    return null;
}

/* Handler functions */

/*
function DOM3K_handlerArray(data, handlerarray)

This is a handler to call a set of handlers in an array |handlerarray| the position
is important, because the result of calling one method is passed to the next.
It can be viewed as a cascade of handlers.
 
*/

function DOM3K_handlerArray(data, handlers)
{
    var res = data;
    for (x in handlers) {
	var h = handlers[x];
	res = h(res);
    }
}

/*
  function DOM3K_handlerStringArray(data, stringhandlers)
  The same as DOM3K_handlerArray, but the handlerarray is passed as a string
  to be evaluated just like: "handler1,handler2,handler3".
*/

function DOM3K_handlerStringArray(data, stringhandlers)
{
    alert(eval(stringhandlers));
}

/*
function DOM3K_getCookieDict()

Returns a hash of cookies, only stores key and value
 */
function DOM3K_getCookieDict()
{
    var pairs = document.cookie.split(/;\s*/);
    var cookies = new Array();
    var values;
    var index;
    for (var x in pairs) {
        index = pairs[x].indexOf('=');
        cookies[pairs[x].substring(0,index)] = unescape(pairs[x].substring(index+1));
    }
    return cookies;
}

/*
function DOM3K_setCookie(name,value,expiressecondsfromnow,path)

Stores a cookie in the browser.

If |expiressecondsfromnow| is null it's set to 12 hours
If |path| is null, document.location.pathname is used

*/
function DOM3K_setCookie(name,value,expiressecondsfromnow,path,extra)
{
    if (expiressecondsfromnow== null) expiressecondsfromnow = 60 * 60 * 12;
    if (path == null) path = document.location.pathname;
    if (extra == null) {
        extra = '';
    } else {
        extra = "; " + extra;
    }
    var date = new Date();
    date.setTime(date.getTime() + expiressecondsfromnow * 1000);
    var cookie = name+'='+escape(value)+"; expires="+date.toGMTString()+"; path=" + path + extra;
    document.cookie = cookie;
}

/*
function DOM3K_getQueryDict()

Returns a dictionary of name and value passed in the query string part of the url
*/
function DOM3K_getQueryDict()
{
    var q = document.location.search.substring(1);
    var pairs = q.split('&');
    var qstring = new Array();
    var x;
    var key, data;
    var index;
    for (x in pairs) {
	try {
	    index = pairs[x].indexOf('=');
	} catch(e) {
	    alert(e);
	    continue;
	}
	key = pairs[x].substring(0,index);
	data = pairs[x].substring(index+1);
        /*alert("index:" + index +","+ key + "," + data);*/
	qstring[key] = data;
    }
    return qstring;
}


/* Default locale */
var __DOM3K_Locale = 'en';

/* locale data */
var __DOM3K_LocaleData = new Array();


/* function DOM3K_RegisterLocaleDictionary(newdict)

Register a new dictionary with language keys and a dictionary (keyname => translated_keyname) as a value.
For example

DOM3K_RegisterLocaleDictionary({
   'es' : {
      'talk_hello' : 'Hola',
      'talk_bye' : 'Hasta luego'
   },
   'en' : {
      'talk_hello' : 'Hello',
      'talk_bye' : 'See you later'
   }
})

The keynames must be self-scoped, in other words, the name must be different in different modules if they must be 
represented in different way. 

*/
function DOM3K_RegisterLocaleDictionary(newdict)
{
    for (var x in newdict) {
	if (__DOM3K_LocaleData[x] == null) {
	    __DOM3K_LocaleData[x] = newdict[x];
	} else {
	    var locale = __DOM3K_LocaleData[x];
	    var ndict = newdict[x];
	    for (var y in ndict) {
		locale[y] = ndict[y];
	    }
	}
    }
}

/* function DOM3K_SetLocale(language)

Sets the default locale to be used in DOM3K_GetLocale
*/
function DOM3K_SetLocale(language)
{
    __DOM3K_Locale = language;
}

/* function DOM3K_GetLocale(language=null)

Returns the complete locale dictionary for a language. If |language|
is not given the default locale will be used (See DOM3K_SetLocale).

*/
function DOM3K_GetLocale(language)
{
    if (language == null) language = __DOM3K_Locale;
    return __DOM3K_LocaleData[language];
}
