2013-07-26 13 views
5

Hammer.jsでプレーンJavaScriptを使用してjQueryスタイルのイベント委譲を行うにはどうすればよいですか?例:Hammer.jsを使用したイベント委任

Hammer(document).on('tap', '.item', function() { 
    console.log('tapped') 
}) 

これは直接行うことができますか、自分で委任する必要はありますか?

+0

検査対象 - ます**のみ**あなたが.item' 'を持つ要素をクリックした場合の作業。しかし、 '.item'の中に別の要素があり、その内部要素をクリックすると、ターゲットを検査することは助けになりません。その親(これは他の回答が提供しているもの)をスキャンする必要があります。あなたの質問では、$ .on( 'tap'、 '.item'、function(){...} ' jquery - 問題のコードを使用すると、内側の要素を '.item'にクリックした場合、正しい情報EVENが提供されます –

+0

ここからわかるように、ターゲットを検査すると' .item'以外のボタンが表示されますhttp://jsbin.com/hobenunale/1/edit?html,js,output - jqueryはあなたに代理要素を表示しています –

答えて

2

ハンドラーに渡されたEventオブジェクトのtargetを調べるだけで済みます。

Here's a demo

+0

これはOPが望んでいないものです –

+0

@Royi、本当ですか? * 4年前* –

+0

重要: 'Hammer(document).on( 'tap'、 '.item'、function(){ console.log( 'タップ') }')を使用する必要がありました。ターゲットはヘルパーではありませんでした:-) –

3

次の関数を使用して、ターゲットがデリゲートかどうかをテストします。

function _getDelegate(selector, target, currentTarget) { 

    var delegate = null; 

    while (target && target != currentTarget) { 
     delegate = $(target).filter(selector)[0]; 
     if (delegate) 
     return delegate; 
     target = target.parentNode; 
    } 

    return delegate; 

} 

私はそれに多く、いくつかのより複雑なセレクタとを使用するので、私はjqueryのフィルタを使用しています。

使用法:

var delegationSelector = ".child"; 
$element.hammer() 
$element.on("tap", function handler(event){ 
    var delegate = _getDelegate(delegationSelector, event.target, event.currentTarget); 
    if(delegate){ // or if(!delegate) return; 
     // Your handler code 
    } 
}); 

これは、すべてのセレクタでは動作しませんが、私はそれがあなたの「ターゲット」は子要素を持っている場合、それはまだ動作することをアンドレの中よりはましだと思います。例えば。 target[div.text]であり、あなたのクラスを持っていないため

​​

アンドレさんはここに失敗します。

上記の_getDelegateの使用については、「$element = $("#parent")」とします。 "Test"という単語をタップした場合、[div.text](タップした場所)とevent.currentTarget[div.parent](ハンドラが登録されている場所)になります。これらのパラメータを使用して_getDelegateを呼び出すと、[div.child]が届き、ハンドラコードを実行する必要があることがわかります。

純粋なJSバージョンの場合は、何かヒットしたかどうかを調べるために両親をループアップするこのようなものが必要です。

これには多くの欠陥があります。クラスは相互のサブストリングになることがあるので、classNameの全体のインデックスは悪い考えである。 "myClass"と "myClass2"。また、私のコードでは、すべてのサブ要素がその親の中に配置されているという前提があります。

+0

ニースですが、あなたの '_isDelegate'メソッドの使用例が参考になります。また、 '_getDelegate'はブール値を返さないので、より正確な名前にならないでしょうか? :) – Lambart

+0

ありがとう。ハンマーのon()を使用して追加したのは良いことですが、ハンドラーでjqueryを使用するだけの使用例を追加しました。 関数名も変更しました。私はそれが本当にハンドラの要素を使用していなかったので、私はそれがisDelegateだとかなり確信しています。要素が必要なときは要素を返すようにするのは簡単な変更でしたが、関数名を変更するのは忘れてしまいました。 – Jools

3

Joolsの答えに触発されて、ここに私が思い付いたことがあります。実際には、これはBackbone.Viewでの使用を意図していますが、他の状況にも容易に適応できます。

ノードツリーがビューのルート要素(this.el)に達すると、ノードツリーの登りが止まります。 HammerJSイベントで識別されるターゲットから開始し、指定されたセレクタに一致する最初の要素を検索し、そのような要素が見つからない場合はundefinedを返します。

バックボーン以外の環境で使用するには、(Joolsのソリューションのように)第3引数として制限/包含要素への参照を渡し、this.elの代わりに使用します。

/** 
* @param {Node}target - the target of the received event 
* @param {String}selector - any jQuery-compatible selector 
*/ 
getEventDelegate: function (target, selector) { 
    var delegate; 
    while (target && target != this.el) { 
     delegate = $(target).filter(selector)[0]; 
     if (delegate) { 
      return delegate; 
     } 
     target = target.parentNode; 
    } 
    return undefined; 
    } 

あなたはonTapコールバック関数を使用している場合、それはこのようなものになります。

/** 
* @param {Event}ev 
*/ 
onTap: function (ev) { 
    var target = this.getEventDelegate(ev.target, "#desiredTarget"); 
    if (target) { 
     // TODO something with the target... 
    } 
} 

をそしてそれをすべてをフックする、あなたはこのような何かをしたいと思います...

this._hammer = new Hammer(this.el); 
this._hammer.on('tap', _.bind(this.onTap, this)); 

(あなたのビューが破壊された場合は、this._hammer.destroy()に電話することを忘れないでください)

+0

奇妙ですが、OPはその問題を解決しない答えを受け入れました。ターゲットは委任されたイベントの要素と同じではありません –

-1

Lambarrのソリューション@継続 - 活字体:

private delegateBind(rootElement:Node,e, selector:string, handler: (target:any) => any) 
    { 

    let target=e.target; 
    let o = { 

     getEventDelegate: function() 
     { 
     var delegate; 

     while (target && target != rootElement) 
     { 
      delegate = jQuery(target).filter(selector)[0]; 
      if (delegate) 
      { 
      return delegate; 
      } 

      target = target.parentNode; 
     } 
     return undefined; 
     } 

    }; 

    target = o.getEventDelegate(); 
    if (target) 
    { 
     handler(target); 
    } 
    } 

使用法:

private registerDocumentclick() 
    { 

    Hammer(this.document).on('tap', e => 
     this.delegateBind(this.document,e,'.article', (elm) => console.log(elm.classList)) 

    ); 
    }