web-dev-qa-db-ja.com

jQueryのaddClassとremoveClass-クラスを削除しない

私は非常に簡単なことをしようとしています。基本的に、クリック可能なdivの「ホットスポット」があり、クリックすると画面全体に表示され、コンテンツが表示されます。 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");
    });   
});

更新:

現在このコードを使用していますが、

$( 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関数はまだ「spot」を追加したり、「grown」を削除したりしませんが、他のクラスを追加し、他のクラスを削除します。時間、互いに元に戻すが、違いはないようだ

28
rhinoceros1

何が起こるかというと、閉じるボタンが.clickable div。したがって、クリックイベントは両方の要素でトリガーされます。

イベントバブリングは、クリックイベントを子ノードから親に伝播させます。あなたの.close_buttonコールバックが最初に実行され、.clickableに到達すると、クラスが再び切り替わります。これは非常に高速に実行されるため、2つのイベントが発生したことに気付くことはありません。

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

イベントが.clickable、イベントパラメータをコールバック関数に追加してから、stopPropagationメソッドを呼び出す必要があります。

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

フィドル: http://jsfiddle.net/u4GCk/1/

一般的なイベントの順序に関する詳細情報: http://www.quirksmode.org/js/events_order.html (それは、かなりきれいなASCII art =]を選んだ場所です) )

63
Guilherme Sehn

この問題は event bubbling が原因で発生します。 _.grown_を追加するコードの最初の部分は正常に機能します。

_.close_button_および_.clickable_の両方のハンドラーが実行されるため、リンクをクリックしたときの2番目の部分「成長したクラスの削除」は期待どおりに機能しません。したがって、grownクラスを削除し、divに読み取りました。

これを回避するには、_.close_button_クリックハンドラー内でe.stopPropagation()を使用して、イベントがバブリングしないようにします。

デモ: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');
});
_
13

addClassremoveClassが表示されるたびに、なぜtoggleClassを使用しないのかと思います。この場合、.clickableクラスを削除して、イベントのバブリングを回避し、.clickabledivの内部をクリックするすべてのイベントでイベントが発生しないようにすることができます。

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

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

divsを使用する代わりに、.clickabledocumentの親ラッパーもお勧めします。あなたがそれらをどのように動的に追加しているかわからないので、あなたのレイアウトを仮定したくありませんでした。

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

ハッピーコーディング:)

7
Blake Plumb

複数回使用する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');
    });

実際にはより多くのコードがありますが、$(this)オブジェクトを取得するためにjQueryライブラリ全体を「ウォークスルー」する必要がないため、非常に高速です。

4

あなたはほとんどそこにいると思います。問題は、「閉じるボタン」リスナーの$(this)はクリック可能なdivではないということです。したがって、最初に検索する必要があります。 $(this)$(this).closest(".clickable")に置き換えてください。そして、Guilhermeが提案している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");
        }
    });
});
3
thomasstephn

なぜ単純化しないのですか?

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/

1
FiLeVeR10

これを試して :

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

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

あなたの質問を理解したと思います。

1
lefoy

実際に、プロパティを変更する順序を入れ替えることで問題を解決しました。たとえば、最初に属性を変更していましたが、実際には属性を変更する前にクラスを削除して新しいクラスを追加する必要がありました。なぜ機能したのかはわかりませんが、機能しました。そのため、試してみるのは$("XXXX").attr('something').removeClass( "class" ).addClass( "newClass" )から$("XXXX").removeClass( "class" ).addClass( "newClass" ).attr('something')に変更することです。

0
Zach Pedigo

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

問題は要素のネストにあると思います。イベントを外側の要素にアタッチすると、内側の要素をクリックすると、実際には外側の要素に対して同じクリックイベントが発生します。したがって、実際には2番目の状態に移行することはありません。あなたができることは、クリックされた要素をチェックすることです。そして、それが閉じるボタンである場合、クラスの変更を回避します。私の解決策は次のとおりです。

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/

0
Krasimir