web-dev-qa-db-fra.com

ajouter une classe avec JavaScript

Je suis en train d'écrire du JavaScript vanille pour créer un menu de navigation agréable. Je suis coincé sur l'ajout d'une classe active.

Je reçois des éléments par nom de classe, PAS par id. Le code ci-dessous fonctionne s'il est remplacé par id. Cependant, j'ai besoin qu'il s'applique à plusieurs éléments. 

HTML

<img class="navButton" id="topArrow" src="images/arrows/top.png" />
<img class="navButton" id="rightArrow" src="images/arrows/right.png" />

JS

var button = document.getElementsByClassName("navButton");

button.onmouseover = function() {
    button.setAttribute("class", "active");
    button.setAttribute("src", "images/arrows/top_o.png");
}

Aucune réponse contenant jQuery s'il vous plaît.

35
vincentieo

document.getElementsByClassName renvoie une liste de nœuds. Vous devrez donc parcourir la liste et lier l'événement à des éléments individuels. Comme ça...

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");
    }
}
42
mohkhan

Dans votre extrait, button est une instance de NodeList, à laquelle vous ne pouvez pas attacher directement un écouteur d'événement ni modifier les propriétés className des éléments directement.
Votre meilleur pari est de déléguer l'événement:

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);

Bien entendu, j’imagine que la classe active doit être supprimée une fois que l’événement mouseout est déclenché. Vous pouvez envisager d’utiliser un deuxième délégant pour cela, mais vous pouvez associer également un gestionnaire d’événements a la classe active:

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);

Il y a quelques améliorations à apporter avec ce code, mais je ne vais pas m'amuser ici ;-).

Vérifiez le violon ici

7
Elias Van Ootegem

Voici une méthode adaptée de Jquery 2.1.1 qui utilise un élément dom au lieu d’un objet jquery (jquery n’est donc pas nécessaire). Comprend les vérifications de type et les expressions rationnelles:

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;
};
2
Aleksandr Albert

getElementsByClassName() renvoie HTMLCollection afin que vous puissiez essayer ceci

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

Modifier

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
Arda

J'aime utiliser une fonction "foreach" personnalisée pour ce genre de choses:

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;
}

(Je ne me souviens plus où j'ai trouvé la fonction ci-dessus, mais cela a été très utile.)

Ensuite, après avoir récupéré vos objets (à elements dans cet exemple), faites simplement

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 est un moyen simple de gérer les classes d'éléments. Juste besoin d'une cale pour quelques navigateurs. Si vous devez utiliser setAttribute, vous devez vous rappeler que tout ce qui y est associé will écrasera les valeurs précédentes.

EDIT: J'ai oublié de mentionner que vous devez utiliser attachEvent au lieu de addEventListener sur certaines IE versions. Testez avec if ( document.addEventListener ) {...}.

0
ojrask

La boucle forEach est intégrée dans un tableau dans 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
ketan

Ajoutez simplement un nom de classe au début de la fonction et les 2ème et 3ème arguments sont optionnels et la magie est faite pour vous!

function getElementsByClass(searchClass, node, tag) {

  var classElements = new Array();

  if (node == null)

    node = document;

  if (tag == null)

    tag = '*';

  var els = node.getElementsByTagName(tag);

  var elsLen = els.length;

  var pattern = new RegExp('(^|\\\\s)' + searchClass + '(\\\\s|$)');

  for (i = 0, j = 0; i < elsLen; i++) {

    if (pattern.test(els[i].className)) {

      classElements[j] = els[i];

      j++;

    }

  }

  return classElements;

}
0
Yoni