2015-11-27 10 views
14

1.7.3のアップデート後にプロトタイプイベントレジストリに問題があるようですが、私は要素のストレージにprototype_event_registryを使用して、クリックイベントにアクセスして再生できました。PrototypeJSイベントレジストリの問題

これは、イベントを停止し、オプションでコールバックに基づいて再開できるようにするためですが、すべてが正常に機能していましたが、1.7.01.7.3の差分を確認した後、

私はこれが内部のものであり、最初はそれを使用してはいけないと知っています。とにかく、私の質問にダウン:

私は1.7.3に対応するためにコードを更新しましたが、それは私には非常にハックようだ、これを行うための良い方法はありますか?

/** 
* 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

それは1.7.1で書き直されたイベントレジストリのように見える - 'Event.cache'オブジェクトはに設定しましたメモリリークを防止し、パフォーマンスを向上させます。私はかなり確信しています。 _prototypeUID'は、拡張された要素に常に存在しなければなりません。そうでなければ、要素ごとにイベントレジストリを参照する方法になります。 –

+0

Event.stop(e)は何をする予定ですか?イベントの伝播を停止する必要がありますか? –

+0

@kiran、伝播を停止しますが、ボタンで指定された追加のクリックハンドラを停止しないので、この関数は:) – epoch

答えて

0

上記のコードを3〜4か月間実行した後、私はついにそれを元に戻すことにしました。特に、1つのページに複数のフレームやイベントハンドラを扱う場合は、多くの問題があるようです。

特定の要素についてEvent.cacheが最も一般的であり、undefinedである。

これは誤った取り扱いによるものかもしれませんが、新しいEventフレームワークは何とか間違っていると思われます。1.7.0に復帰すると、経験したすべての問題が完全に修正されるためです。参考まで

が、これは私が今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; 
} 
関連する問題