reiern70 opened a new issue, #1620:
URL: https://github.com/apache/wicket/issues/1620

   ### Summary
   
   `Wicket.trapFocus`'s keydown handler in 
`wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/modal/trap-focus.js`
 resolves the first and last focusable elements with `$focusable.get(0)` and 
`$focusable.get($focusable.length - 1)` — plain DOM elements, not jQuery 
objects — and then calls `.trigger('focus')` on them. Tabbing past the last 
focusable element (or Shift+Tabbing past the first) inside a focus-trapped 
container, such as a `ModalDialog`, throws a `TypeError` instead of wrapping 
focus around to the other end.
   
   Affects the `wicket-10.x` branch, same regression range as GitHub issue 
#1618. `master` is not affected (see below).
   
   ### Reproduction
   
   Open any component that uses `TrapFocusBehavior` (e.g. a `ModalDialog`), 
then press Tab while focus is on the last focusable element inside it (or 
Shift+Tab while focus is on the first).
   
   Observed in the browser console:
   
   ```
   Uncaught TypeError: lastFocusable.trigger is not a function
       at HTMLElement.<anonymous> (trap-focus.js:...)
   ```
   
   Focus does not wrap around to the other end of the trap.
   
   ### Cause
   
   ```js
   $element.on("keydown", function(e) {
        if (Wicket.Event.keyCode(e) === 9) { // tab
                var $focusable = findFocusable($element);
                if ($focusable.length > 0) {
                        var firstFocusable = $focusable.get(0);
                        var lastFocusable  = $focusable.get($focusable.length - 
1);
   
                        if (e.shiftKey) {
                                if (e.target === firstFocusable || 
$element.is(e.target)) {
                                        e.preventDefault();
                                        lastFocusable.trigger('focus');   // 
<-- TypeError
                                }
                        } else {
                                if (e.target === lastFocusable || 
$element.is(e.target)) {
                                        e.preventDefault();
                                        firstFocusable.trigger('focus');  // 
<-- TypeError
                                }
                        }
                }
        }
   });
   ```
   
   `$focusable.get(index)` returns a plain DOM node, so `.trigger('focus')` is 
not a function on it. The two other `.trigger('focus')` calls in the same file 
(`findFocusable($element).first().trigger('focus')`) are unaffected, since 
`.first()` returns a jQuery object.
   
   ### Regression range
   
   Same as GitHub issue #1618: introduced by the jQuery 4.0.0 migration 
(WICKET-7179), which mechanically rewrote `.focus()` as `.trigger('focus')` 
without checking whether the receiver was a jQuery object.
   
   `master` regained plain `.focus()` incidentally when it later dropped jQuery 
from this file entirely. `wicket-9.x` and `wicket-8.x` predate the migration 
and use `.focus()` directly on the same raw DOM elements.
   
   ### Suggested fix
   
   On `wicket-10.x`, replace the two calls with `.focus()`:
   
   ```diff
   -                                    lastFocusable.trigger('focus');
   +                                    lastFocusable.focus();
   ...
   -                                    firstFocusable.trigger('focus');
   +                                    firstFocusable.focus();
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to