Skip to content

Commit

Permalink
feat: implement spatial navigation (#8570)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
5 people authored Apr 18, 2024
1 parent 582c35f commit 21b4a52
Show file tree
Hide file tree
Showing 21 changed files with 2,125 additions and 235 deletions.
6 changes: 6 additions & 0 deletions src/css/components/_button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@
appearance: none;
}

// Replacement for focus in case spatial navigation is enabled
.video-js.vjs-spatial-navigation-enabled .vjs-button:focus {
outline: 0.0625em solid rgba($primary-foreground-color, 1);
box-shadow: none;
}

.vjs-control .vjs-button {
width: 100%;
height: 100%;
Expand Down
5 changes: 5 additions & 0 deletions src/css/components/_captions-settings.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
background-color: rgba($primary-background-color, 0.75);
color: $primary-foreground-color;
height: 70%;

// When Spatial Navigation is enabled
.vjs-spatial-navigation-enabled & {
height: 80%;
}
}

// Hide if an error occurs
Expand Down
4 changes: 4 additions & 0 deletions src/css/components/_control-bar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
@include background-color-with-alpha($primary-background-color, $primary-background-transparency);
}

.video-js.vjs-spatial-navigation-enabled .vjs-control-bar {
gap: 1px;
}

// Locks the display only if:
// - controls are not disabled
// - native controls are not used
Expand Down
5 changes: 5 additions & 0 deletions src/css/components/_slider.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,8 @@

@include box-shadow(0 0 1em $primary-foreground-color);
}

// Replacement for focus in case spatial navigation is enabled
.video-js.vjs-spatial-navigation-enabled .vjs-slider:focus {
outline: 0.0625em solid rgba($primary-foreground-color, 1);
}
195 changes: 193 additions & 2 deletions src/js/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -1283,6 +1283,49 @@ class Component {
return this.currentDimension('height');
}

/**
* Retrieves the position and size information of the component's element.
*
* @return {Object} An object with `boundingClientRect` and `center` properties.
* - `boundingClientRect`: An object with properties `x`, `y`, `width`,
* `height`, `top`, `right`, `bottom`, and `left`, representing
* the bounding rectangle of the element.
* - `center`: An object with properties `x` and `y`, representing
* the center point of the element. `width` and `height` are set to 0.
*/
getPositions() {
const rect = this.el_.getBoundingClientRect();

// Creating objects that mirror DOMRectReadOnly for boundingClientRect and center
const boundingClientRect = {
x: rect.x,
y: rect.y,
width: rect.width,
height: rect.height,
top: rect.top,
right: rect.right,
bottom: rect.bottom,
left: rect.left
};

// Calculating the center position
const center = {
x: rect.left + rect.width / 2,
y: rect.top + rect.height / 2,
width: 0,
height: 0,
top: rect.top + rect.height / 2,
right: rect.left + rect.width / 2,
bottom: rect.top + rect.height / 2,
left: rect.left + rect.width / 2
};

return {
boundingClientRect,
center
};
}

