Single ESC closes ALL modal dialogs in jQuery UI.

2019-04-09 20:06发布

问题:

Actually, there was (is still) a bug in jQuery: http://bugs.jqueryui.com/ticket/4511.

The reason for this behavior (from the bug description comments): "The dialog itself binds keydown event to itself for closing the dialog on ESC; in addition, the dialog overlay binds a keydown event to the document, without filtering to close only the active dialog."

I cannot come up with an idea of an acceptable workaround. Is there anyone who has had to deal with it yet?

回答1:

Very simple - upon creating a modal dialog, run this:

$([document, window]).unbind('.dialog-overlay'); 

If you create more then one modal dialog, hitting ESC will close the top one only. Then once you focus on the bottom dialog, hit ESC and it will close it as well.

Hope this helped!

P.S. jQuery UI developers should add an option when you want all dialogs close at once upon hitting ESC key or only the focused ones.



回答2:

Easiest thing is I have added event.stopPropagation(); in close function before return self; in jquery.ui.dialog.js file. And I am done with problem of closing dialog boxes one by one on escape keydown. Let me know if anyone find any better solution.

EDITED: this need to add because while clicking on close button event object is undefined.

if(typeof event != 'undefined'){ event.stopPropagation(); }



回答3:

The root of the problem is that jQuery UI keydown event propagates through all dialogs. A fix in the original jQueryUI Dialog code would be to add event.stopPropagation() when topmost dialog was successfully closed and check event.isPropagationStopped() at the beginning of the same keydown event.

As a workaround I did, thanks for Jazzer, the following.

  1. Set dialog option closeOnEscape to false

  2. When dialog gets created, append:

    //newDialog is dialog's content, e.g. var newDialog = $('my dialog content>');
    newDialog.keydown(function(event) {
         if (mydialogs.hasOpenDialogs() && 
             event.keyCode && 
             event.keyCode === $.ui.keyCode.ESCAPE) {
                            $(newDialog).dialog("close");
                            event.preventDefault();
    event.stopPropagation(); } });

  3. when document is loaded do:

    $(function(){
    //allow for ESC to close only top dialog
    $(document).bind('keydown', function(event) {
        if (event.isPropagationStopped()) return true;
        if (mydialogs.hasOpenDialogs() && 
            event.keyCode && 
            event.keyCode === $.ui.keyCode.ESCAPE) {
                            mydialogs.closeTopDialog();
                            event.preventDefault();
                            event.stopPropagation();
        }
    });
    });
    

Event in (2) happens when user hits ESC while typing text in input box inside of the dialog. Event in (3) happens when user hits ESC somewhere else.

mydialogs here is a wrapper around stack (array) of modal dialogs, where every new dialog adds itself via .push() and in .close() removes itself with .pop().