/*
 * This script is writen by Michael Buckley.
 * Home page: http://codefisher.org/web_applications/accessibility/tree

 * The code contained in these files are licensed under the
 * Attribution-ShareAlike 3.0 Unported. 

 * Furthermore;
 * You may not claim the works as your own.
 * You must provide a link back to codefisher.org when using on a website.
 * You may not redistribute these as a package as-is..
 * You must seek approval for commercial purposes, and for applications. 
 * 
 * Please don't remove this from this file.
 * if you want to contact me please use my contact page
 * http://codefisher.org/email 
 *
 * If you modify this script please give me credit for the original script.
 *
 * Linking back to me should you use this script is appreicated and required
 */

var preload = new Array();

/* images to preload */

 preload[0] = '/images/webapps/tree/bar.gif';
 preload[1] = '/images/webapps/tree/blank.gif';
 preload[2] = '/images/webapps/tree/dot.gif';
 preload[3] = '/images/webapps/tree/file.png';
 preload[4] = '/images/webapps/tree/folder-closed.png';
 preload[5] = '/images/webapps/tree/folder-open.png';
 preload[6] = '/images/webapps/tree/twisty-clsd.png';
 preload[7] = '/images/webapps/tree/twisty-file.png';
 preload[8] = '/images/webapps/tree/twisty-open.png';


var treeObj = {twisty:null,innerDiv:null,barImage:null,iconImage:null}
var hiddenItems = new Array();

function initTree(treeId){ 

 var  tree  = document.getElementById(treeId);
tree.style.display = 'none';

setWairole(tree,0,false);

 tree.setAttribute('role','wairole:tree');
  setEventListener(tree,'keydown',treeKeyEvent,false);

 loadTree(tree);
setTimeout(doHidden,0); //make the page appear to finish loading, but still load hidden items
var nodes = tree.getElementsByTagName('li');
var i = 0;
 while(nodes[i] != null){
	if(i-1 < 0){
	  nodes[i].liPrev = null;
	} else {
	  nodes[i].liPrev = nodes[i-1];
	}
	if(nodes[i+1] != null){
	 nodes[i].liNext = nodes[i+1];
	} else {
	 nodes[i].liNext = null;
	}
  i++;
 } 
 tree.style.display = 'block';
}

function doHidden(){
var i = 0;
 while(hiddenItems[i]){
	setWairole(hiddenItems[i][0],hiddenItems[i][1],true);
    i++;
 }
}

function setWairole(treeSection,num,run){
 var treeChild = treeSection.childNodes;
 var i = treeChild.length-1;

 if(treeObj.innerDiv == null){
	treeObj.innerDiv = document.createElement('div');
 }
  var lastItem = null;
 while(treeChild[i]) {
  if(treeChild[i].nodeName.toLowerCase() == 'li'){
	setAaaAttri('level',treeChild[i],num);
	setEventListener(treeChild[i],'keydown',itemCollapseKey,false);
	setEventListener(treeChild[i],'click',itemClickEvent,false);
	setEventListener(treeChild[i],'dblclick',itemDblclickEvent,false);
	setEventListener(treeChild[i],'focus',itemFocusEvent,false);
	setEventListener(treeChild[i],'blur',itemBlurEvent,false);

	if(lastItem != null){
	  lastItem.liSibPrev = treeChild[i];
	treeChild[i].liSibNext = lastItem;
	}

	lastItem = treeChild[i];
	treeSection.firstLiChild = treeChild[i];
	if(treeSection.lastLiChild == null){
	  treeSection.lastLiChild = treeChild[i];
	}

	treeChild[i].setAttribute('selected',false);
	treeChild[i].setAttribute('role','wairole:treeitem');
	if(num == 0){
		treeChild[i].tabIndex = 0;
	} else {
		treeChild[i].tabIndex = -1;
	}
	var newDiv = treeObj.innerDiv.cloneNode(false);
	setClass(newDiv,'container');
	var garbage = treeObj.innerDiv.cloneNode(false);
	setClass(garbage,'garbage');

	treeChild[i].ul == null;
	var treeGroup = treeChild[i].childNodes;
   var j=0;
  while(treeGroup[j]) { 

  if(treeGroup[j].nodeName.toLowerCase() == 'ul'){
	treeChild[i].ul = treeGroup[j];
	treeGroup[j].setAttribute('role','wairole:group');
  } else {
	garbage.appendChild(treeGroup[j].cloneNode(true));
	treeChild[i].removeChild(treeGroup[j]);
	treeChild[i].divNode = treeChild[i].insertBefore(newDiv, treeChild[i].firstChild);
  }
  j++;
  }
	if(treeChild[i].className == "expand" ){
	    setExpandType(treeChild[i],true);
	 setWairole(treeChild[i].ul,num+1,false);
	} else {
	 setExpandType(treeChild[i],false);
	  if(treeChild[i].ul != null){
	    if(run == false){
		hiddenItems[hiddenItems.length] = new Array(treeChild[i].ul,num+1);
	    } else {
	 	setWairole(treeChild[i].ul,num+1,true);
	    }
	  }
	}

	displayTreeItem(treeChild[i],num);
	treeChild[i].divNode.appendChild(garbage);
 }
 i--;
 if(i == -1) {break;}
}

 // preload the images
 var image = document.createElement('img');
 image.style.display = 'none';
 var i = 0;
 while(preload[i]){
  var img = image.cloneNode(true);
  img.src = preload[i];
  document.body.appendChild(img);
  i++;
 }

}

