/*
	TableJacker
	Takes a TABLE with form elements and creates an expandable form array
	Requires table with single TBODY
	Uses TBODY elements to repeat
	(Or something to that effect)
*/

function TableJacker(instance,table,rowControls,message){
	var i, elements, cols, tr, td, a, span, controls;
	this.table = document.getElementById(table);
	this.firstBody = this.table.childNodes.length - 1;
	this.tbody = this.table.childNodes[this.firstBody].cloneNode(true);
	this.instanceName = instance;
	this.rowControls = rowControls == undefined ? false : rowControls;
	this.message = message == undefined ? false : message;
	this.defaults = false;
	this.onAdd = false;
	
	this.firstBody = this.table.childNodes.length - 1;
	
	// set up hidden table
	this.hiddenTable = document.createElement("table");
	this.hiddenTable.style.display = "none";
	this.table.parentNode.appendChild(this.hiddenTable);
	for(i = this.firstBody; i < this.table.childNodes.length; i++){
		this.table.removeChild(this.table.childNodes[i]);
	}
	this.hiddenTable.appendChild(this.tbody);
	
	// alter form element names
	elements = this.getFormElements(this.tbody);
	for(i = 0; i < elements.length; i++){
		elements[i].name += "[dummy]";
		elements[i].id += "[dummy]";
	}
	
	// calculate colspan
	cols = 0;
	for(i = 0; i < this.tbody.rows.length; i++){
		if(cols < this.tbody.rows[i].cells.length){
			cols = this.tbody.rows[i].cells.length;
		}
	}
	
	td = document.createElement("td");

	if(this.rowControls){
		// add row navigation TR
		tr = document.createElement("tr");
		td.colSpan = cols;
		tr.className = "controls";
	}else{
		td.className = "controls";
	}
	this.colSpan = cols;

	controls = new Array();
	controls[0] = new Array("addRow","Add Row");
	controls[1] = new Array("removeRow","Remove Row");
	controls[2] = new Array("moveRowUp","Move Row Up");
	controls[3] = new Array("moveRowDown","Move Row Down");

	for(i = 0; i < controls.length; i++){
		a = document.createElement("a");
		span = document.createElement("span");
		a.className = controls[i][0];
		a.href = "#";
		span.innerHTML = controls[i][1];
		a.appendChild(span);
		td.appendChild(a);
	}
	
	if (this.message)
	{
		msg = document.createElement("span");
		msg.innerHTML = "&nbsp;" + message;
		td.appendChild(msg);
	}
	
	if(this.rowControls){
		tr.appendChild(td);
		this.tbody.appendChild(tr);
	}else{
		this.tbody.childNodes[0].appendChild(td);
	}
}
TableJacker.prototype.table;
TableJacker.prototype.hiddenTable;
TableJacker.prototype.tbody;
TableJacker.prototype.instanceName;
TableJacker.prototype.rowControls;
TableJacker.prototype.colSpan;
TableJacker.prototype.defaults;
TableJacker.prototype.firstBody;
TableJacker.prototype.onAdd;

