I've found that tall dialogs in dijit.Dialog result in an impossible location of the dialog. The top is above the page and the bottom below, making it impossible to exit or edit (scrolling doesn't work since the scroll event reposition the dialog).
The _position function in dijit.Dialog doesn't consider the size of the dialog box. Here is my solution, maybe not the prettiest but it seems to work:
_position: function(){
// summary: position modal dialog in center of screen
if(dojo.hasClass(dojo.body(),"dojoMove")){ return; }
var viewport = dijit.getViewport();
var mb = dojo.marginBox(this.domNode);
var style = this.domNode.style;
style.left = Math.floor((viewport.l + (viewport.w - mb.w)/2)) + "px";
// Change to avoid the dialog being outside the viewport
var top = Math.floor((viewport.t + (viewport.h - mb.h)/2));
// A standard margin is nice to have for layout reasons
// I think it should be proportional to the page height
var margin = Math.floor(viewport.h/30);
// The top can't be less than viewport top
if (top - margin < viewport.t)
{
top = viewport.t + margin;
}
// If the height of the box is the same or bigger than the viewport
// it means that the box should be made scrollable and a bottom should be set
if (mb.h + margin*2 >= viewport.h){
style.overflow = "auto";
// The bottom is margin - the scroll of the page
style.bottom = (margin - viewport.t) + "px";
}
style.top = top + "px";
},
// summary: position modal dialog in center of screen
if(dojo.hasClass(dojo.body(),"dojoMove")){ return; }
var viewport = dijit.getViewport();
var mb = dojo.marginBox(this.domNode);
var style = this.domNode.style;
style.left = Math.floor((viewport.l + (viewport.w - mb.w)/2)) + "px";
// Change to avoid the dialog being outside the viewport
var top = Math.floor((viewport.t + (viewport.h - mb.h)/2));
// A standard margin is nice to have for layout reasons
// I think it should be proportional to the page height
var margin = Math.floor(viewport.h/30);
// The top can't be less than viewport top
if (top - margin < viewport.t)
{
top = viewport.t + margin;
}
// If the height of the box is the same or bigger than the viewport
// it means that the box should be made scrollable and a bottom should be set
if (mb.h + margin*2 >= viewport.h){
style.overflow = "auto";
// The bottom is margin - the scroll of the page
style.bottom = (margin - viewport.t) + "px";
}
style.top = top + "px";
},

