Delaying default events in Javascript

旧街凉风 提交于 2021-02-19 04:37:10

问题


I would like to be able to delay the default action of an event until some other action has been taken.

What it's for: I'm trying to build a reusable, unobtrusive way to confirm actions with a modal-type dialogue. The key wishlist item is that any Javascript handlers are attached by a script, and not written directly inline.

To make this truly reusable, I want to use it on different types of items: html links, checkboxes, and even other Javascript-driven actions. And for purely HTML elements like links or checkboxes, I want them to degrade gracefully so they're usable without Javascript turned on.

Here's how I would envision the implementation:

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

I know about the e.preventDefault function, but that will kill the default action without giving me the ability to resume it. Obviously, the default object with the suspend, resume and prevent methods is made up to illustrate my desired end.

By the way, I'm building this using the Ext.Core library, if that helps. The library provides a good deal of normalization for handling events. But I'm really very interested in learning the general principles of this in Javascript.


回答1:


To resume, you could try saving the event and re-fire it, setting a flag that can be used to skip the handlers that call suspend() ('confirmAction.fire', in your example).

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

This still has potential bugs, such as how it interacts with other event listeners.



来源:https://stackoverflow.com/questions/1263327/delaying-default-events-in-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!