function displayTreeItem(item,num){

	var barNode = treeObj.innerDiv.cloneNode(false);
	var z = 0;
	var higherNode = item.parentNode.parentNode;
	while(z<num){
	 var newBarNode = barNode.cloneNode(false);
	 setClass(newBarNode,'indent');
	 if(higherNode == higherNode.parentNode.lastLiChild){ 
		removeClass(newBarNode,'indent');
		setClass(newBarNode,'spacer-indent');
	 }
	 item.divNode.insertBefore(newBarNode,item.divNode.firstChild);
	 higherNode = higherNode.parentNode.parentNode;	
	 z++;
	}
	var newDiv = item.divNode.appendChild(barNode);
	setClass(newDiv,'indent');
	if(item == item.parentNode.lastLiChild){
		setClass(newDiv,'last-indent');
	}

	if(item.ul != null){
	if(treeObj.twisty == null){
	       var twistyNode = document.createElement('div');
		 setClass(twistyNode,'twisty');
		 treeObj.twisty = twistyNode;
		}
	  	item.twistyNode = item.divNode.appendChild(treeObj.twisty.cloneNode(false));
		setEventListener(item.twistyNode,'click',twistyToggle,false);
		 if(getExpandType(item) == true){
			setClass(item.twistyNode,'twisty-open');
		} else {
			setClass(item.twistyNode,'twisty-closed');
		 }

	}
	if(treeObj.barImage == null){
	 treeObj.barImage = document.createElement('div');
	 setClass(treeObj.barImage,'bar');
	}
       item.divNode.appendChild(treeObj.barImage.cloneNode(false));

	if(treeObj.iconImage == null){
	 treeObj.iconImage = document.createElement('div');
	 setClass(treeObj.iconImage,'icon');
	}
	var iconImage = treeObj.iconImage.cloneNode(false);

	if(item.ul != null){
	   if(getExpandType(item) == true){
		setClass(iconImage,'folder-open-icon');
	  }else {
		 setClass(iconImage,'folder-icon');
	 }
	}

	item.iconNode = item.divNode.appendChild(iconImage);

  return true;
}

function twistyToggle(event){
 if(event.srcElement){
  var item = event.srcElement.parentNode.parentNode;
 } else {
 var item = this.parentNode.parentNode; 
 }
 if(getExpandType(item) == true){
	setExpandType(item,false);
 } else {
	setExpandType(item,true);
  }

 loadTree(getTreeFromChild(item));

}


function loadTree(tree) {
 var x = 0;
 function crawl(tree){
 var nodes = tree.childNodes;
 var listItems = new Array();
 var j = 0; //build static list; 
 while(nodes[j] != null){
	listItems[j] = nodes[j];
	j++;
 }
 nodes = null; //drop var
 var i = 0;
 while(listItems[i]) {
 
  if(listItems[i].nodeName.toLowerCase() == 'li'){
	if(x%2 == 0){
	  removeClass(listItems[i],'even'); setClass(listItems[i],'odd');
	} else {
	  removeClass(listItems[i],'odd'); setClass(listItems[i],'even');
	}
	x++;
   }
  if(listItems[i].ul != null && getExpandType(listItems[i]) == true){
	crawl(listItems[i].ul);
  }
 i++;
 }
}
 if(tree.parentNode.className == 'treewrapper'){
  tree.style.width = tree.parentNode.scrollWidth+'px';
 }
crawl(tree);
}

