4

I have the following code:

<div id="nav">
  <ul>
    <li id="tabOne" class="first current"><a href="./CS1.html" target="SheetView">Page One</a></li>
    <li id="tabTwo"><a href="./CS2.html" target="SheetView">Page Two</a></li>
    <li id="tabThree"><a href="./CS3.html" target="SheetView">Page Three</li>
    <li id="tabFour"><a href="./CS4.html" target="SheetView">Page Four</a></li>
    <li id="tabFive"><a href="./CS5.html" target="SheetView">Page Five</a></li>
    <li id="tabSix"><a href="./CS6.html" target="SheetView">Page Six</a></li>
  </ul>

This loads the selected page into an iframe named "SheetView." What I need to do is use JavaScript to alter the class when an option that isn't the currently selected on is clicked. I should say that I have the current class already setup in my CSS. I just have no way to trigger it.

I thought adding an onlick event to the <UL> up there and calling onclick="Javascript:changeCurrent();" but there is the problem (four actually):

  1. Is <ul onclick="JavaScript:changeCurrent();> where I need to have the event?
  2. What is the resulting JavaScript to make the change happen?
  3. How can I cause the first option to be set as current by default?
  4. Is there a way to keep the currently selected option from being an active link?

I found a few different examples but I couldn't tailor them to work for me. Any help would be most appreciated.

Peter O.
  • 32,158
  • 14
  • 82
  • 96
Benjamin
  • 45
  • 1
  • 1
  • 4

3 Answers3

2

Since you specified that you wanted a non-jQuery response, here's a function that will toggle appropriately:

function toggleNavSelected(el){
    var list = document.getElementById('nav').children[0];
    for(var i=0; i<list.children.length; i++){
        var cur = list.children[i];
        if(el==cur){
            cur.classList.add("current");
            cur.firstChild.onclick = (function(){
                toggleNavSelected(this.parentElement);
                return false;
            });
        } else {
            if(cur.classList.contains("current")){
                cur.classList.remove("current");
            }
            cur.firstChild.onclick = (function(){
                toggleNavSelected(this.parentElement);
            });
        }
    }
}

Either add an onclick handler to each LI (onclick="toggleNavSelected(this);") or execute the following after the menu has loaded:

var list = document.getElementById('nav').children[0];
for(var i=0; i<list.children.length; i++){
    var el = list.children[i];
    el.firstChild.onclick = (function(){
        toggleNavSelected(this.parentElement);
    });
}

Demo: http://jsfiddle.net/bWY7P/2/

(note: The JSFiddle script has a small difference; it adds a return false; to the onclick function so that you can play with it without the links actually following the HREF attribute. Do not use that line in your live code)


Explanation:

The function looks at each LI element within the #nav element.
If that element is the element passed to the function, then it adds the class .current.
Otherwise, it removes the class .current (if present).

The second part binds a function to the onclick event of each a element that calls the toggleNavSelected() function and passes its parent element (the li) as the argument.

joequincy
  • 1,395
  • 10
  • 21
  • See also: [event.preventDefault() vs. return false](http://stackoverflow.com/questions/1357118/event-preventdefault-vs-return-false) – feeela Dec 09 '12 at 00:56
  • Eh. Neither is necessary for Benjamin. I only added it to the JSFiddle to cater to that specific environment. Perfection is unnecessary for tweak to accommodate the demo environment, as long as it's explained. – joequincy Dec 09 '12 at 01:00
  • Hey, thanks for this. I would vote you up but I was informed by a box that such an act would require 15 reputation which I haven't so just thanks. If I get that 15 I'll up vote you. Still wish there was a way to block the active link status of the current tab but at least it's working now. Thanks ever so much. – Benjamin Dec 10 '12 at 01:37
  • @Benjamin, edited the answer. Now when it adds `.current` to an `li`, it also adds a `return false;` to the `onclick` function for the link inside it. (And removes it when removing `.current`) [Feel free to take a look at the differences](http://stackoverflow.com/posts/13783543/revisions) to see what you would need to add. – joequincy Dec 10 '12 at 16:21
0

1) if you want to change the currently selected class when you click an item, put the onclick into the li item 2) using jquery would be very easy here, all you have to do is import the jquery file with the <script> tag and you're ready! For example, you could do onclick="changeClass(this);" on the <li> tag and in a normal JavaScript file or in a script tag:

function changeClass(this){
 $('#nav li').attr("class","");
 $(this).attr("class","current");
}

Replace the 'current' with the class name you want to use

3) it should already be set as current

4) use the :visited CSS selector to change what colour followed links look like eg:

a:visited{
 color: #000000;
}
ABC
  • 718
  • 8
  • 23
  • Actually feeela's adding and removing classes method is better because mine clears all classes. Just change where he has put $('#nav a') to $('#nav li') – ABC Dec 09 '12 at 00:44
  • Mmh, I would set the event-handler to the link, as it the element that was selected by the user. You could still get the list item in jQuery with `$( this ).parent( 'li' )`. – feeela Dec 09 '12 at 00:48
0

First of all you should set the event handler from a separate script, not from an onclick attribute. You don't repeat your code that way and have anything in one place. The HTML is also much cleaner.

Using jQuery it would be as easy as:

var menuLinks = jQuery( '#nav a' );

menuLinks.on( 'click' function() {

    menuLinks.removeClass( 'active' );
    $( this ).addClass( 'active' );

} );

You could also do that in plain JS, but using some library keeps you out of the trouble of browser incompatibilities.

feeela
  • 29,399
  • 7
  • 59
  • 71