Skip to content

Commit

Permalink
Dialog: Awesome new stacking and overlay implementation. Fixes the fo…
Browse files Browse the repository at this point in the history
…llowing tickets:

Fixes #3534 - Dialog: Modal dialog disables all input elements on page.
Fixes #4671 - Dialog: Modal Dialog disables vertical scroll bar in Chrome & Safari.
Fixes #4995 - Dialog: Modal Dialog's overlay dissapears in IE when content is tall.
Fixes #5388 - Dialog: Don't change z-index when already at the top.
Fixes #5466 - Dialog: "modal" Dialog Incorrectly Cancels Input Events.
Fixes #5762 - Dialog: Get rid of z-index workaround, document it instead.
Fixes #6267 - Dialog: checkboxes that inherit a z-index < jqueryui.dialog z-index don't work.
Fixes #7051 - Dialog: modal prevents tab key from moving focus off slider handle.
Fixes #7107 - Dialog: Modal dialog event loss with high zindex child elements (FF 3.6).
Fixes #7120 - Dialog: Modal operation interrupts drag drop marker functionality on gmaps.
Fixes #8172 - Dialog: Change event cancelled when opening modal dialog from another modal dialog.
Fixes #8583 - Dialog: Mouse event wrongly stopped.
Fixes #8722 - Dialog: Remove stack option.
Fixes #8729 - Dialog: Remove zIndex option.
  • Loading branch information
Nate Eagle authored and jzaefferer committed Oct 24, 2012
1 parent 88bfb75 commit 3829a37
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 291 deletions.
3 changes: 2 additions & 1 deletion tests/unit/dialog/dialog.html
Expand Up @@ -52,7 +52,8 @@ <h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2> <h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol> <ol id="qunit-tests"></ol>
<div id="qunit-fixture"> <div id="qunit-fixture">

<div id="dialog1"></div>
<div id="dialog2"></div>
</div> </div>
</body> </body>
</html> </html>
1 change: 0 additions & 1 deletion tests/unit/dialog/dialog_common.js
Expand Up @@ -26,7 +26,6 @@ TestHelpers.commonWidgetTests( "dialog", {
stack: true, stack: true,
title: '', title: '',
width: 300, width: 300,
zIndex: 1000,


// callbacks // callbacks
create: null create: null
Expand Down
42 changes: 24 additions & 18 deletions tests/unit/dialog/dialog_methods.js
Expand Up @@ -106,24 +106,30 @@ test("isOpen", function() {
}); });


test("moveToTop", function() { test("moveToTop", function() {
expect( 3 ); expect( 5 );

function order() {
var d1, d2, dlg1, dlg2, var actual = $( ".ui-dialog" ).map(function() {
expected = $('<div></div>').dialog(), return +$( this ).find( ".ui-dialog-content" ).attr( "id" ).replace( /\D+/, "" );
actual = expected.dialog('moveToTop'); }).get().reverse();
equal(actual, expected, 'moveToTop is chainable'); deepEqual( actual, $.makeArray( arguments ) );

}
d1 = $('<div></div>').dialog(); var dialog1, dialog2,
dlg1 = d1.parents('.ui-dialog'); focusOn = "dialog1";
d1.dialog('close'); dialog1 = $( "#dialog1" ).dialog({
d1.dialog('open'); focus: function() {
d2 = $('<div></div>').dialog(); equal( focusOn, "dialog1" );
dlg2 = d2.parents('.ui-dialog'); }
d2.dialog('close'); });
d2.dialog('open'); focusOn = "dialog2";
ok(dlg1.css('zIndex') < dlg2.css('zIndex'), 'dialog 1 under dialog 2 before moveToTop method called'); dialog2 = $( "#dialog2" ).dialog({
d1.dialog('moveToTop'); focus: function() {
ok(dlg1.css('zIndex') > dlg2.css('zIndex'), 'dialog 1 above dialog 2 after moveToTop method called'); equal( focusOn, "dialog2" );
}
});
order( 2, 1 );
focusOn = "dialog1";
dialog1.dialog( "moveToTop" );
order( 1, 2 );
}); });


test("open", function() { test("open", function() {
Expand Down
79 changes: 2 additions & 77 deletions tests/unit/dialog/dialog_tickets.js
Expand Up @@ -99,10 +99,10 @@ test("#6137: dialog('open') causes form elements to reset on IE7", function() {
'<input type="radio" name="radio" id="b" value="b">b</input></form>').appendTo( "body" ).dialog({autoOpen: false}); '<input type="radio" name="radio" id="b" value="b">b</input></form>').appendTo( "body" ).dialog({autoOpen: false});


d1.find('#b').prop( "checked", true ); d1.find('#b').prop( "checked", true );
equal($('input:checked').val(), 'b', "checkbox b is checked"); equal(d1.find('input:checked').val(), 'b', "checkbox b is checked");


d1.dialog('open'); d1.dialog('open');
equal($('input:checked').val(), 'b', "checkbox b is checked"); equal(d1.find('input:checked').val(), 'b', "checkbox b is checked");


d1.remove(); d1.remove();
}); });
Expand All @@ -117,81 +117,6 @@ test("#6645: Missing element not found check in overlay", function(){
d1.add(d2).remove(); d1.add(d2).remove();
}); });


