103

When you use jquery UI dialog, all works well, except for one thing. When the browser is resized, the dialog just stays in it's initial position which can be really annoying.

You can test it out on: http://jqueryui.com/demos/dialog/

Click on the "modal dialog" example and resize your browser.

I'd love to be able to let dialogs auto-center when the browser resizes. Can this be done in an efficient way for all my dialogs in my app?

Zoe
  • 27,060
  • 21
  • 118
  • 148
Jorre
  • 17,273
  • 32
  • 100
  • 145

6 Answers6

164

Setting the position option will force this, so just use the same selector covering all your dialogs where I use #dialog here (if it doesn't find them no action is taken, like all jQuery):

jQuery UI before 1.10

$(window).resize(function() {
    $("#dialog").dialog("option", "position", "center");
});

jQuery UI 1.10 or higher

$(window).resize(function() {
    $("#dialog").dialog("option", "position", {my: "center", at: "center", of: window});
});

Here's that same jQuery UI demo page adding only the code above, we're just adding a handler to the window's resize event with .resize(), so it triggers the re-center at the appropriate time. ​

Nick Craver
  • 623,446
  • 136
  • 1,297
  • 1,155
  • thanks, that looks great. Maybe I should have told that I don't always know what the ID of my dialog is, like this (how can I target that dialog?): var $dialog = $('') .html(assetBrowser) .dialog({ autoOpen: false, title: 'Assets Manager', modal: true, closeOnEscape: true, buttons: buttons, width: 840, height: 500 }); $dialog.dialog('open'); – Jorre Jun 18 '10 at 09:03
  • 11
    @Jorre - They all get the same class when you create a dialog, to make it generic you can do this: `$(".ui-dialog-content").dialog("option", "position", "center");`, this will check for any dialog :) – Nick Craver Jun 18 '10 at 09:48
  • 3
    Unfortunately proposed answer affects badly resizing of dialog. When you try to resize it with SE handle, dialog gets resized on all 4 sides. –  Dec 22 '11 at 12:27
  • 2
    I recommend throttling or debouncing the resize event. I've seen IE7 & IE8 move the dialog "outside" the viewport due to the resize handler executing too many times. – BStruthers Apr 23 '13 at 15:49
  • 2
    On newer versions of the jQuery UI, I needed to use { my: "center", at: "center", of: window } instead of "center". I'm using 1.11.0. – Mike Dotterer Aug 14 '14 at 17:04
  • @marcovtwout While i don't disagree with your edit, i personally wouldn't recommend editing someone's 100+ scored answer to add content without the poster's approval. – Scimonster Nov 19 '14 at 10:58
  • @Scimonster I think it's odd noone ever noticed this issue before, since this answer stopped being correct 2 years ago. How would I go about asking approval? Isn't that what edit review is for? – marcovtwout Nov 19 '14 at 11:12
  • @marcovtwout It just might have been better to leave a comment here asking, first. Though now i see Mike's comment above from a few months ago, so i guess it's OK. – Scimonster Nov 19 '14 at 11:14
  • There seems to be an extra ')' at the end of the jQuery UI 1.10 or higher method – But those new buttons though.. Dec 15 '14 at 18:46
22

Alternatively to Ellesedil's answer,

That solution did not work for me straight away, So I did the following which is also dynamical but shortened version:

$( window ).resize(function() {
    $(".ui-dialog-content:visible").each(function () {
        $( this ).dialog("option","position",$(this).dialog("option","position"));
    });
});

+1 for Ellesedil though

EDIT:

Much shorter version which works great for single dialogs:

$(window).resize(function(){
    $(".ui-dialog-content").dialog("option","position","center");
});

It is not necessary for .each() to be used perhaps if you have some unique dialogs which you dont want to touch.

Pierre
  • 8,397
  • 4
  • 64
  • 80
  • using the class .ui-dialog-content is for all dialogs, the accepted answer is for a specific dialog – Pierre Dec 06 '13 at 11:20
  • Ah, right. Sorry. Didn't notice the distinction at first glance in the edit. – Ellesedil Dec 06 '13 at 15:24
  • I'm using this approach semi-successfully. It does as advertised but iOS 7 mobile safari really chokes if the keyboard is up. I've attempted to blur() the input but Gingerbread sees keyboard up as a resize event and gets stuck in a loop that never allows input entry. Anyone else facing this? – Joseph Juhnke Jan 30 '14 at 21:02
  • Maybe add a counter outside the `.resize()` and inside if counter reaches `10` or `20` then `break;`, I have not had this problem, I don't cater for those Devices/Browsers. You must try a solution that if it is stuck, you can get out of it – Pierre Feb 01 '14 at 06:50
  • Your first suggestion worked form and @Ellesedil 's answer did not. – akousmata Aug 28 '14 at 14:08
  • @akousmata: It was working on whatever version of jQuery I was using at the time. I'm no longer working on the project where I implemented this (or anything UI related right now, really). If you find a way to make it work in more recent jQuery versions, feel free to edit my answer. – Ellesedil Aug 28 '14 at 14:11
  • Well, this is old anyway - Move on to bootstrap. @Nakupanda has a great compilation for bootstrap. `http://nakupanda.github.io/bootstrap3-dialog/` `https://github.com/nakupanda/bootstrap3-dialog` – Pierre Aug 30 '14 at 14:54
