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

AddClass и removeClass в jQuery - не удалять класс

Я пытаюсь сделать что-то очень простое. В принципе, у меня есть интерактивное "горячее пятно", когда вы нажимаете кнопку, чтобы заполнить экран и отобразить некоторый контент. Я достиг этого, просто изменив класс div, удалив "пятно" и добавив "выросли", и там немного анимации CSS, чтобы он стал расти. Это прекрасно работает.

Проблема заключается в том, что внутри этого div есть close_button, который на данный момент является только текстом. Я хочу, чтобы это переключило классы обратно - то есть удалило вырожденное и чтение. Он не делает этого при нажатии. Я считаю, что это связано с тем, что элемент не имеет этих классов при загрузке DOM, но я новичок в jQuery и не знаю, как обойти это.

Я думаю, что, возможно, гораздо более разумный способ сделать это, может ли кто-нибудь указать мне в правильном направлении? Я был бы очень благодарен. Я пробовал использовать toggleClass, но безрезультатно.

$( document ).ready(function() {      
    $(".clickable").click(function() {  
        $(this).addClass("grown");  
        $(this).removeClass("spot");
    });   

    $(".close_button").click(function() {  
        alert (this);
        $("#spot1").removeClass("grown");  
        $("#spot1").addClass("spot");
    });   
});

UPDATE:

Теперь я использую этот код,

$( document ).ready(function() {   
    $(document).on("click", ".close_button", function () { 
        alert ("oi");
        $("#spot1").addClass("spot");
        $("#spot1").removeClass("grown");
    });  


    $(document).on("click", ".clickable", function () {
        if ($(this).hasClass("spot")){
            $(this).addClass("grown");
            $(this).removeClass("spot");
        }
    });
});

странно функция close_button по-прежнему не добавит "пятно" или не удалит "выросли", хотя добавит какие-либо другие классы, и он удалит другие классы... Я добавил предложение if, потому что я думал, что, возможно, обе функции запускались в то же время, отменяя друг друга, но, похоже, не имеет значения

4b9b3361

Ответ 1

Что происходит, так это то, что кнопка закрытия находится внутри вашего .clickable div, поэтому событие click будет активировано в обоих элементах.

Всплывающее событие приведет к тому, что событие click распространяется от дочерних узлов к родителям. Таким образом, ваш обратный вызов .close_button будет выполнен первым, а когда .clickable будет достигнуто, он снова переключит классы. Поскольку это выполняется очень быстро, вы не можете заметить, что произошло два события.

                    / \
--------------------| |-----------------
| .clickable        | |                |
|   ----------------| |-----------     |
|   | .close_button | |          |     |
|   ------------------------------     |
|             event bubbling           |
----------------------------------------

Чтобы ваше событие не достигало .clickable, вам нужно добавить параметр события в свою функцию обратного вызова, а затем вызвать метод stopPropagation на нем.

$(".close_button").click(function (e) { 
    $("#spot1").addClass("spot");
    $("#spot1").removeClass("grown");
    e.stopPropagation();
});

Fiddle: http://jsfiddle.net/u4GCk/1/

Подробнее о порядке событий в целом: http://www.quirksmode.org/js/events_order.html (где я выбрал это довольно ASCII art =])

Ответ 2

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

Вторая часть "удаление выращенного класса" при нажатии ссылки не работает так, как ожидалось, так как выполняются обработчик для .close_button и .clickable. Таким образом, он удаляет и считывает класс grown в div.

Вы можете избежать этого, используя e.stopPropagation() внутри .close_button обработчик кликов, чтобы избежать события от пузырьков.

DEMO: http://jsfiddle.net/vL8DP/

Полный код

$(document).on('click', '.clickable', function () {
   $(this).addClass('grown').removeClass('spot');
}).on('click', '.close_button', function (e) {
   e.stopPropagation();
   $(this).closest('.clickable').removeClass('grown').addClass('spot');
});

Ответ 3

Всякий раз, когда я вижу addClass и removeClass я думаю, почему бы просто не использовать toggleClass. В этом случае мы можем удалить класс .clickable чтобы избежать .clickable событий и избежать .clickable события для всего, что мы нажимаем внутри .clickable div.

$(document).on("click", ".close_button", function () { 
    $(this).closest(".grown").toggleClass("spot grown clickable");
});  

$(document).on("click", ".clickable", function () {
    $(this).toggleClass("spot grown clickable");
}); 

