Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Updated: Comment 0
Problem/Motivation
After #1851414: Convert Views to use the abstracted dialog modal went in, dialogs don't close via escape anymore.
Proposed resolution
Remaining tasks
User interface changes
API changes
Related Issues
Comment | File | Size | Author |
---|---|---|---|
#14 | core-js-modal-focus-2113567-14.patch | 548 bytes | nod_ |
#12 | 2113567-12-drupal-modal-refocus.patch | 1.59 KB | jessebeach |
#8 | Content__Content____Drupal_D8_Dev_and_Content__Content____Drupal_D8_Dev.png | 283.54 KB | jessebeach |
#8 | Content__Content____Drupal_D8_Dev.png | 266.84 KB | jessebeach |
Comments
Comment #1
jessebeach CreditAttribution: jessebeach commentedClose via Esc does work, but not on the second and third modals in a flow. I'm looking into this.
Comment #2
andypostConfirm that close on Esc works (chrome, ff)
Maybe purpose of the issue is disable this?
Comment #3
dawehnerIt does not work for me on chrome.
Comment #4
jessebeach CreditAttribution: jessebeach commenteddawehner, what dialog did you test? Can you point me to a path?
Comment #5
dawehnerThank you for the help on this issue.
I am looking at /admin/structure/views/view/content and testing the "add field", "add filter" but also editing any filter or field.
The tested chrome version is:
Version 28.0.1500.71 Ubuntu 13.04 (28.0.1500.71-0ubuntu1.13.04.1)
It works though fine on firefox.
Comment #6
jessebeach CreditAttribution: jessebeach commentedReproduced, I think.
Everything works fine on FF, as noted.
On Chrome. the esc key closes the dialog if I simply open the Add field dialog and press esc. If I choose an option in the dialog and press apply, so that the form in the dialog refreshes, then the esc key no longer closes the dialog.
Does that describe your experience dawehner?
Comment #7
dawehnerOh I see, chrome sets the focus to the "For: " select element so you need to get out of that first.
Comment #8
jessebeach CreditAttribution: jessebeach commentedOk, I know the "why" now. At first I though it had something to do with the keypress binding getting lost when the contents of the dialog refreshes. So I tested this theory and found that the handler fires on the first load of the dialog and after a refresh of the content in a multistep form. So this isn't the issue. BUT, I did notice that sometimes the esc key press wouldn't fire in Chrome if the dialog didn't have focus. So after clicking on it a couple times to give it focus, it finally dawned on me that this is the real issue.
In Firefox, some element of the dialog has focus as we move from the first form to the second in a multiform sequence. We know this by checking the
document.activeElement
property on the page.Notice that in the first dialog load, the select box is in focus. On the second page in the form, the
.ui-dialog
element has the page focus.In Chrome, we lose focus on the dialog after it refresh for the second page in the multiform. The focus shifts to the
body
.So pressing the esc key never bubbles through the dialog element.
Now, I don't yet know why we're getting inconsistent focus behavior, but at least I know what to fix!
Comment #9
jessebeach CreditAttribution: jessebeach commentedadding JavaScript tag.
Comment #10
dawehnerjessebeach++
This is really impressive stuff.
Comment #11
jessebeach CreditAttribution: jessebeach commentedSo, the problem comes down to this little bit of code in
jquery.ui.dialog.js
in theopen
method:When we load content into the dialog via AJAX, we call the
openDialog
method in the Drupal dialog code. This in turn invokes thedialog
method on the existing dialog wrapper. If the dialog is already open (this._isOpen
), then the jQuery UI dialog simply checks to see if this dialog was moved -- that is, is there anything visible in the DOM after this modal (i.e. any following siblings before the end body tag)? If not, then it simply returns without calling the rest of the open method code. So, thethis._focusTabbable
method is not called when we refresh the content of the dialog via AJAX. Bummer :/I'm looking for the best way to get around this without hacking jQuery UI, which is not really an option. Our dialog code should do something to refocus the first tabbable when we call our proprietary
open
method on an existing jQuery UI dialog.Comment #12
jessebeach CreditAttribution: jessebeach commentedThe jQuery UI Dialog
_moveToTop
method is checking to see if anything in the DOM follows the modal dialog. If yes, then it has "moved" and focus is recalculated.So we trick jQuery UI into thinking that something exists after an already-open dialog.
Why trick jQuery? Well, I want to have the stand focus calculation run, rather than just setting the focus ourselves, because the dialog widget has a
focus
callback that gets triggered when the focus is recalculated. By tricking it, we ensure that this callback is invoked appropriately when we refresh the content of an existing dialog.Comment #13
dawehnerYour amount of effort is incredible. Thank you!
Manually testing led to the following effect: Escaping out of the dialog was not
possible until i pressed tab one time, but this worked reproducable. (I ensured that the actual js file was loaded)
Comment #14
nod_I agree, great work on finding out and spelling out the problem. The solution is simpler though.
The focus problem is when content is changed through AJAX right? so the focus issue should be solved in a behavior. See the patch, we're even removing a sort of hack as well and no tricking of jQuery needed.
Comment #15
dawehner@nod_
As far as I understand the actual content of the modal is NOT loaded via ajax but just via the URL of the link directly.
Additional "dialog.ajax.js" is not loaded at all on a normal view admin UI screen.
Comment #16
ekl1773Confirmed that modals don't close using esc without this patch.
Tested patch in Chrome and FF with overlay by opening admin/structure/views/view/content, adding two new fields and then attempting to use esc to close the modal. This worked fine for me.
Comment #17
nod_@dawehner dialog.ajax.js is properly added, check the network tab and filter by xhr requests, it should show up whenever you open a modal in views.
Comment #18
jessebeach CreditAttribution: jessebeach commentedIf we just call focus on the dialog element, then the
dialogfocus
event will only be triggered when the dialog opens, not on subsequent focus events. Try out this code in dialog.js for an example of thefocus
callback. It will only be invoked when the Views dialog is opened, not on subsequent content refresh/refocus. I think we do need to trick jQuery UI in order to maintain consistent behavior.Comment #19
jessebeach CreditAttribution: jessebeach commentednod_ and I had a chat and he's convinced me that the approach in #14 is fine. Specifically:
I agree. So, let's go with the patch in #14.
Comment #20
catchSo is this our bug really, or is it worth filing an upstream report for jQuery UI?
Committed/pushed to 8.x, nice work tracking this down, leaving open in case it's worth opening the bug report, can close if it isn't, or if we open one :)
Comment #21
nod_I don't feel it's an upstream issue. We're replacing the content with ajax commands and running behaviors on top of that. Not typical jQuery UI stuff :)
Also I'm not even sure it's possible to fix upstream.
Comment #22
nod_