2013-07-26 10 views
5

Come faccio a delegare eventi in stile jQuery con JavaScript semplice in Hammer.js? Ad es .:Delega eventi con Hammer.js

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

È direttamente possibile o devo eseguire personalmente la delegazione?

+0

Controllo target - saranno ** ** solo lavoro se si fa clic su elemento con '.item'. Ma se all'interno di quel '.item' c'è un altro elemento e fai clic su quell'elemento interno - l'ispezione del bersaglio NON aiuterà. avresti bisogno di scansionare il suo genitore (che è ciò che altre risposte fornite) - che esattamente quello che volevi nella tua domanda '$ .on ('tap', '.item', function() {...}'. with jquery - usando il tuo codice in questione, ti verranno fornite le giuste informazioni ANCHE se hai fatto clic su un elemento interno su '.item' –

+0

Come puoi vedere qui - ispezionando il target mostrerai il pulsante che non è' .item' http://jsbin.com/hobenunale/1/edit?html,js,output - mentre jquery ti mostra l'elemento delegeated –

risposta

2

È sufficiente ispezionare lo target dell'oggetto Event passato al gestore.

Here's a demo.

+0

Questo non è quello che l'OP voleva: –

+0

@Royi, davvero? Perché ha accettato questa risposta .. . * 4 anni fa * –

+0

È importante? Ho bisogno di usare 'Hammer (document) .on ('tap', '.item', function() { console.log ('tapped') })' - E il bersaglio non era un aiutante :-) –

3

Uso la seguente funzione per verificare se l'obiettivo è un delegato.

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; 

} 

Sto usando il filtro jQuery perché lo uso molto e con alcuni selettori più complessi.

Usage:

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

Questo non funziona con tutti i selettori, ma io direi che è meglio che in di André che sarà ancora funzionare se il tuo "target" ha elementi figlio. Per esempio.

<div id="parent"> 
    <div class="child"> 
     <div class="text">Test</div> 
    </div> 
</div> 

André di fallirà qui perché target è il [div.text] e non ha la classe.

Per l'utilizzo sopra di _getDelegate, diciamo '$element = $("#parent"). Se hai toccato la parola "Test" event.target sarebbe [div.text] (dove hai toccato) e event.currentTarget sarebbe [div.parent] (dove è registrato il gestore). Quando hai chiamato _getDelegate con questi parametri, riceverai [div.child] e saprai che dovresti eseguire il codice del gestore.

Per una versione JS pura, ti piacerebbe qualcosa di simile, dove cerchi i genitori per vedere se colpisci qualcosa.

var delegate; 
var target = e.target; // e.g. Inner div 
var currentTarget = e.currentTarget // e.g. #parent 

while(target && target != currentTarget){ 
    if(target.className.indexOf('child')!=-1){ 
     delegate = target; 
     break; 
    } 
    target = target.parentNode; 
} 

if(delegate) { 
    console.log('delegated tap received'); 
} 

Ci sono ancora molti difetti con questo. L'indice indexof className è una cattiva idea perché le classi possono essere sotto-stringhe l'una dell'altra, ad es. "myClass" e "myClass2". Inoltre, il mio codice presuppone che tutti i tuoi sottoelementi siano posizionati all'interno dei loro genitori.

+0

Bello, ma un esempio di utilizzo per il metodo '_isDelegate' sarebbe utile e/o la documentazione dei parametri. Inoltre, '_getDelegate' non dovrebbe essere un nome più accurato in quanto non restituisce un valore booleano? :) – Lambart

+0

Grazie. Ho aggiunto un esempio di utilizzo che utilizza solo il jquery sul gestore, anche se è bene che tu abbia aggiunto l'utilizzo di hammer's(). Ho cambiato anche il nome della funzione. Sono abbastanza sicuro che fosse isDelegate perché, quando l'ho scritto, non ero realmente usando l'elemento nel gestore. Quando volevo l'elemento era una modifica facile per farlo restituire l'elemento, ma ho dimenticato di cambiare il nome della funzione. – Jools

3

Ispirato dalla risposta di Jools, ecco quello che mi è venuto in mente. Non mi sono preoccupato di una soluzione JS pura: infatti, è stata progettata per l'uso con lo Backbone.View, ma è facilmente adattabile ad altre situazioni.

Arresta l'albero del nodo quando raggiunge l'elemento radice della vista (this.el). A partire dal target identificato dall'evento HammerJS, cercherà il primo elemento corrispondente al selettore specificato e restituirà undefined se non viene trovato alcun elemento di questo tipo.

Per l'utilizzo in un ambiente non Backbone, è sufficiente passare un riferimento all'elemento limitante/contenente come terzo argomento (come nella soluzione di Jools) e utilizzarlo per sostituire 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; 
    } 

Se si dispone di una funzione di callback onTap, potrebbe essere simile a questo:

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

E per collegare il tutto, che ci si vuole qualcosa di simile ...

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

(e non dimenticare di chiamare this._hammer.destroy() quando la vista è distrutta!)

+0

Strano ma OP ha accettato una risposta che non risolve il problema. Il target non è lo stesso dell'elemento dell'evento delegato –

-1

Continuando @ soluzione Lambarr - Carattere tipografico:

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

Usage:

private registerDocumentclick() 
    { 

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

    ); 
    }