Подтвердить что ты не робот

Добавить класс с JavaScript

Я пишу несколько ванильных JavaScript для создания приятного меню навигации. Я застрял в добавлении активного класса.

Я получаю элементы по имени класса NOT по id. Приведенный ниже код работает, если он заменен идентификатором, однако мне нужно, чтобы он применялся к нескольким элементам.

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

Нет ответов, содержащих jQuery.

4b9b3361

Ответ 1

document.getElementsByClassName возвращает список node. Таким образом, вам придется перебирать список и привязывать событие к отдельным элементам. Как это...

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

Ответ 2

В вашем фрагменте button есть экземпляр NodeList, к которому вы не можете напрямую присоединить прослушиватель событий, а также не можете напрямую изменять свойства элементов className.
Лучше всего делегировать событие:

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

Конечно, я предполагаю, что класс active должен быть удален после возникновения события mouseout, вы можете подумать об использовании для него второго делегирования, но вы могли бы просто присоединить обработчик событий к одному элементу который имеет класс 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);

Есть некоторые возможности для улучшения, с этим кодом, но я не собираюсь здесь повеселиться, -).

Проверьте скрипту здесь

Ответ 3

Вот метод, адаптированный из JQuery 2.1.1, который принимает элемент dom вместо объекта jquery (поэтому jquery не нужен). Включает проверки типов и выражения регулярных выражений:

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

Ответ 4

getElementsByClassName() возвращает HTMLCollection, чтобы вы могли попробовать это

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

Ответ 5

Существует встроенный цикл forEach для массива в 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"); 
});

Ответ 6

Мне нравится использовать пользовательскую функцию "foreach" для таких вещей:

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

(Не помню, где я нашел указанную выше функцию, но она была весьма полезна.)

Затем после извлечения ваших объектов (до elements в этом примере) просто сделайте

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 - это простой способ обработки классов элементов. Просто нужна прокладка для нескольких браузеров. Если вы должны использовать setAttribute, вы должны помнить, что все, что установлено с ним, будет перезаписывать предыдущие значения.

EDIT: Забыл упомянуть, что вам нужно использовать attachEvent вместо addEventListener в некоторых версиях IE. Проверить с помощью if ( document.addEventListener ) {...}.

Ответ 7

Просто добавьте имя класса в начало funciton, а 2-й и 3-й аргументы являются необязательными, и волшебство сделано для вас!

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;

}