2011-11-08 1 views
27

旧式のコードを持つJavaScriptツールの に取り組んでおり、ツール全体を書き直すことはできません。特定の要素が伝播を停止しても、ページの任意の場所でクリックを処理するにはどうすればよいですか?

メニューが下部に固定された位置に追加されました。クライアントはメニューを開いたり閉じたりするトグルボタンを持つことを大変喜んでいます。 ユーザーが物事を外出し始めたときに閉じるたとえば、ユーザーがページに戻ってフォームフィールド上の何かかクリックを選択したときなどに、

これは技術的に任意のクリックでトリガ、bodyclickイベントに仕事ができる、 は、しかし、クリックイベントが内部リンク上で処理された古いコードにおける多数の項目があり、そしてreturn falseは、クリックに追加されました機能を使用して、リンクのhrefタグにサイトを続行しないようにします。

明らかに、このような一般的な機能は動作しますが、falseを返すことで伝播が停止する内部リンクをクリックした場合は動作しません。

$('body').click(function(){ 
    console.log('clicked'); 
}); 

私は、とにかく を身体クリックイベントを強制できるか、私はいくつかのグローバルクリックイベントまたは類似のものを使用して、メニューdissappearを聞かせすることができます別の方法がある方法はありますか?

年前に作成されたアプリケーション内の他のすべてのクリックを書き換える必要はありません。 それは怪物の仕事になります。なぜなら私は返り値がなくても、どうやってそれらを書き直すのかという手がかりがないからです。しかし、まだ彼らはhrefに行かせません。

答えて

44

イベントは、2つのフェーズ、をバブリングとをキャプチャしています。キャプチャフェーズは、ドキュメントのdefaultViewからイベントターゲットに流れ、バブリングフェーズが続き、イベントターゲットからdefaultViewに戻る最初のフェーズです。詳細については、http://www.w3.org/TR/DOM-Level-3-Events/#event-flowを参照してください。イベントのキャプチャ段階を処理するために

、あなたがtrueaddEventListenerのための第三引数を設定する必要があります。

悲しいこと
document.body.addEventListener('click', fn, true); 

、ウェズリーが述べたように、イベントのキャプチャ段階を確実に処理することができない、またはまるで古いブラウザでは

一つの可能​​な解決策は、クリックのイベントの順序であるため、代わりにmouseupイベントを処理することです:

  1. マウスダウン
  2. クリック

のmouseup

  • あなたが持っていることを確認することができた場合mouseupイベントをキャンセルするハンドラがない場合は、これは一方向(そして、間違いなく、より良い方法)です。注意すべきもう一つは、ほとんどではないにしても(ほとんどではないにしても)多くのUIメニューがマウスダウン時に消えることです。 アンディEと協力して

  • +2

    あなたがこれを使うことができるのだろうかと疑問に思っている人は、ここにキャニウスページがあります:http://caniuse.com/#feat=addeventlistener短い答えは、IE8を気にしない限り、はいです。 –

    0

    私は、これは何が必要だと思う:

    $("body").trigger("click"); 
    

    これは、あなたがどこからでも、本体のクリックイベントをトリガすることができます。

    +0

    domのより深いネストされたものがイベントの伝播を防ぎますが、それが発生しますか? – Matt

    +0

    私はこの問題は、クリックイベントは、クリックイベントが最初の場所で発生することができなかったことを、特定のリンク上のイベントハンドラからfalseを返すことではない飲み込まされていることだと思います。 。 –

    0

    あなたはこれが最初イベントハンドラの仕事であることを確認している場合は、このような何かを行う可能性がありますトリック:

    $('*').click(function(event) { 
        if (this === event.target) { // only fire this handler on the original element 
         alert('clicked'); 
        } 
    }); 
    

    ページに多くの要素がある場合、これは非常に遅くなり、動的に追加されたものでは機能しません。近代的なDOM実装で

    +0

    動的な事は簡単に(、 "クリック" 機能(){})で$( "*")を介して固定することができ、これに関係なく、これは悪い考えです。 – Bbit

    6

    、これは力の暗黒面です:

    var _old = jQuery.Event.prototype.stopPropagation; 
    
    jQuery.Event.prototype.stopPropagation = function() { 
        this.target.nodeName !== 'SPAN' && _old.apply(this, arguments); 
    };  
    

    http://jsfiddle.net/M4teA/2/

    すべてのイベントがjQueryを介して結合していた場合、あなたができることを覚えておいてくださいここでそれらのケースを処理します。この例では、<span>を扱っていない場合は、元の.stopPropagation()とします。


    あなたは予防できません。

    できることは、これらのイベントハンドラを手動でコード内に書き換えることです。これは扱いにくいビジネスですが、格納されているハンドラメソッドにアクセスする方法が分かっていれば、そのメソッドを回避することができます。私はそれを周りに少しを果たしたが、これは私の結果である:

    $(document.body).click(function() { 
        alert('Hi I am bound to the body!'); 
    }); 
    
    $('#bar').click(function(e) { 
        alert('I am the span and I do prevent propagation'); 
        e.stopPropagation(); 
    }); 
    
    $('#yay').click(function() { 
        $('span').each(function(i, elem) { 
         var events  = jQuery._data(elem).events, 
          oldHandler = [ ], 
          $elem   = $(elem); 
    
         if('click' in events) {       
          [].forEach.call(events.click, function(click) { 
           oldHandler.push(click.handler); 
          }); 
    
          $elem.off('click'); 
         } 
    
         if(oldHandler.length) { 
          oldHandler.forEach(function(handler) { 
           $elem.bind('click', (function(h) { 
            return function() { 
             h.apply(this, [{stopPropagation: $.noop}]); 
            }; 
           }(handler))); 
          }); 
         } 
        }); 
    
        this.disabled = 1; 
        return false; 
    }); 
    

    http://jsfiddle.net/M4teA/

    お知らせ、上記のコードは、jQueryの1.7で動作します。これらのクリックイベントが以前のjQueryバージョンまたは「インライン」にバインドされている場合でも、コードを使用できますが、「古いハンドラ」に別々にアクセスする必要があります。

    私は、ここでは完全な世界のシナリオを多く想定しています。たとえば、をfalseに戻す代わりに明示的に呼び出してください。だから、それはまだ役に立たない学術例かもしれないが、私はそれを:-)

    編集出てくるように感じました:ちょっと、return false;はうまく動作しますが、イベントオブジェクトは、同じ方法でアクセスされます。

    +0

    これは賢いです。 :) –

    関連する問題