dataGridFieldFunctions = new Object()

dataGridFieldFunctions.removeFieldRow = function(node) {
    /* Remove the row in which the given node is found */
    
    var row = this.getParentElementById(node, 'datagridwidget-row')
    var tbody = this.getParentElementById(row, 'datagridwidget-tbody')
    tbody.removeChild(row);
}

dataGridFieldFunctions.getInputOrSelect = function(node) {
    /* Get the (first) input or select form element under the given node */
    
    var inputs = node.getElementsByTagName("input");
    if(inputs.length > 0) {
        return inputs[0];
    }
    
    var selects = node.getElementsByTagName("select");
    if(selects.length > 0) {
        return selects[0];
    }

    return null;
}

dataGridFieldFunctions.getWidgetRows = function(currnode) {
	/* Return primary <tr>s of current node's parent DGW */
	tbody = this.getParentElementById(currnode, "datagridwidget-tbody");
	return this.getRows(tbody);
}

dataGridFieldFunctions.getRows = function(tbody) {
	/* Return <tr> rows of <table> element */
    
	var rows = new Array()
	
	child = tbody.firstChild;
	while(child != null) {
		if(child.tagName != null) {
			if(child.tagName.toLowerCase() == "tr") {
				rows = rows.concat(child);
			}
		}
		child = child.nextSibling;
	}
	              
	return rows;   
}

dataGridFieldFunctions.addRowOnChange = function(e) {
    /* Add a new row when changing the last row 
    
       Check that if this onchange event handler was
       called from the last row. In this case,
       add a new row for DGF.
    */

    // XXX: Generalize window.event for windows
    // Grab current node, replicate, remove listener, append
    var currnode = window.event ? window.event.srcElement : e.currentTarget;

    // XXX Should add/remove event listeners via JS, but IE has
    // non-standard methods.  Not hard, but for now, just check 
    // if we are the last row.  If not, bail.

    var tbodyIdTag = "datagridwidget-tbody-";
    var tbody = this.getParentElementById(currnode, tbodyIdTag);    
    var rows = this.getWidgetRows(currnode);
    
    // the field name of this DGW
    var widgetId = tbody.id.substring(tbodyIdTag.length);   
    
    var tr = this.getParentElementById(currnode, "datagridwidget-row");      
    if(tr == null) {
    	// This is debug message. It's only seen
    	// if page templates have been screwed up
    	alert("Couldn't find DataGridWidget row.");
    	return;
    }
    
    // check if edit was performed on the last row           
    // and only then add a new row
    if(rows.length ==(tr.rowIndex)) {    	
    	this.addRow(widgetId);
    }
}

dataGridFieldFunctions.addRow = function(id) {
	/* Explitcly add row for given DataGridField 
	
		@param id Archetypes field id for the widget	
	*/
	
	// fetch required data structure
    var tbody = document.getElementById("datagridwidget-tbody-" + id);    
    var rows = this.getRows(tbody);    
    var lastRow = rows[rows.length-1]
                  
    // Create a new row
    var newtr = lastRow.cloneNode(true);
        
    // Turn on hidden button images for current node
    var imgs = lastRow.getElementsByTagName("img");
    for(var i=0; i<imgs.length; i++)
        imgs[i].style.display = "block";
                                                   
    // Clear content of newly created cells that were duplicated from 
    // the last cells
    cells = newtr.getElementsByTagName("td");
    for(var i=0; i<cells.length; i++) {
        
        td = cells[i];
        
        input = this.getInputOrSelect(td);
        if(input == null) 
            continue;

        input.value = ""
        
        if(input.getAttribute("checked")) {
        	input.removeAttribute("checked");
        }
    }
    
    // Put new row to DOM tree
    tbody.appendChild(newtr);
    
    this.updateOrderIndex(tbody)
}

dataGridFieldFunctions.getParentElement = function(currnode, tagname) {
    /* Find the first parent node with the given tag name */

    tagname = tagname.toUpperCase();
    var parent = currnode.parentNode;

    while(parent.tagName.toUpperCase() != tagname) {
        parent = parent.parentNode;
        // Next line is a safety belt
        if(parent.tagName.toUpperCase() == "BODY") 
            return null;
    }

    return parent;
}

