【问题标题】:Delaying default events in Javascript延迟Javascript中的默认事件
【发布时间】:2010-11-18 19:09:36
【问题描述】:

我希望能够延迟事件的默认操作,直到采取了其他操作。

它的用途:我正在尝试构建一种可重用、不显眼的方式来通过模态对话确认操作。关键的愿望清单项目是任何 Javascript 处理程序都由脚本附加,而不是直接内联编写。

为了使其真正可重用,我想在不同类型的项目上使用它:html 链接、复选框,甚至其他 Javascript 驱动的操作。对于像链接或复选框这样的纯 HTML 元素,我希望它们能够优雅地降级,这样它们就可以在不打开 Javascript 的情况下使用。

这是我对实现的设想:

<a href="/somelink/" class="confirm">Some Link</a>
_________

<script>
    attachEvent('a.confirm','click', confirmAction.fire)

    var confirmAction = (function(){
        var public = {
            fire: function(e){
                e.default.suspend();
                this.modal();
            },
            modal: function(){
                showmodal();
                yesbutton.onclick = this.confirmed;
                nobutton.onclick = this.canceled;
            },
            confirmed: function(){
                hidemodal();
                e.default.resume();
            },
            canceled: function(){
                hidemodal();
                e.default.prevent();
            }
        }
        return public;
    })()

</script>

我知道e.preventDefault 函数,但这会终止默认操作,而我无法恢复它。显然,default 对象与suspendresumeprevent 方法是为了说明我想要的结果。

顺便说一句,如果有帮助的话,我正在使用Ext.Core 库构建它。该库为处理事件提供了大量的规范化。但我真的很想在 Javascript 中学习它的一般原理。

【问题讨论】:

    标签: javascript user-interface dom-events


    【解决方案1】:

    要恢复,您可以尝试保存事件并重新触发它,设置一个可用于跳过调用 suspend() 的处理程序的标志(在您的示例中为“confirmAction.fire”)。

    <a href="/somelink/" class="confirm">Some Link</a>
    _________
    
    <script>
    function bindMethod(self, method) {
        return function() {
            method.apply(self, arguments);
        }
    }
    var confirmAction = (function(){
        var public = {
                delayEvent: function(e) {
                    if (e.suspend()) {
                        this.rememberEvent(e);
                        return true;
                    } else {
                        return false;
                    }
                },
                fire: function(e){
                    if (this.delayEvent(e)) {
                        this.modal();
                    }
                },
                modal: function(){
                        showmodal();
                        yesbutton.onclick = bindMethod(this, this.confirmed);
                        nobutton.onclick = bindMethod(this, this.canceled);
                },
                confirmed: function(){
                        hidemodal();
                        this.rememberEvent().resume();
                },
                canceled: function(){
                        hidemodal();
                        this.forgetEvent();
                },
                rememberEvent: function (e) {
                    if (e) {
                        this.currEvent=e;
                    } else {
                        return this.currEvent;
                    }
                },
                forgetEvent: function () {
                    delete this.currEvent;
                }
        }
        return public;
    })()
    
    // delayableEvent should be mixed in to the event class.
    var delayableEvent = (function (){
         return {
            suspend: function() {
                if (this.suspended) {
                    return false;
                } else {
                    this.suspended = true;
                    this.preventDefault();
                    return true;
                }
            },
            resume: function () {
                /* rest of 'resume' is highly dependent on event implementation, 
                   but might look like */
                this.target.fireEvent(this);
            }
         };
    })();
    
    /* 'this' in event handlers will generally be the element the listener is registered 
     * on, so you need to make sure 'this' has the confirmAction methods.
     */
    mixin('a.confirm', confirmAction);
    attachEvent('a.confirm','click', confirmAction.fire);
    </script>
    

    这仍然存在潜在的错误,例如它如何与其他事件侦听器交互。

    【讨论】:

    • 感谢您的好评。我不知道可以通过e 对象转移默认操作。我将尽快为此构建一个测试用例,并让您知道结果。
    • 请注意,我不小心留下了对 Event.default 属性的引用,该属性在 DOM 中不存在,我从未定义过,也想不出定义的方法。该代码并没有太多使用默认处理程序,因为它只是重新触发事件并包含一些代码以防止“触发”侦听器执行模态操作。
    • confirmedcanceled 监听器的注册方式也存在一个错误,导致“this”绑定不正确。通过添加 bindMethod 函数修复。 Ext.Core 可能有自己的bindMethod 版本。
    • 您还可以将可变参数rememberEvent(...) 拆分为rememberEvent(e)recallEvent()。我只使用了一种方法,因为“记住”这个词是模棱两可的。
    • 我可能实际上误解了您编写的某些内容的意图,但似乎将事件对象分配给另一个变量,然后像函数一样稍后调用它是行不通的。它(正确地)指向一个对象(事件对象)。据我所知,任何地方都没有直接指向实际操作的指针。我将不得不尝试一种不同的方法,可能是某种选择案例来确定默认操作应该是什么,以及一个额外的处理程序来重现该操作。
    猜你喜欢
    • 2012-07-23
    • 1970-01-01
    • 2020-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    相关资源
    最近更新 更多