PDA

View Full Version : Smart Folding Menu Tree Script help



Lady_Aleena
04-26-2005, 01:44 AM
Original Script: Smart Folding Menu Tree Script (http://dynamicdrive.com/dynamicindex1/navigate1.htm)

I am trying to convert this script from using unordered lists to ordered lists. At first it looks simple, but the appearance I would like it to have is not.

With the ordered list, I would like just the list item to be changed, not the numeral proceeding it. So, with the default page color=#003, that is the color the numerals should be. One way that I came up with to get around that was to have the items with drop-down lists to have <span>s that changed color. The problem is that I don't know how to get the <span> to change color when it is selected.

The two colors I am using are:
unselected (folded):#390::selected (unfolded):#609

Here is the code so far:
CSS code
<style>
<!--
#foldheader{cursor:pointer;cursor:hand;}
#foldheader span {color:#390;}
#foldinglist{cursor:auto;font-weight:400;color:#003;}
//-->
</style>
JavaScript Code:
<script language="JavaScript1.2">
<!--

//Smart Folding Menu tree- By Dynamic Drive (rewritten 03/03/02)
//For full source code and more DHTML scripts, visit http://www.dynamicdrive.com
//This credit MUST stay intact for use

var head="display:''"

var ns6=document.getElementById&&!document.all
var ie4=document.all&&navigator.userAgent.indexOf("Opera")==-1

function checkcontained(e){
var iscontained=0
cur=ns6? e.target : event.srcElement
i=0
if (cur.id=="foldheader")
iscontained=1
else
while (ns6&&cur.parentNode||(ie4&&cur.parentElement)){
if (cur.id=="foldheader"||cur.id=="foldinglist"){
iscontained=(cur.id=="foldheader")? 1 : 0
break
}
cur=ns6? cur.parentNode : cur.parentElement
}

if (iscontained){
var foldercontent=ns6? cur.nextSibling.nextSibling : cur.all.tags("OL")[0]
if (foldercontent.style.display=="none"){
foldercontent.style.display=""
}
else{
foldercontent.style.display="none"
}
}
}

if (ie4||ns6)
document.onclick=checkcontained

//-->
</script>
Sample HTML code:
<ol>
<li id="foldheader"><span>Heading 1</span></li>
<ol id="foldinglist" style="display:none;" style="&{head};">
<li>Sub-heading 1a</li>
<li>Sub-heading 1b</li>
<li>Sub-heading 1c</li>
<li>Sub-heading 1d</li>
<li>Sub-heading 1e</li>
</ol>
Is this doable or easier to do some other way? Also, there may be submenues.

Another question, how many of those carriage returns can be safely removed?

jscheuer1
04-26-2005, 06:13 AM
To change a span's color on mouse over and return it to its default on mouse out:
<span onmouseOver="this.style.color='red'" onmouseOut="this.style.color=''">Howdy!</span>

Carriage returns? Which, where? If you mean in the HTML code, probably all of them.

Lady_Aleena
04-27-2005, 12:55 AM
In the original script, the list marker would change when the "folder" was opened and then back again when the "folder" was closed. To open and close the "folder," the user had to click on the item. Instead of having the images for markers, I have numbers. The number will not change on the opening and closing of the "folder," but the text will (I hope). Does that explain what I am trying to do better?

Also, how would I incorporate that mouseover information into the style or script so that I don't have to repeat that whole declaration on a lot of elements. Some of the lists will get pretty long, and I have a limited amount of space to use.

jscheuer1
04-27-2005, 04:09 AM
I'm looking alot more at your code. I've made a work up page of the snippets you provided. It strikes me that you probably don't want a onmouseOver/onmouseOut type event, but rather an onClick event. It would look like:


<span style="color:#390" onClick="(this.style.color=='#390')? this.style.color='#609':this.style.color='#390'">Heading 1</span>Unfortunately, I don't know of any way to condense that but, there might be a way using the parent/contained approach in the code. I'm just not that familiar with that approach yet.

Added later:

I think I have figured this parent/contained philosophy out enough to suggest this as your new 'checkcontained' function with all the other parts (rest of the script, style, HTML) from your original post remaining the same:


function checkcontained(e){
var iscontained=0
cur=ns6? e.target : event.srcElement
i=0
if (cur.id=="foldheader")
iscontained=1
else
while (ns6&&cur.parentNode||(ie4&&cur.parentElement)){
if (cur.id=="foldheader"||cur.id=="foldinglist"){
iscontained=(cur.id=="foldheader")? 1 : 0
break
}
cur=ns6? cur.parentNode : cur.parentElement
}

if (iscontained){
var folderspan=ns6? cur.getElementsByTagName('span')[0] : cur.all.tags("SPAN")[0]
var foldercontent=ns6? cur.nextSibling.nextSibling : cur.all.tags("OL")[0]
if (foldercontent.style.display=="none"){
foldercontent.style.display=""
folderspan.style.color="#609"
}
else{
foldercontent.style.display="none"
folderspan.style.color="#390"
}
}
}

jscheuer1
04-27-2005, 05:38 AM
I tested the above and it works fine. There is one problem that does not come from this new code though. It will not be a problem if you keep span tags out of all but the headers inside the first OL tag. This is only a problem in IE. What happens is that even though the id has changed and the LI tag has been closed, the second span (highlighted red) receives the style '#foldheader span {color:#390;}':


<ol>
<li id="foldheader"><span>Heading 1</span></li>
<ol id="foldinglist" style="display:none;" style="&{head};">
<li><span>Sub-heading 1a</span></li>
<li>Sub-heading 1b</li>
<li>Sub-heading 1c</li>
<li>Sub-heading 1d</li>
<li>Sub-heading 1e</li>
</ol>
</ol>This doesn't happen in Mozilla and can be avoided simply by only using the span element for the foldheaders. Spans outside the OL tag behave as expected. A remedy is to use '#hd {color:#390;}' instead and id only the spans you want to have this initial color.

Lady_Aleena
04-27-2005, 08:37 AM
If I understand what you are saying correctly, all the spans in the list will get the same color as the heading, even the ones that are unselected sub-lists. Is this correct?

I should have pointed out in my very first post, I have problems wrapping my mind around JavaScript. I just can't seem to understand the logic to building it.

jscheuer1
04-27-2005, 09:09 AM
Yes, and it has nothing to do with JavaScript, which you did a pretty good job of wrapping your mind around to come up with your original code modifications, which worked fine as far as they went. The problem I was referring to has to do with IE's inability to logically follow the cascading style. And as I noted, it will not be a problem if, within the bounds of the OL tags in your menu you only use the SPAN tag for headers, which seems to be the direction you were headed in anyway. I probably shouldn't have mentioned it unless it came up. There is another potential problem I noticed that will not be an issue under many normal page circumstances. The headers 'hover zones' extend all the way across the page. Again, not your fault, and currently is due to the fact that there is no containing element of a fixed width for the lists, I tried setting a width for the lists themselves but, once again, IE couldn't follow that logic, while Mozilla did. I have a solution if your finished page still exhibits this behavior. But, best to just go ahead and make a page, as the process of doing that has a good chance of taking care of it.

jscheuer1
04-27-2005, 09:18 AM
I thought a working demo might help, here is one with both of these potential problems solved:


<html>
<head>
<script type="text/javascript">

//Smart Folding Menu tree- By Dynamic Drive (rewritten 03/03/02)
//For full source code and more DHTML scripts, visit http://www.dynamicdrive.com
//This credit MUST stay intact for use

var head="display:''"

var ns6=document.getElementById&&!document.all
var ie4=document.all&&navigator.userAgent.indexOf("Opera")==-1

function checkcontained(e){
var iscontained=0
cur=ns6? e.target : event.srcElement
i=0
if (cur.id=="foldheader")
iscontained=1
else
while (ns6&&cur.parentNode||(ie4&&cur.parentElement)){
if (cur.id=="foldheader"||cur.id=="foldinglist"){
iscontained=(cur.id=="foldheader")? 1 : 0
break
}
cur=ns6? cur.parentNode : cur.parentElement
}

if (iscontained){
var folderspan=ns6? cur.getElementsByTagName('span')[0] : cur.all.tags("SPAN")[0]
//alert(folderspan)
var foldercontent=ns6? cur.nextSibling.nextSibling : cur.all.tags("OL")[0]
//alert(foldercontent)
if (foldercontent.style.display=="none"){
foldercontent.style.display=""
folderspan.style.color="#609"
}
else{
foldercontent.style.display="none"
folderspan.style.color="#390"
}
}
}

if (ie4||ns6)
document.onclick=checkcontained

</script>
<title>List Menu Demo</title>
<style type="text/css">

#foldheader{cursor:pointer;cursor:hand;width:75px!important;width:}
#hd {color:#390;}
#foldinglist{cursor:auto;font-weight:400;color:#003;}

</style>
</HEAD>
<BODY>
<div style=width:200px;margin-top:-5px>
<ol>
<li id="foldheader"><span id="hd">Heading 1</span></li>
<ol id="foldinglist" style="display:none;" style="&{head};">
<li>Sub-heading 1a</li>
<li>Sub-heading 1b</li>
<li>Sub-heading 1c</li>
<li>Sub-heading 1d</li>
<li>Sub-heading 1e</li>
</ol>


<li id="foldheader"><span id="hd">Heading 2</span></li>
<ol id="foldinglist" style="display:none;" style="&{head};">
<li><span>Sub-heading 2a</span></li>
<li>Sub-heading 2b</li>
<li>Sub-heading 2c</li>
<li>Sub-heading 2d</li>
<li>Sub-heading 2e</li>
</ol>
</ol>
</div>


</BODY></html>

Lady_Aleena
04-27-2005, 04:51 PM
I have come to the conclusion that I may need to start from scratch. This script would probably require a lot of retooling for my needs. All of the id attributes would have to be made class attributes for the page to be valid XHTML 1.0 Strict. The dual style attributes will need to be removed. I will be using a few ul elements along with the ol elements. I need to come up with an alternate way to do the spans to get things placed right. The script will have to be compressed as much as possible to save a little space. (If you see me around here a lot, you will notice that I am a person who tries to save as many bytes as possible.)As this stands right now, it will not validate as XHTML 1.0 Strict, which is my ultimate goal along with saving space.