
// $Id: $

// Note that for IE7 getElementTextNS dies if node has no content
// so if, for example, taxon has no common name, we set the value to '[none]'
// Note also that original Ajax code assumed IE6, wheres IE7 is different.


// global flag
var isIE = false;

// global request and XML document objects
var pygmyReq;


var childHeight = 12;
var maxListHeight = 100;

var currentNode;
var rootId = 1;

// Format taxon name
function formatTaxonName(name, rank)
{
	formatted_name = '';
	
	switch (rank)
	{
		case 'genus':
		case 'subspecies':
			formatted_name = '<i>' + name + '</i>';
			break;
			
		// Handle cases where species is undescribed
		case 'species':
			var spPattern = /^\w+\s+sp.\s+/;
			if (spPattern.test(name))
			{
				formatted_name = '<i>' + name.replace(' sp. ', '</i> sp. ');
			}
			else
			{
				formatted_name = '<i>' + name + '</i>';
			}
			break;

			
		default:
			formatted_name = name;
			break;
	}
	return formatted_name;
}

function setRootId(id)
{
	rootId = id;
}

// handle onreadystatechange event of req object
function processReqChange()
{
    // only if req shows "loaded"
    if (pygmyReq.readyState == 4) {
        // only if "OK"
        if (pygmyReq.status == 200) {
            displayNode(currentNode); // call our function to display node
         } else {
            alert("There was a problem retrieving the XML data:\n" +
                pygmyReq.statusText);
         }
    }
}

// Display node
function displayNode(nodeId)
{	
//	alert('displayNode');
	
	// Get info from XML document describing this node 
    var items = pygmyReq.responseXML.getElementsByTagName("node");
	var parentId = getElementTextNS("", "parentId", items[0], 0);
    var children = pygmyReq.responseXML.getElementsByTagName("child");


    // Get the node user clicked on
    var node = document.getElementById('node' + nodeId);

    // Parent node
    var	nodeParent = document.getElementById('node' + parentId);

    if (node == null)
    {
//		alert('node is null');
 

  	/* Node doesn't exist. Either
    	
    		1. User has selected the name of this node in the list of children
    		   of the current node. We now create this node.
    	  	
    	  	or
    	  	
    	  	2. We are intialising the control with a lineage
    	*/
     	
    	if (nodeParent != null)
    	{
//			alert('nodeParent is null');


			 node = document.createElement("div");
			
			// can't use setAttribute('class', '...') as this fails under IE6
			node.className = 'pygmy_node';
			node.setAttribute('id', 'node' + getElementTextNS("", "id", items[0], 0));
			
			nodeParent = document.getElementById('node' + parentId);
	
			// Delete the list of children currently being displayed
			list = document.getElementById('pygmy_list');
			nodeParent.removeChild(list);
	
			// Add node
			nodeParent.appendChild(node);
		}
		else
		{
			// Lineage (assumes that control is empty... )						
			parentId = rootId;
			add = false;
			var lineage = pygmyReq.responseXML.getElementsByTagName("lineage");
			for (var i = 0; i < lineage.length; i++)
			{
				

				var nId = getElementTextNS("", "id", lineage[i], 0);
				if (add)
				{			
					var count = getElementTextNS("", "count", lineage[i], 0);

					node = document.createElement("div");
					node.className = 'pygmy_node';
					node.setAttribute('id', 'node' + nId);
					var html = '<span class="pygmy_internal"'
						+ ' onclick="subtree(' + nId + ')"'
						+ ' ondblclick="nodeInfo(' + nId + ')"'
						+ '>';
			
					rank = getElementTextNS("", "rank", lineage[i], 0) ;
					
					html += formatTaxonName (getElementTextNS("", "name", lineage[i],0), rank);
						
					// common name
					var commonName = getElementTextNS("", "commonName", lineage[i], 0) ;
					if (commonName != '[none]')
					{
						html += '&nbsp;(' + commonName + ')';
					}

					if (count > 0)
					{
						html += '&nbsp;(' + count + ')';
					} 
											
					html += '</span>';
						
					node.innerHTML = html;
					nodeParent = document.getElementById('node' + parentId);
					nodeParent.appendChild(node);
				}
				parentId = nId;				
				if (!add)
				{
					add = (nId == rootId);
				}
			}
			parentId = rootId;
		}
    }
    else
    {
    	/* Node exists, so user has clicked on a node between the root
    	   and the current subtree.  */
    }


	if (children.length > 0)
	{
		// Node has children
		
		// Handle two different ways of representing root of tree
		// Root's parent is 0, or root's parent is itself.
		var spanClass = (parentId == 0) ? 'pygmy_root' : 'pygmy_internal';
		if (parentId == nodeId)
		{
			spanClass = 'pygmy_root';
		}
		var count = getElementTextNS("", "count", items[0], 0);
		
		var html  = '<span class="' + spanClass + '"'
		    + ' onclick="subtree(' + getElementTextNS("", "id", items[0], 0) + ')"'
		    + ' ondblclick="nodeInfo(' + getElementTextNS("", "id", items[0], 0) + ')"'
			+ '>';

		rank = getElementTextNS("", "rank", items[0], 0) ;
		html += formatTaxonName (getElementTextNS("", "name", items[0], 0), rank);
		
		// common name
		commonName = getElementTextNS("", "commonName", items[0], 0) ;
		
		if (commonName != '[none]')
		{
			html += '&nbsp;(' + commonName + ')';
		}

		if (count > 0)
		{
			html += '&nbsp;(' + count + ')';
		}
		
		html += '</span>';			
			
		node.innerHTML = html;
		
		objElement = document.createElement('div');
		objElement.className = 'pygmy_list';
		objElement.setAttribute('id', 'pygmy_list');
		
		node.appendChild(objElement);
	
		// List children of this node and display
		
		var h = 0;
		// loop through <child> elements		
		for (var i = 0; i < children.length; i++)
		{
			var spanClass = (i == children.length-1) ? 'pygmy_lastchild' : 'pygmy_child';
			var count = getElementTextNS("", "count", children[i], 0);

			if (count == 0)
			{
				spanClass += '_inactive';
			}

			var html = '<span class="' + spanClass + '"';
				
			if (count != 0)
			{
				html += ' onclick="subtree(' + getElementTextNS("", "id", children[i], 0) + ')"';
				html += ' ondblclick="nodeInfo(' + getElementTextNS("", "id", children[i], 0) + ')"';
			}
			html += '>';
			
			if (count > 9) { html += '<strong>'; }
			
			rank = getElementTextNS("", "rank", children[i], 0) ;
			html += formatTaxonName (getElementTextNS("", "name", children[i], 0), rank);
			
			// common name
			commonName = getElementTextNS("", "commonName", children[i], 0) ;
			if (commonName != '[none]')
			{
				html += '&nbsp;(' + commonName + ')';
			}
			
			if (count > 9) { html += '</strong>'; }
			
			
			if (count > 0)
			{
				html += '&nbsp;(' + count + ')';
			}
			html +=  '</span><br/>';
							
			objElement.innerHTML += html;
				
			h += childHeight;
		}
		/* For IE 6 */
		if (h > maxListHeight)
		{
			h = maxListHeight;
		}
		objElement.style.height = h + 'px';
		
		fadeUp(objElement,255,255,153);
		
    }
    else
    {
    	// Node is a leaf, so display this in a span of class pygmy_leaf(not clickable)
		var html = '<span class="pygmy_leaf">';
		
		rank = getElementTextNS("", "rank", items[0], 0) ;
		html += formatTaxonName (getElementTextNS("", "name", items[0], 0), rank);

		// common name
		commonName = getElementTextNS("", "commonName", items[0], 0) ;
		if (commonName != '[none]')
		{
			html += '&nbsp;(' + commonName + ')';
		}
			
			
		html += '</span>';

    	node.innerHTML = html;
    }

	document.getElementById('progress').style.display = 'none';

}