function getTreeFromChild(item){
  while(item.parentNode != null){		
    var role = item.getAttribute('role');
     if(role == 'wairole:tree') {
	return item;
    } else {
	item = item.parentNode;
	}
  }
return false;
}

function itemCollapseKey(event) {
 if(event.srcElement){
  var item = event.srcElement;
 } else {
  var item = this;
 }
if(toBool(item.getAttribute('selected')) == true){
  var valueNow = getExpandType(item);
if (event.keyCode == 37 || event.keyCode == 39) {
 if(event.keyCode == 37){
  if(valueNow == true){
	setExpandType(item,false);
   } else {
	moveFocus(item,-1);
	 return noAction(event);
  }
} else if(event.keyCode == 39) {
  if(valueNow == false && item.ul != null){
	setExpandType(item,true);
   } else {
	moveFocus(item,1);
	 return noAction(event);
  }
}
 loadTree(getTreeFromChild(item));
  item.focus();
  return noAction(event);
 }
if(event.keyCode == 40) {
	moveFocus(item,1);
   return noAction(event);
 }
if(event.keyCode == 38) {
	moveFocus(item,-1);
   return noAction(event);
 }
}
return true;
}

function moveFocus(item,dir){
 if(dir == -1){
  if(item.liPrev == null){
   return false;
  }
  if(item.liPrev.clientHeight != 0){
   item.liPrev.focus();
   return false;
  } else {
   if(item.liSibPrev != null){
    item = item.liSibPrev.ul.lastLiChild;
    if(item.clientHeight != 0){
	item.focus();
        return false;
    } else {
     item = item.parentNode.parentNode;
     while(item != null){
      if(item != null){
       item.focus();
       return false;
      } else {
       item = item.parentNode.parentNode;
      }
     }
    }
   }
  }
 } else {
  if(item.liNext == null){
   return false;
  }
  if(item.liNext.offsetHeight != 0){
   item.liNext.focus();
   return false;
  } else {
   if(item.liSibNext != null){
    item.liSibNext.focus();
    return false;
   } else {
    item = item.parentNode.parentNode;
    while(item != null){
     if(item.liSibNext != null){
      item.liSibNext.focus();
      return false;
      item = null;
     } else {
      item = item.parentNode.parentNode;
     }
    }
   }
  }
 }
 return true;
}

function itemClickEvent(event) {
 if(event.srcElement){
  var item = event.srcElement;
   while(item.getAttribute('role') != 'wairole:treeitem' && item != null){
     item = item.parentNode;
   }
 } else {
  var item = this;
 }
 item.focus();
  try { 
   event.stopPropagation();
  } catch(e) {}
}

function itemFocusEvent(event){
 if(event.srcElement){
  var item = event.srcElement;
 } else {
  var item = this;
 }
  if(toBool(item.getAttribute('selected')) != true){ //prevent any loop that can cause the brower to crash
	item.setAttribute('selected',true);
	setClass(item,'focused');
	/* We set the focus on the link so pressing 
	 * enter will open it, other wise there is no 
	 * way to use the link in the keyboard, reason for the 
	 * above loop prevention, becuase focusing in a child 
	 * element puts focus on the parent again */
	function focusLink(item){
		var liChild = item.childNodes;
		var i = 0;
	    while(liChild[i]){
		var tag = liChild[i].nodeName.toLowerCase();
		if(tag == 'a'){
			//liChild[i].focus();
			return false;
		} else if(tag != 'ul') { //We don't want to check sub lists for links
			focusLink(liChild[i]);
		}
	    i++;
	  }
	    return true;
	}
	 focusLink(item);
      }
  return noAction(event);
}

function itemBlurEvent(event){
 if(event.srcElement){
  var item = event.srcElement;
 } else {
  var item = this;
 }
 item.setAttribute('selected',false);
 removeClass(item,'focused'); 
 return noAction(event)
}

function itemDblclickEvent(event){
if(event.srcElement){
 var item = event.srcElement;
} else {
 var item = this;
} 
 if(item.nodeName.toLowerCase() == 'div'){
	item = item.parentNode; //Fix IE problem
 }
  if(item.ul != null){ 
	 if(getExpandType(item) == true){
		setExpandType(item,false);
	} else { 
		setExpandType(item,true);
	}
   }
    loadTree(getTreeFromChild(item));
	return noAction(event)
}


