// IE doesn't provide Node.ELEMENT_NODE
var JSTREE_ELEMENT_NODE = 1;

// Toggle the jstree item with the given id
function jstreeToggle(id)
{
	var div, img;

	style = document.getElementById(id).style;
	img = document.getElementById(id + '_image');

	if (style.display == 'none')
	{
		style.display = 'block';
		img.src = '/wd-common/images/jstree-minus.gif';
	}
	else
	{
		style.display = 'none';
		img.src = '/wd-common/images/jstree-plus.gif';
	}
}

// Initialize a JsTree table from a pointer to the table's <tbody>.  This
// function needs to be called before any other.
//
// This code adds the following properties to each <tr> within the <tbody>:
//
// jstreeParent - The <tr> node that is the JsTree hierarchical parent, or null
// if this is a root.  If the parent is present, it will have a depth of 1 less
// than the current <tr>.
//
// jstreeNext - The next <tr>.  Useful since standards-compliant browsers
// insert TEXT_NODE's that we want to skip.  This is faster than looping every
// time we want the next child.
//
// jstreePrev - The previous <tr>.  (This isn't currently required, but I'd
// rather add it now while I'm still familiar with the code than have someone
// need it later and not have it.)
//
// jstreeDepth - The number of <td>s within this <tr>.  Currently, the root has
// a depth of 2 (1 for the +/-/blank and 1 for the label).  Each "child" in the
// tree will have a depth of +1 since the labels use colspans.
//
// jstreeDisplay - true if the <tr>'s JsTree children should be expanded.
// tr.jstreeParent.jstreeDisplay might differ from (tr.style.display != 'none')
// if the parent is also hidden.  This property is needed when expanding a row
// with children to know whether the child rows need to be expanded.
//
// jstreeLastContent - This is the last <td> of the <tr>.  If
// JsTree::drawTableRow() is not overriden, this will be the <td> containing
// the label.  Otherwise, <td>.jstreePrev can be used to walk backwards until
// the appropriate <td> is found.
//
// This code adds the following properties to each <td> within each <tr> within
// the <tbody>:
//
// jstreePrev - The previous <td>.  (See also <tr>.jstreeLastContent.)
function jstreeTableInit(tbody)
{
	var parents, nodes, i, len, depth, el, parent, prev;

	// Return if we've already initialized.
	if (tbody.jstreeInit)
		return;

	// A mapping from depth D to the most recently found <tr> at depth (D - 1).
	parents = [];

	nodes = tbody.childNodes;
	len = nodes.length;

	for (i = 0; i < len; i++)
	{
		tr = nodes[i];

		// Mozilla, at least, inserts TEXT_NODE's that must be skipped.
		if (tr.nodeType != JSTREE_ELEMENT_NODE)
			continue;

		depth = 0;
		// Determine the depth of this child by counting the number of td's it
		// contains.
		for (child = tr.firstChild; child; child = child.nextSibling)
			if (child.nodeType == JSTREE_ELEMENT_NODE)
			{
				depth++;

				// This will always point to the last content node.
				if (tr.jstreeLastContent)
					child.jstreePrev = tr.jstreeLastContent;
				tr.jstreeLastContent = child;
				
				// NOTE: There must not be TEXT_NODEs present.
				if ((el = child.firstChild)
					//&& el.tagName == 'A'
					//&& (el = el.firstChild)
					&& el.tagName == 'IMG')
						tr.jstreeImage = el;
			}

		tr.jstreeDepth = depth;

		// Set the current node as the parent for the next level deep.
		parents[depth + 1] = tr;

		// If this element has a parent and the parent hasn't had its "default
		// display" initialized, do that here.
		parent = tr.jstreeParent = parents[depth];
		if (parent && parent.jstreeDisplay !== null)
			parent.jstreeDisplay = tr.style.display != 'none';

		// Link the previous item.
		if (prev)
			prev.jstreeNext = tr;
		//tr.jstreePrev = prev;
		prev = tr;
	}

	tbody.jstreeInit = true;
}

// Iterate over all the deep child rows of a JsTree <tr>.  For each deep child,
// call the specified function, passing the child <tr>.
function jstreeTableForEachDeepChild(tr, func)
{
	var depth;

	jstreeTableInit(tr.parentNode);

	depth = tr.jstreeDepth;

	// Continue to process rows as long as the row has a depth greater than
	// the initial row.
	while ((tr = tr.jstreeNext) && tr.jstreeDepth > depth)
		func(tr);
}

// Toggle the given JsTree <tr>.
function jstreeTableToggle(tr)
{
	var hide;

	jstreeTableInit(tr.parentNode);

	if (tr.jstreeDisplay)
	{
		tr.jstreeDisplay = false;
		tr.jstreeImage.src = '/wd-common/images/jstree-plus.gif';
		hide = true;
	}
	else
	{
		tr.jstreeDisplay = true;
		tr.jstreeImage.src = '/wd-common/images/jstree-minus.gif';
	}

	jstreeTableForEachDeepChild(tr, function(tr)
	{
		var parent;

		if (hide)
			tr.style.display = 'none';
		else
		{
			// On a "restore", we only restore ourselves if the parent
			// "remembered" that we were previously restored AND the parent
			// itself is visible (its parent might be closed, too).

			parent = tr.jstreeParent;
			if (parent.jstreeDisplay && parent.style.display != 'none')
				tr.style.display = '';
		}
	});
}
