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

Как повторно использовать addClass и removeClass на одном элементе?

Итак, что я хочу достичь, просто измените классы HTML-ссылки на каждый щелчок следующим образом:

  • Удалите класс .first, если он присутствует, затем добавьте .second класс
  • Удалите .second класс, если он присутствует, затем добавьте .third класс
  • Удалите .third класс, если он присутствует, затем добавьте класс .fourth
  • И так далее...

Пока не повезло. Что я могу делать неправильно?

Вот одна строка HTML-кода, где я пытаюсь выполнить код jQuery:

<a class="first" href="#">Test 1</a>

Здесь мой jQuery:

$( "#menu li a.first" ).click(function() {

   $( "#menu li a.first" ).removeClass("first").addClass("second");

}

$( "#menu li a.second" ).click(function() {

   $( "#menu li a.second" ).removeClass("second").addClass("third");

}

$( "#menu li a.third" ).click(function() {

   $( "#menu li a.second" ).removeClass("third").addClass("fourth");

}

Спасибо заранее!

4b9b3361

Ответ 1

Проблема заключается в том, что вы пытаетесь присоединить обработчик событий до того, как он даже имеет класс second или third.

Кроме того, этот подход довольно многословный. Я предлагаю просто предоставить массив классов. Например:

var classNames = ['first', 'second', 'third'];

Затем добавьте к кнопке другой идентификатор, например добавьте класс class-changer. И присоедините следующий обработчик событий.

$('.class-changer').on('click', function() {
    var $el = $(this)
    for (var i= 0; i < classNames.length; i++) {
        if ($el.hasClass(classNames[i]) && classNames[i+1]) {
           $el.removeClass(classNames[i]).addClass(classNames[i+1]);
           break;
        }
    }
});

Ответ 2

Поместите все классы в массив и по щелчку ссылки добавьте класс один за другим, как показано ниже.

var classes = ["first", "second", "third", "fourth"];
$("#menu li a").click(function () {
    var index = classes.indexOf(this.className);
    var newIndex = (index + 1) % classes.length; //return to first after reaching last

    $(this).removeClass(classes[index]).addClass(classes[newIndex]);
});
.first { color: red; }
.second { color: green; }
.third { color: blue; }
.fourth { color: purple; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="menu">
    <li>
        <a class="first" href="#">Test 1</a>
    </li>
</ul>

Ответ 3

Вы можете сделать это с использованием .data()

HTML:

<a class="first" href="#" id="test">Test 1</a>

JS:

$(".first").data("classes",["one","two","three","four"]).click(function() {
  var elem = $(this);
  var cnt = (elem.data("cnt") || 0)
  var classes = elem.data("classes");
  elem.removeClass().addClass(classes[cnt % classes.length] + " first").data("cnt",++cnt);
});

Demo

$(".first").data("classes",["one","two","three","four"]).click(function() {
  var elem = $(this);
  var cnt = (elem.data("cnt") || 0)
  var classes = elem.data("classes");
  elem.removeClass().addClass(classes[cnt % classes.length] + " first").data("cnt",++cnt);
});
.one{
  color:red;
}
.two{
  color:yellow;
}
.three{
  color:green;
}
.four{
  color:blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<a class="first" href="#" id="test">Test 1</a>

Ответ 4

Предполагая, что на самом деле у вас есть только 1 ссылка, состояние которой вы пытаетесь изменить, вместо связки ссылок в вашем меню, в которых вы хотите, чтобы ВСЕ перемещались от ".first" до ".second", когда вы нажимаете, Я бы предложил этот как самый идиоматический способ (каламбур не предназначен).

// Only select the menu once
var $menu = $('#menu');

// Delegate to elements with the correct class.
// Specifying the "li a" is probably unnecessary,
// unless you have other elements with the same classes in "#menu".
$menu.on('click', '.first', function(e) {

    // Inside a jQuery event handler,
    // `this` refers to the element that triggered the event.
    // If the event is delegated, it the delegation target
    // (".first" in this instance), not the bound element ("#menu").
    $(this).removeClass('first').addClass('second');

});

$menu.on('click', '.second', function(e) {
   $(this).removeClass('second').addClass('third');
});

$menu.on('click', '.third', function(e) {
   $(this).removeClass('third').addClass('fourth');
});

Ресурсы

Ответ 5

Не уверен, что это решит вашу проблему, но я бы снял для условного оператора и только один делегированный прослушиватель событий:

$("#menu li").on('click', 'a', function()
{
   if($(this).hasClass('first'))
   {
       $(this).removeClass('first').adddClass('second');
   }
   elseif($(this).hasClass('second'))
   {
       $(this).removeClass('second').adddClass('third');
   }
   // etc...
}

Ответ 6

Если вы хотите связать событие, выбранный элемент должен существовать ранее.

Чтобы связать обработчик событий с элементами, которые еще не существуют (например, динамически созданным или измененным), вы можете сделать это:

$(document).on('click', '#menu li a.first', function() {

    $( "#menu li a.first" ).removeClass("first").addClass("second");

});

$(document).on('click', '#menu li a.second', function() {

   $( "#menu li a.second" ).removeClass("second").addClass("third");

});

$(document).on('click', '#menu li a.third', function() {

   $( "#menu li a.third" ).removeClass("third").addClass("fourth");

});

Ответ 7

<a class="changable first" href="#">Test 1</a>
$( ".changable" ).click(function(event) {
classes = ['first','second','third','fourth']
changed=false
for (c in classes){
    if (event.target.classList.contains(classes[c]) && changed==false){
       $(this).removeClass((classes[c]));
       index_to_add=classes.indexOf(classes[c])+1
       class_to_add=classes[index_to_add]
       $(this).addClass(class_to_add);
       changed=true;
    }
}

});

Ответ 8

Хорошо, поэтому для этого есть несколько обходных путей, о которых еще не упоминалось.

Вы можете использовать объект Javascript для этого не просто массива. Объект может упростить задачу, если вам нужна цепочка вместо списка.

var classNames = {first:'second', second:'third', third:'fourth'};

$('#menu li a').on('click', function() {
    if(typeof classNames[this.className] !== 'undefined'){
        this.className = classNames[this.className];
    }
});

Второй способ - использовать .on('click', [selector], handler) вместо click, который может обрабатывать динамически загруженные, добавленные или измененные элементы.

$('#menu li').on('click', 'a.first', function() {
    $(this).removeClass("first").addClass("second");
});

$('#menu li').on('click', 'a.second', function() {
   $(this).removeClass("second").addClass("third");
});

$('#menu li').on('click', 'a.third', function() {
   $(this).removeClass("third").addClass("fourth");
});

Даже близко к идеальному, но все же рабочему решению.

Вы можете использовать if .. else или switch .. case внутри функции для создания дерева решений.

Так что в основном есть много решений. Выберите лучшее.

Ответ 9

Попробуйте привязать событие к родительскому,

Моя попытка,

var $classes = ['first', 'second', 'third'];

$(function(){
    $('#subject').click(function(){
        current = $(this).find('a:first');
        index = $.inArray(current.attr('class'), $classes);
        if($classes.length > index+1)
            current.removeClass($classes[index]).addClass($classes[index+1])
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id='subject'>
	<a class="first" href="#">Test 1</a>
</div>

Ответ 10

Нет, вы не можете. Поскольку JavaScript работает только после загрузки страницы (если вы поместили их внутри функции $( document ).ready()), дальнейшие функции ниже никогда не будут выполняться. Он может обнаруживать только <a class="first" href="#">Test 1</a>, но не <a class="second" href="#">Test 1</a>, потому что <a class="second" href="#">Test 1</a> генерируются после загрузки страницы и, следовательно, никогда не будут выполняться, если вы не используете Ajax.

Обновление: Это можно сделать. См. Комментарий @i3b13 ниже.