text: /*
  
    == PHP FILE TREE JAVASCRIPT EXTENSION ==
    
    Based on the Expandable Listmenu Script by Daniel Nolan
    http://www.bleedingego.co.uk/webdev.php
    
    Modified by Cory S.N. LaViska
    http://abeautifulsite.net/
    
    == WHAT IT DOES ==
    
    This script makes the nested lists created by PHP File Tree expand and 
    collapse dynamically.
    
    == USAGE ==
    
    Include the script into the <head></head> section of the appropriate 
    page(s) as shown below:
    
    <script src="php_file_tree.js" type="text/javascript"></script>
    
    All file trees generated by PHP File Tree will automatically collapse to 
    the top level (as specified by $directory) and become dynamic.
  
    == FAQS ==
    
    Q Can I have more than one file tree on one page?
    A Yes.  You can have as many as you want and they will all function as expected.
    
  */
  
  function init_php_file_tree() {
      if (!document.getElementsByTagName) {
          return;
      }
      var aMenus = document.getElementsByTagName("LI");
      for (var i = 0; i < aMenus.length; i++) {
  	var mclass = aMenus[i].className;
  	if (mclass.indexOf("pft-directory") > -1) {
  	    var submenu = aMenus[i].childNodes;
  	    for (var j = 0; j < submenu.length; j++) {
  		if (submenu[j].tagName == "A" && submenu[j].className == "toggle") {
                      //submenu[j].onclick = toggleDir();// doesn't work
  		    submenu[j].onclick = function() {             // here's where we inject the open/close onclick() functionality
  			var node = this.nextSibling;			
  			while (1) {
  			    if (node != null) {
  				if (node.tagName == "UL") {
  				    var d = (node.style.display == "none")
  				    node.style.display = (d) ? "block" : "none";
  				    this.className = (d) ? "open" : "closed";
  				    return false;
  				}
  				node = node.nextSibling;
  			    } else {
  				return false;
  			    }
  			}
  			return false;
  		    }
  		    submenu[j].className = (mclass.indexOf("open") > -1) ? "open" : "closed";
  		}
  		if (submenu[j].tagName == "UL")
  		    submenu[j].style.display = (mclass.indexOf("open") > -1) ? "block" : "none";
  	    }
  	}
      }
      return false;
  }
  
  
  
  
  //open url in iframe 'iFrameID'
  //TODO expand/highlight the directory in which the document resides 
  function openInContentFrame(url) {
      document.getElementById('contentFrame').src=url;
  }
  
  function getFoundCountDiv() {
      return document.querySelectorAll("div#foundCountDiv")[0];
  }
  
  function clearFoundCount() {
      getFoundCountDiv().innerText="" ;
  }
  
  function setFoundCount(n) {
      getFoundCountDiv().innerText=("Found " + n);
  }
  
  function findButtonClick() {
      collapseAllDirs(getDirs((getIndexFrame())));
      //unhighlightAllDirs(getDirs((getIndexFrame()))); // for whatever reason, this doesn't work
      unhighlightAllDirs(findDirByName(""));
      clearFoundCount();
      let searchTerm = document.getElementById("searchTextField").value;
      if (searchTerm.trim().length>0) {
          let dirs = findDirByName(searchTerm);
          setFoundCount(dirs.length);
          hideAllDirs(getDirs((getIndexFrame())));
          for (let i=dirs.length-1; i > -1; i--) {
              //expandDirAndParents(dirs[i]);
              expandDirAndParents1(dirs[i]);
              highlightDir(dirs[i]);
          }
      }
  }
  
  function resetButtonClick() {
      expandAllDirs(getDirs((getIndexFrame())));
      collapseAllDirs(getDirs((getIndexFrame())));
      unhighlightAllDirs(getDirs((getIndexFrame())));
      clearSearchField();
      clearFoundCount();
  }
  
  function expandAllButtonClick() {
      expandAllDirs(getDirs((getIndexFrame())));
  }
  
  function collapseAllButtonClick() {
       collapseAllDirs(getDirs((getIndexFrame())));
  }
  
  function clearSearchField() {
      document.getElementById("searchTextField").value="";
  }
  
  function highlightDir(dir) {
      dir.style.backgroundColor="orange";
  }
  
  //TODO  can we rewrite this to use querySelectorAll() ?
  function findDirByName(searchStr) {
      //console.log("searching for " + searchStr);//DEBUG
      getFoundCountDiv().innerText=("searching for " + searchStr);
      return $("iframe#indexFrame").contents().find(`a:contains("${searchStr}")`);
  }
  
  // TODO not sure this is working
  function walkUpParentTree(node, aFunc) {
      if(node!==undefined) {
          aFunc(node);
          if ((node.classList !== undefined) && (node.classList.length > 0) && (node.classList[0]!=="php-file-tree")) {   
              walkUpParentTree(node.parentElement, aFunc);
          }
      }
  }
  
  //TODO this works, but is not sufficiently generalized
  function expandDirAndParents1(dir) {
      if(dir!==undefined) {
          expandDir(dir);        
          if (dir.classList[0]!=="php-file-tree") {   
              expandDirAndParents1(dir.parentElement);
          }
      }
  }
  
  
  function expandDir(dir) {    
      //console.log("expandDir(" + dir + ") - setting display attribute to 'block'");//DEBUG
      dir.style="display: block;";
  }
  
  
  //TODO not really working correctly
  function generalizedExpandDirAndParents(dir) {
      //console.log("generalizedExpandDirAndParents(" + dir + ")");//DEBUG    
      walkUpParentTree(dir, expandDir);
  }
  
  // returns a reference to the indexFrame iFrame
  function getIndexFrame() {
      return document.querySelectorAll('iframe#indexFrame')[0];
  }
  
  // returns an array of ul nodes residing within the iFrame
  function getDirs(iFrame) {
     return iFrame.contentWindow.document.body.querySelectorAll('ul')
  }
  
  
  // example usage: expandAllDirs(getDirs((getIndexFrame())));
  function expandAllDirs(dirs) {
      dirs.forEach( item => { expandDir(item);} );
  }
  
  // example usage: collapseAllDirs(getDirs((getIndexFrame())));
  function collapseAllDirs(dirs) {
      if(dirs!==undefined) {
          for (let i=0; i < dirs.length; i++) {        
              if( dirs[i].classList[0]!=="php-file-tree")  {
                  dirs[i].style="display: none;";
              }
          }
      }
  }
  
  // example usage: hideAllDirs(getDirs((getIndexFrame())));
  function hideAllDirs(dirs) {
      if(dirs!==undefined) {
          for (let i=0; i < dirs.length; i++) {        
              dirs[i].style="display: none;";
          }
      }
  }
  
  // example usage: unhighlightAllDirs(getDirs((getIndexFrame())));
  function unhighlightAllDirs(dirs) {
     if(dirs!==undefined) {
          for (let i=0; i < dirs.length; i++) {        
              dirs[i].style.backgroundColor="white"; // "none" would be better
          }
      }
  }
  
  /*
  // case insensitive search
  jQuery.expr[':'].icontains = function(a, i, m) {
    return jQuery(a).text().toUpperCase()
        .indexOf(m[3].toUpperCase()) >= 0;
  };
  */
  
  
  
  function include(file) { 
    
    var script  = document.createElement('script'); 
    script.src  = file; 
    script.type = 'text/javascript'; 
    script.defer = true; 
    
    document.getElementsByTagName('head').item(0).appendChild(script); 
    
  } 
    
  
  include('/libnav/js/jquery-3.5.1.min.js'); 
  
  window.onload = init_php_file_tree;
  