2015-11-27 63 views
14

Có vẻ như có vấn đề với đăng ký sự kiện mẫu sau khi cập nhật 1.7.3, tôi đang sử dụng prototype_event_registry trên bộ nhớ phần tử để truy cập các sự kiện nhấp để tôi có thể phát lại chúng.Các vấn đề về đăng ký sự kiện PrototypeJS

Điều này là để tôi có thể dừng sự kiện và tiếp tục tùy chọn dựa trên gọi lại, mọi thứ hoạt động tốt, nhưng sau khi xem các điểm khác nhau cho 1.7.01.7.3 dường như bị xóa?

Tôi biết rằng đây là nội bộ và có lẽ tôi không nên sử dụng nó ngay từ đầu. Dù sao, xuống đến câu hỏi của tôi:

Tôi đã cập nhật mã của mình để làm việc với 1.7.3 nhưng có vẻ như vô cùng khó khăn với tôi, có cách nào tốt hơn để làm điều này không?

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

Dường như các registry Sự kiện này được viết lại bằng 1.7.1 - 'cái Event.cache' đối tượng đã được thiết lập để ngăn chặn một số rò rỉ bộ nhớ cải thiện hiệu suất. Tôi khá chắc chắn rằng 'yếu tố. _prototypeUID' phải luôn tồn tại trên bất kỳ phần tử mở rộng nào - nhưng nếu không thì đó sẽ là cách để tham khảo sổ đăng ký sự kiện trên mỗi phần tử. –

+0

Không phải Event.stop (e) đang làm gì phải làm sao? Nó nên dừng sự kiện tuyên truyền, phải không? –

+0

@kiran, nó dừng tuyên truyền, nhưng sẽ không dừng bất kỳ trình xử lý nhấp chuột bổ sung nào được chỉ định trên nút, do đó chức năng này :) – epoch

Trả lời

0

Sau khi chạy với mã trên trong 3-4 tháng, cuối cùng tôi đã quyết định hoàn nguyên. Dường như có rất nhiều vấn đề, đặc biệt là khi xử lý nhiều khung và trình xử lý sự kiện trên một trang.

Hình phổ biến nhất là, Event.cache cho một phần tử cụ thể là undefined.

Điều này có thể do xử lý không chính xác ở trên, nhưng tôi rất nghi ngờ khung mới Event không chính xác bằng cách nào đó, vì hoàn nguyên về 1.7.0 hoàn toàn khắc phục tất cả các vấn đề tôi gặp phải.

Chỉ cần để tham khảo, đây là mã bây giờ tôi đang sử dụng với 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; 
} 
Các vấn đề liên quan