dataGridFieldFunctions.getParentElementById = function(currnode, id) {
    /* Find the first parent node with the given id 
    
    	Id is partially matched: the beginning of
    	an element id matches parameter id string.
    
    	Currnode: Node where ascending in DOM tree beings
    	Id: Id string to look for. 
    	    	
    */
    
    id = id.toLowerCase();
    var parent = currnode.parentNode;

    while(true) {
       
    	var parentId = parent.getAttribute("id");
    	if(parentId != null) {    	
    		 if(parentId.toLowerCase().substring(0, id.length) == id) break;
    	}
    	    
        parent = parent.parentNode;
        // Next line is a safety belt
        if(parent.tagName.toUpperCase() == "BODY") 
            return null;
    }

    return parent;
}

dataGridFieldFunctions.moveRowDown = function(currnode){
    /* Move the given row down one */
           
    var tbody = this.getParentElementById(currnode, "datagridwidget-tbody");    
    
    var rows = this.getWidgetRows(currnode);
    
    var row = this.getParentElementById(currnode, "datagridwidget-row");      
    if(row == null) {
    	alert("Couldn't find DataGridWidget row");
    	return;
    }
    
    var idx = null
    
    // We can't use nextSibling because of blank text nodes in some browsers
    // Need to find the index of the row
    for(var t = 0; t < rows.length; t++) {
        if(rows[t] == row) {
            idx = t;
            break;
        }
    }

    // Abort if the current row wasn't found
    if(idx == null)
        return;     
        
    // If this was the last row (before the blank row at the end used to create
    // new rows), move to the top, else move down one.
    if(idx + 2 == rows.length) {
        var nextRow = rows.item[0]
        this.shiftRow(row, nextRow)
    } else {
        var nextRow = rows[idx+1]
        this.shiftRow(nextRow, row)
    }
    
    this.updateOrderIndex(tbody)

}

dataGridFieldFunctions.moveRowUp = function(currnode){
    /* Move the given row up one */
    
    var tbody = this.getParentElementById(currnode, "datagridwidget-tbody");    
    var rows = this.getWidgetRows(currnode);
    
    var row = this.getParentElementById(currnode, "datagridwidget-row");      
    if(row == null) {
    	alert("Couldn't find DataGridWidget row");
    	return;
    }

    var idx = null
    
    // We can't use nextSibling because of blank text nodes in some browsers
    // Need to find the index of the row
    for(var t = 0; t < rows.length; t++) {
        if(rows[t] == row) {
            idx = t;
            break;
        }
    }
    
    // Abort if the current row wasn't found
    if(idx == null)
        return;
        
    // If this was the first row, move to the end (i.e. before the blank row
    // at the end used to create new rows), else move up one
    if(idx == 0) {
        var previousRow = rows[rows.length - 1]
        this.shiftRow(row, previousRow)
    } else {
        var previousRow = rows[idx-1]
        this.shiftRow(row, previousRow)
    }
    
    this.updateOrderIndex(tbody)
}

dataGridFieldFunctions.shiftRow = function(bottom, top){
    /* Put node top before node bottom */
    
    bottom.parentNode.insertBefore(bottom, top)   
}

dataGridFieldFunctions.updateOrderIndex = function (tbody) {

    /* Update the hidden orderindex variables to be in the right order */
    
    var xre = new RegExp(/^orderindex__/)
    var idx = 0;
    var cell;
    
    for (var c = 0; (cell = tbody.getElementsByTagName('INPUT').item(c)); c++) {
            
        if (cell.getAttribute('id')) {
            if (xre.exec(cell.id)) {
                cell.value = idx;
            }
        }           
        this.updateRadioButtonGroupName(this.getParentElement(cell, "TR"), idx);        
        idx++;
    }      
}

dataGridFieldFunctions.updateRadioButtonGroupName = function (row, newIndex) {
	/* Adjust radio button group names after reordering 
	
	   Why we do this, see RadioColumn class comments
	   
	   TODO: If chain onchange -> updateOrderIndex -> updaterRadioButtonGroupName
	   is triggered on Firefox, the value of checked radio button is put to the
	   newly generated row instead of clicked row.
	*/

   var cell;
   var xre = new RegExp(/^radio/)
   
    for (var c = 0; (cell = row.getElementsByTagName('INPUT').item(c)); c++) {
   	    	    
   	   	if(cell.getAttribute('type')) {
   	   		var type = cell.getAttribute('type');
             if (xre.exec(type)) {          
            	
				var name = cell.getAttribute("NAME")
				if(name == null) continue;

				// save fieldId + columnId part
				var baseLabel = name.substring(0, name.lastIndexOf("."));				
				// update per row running id
				cell.setAttribute("NAME", baseLabel + "." + newIndex);
			}
   	    }               
	}
}
