add class with JavaScript

前端 未结 7 2010
傲寒
傲寒 2020-12-29 02:38

I am writing some vanilla JavaScript to create a nice navigation menu. I am stuck on adding an active class.

I am getting elements by class name NOT by id. The belo

相关标签:
7条回答
  • 2020-12-29 02:41

    There is build in forEach loop for array in ECMAScript 5th Edition.

    var buttons = document.getElementsByClassName("navButton");
    
    Array.prototype.forEach.call(buttons,function(button) { 
        button.setAttribute("class", "active");
        button.setAttribute("src", "images/arrows/top_o.png"); 
    });
    
    0 讨论(0)
  • 2020-12-29 02:41

    I like to use a custom "foreach" function of sorts for these kinds of things:

    function Each( objs, func )
    {
        if ( objs.length ) for ( var i = 0, ol = objs.length, v = objs[ 0 ]; i < ol && func( v, i ) !== false; v = objs[ ++i ] );
        else for ( var p in objs ) if ( func( objs[ p ], p ) === false ) break;
    }
    

    (Can't remember where I found the above function, but it has been quite useful.)

    Then after fetching your objects (to elements in this example) just do

    Each( elements, function( element )
    {
        element.addEventListener( "mouseover", function()
        {
            element.classList.add( "active" );
            //element.setAttribute( "class", "active" );
            element.setAttribute( "src", "newsource" );
        });
    
        // Remove class and new src after "mouseover" ends, if you wish.
        element.addEventListener( "mouseout", function()
        {
            element.classList.remove( "active" );
            element.setAttribute( "src", "originalsource" );
        });
    });
    

    classList is a simple way for handling elements' classes. Just needs a shim for a few browsers. If you must use setAttribute you must remember that whatever is set with it will overwrite the previous values.

    EDIT: Forgot to mention that you need to use attachEvent instead of addEventListener on some IE versions. Test with if ( document.addEventListener ) {...}.

    0 讨论(0)
  • 2020-12-29 02:52

    In your snippet, button is an instance of NodeList, to which you can't attach an event listener directly, nor can you change the elements' className properties directly.
    Your best bet is to delegate the event:

    document.body.addEventListener('mouseover',function(e)
    {
        e = e || window.event;
        var target = e.target || e.srcElement;
        if (target.tagName.toLowerCase() === 'img' && target.className.match(/\bnavButton\b/))
        {
            target.className += ' active';//set class
        }
    },false);
    

    Of course, my guess is that the active class needs to be removed once the mouseout event fires, you might consider using a second delegator for that, but you could just aswell attach an event handler to the one element that has the active class:

    document.body.addEventListener('mouseover',function(e)
    {
        e = e || window.event;
        var oldSrc, target = e.target || e.srcElement;
        if (target.tagName.toLowerCase() === 'img' && target.className.match(/\bnavButton\b/))
        {
            target.className += ' active';//set class
            oldSrc = target.getAttribute('src');
            target.setAttribute('src', 'images/arrows/top_o.png');
            target.onmouseout = function()
            {
                target.onmouseout = null;//remove this event handler, we don't need it anymore
                target.className = target.className.replace(/\bactive\b/,'').trim();
                target.setAttribute('src', oldSrc);
            };
        }
    },false);
    

    There is some room for improvements, with this code, but I'm not going to have all the fun here ;-).

    Check the fiddle here

    0 讨论(0)
  • 2020-12-29 02:53

    getElementsByClassName() returns HTMLCollection so you could try this

    var button = document.getElementsByClassName("navButton")[0];
    

    Edit

    var buttons = document.getElementsByClassName("navButton");
    for(i=0;buttons.length;i++){
       buttons[i].onmouseover = function(){
         this.className += ' active' //add class
         this.setAttribute("src", "images/arrows/top_o.png");
       }
    }
    
    0 讨论(0)
  • 2020-12-29 02:58

    document.getElementsByClassName returns a node list. So you'll have to iterate over the list and bind the event to individual elements. Like this...

    var buttons = document.getElementsByClassName("navButton");
    
    for(var i = 0; i < buttons.length; ++i){
        buttons[i].onmouseover = function() {
            this.setAttribute("class", "active");
            this.setAttribute("src", "images/arrows/top_o.png");
        }
    }
    
    0 讨论(0)
  • 2020-12-29 02:58

    Here is a method adapted from Jquery 2.1.1 that take a dom element instead of a jquery object (so jquery is not needed). Includes type checks and regex expressions:

    function addClass(element, value) {
        // Regex terms
        var rclass = /[\t\r\n\f]/g,
            rnotwhite = (/\S+/g);
    
        var classes,
            cur,
            curClass,
            finalValue,
            proceed = typeof value === "string" && value;
    
        if (!proceed) return element;
    
        classes = (value || "").match(rnotwhite) || [];
    
        cur = element.nodeType === 1
            && (element.className
                    ? (" " + element.className + " ").replace(rclass, " ")
                    : " "
            );
    
        if (!cur) return element;
    
        var j = 0;
    
        while ((curClass = classes[j++])) {
    
            if (cur.indexOf(" " + curClass + " ") < 0) {
    
                cur += curClass + " ";
    
            }
    
        }
    
        // only assign if different to avoid unneeded rendering.
        finalValue = cur.trim();
    
        if (element.className !== finalValue) {
    
            element.className = finalValue;
    
        }
    
        return element;
    };
    
    0 讨论(0)
提交回复
热议问题