Я также рекомендую родительскую оболочку для .clickable divs вместо того, чтобы использовать document. Я не уверен, как вы добавляете их динамически, поэтому не хотел принимать ваш макет за вас.

http://jsfiddle.net/bplumb/ECQg5/2/

Удачного кодирования :)

Ответ 4

Я бы рекомендовал кэшировать объекты jQuery, которые вы используете более одного раза. Для экземпляра:

    $(document).on("click", ".clickable", function () {
        $(this).addClass("grown");
        $(this).removeClass("spot");
    });

:

    var doc = $(document);
    doc.on('click', '.clickable', function(){
       var currentClickedObject = $(this);
       currentClickedObject.addClass('grown');
       currentClickedObject.removeClass('spot');
    });

его на самом деле больше кода, НО это muuuuuuch быстрее, потому что вам не нужно "ходить" через всю библиотеку jQuery, чтобы получить объект $(this).

Ответ 5

Я думаю, ты почти там. Дело в том, что ваш $(this) в прослушивателе "закрыть" не является интерактивным div. Поэтому вы хотите сначала его искать. попробуйте заменить $(this) на $(this).closest(".clickable"). И не забывайте e.stopPropagation(), как предлагает Гильерме. это должно быть что-то вроде:

$( document ).ready(function() {   
    $(document).on("click", ".close_button", function () { 
        alert ("oi");
        e.stopPropagation()
        $(this).closest(".clickable").addClass("spot");
        $(this).closest(".clickable").removeClass("grown");
    });  


    $(document).on("click", ".clickable", function () {
        if ($(this).hasClass("spot")){
            $(this).addClass("grown");
            $(this).removeClass("spot");
        }
    });
});

Ответ 6

Попробуйте следующее:

$('.close-button').on('click', function(){
  $('.element').removeClass('grown');
  $('.element').addClass('spot');
});

$('.element').on('click', function(){
  $(this).removeClass('spot');
  $(this).addClass('grown');
});

Надеюсь, я понял ваш вопрос.

Ответ 7

Почему бы не упростить его?

JQuery

$('.clickable').on('click', function() {//on parent click
    $(this).removeClass('spot').addClass('grown');//use remove/add Class here because it needs to perform the same action every time, you don't want a toggle
}).children('.close_button').on('click', function(e) {//on close click
    e.stopPropagation();//stops click from triggering on parent
    $(this).parent().toggleClass('spot grown');//since this only appears when .grown is present, toggling will work great instead of add/remove Class and save some space
});

Таким образом, это намного проще поддерживать.

сделал скрипку: http://jsfiddle.net/filever10/3SmaV/

Ответ 8

Используйте . on()

вам нужно делегировать события, поскольку эти классы не присутствуют в DOM, когда DOM готов.

$(document).on("click", ".clickable", function () {
    $(this).addClass("grown");
    $(this).removeClass("spot");
});
$(document).on("click", ".close_button", function () {  
    $("#spot1").removeClass("grown");
    $("#spot1").addClass("spot");
});  

Ответ 9

Я думаю, что проблема заключается в вложении элементов. Когда вы присоединяете событие к внешнему элементу, клики по внутренним элементам фактически запускают одно и то же событие click для внешнего элемента. Итак, вы на самом деле никогда не переходите ко второму состоянию. Что вы можете сделать, так это проверить элемент с кликом. И если это кнопка закрытия, чтобы избежать изменения класса. Вот мое решение:

var element = $(".clickable");
var closeButton = element.find(".close_button");
var onElementClick = function(e) {
    if(e.target !== closeButton[0]) {
        element.removeClass("spot").addClass("grown");
        element.off("click");
        closeButton.on("click", onCloseClick);
    }
}
var onCloseClick = function() {
    element.removeClass("grown").addClass("spot");
    closeButton.off("click");
    element.on("click", onElementClick);
}
element.on("click", onElementClick);

Кроме того, я добавляю и удаляю обработчики событий.

JSFiddle → http://jsfiddle.net/zmw9E/1/

Ответ 10

Я на самом деле просто решил проблему, меняющуюся, изменив порядок, в котором я изменял свойства. Например, сначала я изменял атрибут, но мне фактически пришлось удалить класс и добавить новый класс, прежде чем изменять атрибуты. Я не уверен, почему это сработало, но это сработало. Таким образом, можно попробовать изменить значение с $("XXXX").attr('something').removeClass( "class").addClass( "newClass" ) на $("XXXX").removeClass( "class").addClass( "newClass").attr('something').