Added ‘global’ keyboard shortcut option
This commit is contained in:
parent
d5b5faafbb
commit
df7f52d885
@ -1,5 +1,8 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
# v2.0.2
|
||||||
|
- Added 'global' keyboard shortcut option
|
||||||
|
|
||||||
# v2.0.1
|
# v2.0.1
|
||||||
- Version bump for NPM
|
- Version bump for NPM
|
||||||
|
|
||||||
|
4
dist/plyr.js
vendored
4
dist/plyr.js
vendored
File diff suppressed because one or more lines are too long
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "plyr",
|
"name": "plyr",
|
||||||
"version": "2.0.1",
|
"version": "2.0.2",
|
||||||
"description": "A simple, accessible and customizable HTML5, YouTube and Vimeo media player",
|
"description": "A simple, accessible and customizable HTML5, YouTube and Vimeo media player",
|
||||||
"homepage": "http://plyr.io",
|
"homepage": "http://plyr.io",
|
||||||
"main": "src/js/plyr.js",
|
"main": "src/js/plyr.js",
|
||||||
|
33
readme.md
33
readme.md
@ -122,7 +122,7 @@ Include the `plyr.js` script before the closing `</body>` tag and then call `ply
|
|||||||
If you want to use our CDN for the JavaScript, you can use the following:
|
If you want to use our CDN for the JavaScript, you can use the following:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<script src="https://cdn.plyr.io/2.0.1/plyr.js"></script>
|
<script src="https://cdn.plyr.io/2.0.2/plyr.js"></script>
|
||||||
```
|
```
|
||||||
|
|
||||||
### CSS
|
### CSS
|
||||||
@ -135,11 +135,11 @@ Include the `plyr.css` stylsheet into your `<head>`
|
|||||||
If you want to use our CDN for the default CSS, you can use the following:
|
If you want to use our CDN for the default CSS, you can use the following:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<link rel="stylesheet" href="https://cdn.plyr.io/2.0.1/plyr.css">
|
<link rel="stylesheet" href="https://cdn.plyr.io/2.0.2/plyr.css">
|
||||||
```
|
```
|
||||||
|
|
||||||
### SVG Sprite
|
### SVG Sprite
|
||||||
The SVG sprite is loaded automatically from our CDN. To change this, see the [options](#Options) below. For reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/2.0.1/plyr.svg`.
|
The SVG sprite is loaded automatically from our CDN. To change this, see the [options](#Options) below. For reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/2.0.2/plyr.svg`.
|
||||||
|
|
||||||
## Advanced
|
## Advanced
|
||||||
|
|
||||||
@ -321,9 +321,9 @@ Note the single quotes encapsulating the JSON and double quotes on the object ke
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>keyboardShortcuts</code></td>
|
<td><code>keyboardShortcuts</code></td>
|
||||||
<td>Boolean</td>
|
<td>Object</td>
|
||||||
<td><code>true</code></td>
|
<td><code>{ focused: true, global: true }</code></td>
|
||||||
<td>Enable <a href="#shortcuts">keyboard shortcuts</a></td>
|
<td>Enable <a href="#shortcuts">keyboard shortcuts</a> for focused players only or global as well (if there's only one player in the document)</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>tooltips</code></td>
|
<td><code>tooltips</code></td>
|
||||||
@ -873,50 +873,65 @@ More info on the respective API's here:
|
|||||||
*Please note*: not all API methods may work 100%. Your mileage may vary. It's better to use the universal plyr API where possible.
|
*Please note*: not all API methods may work 100%. Your mileage may vary. It's better to use the universal plyr API where possible.
|
||||||
|
|
||||||
## Shortcuts
|
## Shortcuts
|
||||||
By default, a focused player will bind the following keyboard shortcuts:
|
By default, a player will bind the following keyboard shortcuts when it has focus. If you have the `global` option to `true` and there's only one player in the document then the shortcuts will work when any element has focus, apart from an element that requires input (such as an `<input>`, `<select>` or `[contenteditable]`).
|
||||||
|
|
||||||
<table class="table" width="100%">
|
<table class="table" width="100%">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th width="25%">Key</th>
|
<th width="25%">Key</th>
|
||||||
<th width="75%">Action</th>
|
<th width="25%">Global</th>
|
||||||
|
<th width="50%">Action</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>0</code> to <code>9</code></td>
|
<td><code>0</code> to <code>9</code></td>
|
||||||
|
<td>✔</td>
|
||||||
<td>Seek from 0 to 90% respectively</td>
|
<td>Seek from 0 to 90% respectively</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>space</code> or <code>K</code></td>
|
<td><code>space</code></td>
|
||||||
|
<td></td>
|
||||||
|
<td>Toggle playback</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>K</code></td>
|
||||||
|
<td>✔</td>
|
||||||
<td>Toggle playback</td>
|
<td>Toggle playback</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>←</code></td>
|
<td><code>←</code></td>
|
||||||
|
<td></td>
|
||||||
<td>Seek backward by the <code>seekTime</code> option</td>
|
<td>Seek backward by the <code>seekTime</code> option</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>→</code></td>
|
<td><code>→</code></td>
|
||||||
|
<td></td>
|
||||||
<td>Seek forward by the <code>seekTime</code> option</td>
|
<td>Seek forward by the <code>seekTime</code> option</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>↑</code></td>
|
<td><code>↑</code></td>
|
||||||
|
<td></td>
|
||||||
<td>Increase volume</td>
|
<td>Increase volume</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>↓</code></td>
|
<td><code>↓</code></td>
|
||||||
|
<td></td>
|
||||||
<td>Decrease volume</td>
|
<td>Decrease volume</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>M</code></td>
|
<td><code>M</code></td>
|
||||||
|
<td>✔</td>
|
||||||
<td>Toggle mute</td>
|
<td>Toggle mute</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>F</code></td>
|
<td><code>F</code></td>
|
||||||
|
<td>✔</td>
|
||||||
<td>Toggle fullscreen</td>
|
<td>Toggle fullscreen</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>C</code></td>
|
<td><code>C</code></td>
|
||||||
|
<td>✔</td>
|
||||||
<td>Toggle captions</td>
|
<td>Toggle captions</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
175
src/js/plyr.js
175
src/js/plyr.js
@ -1,6 +1,6 @@
|
|||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// Plyr
|
// Plyr
|
||||||
// plyr.js v2.0.1
|
// plyr.js v2.0.2
|
||||||
// https://github.com/selz/plyr
|
// https://github.com/selz/plyr
|
||||||
// License: The MIT License (MIT)
|
// License: The MIT License (MIT)
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
@ -43,12 +43,15 @@
|
|||||||
displayDuration: true,
|
displayDuration: true,
|
||||||
loadSprite: true,
|
loadSprite: true,
|
||||||
iconPrefix: 'plyr',
|
iconPrefix: 'plyr',
|
||||||
iconUrl: 'https://cdn.plyr.io/2.0.1/plyr.svg',
|
iconUrl: 'https://cdn.plyr.io/2.0.2/plyr.svg',
|
||||||
clickToPlay: true,
|
clickToPlay: true,
|
||||||
hideControls: true,
|
hideControls: true,
|
||||||
showPosterOnEnd: false,
|
showPosterOnEnd: false,
|
||||||
disableContextMenu: true,
|
disableContextMenu: true,
|
||||||
keyboardShorcuts: true,
|
keyboardShorcuts: {
|
||||||
|
focused: true,
|
||||||
|
global: true
|
||||||
|
},
|
||||||
tooltips: {
|
tooltips: {
|
||||||
controls: false,
|
controls: false,
|
||||||
seek: true
|
seek: true
|
||||||
@ -56,6 +59,7 @@
|
|||||||
selectors: {
|
selectors: {
|
||||||
html5: 'video, audio',
|
html5: 'video, audio',
|
||||||
embed: '[data-type]',
|
embed: '[data-type]',
|
||||||
|
editable: 'input, select, [contenteditable]',
|
||||||
container: '.plyr',
|
container: '.plyr',
|
||||||
controls: {
|
controls: {
|
||||||
container: null,
|
container: null,
|
||||||
@ -2896,88 +2900,111 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Keyboard shortcuts
|
// Keyboard shortcuts
|
||||||
if (config.keyboardShorcuts) {
|
if (config.keyboardShorcuts.focused) {
|
||||||
var first = true;
|
var last = null;
|
||||||
|
|
||||||
_on(plyr.container, 'keydown keyup', function(event) {
|
// Handle global presses
|
||||||
var code = getKeyCode(event),
|
if (config.keyboardShorcuts.global) {
|
||||||
pressed = event.type === 'keydown';
|
_on(window, 'keydown keyup', function(event) {
|
||||||
|
var code = getKeyCode(event),
|
||||||
|
focused = getFocusElement(),
|
||||||
|
allowed = [48,49,50,51,52,53,54,56,57,75,77,70,67],
|
||||||
|
count = get().length;
|
||||||
|
|
||||||
// If the event is bubbled from the media element
|
// Only handle global key press if there's only one player
|
||||||
// Firefox doesn't get the keycode for whatever reason
|
// and the key is in the allowed keys
|
||||||
if (!_is.number(code)) {
|
// and if the focused element is not editable (e.g. text input)
|
||||||
|
// and any that accept key input http://webaim.org/techniques/keyboard/
|
||||||
|
if (count === 1 && _inArray(allowed, code) && (!_is.htmlElement(focused) || !_matches(focused, config.selectors.editable))) {
|
||||||
|
handleKey(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle presses on focused
|
||||||
|
_on(plyr.container, 'keydown keyup', handleKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleKey(event) {
|
||||||
|
var code = getKeyCode(event),
|
||||||
|
pressed = event.type === 'keydown',
|
||||||
|
held = pressed && code === last;
|
||||||
|
|
||||||
|
// If the event is bubbled from the media element
|
||||||
|
// Firefox doesn't get the keycode for whatever reason
|
||||||
|
if (!_is.number(code)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seek by the number keys
|
||||||
|
function seekByKey() {
|
||||||
|
// Get current duration
|
||||||
|
var duration = plyr.media.duration;
|
||||||
|
|
||||||
|
// Bail if we have no duration set
|
||||||
|
if (!_is.number(duration)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seek by the number keys
|
// Divide the max duration into 10th's and times by the number value
|
||||||
function seekByKey() {
|
_seek((duration / 10) * (code - 48));
|
||||||
// Get current duration
|
}
|
||||||
var duration = plyr.media.duration;
|
|
||||||
|
|
||||||
// Bail if we have no duration set
|
// Handle the key on keydown
|
||||||
if (!_is.number(duration)) {
|
// Reset on keyup
|
||||||
return;
|
if (pressed) {
|
||||||
}
|
// Which keycodes should we prevent default
|
||||||
|
var preventDefault = [48,49,50,51,52,53,54,56,57,32,75,38,40,77,39,37,70,67];
|
||||||
|
|
||||||
// Divide the max duration into 10th's and times by the number value
|
// If the code is found prevent default (e.g. prevent scrolling for arrows)
|
||||||
_seek((duration / 10) * (code - 48));
|
if (_inArray(preventDefault, code)) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle the key on keydown
|
switch(code) {
|
||||||
// Reset on keyup
|
// 0-9
|
||||||
if (pressed) {
|
case 48:
|
||||||
// Which keycodes should we prevent default
|
case 49:
|
||||||
var preventDefault = [48,49,50,51,52,53,54,56,57,32,75,38,40,77,39,37,70,67];
|
case 50:
|
||||||
|
case 51:
|
||||||
// If the code is found prevent default (e.g. prevent scrolling for arrows)
|
case 52:
|
||||||
if (_inArray(preventDefault, code)) {
|
case 53:
|
||||||
event.preventDefault();
|
case 54:
|
||||||
}
|
case 55:
|
||||||
|
case 56:
|
||||||
switch(code) {
|
case 57: if (!held) { seekByKey(); } break;
|
||||||
// 0-9
|
// Space and K key
|
||||||
case 48:
|
case 32:
|
||||||
case 49:
|
case 75: if (!held) { _togglePlay(); } break;
|
||||||
case 50:
|
// Arrow up
|
||||||
case 51:
|
case 38: _increaseVolume(); break;
|
||||||
case 52:
|
// Arrow down
|
||||||
case 53:
|
case 40: _decreaseVolume(); break;
|
||||||
case 54:
|
// M key
|
||||||
case 55:
|
case 77: if (!held) { _toggleMute() } break;
|
||||||
case 56:
|
// Arrow forward
|
||||||
case 57: if (first) { seekByKey() } break;
|
case 39: _forward(); break;
|
||||||
// Space and K key
|
// Arrow back
|
||||||
case 32:
|
case 37: _rewind(); break;
|
||||||
case 75: if (first) { _togglePlay(); } break;
|
// F key
|
||||||
// Arrow up
|
case 70: _toggleFullscreen(); break;
|
||||||
case 38: _increaseVolume(); break;
|
// C key
|
||||||
// Arrow down
|
case 67: if (!held) { _toggleCaptions(); } break;
|
||||||
case 40: _decreaseVolume(); break;
|
|
||||||
// M key
|
|
||||||
case 77: if (first) { _toggleMute() } break;
|
|
||||||
// Arrow forward
|
|
||||||
case 39: _forward(); break;
|
|
||||||
// Arrow back
|
|
||||||
case 37: _rewind(); break;
|
|
||||||
// F key
|
|
||||||
case 70: if (first) { _toggleFullscreen() } break;
|
|
||||||
// C key
|
|
||||||
case 67: if (first) { _toggleCaptions() } break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Escape is handle natively when in full screen
|
|
||||||
// So we only need to worry about non native
|
|
||||||
if (!fullscreen.supportsFullScreen && plyr.isFullscreen && code === 27) {
|
|
||||||
_toggleFullscreen();
|
|
||||||
}
|
|
||||||
|
|
||||||
// First run completed
|
|
||||||
first = false;
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
first = true;
|
// Escape is handle natively when in full screen
|
||||||
|
// So we only need to worry about non native
|
||||||
|
if (!fullscreen.supportsFullScreen && plyr.isFullscreen && code === 27) {
|
||||||
|
_toggleFullscreen();
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
// Store last code for next cycle
|
||||||
|
last = code;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
last = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Focus/tab management
|
// Focus/tab management
|
||||||
|
Loading…
x
Reference in New Issue
Block a user