TableJacker.prototype.setDefaults = function(defaults){
	this.defaults = defaults;
}
TableJacker.prototype.getFormElements = function(el){
	var i, j, nodeName, list, childList;
	list = new Array();
	for(i = 0; i < el.childNodes.length; i++){
		nodeName = el.childNodes[i].nodeName.toLowerCase();
		if(nodeName == "input"
		|| nodeName == "select"
		|| nodeName == "textarea"){
			list[list.length] = el.childNodes[i];
		}
		else if(el.childNodes[i].childNodes.length > 0){
			childList = this.getFormElements(el.childNodes[i]);
			for(j = 0; j < childList.length; j++){
				list[list.length] = childList[j];
			}
		}
	}
	return list;
}
TableJacker.prototype.removeRow = function(rowIndex){
	if(this.table.childNodes.length > 1){
		this.table.removeChild(this.table.childNodes[rowIndex]);
	}
	this.refreshNames();
}
TableJacker.prototype.addRow = function(insertAfter){
	var insert = 0;
	tbody = this.tbody.cloneNode(true);
	if(insertAfter === false || this.table.childNodes.length==0 || insertAfter==(this.table.childNodes.length-1)){
		insert = this.table.childNodes.length;
		this.table.appendChild(tbody);
	}
	else{
		insert = insertAfter+1;
		this.table.insertBefore(tbody,this.table.childNodes[insertAfter+1]);
	}
	if(this.defaults != false){
		var elements = this.allElements(tbody,["input","select"]);
		for(var i = 0; i < elements.length; i++){
			elements[i].value = this.defaults[i];
		}
	}
	this.refreshNames();
	if(this.onAdd){
		this.onAdd(tbody,insert);
	}
}
TableJacker.prototype.allElements = function(el,tags,childNodes){
	if(!(childNodes instanceof Array)){
		childNodes = new Array();
	}
	var childNodes = new Array();
	for(var i = 0; i < el.childNodes.length; i++){
		var nodeName = el.childNodes[i].nodeName.toLowerCase();
		if(tags instanceof Array){
			var addNode = false;
			for(var j = 0; j < tags.length; j++){
				if(tags[j] == nodeName){
					addNode = true;
					break;
				}
			}
		}else addNode = true;
		if(addNode)childNodes[childNodes.length] = el.childNodes[i];
		if(el.childNodes[i].childNodes.length){
			childNodes = childNodes.concat(this.allElements(el.childNodes[i],tags,childNodes));
		}
	}
	return childNodes;
}
TableJacker.prototype.moveRowUp = function(rowIndex){
	tbody = this.table.childNodes[rowIndex];
	this.table.removeChild(tbody);
	if(rowIndex <= this.firstBody){
		this.table.appendChild(tbody);
	}else{
		this.table.insertBefore(tbody,this.table.childNodes[rowIndex-1]);
	}
	this.refreshNames();
}
TableJacker.prototype.moveRowDown = function(rowIndex){
	tbody = this.table.childNodes[rowIndex];
	this.table.removeChild(tbody);
	if(rowIndex == this.table.childNodes.length){
		this.table.insertBefore(tbody,this.table.childNodes[this.firstBody]);
	}else{
		if((rowIndex+1) >= this.table.childNodes.length){
			this.table.appendChild(tbody);
		}
		else{
			this.table.insertBefore(tbody,this.table.childNodes[rowIndex+1]);
		}
	}
	this.refreshNames();
}
TableJacker.prototype.refreshNames = function(){
	var elements, i, j;
	
	for(i = this.firstBody; i < this.table.childNodes.length; i++){	
		elements = this.getFormElements(this.table.childNodes[i]);
		for(j = 0; j < elements.length; j++){
			elements[j].name = elements[j].name.replace(/(.*?)\[([0-9]+|dummy)\]$/,"$1") + "["+i+"]";
			elements[j].id = elements[j].id.replace(/(.*?)\[([0-9]+|dummy)\]$/,"$1") + "["+i+"]";
		}
		//.onclick = new Function(this.instanceName+".addRow("+i+",false);return false;");

		this.table.childNodes[i].className = (i%2==0) ? "even" : "odd";
		if(this.rowControls){
			this.table.childNodes[i].rows[this.table.childNodes[i].rows.length-1].childNodes[0].childNodes[0].onclick = new Function(this.instanceName+".addRow("+i+");return false;");
			this.table.childNodes[i].rows[this.table.childNodes[i].rows.length-1].childNodes[0].childNodes[1].onclick = new Function(this.instanceName+".removeRow("+i+");return false;");
			this.table.childNodes[i].rows[this.table.childNodes[i].rows.length-1].childNodes[0].childNodes[2].onclick = new Function(this.instanceName+".moveRowUp("+i+");return false;");
			this.table.childNodes[i].rows[this.table.childNodes[i].rows.length-1].childNodes[0].childNodes[3].onclick = new Function(this.instanceName+".moveRowDown("+i+");return false;");
		}else{
			this.table.childNodes[i].rows[0].childNodes[this.colSpan].childNodes[0].onclick = new Function(this.instanceName+".addRow("+i+");return false;");
			this.table.childNodes[i].rows[0].childNodes[this.colSpan].childNodes[1].onclick = new Function(this.instanceName+".removeRow("+i+");return false;");
			this.table.childNodes[i].rows[0].childNodes[this.colSpan].childNodes[2].onclick = new Function(this.instanceName+".moveRowUp("+i+");return false;");
			this.table.childNodes[i].rows[0].childNodes[this.colSpan].childNodes[3].onclick = new Function(this.instanceName+".moveRowDown("+i+");return false;");
		}
		
	}
	
}
TableJacker.prototype.addValues = function(values){
	var i, j,  tbody;
	for(i = 0; i < values.length; i++){
		tbody = this.tbody.cloneNode(true);
		elements = this.getFormElements(tbody);
		for(j = 0; j < values[i].length; j++){
			if(j < elements.length){
				elements[j].value = values[i][j];
			}
		}
		this.table.appendChild(tbody);
		this.refreshNames();
		if(this.onAdd){
			this.onAdd(tbody,i);
		}
	}
}
TableJacker.prototype.setValues = function(values){
	while(this.table.childNodes.length > this.firstBody){
		this.table.removeChild(this.table.childNodes[this.firstBody]);
	}
	this.addValues(values);
}
