Skip to content

Commit

Permalink
Add Hotkeys Plugin (#165)
Browse files Browse the repository at this point in the history
* Add Hotkeys Plugin

* Add init and destroy methods

* Add options

* Fix bind of onKeydown

* Improve conditions of hokeys if-else

* Refactor options

* Rename pluginParameter type

* Add doc

* Add elements

* Typo

* Improve conditions

* Add Vlitejs

* Doc

* Doc

* Update HTML5 example

* Fix keydown for multiple check

---------

Co-authored-by: Yoriiis <2563298+yoriiis@users.noreply.github.com>
  • Loading branch information
rtritto and yoriiis authored Mar 4, 2025
1 parent a86b4c1 commit d168ca6
Show file tree
Hide file tree
Showing 9 changed files with 214 additions and 120 deletions.
17 changes: 1 addition & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ Sizes of the `vlitejs` bundle compared to the competition:
- [**Cast**](./src/plugins/cast/README.md) - Supports for Google Cast API.
- [**AirPlay**](./src/plugins/airplay/README.md) - Supports for Apple AirPlay API.
- [**Monetization**](./src/plugins/ima/README.md) - Supports for Google IMA SDK.
- [**Hotkeys**](./src/plugins/hotkeys/README.md) - Supports for hotkeys to add keyboard shortcuts.
- **Playsinline** - Supports the `playsinline` attribute.
- **SVG icons** - SVG are inlined into the library, no sprites to includes.
- [**Shortcuts**](#shortcuts) - Supports keyboard shortcuts.
- **Accessibility** - W3C and A11Y valid.

[![Image of vLitejs](https://yoriiis.github.io/cdn/static/vlitejs/demo-screenshot.jpg)](https://vlite.js.org)
Expand Down Expand Up @@ -201,9 +201,7 @@ The player controls can be customized with the following parameters:
| `playPause` | `Boolean` | `true` | Display the play/pause button on the control bar |
| `progressBar` | `Boolean` | `true` | Display the progress bar on the control bar |
| `time` | `Boolean` | `true` | Display the time information on the control bar |
| `seekTime` | `Number` | `5` | Set seek time seconds of the backward and forward shortcuts |
| `volume` | `Boolean` | `true` | Display the volume button on the control bar |
| `volumeStep` | `Number` | `0.1` | Set the volume step (between 0 and 1) of the increase and decrease shortcuts |
| `fullscreen`&sup1;| `Boolean` | `true` | Display the fullscreen button on the control bar |
| `poster`&sup1; | `String\|null` | `null` | Customize the video poster url |
| `bigPlay`&sup1; | `Boolean` | `true` | Display the big play button on the poster video |
Expand Down Expand Up @@ -334,19 +332,6 @@ The player exposes some custom CSS properties, locally scopped under the `.v-vli

---

## Shortcuts

The player accepts the following keyboard shortcuts.

| Key | Action |
| :---------------: | ------------------------ |
| <kbd>space</kbd> | Toggle playback |
| <kbd>Esc</kbd> | Exit the fullscreen |
| <kbd>&larr;</kbd> | Seek backward of `5s` |
| <kbd>&rarr;</kbd> | Seek forward of `5s` |
| <kbd>&uarr;</kbd> | Increase volume of `10%` |
| <kbd>&darr;</kbd> | Decrease volume of `10%` |

## Contributors

Many thanks to [Victor Schirm](https://www.behance.net/victorshm) for the `vlitejs` logo.
Expand Down
2 changes: 1 addition & 1 deletion config/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ const { author, license, name, version } = pkg

export const banner = `/*!\n * @license ${license}\n * @name ${name}\n * @version ${version}\n * @copyright ${new Date().getUTCFullYear()} ${author}\n */`
export const providers = ['youtube', 'vimeo', 'dailymotion']
export const plugins = ['subtitle', 'pip', 'cast', 'airplay', 'ima', 'volume-bar', 'sticky']
export const plugins = ['subtitle', 'pip', 'cast', 'airplay', 'ima', 'volume-bar', 'sticky', 'hotkeys']
7 changes: 6 additions & 1 deletion examples/html5/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import VlitejsCast from '../../dist/plugins/cast.js'
import VlitejsPip from '../../dist/plugins/pip.js'
import VlitejsSubtitle from '../../dist/plugins/subtitle.js'
import VlitejsVolumeBar from '../../dist/plugins/volume-bar.js'
import VlitejsHotkeys from '../../dist/plugins/hotkeys.js'
import Vlitejs from '../../dist/vlite.js'

Vlitejs.registerPlugin('subtitle', VlitejsSubtitle)
Expand All @@ -24,6 +25,10 @@ Vlitejs.registerPlugin('cast', VlitejsCast, {
})
Vlitejs.registerPlugin('airplay', VlitejsAirplay)
Vlitejs.registerPlugin('volume-bar', VlitejsVolumeBar)
Vlitejs.registerPlugin('hotkeys', VlitejsHotkeys, {
seekStep: 3,
volumeStep: 0.2
})

/* eslint-disable no-unused-vars */
const vlite = new Vlitejs('#player', {
Expand All @@ -42,7 +47,7 @@ const vlite = new Vlitejs('#player', {
muted: false,
autoHide: true
},
plugins: ['subtitle', 'pip', 'cast', 'airplay', 'volume-bar'],
plugins: ['subtitle', 'pip', 'cast', 'airplay', 'volume-bar', 'hotkeys'],
onReady: (player) => {
console.log(player)

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"monetization",
"ima-sdk",
"sticky",
"volume bar"
"volume bar",
"hotkeys"
],
"homepage": "https://vlite.js.org",
"bugs": "https://github.com/vlitejs/vlite/issues",
Expand Down
90 changes: 0 additions & 90 deletions src/core/vlite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@ const DEFAULT_OPTIONS: interfaceDefaultOptions = {
playPause: true,
progressBar: true,
time: true,
seekTime: 5,
volume: true,
volumeStep: 0.1,
loop: false
},
video: {
Expand All @@ -31,9 +29,7 @@ const DEFAULT_OPTIONS: interfaceDefaultOptions = {
playPause: true,
progressBar: true,
time: true,
seekTime: 5,
volume: true,
volumeStep: 0.1,
fullscreen: true,
poster: null,
bigPlay: true,
Expand Down Expand Up @@ -134,7 +130,6 @@ class Vlitejs {

this.onClickOnPlayer = this.onClickOnPlayer.bind(this)
this.onDoubleClickOnPlayer = this.onDoubleClickOnPlayer.bind(this)
this.onKeydown = this.onKeydown.bind(this)
this.onMousemove = this.onMousemove.bind(this)
this.onChangeFullScreen = this.onChangeFullScreen.bind(this)

Expand Down Expand Up @@ -207,7 +202,6 @@ class Vlitejs {
this.autoHideGranted && this.container.addEventListener('mousemove', this.onMousemove)
document.addEventListener(this.supportFullScreen.changeEvent, this.onChangeFullScreen)
}
this.container.addEventListener('keydown', this.onKeydown)
}

/**
Expand Down Expand Up @@ -245,57 +239,6 @@ class Vlitejs {
}
}

/**
* On keydown event on the media element
* @param e Event listener datas
*/
onKeydown(e: KeyboardEvent) {
const activeElement = document.activeElement
const { keyCode } = e

// Stop and start the auto hide timer on selected key code
if (
[9, 32, 37, 39].includes(keyCode) &&
this.autoHideGranted &&
(activeElement === this.container || activeElement?.closest('.v-vlite'))
) {
this.stopAutoHideTimer()
this.startAutoHideTimer()
}

// Backward or forward video with arrow keys
if (
[37, 39].includes(keyCode) &&
(activeElement === this.container || activeElement === this.player.elements.progressBar)
) {
// Prevent default behavior on input range
e.preventDefault()

if (keyCode === 37) {
this.fastForward('backward')
} else if (keyCode === 39) {
this.fastForward('forward')
}
}

// Increase or decrease volume with arrow keys
if (
[38, 40].includes(keyCode) &&
(activeElement === this.container || activeElement === this.player.elements.volume)
) {
if (keyCode === 38) {
this.increaseVolume()
} else if (keyCode === 40) {
this.decreaseVolume()
}
}

// Toggle the media playback with spacebar key
if (keyCode === 32 && activeElement === this.container) {
this.player.controlBar.togglePlayPause(e)
}
}

/**
* On mousemove on the player
*/
Expand All @@ -316,37 +259,6 @@ class Vlitejs {
}
}

/**
* Trigger the video fast forward (front and rear)
* @param direction Direction (backward|forward)
*/
fastForward(direction: string) {
this.player.getCurrentTime().then((seconds: number) => {
this.player.seekTo(
direction === 'backward' ? seconds - this.options.seekTime : seconds + this.options.seekTime
)
})
}

/**
* Increase the player volume
*/
increaseVolume() {
this.player.isMuted && this.player.unMute()
this.player.getVolume().then((volume: number) => {
this.player.setVolume(Math.min(Math.round((volume + this.options.volumeStep) * 10) / 10, 1))
})
}

/**
* Decrease the player volume
*/
decreaseVolume() {
this.player.getVolume().then((volume: number) => {
this.player.setVolume(Math.max(Math.round((volume - this.options.volumeStep) * 10) / 10, 0))
})
}

/**
* Stop the auto hide timer and show the video control bar
*/
Expand All @@ -372,8 +284,6 @@ class Vlitejs {
* Remove events listeners
*/
removeEvents() {
this.container.removeEventListener('keydown', this.onKeydown)

if (this.type === 'video') {
this.container.removeEventListener('click', this.onClickOnPlayer)
this.container.removeEventListener('dblclick', this.onDoubleClickOnPlayer)
Expand Down
19 changes: 10 additions & 9 deletions src/plugins/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@ The plugin's API allows you to extends the capabilities of `vLitejs` and add cus

Each plugin can be loaded on demand with the API.

| Plugin name | Description |
| ------------------------------------- | ------------------------------------------ |
| [Subtitle](./subtitle/README.md) | Supports for multiple caption tracks (VTT) |
| [Picture-in-Picture](./pip/README.md) | Supports for picture-in-picture mode |
| [Volume bar](./volume-bar/README.md) | Supports for volume bar |
| [Cast](./cast/README.md) | Supports for Google Cast API |
| [AirPlay](./airplay/README.md) | Supports for Apple AirPlay API |
| [Ima](./ima/README.md) | Supports for Google IMA SDK |
| [Sticky](./sticky/README.md) | Supports for sticky mode |
| Plugin name | Description |
| ------------------------------------- | ---------------------------------------------- |
| [Subtitle](./subtitle/README.md) | Supports for multiple caption tracks (VTT) |
| [Picture-in-Picture](./pip/README.md) | Supports for picture-in-picture mode |
| [Volume bar](./volume-bar/README.md) | Supports for volume bar |
| [Cast](./cast/README.md) | Supports for Google Cast API |
| [AirPlay](./airplay/README.md) | Supports for Apple AirPlay API |
| [Ima](./ima/README.md) | Supports for Google IMA SDK |
| [Sticky](./sticky/README.md) | Supports for sticky mode |
| [Hotkeys](./hotkeys/README.md) | Supports for hotkeys to add keyboard shortcuts |

## Create a custom plugin

Expand Down
62 changes: 62 additions & 0 deletions src/plugins/hotkeys/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Plugin: Hotkeys

Supports for hotkeys to add keyboard shortcuts.

The player accepts the following keyboard shortcuts.

| Key | Action |
| :---------------: | ------------------------ |
| <kbd>space</kbd> | Toggle playback |
| <kbd>Esc</kbd> | Exit the fullscreen |
| <kbd>&larr;</kbd> | Seek backward of `5s` |
| <kbd>&rarr;</kbd> | Seek forward of `5s` |
| <kbd>&uarr;</kbd> | Increase volume of `10%` |
| <kbd>&darr;</kbd> | Decrease volume of `10%` |

## Overview

| <!-- --> | <!-- --> |
| ---------------- | -------------------------------------------- |
| Name | `hotkeys` |
| Path | `vlitejs/plugins/hotkeys` |
| Entry point | `vlitejs/plugins/hotkeys/hotkeys.js` |
| Provider&sup2; | `'html5', 'youtube', 'vimeo', 'dailymotion'` |
| Media type&sup3; | `'video', 'audio'` |

## Usage

### HTML

```html
<video id="player" src="<path_to_video_mp4>"></video>
```

### JavaScript

```js
import 'vlitejs/vlite.css';
import Vlitejs from 'vlitejs';
import VlitejsHotkeys from 'vlitejs/plugins/hotkeys.js';

Vlitejs.registerPlugin('hotkeys', VlitejsHotkeys);

new Vlitejs('#player', {
plugins: ['hotkeys']
});
```

## Configuration

The plugin allows customization with an optional object as the third parameter of the `registerPlugin` function.

| Event Type | Type | Default | Description |
| ------------ | :--------: | :-----: | ---------------------------------------------------------------------------- |
| `seekTime` | `Number` | `5` | Set seek time seconds of the backward and forward shortcuts |
| `volumeStep` | `Number` | `0.1` | Set the volume step (between 0 and 1) of the increase and decrease shortcuts |

```js
Vlitejs.registerPlugin('hotkeys', VlitejsHotkeys, {
seekTime: 3,
volumeStep: 0.2
});
```
Loading

0 comments on commit d168ca6

Please sign in to comment.