function displayNode(row)
{
	text = '';

	for (n in row.childNodes) {
		text += n + '\t';
		n = row.childNodes[n];
		switch(n.nodeType) {
		case 1:
			text += n.className + '\t';
		case 2:
		case 3:
			text += n.nodeType + '\t' +
			    + n.nodeName + '\t'
			    + n.data + '\t'
			    + n.nodeValue;
			break;
		case undefined:
			break;
		}
		text += '\n';
	}
	alert(text);
	return true;
}

function childByAttribute(node, attr, val)
{
	for (child in node.childNodes) {
		child = node.childNodes[child];
		if (child.nodeType != 1)
			continue;
		if (attr == 'CLASS') {
			if (child.className == val)
				return child;
		} else if (child.getAttribute(attr) == val)
			return child;
	}
	return null;
}

function uncheck(row)
{
	checkbox = childByAttribute(row, 'CLASS', 'included');
	if (checkbox == '')
		return false;
	checkbox = checkbox.firstChild;
	checkbox.checked = false;
	return false;
}

var bgcolors = new Array();

function restoreBG()
{
	while (bgcolors.length) {
		bgcolors[0].td.style.backgroundColor = bgcolors[0].color;
		bgcolors.shift();
	}
}

function flash(td, color)
{
	var slot;
	/* See if this element is already flashing */
	for (slot = 0; slot < bgcolors.length; slot++)
		if (bgcolors[slot].td == td)
			return;

	/* Ok, record its current color and set it to red for a second */
	bgcolors[slot] = new Object();
	bgcolors[slot].td = td;
	bgcolors[slot].color = td.style.backgroundColor;
	td.style.backgroundColor = color;
	setTimeout("restoreBG()", 300);
	return false;
}

var sname_re = new RegExp("^[A-z_][A-z_0-9]*$");
function trim(str)
{
	return str.replace(/^\s*(\S*)\s*$/, '$1');
}
	
/*
 * Updates the form and its fields from the currently displayed table
 * data. The function is invoked whenever a raw is added or deleted.
 * It assumes:
 *	. the rows are sequentionally numbered, starting from 0, which
 *	  is a template;
 *	. the fields' NAMEs are the same as the table cell's CLASSes plus
 *	  the row's number
 */
function table2form(table)
{
	for (index = 1; index < table.childNodes.length - 1; index++) {
		row = table.childNodes[index];
		if (row.nodeType != 1)
			continue;

		if (index % 2)
			row.className = 'odd';
		else
			row.className = 'even';

		for (cell in row.childNodes) {
			cell = row.childNodes[cell];
			if (cell.nodeType != 1) continue;
			if (cell.className == 'counter') {
				cell.firstChild.data = index;
				continue;
			}
			cell.firstChild.name = cell.className + index;
		}
	}
	table.lastChild.lastChild.firstChild.data = '$' +
	    (index-1) * LicensePrice;
}

function addrow(row)
{
	var table = row.parentNode;
	newrow = row.cloneNode(true); /* deep copy */

	/*
	 * Copy the selected platform from the row0
	 * and reset the row0 afterwards...
	 */
	platform = childByAttribute(row, 'CLASS', 'platform');
	newplatform = childByAttribute(newrow, 'CLASS', 'platform');
	newplatform.firstChild.selectedIndex =
	    platform.firstChild.selectedIndex;
/* Do not reset for now...
	platform.firstChild.selectedIndex = 0;
---- */

	newcheckbox = childByAttribute(newrow, 'CLASS', 'included');
	checkbox = childByAttribute(row, 'CLASS', 'included');
	newcheckbox.firstChild.checked = true;
	checkbox.firstChild.checked = false;
	/* checkbox.firstChild.disabled = true; */

	newsname = childByAttribute(newrow, 'CLASS', 'sname');
	sname = childByAttribute(row, 'CLASS', 'sname');
	newsname.firstChild.value = sname.firstChild.value;
	sname.firstChild.value = 'Another one?';

	table.insertBefore(newrow, table.lastChild);
	table2form(table);
}

function deleterow(row)
{
	table = row.parentNode;
	if (row == table.firstChild)
		return;

	table.removeChild(row);
	table2form(table);
}

var clicked=false;

function checktotal()
{
	/*
	 * Getting to a table's first row is non-trivial, because
	 * different browsers number the table's children differently.
	 * Mozilla always inserts implicit thead and tbody, while
	 * Opera does not...
	 * So we start with the total's TD, which we can get by ID
	 * and work our way up.
	 */
	var total_td = document.getElementById('total');

	/*
	 * "clicked" is set, when the user clicks on the submit button,
	 * as opposite to pressing Enter on the keyboard
	 */
	if (!clicked) {
		var toprow = total_td.parentNode.parentNode.firstChild;

		if (encourage(toprow))
			return false;
	}

	clicked = false;

	var total = total_td.lastChild.data.substring(1);
	if (total > 0)
		return true;
	flash(total_td, 'orange');
	return false;

}

function encourage(row)
{
	var platform = childByAttribute(row, 'CLASS', 'platform');
	platform = platform.firstChild;
	platform = platform[platform.selectedIndex].value;
	if (platform == 'empty')
		return false;

	var sname = childByAttribute(row, 'CLASS', 'sname');
	sname = sname.firstChild.value;
	if (sname_re.exec(sname) == null)
		return false;

	var checkbox = childByAttribute(row, 'CLASS', 'included');
	flash(checkbox, 'green');
	return true;
}
	
function checkrow(checkbox)
{
	var row = checkbox.parentNode.parentNode;
	var platform_td = childByAttribute(row, 'CLASS', 'platform');
	if (platform_td == '')
		return false;
	platform = platform_td.firstChild;
	platform = platform[platform.selectedIndex].value;

	if (platform == 'empty') {
		flash(platform_td, 'red');
		checkbox.checked = false;
		return false;
	}
	sname_td = childByAttribute(row, 'CLASS', 'sname');
	if (sname_td == '')
		return false; /* XXX Should never happen! */

	sname = sname_td.firstChild.value;
	if (sname_re.exec(sname) == null) {
		flash(sname_td, 'red');
		checkbox.checked = false;
		return false;
	}

	if (checkbox.checked) {
	/*
		alert('License for Sybase server ' + sname
		    + '\nrunning on "' + platform
		    + '"\nadded to your list');
	*/
		addrow(row);
	} else {
		if (!confirm('Delete license for ' + sname +
		    ' from your list?'))
			checkbox.checked = true;
		else
			deleterow(row);
	}
	return true;
}

function helpreset(form)
{
	table = childByAttribute(form, 'NAME', 'Licenses');
	alert('Table has ' + table.childNodes.length + 'rows');
	for (index = 1; index < table.childNodes.length - 1; index++)
		table.removeChild(table.childNodes[index]);
	form.reset();
}