// retrieve XML document (reusable generic function);
// parameter is URL string (relative or complete) to
// an .xml file whose Content-Type is a valid XML
// type, such as text/xml; XML source must be from
// same domain as HTML file
function loadXMLDoc(url) {
    // branch for native XMLHttpRequest object

//	alert('loadXMLDoc');

    if (window.XMLHttpRequest) {
		// IE7 supports XMLHttpRequest
		//alert('loadXMLDoc');
	
        pygmyReq = new XMLHttpRequest();
        pygmyReq.onreadystatechange = processReqChange;
        pygmyReq.open("GET", url, true);
        pygmyReq.send(null);
    // branch for IE/Windows ActiveX version
    } else if (window.ActiveXObject) {
        isIE = true;
		//alert('2');


        pygmyReq = new ActiveXObject("Microsoft.XMLHTTP");
        if (pygmyReq) {
            pygmyReq.onreadystatechange = processReqChange;
            pygmyReq.open("GET", url, true);
            pygmyReq.send();
        }
    }
}


// retrieve text of an XML document element, including
// elements using namespaces
function getElementTextNS(prefix, local, parentElem, index) {
    var result = "";

    if (prefix && isIE) {
        // IE/Windows way of handling namespaces
        result = parentElem.getElementsByTagName(prefix + ":" + local)[index];
    } else {
        // the namespace versions of this method
        // (getElementsByTagNameNS()) operate
        // differently in Safari and Mozilla, but both
        // return value with just local name, provided
        // there aren't conflicts with non-namespace element
        // names
        result = parentElem.getElementsByTagName(local)[index];
    }
    if (result) {
        // get text, accounting for possible
        // whitespace (carriage return) text nodes
        if (result.childNodes.length > 1) {
            return result.childNodes[1].nodeValue;
        } else {
            return result.firstChild.nodeValue;    		
        }
    } else {
        return "";
    }
}


function fadeUp(element,red,green,blue) {
  if (element.fade) {
    clearTimeout(element.fade);
  }
  element.style.backgroundColor = "rgb("+red+","+green+","+blue+")";
  if (red == 255 && green == 255 && blue == 255) {
    return;
  }
  var newred = red + Math.ceil((255 - red)/10);
  var newgreen = green + Math.ceil((255 - green)/10);
  var newblue = blue + Math.ceil((255 - blue)/10);
  var repeat = function() {
    fadeUp(element,newred,newgreen,newblue)
  };
  element.fade = setTimeout(repeat,100);
}
