Как повторно использовать 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");
}
Спасибо заранее!
Ответы
Ответ 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 ниже.