test("#6966: Escape key closes all dialogs, not the top one", function(){
expect(24);
// test with close function removing dialog triggered through the overlay
d1 = $('<div title="dialog 1">Dialog 1</div>').dialog({modal: true, close: function(){ d1.remove(); }});
d2 = $('<div title="dialog 2">Dialog 2</div>').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');

$( 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 = $('<div title="dialog 1">Dialog 1</div>').dialog({modal: true, close: function(){ d1.remove(); }});
d2 = $('<div title="dialog 2">Dialog 2</div>').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 = $('<div title="dialog 1">Dialog 1</div>').dialog({modal: true});
d2 = $('<div title="dialog 2">Dialog 2</div>').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 = $('<div title="dialog 1">Dialog 1</div>').dialog({modal: true});
d2 = $('<div title="dialog 2">Dialog 2</div>').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();
});

test("#4980: Destroy should place element back in original DOM position", function(){ test("#4980: Destroy should place element back in original DOM position", function(){
expect( 2 ); expect( 2 );
container = $('<div id="container"><div id="modal">Content</div></div>'); container = $('<div id="container"><div id="modal">Content</div></div>');
Expand Down
89 changes: 89 additions & 0 deletions tests/visual/dialog/complex-dialogs.html
@@ -0,0 +1,89 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Dialog Visual Test</title>
<link rel="stylesheet" href="../../../themes/base/jquery.ui.all.css">
<script src="../../../jquery-1.8.2.js"></script>
<script src="../../../external/jquery.bgiframe-2.1.2.js"></script>
<script src="../../../ui/jquery.ui.core.js"></script>
<script src="../../../ui/jquery.ui.widget.js"></script>
<script src="../../../ui/jquery.ui.mouse.js"></script>
<script src="../../../ui/jquery.ui.draggable.js"></script>
<script src="../../../ui/jquery.ui.position.js"></script>
<script src="../../../ui/jquery.ui.resizable.js"></script>
<script src="../../../ui/jquery.ui.dialog.js"></script>

<!-- stuff needed to make things complex -->
<script src="../../../ui/jquery.ui.datepicker.js"></script>
<script src="../../../ui/jquery.ui.menu.js"></script>
<script src="../../../ui/jquery.ui.autocomplete.js"></script>
<script src="../../../ui/jquery.ui.tooltip.js"></script>

<script>
$(function() {
$( "#dialog" ).dialog({
modal: true,
height: 300,
width: 500
});

var datepickerDialog = $( "#dialog-datepicker" ).dialog({
autoOpen: false,
modal: true,
}),

autocompleteDialog = $( "#dialog-autocomplete" ).dialog({
autoOpen: false,
modal: false,
width: 600
});

$( "#open-datepicker" ).click(function() {
datepickerDialog.dialog( "open" );
});

$( "#open-autocomplete" ).click(function() {
autocompleteDialog.dialog( "open" );
});

$( "#datepicker" ).datepicker();

$( "#autocomplete" ).autocomplete({
source: [
"ActionScript",
"AppleScript",
"Asp",
"BASIC",
"Scheme"
]
});

$( document ).tooltip();
});
</script>
</head>
<body>

<p>WHAT: A modal dialog opening another modal dialog (including a datepicker), opening a non-modal dialog (including an autocomplete with tooltip applied). A regular link on the page, outside of the dialogs.</p>
<p>EXPECTED: As long as a modal dialog is open, focus stays within the dialogs. Both mouse and keyboard interactions are captured and restricted to the dialog. When the nested modal dialog is open, the first modal dialog can't be interacted with, until the nested dialog is closed. When the third dialog is open (not modal), switching between the two dialogs is possible, both can be interacted with.</p>

<a href="#">Outside link</a>

<div id="dialog" title="Basic dialog">
<p>This is the default dialog which is useful for displaying information. The dialog window can be moved, resized and closed with the 'x' icon.</p>
<p><button id="open-datepicker">Open another window with a datepicker.</button></p>
</div>

<div id="dialog-datepicker" title="A dialog with a datepicker">
<p>Date: <input id="datepicker"></p>
<p><button id="open-autocomplete">Open another window with an autocomplete and a tooltip.</button></p>
</div>

<div id="dialog-autocomplete">
<label for="autocomplete">Tags: </label>
<input id="autocomplete" title="Try typing something!">
</div>

</body>
</html>
4 changes: 3 additions & 1 deletion themes/base/jquery.ui.core.css
Expand Up @@ -19,6 +19,8 @@
.ui-helper-clearfix { zoom: 1; } .ui-helper-clearfix { zoom: 1; }
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }


.ui-front { z-index: 100; }



/* Interaction Cues /* Interaction Cues
----------------------------------*/ ----------------------------------*/
Expand All @@ -36,4 +38,4 @@
----------------------------------*/ ----------------------------------*/


/* Overlays */ /* Overlays */
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } .ui-widget-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; }
2 changes: 1 addition & 1 deletion themes/base/jquery.ui.dialog.css
Expand Up @@ -8,7 +8,7 @@
* *
* http://docs.jquery.com/UI/Dialog#theming * http://docs.jquery.com/UI/Dialog#theming
*/ */
.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; } .ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; outline: 0; }
.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; } .ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; } .ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } .ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
Expand Down

2 comments on commit 3829a37

@jzaefferer
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@neagle Nate, could you sign our CLA? http://jquery.github.com/cla.html Thanks.

@neagle
Copy link

@neagle neagle commented on 3829a37 Nov 26, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

Please sign in to comment.