mirror of
https://github.com/DanielnetoDotCom/YouPHPTube
synced 2025-10-03 01:39:24 +02:00
Update seek buttons
This commit is contained in:
parent
2b7ac37bc3
commit
f016de70f9
30 changed files with 1092 additions and 2 deletions
15
node_modules/.package-lock.json
generated
vendored
15
node_modules/.package-lock.json
generated
vendored
|
@ -2024,6 +2024,21 @@
|
||||||
"video.js": "5.x || 6.x || 7.x || *"
|
"video.js": "5.x || 6.x || 7.x || *"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/videojs-seek-buttons": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/videojs-seek-buttons/-/videojs-seek-buttons-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-LcaskoqIshE1Dy/yqVPRlt2qSYzDq/vT9iqYxyy+crKdBW4zBXW743GVA7G7kX8BF8U9EGgQTajRJQGBQMtQaQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"global": "^4.4.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14",
|
||||||
|
"npm": ">=6"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"video.js": "^8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/videojs-vtt.js": {
|
"node_modules/videojs-vtt.js": {
|
||||||
"version": "0.15.4",
|
"version": "0.15.4",
|
||||||
"resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.15.4.tgz",
|
"resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.15.4.tgz",
|
||||||
|
|
30
node_modules/videojs-seek-buttons/CONTRIBUTING.md
generated
vendored
Normal file
30
node_modules/videojs-seek-buttons/CONTRIBUTING.md
generated
vendored
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# CONTRIBUTING
|
||||||
|
|
||||||
|
We welcome contributions from everyone!
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
Make sure you have Node.js 8 or higher and npm installed.
|
||||||
|
|
||||||
|
1. Fork this repository and clone your fork
|
||||||
|
1. Install dependencies: `npm install`
|
||||||
|
1. Run a development server: `npm start`
|
||||||
|
|
||||||
|
### Making Changes
|
||||||
|
|
||||||
|
Refer to the [video.js plugin conventions][conventions] for more detail on best practices and tooling for video.js plugin authorship.
|
||||||
|
|
||||||
|
When you've made your changes, push your commit(s) to your fork and issue a pull request against the original repository.
|
||||||
|
|
||||||
|
### Running Tests
|
||||||
|
|
||||||
|
Testing is a crucial part of any software project. For all but the most trivial changes (typos, etc) test cases are expected. Tests are run in actual browsers using [Karma][karma].
|
||||||
|
|
||||||
|
- In all available and supported browsers: `npm test`
|
||||||
|
- In a specific browser: `npm run test:chrome`, `npm run test:firefox`, etc.
|
||||||
|
- While development server is running (`npm start`), navigate to [`http://localhost:9999/test/`][local]
|
||||||
|
|
||||||
|
|
||||||
|
[karma]: http://karma-runner.github.io/
|
||||||
|
[local]: http://localhost:9999/test/
|
||||||
|
[conventions]: https://github.com/videojs/generator-videojs-plugin/blob/master/docs/conventions.md
|
13
node_modules/videojs-seek-buttons/LICENSE
generated
vendored
Normal file
13
node_modules/videojs-seek-buttons/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
Copyright mister-ben <git@misterben.me>
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
133
node_modules/videojs-seek-buttons/README.md
generated
vendored
Normal file
133
node_modules/videojs-seek-buttons/README.md
generated
vendored
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
# videojs-seek-buttons
|
||||||
|
|
||||||
|
Plugin for video.js to add seek buttons to the control bar. These buttons allow the user to skip forward or back by a configured number of seconds.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||||
|
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||||
|
|
||||||
|
|
||||||
|
- [Installation](#installation)
|
||||||
|
- [Options](#options)
|
||||||
|
- [Control position](#control-position)
|
||||||
|
- [Usage](#usage)
|
||||||
|
- [`<script>` Tag](#script-tag)
|
||||||
|
- [Browserify/CommonJS](#browserifycommonjs)
|
||||||
|
- [RequireJS/AMD](#requirejsamd)
|
||||||
|
- [License](#license)
|
||||||
|
|
||||||
|
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Version 3.x requires video.js version 6.x or 7.x to be installed as a peer dependency (latest v7 is recommended).
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install videojs-seek-buttons@latest7
|
||||||
|
```
|
||||||
|
|
||||||
|
Version 4.x requires video.js version 8.x to be installed as a peer dependency. Earlier versions of Video.js are not supported.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install videojs-seek-buttons@latest8
|
||||||
|
```
|
||||||
|
|
||||||
|
However Video.js 8.2.0 + has a [built-in seek buttons functionality](https://videojs.com/guides/options/#skipbuttons). Consider using that instead of this plugin.
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
- `forward` - if a number greater than 0, a seek forward button will be added which seeks that number of seconds
|
||||||
|
- `back` - if a number greater than 0, a seek back button will be added which seeks that number of seconds
|
||||||
|
- `forwardIndex` - the position in the control bar to insert the button. Defaults to `1`. See note below.
|
||||||
|
- `backIndex` - the position in the control bar to insert the button. Defaults to `1`. See note below.
|
||||||
|
|
||||||
|
### Control position
|
||||||
|
|
||||||
|
`forwardIndex` and `backIndex` set the posiiton of the button in the control bar. Note if both a back and forward button are used, the forward button is inserted first.
|
||||||
|
|
||||||
|
Assuming the standard control bar, the play button is at index `0`. With the default index of `1` for both, the forward button is inserted after the play button, then the back button is inserted after the play button and before the forward button. Setting `backIndex` to `0` would place the back button before the play button instead, so they surround the play button.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
To include videojs-seek-buttons on your website or web application, use any of the following methods to include the script.
|
||||||
|
|
||||||
|
You also need to include the plugin's CSS.
|
||||||
|
|
||||||
|
### `<script>` Tag
|
||||||
|
|
||||||
|
This is the simplest case. Get the script in whatever way you prefer and include the plugin _after_ you include [video.js][videojs], so that the `videojs` global is available.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<link rel="stylesheet" href="//path/to/video-js.css">
|
||||||
|
<link rel="stylesheet" href="//path/to/videojs-seek-buttons.css">
|
||||||
|
<script src="//path/to/video.min.js"></script>
|
||||||
|
<script src="//path/to/videojs-seek-buttons.min.js"></script>
|
||||||
|
<script>
|
||||||
|
var player = videojs('my-video');
|
||||||
|
|
||||||
|
player.seekButtons({
|
||||||
|
forward: 30,
|
||||||
|
back: 10
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// You could alternatively include the plugin in the setup options, e.g.
|
||||||
|
// var player = videojs('my-video', {
|
||||||
|
// plugins: {
|
||||||
|
// seekButtons: {
|
||||||
|
// forward: 30,
|
||||||
|
// back: 10
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
The dist versions will be available from services which host npm packages such as jsdelivr:
|
||||||
|
|
||||||
|
* https://cdn.jsdelivr.net/npm/videojs-seek-buttons/dist/videojs-seek-buttons.min.js
|
||||||
|
* https://cdn.jsdelivr.net/npm/videojs-seek-buttons/dist/videojs-seek-buttons.css
|
||||||
|
|
||||||
|
### Browserify/CommonJS
|
||||||
|
|
||||||
|
When using with Browserify, install videojs-seek-buttons via npm and `require` the plugin as you would any other module.
|
||||||
|
Make sure if using React to also `include "videojs-seek-buttons/dist/videojs-seek-buttons.css"`, otherwise the icons will not appear in the control bar.
|
||||||
|
|
||||||
|
```js
|
||||||
|
var videojs = require('video.js');
|
||||||
|
|
||||||
|
// The actual plugin function is exported by this module, but it is also
|
||||||
|
// attached to the `Player.prototype`; so, there is no need to assign it
|
||||||
|
// to a variable.
|
||||||
|
require('videojs-seek-buttons');
|
||||||
|
|
||||||
|
var player = videojs('my-video');
|
||||||
|
|
||||||
|
player.seekButtons({
|
||||||
|
forward: 30,
|
||||||
|
back: 10
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### RequireJS/AMD
|
||||||
|
|
||||||
|
When using with RequireJS (or another AMD library), get the script in whatever way you prefer and `require` the plugin as you normally would:
|
||||||
|
|
||||||
|
```js
|
||||||
|
require(['video.js', 'videojs-seek-buttons'], function(videojs) {
|
||||||
|
var player = videojs('my-video');
|
||||||
|
|
||||||
|
player.seekButtons({
|
||||||
|
forward: 30,
|
||||||
|
back: 10
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Apache-2.0. Copyright (c) mister-ben <git@misterben.me>
|
||||||
|
|
||||||
|
|
||||||
|
[videojs]: http://videojs.com/
|
4
node_modules/videojs-seek-buttons/dist/lang/de.js
generated
vendored
Normal file
4
node_modules/videojs-seek-buttons/dist/lang/de.js
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
videojs.addLanguage('de', {
|
||||||
|
"Seek forward {{seconds}} seconds": "{{seconds}} Sekunden vorspulen",
|
||||||
|
"Seek back {{seconds}} seconds": "{{seconds}} Sekunden zurückspulen"
|
||||||
|
});
|
4
node_modules/videojs-seek-buttons/dist/lang/en.js
generated
vendored
Normal file
4
node_modules/videojs-seek-buttons/dist/lang/en.js
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
videojs.addLanguage('en', {
|
||||||
|
"Seek forward {{seconds}} seconds": "Seek forward {{seconds}} seconds",
|
||||||
|
"Seek back {{seconds}} seconds": "Seek back {{seconds}} seconds"
|
||||||
|
});
|
4
node_modules/videojs-seek-buttons/dist/lang/fa.js
generated
vendored
Normal file
4
node_modules/videojs-seek-buttons/dist/lang/fa.js
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
videojs.addLanguage('fa', {
|
||||||
|
"Seek forward {{seconds}} seconds": "{{seconds}} ثانیه بعد",
|
||||||
|
"Seek back {{seconds}} seconds": "{{seconds}} ثانیه قبل"
|
||||||
|
});
|
4
node_modules/videojs-seek-buttons/dist/lang/it.js
generated
vendored
Normal file
4
node_modules/videojs-seek-buttons/dist/lang/it.js
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
videojs.addLanguage('it', {
|
||||||
|
"Seek forward {{seconds}} seconds": "Avanti di {{seconds}} secondi",
|
||||||
|
"Seek back {{seconds}} seconds": "Indietro di {{seconds}} secondi"
|
||||||
|
});
|
4
node_modules/videojs-seek-buttons/dist/lang/ja.js
generated
vendored
Normal file
4
node_modules/videojs-seek-buttons/dist/lang/ja.js
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
videojs.addLanguage('ja', {
|
||||||
|
"Seek forward {{seconds}} seconds": "{{seconds}}秒進む",
|
||||||
|
"Seek back {{seconds}} seconds": "{{seconds}}秒戻る"
|
||||||
|
});
|
4
node_modules/videojs-seek-buttons/dist/lang/lv.js
generated
vendored
Normal file
4
node_modules/videojs-seek-buttons/dist/lang/lv.js
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
videojs.addLanguage('lv', {
|
||||||
|
"Seek forward {{seconds}} seconds": "Pārtīt uz priekšu {{seconds}} sekundes",
|
||||||
|
"Seek back {{seconds}} seconds": "Pārtīt atpakaļ {{seconds}} sekundes"
|
||||||
|
});
|
4
node_modules/videojs-seek-buttons/dist/lang/nl.js
generated
vendored
Normal file
4
node_modules/videojs-seek-buttons/dist/lang/nl.js
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
videojs.addLanguage('nl', {
|
||||||
|
"Seek forward {{seconds}} seconds": "{{seconds}} seconden vooruit",
|
||||||
|
"Seek back {{seconds}} seconds": "{{seconds}} seconden terug"
|
||||||
|
});
|
4
node_modules/videojs-seek-buttons/dist/lang/ru.js
generated
vendored
Normal file
4
node_modules/videojs-seek-buttons/dist/lang/ru.js
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
videojs.addLanguage('ru', {
|
||||||
|
"Seek forward {{seconds}} seconds": "На {{seconds}} секунд вперед",
|
||||||
|
"Seek back {{seconds}} seconds": "На {{seconds}} секунд назад"
|
||||||
|
});
|
4
node_modules/videojs-seek-buttons/dist/lang/zh-CN.js
generated
vendored
Normal file
4
node_modules/videojs-seek-buttons/dist/lang/zh-CN.js
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
videojs.addLanguage('zh-CN', {
|
||||||
|
"Seek forward {{seconds}} seconds": "快进 {{seconds}} 秒",
|
||||||
|
"Seek back {{seconds}} seconds": "快退 {{seconds}} 秒"
|
||||||
|
});
|
4
node_modules/videojs-seek-buttons/dist/lang/zh-TW.js
generated
vendored
Normal file
4
node_modules/videojs-seek-buttons/dist/lang/zh-TW.js
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
videojs.addLanguage('zh-TW', {
|
||||||
|
"Seek forward {{seconds}} seconds": "快轉 {{seconds}} 秒",
|
||||||
|
"Seek back {{seconds}} seconds": "倒轉 {{seconds}} 秒"
|
||||||
|
});
|
133
node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.cjs.js
generated
vendored
Normal file
133
node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.cjs.js
generated
vendored
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
/*! @name videojs-seek-buttons @version 4.0.3 @license Apache-2.0 */
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var videojs = require('video.js');
|
||||||
|
|
||||||
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
||||||
|
|
||||||
|
var videojs__default = /*#__PURE__*/_interopDefaultLegacy(videojs);
|
||||||
|
|
||||||
|
var version = "4.0.3";
|
||||||
|
|
||||||
|
const Button = videojs__default["default"].getComponent('Button'); // Default options for the plugin.
|
||||||
|
|
||||||
|
const defaults = {
|
||||||
|
forwardIndex: 1,
|
||||||
|
backIndex: 1
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Set up buttons when the player is ready.
|
||||||
|
*
|
||||||
|
* @function onPlayerReady
|
||||||
|
* @param {Player} player
|
||||||
|
* A Video.js player object.
|
||||||
|
*
|
||||||
|
* @param {Object} [options={}]
|
||||||
|
* A plain object containing options for the plugin.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const onPlayerReady = (player, options) => {
|
||||||
|
player.addClass('vjs-seek-buttons');
|
||||||
|
|
||||||
|
if (options.forward && options.forward > 0) {
|
||||||
|
player.controlBar.seekForward = player.controlBar.addChild('seekButton', {
|
||||||
|
direction: 'forward',
|
||||||
|
seconds: options.forward
|
||||||
|
}, options.forwardIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.back && options.back > 0) {
|
||||||
|
player.controlBar.seekBack = player.controlBar.addChild('seekButton', {
|
||||||
|
direction: 'back',
|
||||||
|
seconds: options.back
|
||||||
|
}, options.backIndex);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Plugin init if ready or on ready
|
||||||
|
*
|
||||||
|
* @function seekButtons
|
||||||
|
* @param {Object} [options={}]
|
||||||
|
* An object of options left to the plugin author to define.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
const seekButtons = function (options) {
|
||||||
|
this.ready(() => {
|
||||||
|
onPlayerReady(this, videojs__default["default"].obj.merge(defaults, options));
|
||||||
|
});
|
||||||
|
}; // Include the version number.
|
||||||
|
|
||||||
|
|
||||||
|
seekButtons.VERSION = version;
|
||||||
|
/**
|
||||||
|
* Button to seek forward/back
|
||||||
|
*
|
||||||
|
* @extends Button
|
||||||
|
* @class SeekButton
|
||||||
|
*/
|
||||||
|
|
||||||
|
class SeekButton extends Button {
|
||||||
|
/**
|
||||||
|
* Constructor for class
|
||||||
|
*
|
||||||
|
* @param {Player|Object} player The player
|
||||||
|
* @param {Object=} options Button options
|
||||||
|
* @param {string} options.direction back or forward
|
||||||
|
* @param {Int} options.seconds number of seconds to seek
|
||||||
|
*/
|
||||||
|
constructor(player, options) {
|
||||||
|
super(player, options);
|
||||||
|
this.$('.vjs-icon-placeholder').classList.add('vjs-icon-replay');
|
||||||
|
|
||||||
|
if (this.options_.direction === 'forward') {
|
||||||
|
this.controlText(this.localize('Seek forward {{seconds}} seconds').replace('{{seconds}}', this.options_.seconds));
|
||||||
|
} else if (this.options_.direction === 'back') {
|
||||||
|
this.controlText(this.localize('Seek back {{seconds}} seconds').replace('{{seconds}}', this.options_.seconds));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Return button class names which include the seek amount.
|
||||||
|
*
|
||||||
|
* @return {string} css cass string
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
buildCSSClass() {
|
||||||
|
/* Each button will have the classes:
|
||||||
|
`vjs-seek-button`
|
||||||
|
`skip-forward` or `skip-back`
|
||||||
|
`skip-n` where `n` is the number of seconds
|
||||||
|
So you could have a generic icon for "skip back" and a more
|
||||||
|
specific one for "skip back 30 seconds"
|
||||||
|
*/
|
||||||
|
return `vjs-seek-button skip-${this.options_.direction} ` + `skip-${this.options_.seconds} ${super.buildCSSClass()}`;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Seek with the button's configured offset
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
handleClick() {
|
||||||
|
const now = this.player_.currentTime();
|
||||||
|
|
||||||
|
if (this.options_.direction === 'forward') {
|
||||||
|
let duration = this.player_.duration();
|
||||||
|
|
||||||
|
if (this.player_.liveTracker && this.player_.liveTracker.isLive()) {
|
||||||
|
duration = this.player_.liveTracker.seekableEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.player_.currentTime(Math.min(now + this.options_.seconds, duration));
|
||||||
|
} else if (this.options_.direction === 'back') {
|
||||||
|
this.player_.currentTime(Math.max(0, now - this.options_.seconds));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
videojs__default["default"].registerComponent('SeekButton', SeekButton); // Register the plugin with video.js.
|
||||||
|
|
||||||
|
videojs__default["default"].registerPlugin('seekButtons', seekButtons);
|
||||||
|
|
||||||
|
module.exports = seekButtons;
|
2
node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.css
generated
vendored
Normal file
2
node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.css
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/*! @name videojs-seek-buttons @version 4.0.3 @license Apache-2.0 */
|
||||||
|
.video-js .vjs-seek-button{cursor:pointer}.video-js .vjs-seek-button.skip-back .vjs-icon-placeholder::before{transform:rotate(-45deg)}.video-js .vjs-seek-button.skip-forward .vjs-icon-placeholder::before{transform:scale(-1,1) rotate(-45deg)}
|
127
node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.es.js
generated
vendored
Normal file
127
node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.es.js
generated
vendored
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
/*! @name videojs-seek-buttons @version 4.0.3 @license Apache-2.0 */
|
||||||
|
import videojs from 'video.js';
|
||||||
|
|
||||||
|
var version = "4.0.3";
|
||||||
|
|
||||||
|
const Button = videojs.getComponent('Button'); // Default options for the plugin.
|
||||||
|
|
||||||
|
const defaults = {
|
||||||
|
forwardIndex: 1,
|
||||||
|
backIndex: 1
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Set up buttons when the player is ready.
|
||||||
|
*
|
||||||
|
* @function onPlayerReady
|
||||||
|
* @param {Player} player
|
||||||
|
* A Video.js player object.
|
||||||
|
*
|
||||||
|
* @param {Object} [options={}]
|
||||||
|
* A plain object containing options for the plugin.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const onPlayerReady = (player, options) => {
|
||||||
|
player.addClass('vjs-seek-buttons');
|
||||||
|
|
||||||
|
if (options.forward && options.forward > 0) {
|
||||||
|
player.controlBar.seekForward = player.controlBar.addChild('seekButton', {
|
||||||
|
direction: 'forward',
|
||||||
|
seconds: options.forward
|
||||||
|
}, options.forwardIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.back && options.back > 0) {
|
||||||
|
player.controlBar.seekBack = player.controlBar.addChild('seekButton', {
|
||||||
|
direction: 'back',
|
||||||
|
seconds: options.back
|
||||||
|
}, options.backIndex);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Plugin init if ready or on ready
|
||||||
|
*
|
||||||
|
* @function seekButtons
|
||||||
|
* @param {Object} [options={}]
|
||||||
|
* An object of options left to the plugin author to define.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
const seekButtons = function (options) {
|
||||||
|
this.ready(() => {
|
||||||
|
onPlayerReady(this, videojs.obj.merge(defaults, options));
|
||||||
|
});
|
||||||
|
}; // Include the version number.
|
||||||
|
|
||||||
|
|
||||||
|
seekButtons.VERSION = version;
|
||||||
|
/**
|
||||||
|
* Button to seek forward/back
|
||||||
|
*
|
||||||
|
* @extends Button
|
||||||
|
* @class SeekButton
|
||||||
|
*/
|
||||||
|
|
||||||
|
class SeekButton extends Button {
|
||||||
|
/**
|
||||||
|
* Constructor for class
|
||||||
|
*
|
||||||
|
* @param {Player|Object} player The player
|
||||||
|
* @param {Object=} options Button options
|
||||||
|
* @param {string} options.direction back or forward
|
||||||
|
* @param {Int} options.seconds number of seconds to seek
|
||||||
|
*/
|
||||||
|
constructor(player, options) {
|
||||||
|
super(player, options);
|
||||||
|
this.$('.vjs-icon-placeholder').classList.add('vjs-icon-replay');
|
||||||
|
|
||||||
|
if (this.options_.direction === 'forward') {
|
||||||
|
this.controlText(this.localize('Seek forward {{seconds}} seconds').replace('{{seconds}}', this.options_.seconds));
|
||||||
|
} else if (this.options_.direction === 'back') {
|
||||||
|
this.controlText(this.localize('Seek back {{seconds}} seconds').replace('{{seconds}}', this.options_.seconds));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Return button class names which include the seek amount.
|
||||||
|
*
|
||||||
|
* @return {string} css cass string
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
buildCSSClass() {
|
||||||
|
/* Each button will have the classes:
|
||||||
|
`vjs-seek-button`
|
||||||
|
`skip-forward` or `skip-back`
|
||||||
|
`skip-n` where `n` is the number of seconds
|
||||||
|
So you could have a generic icon for "skip back" and a more
|
||||||
|
specific one for "skip back 30 seconds"
|
||||||
|
*/
|
||||||
|
return `vjs-seek-button skip-${this.options_.direction} ` + `skip-${this.options_.seconds} ${super.buildCSSClass()}`;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Seek with the button's configured offset
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
handleClick() {
|
||||||
|
const now = this.player_.currentTime();
|
||||||
|
|
||||||
|
if (this.options_.direction === 'forward') {
|
||||||
|
let duration = this.player_.duration();
|
||||||
|
|
||||||
|
if (this.player_.liveTracker && this.player_.liveTracker.isLive()) {
|
||||||
|
duration = this.player_.liveTracker.seekableEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.player_.currentTime(Math.min(now + this.options_.seconds, duration));
|
||||||
|
} else if (this.options_.direction === 'back') {
|
||||||
|
this.player_.currentTime(Math.max(0, now - this.options_.seconds));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
videojs.registerComponent('SeekButton', SeekButton); // Register the plugin with video.js.
|
||||||
|
|
||||||
|
videojs.registerPlugin('seekButtons', seekButtons);
|
||||||
|
|
||||||
|
export { seekButtons as default };
|
137
node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.js
generated
vendored
Normal file
137
node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.js
generated
vendored
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
/*! @name videojs-seek-buttons @version 4.0.3 @license Apache-2.0 */
|
||||||
|
(function (global, factory) {
|
||||||
|
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('video.js')) :
|
||||||
|
typeof define === 'function' && define.amd ? define(['video.js'], factory) :
|
||||||
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.videojsSeekButtons = factory(global.videojs));
|
||||||
|
})(this, (function (videojs) { 'use strict';
|
||||||
|
|
||||||
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
||||||
|
|
||||||
|
var videojs__default = /*#__PURE__*/_interopDefaultLegacy(videojs);
|
||||||
|
|
||||||
|
var version = "4.0.3";
|
||||||
|
|
||||||
|
const Button = videojs__default["default"].getComponent('Button'); // Default options for the plugin.
|
||||||
|
|
||||||
|
const defaults = {
|
||||||
|
forwardIndex: 1,
|
||||||
|
backIndex: 1
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Set up buttons when the player is ready.
|
||||||
|
*
|
||||||
|
* @function onPlayerReady
|
||||||
|
* @param {Player} player
|
||||||
|
* A Video.js player object.
|
||||||
|
*
|
||||||
|
* @param {Object} [options={}]
|
||||||
|
* A plain object containing options for the plugin.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const onPlayerReady = (player, options) => {
|
||||||
|
player.addClass('vjs-seek-buttons');
|
||||||
|
|
||||||
|
if (options.forward && options.forward > 0) {
|
||||||
|
player.controlBar.seekForward = player.controlBar.addChild('seekButton', {
|
||||||
|
direction: 'forward',
|
||||||
|
seconds: options.forward
|
||||||
|
}, options.forwardIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.back && options.back > 0) {
|
||||||
|
player.controlBar.seekBack = player.controlBar.addChild('seekButton', {
|
||||||
|
direction: 'back',
|
||||||
|
seconds: options.back
|
||||||
|
}, options.backIndex);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Plugin init if ready or on ready
|
||||||
|
*
|
||||||
|
* @function seekButtons
|
||||||
|
* @param {Object} [options={}]
|
||||||
|
* An object of options left to the plugin author to define.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
const seekButtons = function (options) {
|
||||||
|
this.ready(() => {
|
||||||
|
onPlayerReady(this, videojs__default["default"].obj.merge(defaults, options));
|
||||||
|
});
|
||||||
|
}; // Include the version number.
|
||||||
|
|
||||||
|
|
||||||
|
seekButtons.VERSION = version;
|
||||||
|
/**
|
||||||
|
* Button to seek forward/back
|
||||||
|
*
|
||||||
|
* @extends Button
|
||||||
|
* @class SeekButton
|
||||||
|
*/
|
||||||
|
|
||||||
|
class SeekButton extends Button {
|
||||||
|
/**
|
||||||
|
* Constructor for class
|
||||||
|
*
|
||||||
|
* @param {Player|Object} player The player
|
||||||
|
* @param {Object=} options Button options
|
||||||
|
* @param {string} options.direction back or forward
|
||||||
|
* @param {Int} options.seconds number of seconds to seek
|
||||||
|
*/
|
||||||
|
constructor(player, options) {
|
||||||
|
super(player, options);
|
||||||
|
this.$('.vjs-icon-placeholder').classList.add('vjs-icon-replay');
|
||||||
|
|
||||||
|
if (this.options_.direction === 'forward') {
|
||||||
|
this.controlText(this.localize('Seek forward {{seconds}} seconds').replace('{{seconds}}', this.options_.seconds));
|
||||||
|
} else if (this.options_.direction === 'back') {
|
||||||
|
this.controlText(this.localize('Seek back {{seconds}} seconds').replace('{{seconds}}', this.options_.seconds));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Return button class names which include the seek amount.
|
||||||
|
*
|
||||||
|
* @return {string} css cass string
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
buildCSSClass() {
|
||||||
|
/* Each button will have the classes:
|
||||||
|
`vjs-seek-button`
|
||||||
|
`skip-forward` or `skip-back`
|
||||||
|
`skip-n` where `n` is the number of seconds
|
||||||
|
So you could have a generic icon for "skip back" and a more
|
||||||
|
specific one for "skip back 30 seconds"
|
||||||
|
*/
|
||||||
|
return `vjs-seek-button skip-${this.options_.direction} ` + `skip-${this.options_.seconds} ${super.buildCSSClass()}`;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Seek with the button's configured offset
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
handleClick() {
|
||||||
|
const now = this.player_.currentTime();
|
||||||
|
|
||||||
|
if (this.options_.direction === 'forward') {
|
||||||
|
let duration = this.player_.duration();
|
||||||
|
|
||||||
|
if (this.player_.liveTracker && this.player_.liveTracker.isLive()) {
|
||||||
|
duration = this.player_.liveTracker.seekableEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.player_.currentTime(Math.min(now + this.options_.seconds, duration));
|
||||||
|
} else if (this.options_.direction === 'back') {
|
||||||
|
this.player_.currentTime(Math.max(0, now - this.options_.seconds));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
videojs__default["default"].registerComponent('SeekButton', SeekButton); // Register the plugin with video.js.
|
||||||
|
|
||||||
|
videojs__default["default"].registerPlugin('seekButtons', seekButtons);
|
||||||
|
|
||||||
|
return seekButtons;
|
||||||
|
|
||||||
|
}));
|
2
node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.min.js
generated
vendored
Normal file
2
node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.min.js
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/*! @name videojs-seek-buttons @version 4.0.3 @license Apache-2.0 */
|
||||||
|
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?module.exports=s(require("video.js")):"function"==typeof define&&define.amd?define(["video.js"],s):(e="undefined"!=typeof globalThis?globalThis:e||self).videojsSeekButtons=s(e.videojs)}(this,(function(e){"use strict";function s(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var t=s(e);const o=t.default.getComponent("Button"),i={forwardIndex:1,backIndex:1},n=function(e){this.ready((()=>{((e,s)=>{e.addClass("vjs-seek-buttons"),s.forward&&s.forward>0&&(e.controlBar.seekForward=e.controlBar.addChild("seekButton",{direction:"forward",seconds:s.forward},s.forwardIndex)),s.back&&s.back>0&&(e.controlBar.seekBack=e.controlBar.addChild("seekButton",{direction:"back",seconds:s.back},s.backIndex))})(this,t.default.obj.merge(i,e))}))};n.VERSION="4.0.3";return t.default.registerComponent("SeekButton",class extends o{constructor(e,s){super(e,s),this.$(".vjs-icon-placeholder").classList.add("vjs-icon-replay"),"forward"===this.options_.direction?this.controlText(this.localize("Seek forward {{seconds}} seconds").replace("{{seconds}}",this.options_.seconds)):"back"===this.options_.direction&&this.controlText(this.localize("Seek back {{seconds}} seconds").replace("{{seconds}}",this.options_.seconds))}buildCSSClass(){return`vjs-seek-button skip-${this.options_.direction} skip-${this.options_.seconds} ${super.buildCSSClass()}`}handleClick(){const e=this.player_.currentTime();if("forward"===this.options_.direction){let s=this.player_.duration();this.player_.liveTracker&&this.player_.liveTracker.isLive()&&(s=this.player_.liveTracker.seekableEnd()),this.player_.currentTime(Math.min(e+this.options_.seconds,s))}else"back"===this.options_.direction&&this.player_.currentTime(Math.max(0,e-this.options_.seconds))}}),t.default.registerPlugin("seekButtons",n),n}));
|
31
node_modules/videojs-seek-buttons/index.html
generated
vendored
Normal file
31
node_modules/videojs-seek-buttons/index.html
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>videojs-seek-buttons Demo</title>
|
||||||
|
<link href="node_modules/video.js/dist/video-js.css" rel="stylesheet">
|
||||||
|
<link href="dist/videojs-seek-buttons.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<video id="videojs-seek-buttons-player" class="video-js vjs-default-skin" controls>
|
||||||
|
<source src="//vjs.zencdn.net/v/oceans.mp4" type='video/mp4'>
|
||||||
|
<source src="//vjs.zencdn.net/v/oceans.webm" type='video/webm'>
|
||||||
|
</video>
|
||||||
|
<ul>
|
||||||
|
<li><a href="/test/debug.html">Run unit tests in browser.</a></li>
|
||||||
|
<li><a href="docs/api/">Read generated docs.</a></li>
|
||||||
|
</ul>
|
||||||
|
<script src="node_modules/video.js/dist/video.js"></script>
|
||||||
|
<script src="dist/videojs-seek-buttons.js"></script>
|
||||||
|
<script>
|
||||||
|
(function(window, videojs) {
|
||||||
|
var examplePlayer = window.examplePlayer = videojs('videojs-seek-buttons-player');
|
||||||
|
var seekButtons = window.seekButtons = examplePlayer.seekButtons({
|
||||||
|
forward: 30,
|
||||||
|
back: 10
|
||||||
|
});
|
||||||
|
// examplePlayer.src('https://cph-p2p-msl.akamaized.net/hls/live/2000341/test/master.m3u8');
|
||||||
|
}(window, window.videojs));
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
107
node_modules/videojs-seek-buttons/package.json
generated
vendored
Normal file
107
node_modules/videojs-seek-buttons/package.json
generated
vendored
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
{
|
||||||
|
"name": "videojs-seek-buttons",
|
||||||
|
"repository": "https://github.com/mister-ben/videojs-seek-buttons",
|
||||||
|
"issues": "https://github.com/mister-ben/videojs-seek-buttons/issues",
|
||||||
|
"version": "4.0.3",
|
||||||
|
"description": "Plugin for video.js to add seek buttons to the control bar",
|
||||||
|
"main": "dist/videojs-seek-buttons.cjs.js",
|
||||||
|
"module": "dist/videojs-seek-buttons.es.js",
|
||||||
|
"generator-videojs-plugin": {
|
||||||
|
"version": "8.0.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"prebuild": "npm run clean",
|
||||||
|
"build": "npm-run-all -s clean -p build:*",
|
||||||
|
"build-prod": "cross-env-shell NO_TEST_BUNDLE=1 'npm run build'",
|
||||||
|
"build-test": "cross-env-shell TEST_BUNDLE_ONLY=1 'npm run build'",
|
||||||
|
"build:css": "postcss -o dist/videojs-seek-buttons.css --config scripts/postcss.config.js src/plugin.css",
|
||||||
|
"build:js": "rollup -c scripts/rollup.config.js",
|
||||||
|
"build:lang": "vjslang --dir dist/lang",
|
||||||
|
"clean": "shx rm -rf ./dist ./test/dist ./cjs ./es && shx mkdir -p ./dist ./test/dist ./cjs ./es",
|
||||||
|
"postclean": "shx mkdir -p ./dist ./test/dist",
|
||||||
|
"docs": "npm-run-all docs:*",
|
||||||
|
"docs:api": "jsdoc src -r -d docs/api",
|
||||||
|
"docs:toc": "doctoc --notitle README.md",
|
||||||
|
"lint": "vjsstandard",
|
||||||
|
"server": "karma start scripts/karma.conf.js --singleRun=false --auto-watch",
|
||||||
|
"start": "npm-run-all -p server watch",
|
||||||
|
"pretest": "npm-run-all lint build",
|
||||||
|
"test": "npm-run-all lint build-test && karma start scripts/karma.conf.js",
|
||||||
|
"posttest": "shx cat test/dist/coverage/text.txt",
|
||||||
|
"test:unit": "karma start scripts/karma.conf.js",
|
||||||
|
"test:verify": "vjsverify --skip-es-check --verbose",
|
||||||
|
"update-changelog": "conventional-changelog -p videojs -i CHANGELOG.md -s",
|
||||||
|
"preversion": "npm test",
|
||||||
|
"version": "is-prerelease || npm run update-changelog && git add CHANGELOG.md",
|
||||||
|
"watch": "npm-run-all -p watch:*",
|
||||||
|
"watch:css": "npm run build:css -- -w",
|
||||||
|
"watch:js": "npm run build:js -- -w",
|
||||||
|
"prepublishOnly": "npm-run-all build-prod && vjsverify --skip-es-check --verbose"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14",
|
||||||
|
"npm": ">=6"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"videojs",
|
||||||
|
"videojs-plugin"
|
||||||
|
],
|
||||||
|
"author": "mister-ben <git@misterben.me>",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"vjsstandard": {
|
||||||
|
"ignore": [
|
||||||
|
"es",
|
||||||
|
"cjs",
|
||||||
|
"dist",
|
||||||
|
"docs",
|
||||||
|
"test/dist"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"CONTRIBUTING.md",
|
||||||
|
"cjs/",
|
||||||
|
"dist/",
|
||||||
|
"docs/",
|
||||||
|
"es/",
|
||||||
|
"index.html",
|
||||||
|
"scripts/",
|
||||||
|
"src/",
|
||||||
|
"test/"
|
||||||
|
],
|
||||||
|
"husky": {
|
||||||
|
"hooks": {
|
||||||
|
"pre-commit": "lint-staged",
|
||||||
|
"pre-push": "npm run test"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint-staged": {
|
||||||
|
"*.js": "vjsstandard --fix",
|
||||||
|
"README.md": "doctoc --notitle"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"global": "^4.4.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/cli": "^7.13.16",
|
||||||
|
"@babel/runtime": "^7.14.0",
|
||||||
|
"@videojs/babel-config": "^1.0.0",
|
||||||
|
"@videojs/generator-helpers": "~3.2.0",
|
||||||
|
"jsdoc": "^4.0.0",
|
||||||
|
"karma": "^6.3.2",
|
||||||
|
"postcss": "^8.2.13",
|
||||||
|
"postcss-cli": "^8.3.1",
|
||||||
|
"rollup": "^2.46.0",
|
||||||
|
"sinon": "^15.0.0",
|
||||||
|
"video.js": "^8.3.0",
|
||||||
|
"videojs-generate-karma-config": "~8.0.0",
|
||||||
|
"videojs-generate-postcss-config": "~3.0.0",
|
||||||
|
"videojs-generate-rollup-config": "^7.0.0",
|
||||||
|
"videojs-generator-verify": "^4.1.0",
|
||||||
|
"videojs-languages": "^2.0.0",
|
||||||
|
"videojs-standard": "^9.0.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"video.js": "^8"
|
||||||
|
},
|
||||||
|
"browser": "dist/videojs-seek-buttons.js"
|
||||||
|
}
|
12
node_modules/videojs-seek-buttons/scripts/karma.conf.js
generated
vendored
Normal file
12
node_modules/videojs-seek-buttons/scripts/karma.conf.js
generated
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
const generate = require('videojs-generate-karma-config');
|
||||||
|
|
||||||
|
module.exports = function(config) {
|
||||||
|
|
||||||
|
// see https://github.com/videojs/videojs-generate-karma-config
|
||||||
|
// for options
|
||||||
|
const options = {};
|
||||||
|
|
||||||
|
config = generate(config, options);
|
||||||
|
|
||||||
|
// any other custom stuff not supported by options here!
|
||||||
|
};
|
9
node_modules/videojs-seek-buttons/scripts/postcss.config.js
generated
vendored
Normal file
9
node_modules/videojs-seek-buttons/scripts/postcss.config.js
generated
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
const generate = require('videojs-generate-postcss-config');
|
||||||
|
|
||||||
|
module.exports = function(context) {
|
||||||
|
const result = generate({}, context);
|
||||||
|
|
||||||
|
// do custom stuff here
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
11
node_modules/videojs-seek-buttons/scripts/rollup.config.js
generated
vendored
Normal file
11
node_modules/videojs-seek-buttons/scripts/rollup.config.js
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
const generate = require('videojs-generate-rollup-config');
|
||||||
|
|
||||||
|
// see https://github.com/videojs/videojs-generate-rollup-config
|
||||||
|
// for options
|
||||||
|
const options = {};
|
||||||
|
const config = generate(options);
|
||||||
|
|
||||||
|
// Add additonal builds/customization here!
|
||||||
|
|
||||||
|
// export the builds to rollup
|
||||||
|
export default Object.values(config.builds);
|
15
node_modules/videojs-seek-buttons/src/plugin.css
generated
vendored
Normal file
15
node_modules/videojs-seek-buttons/src/plugin.css
generated
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
.video-js {
|
||||||
|
|
||||||
|
/* This class is added to the video.js element by the plugin by default. */
|
||||||
|
& .vjs-seek-button {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&.skip-back .vjs-icon-placeholder::before {
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.skip-forward .vjs-icon-placeholder::before {
|
||||||
|
transform: scale(-1, 1) rotate(-45deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
126
node_modules/videojs-seek-buttons/src/plugin.js
generated
vendored
Normal file
126
node_modules/videojs-seek-buttons/src/plugin.js
generated
vendored
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
import videojs from 'video.js';
|
||||||
|
import {version as VERSION} from '../package.json';
|
||||||
|
|
||||||
|
const Button = videojs.getComponent('Button');
|
||||||
|
|
||||||
|
// Default options for the plugin.
|
||||||
|
const defaults = {
|
||||||
|
forwardIndex: 1,
|
||||||
|
backIndex: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up buttons when the player is ready.
|
||||||
|
*
|
||||||
|
* @function onPlayerReady
|
||||||
|
* @param {Player} player
|
||||||
|
* A Video.js player object.
|
||||||
|
*
|
||||||
|
* @param {Object} [options={}]
|
||||||
|
* A plain object containing options for the plugin.
|
||||||
|
*/
|
||||||
|
const onPlayerReady = (player, options) => {
|
||||||
|
|
||||||
|
player.addClass('vjs-seek-buttons');
|
||||||
|
|
||||||
|
if (options.forward && options.forward > 0) {
|
||||||
|
player.controlBar.seekForward = player.controlBar.addChild('seekButton', {
|
||||||
|
direction: 'forward',
|
||||||
|
seconds: options.forward
|
||||||
|
}, options.forwardIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.back && options.back > 0) {
|
||||||
|
player.controlBar.seekBack = player.controlBar.addChild('seekButton', {
|
||||||
|
direction: 'back',
|
||||||
|
seconds: options.back
|
||||||
|
}, options.backIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin init if ready or on ready
|
||||||
|
*
|
||||||
|
* @function seekButtons
|
||||||
|
* @param {Object} [options={}]
|
||||||
|
* An object of options left to the plugin author to define.
|
||||||
|
*/
|
||||||
|
const seekButtons = function(options) {
|
||||||
|
this.ready(() => {
|
||||||
|
onPlayerReady(this, videojs.obj.merge(defaults, options));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Include the version number.
|
||||||
|
seekButtons.VERSION = VERSION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Button to seek forward/back
|
||||||
|
*
|
||||||
|
* @extends Button
|
||||||
|
* @class SeekButton
|
||||||
|
*/
|
||||||
|
class SeekButton extends Button {
|
||||||
|
/**
|
||||||
|
* Constructor for class
|
||||||
|
*
|
||||||
|
* @param {Player|Object} player The player
|
||||||
|
* @param {Object=} options Button options
|
||||||
|
* @param {string} options.direction back or forward
|
||||||
|
* @param {Int} options.seconds number of seconds to seek
|
||||||
|
*/
|
||||||
|
constructor(player, options) {
|
||||||
|
super(player, options);
|
||||||
|
this.$('.vjs-icon-placeholder').classList.add('vjs-icon-replay');
|
||||||
|
if (this.options_.direction === 'forward') {
|
||||||
|
this.controlText(this.localize('Seek forward {{seconds}} seconds')
|
||||||
|
.replace('{{seconds}}', this.options_.seconds));
|
||||||
|
} else if (this.options_.direction === 'back') {
|
||||||
|
this.controlText(this.localize('Seek back {{seconds}} seconds')
|
||||||
|
.replace('{{seconds}}', this.options_.seconds));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return button class names which include the seek amount.
|
||||||
|
*
|
||||||
|
* @return {string} css cass string
|
||||||
|
*/
|
||||||
|
buildCSSClass() {
|
||||||
|
/* Each button will have the classes:
|
||||||
|
`vjs-seek-button`
|
||||||
|
`skip-forward` or `skip-back`
|
||||||
|
`skip-n` where `n` is the number of seconds
|
||||||
|
So you could have a generic icon for "skip back" and a more
|
||||||
|
specific one for "skip back 30 seconds"
|
||||||
|
*/
|
||||||
|
return `vjs-seek-button skip-${this.options_.direction} ` +
|
||||||
|
`skip-${this.options_.seconds} ${super.buildCSSClass()}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Seek with the button's configured offset
|
||||||
|
*/
|
||||||
|
handleClick() {
|
||||||
|
const now = this.player_.currentTime();
|
||||||
|
|
||||||
|
if (this.options_.direction === 'forward') {
|
||||||
|
let duration = this.player_.duration();
|
||||||
|
|
||||||
|
if (this.player_.liveTracker && this.player_.liveTracker.isLive()) {
|
||||||
|
duration = this.player_.liveTracker.seekableEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.player_.currentTime(Math.min(now + this.options_.seconds, duration));
|
||||||
|
} else if (this.options_.direction === 'back') {
|
||||||
|
this.player_.currentTime(Math.max(0, now - this.options_.seconds));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
videojs.registerComponent('SeekButton', SeekButton);
|
||||||
|
|
||||||
|
// Register the plugin with video.js.
|
||||||
|
videojs.registerPlugin('seekButtons', seekButtons);
|
||||||
|
|
||||||
|
export default seekButtons;
|
122
node_modules/videojs-seek-buttons/test/plugin.test.js
generated
vendored
Normal file
122
node_modules/videojs-seek-buttons/test/plugin.test.js
generated
vendored
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
import document from 'global/document';
|
||||||
|
|
||||||
|
import QUnit from 'qunit';
|
||||||
|
import sinon from 'sinon';
|
||||||
|
import videojs from 'video.js';
|
||||||
|
|
||||||
|
import plugin from '../src/plugin';
|
||||||
|
|
||||||
|
const Player = videojs.getComponent('Player');
|
||||||
|
|
||||||
|
QUnit.test('the environment is sane', function(assert) {
|
||||||
|
assert.strictEqual(typeof Array.isArray, 'function', 'es5 exists');
|
||||||
|
assert.strictEqual(typeof sinon, 'object', 'sinon exists');
|
||||||
|
assert.strictEqual(typeof videojs, 'function', 'videojs exists');
|
||||||
|
assert.strictEqual(typeof plugin, 'function', 'plugin is a function');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.module('videojs-seek-buttons', {
|
||||||
|
|
||||||
|
beforeEach() {
|
||||||
|
|
||||||
|
// Mock the environment's timers because certain things - particularly
|
||||||
|
// player readiness - are asynchronous in video.js 5. This MUST come
|
||||||
|
// before any player is created; otherwise, timers could get created
|
||||||
|
// with the actual timer methods!
|
||||||
|
this.clock = sinon.useFakeTimers();
|
||||||
|
|
||||||
|
this.fixture = document.getElementById('qunit-fixture');
|
||||||
|
this.video = document.createElement('video');
|
||||||
|
this.fixture.appendChild(this.video);
|
||||||
|
this.player = videojs(this.video);
|
||||||
|
},
|
||||||
|
|
||||||
|
afterEach() {
|
||||||
|
this.player.dispose();
|
||||||
|
this.clock.restore();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('registers itself with video.js', function(assert) {
|
||||||
|
assert.expect(2);
|
||||||
|
|
||||||
|
assert.strictEqual(
|
||||||
|
typeof Player.prototype.seekButtons,
|
||||||
|
'function',
|
||||||
|
'videojs-seek-buttons plugin was registered'
|
||||||
|
);
|
||||||
|
|
||||||
|
this.player.seekButtons();
|
||||||
|
|
||||||
|
// Tick the clock forward enough to trigger the player to be "ready".
|
||||||
|
this.clock.tick(1);
|
||||||
|
|
||||||
|
assert.ok(
|
||||||
|
this.player.hasClass('vjs-seek-buttons'),
|
||||||
|
'the plugin adds a class to the player'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('adds buttons with classes', function(assert) {
|
||||||
|
this.player.seekButtons({
|
||||||
|
forward: 30,
|
||||||
|
back: 10
|
||||||
|
});
|
||||||
|
|
||||||
|
// Tick the clock forward enough to trigger the player to be "ready".
|
||||||
|
this.clock.tick(1);
|
||||||
|
|
||||||
|
assert.ok(
|
||||||
|
this.player.controlBar.seekBack,
|
||||||
|
'the plugin adds a back button to the player'
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.ok(
|
||||||
|
this.player.controlBar.seekForward,
|
||||||
|
'the plugin adds a forward button to the player'
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.ok(
|
||||||
|
this.player.controlBar.seekBack.hasClass('skip-10'),
|
||||||
|
'the plugin adds a seconds class to the button'
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.ok(
|
||||||
|
this.player.controlBar.seekBack.hasClass('skip-back'),
|
||||||
|
'the plugin adds a direction class to the button'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('calls currentTime with the correct time', function(assert) {
|
||||||
|
this.player.duration(100);
|
||||||
|
|
||||||
|
this.player.seekButtons({
|
||||||
|
forward: 30,
|
||||||
|
back: 10
|
||||||
|
});
|
||||||
|
|
||||||
|
// Tick the clock forward enough to trigger the player to be "ready".
|
||||||
|
this.clock.tick(1);
|
||||||
|
|
||||||
|
const time = this.player.currentTime();
|
||||||
|
|
||||||
|
const spy = sinon.spy(this.player, 'currentTime');
|
||||||
|
|
||||||
|
this.player.controlBar.seekForward.trigger('click');
|
||||||
|
|
||||||
|
assert.ok(
|
||||||
|
spy.withArgs(time + 30).calledOnce,
|
||||||
|
'forward button triggers seek 30 seconds'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Fake that the seek happened - it won't have as the test player has no source.
|
||||||
|
this.player.tech_.currentTime = () => 30;
|
||||||
|
|
||||||
|
this.player.controlBar.seekBack.trigger('click');
|
||||||
|
|
||||||
|
assert.ok(
|
||||||
|
spy.withArgs(20).calledOnce,
|
||||||
|
'back button triggers seek back 10 seconds'
|
||||||
|
);
|
||||||
|
|
||||||
|
});
|
24
package-lock.json
generated
24
package-lock.json
generated
|
@ -38,6 +38,7 @@
|
||||||
"videojs-font": "^4.1.0",
|
"videojs-font": "^4.1.0",
|
||||||
"videojs-ima": "^2.1.0",
|
"videojs-ima": "^2.1.0",
|
||||||
"videojs-landscape-fullscreen": "^11.1111.0",
|
"videojs-landscape-fullscreen": "^11.1111.0",
|
||||||
|
"videojs-seek-buttons": "^4.0.3",
|
||||||
"wow.js": "^1.2.2"
|
"wow.js": "^1.2.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -2062,6 +2063,21 @@
|
||||||
"video.js": "5.x || 6.x || 7.x || *"
|
"video.js": "5.x || 6.x || 7.x || *"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/videojs-seek-buttons": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/videojs-seek-buttons/-/videojs-seek-buttons-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-LcaskoqIshE1Dy/yqVPRlt2qSYzDq/vT9iqYxyy+crKdBW4zBXW743GVA7G7kX8BF8U9EGgQTajRJQGBQMtQaQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"global": "^4.4.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14",
|
||||||
|
"npm": ">=6"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"video.js": "^8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/videojs-vtt.js": {
|
"node_modules/videojs-vtt.js": {
|
||||||
"version": "0.15.4",
|
"version": "0.15.4",
|
||||||
"resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.15.4.tgz",
|
"resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.15.4.tgz",
|
||||||
|
@ -3688,6 +3704,14 @@
|
||||||
"global": "^4.4.0"
|
"global": "^4.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"videojs-seek-buttons": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/videojs-seek-buttons/-/videojs-seek-buttons-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-LcaskoqIshE1Dy/yqVPRlt2qSYzDq/vT9iqYxyy+crKdBW4zBXW743GVA7G7kX8BF8U9EGgQTajRJQGBQMtQaQ==",
|
||||||
|
"requires": {
|
||||||
|
"global": "^4.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"videojs-vtt.js": {
|
"videojs-vtt.js": {
|
||||||
"version": "0.15.4",
|
"version": "0.15.4",
|
||||||
"resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.15.4.tgz",
|
"resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.15.4.tgz",
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
"videojs-font": "^4.1.0",
|
"videojs-font": "^4.1.0",
|
||||||
"videojs-ima": "^2.1.0",
|
"videojs-ima": "^2.1.0",
|
||||||
"videojs-landscape-fullscreen": "^11.1111.0",
|
"videojs-landscape-fullscreen": "^11.1111.0",
|
||||||
|
"videojs-seek-buttons": "^4.0.3",
|
||||||
"wow.js": "^1.2.2"
|
"wow.js": "^1.2.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ class SeekButton extends PluginAbstract {
|
||||||
global $global;
|
global $global;
|
||||||
$css = "";
|
$css = "";
|
||||||
if (isVideoPlayerHasProgressBar() && !isMobile()) {
|
if (isVideoPlayerHasProgressBar() && !isMobile()) {
|
||||||
$css = '<link href="' .getURL('plugin/SeekButton/videojs-seek-buttons/videojs-seek-buttons.css') .'" rel="stylesheet" type="text/css"/>';
|
$css = '<link href="' .getURL('node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.css') .'" rel="stylesheet" type="text/css"/>';
|
||||||
$css .= '<link href="' .getURL('plugin/SeekButton/seek.css') .'" rel="stylesheet" type="text/css"/>';
|
$css .= '<link href="' .getURL('plugin/SeekButton/seek.css') .'" rel="stylesheet" type="text/css"/>';
|
||||||
$css .= '<style>.video-js .vjs-seek-button {font-size: 25px;width: 2em !important;}</style>';
|
$css .= '<style>.video-js .vjs-seek-button {font-size: 25px;width: 2em !important;}</style>';
|
||||||
if(isMobile()){
|
if(isMobile()){
|
||||||
|
@ -55,7 +55,7 @@ class SeekButton extends PluginAbstract {
|
||||||
$obj = $this->getDataObject();
|
$obj = $this->getDataObject();
|
||||||
$js = "";
|
$js = "";
|
||||||
if (isVideoPlayerHasProgressBar()) {
|
if (isVideoPlayerHasProgressBar()) {
|
||||||
$js .= '<script src="' .getURL('plugin/SeekButton/videojs-seek-buttons/videojs-seek-buttons.min.js') . '" type="text/javascript"></script>';
|
$js .= '<script src="' .getURL('node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.min.js') . '" type="text/javascript"></script>';
|
||||||
$js .= '<script>'
|
$js .= '<script>'
|
||||||
. 'var playerSeekForward = ' . $obj->forward . '; '
|
. 'var playerSeekForward = ' . $obj->forward . '; '
|
||||||
. 'var playerSeekBack = ' . $obj->back . ';'
|
. 'var playerSeekBack = ' . $obj->back . ';'
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue