Corey
Corey

Reputation: 1195

Changing CSS class with Javascript

Is there a better way than the implementation I have now? I'm concerned that the way I've done it is a little hackish and am wondering if there's a more elegant solution.

I want to change the "selected" element on the page by applying a CSS class to it, and remove the one that is currently selected. The code I have for changing the element's class:

function changeClass(element) {
    document.getElementById("nav").getElementsByClassName("selected")[0].className = "";
    element.className = "selected";
}

And the corresponding elements:

<div id="nav">
    <ul>
        <li><a href="#" onclick="changeClass(this)" class="selected">Main</a></li>
        <li><a href="#" onclick="changeClass(this)">Downloads</a></li>
        <li><a href="#" onclick="changeClass(this)">News</a></li>
        <li><a href="#" onclick="changeClass(this)">Forums</a></li>
        <li><a href="#" onclick="changeClass(this)">Proposals</a></li>
    </ul>
</div>

Again, this seems a little hacky. Is there a better way of accomplishing what I'm trying to do?

Upvotes: 1

Views: 13760

Answers (5)

jdigital
jdigital

Reputation: 12296

Here's how to do this with JQuery:

$(document).ready( function()
{
    $("a").click( function()
    {
        $(".selected").removeClass("selected");
        $(this).addClass("selected");
    } );
});

This clears the existing "selected" class and adds it to the one just clicked.

Upvotes: 5

kennebec
kennebec

Reputation: 104840

<!doctype html>
<html lang="en">
<head>
<meta charset= "utf-8">
<title>Untitled Document</title>

<style type="text/css">
li{margin:1ex 1em}
ul.selectable a{color:blue;text-decoration:underline;font-size:2em}
ul.selectable a.selected{color:red;border:red dotted 1px}
</style>
<script type="text/javascript">
// It is easier to fake a lightweight forEach than 
//an  getElementsByClassName function


Array.prototype.forAll= function(fun){
    var L= this.length, tem;
    if(typeof fun== 'function'){
        while(L){
            fun(this[--L]);
        }
    }
}

// You could have just one handler, listening to the div or ul
// and running the function on the target it it is a hyperlink.

onload= function(){
    var pa= document.getElementById("nav"),
    collection= pa.getElementsByTagName('a');

    pa.onclick= function(e){
        e= window.event? event.srcElement: e.target;
        if(e.tagName== 'A'){
            [].forAll.call(collection,function(itm){
                itm.className= '';
            });
            e.className= "selected";
            return e.focus();
        }
        return true;
    }
}

</script>
</head>
<body>

<div id= "nav"> 
<ul class= "selectable"> 
<li> <a href= "#" class= "selected"> Main</a> </li> 
<li> <a href= "#"> Downloads</a> </li> 
<li> <a href= "#"> News</a> </li> 
<li> <a href= "#"> Forums</a> </li> 
<li> <a href= "#"> Proposals</a> </li> 
</ul> 
</div>

</body>
</html>

Upvotes: 0

Ed Daniel
Ed Daniel

Reputation: 517

There's not a lot wrong with what you've got.

Instead of getElementsByClassName, which isn't supported by IE, consider using getElementsByTagName to get all the <a> tags as an array, then iterating through that array, setting className to "" for each.

A Javascript library like jQuery or Prototype does indeed give you lots of functions specifically designed for this sort of work. But, unless you're doing a fair bit more Javascript than this, they're complete overkill.

Lastly, if your <a>s are intended to be back-up navigation in case Javascript is disabled, you probably want your onclick handlers to return false; that prevents the link from being followed. (In your case, to "#".)

Upvotes: 0

Behrang Saeedzadeh
Behrang Saeedzadeh

Reputation: 47971

I recommend you to use a JavaScript library to do this. For example, with jQuery you could do something like this:

$("#nav .selected").removeClass("selected");

This would remove the "selected" class from all child elements of #nav that have the class "selected".

Upvotes: -1

HoLyVieR
HoLyVieR

Reputation: 11134

Using the getElementByClassName isn't too recommended, because currently there are browser that don't fully support this functionnality (mainly IE). This is probably something that would work better on all browser :

<html>
<head>

<script type="text/javascript">
var previousElement = null;
function changeClass (newElement) {
     if (previousElement != null) {
          previousElement.className = "";
     }

     newElement.className = "selected";
     previousElement = newElement;
}

// just add a call to this function on the load of the page
function onload() {
     lis = document.getElementById("nav").getElementsByTagName("a");
     for (var i=0; i<lis.length; i++) {
          if (lis[i].className == "selected")
            previousElement = lis[i];
     }
}
</script>
<style type="text/css">
.selected {
    background: #0ee;
}
</style>
</head>
<body onload="onload()">
<div id="nav">
    <ul>
        <li><a href="#" onclick="changeClass(this)" class="selected">Main</a></li>
        <li><a href="#" onclick="changeClass(this)">Downloads</a></li>
        <li><a href="#" onclick="changeClass(this)">News</a></li>
        <li><a href="#" onclick="changeClass(this)">Forums</a></li>
        <li><a href="#" onclick="changeClass(this)">Proposals</a></li>
    </ul>
</div>
</body>
</html>

Upvotes: 3

Related Questions