feat: implement spatial navigation (#8570)
* feat(player): add spatialNavigation feature
Adds spatialNavigation feature to enhance user experience
- Implemented spatial navigation in slider component
- Enhanced player functionality for improved navigation
* feat(player): add spatialNavigation class
Adds spatialNavigation class to manage spatial-navigation-polyfill
- Set class SpatialNavigation on its own file
- Imported SpatialNavigation class on component class
* feat(player): update spatialNavigation class
Adds 3 methods to spatialNavigation class to manage spatial-navigation-polyfill
- Added start() to: Start listen of keydown events
- Added stop() to: Stop listen key down events
- Added getComponents() to: Get current focusable components
* feat(player): modify spatialNavigation class & modify component class
Modify spatialNavigation class:
-Remove unrequired version of function ‘getComponents’
Modify component class:
-Add function ‘getIsFocusable’
* Added methods getPositions, handleFocus and handleBLur for spatial navigation needs
* feat(player): modify Component class, BigPlayButton class & ClickableComponent class
Modify Component class:
-Add method getIsAvailableToBeFocused
-Modify method getIsFocusable to only focus on finding focusable candidates
Modify spatialNavigation class:
-Remove unrequired method ‘getIsFocusable’
Modify component class:
-Remove unrequired method ‘getIsFocusable’
* Added import in player.js, Created base methods inside spatial-navigation.js
* feat(player): modify Component class & SpatialNavigation class
Modify Component class:
-Modify method getIsAvailableToBeFocused to be more strict on candidates
Modify spatialNavigation class:
-Modify method getComponents to get all focusable components
* feat(player): modify Component class
Modify Component class:
-Add documentation to ‘isVisible’ function
* added keydown event logic for spatial-navigation
* feat(player): modify SpatialNavigation class
Modify SpatialNavigation class:
-Modify documentation of functions
* feat(player): modify SpatialNavigation class
Modify SpatialNavigation class:
-Add ‘clear’ & ‘remove’ methods
* feat(player): modify SpatialNavigation class
Modify SpatialNavigation class:
-Add documentation of functions
* feat(player): modify SpatialNavigation class
Modify SpatialNavigation class:
-Add function ‘getCurretComponent’‘’
* feat(player): modify SpatialNavigation class
Modify SpatialNavigation class:
-Add documentation for ‘findBestCandidate’ method
* Added logic for moving focus to the best candidate
* Implemented move, findBestCandidate, isInDirection, and calculateDistance methods for spatial navigation logic
* Added a new player option enableKeydownListener, Added gap: 1px to control-bar for spatial-navigation-polyfill needs
* feat(player): modify SpatialNavigation class & Component class
Modify SpatialNavigation class:
-Add function ‘handlePlayerBlur’
-Add function ‘handlePlayerFocus’
Modify Component class:
-Modify ‘handleBlur’
-Modify ‘handleFocus’
* Removed enableKeydownListener flag, as user should start the SpatialNavigation manually
* Added functionality to track changes in the focusableComponents list (custom event focusableComponentsChanged)
* feat(player): modify SpatialNavigation class, ModalDialog & Component class
Modify SpatialNavigation class:
-Add ‘lastFocusedComponent’
-Add function ‘refocusComponent’
Modify ModalDialog class:
-Add condition on ‘close’ function
Modify Component class:
-Modify ‘handleBlur’ to store blurred component
* feat(player): modify ModalDialog
Modify ModalDialog:
-Add condition to close Modal on Backspace
* Refactor SpatialNavigation to use player.spatialNavigation
* Added a new custom event endOfFocusableComponents
* Added new styles for focused elements in case spatial navigation is enabled
* feat(player): modify SpatialNavigation class:
-Add condition so getComponents can get as candidates the UI elements from the playlist-ui
* Changed to window.SpatialNabigation to this.player_.spatialNavigation
* feat(player): modify text-track-settings, created test-track-settings-colors.js, text-track-settings-font.js,text-track-fieldset.js & text-track-select.js:
Modify text-track-settings class:
- Add changes so newly created components can work as content of the modal.
- Create new components as a refactor of the contents of text-track-settings
* changed handleKeyDown inside component.js, getComponents method is now iterating player.children
* feat(player): create TrackSettingsControls Component & Modify TextTrackSettings
Create TrackSettingsControls Component:
-Create Component to show buttons reset & done as components.
Modify TextTrackSettings:
-Add Component TrackSettingsControls in TextTrackSettings
* feat(player): Modify ModalDialog
Modify ModalDialog:
-Add condition for stop propagation of event inside of ModalDialog when spatialNavigation is enabled
* getIsFocusable and getIsAvailableToBeFocused methods are now accepting el as a parameter, added a new methods findSuitableDOMChild and focus for spatialNavigation class
* feat(player): Modify TextTrackSettings:
Modify TextTrackSettings:
-Remove unrequired methods to create DOM elements since now those are created by Components.
* feat(player): Modify CaptionSettingsMenuItem:
Modify CaptionSettingsMenuItem:
-Add condition to focus component of TextTrackSelect when modal is open
* feat(player): Modify TextTrackSelect & TextTrackFieldset:
Modify TextTrackSelect :
Modify TextTrackFieldset:
-Add comments to certain functions to explain the code
* feat(player): Modify TrackSettingsControls:
Modify TrackSettingsControls:
-Remove unrequired comments & add comments to certain functions to explain the code
* feat(player): Modify SpatialNavigation, Component & ModalDialog:
Modify SpatialNavigation:
Modify Component:
Modify ModalDialog:
-Add & update comments of documentation.
* Handle ENTER keydown in Modals when spatial navigation is enabled
* feat(player): Modify ModalDialog, spatialNavigation, TrackSettingsControls, TextTrackFieldset, TextTrackSelect, TrackSettingsColors, TrackSettingsFont:
Modify ModalDialog:
Modify spatialNavigation:
Modify TrackSettingsControls:
Modify TextTrackFieldset:
Modify TextTrackSelect:
Modify TrackSettingsColors:
Modify TrackSettingsFont:
-Add & update comments of documentation.
* Implement additional RCU controls
* feat(player): Modify Component class:
Modify Component :
-Remove unrequired condition inside of handleFocus method.
* feat(player): Modify ModalDialog & CaptionSettingsMenuItem
Modify ModalDialog:
Modify CaptionSettingsMenuItem:
-Modify spatialNavigation condition to be more specific regarding spatialNavigation implementation.
* feat(player): Modify SpatialNavigation class:
Modify SpatialNavigation :
-Fix bug where ‘enter’ press was not working properly on select component inside of the ‘vjs-text-track-settings’ modal.
* feat(player): Modify SpatialNavigation class:
Modify SpatialNavigation :
-Minor improvements on the loops of certain functions to stop when they have found the element they are looking for.
-Implement minor spacing formatting on switch statement.
* Update src/js/component.js
More understandable documentation.
Co-authored-by: Dzianis Dashkevich <98566601+dzianis-dashkevich@users.noreply.github.com>
* Update src/js/component.js
More understandable documentation.
Co-authored-by: Dzianis Dashkevich <98566601+dzianis-dashkevich@users.noreply.github.com>
* feat(player): Modify SpatialNavigation & Component class:
Modify Component class :
Modify SpatialNavigation class :
-Modify ‘getIsFocusable’ function to use ‘this.el_’ instead of ‘el’ parameter
* feat(player): Modify SpatialNavigation class:
Modify SpatialNavigation class :
-Refactor onKeyDown function to use static data & return when pause is true.
* feat(player): Modify SpatialNavigation class:
Modify SpatialNavigation class :
-Refactor to use ‘.el()’ instead of ‘.el_’
* Update src/js/spatial-navigation.js
Co-authored-by: Walter Seymour <walterseymour15@gmail.com>
* feat(player): Modify ModalDialog class & MenuItem class:
Modify ModalDialog class :
Modify MenuItem class :
-Correct typo of ‘isSpatialNavlistening’ to ‘isSpatialNavListening’.
* removed unused property, remove this.focus, which was added for testing purposes
* Changed parameters to private, removed redundant code, removed initialFocusedComponent parameter, change STEP_SECONDS to static
* feat(player): solve remaining conflict:
Modify Spatial Navigation class :
- Solve conflict
* feat(player): Rename TrackSettingsColors & TrackSettingsFont
* feat(player): Remove unrequired functions calls from components TextTrackSettingsColors & TextTrackSettingsFont.
* feat(player): Update spatial-navigation.js's keypress return keyword.
* bind focus and blur just if spatial navigation is enabled, add 1px gap if spatial navigation is enabled
* feat(player): Modify calls on 'isListening' & 'isPaused' for ModalDialog & TextTrackMenuItem
* feat(player): remove unrequired object on component 'TrackSettingsControls'
* Removed 1px gap
* feat(player): Rename function ‘getComponents’ to ‘updateFocusableComponents’
* Changed SpatialNavigation class to extend EventTarget, removed redundant methods for events
* fix(player): fix call of 'getIsAvailableToBeFocused' that was throwing an error.
* removed Static maps for key presses and extended keycode with the missing keys
* refactor(player): Modify functions of 'getIsDisabled', 'getIsExpresslyInert' & 'getIsFocusable' to be more in pair when stablished code of the player.
* Conditional assignment for keycode.codes.back based on platform, changed Backspace to Back key for Modal closing
* Extend the object for reverse lookup, prenet Up/down keys to open a menu if spatial navigation is anabled
* refactor(player): Refactor 'SpatialNavKeycodes' file to not patch 'keycode' dependency
* fix(pllayer): fix issue related to 'back' not being used properly in function 'isEventKey'
* feat(player): Rename imports of 'spatial-navigation-keycode' to have their extension
* feat(player): Add example of use of 'Client app uses a global spatial-navigation solution'
* feat(player): rename 'spatial-navigation-keycode.js' filename
* Fix on src chnage issue, ESC button closing modal, expand vjs-modal-dialog
* change file name and object name
* fix: Update ids of labels to use 'guid' so unit test works properly
* fix: update localized text in text-track-settings-font & text-track-settings
* Mark some methods as private
* fix: modify content of modal 'text-track-settings' to change language properly
* fix: add missing '.' in jsdoc of text-track components
* feature: add unit test for 'text-track-select' component
* Add test for Spatial Navigation
* test(player): Add minor test related to 'handleBlur' & 'handleFocus'
* feat(player): Remove unrequired files from 'react-video-nav-app'
* test(player): Add small test to check if 'getPositions' returns required properties
* test(player): add test to verify 'getPositions()' properties are not empty
* Add missing tests for performMediaAction_ and move
* test(player): add test to for 'component.js' related to 'handleBlur'
* test(player): add minor test in component related to test keypress propagation event
* test(player): add test for component related to 'getIsAvailableToBeFocused' function
* test(player): add test for Modal Dialog related to call function of spatial navigation
* test(player): add tests for 'spatial-navigation-key-codes'
* test(player): add tests for keycodes related to 'should return event name if keyCode is not available'
* test(player): add minor test for case when not required parametters are passed
* test(player): add test for 'caption-settings-menu-item'
* feat(player): remove 'react-video-nav-app'
* Move handleFocus and handleBlur from components.js to spatial-navigation.js
* refactor(player): refactor 'searchForTrackSelect' to be handled in the spatial navigation
* remove unrequired code in function 'searchForTrackSelect'
* update documentation comment to be in pair to its current use
* remove spatial navigation keydown from modal dialog and move it to spatial navigation class, modify the modal-dialog test accordingly
* remove useless tests
* Remove caption-settings-menu-item.test.js
* Add minor test to 'searchForTrackSelect' in spatial-navigation.test.js
* Add unit test for back key and listening to events
---------
Co-authored-by: CarlosVillasenor <carlosdeveloper9@gmail.com>
Co-authored-by: Dzianis Dashkevich <98566601+dzianis-dashkevich@users.noreply.github.com>
Co-authored-by: Walter Seymour <walterseymour15@gmail.com>
Co-authored-by: Carlos Villasenor Castillo <cvillasenor@Carloss-MacBook-Pro.local>
2024-04-18 03:34:52 +02:00
/* eslint-env qunit */
import SpatialNavigation from '../../src/js/spatial-navigation.js' ;
import SpatialNavigationKeyCodes from '../../src/js/utils/spatial-navigation-key-codes' ;
import TestHelpers from './test-helpers.js' ;
import sinon from 'sinon' ;
import document from 'global/document' ;
import TextTrackSelect from '../../src/js/tracks/text-track-select' ;
2024-07-29 20:11:58 +02:00
import * as Dom from '../../src/js/utils/dom.js' ;
feat: implement spatial navigation (#8570)
* feat(player): add spatialNavigation feature
Adds spatialNavigation feature to enhance user experience
- Implemented spatial navigation in slider component
- Enhanced player functionality for improved navigation
* feat(player): add spatialNavigation class
Adds spatialNavigation class to manage spatial-navigation-polyfill
- Set class SpatialNavigation on its own file
- Imported SpatialNavigation class on component class
* feat(player): update spatialNavigation class
Adds 3 methods to spatialNavigation class to manage spatial-navigation-polyfill
- Added start() to: Start listen of keydown events
- Added stop() to: Stop listen key down events
- Added getComponents() to: Get current focusable components
* feat(player): modify spatialNavigation class & modify component class
Modify spatialNavigation class:
-Remove unrequired version of function ‘getComponents’
Modify component class:
-Add function ‘getIsFocusable’
* Added methods getPositions, handleFocus and handleBLur for spatial navigation needs
* feat(player): modify Component class, BigPlayButton class & ClickableComponent class
Modify Component class:
-Add method getIsAvailableToBeFocused
-Modify method getIsFocusable to only focus on finding focusable candidates
Modify spatialNavigation class:
-Remove unrequired method ‘getIsFocusable’
Modify component class:
-Remove unrequired method ‘getIsFocusable’
* Added import in player.js, Created base methods inside spatial-navigation.js
* feat(player): modify Component class & SpatialNavigation class
Modify Component class:
-Modify method getIsAvailableToBeFocused to be more strict on candidates
Modify spatialNavigation class:
-Modify method getComponents to get all focusable components
* feat(player): modify Component class
Modify Component class:
-Add documentation to ‘isVisible’ function
* added keydown event logic for spatial-navigation
* feat(player): modify SpatialNavigation class
Modify SpatialNavigation class:
-Modify documentation of functions
* feat(player): modify SpatialNavigation class
Modify SpatialNavigation class:
-Add ‘clear’ & ‘remove’ methods
* feat(player): modify SpatialNavigation class
Modify SpatialNavigation class:
-Add documentation of functions
* feat(player): modify SpatialNavigation class
Modify SpatialNavigation class:
-Add function ‘getCurretComponent’‘’
* feat(player): modify SpatialNavigation class
Modify SpatialNavigation class:
-Add documentation for ‘findBestCandidate’ method
* Added logic for moving focus to the best candidate
* Implemented move, findBestCandidate, isInDirection, and calculateDistance methods for spatial navigation logic
* Added a new player option enableKeydownListener, Added gap: 1px to control-bar for spatial-navigation-polyfill needs
* feat(player): modify SpatialNavigation class & Component class
Modify SpatialNavigation class:
-Add function ‘handlePlayerBlur’
-Add function ‘handlePlayerFocus’
Modify Component class:
-Modify ‘handleBlur’
-Modify ‘handleFocus’
* Removed enableKeydownListener flag, as user should start the SpatialNavigation manually
* Added functionality to track changes in the focusableComponents list (custom event focusableComponentsChanged)
* feat(player): modify SpatialNavigation class, ModalDialog & Component class
Modify SpatialNavigation class:
-Add ‘lastFocusedComponent’
-Add function ‘refocusComponent’
Modify ModalDialog class:
-Add condition on ‘close’ function
Modify Component class:
-Modify ‘handleBlur’ to store blurred component
* feat(player): modify ModalDialog
Modify ModalDialog:
-Add condition to close Modal on Backspace
* Refactor SpatialNavigation to use player.spatialNavigation
* Added a new custom event endOfFocusableComponents
* Added new styles for focused elements in case spatial navigation is enabled
* feat(player): modify SpatialNavigation class:
-Add condition so getComponents can get as candidates the UI elements from the playlist-ui
* Changed to window.SpatialNabigation to this.player_.spatialNavigation
* feat(player): modify text-track-settings, created test-track-settings-colors.js, text-track-settings-font.js,text-track-fieldset.js & text-track-select.js:
Modify text-track-settings class:
- Add changes so newly created components can work as content of the modal.
- Create new components as a refactor of the contents of text-track-settings
* changed handleKeyDown inside component.js, getComponents method is now iterating player.children
* feat(player): create TrackSettingsControls Component & Modify TextTrackSettings
Create TrackSettingsControls Component:
-Create Component to show buttons reset & done as components.
Modify TextTrackSettings:
-Add Component TrackSettingsControls in TextTrackSettings
* feat(player): Modify ModalDialog
Modify ModalDialog:
-Add condition for stop propagation of event inside of ModalDialog when spatialNavigation is enabled
* getIsFocusable and getIsAvailableToBeFocused methods are now accepting el as a parameter, added a new methods findSuitableDOMChild and focus for spatialNavigation class
* feat(player): Modify TextTrackSettings:
Modify TextTrackSettings:
-Remove unrequired methods to create DOM elements since now those are created by Components.
* feat(player): Modify CaptionSettingsMenuItem:
Modify CaptionSettingsMenuItem:
-Add condition to focus component of TextTrackSelect when modal is open
* feat(player): Modify TextTrackSelect & TextTrackFieldset:
Modify TextTrackSelect :
Modify TextTrackFieldset:
-Add comments to certain functions to explain the code
* feat(player): Modify TrackSettingsControls:
Modify TrackSettingsControls:
-Remove unrequired comments & add comments to certain functions to explain the code
* feat(player): Modify SpatialNavigation, Component & ModalDialog:
Modify SpatialNavigation:
Modify Component:
Modify ModalDialog:
-Add & update comments of documentation.
* Handle ENTER keydown in Modals when spatial navigation is enabled
* feat(player): Modify ModalDialog, spatialNavigation, TrackSettingsControls, TextTrackFieldset, TextTrackSelect, TrackSettingsColors, TrackSettingsFont:
Modify ModalDialog:
Modify spatialNavigation:
Modify TrackSettingsControls:
Modify TextTrackFieldset:
Modify TextTrackSelect:
Modify TrackSettingsColors:
Modify TrackSettingsFont:
-Add & update comments of documentation.
* Implement additional RCU controls
* feat(player): Modify Component class:
Modify Component :
-Remove unrequired condition inside of handleFocus method.
* feat(player): Modify ModalDialog & CaptionSettingsMenuItem
Modify ModalDialog:
Modify CaptionSettingsMenuItem:
-Modify spatialNavigation condition to be more specific regarding spatialNavigation implementation.
* feat(player): Modify SpatialNavigation class:
Modify SpatialNavigation :
-Fix bug where ‘enter’ press was not working properly on select component inside of the ‘vjs-text-track-settings’ modal.
* feat(player): Modify SpatialNavigation class:
Modify SpatialNavigation :
-Minor improvements on the loops of certain functions to stop when they have found the element they are looking for.
-Implement minor spacing formatting on switch statement.
* Update src/js/component.js
More understandable documentation.
Co-authored-by: Dzianis Dashkevich <98566601+dzianis-dashkevich@users.noreply.github.com>
* Update src/js/component.js
More understandable documentation.
Co-authored-by: Dzianis Dashkevich <98566601+dzianis-dashkevich@users.noreply.github.com>
* feat(player): Modify SpatialNavigation & Component class:
Modify Component class :
Modify SpatialNavigation class :
-Modify ‘getIsFocusable’ function to use ‘this.el_’ instead of ‘el’ parameter
* feat(player): Modify SpatialNavigation class:
Modify SpatialNavigation class :
-Refactor onKeyDown function to use static data & return when pause is true.
* feat(player): Modify SpatialNavigation class:
Modify SpatialNavigation class :
-Refactor to use ‘.el()’ instead of ‘.el_’
* Update src/js/spatial-navigation.js
Co-authored-by: Walter Seymour <walterseymour15@gmail.com>
* feat(player): Modify ModalDialog class & MenuItem class:
Modify ModalDialog class :
Modify MenuItem class :
-Correct typo of ‘isSpatialNavlistening’ to ‘isSpatialNavListening’.
* removed unused property, remove this.focus, which was added for testing purposes
* Changed parameters to private, removed redundant code, removed initialFocusedComponent parameter, change STEP_SECONDS to static
* feat(player): solve remaining conflict:
Modify Spatial Navigation class :
- Solve conflict
* feat(player): Rename TrackSettingsColors & TrackSettingsFont
* feat(player): Remove unrequired functions calls from components TextTrackSettingsColors & TextTrackSettingsFont.
* feat(player): Update spatial-navigation.js's keypress return keyword.
* bind focus and blur just if spatial navigation is enabled, add 1px gap if spatial navigation is enabled
* feat(player): Modify calls on 'isListening' & 'isPaused' for ModalDialog & TextTrackMenuItem
* feat(player): remove unrequired object on component 'TrackSettingsControls'
* Removed 1px gap
* feat(player): Rename function ‘getComponents’ to ‘updateFocusableComponents’
* Changed SpatialNavigation class to extend EventTarget, removed redundant methods for events
* fix(player): fix call of 'getIsAvailableToBeFocused' that was throwing an error.
* removed Static maps for key presses and extended keycode with the missing keys
* refactor(player): Modify functions of 'getIsDisabled', 'getIsExpresslyInert' & 'getIsFocusable' to be more in pair when stablished code of the player.
* Conditional assignment for keycode.codes.back based on platform, changed Backspace to Back key for Modal closing
* Extend the object for reverse lookup, prenet Up/down keys to open a menu if spatial navigation is anabled
* refactor(player): Refactor 'SpatialNavKeycodes' file to not patch 'keycode' dependency
* fix(pllayer): fix issue related to 'back' not being used properly in function 'isEventKey'
* feat(player): Rename imports of 'spatial-navigation-keycode' to have their extension
* feat(player): Add example of use of 'Client app uses a global spatial-navigation solution'
* feat(player): rename 'spatial-navigation-keycode.js' filename
* Fix on src chnage issue, ESC button closing modal, expand vjs-modal-dialog
* change file name and object name
* fix: Update ids of labels to use 'guid' so unit test works properly
* fix: update localized text in text-track-settings-font & text-track-settings
* Mark some methods as private
* fix: modify content of modal 'text-track-settings' to change language properly
* fix: add missing '.' in jsdoc of text-track components
* feature: add unit test for 'text-track-select' component
* Add test for Spatial Navigation
* test(player): Add minor test related to 'handleBlur' & 'handleFocus'
* feat(player): Remove unrequired files from 'react-video-nav-app'
* test(player): Add small test to check if 'getPositions' returns required properties
* test(player): add test to verify 'getPositions()' properties are not empty
* Add missing tests for performMediaAction_ and move
* test(player): add test to for 'component.js' related to 'handleBlur'
* test(player): add minor test in component related to test keypress propagation event
* test(player): add test for component related to 'getIsAvailableToBeFocused' function
* test(player): add test for Modal Dialog related to call function of spatial navigation
* test(player): add tests for 'spatial-navigation-key-codes'
* test(player): add tests for keycodes related to 'should return event name if keyCode is not available'
* test(player): add minor test for case when not required parametters are passed
* test(player): add test for 'caption-settings-menu-item'
* feat(player): remove 'react-video-nav-app'
* Move handleFocus and handleBlur from components.js to spatial-navigation.js
* refactor(player): refactor 'searchForTrackSelect' to be handled in the spatial navigation
* remove unrequired code in function 'searchForTrackSelect'
* update documentation comment to be in pair to its current use
* remove spatial navigation keydown from modal dialog and move it to spatial navigation class, modify the modal-dialog test accordingly
* remove useless tests
* Remove caption-settings-menu-item.test.js
* Add minor test to 'searchForTrackSelect' in spatial-navigation.test.js
* Add unit test for back key and listening to events
---------
Co-authored-by: CarlosVillasenor <carlosdeveloper9@gmail.com>
Co-authored-by: Dzianis Dashkevich <98566601+dzianis-dashkevich@users.noreply.github.com>
Co-authored-by: Walter Seymour <walterseymour15@gmail.com>
Co-authored-by: Carlos Villasenor Castillo <cvillasenor@Carloss-MacBook-Pro.local>
2024-04-18 03:34:52 +02:00
QUnit . module ( 'SpatialNavigation' , {
beforeEach ( ) {
this . clock = sinon . useFakeTimers ( ) ;
// Ensure each test starts with a player that has spatial navigation enabled
this . player = TestHelpers . makePlayer ( {
controls : true ,
bigPlayButton : true ,
spatialNavigation : { enabled : true }
} ) ;
// Directly reference the instantiated SpatialNavigation from the player
this . spatialNav = this . player . spatialNavigation ;
} ,
afterEach ( ) {
if ( this . spatialNav && this . spatialNav . isListening _ ) {
this . spatialNav . stop ( ) ;
}
this . player . dispose ( ) ;
this . clock . restore ( ) ;
}
} ) ;
QUnit . test ( 'Initialization sets up initial properties' , function ( assert ) {
assert . ok ( this . spatialNav instanceof SpatialNavigation , 'Instance of SpatialNavigation' ) ;
assert . deepEqual ( this . spatialNav . focusableComponents , [ ] , 'Initial focusableComponents is an empty array' ) ;
assert . notOk ( this . spatialNav . isListening _ , 'isListening_ is initially false' ) ;
assert . notOk ( this . spatialNav . isPaused _ , 'isPaused_ is initially false' ) ;
} ) ;
QUnit . test ( 'start method initializes event listeners' , function ( assert ) {
const onSpy = sinon . spy ( this . player , 'on' ) ;
this . spatialNav . start ( ) ;
// Check if event listeners are added
assert . ok ( onSpy . calledWith ( 'keydown' ) , 'keydown 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 ( 'modalclose' ) , 'modalclose event listener added' ) ;
// Additionally, check if isListening_ flag is set
assert . ok ( this . spatialNav . isListening _ , 'isListening_ flag is set' ) ;
onSpy . restore ( ) ;
} ) ;
QUnit . test ( 'stop method removes event listeners' , function ( assert ) {
const offSpy = sinon . spy ( this . player , 'off' ) ;
this . spatialNav . start ( ) ;
this . spatialNav . stop ( ) ;
assert . ok ( offSpy . calledWith ( 'keydown' ) , 'keydown event listener removed' ) ;
assert . notOk ( this . spatialNav . isListening _ , 'isListening_ flag is unset' ) ;
offSpy . restore ( ) ;
} ) ;
QUnit . test ( 'onKeyDown_ handles navigation keys' , function ( assert ) {
// Ensure onKeyDown_ is bound correctly.
assert . equal ( typeof this . spatialNav . onKeyDown _ , 'function' , 'onKeyDown_ should be a function' ) ;
assert . equal ( this . spatialNav . onKeyDown _ . hasOwnProperty ( 'prototype' ) , false , 'onKeyDown_ should be bound to the instance' ) ;
// Prepare a spy for the move method to track its calls.
const moveSpy = sinon . spy ( this . spatialNav , 'move' ) ;
// Create and dispatch a mock keydown event.
const event = new KeyboardEvent ( 'keydown' , { // eslint-disable-line no-undef
key : 'ArrowRight' ,
code : 'ArrowRight' ,
keyCode : 39
} ) ;
// Directly invoke the onKeyDown_ handler to simulate receiving the event.
this . spatialNav . onKeyDown _ ( event ) ;
// Assert that move was called correctly.
assert . ok ( moveSpy . calledOnce , 'move method should be called once on keydown event' ) ;
assert . ok ( moveSpy . calledWith ( 'right' ) , 'move method should be called with "right" argument' ) ;
// Restore the spy to clean up.
moveSpy . restore ( ) ;
} ) ;
QUnit . test ( 'onKeyDown_ handles media keys' , function ( assert ) {
const performMediaActionSpy = sinon . spy ( this . spatialNav , 'performMediaAction_' ) ;
// Create a mock event for the 'play' key, using the hardcoded keyCode 415.
const event = new KeyboardEvent ( 'keydown' , { // eslint-disable-line no-undef
keyCode : 415
} ) ;
// Directly call the onKeyDown_ handler.
this . spatialNav . onKeyDown _ ( event ) ;
// Assert that the performMediaAction_ method was called.
assert . ok ( performMediaActionSpy . calledOnce , 'performMediaAction_ method should be called once for media play key' ) ;
assert . ok ( performMediaActionSpy . calledWith ( 'play' ) , 'performMediaAction_ should be called with "play"' ) ;
performMediaActionSpy . restore ( ) ;
} ) ;
QUnit . test ( 'onKeyDown_ handles Back key when target is closeable' , function ( assert ) {
// Create a spy for the close method.
const closeSpy = sinon . spy ( ) ;
// Create a spy for the preventDefault method.
const preventDefaultSpy = sinon . spy ( ) ;
// Create a mock event target that is closeable.
const closeableTarget = {
close : closeSpy ,
closeable : ( ) => true
} ;
// Create a mock event for the 'Back' key, including a properly mocked originalEvent.
const event = {
preventDefault : preventDefaultSpy ,
target : closeableTarget ,
originalEvent : {
keyCode : SpatialNavigationKeyCodes . BACK ,
preventDefault : preventDefaultSpy
}
} ;
// Stub the SpatialNavigationKeyCodes.isEventKey to return true when the 'Back' key is pressed.
sinon . stub ( SpatialNavigationKeyCodes , 'isEventKey' ) . callsFake ( ( evt , keyName ) => keyName === 'Back' ) ;
// Call the onKeyDown_ method with the mock event.
this . spatialNav . onKeyDown _ ( event ) ;
// Asserts
assert . ok ( SpatialNavigationKeyCodes . isEventKey . calledWith ( event . originalEvent , 'Back' ) , 'isEventKey should be called with Back' ) ;
assert . ok ( preventDefaultSpy . calledOnce , 'preventDefault should be called once' ) ;
assert . ok ( closeSpy . calledOnce , 'close method should be called on the target' ) ;
// Restore stubs
SpatialNavigationKeyCodes . isEventKey . restore ( ) ;
} ) ;
QUnit . test ( 'performMediaAction_ executes play' , function ( assert ) {
const playSpy = sinon . spy ( this . player , 'play' ) ;
this . spatialNav . performMediaAction _ ( 'play' ) ;
assert . ok ( playSpy . calledOnce , 'play method should be called once for "play" action' ) ;
playSpy . restore ( ) ;
} ) ;
QUnit . test ( 'performMediaAction_ executes pause' , function ( assert ) {
const pauseSpy = sinon . spy ( this . player , 'pause' ) ;
sinon . stub ( this . player , 'paused' ) . returns ( false ) ;
this . spatialNav . performMediaAction _ ( 'pause' ) ;
assert . ok ( pauseSpy . calledOnce , 'pause method should be called once for "pause" action' ) ;
pauseSpy . restore ( ) ;
} ) ;
QUnit . test ( 'performMediaAction_ executes fast forward' , function ( assert ) {
const userSeekSpy = sinon . spy ( this . spatialNav , 'userSeek_' ) ;
const STEP _SECONDS = 5 ;
const initialTime = 30 ;
this . player . currentTime = ( ) => initialTime ;
this . spatialNav . performMediaAction _ ( 'ff' ) ;
const expectedNewTime = initialTime + STEP _SECONDS ;
assert . ok ( userSeekSpy . calledOnce , 'userSeek_ method should be called once for "fast forward" action' ) ;
assert . ok ( userSeekSpy . calledWith ( expectedNewTime ) , ` userSeek_ method should be called with correct time offset: expected ${ expectedNewTime } , got ${ userSeekSpy . firstCall . args [ 0 ] } ` ) ;
userSeekSpy . restore ( ) ;
} ) ;
QUnit . test ( 'performMediaAction_ executes rewind' , function ( assert ) {
const userSeekSpy = sinon . spy ( this . spatialNav , 'userSeek_' ) ;
const STEP _SECONDS = 5 ;
const initialTime = 30 ;
this . player . currentTime = ( ) => initialTime ;
this . spatialNav . performMediaAction _ ( 'rw' ) ;
const expectedNewTime = initialTime - STEP _SECONDS ;
assert . ok ( userSeekSpy . calledOnce , 'userSeek_ method should be called once for "rewind" action' ) ;
assert . ok ( userSeekSpy . calledWith ( expectedNewTime ) , ` userSeek_ method should be called with correct time offset: expected ${ expectedNewTime } , got ${ userSeekSpy . firstCall . args [ 0 ] } ` ) ;
userSeekSpy . restore ( ) ;
} ) ;
QUnit . test ( 'focus method sets focus on a player component' , function ( assert ) {
this . spatialNav . start ( ) ;
const component = this . player . getChild ( 'bigPlayButton' ) ;
assert . ok ( component , 'The target component exists.' ) ;
// Mock getIsAvailableToBeFocused to always return true
component . getIsAvailableToBeFocused = ( ) => true ;
// Spy on the focus method to check if it's called
const focusSpy = sinon . spy ( component , 'focus' ) ;
this . spatialNav . focus ( component ) ;
assert . ok ( focusSpy . calledOnce , 'focus method called on component' ) ;
// Clean up
focusSpy . restore ( ) ;
} ) ;
QUnit . test ( 'refocusComponent method refocuses the last focused component after losing focus' , function ( assert ) {
this . spatialNav . start ( ) ;
// Get the bigPlayButton component from the player
const bigPlayButton = this . player . getChild ( 'bigPlayButton' ) ;
// Mock getIsAvailableToBeFocused to always return true for testing
bigPlayButton . getIsAvailableToBeFocused = ( ) => true ;
// Focus the bigPlayButton and set it as the last focused component
this . spatialNav . focus ( bigPlayButton ) ;
// Simulate losing focus
bigPlayButton . el ( ) . blur ( ) ;
// Call refocusComponent to attempt to refocus the last focused component
this . spatialNav . refocusComponent ( ) ;
// Check if the bigPlayButton is focused again
assert . strictEqual ( this . spatialNav . lastFocusedComponent _ , bigPlayButton , 'lastFocusedComponent_ should be set to the blurred component' ) ;
} ) ;
QUnit . test ( 'move method changes focus to the right component' , function ( assert ) {
this . spatialNav . start ( ) ;
const rightComponent = {
name : ( ) => 'rightComponent' ,
el : ( ) => document . createElement ( 'div' ) ,
focus : sinon . spy ( ) ,
getPositions : ( ) => ( { center : { x : 300 , y : 100 } , boundingClientRect : { top : 0 , left : 300 , bottom : 200 , right : 400 } } ) ,
getIsAvailableToBeFocused : ( ) => true
} ;
const currentComponent = {
name : ( ) => 'currentComponent' ,
el : ( ) => document . createElement ( 'div' ) ,
focus : sinon . spy ( ) ,
getPositions : ( ) => ( { center : { x : 100 , y : 100 } , boundingClientRect : { top : 0 , left : 100 , bottom : 200 , right : 200 } } ) ,
getIsAvailableToBeFocused : ( ) => true
} ;
this . spatialNav . focusableComponents = [ currentComponent , rightComponent ] ;
this . spatialNav . getCurrentComponent = ( ) => currentComponent ;
this . spatialNav . move ( 'right' ) ;
assert . ok ( rightComponent . focus . calledOnce , 'Focus should move to the right component' ) ;
assert . notOk ( currentComponent . focus . called , 'Focus should not remain on the current component' ) ;
} ) ;
QUnit . test ( 'move method changes focus to the left component' , function ( assert ) {
this . spatialNav . start ( ) ;
const leftComponent = {
name : ( ) => 'leftComponent' ,
el : ( ) => document . createElement ( 'div' ) ,
focus : sinon . spy ( ) ,
getPositions : ( ) => ( { center : { x : 0 , y : 100 } , boundingClientRect : { top : 0 , left : 0 , bottom : 200 , right : 100 } } ) ,
getIsAvailableToBeFocused : ( ) => true
} ;
const currentComponent = {
name : ( ) => 'currentComponent' ,
el : ( ) => document . createElement ( 'div' ) ,
focus : sinon . spy ( ) ,
getPositions : ( ) => ( { center : { x : 200 , y : 100 } , boundingClientRect : { top : 0 , left : 200 , bottom : 200 , right : 300 } } ) ,
getIsAvailableToBeFocused : ( ) => true
} ;
this . spatialNav . focusableComponents = [ leftComponent , currentComponent ] ;
this . spatialNav . getCurrentComponent = ( ) => currentComponent ;
this . spatialNav . move ( 'left' ) ;
assert . ok ( leftComponent . focus . calledOnce , 'Focus should move to the left component' ) ;
assert . notOk ( currentComponent . focus . called , 'Focus should not remain on the current component' ) ;
} ) ;
QUnit . test ( 'move method changes focus to the above component' , function ( assert ) {
this . spatialNav . start ( ) ;
const aboveComponent = {
name : ( ) => 'aboveComponent' ,
el : ( ) => document . createElement ( 'div' ) ,
focus : sinon . spy ( ) ,
getPositions : ( ) => ( { center : { x : 100 , y : 0 } , boundingClientRect : { top : 0 , left : 0 , bottom : 100 , right : 200 } } ) ,
getIsAvailableToBeFocused : ( ) => true
} ;
const currentComponent = {
name : ( ) => 'currentComponent' ,
el : ( ) => document . createElement ( 'div' ) ,
focus : sinon . spy ( ) ,
getPositions : ( ) => ( { center : { x : 100 , y : 200 } , boundingClientRect : { top : 200 , left : 0 , bottom : 300 , right : 200 } } ) ,
getIsAvailableToBeFocused : ( ) => true
} ;
this . spatialNav . focusableComponents = [ aboveComponent , currentComponent ] ;
this . spatialNav . getCurrentComponent = ( ) => currentComponent ;
this . spatialNav . move ( 'up' ) ;
assert . ok ( aboveComponent . focus . calledOnce , 'Focus should move to the above component' ) ;
assert . notOk ( currentComponent . focus . called , 'Focus should not remain on the current component' ) ;
} ) ;
QUnit . test ( 'move method changes focus to the below component' , function ( assert ) {
this . spatialNav . start ( ) ;
const belowComponent = {
name : ( ) => 'belowComponent' ,
el : ( ) => document . createElement ( 'div' ) ,
focus : sinon . spy ( ) ,
getPositions : ( ) => ( { center : { x : 100 , y : 300 } , boundingClientRect : { top : 300 , left : 0 , bottom : 400 , right : 200 } } ) ,
getIsAvailableToBeFocused : ( ) => true
} ;
const currentComponent = {
name : ( ) => 'currentComponent' ,
el : ( ) => document . createElement ( 'div' ) ,
focus : sinon . spy ( ) ,
getPositions : ( ) => ( { center : { x : 100 , y : 100 } , boundingClientRect : { top : 0 , left : 0 , bottom : 200 , right : 200 } } ) ,
getIsAvailableToBeFocused : ( ) => true
} ;
this . spatialNav . focusableComponents = [ belowComponent , currentComponent ] ;
this . spatialNav . getCurrentComponent = ( ) => currentComponent ;
this . spatialNav . move ( 'down' ) ;
assert . ok ( belowComponent . focus . calledOnce , 'Focus should move to the below component' ) ;
assert . notOk ( currentComponent . focus . called , 'Focus should not remain on the current component' ) ;
} ) ;
QUnit . test ( 'getCurrentComponent method returns the current focused component' , function ( assert ) {
this . spatialNav . start ( ) ;
// Get the bigPlayButton component from the player
const bigPlayButton = this . player . getChild ( 'bigPlayButton' ) ;
// Mock getIsAvailableToBeFocused to always return true for testing
bigPlayButton . getIsAvailableToBeFocused = ( ) => true ;
// Focus the bigPlayButton
this . spatialNav . focus ( bigPlayButton ) ;
// Call getCurrentComponent to get the current focused component
const currentComponent = this . spatialNav . getCurrentComponent ( ) ;
// Check if the currentComponent is the bigPlayButton
assert . strictEqual ( currentComponent , bigPlayButton , 'getCurrentComponent should return the focused component' ) ;
} ) ;
QUnit . test ( 'add method adds a new focusable component' , function ( assert ) {
this . spatialNav . start ( ) ;
// Create a mock component with an 'el_' property and 'el' method
const newComponent = {
name : ( ) => 'newComponent' ,
el _ : document . createElement ( 'div' ) ,
el ( ) {
return this . el _ ;
} ,
focus : sinon . spy ( ) ,
getPositions : ( ) => ( { center : { x : 100 , y : 100 } , boundingClientRect : { top : 100 , left : 100 , bottom : 200 , right : 200 } } ) ,
getIsAvailableToBeFocused : ( ) => true ,
getIsFocusable : ( ) => true
} ;
// Add the new component
this . spatialNav . add ( newComponent ) ;
// Check if the new component is added to the list of focusable components
assert . strictEqual ( this . spatialNav . focusableComponents . includes ( newComponent ) , true , 'New component should be added' ) ;
} ) ;
QUnit . test ( 'remove method removes a focusable component' , function ( assert ) {
this . spatialNav . start ( ) ;
// Create a mock component
const componentToRemove = {
name : ( ) => 'componentToRemove' ,
el _ : document . createElement ( 'div' ) ,
el ( ) {
return this . el _ ;
} ,
focus : sinon . spy ( ) ,
getPositions : ( ) => ( { center : { x : 100 , y : 100 } , boundingClientRect : { top : 100 , left : 100 , bottom : 200 , right : 200 } } ) ,
getIsAvailableToBeFocused : ( ) => true ,
getIsFocusable : ( ) => true
} ;
// Add the component to be removed
this . spatialNav . add ( componentToRemove ) ;
// Remove the component
this . spatialNav . remove ( componentToRemove ) ;
// Check if the component is removed from the list of focusable components
assert . strictEqual ( this . spatialNav . focusableComponents . includes ( componentToRemove ) , false , 'Component should be removed' ) ;
} ) ;
QUnit . test ( 'clear method removes all focusable components' , function ( assert ) {
this . spatialNav . start ( ) ;
// Create mock components
const component1 = {
name : ( ) => 'component1' ,
el _ : document . createElement ( 'div' ) ,
el ( ) {
return this . el _ ;
} ,
focus : sinon . spy ( ) ,
getPositions : ( ) => ( { center : { x : 100 , y : 100 } , boundingClientRect : { top : 100 , left : 100 , bottom : 200 , right : 200 } } ) ,
getIsAvailableToBeFocused : ( ) => true ,
getIsFocusable : ( ) => true
} ;
const component2 = {
name : ( ) => 'component2' ,
el _ : document . createElement ( 'div' ) ,
el ( ) {
return this . el _ ;
} ,
focus : sinon . spy ( ) ,
getPositions : ( ) => ( { center : { x : 100 , y : 100 } , boundingClientRect : { top : 100 , left : 100 , bottom : 200 , right : 200 } } ) ,
getIsAvailableToBeFocused : ( ) => true ,
getIsFocusable : ( ) => true
} ;
// Add the components
this . spatialNav . add ( component1 ) ;
this . spatialNav . add ( component2 ) ;
// Clear all components
this . spatialNav . clear ( ) ;
// Check if the focusableComponents array is empty after clearing
assert . strictEqual ( this . spatialNav . focusableComponents . length , 0 , 'All components should be cleared' ) ;
} ) ;
QUnit . test ( 'should call `searchForTrackSelect()` if spatial navigation is enabled on click event' , function ( assert ) {
const element = document . createElement ( 'div' ) ;
element . classList . add ( 'vjs-text-track-settings' ) ;
const clickEvent = new MouseEvent ( 'click' , { // eslint-disable-line no-undef
view : this . window ,
bubbles : true ,
cancelable : true ,
currentTarget : element
} ) ;
Object . defineProperty ( clickEvent , 'relatedTarget' , { writable : false , value : element } ) ;
Object . defineProperty ( clickEvent , 'currentTarget' , { writable : false , value : element } ) ;
2024-04-18 20:57:27 +02:00
const trackSelectSpy = sinon . spy ( this . spatialNav , 'searchForTrackSelect_' ) ;
feat: implement spatial navigation (#8570)
* feat(player): add spatialNavigation feature
Adds spatialNavigation feature to enhance user experience
- Implemented spatial navigation in slider component
- Enhanced player functionality for improved navigation
* feat(player): add spatialNavigation class
Adds spatialNavigation class to manage spatial-navigation-polyfill
- Set class SpatialNavigation on its own file
- Imported SpatialNavigation class on component class
* feat(player): update spatialNavigation class
Adds 3 methods to spatialNavigation class to manage spatial-navigation-polyfill
- Added start() to: Start listen of keydown events
- Added stop() to: Stop listen key down events
- Added getComponents() to: Get current focusable components
* feat(player): modify spatialNavigation class & modify component class
Modify spatialNavigation class:
-Remove unrequired version of function ‘getComponents’
Modify component class:
-Add function ‘getIsFocusable’
* Added methods getPositions, handleFocus and handleBLur for spatial navigation needs
* feat(player): modify Component class, BigPlayButton class & ClickableComponent class
Modify Component class:
-Add method getIsAvailableToBeFocused
-Modify method getIsFocusable to only focus on finding focusable candidates
Modify spatialNavigation class:
-Remove unrequired method ‘getIsFocusable’
Modify component class:
-Remove unrequired method ‘getIsFocusable’
* Added import in player.js, Created base methods inside spatial-navigation.js
* feat(player): modify Component class & SpatialNavigation class
Modify Component class:
-Modify method getIsAvailableToBeFocused to be more strict on candidates
Modify spatialNavigation class:
-Modify method getComponents to get all focusable components
* feat(player): modify Component class
Modify Component class:
-Add documentation to ‘isVisible’ function
* added keydown event logic for spatial-navigation
* feat(player): modify SpatialNavigation class
Modify SpatialNavigation class:
-Modify documentation of functions
* feat(player): modify SpatialNavigation class
Modify SpatialNavigation class:
-Add ‘clear’ & ‘remove’ methods
* feat(player): modify SpatialNavigation class
Modify SpatialNavigation class:
-Add documentation of functions
* feat(player): modify SpatialNavigation class
Modify SpatialNavigation class:
-Add function ‘getCurretComponent’‘’
* feat(player): modify SpatialNavigation class
Modify SpatialNavigation class:
-Add documentation for ‘findBestCandidate’ method
* Added logic for moving focus to the best candidate
* Implemented move, findBestCandidate, isInDirection, and calculateDistance methods for spatial navigation logic
* Added a new player option enableKeydownListener, Added gap: 1px to control-bar for spatial-navigation-polyfill needs
* feat(player): modify SpatialNavigation class & Component class
Modify SpatialNavigation class:
-Add function ‘handlePlayerBlur’
-Add function ‘handlePlayerFocus’
Modify Component class:
-Modify ‘handleBlur’
-Modify ‘handleFocus’
* Removed enableKeydownListener flag, as user should start the SpatialNavigation manually
* Added functionality to track changes in the focusableComponents list (custom event focusableComponentsChanged)
* feat(player): modify SpatialNavigation class, ModalDialog & Component class
Modify SpatialNavigation class:
-Add ‘lastFocusedComponent’
-Add function ‘refocusComponent’
Modify ModalDialog class:
-Add condition on ‘close’ function
Modify Component class:
-Modify ‘handleBlur’ to store blurred component
* feat(player): modify ModalDialog
Modify ModalDialog:
-Add condition to close Modal on Backspace
* Refactor SpatialNavigation to use player.spatialNavigation
* Added a new custom event endOfFocusableComponents
* Added new styles for focused elements in case spatial navigation is enabled
* feat(player): modify SpatialNavigation class:
-Add condition so getComponents can get as candidates the UI elements from the playlist-ui
* Changed to window.SpatialNabigation to this.player_.spatialNavigation
* feat(player): modify text-track-settings, created test-track-settings-colors.js, text-track-settings-font.js,text-track-fieldset.js & text-track-select.js:
Modify text-track-settings class:
- Add changes so newly created components can work as content of the modal.
- Create new components as a refactor of the contents of text-track-settings
* changed handleKeyDown inside component.js, getComponents method is now iterating player.children
* feat(player): create TrackSettingsControls Component & Modify TextTrackSettings
Create TrackSettingsControls Component:
-Create Component to show buttons reset & done as components.
Modify TextTrackSettings:
-Add Component TrackSettingsControls in TextTrackSettings
* feat(player): Modify ModalDialog
Modify ModalDialog:
-Add condition for stop propagation of event inside of ModalDialog when spatialNavigation is enabled
* getIsFocusable and getIsAvailableToBeFocused methods are now accepting el as a parameter, added a new methods findSuitableDOMChild and focus for spatialNavigation class
* feat(player): Modify TextTrackSettings:
Modify TextTrackSettings:
-Remove unrequired methods to create DOM elements since now those are created by Components.
* feat(player): Modify CaptionSettingsMenuItem:
Modify CaptionSettingsMenuItem:
-Add condition to focus component of TextTrackSelect when modal is open
* feat(player): Modify TextTrackSelect & TextTrackFieldset:
Modify TextTrackSelect :
Modify TextTrackFieldset:
-Add comments to certain functions to explain the code
* feat(player): Modify TrackSettingsControls:
Modify TrackSettingsControls:
-Remove unrequired comments & add comments to certain functions to explain the code
* feat(player): Modify SpatialNavigation, Component & ModalDialog:
Modify SpatialNavigation:
Modify Component:
Modify ModalDialog:
-Add & update comments of documentation.
* Handle ENTER keydown in Modals when spatial navigation is enabled
* feat(player): Modify ModalDialog, spatialNavigation, TrackSettingsControls, TextTrackFieldset, TextTrackSelect, TrackSettingsColors, TrackSettingsFont:
Modify ModalDialog:
Modify spatialNavigation:
Modify TrackSettingsControls:
Modify TextTrackFieldset:
Modify TextTrackSelect:
Modify TrackSettingsColors:
Modify TrackSettingsFont:
-Add & update comments of documentation.
* Implement additional RCU controls
* feat(player): Modify Component class:
Modify Component :
-Remove unrequired condition inside of handleFocus method.
* feat(player): Modify ModalDialog & CaptionSettingsMenuItem
Modify ModalDialog:
Modify CaptionSettingsMenuItem:
-Modify spatialNavigation condition to be more specific regarding spatialNavigation implementation.
* feat(player): Modify SpatialNavigation class:
Modify SpatialNavigation :
-Fix bug where ‘enter’ press was not working properly on select component inside of the ‘vjs-text-track-settings’ modal.
* feat(player): Modify SpatialNavigation class:
Modify SpatialNavigation :
-Minor improvements on the loops of certain functions to stop when they have found the element they are looking for.
-Implement minor spacing formatting on switch statement.
* Update src/js/component.js
More understandable documentation.
Co-authored-by: Dzianis Dashkevich <98566601+dzianis-dashkevich@users.noreply.github.com>
* Update src/js/component.js
More understandable documentation.
Co-authored-by: Dzianis Dashkevich <98566601+dzianis-dashkevich@users.noreply.github.com>
* feat(player): Modify SpatialNavigation & Component class:
Modify Component class :
Modify SpatialNavigation class :
-Modify ‘getIsFocusable’ function to use ‘this.el_’ instead of ‘el’ parameter
* feat(player): Modify SpatialNavigation class:
Modify SpatialNavigation class :
-Refactor onKeyDown function to use static data & return when pause is true.
* feat(player): Modify SpatialNavigation class:
Modify SpatialNavigation class :
-Refactor to use ‘.el()’ instead of ‘.el_’
* Update src/js/spatial-navigation.js
Co-authored-by: Walter Seymour <walterseymour15@gmail.com>
* feat(player): Modify ModalDialog class & MenuItem class:
Modify ModalDialog class :
Modify MenuItem class :
-Correct typo of ‘isSpatialNavlistening’ to ‘isSpatialNavListening’.
* removed unused property, remove this.focus, which was added for testing purposes
* Changed parameters to private, removed redundant code, removed initialFocusedComponent parameter, change STEP_SECONDS to static
* feat(player): solve remaining conflict:
Modify Spatial Navigation class :
- Solve conflict
* feat(player): Rename TrackSettingsColors & TrackSettingsFont
* feat(player): Remove unrequired functions calls from components TextTrackSettingsColors & TextTrackSettingsFont.
* feat(player): Update spatial-navigation.js's keypress return keyword.
* bind focus and blur just if spatial navigation is enabled, add 1px gap if spatial navigation is enabled
* feat(player): Modify calls on 'isListening' & 'isPaused' for ModalDialog & TextTrackMenuItem
* feat(player): remove unrequired object on component 'TrackSettingsControls'
* Removed 1px gap
* feat(player): Rename function ‘getComponents’ to ‘updateFocusableComponents’
* Changed SpatialNavigation class to extend EventTarget, removed redundant methods for events
* fix(player): fix call of 'getIsAvailableToBeFocused' that was throwing an error.
* removed Static maps for key presses and extended keycode with the missing keys
* refactor(player): Modify functions of 'getIsDisabled', 'getIsExpresslyInert' & 'getIsFocusable' to be more in pair when stablished code of the player.
* Conditional assignment for keycode.codes.back based on platform, changed Backspace to Back key for Modal closing
* Extend the object for reverse lookup, prenet Up/down keys to open a menu if spatial navigation is anabled
* refactor(player): Refactor 'SpatialNavKeycodes' file to not patch 'keycode' dependency
* fix(pllayer): fix issue related to 'back' not being used properly in function 'isEventKey'
* feat(player): Rename imports of 'spatial-navigation-keycode' to have their extension
* feat(player): Add example of use of 'Client app uses a global spatial-navigation solution'
* feat(player): rename 'spatial-navigation-keycode.js' filename
* Fix on src chnage issue, ESC button closing modal, expand vjs-modal-dialog
* change file name and object name
* fix: Update ids of labels to use 'guid' so unit test works properly
* fix: update localized text in text-track-settings-font & text-track-settings
* Mark some methods as private
* fix: modify content of modal 'text-track-settings' to change language properly
* fix: add missing '.' in jsdoc of text-track components
* feature: add unit test for 'text-track-select' component
* Add test for Spatial Navigation
* test(player): Add minor test related to 'handleBlur' & 'handleFocus'
* feat(player): Remove unrequired files from 'react-video-nav-app'
* test(player): Add small test to check if 'getPositions' returns required properties
* test(player): add test to verify 'getPositions()' properties are not empty
* Add missing tests for performMediaAction_ and move
* test(player): add test to for 'component.js' related to 'handleBlur'
* test(player): add minor test in component related to test keypress propagation event
* test(player): add test for component related to 'getIsAvailableToBeFocused' function
* test(player): add test for Modal Dialog related to call function of spatial navigation
* test(player): add tests for 'spatial-navigation-key-codes'
* test(player): add tests for keycodes related to 'should return event name if keyCode is not available'
* test(player): add minor test for case when not required parametters are passed
* test(player): add test for 'caption-settings-menu-item'
* feat(player): remove 'react-video-nav-app'
* Move handleFocus and handleBlur from components.js to spatial-navigation.js
* refactor(player): refactor 'searchForTrackSelect' to be handled in the spatial navigation
* remove unrequired code in function 'searchForTrackSelect'
* update documentation comment to be in pair to its current use
* remove spatial navigation keydown from modal dialog and move it to spatial navigation class, modify the modal-dialog test accordingly
* remove useless tests
* Remove caption-settings-menu-item.test.js
* Add minor test to 'searchForTrackSelect' in spatial-navigation.test.js
* Add unit test for back key and listening to events
---------
Co-authored-by: CarlosVillasenor <carlosdeveloper9@gmail.com>
Co-authored-by: Dzianis Dashkevich <98566601+dzianis-dashkevich@users.noreply.github.com>
Co-authored-by: Walter Seymour <walterseymour15@gmail.com>
Co-authored-by: Carlos Villasenor Castillo <cvillasenor@Carloss-MacBook-Pro.local>
2024-04-18 03:34:52 +02:00
const textTrackSelectComponent = new TextTrackSelect ( this . player , {
SelectOptions : [ 'Option 1' , 'Option 2' , 'Option 3' ] ,
legendId : '1' ,
id : 1 ,
labelId : '1'
} ) ;
this . spatialNav . updateFocusableComponents = ( ) => [ textTrackSelectComponent ] ;
this . spatialNav . handlePlayerBlur _ ( clickEvent ) ;
assert . ok ( trackSelectSpy . calledOnce ) ;
} ) ;
2024-07-23 00:43:20 +02:00
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"' ) ;
} ) ;
2024-07-29 20:11:58 +02:00
QUnit . test ( 'error on player focus the second focusable element of error modal' , function ( assert ) {
this . spatialNav . start ( ) ;
const firstComponent = {
name : ( ) => 'firstComponent' ,
el : ( ) => document . createElement ( 'div' ) ,
focus : sinon . spy ( ) ,
getIsAvailableToBeFocused : ( ) => true
} ;
const secondComponent = {
name : ( ) => 'secondComponent' ,
el : ( ) => document . createElement ( 'div' ) ,
focus : sinon . spy ( ) ,
getIsAvailableToBeFocused : ( ) => true
} ;
this . spatialNav . focusableComponents = [ firstComponent , secondComponent ] ;
this . spatialNav . getCurrentComponent = ( ) => firstComponent ;
this . spatialNav . updateFocusableComponents = ( ) => [ firstComponent , secondComponent ] ;
this . player . error ( {
code : 1 ,
dismiss : true
} ) ;
assert . ok ( secondComponent . focus . calledOnce , 'Focus should move to the second component' ) ;
assert . notOk ( firstComponent . focus . called , 'Focus should not remain on the first component' ) ;
} ) ;
QUnit . test ( 'on error, modalButtons should get the buttons if those are available' , function ( assert ) {
this . spatialNav . start ( ) ;
const buttonContainer = Dom . createEl ( 'div' , { } , { class : 'vjs-errors-ok-button-container' } ) ;
const testEl1 = Dom . createEl ( 'button' , { } , { class : 'c1' } ) ;
// Add first element to error modal
buttonContainer . appendChild ( testEl1 ) ;
const testEl2 = Dom . createEl ( 'button' , { } , { class : 'c1' } ) ;
// Add second element to error modal
buttonContainer . appendChild ( testEl2 ) ;
this . player . errorDisplay . el ( ) . appendChild ( buttonContainer ) ;
this . player . error ( {
code : 1 ,
dismiss : true
} ) ;
this . spatialNav . getCurrentComponent = ( ) => this . spatialNav . focusableComponents [ 0 ] ;
const getPositionsEl1Spy = sinon . spy ( this . spatialNav . focusableComponents [ 0 ] , 'getPositions' ) ;
const getPositionsEl2Spy = sinon . spy ( this . spatialNav . focusableComponents [ 1 ] , 'getPositions' ) ;
this . spatialNav . move ( 'left' ) ;
assert . strictEqual ( this . spatialNav . focusableComponents . length , 2 , 'button elements are now part of the array of focusableComponents' ) ;
assert . ok ( getPositionsEl1Spy . calledOnce , 'getPositions method called on button' ) ;
assert . ok ( getPositionsEl2Spy . calledOnce , 'getPositions method called on button' ) ;
assert . strictEqual ( this . spatialNav . focusableComponents [ 0 ] . name ( ) , 'ModalButton1' , 'testEl1 name should be ModalButton1' ) ;
assert . strictEqual ( this . spatialNav . focusableComponents [ 1 ] . name ( ) , 'ModalButton2' , 'testEl2 name should be ModalButton2' ) ;
getPositionsEl1Spy . restore ( ) ;
getPositionsEl2Spy . restore ( ) ;
} ) ;
QUnit . test ( 'on error, modalButtons added functions should work properly' , function ( assert ) {
this . spatialNav . start ( ) ;
const buttonContainer = Dom . createEl ( 'div' , { } , { class : 'vjs-errors-ok-button-container' } ) ;
const testEl1 = Dom . createEl ( 'button' , { } , { class : 'c1' } ) ;
// Add first element to error modal
buttonContainer . appendChild ( testEl1 ) ;
this . player . errorDisplay . el ( ) . appendChild ( buttonContainer ) ;
this . player . error ( { code : 1 , dismiss : true } ) ;
assert . strictEqual ( this . spatialNav . focusableComponents [ 0 ] . el ( ) instanceof Element , true , 'el function from modal buttons should return a DOM element' ) ; // eslint-disable-line no-undef
assert . strictEqual ( this . spatialNav . focusableComponents [ 0 ] . getIsFocusable ( ) , true , 'getIsFocusable function from modal buttons is always true' ) ;
assert . strictEqual ( this . spatialNav . focusableComponents [ 0 ] . getIsAvailableToBeFocused ( ) , true , 'getIsAvailableToBeFocused function from modal buttons is always true' ) ;
assert . strictEqual ( this . spatialNav . focusableComponents [ 0 ] . getIsAvailableToBeFocused ( ) , true , 'getIsAvailableToBeFocused function from modal buttons is always true' ) ;
assert . strictEqual ( typeof this . spatialNav . focusableComponents [ 0 ] . getPositions ( ) , 'object' , 'focusableComponents function from modal buttons should return an object' ) ;
} ) ;
QUnit . test ( 'If component passes the required functions it should be added to focusableComponents' , function ( assert ) {
this . spatialNav . start ( ) ;
const firstComponent = {
name _ : 'firstComponent' ,
name : ( ) => this . name ,
el _ : document . createElement ( 'div' ) ,
el : ( ) => this . el _ ,
focus : sinon . spy ( ) ,
getIsAvailableToBeFocused : ( ) => true ,
getIsFocusable : ( ) => true
} ;
this . player . children _ . push ( firstComponent ) ;
this . spatialNav . getCurrentComponent = ( ) => firstComponent ;
this . spatialNav . updateFocusableComponents ( ) ;
assert . strictEqual ( this . spatialNav . focusableComponents . length , 1 , 'focusableComponents array should have 1 component' ) ;
assert . strictEqual ( this . spatialNav . focusableComponents [ 0 ] . name _ , 'firstComponent' , 'the name of the component in focusableComponents array should be "firstComponent"' ) ;
} ) ;
2024-08-22 17:07:41 +02:00
QUnit . test ( 'Doesn\'t error if no ErrorDisplay component is present' , function ( assert ) {
this . player . errorDisplay . dispose ( ) ;
delete this . player . errorDisplay ;
this . spatialNav . start ( ) ;
assert . ok ( true , 'started without throwing when errorDisplay not present' ) ;
} ) ;