2009-07-12 18 views
3

が、私はこのコードを持っている想像して停止します。JavaScriptは、追加のイベントリスナー

var myFunc1 = function(event) { 
    alert(1); 
} 
var myFunc2 = function(event) { 
    alert(2); 
} 

element.addEventListener('click', myFunc1); 
element.addEventListener('click', myFunc2); 

クリックイベントが発射されるmyFunc1はmyFunc2そして、呼ばれています。しかし、myFunc1のいくつかの条件が満たされた場合に、myFunc2が呼び出されないようにするにはどうすればよいですか? event.stopPropagation()は解決策ではありません。これはイベントキャプチャ/バブリングの問題ではないためです。

ありがとうございました。

+0

いつも一緒に呼ばれていますか? –

+0

いいえ、時々私はどちらか一方しか使用しません。リスナーは異なるコンポーネントで追加されるため、組み合わせることはできません。 –

+0

stopPropです!a!ゲットストップしない!私はそれがちょうどタイプミスであることを賭けている – epascarello

答えて

5

さらに問題があります:イベントリスナーが実行される順序は未定義です。これを回避するには、イベントのディスパッチを自分で処理する必要があります。これは、llimllibの提案のいくつかの変種につながります。

function dispatchSleightEvent(evt) { 
    var listeners = evt.currentTarget.sleightListeners[evt.type]; 
    // can't use for-in because enumeration order is implementation dependent 
    for (var i=0; i<listeners.length; ++i) { 
     if (listeners[i]) { 
     if (! listeners[i].call(evt.currentTarget, evt)) { 
      return false; 
     } 
     } 
    } 
    return true; 
} 

function mixinSleightTarget(obj) { 
    if (! obj.sleightListeners) { 
    obj.sleightListeners = {} 
    obj.addSleightListener = function(type, listener) { 
     if (!this.sleightListeners[type]) { 
      this.sleightListeners[type] = []; 
      this.addEventListener(type, dispatchSleightEvent); 
     } 
     if (!this.sleightListeners[type+listener] { 
      this.sleightListeners[type+listener] = this.sleightListeners[type].length; 
      this.sleightListeners[type].push(listener); 
     } 
    } 
    obj.removeSleightListener = function(type, listener) { 
     if (this.sleightListeners[type+listener] { 
      delete this.sleightListeners[type][this.sleightListeners[type+listener]]; 
      delete this.sleightListeners[type+listener]; 
     }   
    } 
    } 
} 

このコードは完全にテストされていません。 1つのターゲット上でイベントディスパッチを停止するには、イベントリスナーがfalseを返します。より多くのデータ隠蔽が必要な場合は、関数のプログラミングの観点から上記を書き直すことができますが、メモリリークが発生する可能性があります。

+0

stopImmediatePropagation()が実装されるまで、カスタムイベントハンドラが最適なソリューションであるため、これを答えとしてマークしました。注文が未定義であることは間違いありませんが、それはDOM Level-3(FIFO)で定義されています.Geckoで行ったすべてのテストでは、この注文が現在の実装で一貫していることが示唆されていますFF3で動作する必要があります)。当面の単純さのために、私は現在、私の最初のanwserに似た解決策を選んでいます。 –

+0

私が心配していた問題の1つは、リスナーが追加される順序ですが、それは今のところ問題ではないように思えます。より良い設計は、明示的なリスナーの依存関係をサポートします。 – outis

2

私はこれまでに与えた制約を満たす最も簡単な答えから始めます。あなたがまだ指定していない状態を満たしていない場合は、私に知らせてください。

クリックハンドラを1つだけ許可し、そこで条件に基づいて関数を呼び出します。あなたのテストコードは

var myFunc1 = function(event) { 
    alert(1); 
} 
var myFunc2 = function(event) { 
    alert(2); 
} 
var clickHandler = function(event) { 
    if (f1active) myFunc1(event); 
    if (f2active) myFunc2(event); 
} 

element.addEventListener('click', clickHandler); 
var f1active = true; 
var f2active = true; 

となります。もちろん、あなたはどんな条件でもclickHandlerに入れられます。

+0

問題はa)いつも両方のリスナーを同時に使用しているとは限らず、b)リスナーが大きなモジュールライブラリ内の異なるコンポーネントに追加されているため、それらをマージするだけでは意味がありません。かなり困難です。 –

3

はまだ良い解決策を探しているが、これはそれを行うための唯一の方法かもしれ:

var myFunc1 = function(event) { 
    alert(1); 
    if (something) { 
     event.cancel = true; 
    } 
} 
var myFunc2 = function(event) { 
    if (event.cancel) { 
     return; 
    } 
    alert(2); 
} 

document.body.addEventListener('click', myFunc1, false); 
document.body.addEventListener('click', myFunc2, false); 

思考/コメント大歓迎。

5

DOMレベル3のメソッドevent.stopImmediatePropagationは、私がここで必要とするものです。 残念ながら、それは現在私が知っているどのブラウザでも実装されていません

+1

これは私が探していたものです!!!!!!どうもありがとう! –

+1

ありがとうございます。[現在、多くのブラウザで実装されている](http://stackoverflow.com/a/18078452/1185136) –

0

私はoutis解決策を、あなた自身のイベントディスパッチャーで既存のDOMイベントディスパッチモデルを装飾または適応させる必要があると思います。

は、いくつかの検索を行なったし、このリンクを発見した、または、ActionScriptのディスパッチャの実装に基づいて、もちろん日付2007年

http://positionabsolute.net/blog/2007/06/event-dispatcher.php

をニーズに合わせてもしなくてもよい、私は本当にjavascripterありませんよこれが関係ない場合は、私に頭をアップしてください。

+0

あなたのリンクは古くなっています – murtho

関連する問題