在Javascript中延迟默认事件

时间:2009-08-11 22:26:46

标签: javascript javascript-events user-interface

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

它的用途:我正在尝试建立一种可重复使用,不引人注目的方式来确认模态对话的动作。关键的wishlist项是任何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函数,但是这会在没有让我恢复它的情况下终止默认操作。显然,使用defaultsuspendresume方法的prevent对象可以用来说明我想要的结果。

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

谢谢!

1 个答案:

答案 0 :(得分:0)

要恢复,您可以尝试保存事件并重新启动它,设置一个标志,可用于跳过调用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>

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