Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 14 of 14
  1. #1
    Senior Coder
    Join Date
    Oct 2003
    Location
    Australia
    Posts
    1,963
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Question Walking DOM, changing <a> classes

    Hey
    I'm working on my first little JS related project and I need the help of a DOM concious coder please.
    The Deal
    I have a series of 3 modules that are only being displayed one at a time - upon selection of the link to activate one it hides the rest.
    These modules each have 3 sub-modules which are also being displayed one at a time, with the links to choose the active one within the parent module (div).

    That stuff's all good, but what I need help with is setting the class of the <a> that has just been clicked to "active" and making sure that no other link within the same module is also assigned class="active".
    The parent link of the chosen module will need to active also, so I can't just go through the whole page removing any instance of class="active"
    When one of the three parent modules is activated, it also activates the first of it's children, so I also need to assign class="active" to the first <a> child of the parent div.
    Here's my JS for the show/hide stuff (not x-browser yet )
    Code:
    <script type="text/javascript">
    mod=new Array()
    mod[0]="ssm-hits"
    mod[1]="ssm-user"
    mod[2]="ssm-refer"
    
    hits=new Array()
    hits[0]="ss-hits"
    hits[1]="ss-last-week"
    hits[2]="ss-resources"
    
    user=new Array()
    user[0]="ss-platform"
    user[1]="ss-browser"
    user[2]="ss-lang"
    
    refer=new Array()
    refer[0]="ss-refer"
    refer[1]="ss-repeat"
    refer[2]="ss-search"
    
    function hideexcept(elm, arr) {
    	for (var i = 0; i < arr.length; i++) {
    		var layer = document.getElementById(arr[i]);
    		if (elm!= arr[i]) {
    			layer.style.display = "none";
    		}
    		else {
    			layer.style.display = "block";
    		}
    	}
    }
    </script>
    The 'mod' array is the parent of the other three arrays.
    Here is a working, unstyled version of the page:
    http://leftjustified.net/staticModule.html

    As always, help is greatly appreciated
    Last edited by mindlessLemming; 08-10-2004 at 01:04 AM.

    I take no responsibility for the above nonsense.


    Left Justified

  • #2
    Regular Coder
    Join Date
    Jun 2004
    Location
    underground
    Posts
    186
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Here's something:

    In theory, this is useable w/ scripting disabled...
    Code:
    <html>
    <head>
    <title>Left Justified: Statistics</title>
    
    <style type="text/css">
    .active1
     {
       font:caption;
       color:inactivecaptiontext;
       background:inactivecaption;
       border:1px outset;
       padding:0 .25em 0 .25em;
     }
    .active2
     {
       font:caption;
       color:captiontext;
       background:activecaption;
       border:1px outset;
       padding:0 .25em 0 .25em;
     }
    </style>
    
    <script type="text/javascript">
    
    window.onload = function()
     {
       var divs = document.getElementsByTagName("DIV"),
              n = divs.length,
              i = -1,
              at;
       while(++i < n)
        {
          at = divs[i];
          if(!at.getAttributeNode("hideme"))
            continue;
          at.style.display = "none";
        }
       
     }
    
    var arr = [];
    function syncClass(e, top)
     {
       var ele = (e.target ? e.target : e.srcElement),
           ar0 = arr[0],
           ar1 = arr[1],
           ar2 = arr[2],
           stl;
       if(ele.nodeName != "A")
         return false;
       var ref = document.getElementsByTagName("A")[ele.hash.substr(1)];
       if(top)
        {
          if(ar1)
            ar1.className = "";
          ref.className = "active2";
          arr[1] = ref;
          ar1 = arr[1];
          if(ele != ar0)
           {
             if(ar0)
               ar0.className = "";
             ele.className = "active1";
             arr[0] = ele;
             ar0 = arr[0];
             ele = ref;
             if(ar2)
               ar2.display = "none";
           }
          stl = ref.parentNode.parentNode.parentNode.style;
          stl.display = "";
          arr[2] = stl;
          ref = document.getElementsByTagName("A")[ref.hash.substr(1)];
        }
       if(ele != ar1 && ele != ar0)
        {
          ar1.className = "";
          ele.className = "active2";
          arr[1] = ele;
        }
       stl = ref.parentNode.parentNode.style;
       if(!arr[3])
         arr[3] = stl;
       arr[3].display = "none";
       stl.display = "";
       arr[3] = stl;
     }
    </script>
    
    </head>
    <body>
     <ul onclick="syncClass(event, 1)">
       <li><a href="#serstats">Server Stats</a></li>
       <li><a href="#usertats">User Stats</a></li>
       <li><a href="#refstats">Referrer Stats</a></li>
     </ul>
    
    <div hideme>
     <ul onclick="syncClass(event, 0)">
       <li><a name="serstats" href="#serstats1">Site Hits</a></li>
       <li><a href="#serstats2">Hits this Week</a></li>
       <li><a href="#serstats3">Resources</a></li>
     </ul>
    	<div hideme>
    	<h3><a name="serstats1">Hits <span>Uniques</span></a></h3>
    	<p>serstats1 data...</p>
    	</div>
    
    	<div hideme>
    	<h3><a name="serstats2">Hits in the last week</a></h3>
    	<p>serstats2 data...</p>
    	</div>
    
    	<div hideme>
    	<h3><a name="serstats3">Resources <span>Hits</span></a></h3>
    	<p>serstats3 data...</p>
    	</div>
    </div>
    
    <div hideme>
     <ul  onclick="syncClass(event, 0)">
       <li><a name="usertats" href="#usertats1">Platform</a></li>
       <li><a href="#usertats2">Browser</a></li>
       <li><a href="#usertats3">Language</a></li>
     </ul>
    	<div hideme>
    	<h3><a name="usertats1">Platform <span>%</span></a></h3>
    	<p>usertats1 data...</p>
    	</div>
    
    	<div hideme>
    	<h3><a name="usertats2">Browser <span>%</span></a></h3>
    	<p>usertats2 data...</p>
    	</div>
    
    	<div hideme>
    	<h3><a name="usertats3">Languages <span>%</span></a></h3>
    	<p>usertats3 data...</p>
    	</div>
    </div>
    
    <div hideme>
     <ul  onclick="syncClass(event, 0)">
       <li><a name="refstats" href="#refstats1">Recent Referrers</a></li>
       <li><a href="#refstats2">Repeat Referrers</a></li>
       <li><a href="#refstats3">Search Strings</a></li>
     </ul>
    	<div hideme>
    	<h3><a name="refstats1">Recent Referrers <span>When</span></a></h3>
    	<p>refstats1 data...</p>
    	</div>
    
    	<div hideme>
    	<h3><a name="refstats2">Repeat Referrers <span>Hits</span></a></h3>
    	<p>refstats2 data...</p>
    	</div>
    
    	<div hideme>
    	<h3><a name="refstats3">Search Strings <span>Hits</span></a></h3>
    	<p>refstats3 data...</p>
    	</div>
    </div>
    </body>
    </html>
    edit:// oops, found a bug (as usual); I'll fix that...
    Ok, it all seems to work now!
    Last edited by neofibril; 08-11-2004 at 07:16 AM. Reason: foo
    Modesty is often lacking in our transactions.

  • #3
    Senior Coder
    Join Date
    Oct 2003
    Location
    Australia
    Posts
    1,963
    Thanks
    0
    Thanked 0 Times in 0 Posts

    I can't even begin to understand that..
    Thankyou so much! Unfortunately, it doesn't work once the content is in there due to this (i think)

    document.getElementsByTagName("DIV")

    There are other divs within the hidden divs that aren't being revieled.
    I was originally adapting this: http://www.alistapart.com/d/eatcake/5.html
    but it had the same problem.
    Oh well, guess it's back to the ol' drawing board for this one. (at least until I get half a clue about javascript!)

    Thanks again

    I take no responsibility for the above nonsense.


    Left Justified

  • #4
    Regular Coder
    Join Date
    Jun 2004
    Location
    underground
    Posts
    186
    Thanks
    0
    Thanked 0 Times in 0 Posts
    That's probably a minor thing to fix; I should have tried it with your full demo page, huh.

    Is that something you'd like me to correct, or are there other probs w/ the example?
    Modesty is often lacking in our transactions.

  • #5
    Regular Coder
    Join Date
    Jun 2004
    Location
    underground
    Posts
    186
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Ok, I got it

    - had to change getAttributeNode("hideme") to atttibutes["hideme"]

    Hopefully, this is the one:
    Code:
    <html>
    <head>
    <title>Left Justified: Statistics</title>
    
    <style type="text/css">
    .active1
     {
       font:caption;
       color:inactivecaptiontext;
       background:inactivecaption;
       border:1px outset;
       padding:0 .25em 0 .25em;
     }
    .active2
     {
       font:caption;
       color:captiontext;
       background:activecaption;
       border:1px outset;
       padding:0 .25em 0 .25em;
     }
    </style>
    
    <script type="text/javascript">
    
    window.onload = function()
     {
       var divs = document.getElementsByTagName("DIV"),
              n = divs.length,
              i = -1,
              at;
       while(++i < n)
        {
          at = divs[i];
          if(!at.attributes["hideme"])
            continue;
          at.style.display = "none";
        }
       
     }
    
    var arr = [];
    function syncClass(e, top)
     {
       var ele = (e.target ? e.target : e.srcElement),
           ar0 = arr[0],
           ar1 = arr[1],
           ar2 = arr[2],
           stl;
       if(ele.nodeName != "A")
         return false;
       var ref = document.getElementsByTagName("A")[ele.hash.substr(1)];
       if(top)
        {
          if(ar1)
            ar1.className = "";
          ref.className = "active2";
          arr[1] = ref;
          ar1 = arr[1];
          if(ele != ar0)
           {
             if(ar0)
               ar0.className = "";
             ele.className = "active1";
             arr[0] = ele;
             ar0 = arr[0];
             ele = ref;
             if(ar2)
               ar2.display = "none";
           }
          stl = ref.parentNode.parentNode.parentNode.style;
          stl.display = "";
          arr[2] = stl;
          ref = document.getElementsByTagName("A")[ref.hash.substr(1)];
        }
       if(ele != ar1 && ele != ar0)
        {
          ar1.className = "";
          ele.className = "active2";
          arr[1] = ele;
        }
       stl = ref.parentNode.parentNode.style;
       if(!arr[3])
         arr[3] = stl;
       arr[3].display = "none";
       stl.display = "";
       arr[3] = stl;
     }
    </script>
    
    </head>
    <body>
     <ul onclick="syncClass(event, 1)">
       <li><a href="#serstats">Server Stats</a></li>
       <li><a href="#usertats">User Stats</a></li>
       <li><a href="#refstats">Referrer Stats</a></li>
     </ul>
    
    <div hideme>
     <ul onclick="syncClass(event, 0)">
       <li><a name="serstats" href="#serstats1">Site Hits</a></li>
       <li><a href="#serstats2">Hits this Week</a></li>
       <li><a href="#serstats3">Resources</a></li>
     </ul>
    	<div hideme>
    	<h3><a name="serstats1">Hits <span>Uniques</span></a></h3>
    	<div>serstats1 data...</div>
    	</div>
    
    	<div hideme>
    	<h3><a name="serstats2">Hits in the last week</a></h3>
    	<div>serstats2 data...</div>
    	</div>
    
    	<div hideme>
    	<h3><a name="serstats3">Resources <span>Hits</span></a></h3>
    	<div>serstats3 data...</div>
    	</div>
    </div>
    
    <div hideme>
     <ul  onclick="syncClass(event, 0)">
       <li><a name="usertats" href="#usertats1">Platform</a></li>
       <li><a href="#usertats2">Browser</a></li>
       <li><a href="#usertats3">Language</a></li>
     </ul>
    	<div hideme>
    	<h3><a name="usertats1">Platform <span>%</span></a></h3>
    	<div>usertats1 data...</div>
    	</div>
    
    	<div hideme>
    	<h3><a name="usertats2">Browser <span>%</span></a></h3>
    	<div>usertats2 data...</div>
    	</div>
    
    	<div hideme>
    	<h3><a name="usertats3">Languages <span>%</span></a></h3>
    	<div>usertats3 data...</div>
    	</div>
    </div>
    
    <div hideme>
     <ul  onclick="syncClass(event, 0)">
       <li><a name="refstats" href="#refstats1">Recent Referrers</a></li>
       <li><a href="#refstats2">Repeat Referrers</a></li>
       <li><a href="#refstats3">Search Strings</a></li>
     </ul>
    	<div hideme>
    	<h3><a name="refstats1">Recent Referrers <span>When</span></a></h3>
    	<div>refstats1 data...</div>
    	</div>
    
    	<div hideme>
    	<h3><a name="refstats2">Repeat Referrers <span>Hits</span></a></h3>
    	<div>refstats2 data...</div>
    	</div>
    
    	<div hideme>
    	<h3><a name="refstats3">Search Strings <span>Hits</span></a></h3>
    	<div>refstats3 data...</div>
    	</div>
    </div>
    </body>
    </html>
    Last edited by neofibril; 08-11-2004 at 08:25 AM. Reason: pasted the wrong code :o
    Modesty is often lacking in our transactions.

  • #6
    Senior Coder
    Join Date
    Oct 2003
    Location
    Australia
    Posts
    1,963
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Thanks
    Still doesn't do it though
    Also, is it really nessecarry to use invalid code? (<a name=""> and <div hideme>)
    I can't use a custom doctype as this is going to be an addon to an existing open source product...
    I can totally understand if you just want to wipe your hands of this whole mess. I'm more trouble than I'm worth most of the time

    I take no responsibility for the above nonsense.


    Left Justified

  • #7
    Regular Coder
    Join Date
    Jun 2004
    Location
    underground
    Posts
    186
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Quote Originally Posted by mindlessLemming
    Still doesn't do it though
    Well, what's wrong?
    (note that I fixed some pasting errors, 5 minutes after I posted that one...)

    Quote Originally Posted by mindlessLemming
    Also, is it really nessecarry to use invalid code?
    I didn't know that expando attributes were invalid, nor that there was a problem with giving anchors a name attribute... isn't that how they work?

    The "hideme" expando can be replaced with a name attribute (with a slight change in the script)... if that's more valid.
    Quote Originally Posted by mindlessLemming
    I can't use a custom doctype as this is going to be an addon to an existing open source product...
    open source product
    Quote Originally Posted by mindlessLemming
    I can totally understand if you just want to wipe your hands of this whole mess. I'm more trouble than I'm worth most of the time
    I just play with scripts (for fun ); feel free to inform me of the correct markup with which to exploit.
    Modesty is often lacking in our transactions.

  • #8
    Senior Coder
    Join Date
    Oct 2003
    Location
    Australia
    Posts
    1,963
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Quote Originally Posted by neofibril
    Well, what's wrong?
    Well, your div's get displayed just fine, but when I put the real content in there it doesn't display any of it...
    I didn't know that expando attributes were invalid, nor that there was a problem with giving anchors a name attribute... isn't that how they work?
    Oops, my mistake. I'm so used to coding in XHTML Strict, which only allows the name attribute on form elements. This is XHTML Trans, so <a name=""> is fine.
    Expando? Never heard of it, but it sure ain't XHTML!
    The "hideme" expando can be replaced with a name attribute (with a slight change in the script)... if that's more valid.
    id="" is the only choice. If you have a look at my example in my original post, I have already assigned all the relevant ID's and marked up everything how it needs to be - including all show/hide functionallity.
    All I really need is a function which walks through the <a> (or <li>) elements contained within a certain <ul> and assigns class="active" to one, while making sure that none of the others have class="active".
    open source product
    http://leftjustified.net/stats/
    (Doesn't allow linking - copy paste url )

    Last edited by mindlessLemming; 08-11-2004 at 10:44 AM.

    I take no responsibility for the above nonsense.


    Left Justified

  • #9
    Regular Coder
    Join Date
    Jun 2004
    Location
    underground
    Posts
    186
    Thanks
    0
    Thanked 0 Times in 0 Posts
    The thing is, using an id for the divs changes the whole grouping dynamic: is 'name' invalid, or just not preferred for some reason?

    Also, Is the "real content" (which doesn't show up) equal to that of your staticModule-demo-page, or no?
    Another thing: the parentNode references are hard-coded, based on your example. If that needs to be flexible, I'd have to rethink it.
    Modesty is often lacking in our transactions.

  • #10
    Regular Coder
    Join Date
    Jun 2004
    Location
    underground
    Posts
    186
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Ok, so 'name' was never valid for a div; sorry.

    Would 'class' be problematic, as well?

    OT:
    the 'name' attrib being deprecated for anchors in XHTML strict: what's the alternative, I wonder?


    @ If you want something done right...

    Really, I assumed your markup was catering to the script, and when consolidating the two ideas into one event/function, it seemed better to change the references to that end.

    Piecing together code snippets is usually not a great way to proceed, IMO.
    Modesty is often lacking in our transactions.

  • #11
    Senior Coder
    Join Date
    Oct 2003
    Location
    Australia
    Posts
    1,963
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Quote Originally Posted by neofibril
    Would 'class' be problematic, as well?
    Possibly, as the parent div's are already assigned classes...However, I would be willing to add an outer div around each one, if that's really nessecarry.
    the 'name' attrib being deprecated for anchors in XHTML strict: what's the alternative, I wonder?
    id's on any element.
    eg:
    Code:
    <a href="#menu">Skip to Menu</a>
    ...
    <ul id="menu">
       <li>....
    @ If you want something done right...
    You're right
    Thanks again for all your patient help - you've been a champ
    Maybe I should use this as an opportunity to start learning js...

    I take no responsibility for the above nonsense.


    Left Justified

  • #12
    Regular Coder
    Join Date
    Jun 2004
    Location
    underground
    Posts
    186
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Quote Originally Posted by mindlessLemming
    Possibly, as the parent div's are already assigned classes...However, I would be willing to add an outer div around each one, if that's really nessecarry.
    A regexp would facilitate distinction by class, but, after all, I guess its pretty lame to flag each div, just for one loop; so...

    The following function does the same thing, minus the need for attributes -- except for the first <ul> having id="root":
    <ul id="root" onclick="syncClass(event, 1)"> -- now, you can get rid of all that "hideme" nonsense

    (This assumes that all of the <a> tags in that <ul>, and the ones they point to, have href="#...")
    edit:// never fails (it doesn't work as I thought); i'll fix it...
    alright... seems to work now (wasn't awake).
    Code:
    window.onload = function()
     {
       var anchs = document.getElementById("root").getElementsByTagName("A"),
           atags = document.getElementsByTagName("A"),
              ar = [],
               n = anchs.length,
               i = -1,
               pn,
               aa;
       while(++i < n)
        {
          pn = atags[anchs[i].hash.substr(1)].parentNode.parentNode;
          aa = pn.getElementsByTagName("A");
          ar.push(aa.length, aa);
          pn.parentNode.style.display = "none";
        }
       while(ar.length)
         follow(-1, ar.shift(), ar.shift());
       function follow(x, y, z)
        {
          while(++x < y)
            atags[z[x].hash.substr(1)].parentNode.parentNode.style.display = "none";
        }
     }
    Quote Originally Posted by mindlessLemming
    id's on any element.
    Ah, that's good to know; well if you'd rather use id's, the script works just fine with that (as do the anchors, strangely enough ); all that's really important is the position of each anchor being the same as what the function expects... including those wihin the <h3> tags! (If you want to change that, just play around with adding or removing the parentNode.parentNode... bits.)



    Quote Originally Posted by mindlessLemming
    Maybe I should use this as an opportunity to start learning js...
    Surely you're as capable as I.
    Last edited by neofibril; 08-12-2004 at 05:40 AM. Reason: fix...
    Modesty is often lacking in our transactions.

  • #13
    Regular Coder
    Join Date
    Jun 2004
    Location
    underground
    Posts
    186
    Thanks
    0
    Thanked 0 Times in 0 Posts
    I'll have to leave it at that; something's come up...
    Last edited by neofibril; 08-12-2004 at 08:42 PM.
    Modesty is often lacking in our transactions.

  • #14
    Senior Coder
    Join Date
    Oct 2003
    Location
    Australia
    Posts
    1,963
    Thanks
    0
    Thanked 0 Times in 0 Posts
    THanks for all your help.
    I'll let you know how I go.

    I take no responsibility for the above nonsense.


    Left Justified


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •