2015-11-27 13 views
14

Sembra esserci un problema con il registro degli eventi prototipo dopo l'aggiornamento 1.7.3, stavo usando prototype_event_registry sulla memoria degli elementi per accedere agli eventi click in modo che potessi riprodurli.Problemi del registro eventi PrototypeJS

questo è così che posso smettere di eventi e, facoltativamente, riprendo a loro sulla base di una richiamata, tutto funzionava bene, ma dopo aver letto le diff per 1.7.0 e 1.7.3 sembra essere rimosso?

So che questo era interno e probabilmente non avrei dovuto usarlo in primo luogo. Comunque, fino alla mia domanda:

Ho aggiornato il mio codice per lavorare con 1.7.3 ma mi sembra estremamente intrusivo, c'è un modo migliore per farlo?

/** 
* creates a toggling handler for click events taking previous click events into account. 
* 
* w.r.t stopping of a click event, handles cases where the button is a submit or a normal button. 
* in the case of a submit, calling <tt>Event.stop()</tt> should be sufficient as there are no other listeners on the button. 
* however, if a normal button has a handler that calls <tt>save()</tt>, and another handler using client code and calling stop, 
* it will not affect stopping of the event, since <tt>Event.stop</tt> only stops propagation, not other handlers! 
* 
* note that this function will always execute the specified handler before any other defined events. 
* 
* @param {Element} element the element to use for this click event 
* @param {Function} handler the handler to use for this stopping click event, if this handler returns true, 
* all other actions for the click event will be prevented 
* @returns {Element} the element that was supplied as argument 
*/ 
function stoppingClickEvent(element, handler) { 
    if (!element) throw 'cannot use method, if element is undefined'; 

    // assign default handler if none was supplied 
    handler = handler || Prototype.emptyFunction; 

    if (element.type && element.type === 'submit') { 
     element.on('click', function(submitEvent) { 
      // call the supplied handler with the current element as context and the event as argument 
      // if it returns true, we should stop the event 
      var stopEvent = handler.call(element, submitEvent); 

      if (stopEvent) { 
       // since the element's default action will be to submit a form, we prevent it 
       submitEvent.stop(); 
      } 
     }); 
    } else { 
     // prototype 1.7.3 removed support for 'prototype_event_registry', so we need to do multiple hacks here 
     // first get the window of the element so we can access the prototype 
     // event cache from the correct context (frames) 
     var elementDoc = element.ownerDocument; 
     var elementWindow = elementDoc.defaultView || elementDoc.parentWindow; 

     if (!elementWindow) { 
      throw 'cannot access the window object for element ' + element.id; 
     } 

     // we are dealing with a normal element's click event, so we don't know how many click events have been set up. 
     // capture them all so we can decide to call them or not. 
     // FIXME: need a better way of doing this 
     var registry = elementWindow['Event'].cache[element._prototypeUID || element.uniqueID] || {}, 
      events = registry['click'] || []; 

     // now that we have a copy of the events, we can stop them all and add our new handler 
     element.stopObserving('click').on('click', function(clickEvent) { 
      // call the supplied handler with the current element as context and the event as argument 
      // if it returns true, we should stop the event 
      var stopEvent = handler.call(element, clickEvent); 

      if (!stopEvent) { 
       // the event should not be stopped, run all the original click events 
       events.each(function(wrapper) { 
        wrapper.handler.call(element, clickEvent); 
       }); 
      } 
     }); 
    } 

    return element; 
} 
+1

Sembra che il registro evento è stato riscritto in 1.7.1 - il 'Event.cache' oggetto è stato installato a evitare che alcune perdite di memoria migliorino le prestazioni. Sono abbastanza sicuro che 'elemento. _prototypeUID' dovrebbe sempre esistere su qualsiasi elemento esteso, ma in caso contrario sarebbe il modo di fare riferimento al registro eventi per elemento. –

+0

Non è Event.stop (e) che fa ciò che dovrebbe fare? Dovrebbe fermare la propagazione dell'evento, no? –

+0

@kiran, interrompe la propagazione, ma non arresta alcun gestore di clic aggiuntivo specificato sul pulsante, quindi questa funzione :) – epoch

risposta

0

Dopo aver eseguito con il codice di cui sopra per 3-4 mesi, ho finalmente deciso di tornare esso. Sembra che ci siano molti problemi, specialmente quando si tratta di più frame e gestori di eventi su una singola pagina.

Il più prevalente è, Event.cache per un elemento specifico è undefined.

questo può essere dovuto ad un'errata manipolazione sopra, ma ho il sospetto fortemente il nuovo quadro Event per essere corretto in qualche modo, dal momento che un Ripristina 1.7.0 risolve completamente tutti i problemi che ho vissuto.

Solo per riferimento, questo è il codice Ora sto utilizzando con 1.7.0:

/** 
* creates a toggling handler for click events taking previous click events into account. 
* 
* w.r.t stopping of a click event, handles cases where the button is a submit or a normal button. 
* in the case of a submit, calling <tt>Event.stop()</tt> should be sufficient as there are no other listeners on the button. 
* however, if a normal button has a handler that calls <tt>save()</tt>, and another handler using client code and calling stop, 
* it will not affect stopping of the event, since <tt>Event.stop</tt> only stops propagation, not other handlers! 
* 
* note that this function will always execute the specified handler before any other defined events. 
* 
* @param {Element} element the element to use for this click event 
* @param {Function} handler the handler to use for this stopping click event, if this handler returns true, 
* all other actions for the click event will be prevented 
* @returns {Element} the element that was supplied as argument 
*/ 
function stoppingClickEvent(element, handler) { 
    if (!element) throw 'cannot use method, if element is undefined'; 

    // assign default handler if none was supplied 
    handler = handler || Prototype.emptyFunction; 

    if (element.type && element.type === 'submit') { 
     element.on('click', function(submitEvent) { 
      // call the supplied handler with the current element as context and the event as argument 
      // if it returns true, we should stop the event 
      var stopEvent = handler.call(element, submitEvent); 

      if (stopEvent) { 
       // since the element's default action will be to submit a form, we prevent it 
       submitEvent.stop(); 
      } 
     }); 
    } else { 
     // we are dealing with a normal element's click event, so we don't know how many click events have been set up. 
     // capture them all so we can decide to call them or not. 
     var registry = element.getStorage().get('prototype_event_registry') || $H(), 
      events = registry.get('click') || []; 

     // now that we have a copy of the events, we can stop them all and add our new handler 
     element.stopObserving('click').on('click', function(clickEvent) { 
      // call the supplied handler with the current element as context and the event as argument 
      // if it returns true, we should stop the event 
      var stopEvent = handler.call(element, clickEvent); 

      if (!stopEvent) { 
       // the event should not be stopped, run all the original click events 
       events.each(function(func) { 
        func.call(element, clickEvent); 
       }); 
      } 
     }); 
    } 

    return element; 
} 
Problemi correlati