From cab4c467d9c12ec61a652c3bf68eedd166319b34 Mon Sep 17 00:00:00 2001 From: Jay Merrifield Date: Thu, 3 May 2012 19:02:23 -0400 Subject: [PATCH] Dialog: Handle escape for all overlays. Fixes #8300 - Dialog: Incorrect behavior for ESCAPE with multiple modal dialogs. --- tests/unit/dialog/dialog_tickets.js | 64 +++++++++++++++++++++++++---- ui/jquery.ui.dialog.js | 26 +++++++----- 2 files changed, 72 insertions(+), 18 deletions(-) diff --git a/tests/unit/dialog/dialog_tickets.js b/tests/unit/dialog/dialog_tickets.js index a169bd1a5..98983cf33 100644 --- a/tests/unit/dialog/dialog_tickets.js +++ b/tests/unit/dialog/dialog_tickets.js @@ -117,26 +117,76 @@ test("#6645: Missing element not found check in overlay", function(){ }); test("#6966: Escape key closes all dialogs, not the top one", function(){ - expect(8); - // test with close function removing dialog - d1 = $('
Dialog 1
').dialog({modal: true}); + expect(24); + // test with close function removing dialog triggered through the overlay + d1 = $('
Dialog 1
').dialog({modal: true, close: function(){ d1.remove(); }}); d2 = $('
Dialog 2
').dialog({modal: true, close: function(){ d2.remove(); }}); - ok(d1.dialog("isOpen"), 'first dialog is open'); - ok(d2.dialog("isOpen"), 'second dialog is open'); - d2.simulate("keydown", {keyCode: $.ui.keyCode.ESCAPE}); - ok(d1.dialog("isOpen"), 'first dialog still open'); + + ok(d1.data('dialog') && d1.dialog('isOpen'), 'first dialog is open'); + ok(d2.data('dialog') && d2.dialog('isOpen'), 'second dialog is open'); + + $( document ).simulate('keydown', {keyCode: $.ui.keyCode.ESCAPE}); + ok(d1.data('dialog') && d1.dialog('isOpen'), 'first dialog still open'); ok(!d2.data('dialog'), 'second dialog is closed'); + + $( document ).simulate('keydown', {keyCode: $.ui.keyCode.ESCAPE}); + ok(!d1.data('dialog'), 'first dialog is closed'); + ok(!d2.data('dialog'), 'second dialog is closed'); + + d2.remove(); + d1.remove(); + + // test with close function removing dialog triggered through the dialog + d1 = $('
Dialog 1
').dialog({modal: true, close: function(){ d1.remove(); }}); + d2 = $('
Dialog 2
').dialog({modal: true, close: function(){ d2.remove(); }}); + + ok(d1.data('dialog') && d1.dialog('isOpen'), 'first dialog is open'); + ok(d2.data('dialog') && d2.dialog('isOpen'), 'second dialog is open'); + + d2.simulate('keydown', {keyCode: $.ui.keyCode.ESCAPE}); + ok(d1.data('dialog') && d1.dialog('isOpen'), 'first dialog still open'); + ok(!d2.data('dialog'), 'second dialog is closed'); + + d1.simulate('keydown', {keyCode: $.ui.keyCode.ESCAPE}); + ok(!d1.data('dialog'), 'first dialog is closed'); + ok(!d2.data('dialog'), 'second dialog is closed'); + d2.remove(); d1.remove(); // test without close function removing dialog d1 = $('
Dialog 1
').dialog({modal: true}); d2 = $('
Dialog 2
').dialog({modal: true}); + ok(d1.dialog("isOpen"), 'first dialog is open'); ok(d2.dialog("isOpen"), 'second dialog is open'); + d2.simulate("keydown", {keyCode: $.ui.keyCode.ESCAPE}); ok(d1.dialog("isOpen"), 'first dialog still open'); ok(!d2.dialog("isOpen"), 'second dialog is closed'); + + d1.simulate("keydown", {keyCode: $.ui.keyCode.ESCAPE}); + ok(!d1.dialog("isOpen"), 'first dialog is closed'); + ok(!d2.dialog("isOpen"), 'second dialog is closed'); + + d2.remove(); + d1.remove(); + + // test without close function removing dialog triggered through the overlay + d1 = $('
Dialog 1
').dialog({modal: true}); + d2 = $('
Dialog 2
').dialog({modal: true}); + + ok(d1.dialog("isOpen"), 'first dialog is open'); + ok(d2.dialog("isOpen"), 'second dialog is open'); + + $( document ).simulate("keydown", {keyCode: $.ui.keyCode.ESCAPE}); + ok(d1.dialog("isOpen"), 'first dialog still open'); + ok(!d2.dialog("isOpen"), 'second dialog is closed'); + + $( document ).simulate("keydown", {keyCode: $.ui.keyCode.ESCAPE}); + ok(!d1.dialog("isOpen"), 'first dialog is closed'); + ok(!d2.dialog("isOpen"), 'second dialog is closed'); + d2.remove(); d1.remove(); }); diff --git a/ui/jquery.ui.dialog.js b/ui/jquery.ui.dialog.js index 144cf9725..45ee37789 100644 --- a/ui/jquery.ui.dialog.js +++ b/ui/jquery.ui.dialog.js @@ -713,21 +713,25 @@ $.extend( $.ui.dialog.overlay, { } }, 1 ); - // allow closing by pressing the escape key - $( document ).bind( "keydown.dialog-overlay", function( event ) { - if ( dialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && - event.keyCode === $.ui.keyCode.ESCAPE ) { - - dialog.close( event ); - event.preventDefault(); - } - }); - // handle window resize $( window ).bind( "resize.dialog-overlay", $.ui.dialog.overlay.resize ); } - + var $el = ( this.oldInstances.pop() || $( "
" ).addClass( "ui-widget-overlay" ) ); + + // allow closing by pressing the escape key + $( document ).bind( "keydown.dialog-overlay", function( event ) { + var instances = $.ui.dialog.overlay.instances; + // only react to the event if we're the top overlay + if ( instances.length !== 0 && instances[ instances.length - 1 ] === $el && + dialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && + event.keyCode === $.ui.keyCode.ESCAPE ) { + + dialog.close( event ); + event.preventDefault(); + } + }); + $el.appendTo( document.body ).css({ width: this.width(), height: this.height()