1
0
mirror of https://github.com/videojs/video.js.git synced 2025-01-02 06:32:07 +02:00

fix(spatial-navigation): keep navigation going when player has an error (#8805)

## Description
The bug:
 Focus is lost when playback error is displayed.

This small PR will update the spatial-navigation logic so when the error
modal is shown the spatial-navigation will try to focus the components
present in the error modal, in most cases this will be the vjs close
button.

## Specific Changes proposed
Keep navigation working when player shows the error modal by focusing a
component in that modal.

## Requirements Checklist
- [x] Feature implemented / Bug fixed
- [ ] If necessary, more likely in a feature request than a bug fix
- [ ] Change has been verified in an actual browser (Chrome, Firefox,
IE)
  - [ ] Unit Tests updated or fixed
  - [ ] Docs/guides updated
- [ ] Example created ([starter template on
JSBin](https://codepen.io/gkatsev/pen/GwZegv?editors=1000#0))
- [ ] Has no DOM changes which impact accessiblilty or trigger warnings
(e.g. Chrome issues tab)
  - [ ] Has no changes to JSDoc which cause `npm run docs:api` to error
- [ ] Reviewed by Two Core Contributors
This commit is contained in:
Carlos Javier Villaseñor Castillo 2024-07-22 16:43:20 -06:00 committed by GitHub
parent 86d29cdc66
commit 76e99b7bea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 25 additions and 3 deletions

View File

@ -56,6 +56,9 @@ class SpatialNavigation extends EventTarget {
this.player_.on('modalclose', () => { this.player_.on('modalclose', () => {
this.refocusComponent(); this.refocusComponent();
}); });
this.player_.on('error', () => {
this.focus(this.updateFocusableComponents()[0]);
});
this.player_.on('focusin', this.handlePlayerFocus_.bind(this)); this.player_.on('focusin', this.handlePlayerFocus_.bind(this));
this.player_.on('focusout', this.handlePlayerBlur_.bind(this)); this.player_.on('focusout', this.handlePlayerBlur_.bind(this));
this.isListening_ = true; this.isListening_ = true;
@ -196,7 +199,7 @@ class SpatialNavigation extends EventTarget {
} }
if (!(event.currentTarget.contains(event.relatedTarget)) && !isChildrenOfPlayer || !nextFocusedElement) { if (!(event.currentTarget.contains(event.relatedTarget)) && !isChildrenOfPlayer || !nextFocusedElement) {
if (currentComponent.name() === 'CloseButton') { if (currentComponent && currentComponent.name() === 'CloseButton') {
this.refocusComponent(); this.refocusComponent();
} else { } else {
this.pause(); this.pause();
@ -307,7 +310,11 @@ class SpatialNavigation extends EventTarget {
return null; return null;
} }
return searchForSuitableChild(component.el()); if (component.el()) {
return searchForSuitableChild(component.el());
}
return null;
} }
/** /**
@ -464,7 +471,7 @@ class SpatialNavigation extends EventTarget {
*/ */
refocusComponent() { refocusComponent() {
if (this.lastFocusedComponent_) { if (this.lastFocusedComponent_) {
// If use is not active, set it to active. // If user is not active, set it to active.
if (!this.player_.userActive()) { if (!this.player_.userActive()) {
this.player_.userActive(true); this.player_.userActive(true);
} }
@ -492,6 +499,10 @@ class SpatialNavigation extends EventTarget {
* @param {Component} component - The component to be focused. * @param {Component} component - The component to be focused.
*/ */
focus(component) { focus(component) {
if (typeof component !== 'object') {
return;
}
if (component.getIsAvailableToBeFocused(component.el())) { if (component.getIsAvailableToBeFocused(component.el())) {
component.focus(); component.focus();
} else if (this.findSuitableDOMChild(component)) { } else if (this.findSuitableDOMChild(component)) {

View File

@ -44,6 +44,7 @@ QUnit.test('start method initializes event listeners', function(assert) {
assert.ok(onSpy.calledWith('loadedmetadata'), 'loadedmetadata event listener added'); assert.ok(onSpy.calledWith('loadedmetadata'), 'loadedmetadata event listener added');
assert.ok(onSpy.calledWith('modalKeydown'), 'modalKeydown event listener added'); assert.ok(onSpy.calledWith('modalKeydown'), 'modalKeydown event listener added');
assert.ok(onSpy.calledWith('modalclose'), 'modalclose event listener added'); assert.ok(onSpy.calledWith('modalclose'), 'modalclose event listener added');
assert.ok(onSpy.calledWith('error'), 'error event listener added');
// Additionally, check if isListening_ flag is set // Additionally, check if isListening_ flag is set
assert.ok(this.spatialNav.isListening_, 'isListening_ flag is set'); assert.ok(this.spatialNav.isListening_, 'isListening_ flag is set');
@ -491,3 +492,13 @@ QUnit.test('should call `searchForTrackSelect()` if spatial navigation is enable
assert.ok(trackSelectSpy.calledOnce); assert.ok(trackSelectSpy.calledOnce);
}); });
QUnit.test('error on player calls updateFocusableComponents', function(assert) {
const updateFocusableComponentsSpy = sinon.spy(this.spatialNav, 'updateFocusableComponents');
this.spatialNav.start();
this.player.error('Error 1');
assert.ok(updateFocusableComponentsSpy.calledOnce, 'on error event spatial navigation should call "updateFocusableComponents"');
});