/**
* Set the focus to this component
*/
Expand All @@ -1308,8 +1351,8 @@ class Component {
if (this.player_) {

// We only stop propagation here because we want unhandled events to fall
// back to the browser. Exclude Tab for focus trapping.
if (!keycode.isEventKey(event, 'Tab')) {
// back to the browser. Exclude Tab for focus trapping, exclude also when spatialNavigation is enabled.
if (!keycode.isEventKey(event, 'Tab') && !(this.player_.options_.playerOptions.spatialNavigation && this.player_.options_.playerOptions.spatialNavigation.enabled)) {
event.stopPropagation();
}
this.player_.handleKeyDown(event);
Expand Down Expand Up @@ -1765,6 +1808,154 @@ class Component {
});
}

/**
* Decide whether an element is actually disabled or not.
*
* @function isActuallyDisabled
* @param element {Node}
* @return {boolean}
*
* @see {@link https://html.spec.whatwg.org/multipage/semantics-other.html#concept-element-disabled}
*/
getIsDisabled() {
return Boolean(this.el_.disabled);
}

/**
* Decide whether the element is expressly inert or not.
*
* @see {@link https://html.spec.whatwg.org/multipage/interaction.html#expressly-inert}
* @function isExpresslyInert
* @param element {Node}
* @return {boolean}
*/
getIsExpresslyInert() {
return this.el_.inert && !this.el_.ownerDocument.documentElement.inert;
}

/**
* Determine whether or not this component can be considered as focusable component.
*
* @param {HTMLElement} el - The HTML element representing the component.
* @return {boolean}
* If the component can be focused, will be `true`. Otherwise, `false`.
*/
getIsFocusable() {
return this.el_.tabIndex >= 0 && !(this.getIsDisabled() || this.getIsExpresslyInert());
}

/**
* Determine whether or not this component is currently visible/enabled/etc...
*
* @param {HTMLElement} el - The HTML element representing the component.
* @return {boolean}
* If the component can is currently visible & enabled, will be `true`. Otherwise, `false`.
*/
getIsAvailableToBeFocused(el) {
/**
* Decide the style property of this element is specified whether it's visible or not.
*
* @function isVisibleStyleProperty
* @param element {CSSStyleDeclaration}
* @return {boolean}
*/
function isVisibleStyleProperty(element) {
const elementStyle = window.getComputedStyle(element, null);
const thisVisibility = elementStyle.getPropertyValue('visibility');
const thisDisplay = elementStyle.getPropertyValue('display');
const invisibleStyle = ['hidden', 'collapse'];

return (thisDisplay !== 'none' && !invisibleStyle.includes(thisVisibility));
}

/**
* Decide whether the element is being rendered or not.
* 1. If an element has the style as "visibility: hidden | collapse" or "display: none", it is not being rendered.
* 2. If an element has the style as "opacity: 0", it is not being rendered.(that is, invisible).
* 3. If width and height of an element are explicitly set to 0, it is not being rendered.
* 4. If a parent element is hidden, an element itself is not being rendered.
* (CSS visibility property and display property are inherited.)
*
* @see {@link https://html.spec.whatwg.org/multipage/rendering.html#being-rendered}
* @function isBeingRendered
* @param element {Node}
* @return {boolean}
*/
function isBeingRendered(element) {
if (!isVisibleStyleProperty(element.parentElement)) {
return false;
}
if (!isVisibleStyleProperty(element) || (element.style.opacity === '0') || (window.getComputedStyle(element).height === '0px' || window.getComputedStyle(element).width === '0px')) {
return false;
}
return true;
}

/**
* Determine if the element is visible for the user or not.
* 1. If an element sum of its offsetWidth, offsetHeight, height and width is less than 1 is not visible.
* 2. If elementCenter.x is less than is not visible.
* 3. If elementCenter.x is more than the document's width is not visible.
* 4. If elementCenter.y is less than 0 is not visible.
* 5. If elementCenter.y is the document's height is not visible.
*
* @function isVisible
* @param element {Node}
* @return {boolean}
*/
function isVisible(element) {
if ((element.offsetWidth + element.offsetHeight + element.getBoundingClientRect().height + element.getBoundingClientRect().width) === 0) {
return false;
}

// Define elementCenter object with props of x and y
// x: Left position relative to the viewport plus element's width (no margin) divided between 2.
// y: Top position relative to the viewport plus element's height (no margin) divided between 2.
const elementCenter = {
x: element.getBoundingClientRect().left + element.offsetWidth / 2,
y: element.getBoundingClientRect().top + element.offsetHeight / 2
};

if (elementCenter.x < 0) {
return false;
}
if (elementCenter.x > (document.documentElement.clientWidth || window.innerWidth)) {
return false;
}
if (elementCenter.y < 0) {
return false;
}
if (elementCenter.y > (document.documentElement.clientHeight || window.innerHeight)) {
return false;
}

let pointContainer = document.elementFromPoint(elementCenter.x, elementCenter.y);

while (pointContainer) {
if (pointContainer === element) {
return true;
}
if (pointContainer.parentNode) {
pointContainer = pointContainer.parentNode;
} else {
return false;
}

}
}

// If no DOM element was passed as argument use this component's element.
if (!el) {
el = this.el();
}

// If element is visible, is being rendered & either does not have a parent element or its tabIndex is not negative.
if (isVisible(el) && isBeingRendered(el) && ((!el.parentElement) || (el.tabIndex >= 0))) {
return true;
}
return false;
}

/**
* Register a `Component` with `videojs` given the name and the component.
*
Expand Down
2 changes: 1 addition & 1 deletion src/js/menu/menu-button.js
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ class MenuButton extends Component {
this.menuButton_.focus();
}
// Up Arrow or Down Arrow also 'press' the button to open the menu
} else if (keycode.isEventKey(event, 'Up') || keycode.isEventKey(event, 'Down')) {
} else if ((keycode.isEventKey(event, 'Up') || keycode.isEventKey(event, 'Down')) && !(this.player_.options_.playerOptions.spatialNavigation && this.player_.options_.playerOptions.spatialNavigation.enabled)) {
if (!this.buttonPressed_) {
event.preventDefault();
this.pressButton();
Expand Down
15 changes: 12 additions & 3 deletions src/js/modal-dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const MODAL_CLASS_NAME = 'vjs-modal-dialog';
class ModalDialog extends Component {

/**
* Create an instance of this class.
* Creates an instance of this class.
*
* @param { import('./player').default } player
* The `Player` that this class should be attached to.
Expand Down Expand Up @@ -236,6 +236,7 @@ class ModalDialog extends Component {
if (!this.opened_) {
return;
}

const player = this.player();

/**
Expand Down Expand Up @@ -265,8 +266,10 @@ class ModalDialog extends Component {
*
* @event ModalDialog#modalclose
* @type {Event}
*
* @property {boolean} [bubbles=true]
*/
this.trigger('modalclose');
this.trigger({type: 'modalclose', bubbles: true});
this.conditionalBlur_();

if (this.options_.temporary) {
Expand Down Expand Up @@ -454,7 +457,13 @@ class ModalDialog extends Component {
* @listens keydown
*/
handleKeyDown(event) {

/**
* Fired a custom keyDown event that bubbles.
*
* @event ModalDialog#modalKeydown
* @type {Event}
*/
this.trigger({type: 'modalKeydown', originalEvent: event, target: this, bubbles: true});
// Do not allow keydowns to reach out of the modal dialog.
event.stopPropagation();

Expand Down
12 changes: 12 additions & 0 deletions src/js/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {hooks} from './utils/hooks';
import {isObject} from './utils/obj';
import keycode from 'keycode';
import icons from '../images/icons.svg';
import SpatialNavigation from './spatial-navigation.js';

// The following imports are used only to ensure that the corresponding modules
// are always included in the video.js package. Importing the modules will
Expand Down Expand Up @@ -562,6 +563,13 @@ class Player extends Component {
this.addClass('vjs-audio');
}

// Check if spatial navigation is enabled in the options.
// If enabled, instantiate the SpatialNavigation class.
if (options.spatialNavigation && options.spatialNavigation.enabled) {
this.spatialNavigation = new SpatialNavigation(this);
this.addClass('vjs-spatial-navigation-enabled');
}

// TODO: Make this smarter. Toggle user state between touching/mousing
// using events, since devices can have both touch and mouse events.
// TODO: Make this check be performed again when the window switches between monitors
Expand Down Expand Up @@ -5447,6 +5455,10 @@ Player.prototype.options_ = {
responsive: false,
audioOnlyMode: false,
audioPosterMode: false,
spatialNavigation: {
enabled: false,
horizontalSeek: false
},
// Default smooth seeking to false
enableSmoothSeeking: false
};
Expand Down
26 changes: 22 additions & 4 deletions src/js/slider/slider.js
Original file line number Diff line number Diff line change
Expand Up @@ -308,14 +308,32 @@ class Slider extends Component {
* @listens keydown
*/
handleKeyDown(event) {

// Left and Down Arrows
if (keycode.isEventKey(event, 'Left') || keycode.isEventKey(event, 'Down')) {
const spatialNavOptions = this.options_.playerOptions.spatialNavigation;
const spatialNavEnabled = spatialNavOptions && spatialNavOptions.enabled;
const horizontalSeek = spatialNavOptions && spatialNavOptions.horizontalSeek;

if (spatialNavEnabled) {
if ((horizontalSeek && keycode.isEventKey(event, 'Left')) ||
(!horizontalSeek && keycode.isEventKey(event, 'Down'))) {
event.preventDefault();
event.stopPropagation();
this.stepBack();
} else if ((horizontalSeek && keycode.isEventKey(event, 'Right')) ||
(!horizontalSeek && keycode.isEventKey(event, 'Up'))) {
event.preventDefault();
event.stopPropagation();
this.stepForward();
} else {
super.handleKeyDown(event);
}

// Left and Down Arrows
} else if (keycode.isEventKey(event, 'Left') || keycode.isEventKey(event, 'Down')) {
event.preventDefault();
event.stopPropagation();
this.stepBack();

// Up and Right Arrows
// Up and Right Arrows
} else if (keycode.isEventKey(event, 'Right') || keycode.isEventKey(event, 'Up')) {
event.preventDefault();
event.stopPropagation();
Expand Down
Loading

0 comments on commit 21b4a52

Please sign in to comment.