- From: Ian Hickson <ian@hixie.ch>
- Date: Tue, 17 Dec 2013 20:14:58 +0000 (UTC)
- To: Brian Blakely <anewpage.media@gmail.com>, Matt Falkenhagen <falken@chromium.org>, Scott González <scott.gonzalez@gmail.com>
- Cc: "whatwg@lists.whatwg.org" <whatwg@lists.whatwg.org>, Ojan Vafai <ojan@chromium.org>
On Sat, 2 Nov 2013, Brian Blakely wrote: > On Sat, Nov 2, 2013 at 5:29 PM, Ian Hickson <ian@hixie.ch> wrote: > > On Sat, 2 Nov 2013, Brian Blakely wrote: > > > > > > 1. When a modal dialog is active, the user can still scroll the > > > underlying page. > > > > Why is that a bug? > > By its nature, a modal view blocks interaction with the underlying > content. > > It's also inherently disorienting. Imagine opening a modal, > accidentally scrolling the underlying page while interacting with said > modal, then closing the modal and seeing something totally different > from before and not understanding why. This happens today with the > majority of our "lightbox" plugins, and we have the opportunity to fix > it now. I've changed the spec to make the ancestors of <dialog>s inert, so this should be fixed now. > > > 2. Even if the root element has overflow hidden, it should be > > > possible to scroll the modal "layer" when a dialog escapes the > > > boundaries of the viewport (or iframe). > > > > Why? Isn't the whole point of 'overflow: hidden' on the root element > > to prevent the ability to move the viewport? > > > > You can always but the overflow property on a child of the <body>, > > e.g. a fixed positioned <div>. Then the scrollbars would be hidden for > > the div, but the viewport could still be moved for dialogs. > > <div> wrappers are what we use today, and are what <dialog> should be > alleviating. Maybe ::backdrop should be a pseudo-parent for <dialog>, > with overflow: auto by default. At the very least, that would be a much > more flexible solution going forward. This is an interesting issue. Right now, arguably, even if the dialog isn't 'fixed' and the viewport isn't 'overflow:hidden', it's not clear that you can scroll if the dialog doesn't fit, because of the fix to the problem described above -- it's the same scrolling mechanism that scrolls the view of the dialog as scrolls the parent's contents -- in fact, the dialog is just part of the parent's contents. I'm not sure what the right answer is here. For dialogs whose containing block is the initial containing block, maybe we can require that, as a special case, the browser allow the viewport to be moved around to view the dialog (but then what happens if it _is_ overflow:hidden and the dialog goes away? Does it snap back? What about the background, what do we show in the parts the author never intended to have visible?). But what about when the dialog is in a <div> with overflow:scroll, if it's not absolutely positioned? I guess that's a rare case (and you can't position a dialog inside an overflow:scroll element because of the rule about the containing block for <dialog> elements), so maybe we ignore it. I've added a rule to the spec that says that viewports have to be pannable so you can see all of a dialog, but I don't know how feasible that really is. > > > 3. When the modal dialog's height changes, either due to CSS or > > > content changes, the vertical position of the dialog should change > > > (unless the height exceeds the viewport height). > > > > That's an interesting idea, but I'm not convinced it's the right > > answer. Having the dialog move up and down when stuff is added at the > > bottom would be quite weird. You can always implement this manually > > from script. > > To go back to hacky and rather difficult-to-maintain JS techniques for > something so simple seems antithetical to the intention of <dialog> to > me. Modern modal implementations don't require that. My point isn't that we shouldn't offer the feature because it is already possible. My point is that this feature is actively bad. I'm saying I don't think it's good UI for the dialog position to change when it increases in height. On Tue, 17 Dec 2013, Matt Falkenhagen wrote: > On Fri, Sep 27, 2013 at 7:15 AM, Ian Hickson <ian@hixie.ch> wrote: > > > > I started doing this, since several people have asked about this and > > it seems the consistency between showModalDialog()/close() seems less > > interesting to people than the consistency with "open" everywhere > > else. However, it turns out this would make the show() method clash > > with the "open" IDL attribute on <dialog>, which we want since it > > matches the name of the open="" content attribute which matches > > <details open>. > > > > Note that window.open() and document.open() don't really do the same > > as this method does, either. window.open() creates a new Window, or > > navigates and existing one; document.open() resets the document. > > dialog.show() just changes the dialog to be visible. > > > > Also, there's an interesting mix in other APIs. (Disclaimer: I don't > > know many of these APIs personally, so I may be misinterpreting their > > documentation wildly. I basically looked for terms like "open" and > > "close" in the docs and tried to see what the right methods were in > > each case. I only included methods for modal dialogs if there was a > > trivial method; many APIs have to be configured to make dialogs modals > > separately.) > > > > Android uses show() and dismiss() > > Closure uses setVisible() > > Cocoa uses makeKeyAndOrderFront:, orderOut:, close, and performClose:. > > Delphi uses Show(), ShowModal(), Hide(), and Close(). > > Ext JS uses show(), hide(), and close(). > > jQuery uses "open" and "close". > > Gtk uses gtk_widget_show(), gtk_dialog_run(), gtk_window_close(). > > Gtk also has gtk_widget_hide(), see [0] What's the difference between gtk_window_close and gtk_widget_hide? I couldn't tell from the documentation. > > .NET uses Show(), ShowDialog(), Hide(), and Close(). > > Win32 uses ShowWindow() and CloseWindow(). > > X11 uses XMapWindow() and XUnmapWindow() > > > > Most of the APIs I looked at use "close". Most use "show". So I think > > we're in ok company here. > > Sorry to add feedback so late. Whenever there's a post/tweet about > Chrome's <dialog>, the most common complaint from devs seems to be this > show/close naming. It's certainly a common complaint, but I don't understand why, given the existing naming conventions. > In the list of existing APIs above, only Win32 has only show/close. Delphi's Hide() and Close() are different. Close() is what you need to end a dialog's modal loop -- it sets a return value and hides the dialog. This is distinct from just Hide(), which makes the dialog invisible but keeps it modal. That is, conceptually, if this is a conversation the user is having with someone, Hide() is like that person stepping out of the way to afford the user a better view of the topic of conversation, while Close() is that person leaving the conversation. The semantic of Delphi's Close() is closer to what I'm looking for here. > Of APIs that have all of show/hide/close, it looks like close does > something like dispose of the object/free its memory so it can't be > shown again [...] So show/hide for <dialog> seems more consistent than > show/close with these APIs. I don't know if it's that simple. As noted above for Delphi's case, there's a difference between "hide" and "close", in that "hide" is just a matter of opacity, and "close" is when the dialog ends its life. In the case of HTML, you can set hidden="" on a <dialog>, and you can close it. Closing it does much more, e.g. setting returnValue, removing it from the pending dialog stack, firing events, etc. Yes, the dialog can be reused, it's not destroyed, but it's also not merely hidden. > Some additional data points: Thanks for the data. (Thanks also for the references.) So let's go through the list again. First let's put aside the ones that can't really help us. setVisible() doesn't fit any of the relevant idioms on the Web, so let's ignore those. We can also ignore X11 and Xt, which have their own idioms: Closure: setVisible() Java AWT: setVisible() (deprecated alternatives listed below) X11: XMapWindow(), XUnmapWindow() Xt: XtPopup(), XtPopdown() For opening the dialog, "open" is surprisingly rarely used. The only examples we found were HTML itself, and jQuery: HTML: window.open(), window.showModalDialog(), window.close() jQuery: "open", "close" BTW, jQuery actually does also use "show" for relevant API surface; it gives instructions on how to animate the opening of the dialog. Of all those that remain, only Cocoa doesn't use "show", and what it uses is Cocoa-specific: Cocoa: makeKeyAndOrderFront:, orderOut:, close, performClose: So it seems reasonable to use "show" for opening the dialog. For the modal case, we have ShowDialog(), ShowModal(), ..._run(), and showModalDialog(). ShowModal() appears twice, three times if you include showModalDialog(). Based on this, it seems reasonable to go with show() and showModal(). So that leaves the opposite end of the conversation. Here, Android is an outlier, so let's ignore that: Android: show(), dismiss() There's some that use some special names other than hide or close, e.g. wxWindows, which has Show(false) and EndModal(): wxWindows: Show(true), ShowModal(), Show(false), EndModal(), Close() ...and Qt, which really uses done() to close a dialog, not close(), since close() doesn't set the return value. (I'm ignoring "destroy" since many of these APIs have destructors with similar names, but those aren't really what we're looking for here.) So with that out of the way, there's five (four if you ignore the deprecated one) that only use "hide", not "close", as the key term: Bootstrap: show(), hide() Dojo: show(), hide() GWT: show(), hide() YUI: show(), hide() Java AWT deprecated API: show(), hide() There's five that use "close", not "hide", paired with either "show" or "open", plus Cocoa which uses "close", not "hide", but has other terms for opening, as mentioned earlier (Cocoa does use "hide" in some of its related APIs, but not as an imperative): Blackberry: show(), close() Win32: ShowWindow(), CloseWindow(). jQuery: "open", "close" HTML: window.open(), window.showModalDialog(), window.close() wxWindows: Show(true), ShowModal(), Show(false), EndModal(), Close() Cocoa: makeKeyAndOrderFront:, orderOut:, close, performClose: There's some that use both (though in all three cases I would argue that their use of "Close" is closer to what we want than their use of "Hide"): .NET: Show(), ShowDialog(), Hide(), Close() Delphi: Show(), ShowModal(), Hide(), Close() Ext JS: show(), hide(), close() ...and then there's some special cases, like Qt, mentioned above, where "done" is the one with the semantic we want, but where "close" and "hide" are also available with slightly different semantics: Qt: show(), hide(), close(), done() ...or Gtk, where the _window/dialog_ logic uses close(), but where you can also use the "inherited" hide() as far as I can tell: Gtk: gtk_widget_show(), gtk_dialog_run(), gtk_widget_hide(), gtk_window_close() This leads me to the same conclusion as before. show()/close() is the combination most consistent with existing APIs. But I think that's ok. We do _have_ "hide" in our API, it's just (like in Cocoa's case) not used as an imperative term, but as an attribute. <dialog> <dialog open=""> <dialog hidden=""> <dialog open="" hidden=""> dialog.open = true; dialog.open = false; dialog.hidden = true; dialog.hidden = false; dialow.show(); dialow.showModal(); dialog.returnValue = result; dialog.close(); dialog.close(result); "open" is the state meaning the dialog is up. "hidden" is the state meaning the rendering is not visible, which overrides "open". (Not dialog-specific.) show() sets open to true and positions the dialog. showModal() sets open to true, positions the dialog, and sets up the modality. close() sets the return value and sets open to false, unwinding the modality if necessary. We could use open()/openModal()/close() and have opened="" or isopen="" (after jQuery's "isOpen" and HTML's ismap=""), but the inconsistency with <details> would be hard to square, IMHO. And pretty much none of the APIs above use "open". They almost all use "show". We could do show/hide instead of show/close, and still use open="" for the visible state, but then there's the confusing similarity with hidden="" (it's very odd for hide() to remove open() rather than adding hidden=""). We could reuse hidden="" instead of open="". The problem there is that you'd have to always be declaring dialogs as <dialog hidden="">, which is pretty lame (that's why I made the default be hidden and used open="" to show the dialogs). I dunno. I certainly agree that it's weird to not have the two opposite imperative methods be antonyms. It's just that internal inconsistency is even worse than that. My conclusion is that it's a tough call, but the current API is probably the least bad compromise (there's a resounding endorsement, eh?). I'm not the final decider on this, though; that would be the browser vendors. I believe Blink is currently getting an implementation of this; if you can convince whoever is writing that code to use a different API, then I'll change the spec accordingly. Please do consider the whole language when doing so, though, not just <dialog>. A non-antonym pair of terms in an API is something you can learn easily enough; figuring out when to use open="" and when to use opened="" is much harder, especially when they're right next to each other. -- Ian Hickson U+1047E )\._.,--....,'``. fL http://ln.hixie.ch/ U+263A /, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Received on Tuesday, 17 December 2013 20:15:25 UTC