RE: CLA, there isn't much
RE: CLA, there isn't much that will 'happen'. Aimee will make note that you have submitted your CLA, and then when you submit patches you can put CLA on file in trac ticket or someone will come along behind you and do the same thing if they know who filed the ticket.
As far as your actual problem, It was my understanding that Dialog expect the content to be sized and the dialog expands to that space,
The problem arises when the
The problem arises when the dialog is bigger than the viewport, taller to be exact. The dialog size depends on what you put into the div. I consider this a semiserious bug since on small screens like a phone this will probably be an issue even in tiny login forms.
I think what Dustin is referring to...
...is the need for the developer to put an explicit height on the central content pane in the dialog in question, probably in conjunction with overflow: auto on the same node, so that you can stick as much content within the dialog you want. You'll end up with a scrollbar in the middle of the dialog but that's a lot better than letting it stretch to a height greater than the viewport.
#5286
Yes, see #5286.
I think your solution doesn't solve the whole problem since the bottom of the dialog is still off the screen.
The second part:
The second part covers the scrolling being disabled:
{
style.top = top + "px";
}
Unless the div is outside the viewport then the style won't be set if the size is bigger than the screen (viewport).
height?
Don't you need to reduce the height of the Dialog.containerNode, to enable a scrollbar on the dialog box? Or are you suggesting the user use the scrollbar on the browser itself?
I scroll the browser and not
I scroll the browser and not the div, both have their pros and cons. To set overflow style, set bottom of the dialog box will probably require more lines of code... I gave it a shot but couldn't get it to work with:
style.bottom = "20px";
style.overflow = "auto";
}
oh i see
OK, I understand what you mean then :-). Yeah I think that's OK for a typical page but would look weird for an app-type page like yahoo mail. As you said, there are pros and cons.
My latest version of the
My latest version of the code that seem to work with both a large dialog and a small regular dialog. Checked in ff2 in a scrollpage setting.
// summary: position modal dialog in center of screen
if(dojo.hasClass(dojo.body(),"dojoMove")){ return; }
var viewport = dijit.getViewport();
var mb = dojo.marginBox(this.domNode);
var style = this.domNode.style;
style.left = Math.floor((viewport.l + (viewport.w - mb.w)/2)) + "px";
// Change to avoid the dialog being outside the viewport
var top = Math.floor((viewport.t + (viewport.h - mb.h)/2));
// The top can't be less than 0
if (top < 0)
{
// A standard margin is nice to have
top = 20;
}
// Make the div scrollable
if (mb.h + top > viewport.h){
style.bottom = (20 - viewport.t) + "px";
style.overflow = "auto";
mb = dojo.marginBox(this.domNode);
}
style.top = top + "px";
style.bottom = (mb.b - viewport.t) + "px";
},
Thanks
This is a nice solution to a problem that's been driving me nuts for a while in my application - we have some dialogs that are just too large - maybe not the best use of a dialog, but it's what the client wants so I had to try to set heights manually but then on large monitors some dialogs are much smaller than they need to be and on very small screens it still causes scrolling off the screen.
Have you tested your solution on multiple browsers? Also, I assume the same logic could be uses to set the style.right for when it's too wide?
The only thing I do NOT like about this is the "Loading..." message is now displayed with in a tall skinny dialog on some of my dialogs that take longer to load. Any ideas on how to deal with that?
Josh
no go on ie
Couple things I noticed:
1. the last line uses mb.b - that's not a property of marginBox (w,h,l,t are) so I'm not sure what that last line was attempting to do. I only noticed the error when trying to run this in ie6, firefox didn't complain about mb.b being undefined.
2. speaking of ie - this whole idea doesn't seem to work at all in ie6. :( setting style.overflow = 'auto' happens, but IE always renders the dialog in its full size. I unfortunately cannot ignore ie6 so I'll have to find an alternate solution to this problem.
Thanks,
Josh
1. Thanks, fixed. See the
1. Thanks, fixed. See the very first post for an update.
2. That's a bummer, how is ie7? How u tried setting overflow = 'scroll'?
I've only tested with ff2.
I've only tested with ff2. It works nicely although I've found that it doesn't work scrolling upwards the last scroll. I need to have another look at the code. I think the top margin should be a proportion of the viewport height and I'm planning on adding that.
Some notes
Thanks - I'd be interested in any updates you make cause I've spent 3 hours playing with this and things are still working very strangely. I think there may be some race conditions with the time _position is called because on some occasions the behavior is different.
I have a dialog the loads external content via the href paramater - sometimes it takes a few moments. What I first notice is that the Dialog is adjusted before this message so the "Loading..." message appears in a tall/skinny box while xhr does it's thing. The next thing I notice is that the dialog is "sort of" centered - it's usually a little bit to the right and a little bit lower than center. If I use the browsers main scrollbar (which connects to Dialog.layout) then it centers.
Now the above I could deal with, but if I close this particular dialog and re-open it, then the "Loading" message is in a tall skinny dialog again, but this time it's so large that the title is off-screen. Then when the dialog content shows up it does adjust somewhat but again, the TitleBar is off screen. Once again if I use the browser scrollbar a little the dialog will eventually resize and recenter to the desired location. It seems to me that perhaps the marginBox returned from dojo.marginBox is not quite ready at the time _position is called and hence the calculations are a bit off? I'm also lead to this conclusion by the fact that sometimes even the first dialog appearance has a TitleBar off screen.
If you want I can provide screen shots or can walk you through my application to help.
Thanks,
Josh
I've updated the code on top
I've updated the code on top of the page to my latest version. This one seems to work nicely. Checked with a small dialog and a really large one. I have been scrolling like crazy and only found a bug in firefox (the rendering sometimes becomes a little weird, nothing important).
I think your problem with the size of the app is that you should do a diji.byId('my_dialog_div').layout() after each change of data. I've done without the loading message so far in my app (the load is pretty fast) but It's a little tempting I must say...
mgordon - wish you were two
mgordon - wish you were two hours faster. I stopped trying to mess with _position and decided instead to try this approach:
1. save cookie with dojo.cookie on browser resize (which fires onload too) of the viewport width/height
2. when I show a dialog I check the values of this cookie and make sure the dialog's width/height are set appropriate for this value and set overflow to auto. I allow the user to define the max width/height and make some other calculations to try to get an ideal size. (this is for an app where dialog content could be just about anything)
I think IE's overflow probably should have worked (maybe it was cause of the mb.b error?) and I might try this out again but I have other fish to fry now. :) I still like your solution best cause it handles resizing events and doesn't require cookies.
FWIW - you may want to style this.containerNode instead of this.domNode - sometimes the scrollbar (noticed on ie) will show up on top of the titlebar's "X", whereas setting containerNode.overflow = auto will show the scrollbar under the title bar.
Cheers,
Josh