13

A more comprehensive answer, which uses Nick's answer in a more flexible way can be found here.

An adaption of the code of relevance from that thread is below. This extension essentially creates a new dialog setting called autoReposition which accepts a true or false. The code as written defaults the option to true. Put this into a .js file in your project so that your pages can leverage it.

    $.ui.dialog.prototype.options.autoReposition = true;
    $(window).resize(function () {
        $(".ui-dialog-content:visible").each(function () {
            if ($(this).dialog('option', 'autoReposition')) {
                $(this).dialog('option', 'position', $(this).dialog('option', 'position'));
            }
        });
    });

This allows you to supply a "true" or "false" for this new setting when you create your dialog on your page.

$(function() {
    $('#divModalDialog').dialog({
        autoOpen: false,
        modal: true,
        draggable: false,
        resizable: false,
        width: 435,
        height: 200,
        dialogClass: "loadingDialog",
        autoReposition: true,    //This is the new autoReposition setting
        buttons: {
            "Ok": function() {
                $(this).dialog("close");
            }
        }
    });
});

Now this dialog will always reposition itself. AutoReposition (or whatever you call the setting) can handle any dialogs that do not have a default position and automatically reposition them when the window resizes. Since you're setting this when you create the dialog, you don't need to identify a dialog somehow because the repositioning functionality becomes built into the dialog itself. And the best part is that since this is set per dialog, you can have some dialogs reposition themselves and others remain where they are.

Credit to user scott.gonzalez on the jQuery forums for the complete solution.

nacho4d
  • 43,720
  • 45
  • 157
  • 240
Ellesedil
  • 1,576
  • 1
  • 20
  • 44
  • This addon/edit doesn't seem to work anymore as of July 2014. The answer from @Pierre works still. – degenerate Jul 03 '14 at 16:33
  • @degenerate: It's possible that updates to jQuery may necessitate changes to the syntax a bit. I'm no longer working or even have access to the project where I implemented this (actually, I'm currently writing APIs), so I don't have an easy way to determine if any changes are needed for recent jQuery versions. – Ellesedil Jul 03 '14 at 16:40
  • This answer does not work for recent versions. But the idea is great. This is the content of my window resize handler: `$(".ui-dialog-content:visible").each(function () { if ($(this).dialog('option', 'autoReposition')) { $(this).dialog('option', 'position', $(this).dialog('option', 'position')); } });` It works great :) – nacho4d Aug 21 '15 at 07:11
  • @nacho4d: Feel free to edit the answer and add the newer code for whatever jquery version you're working in to the bottom. – Ellesedil Aug 21 '15 at 07:15
  • 1
    @Ellesedil I just changed a couple of lines in your first chunk of code. Actually it is what scott.gonzalez wrote first in the thread. I don't know why he changed `$( "#dialog" ).dialog( "option", "position" ) ` to `$(this).data("dialog").options.position` later. Anyway, now this answer works! – nacho4d Aug 21 '15 at 14:24
3

Alternatively jQuery ui position can be used,

$(window).resize(function ()
{
    $(".ui-dialog").position({
        my: "center", at: "center", of: window
    });
});
AkilaI
  • 131
  • 9
2

Another CSS-only option which works is this. The negative margins should equal half your height and half your width. So in this case, my dialog is 720px wide by 400px tall. This centers it vertically and horizontally.

.ui-dialog {
  top:50% !important;
  margin-top:-200px !important; 
  left:50% !important;
  margin-left:-360px !important
}
Kirk Ross
  • 6,413
  • 13
  • 61
  • 104
0

Hello everyone!

Vanilla JS solution:

(function() {
  window.addEventListener("resize", resizeThrottler, false);

  var resizeTimeout;

  function resizeThrottler() {
    if (!resizeTimeout) {
      resizeTimeout = setTimeout(function() {
        resizeTimeout = null;
        actualResizeHandler();
      }, 66);
    }
  }

  function actualResizeHandler() {
    $(".ui-dialog-content").dialog("option", "position", { my: "center", at: "center", of: window });
  }
}());
Alexandr Kazakov
  • 682
  • 1
  • 7
  • 15