Javascript PrototypeJS事件注册表问题

Javascript PrototypeJS事件注册表问题,javascript,prototypejs,dom-events,Javascript,Prototypejs,Dom Events,在1.7.3更新之后,原型事件注册表似乎出现了问题,我在元素存储上使用prototype\u event\u注册表来访问单击事件,以便重播它们 这样我就可以停止事件并根据回调选择恢复它们,一切正常,但在查看1.7.0和1.7.3的差异后,它似乎被删除了 我知道这是内部的,我可能一开始就不应该使用它。总之,我的问题是: 我已经更新了我的代码以使用1.7.3,但它对我来说似乎非常粗糙,有更好的方法吗 /** * creates a toggling handler for click events

1.7.3
更新之后,原型事件注册表似乎出现了问题,我在元素存储上使用
prototype\u event\u注册表来访问单击事件,以便重播它们

这样我就可以停止事件并根据回调选择恢复它们,一切正常,但在查看
1.7.0
1.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;
}
/**
*为单击事件创建切换处理程序,同时考虑以前的单击事件。
*
*w.r.t停止点击事件,处理按钮为提交或普通按钮的情况。
*对于提交,调用Event.stop()就足够了,因为按钮上没有其他侦听器。
*但是,如果一个普通按钮有一个调用save()的处理程序,另一个处理程序使用客户端代码并调用stop,
*它不会影响事件的停止,因为event.stop只停止传播,而不停止其他处理程序!
*
*请注意,此函数将始终在任何其他已定义事件之前执行指定的处理程序。
*
*@param{Element}Element用于此单击事件的元素
*@param{Function}handler用于此停止单击事件的处理程序,如果此处理程序返回true,
*将阻止单击事件的所有其他操作
*@返回{Element}作为参数提供的元素
*/
函数stoppingClickEvent(元素、处理程序){
if(!element)throw'不能使用方法,if element未定义';
//如果未提供任何处理程序,则分配默认处理程序
handler=handler | | Prototype.emptyFunction;
if(element.type&&element.type==='submit'){
元素上('click',函数(submitEvent){
//调用提供的处理程序,当前元素作为上下文,事件作为参数
//如果返回true,我们应该停止事件
var stopEvent=handler.call(元素,submitEvent);
如果(停止事件){
//因为元素的默认操作是提交表单,所以我们阻止它
submitEvent.stop();
}
});
}否则{
//prototype 1.7.3取消了对“prototype\u event\u registry”的支持,因此我们需要在这里进行多次破解
//首先获取元素的窗口,以便我们可以访问原型
//来自正确上下文(帧)的事件缓存
var elementDoc=element.ownerDocument;
var elementWindow=elementDoc.defaultView | | elementDoc.parentWindow;
如果(!elementWindow){
throw'无法访问元素'+element.id'的窗口对象;
}
//我们正在处理一个普通元素的单击事件,所以我们不知道设置了多少个单击事件。
//把他们都抓起来,这样我们就可以决定是否给他们打电话。
//FIXME:需要一个更好的方法来做这件事吗
var registry=elementWindow['Event'].cache[element._prototypeUID | | | element.uniqueID]| |{},
事件=注册表[“单击”]| |[];
//现在我们有了事件的副本,我们可以停止所有事件并添加新的处理程序
元素。停止观察('click')。打开('click',函数(clickEvent){
//调用提供的处理程序,当前元素作为上下文,事件作为参数
//如果返回true,我们应该停止事件
var stopEvent=handler.call(元素,clickEvent);
如果(!stopEvent){
//不应停止该事件,请运行所有原始单击事件
events.each(函数(包装器){
wrapper.handler.call(元素,clickEvent);
});
}
});
}
返回元素;
}

在使用上述代码运行了3-4个月后,我最终决定恢复它。似乎有很多问题,特别是在处理单个页面上的多个帧和事件处理程序时

最常见的是,
Event.cache
,用于
未定义的特定元素

这可能是因为上面的处理不正确,但我高度怀疑新的
事件
框架在某种程度上是不正确的,因为还原到
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;
}
/**
*为单击事件创建切换处理程序,同时考虑以前的单击事件。
*
*w.r.t停止点击事件,处理按钮为提交或普通按钮的情况。
*对于提交,调用Event.stop()就足够了,因为按钮上没有其他侦听器。
*但是,如果一个普通按钮有一个调用save()的处理程序,另一个处理程序使用客户端代码并调用stop,
*它不会影响事件的停止,因为event.stop只停止传播,而不停止其他处理程序!
*
*请注意,此函数将始终在任何其他已定义事件之前执行指定的处理程序。
*
*@param{Element}Element用于此单击事件的元素
*@param{Function}handler用于此停止单击事件的处理程序,如果此处理程序返回true,
*将阻止单击事件的所有其他操作
*@返回{Element}作为参数提供的元素
*/
函数stoppingClickEvent(元素、处理程序){
if(!element)throw'不能使用方法,if element未定义';
//如果未提供任何处理程序,则分配默认处理程序
handler=handler | | Prototype.emptyFunction;
if(element.type&&element.type==='submit'){
元素上('click',函数(submitEvent){
//使用当前元素a调用提供的处理程序