I wonder if anyone can help. An HTML div in a page of mine contains a tree control which is shown or hidden depending upon a button pressed by a user. The button triggers an Ajax event which sets a variable on the server to show or hide the tree so that the state is persisted.
But here’s the problem; when the tree is re-displayed, the icons for expanding / collapsing brances are not present. So far, I’ve not been able to work out why this is the case.
The tree is shown below: the first graphic shows the tree as it should be, the second shows it after it has been hidden and re-displayed.
alt text http://www.dcs.bbk.ac.uk/~martin/Tree_with_icons.png alt text http://www.dcs.bbk.ac.uk/~martin/Tree_without_icons.png
The tree’s HTML is built on the server as a list and each list item has a class reference to CSS as follows:
ul.tree li.liOpen .bullet { background: url(myApp_Minus.png) center left no-repeat; cursor: pointer; } ul.tree li.liClosed .bullet { background: url(myApp_Plus.png) center left no-repeat; cursor: pointer; } ul.tree li.liBullet .bullet { background: url(myApp_Hyphen.png) center left no-repeat; cursor: pointer; }
Can anyone advise a method of showing the icons when the tree is re-displayed?
I’ve tried putting a link to the CSS file in the div, inline CSS elements and so on but without success.
Any help would be welcome.
I attach an extract of the tree’s HTML at runtime:
<td align = 'left'> <div id = 'tree'><ul class = 'tree' id = 'navTree'> <li class = 'liOpen'> <a href = '/myDataSharer/aboutConcept#communities'> <img alt = 'Community' src = '/myDataSharer/images/myDataSharer_Community_Small.png'> </a>  <a href = '/myDataSharer/commDashboard?CommNo=1&TagText='>Martin</a> <ul> <li class = 'liOpen'> <a href = '/myDataSharer/aboutConcept#datasets'> <img alt = 'Tabular dataset' src = '/myDataSharer/images/myDataSharer_TabularDataset_Small.png'> </a>  <a href = '/myDataSharer/displayDataset?DatasetNo=1&pageRowNo=0&TagText='>Planets</a> </li> <ul> <li> <a href = '/myDataSharer/aboutConcept#QAV'> <img alt = 'Visualisation' src = '/myDataSharer/images/myDataSharer_Visualisation_Small.png'> </a>  <a href = '/myDataSharer/displayQAV?QAVNo=109&TagText='>Test QAV</a> </li> <li> <a href
The tree itself is in a div called ‘tree’ which is updated from Javascript method as follows:
document.getElementById('tree').style.visibility = 'visible'; document.getElementById('tree').innerHTML = str;
The Javascript for the tree is:
/* WRITTEN BY: Martin O'Shea for myDataSharerAlpha. * * This program has been inherited verbatim from the original author's sample code as mentioned * below. No changes have been made other than a rename of a variable on line 121 from 'mktree' to 'tree'. * =================================================================== * Author: Matt Kruse <matt@mattkruse.com> * WWW: http://www.mattkruse.com/ * * NOTICE: You may use this code for any purpose, commercial or * private, without any further permission from the author. You may * remove this notice from your final code if you wish, however it is * appreciated by the author if at least my web site address is kept. * * You may *NOT* re-distribute this code in any way except through its * use. That means, you can include it in your product, or your web * site, or any other form where the code is actually being used. You * may not put the plain javascript up on your site for download or * include it in your javascript libraries for download. * If you wish to share this code with others, please just point them * to the URL instead. * Please DO NOT link directly to my .js files from your site. Copy * the files to your server and use them there. Thank you. * ===================================================================== * HISTORY * ------------------------------------------------------------------ * December 9, 2003: Added script to the Javascript Toolbox * December 10, 2003: Added the preProcessTrees variable to allow user * to turn off automatic conversion of UL's onLoad * March 1, 2004: Changed it so if a <li> has a class already attached * to it, that class won't be erased when initialized. This allows * you to set the state of the tree when painting the page simply * by setting some <li>'s class name as being 'liOpen' (see example) * * This code is inspired by and extended from Stuart Langridge's aqlist code: * http://www.kryogenix.org/code/browser/aqlists/ * Stuart Langridge, November 2002 * sil@kryogenix.org * Inspired by Aaron's labels.js (http://youngpup.net/demos/labels/) * and Dave Lindquist's menuDropDown.js (http://www.gazingus.org/dhtml/?id=109) */ // Automatically attach a listener to the window onload, to convert the trees addEvent(window,'load',convertTrees); // Utility function to add an event listener function addEvent(o,e,f){ if (o.addEventListener){ o.addEventListener(e,f,true); return true; } else if (o.attachEvent){ return o.attachEvent('on'+e,f); } else { return false; } } // utility function to set a global variable if it is not already set function setDefault(name,val) { if (typeof(window[name])=='undefined' || window[name]==null) { window[name]=val; } } // Full expands a tree with a given ID function expandTree(treeId) { var ul = document.getElementById(treeId); if (ul == null) { return false; } expandCollapseList(ul,nodeOpenClass); } // Fully collapses a tree with a given ID function collapseTree(treeId) { var ul = document.getElementById(treeId); if (ul == null) { return false; } expandCollapseList(ul,nodeClosedClass); } // Expands enough nodes to expose an LI with a given ID function expandToItem(treeId,itemId) { var ul = document.getElementById(treeId); if (ul == null) { return false; } var ret = expandCollapseList(ul,nodeOpenClass,itemId); if (ret) { var o = document.getElementById(itemId); if (o.scrollIntoView) { o.scrollIntoView(false); } } } // Performs 3 functions: // a) Expand all nodes // b) Collapse all nodes // c) Expand all nodes to reach a certain ID function expandCollapseList(ul,cName,itemId) { if (!ul.childNodes || ul.childNodes.length==0) { return false; } // Iterate LIs for (var itemi=0;itemi<ul.childNodes.length;itemi++) { var item = ul.childNodes[itemi]; if (itemId!=null && item.id==itemId) { return true; } if (item.nodeName == 'LI') { // Iterate things in this LI var subLists = false; for (var sitemi=0;sitemi<item.childNodes.length;sitemi++) { var sitem = item.childNodes[sitemi]; if (sitem.nodeName=='UL') { subLists = true; var ret = expandCollapseList(sitem,cName,itemId); if (itemId!=null && ret) { item.className=cName; return true; } } } if (subLists && itemId==null) { item.className = cName; } } } } // Search the document for UL elements with the correct CLASS name, then process them function convertTrees() { setDefault('treeClass','tree'); setDefault('nodeClosedClass','liClosed'); setDefault('nodeOpenClass','liOpen'); setDefault('nodeBulletClass','liBullet'); setDefault('nodeLinkClass','bullet'); setDefault('preProcessTrees',true); if (preProcessTrees) { if (!document.createElement) { return; } // Without createElement, we can't do anything uls = document.getElementsByTagName('ul'); for (var uli=0;uli<uls.length;uli++) { var ul=uls[uli]; if (ul.nodeName=='UL' && ul.className==treeClass) { processList(ul); } } } } // Process a UL tag and all its children, to convert to a tree function processList(ul) { if (!ul.childNodes || ul.childNodes.length==0) { return; } // Iterate LIs for (var itemi=0;itemi<ul.childNodes.length;itemi++) { var item = ul.childNodes[itemi]; if (item.nodeName == 'LI') { // Iterate things in this LI var subLists = false; for (var sitemi=0;sitemi<item.childNodes.length;sitemi++) { var sitem = item.childNodes[sitemi]; if (sitem.nodeName=='UL') { subLists = true; processList(sitem); } } var s= document.createElement('SPAN'); var t= '\u00A0'; // s.className = nodeLinkClass; if (subLists) { // This LI has UL's in it, so it's a +/- node if (item.className==null || item.className=='') { item.className = nodeClosedClass; } // If it's just text, make the text work as the link also if (item.firstChild.nodeName=='#text') { t = t+item.firstChild.nodeValue; item.removeChild(item.firstChild); } s.onclick = function () { this.parentNode.className = (this.parentNode.className==nodeOpenClass) ? nodeClosedClass : nodeOpenClass; return false; } } else { // No sublists, so it's just a bullet node item.className = nodeBulletClass; s.onclick = function () { return false; } } s.appendChild(document.createTextNode(t)); item.insertBefore(s,item.firstChild); } } }
Thanks.
The Ajax of the web page is shown below:
<script language='Javascript'> function xmlhttpPost(strURL) { var xmlHttpReq = false; var self = this; // Mozilla / Safari. if (window.XMLHttpRequest) { self.xmlHttpReq = new XMLHttpRequest(); } // IE. else if (window.ActiveXObject) { self.xmlHttpReq = new ActiveXObject('Microsoft.XMLHTTP'); } self.xmlHttpReq.open('POST', strURL, true); self.xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); self.xmlHttpReq.onreadystatechange = function() { if (self.xmlHttpReq.readyState == 4) { updatePage(self.xmlHttpReq.responseText); } } self.xmlHttpReq.send(getQueryStr()); } function getQueryStr() { queryStr = 'action=toggleTree'; return queryStr; } function updatePage(str) { if (str == 'false') { // Hide tree buttons and tree. document.getElementById('tree').style.visibility = 'hidden'; document.getElementById('expColTreeButtons').style.visibility = 'hidden'; } else { // Show tree buttons. document.getElementById('expColTreeButtons').style.visibility = 'visible'; // Show tree. document.getElementById('tree').style.visibility = 'visible'; document.getElementById('tree').innerHTML = str; } } function toggleTree() { // Make call to server to toggle tree. document.getElementById('tree').innerHTML = '<img src='/myDataSharer/images/myDataSharer_Wait.gif' alt='Growing tree' />' xmlhttpPost('/myDataSharer/toggleTree'); }
The Ajax above is triggered from a form which has three buttons. The ‘Show / hide’ button sees to things; the other two of the buttons are also enclosed within a div but they are alright.
<form> <input class = 'treeButton' type='submit' value='Show / hide' onClick = 'toggleTree(); return false;'> <div id = 'expColTreeButtons'> <input class = 'treeButton' type='submit' value='Expand all' onClick = 'expandTree('navTree'); return false;'> <br /> <input class = 'treeButton' type='submit' value='Collapse all' onClick = 'collapseTree('navTree'); return false;'> <br /> </div> </form>
This question has now resolved. Thanks those who contributed.
The solution was to re-process the Javascript tree after the div had been updated.