function treeKeyEvent(event){
 if(event.srcElement){
  var item = event.srcElement;
 } else {
  var item = this;
 }
 if(event.charCode){
 var unicode = event.charCode 
  } else {
   var unicode = event.keyCode; 
  }
  var charString = String.fromCharCode(unicode).toLowerCase();

 if(unicode > 64 && unicode < 91){
 keyObj = {found:false}
 function crawl(tree){
 var listItems = tree.childNodes;
 var i = 0;
  while(listItems[i]) { 
   if(listItems[i].nodeName.toLowerCase() == 'li'){
	if(keyObj.found == true){
		var firstChar = trim(listItems[i].textContent).substr(0,1).toLowerCase(); 
		if(firstChar == ''){
			var firstChar = trim(listItems[i].innerText).substr(0,1).toLowerCase(); 	
		}
		if(firstChar == charString){
			listItems[i].focus();
			return true;
		}
	}
	if(toBool(listItems[i].getAttribute('selected')) == true){
		keyObj.found = true;
	}
	var list = listItems[i].childNodes;
	var j = 0;

	while(list[j]){
		if(list[j].nodeName.toLowerCase() == 'ul'){
		   if(getExpandType(listItems[i]) == true){
			if(crawl(list[j],keyObj.found) == true){
				return true;
			}
		   }
		}
	   j++;
	}	 
  }
 i++;
 }

 return false;
 }

 if(crawl(getTreeFromChild(item)) == false){
	keyObj.found = true;
	crawl(getTreeFromChild(item),true);
  }
 }
}


function trim(str){
   if(str != '' && str != null){
	str = str.replace(/^(\t*\n* *)*/,'');
	if(str != ''){ str = str.replace(/(\t*\n* *)*$/,''); }
   }
   if(str == null){
	str = ''; //easy point to catch an IE problem
   }
   return str;
}

function toBool(aBool){
 //change a bool string to a bool to help cross broser support
 if(aBool == 'true' || aBool == true){
  return true;
 }
 return false;
}

function getExpandType(item){
 if(item.getAttributeNS) {
   var aBool = item.getAttributeNS('http://www.w3.org/2005/07/aaa', "expanded");
  } else {
   var aBool = item.getAttribute("aaa:expanded");
  }
    return toBool(aBool);
}

function setExpandType(item,value){
 if(item.ul != null){
  if(value == true){
   item.ul.style.display = 'block';
  if(item.twistyNode){
   setClass(item.iconNode,'folder-open-icon');
   removeClass(item.iconNode,'folder-icon')
   setClass(item.twistyNode,'twisty-open');
   removeClass(item.twistyNode,'twisty-closed');
   }
  } else {
   item.ul.style.display = 'none';
  if(item.twistyNode){
   removeClass(item.iconNode,'folder-open-icon');
   setClass(item.iconNode,'folder-icon');
   removeClass(item.twistyNode,'twisty-open');
   setClass(item.twistyNode,'twisty-closed');
   }
  }
 }
 if(item.getAttributeNS) {
   return item.setAttributeNS('http://www.w3.org/2005/07/aaa', "expanded", value);
 } else {
  return item.setAttribute("aaa:expanded", value);
 }
}

function noAction(event){
 if(event.cancelBubble){
	 event.cancelBubble = true;
 } else {
  try { 
   event.stopPropagation();
  } catch(e) {}
 }
 return false;
}

function setEventListener(item,event,func,bool) {
 if(item.addEventListener){
	item.addEventListener(event,func,bool);
 } else {
	item.attachEvent('on'+event,func,bool);
 }
}

function setAaaAttri(aAttri,aElem,value){
 if(aElem.setAttributeNS) {
	aElem.setAttributeNS("http://www.w3.org/2005/07/aaa", aAttri, value);
 } else {
   aElem.setAttribute("aaa:" + aAttri, value);
 }
 return true;
}

function setClass(item,value){
if(value != null){
  var valueNow = item.className;
  item.className = valueNow + ' ' + value;
 }
}

function removeClass(item,value){
  var valueNow = item.className;
 var classReg = new RegExp(value,'gi');
 item.className = valueNow.replace(classReg,'');
}