diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json index f2a95e5ca8..7688d33896 100644 --- a/node_modules/.package-lock.json +++ b/node_modules/.package-lock.json @@ -2024,6 +2024,21 @@ "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": { "version": "0.15.4", "resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.15.4.tgz", diff --git a/node_modules/videojs-seek-buttons/CONTRIBUTING.md b/node_modules/videojs-seek-buttons/CONTRIBUTING.md new file mode 100644 index 0000000000..175d9765ed --- /dev/null +++ b/node_modules/videojs-seek-buttons/CONTRIBUTING.md @@ -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 diff --git a/node_modules/videojs-seek-buttons/LICENSE b/node_modules/videojs-seek-buttons/LICENSE new file mode 100644 index 0000000000..2f8716dd79 --- /dev/null +++ b/node_modules/videojs-seek-buttons/LICENSE @@ -0,0 +1,13 @@ +Copyright mister-ben + +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. diff --git a/node_modules/videojs-seek-buttons/README.md b/node_modules/videojs-seek-buttons/README.md new file mode 100644 index 0000000000..6b1741f135 --- /dev/null +++ b/node_modules/videojs-seek-buttons/README.md @@ -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 + + + + + +- [Installation](#installation) +- [Options](#options) + - [Control position](#control-position) +- [Usage](#usage) + - [` + + +``` + +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/ diff --git a/node_modules/videojs-seek-buttons/dist/lang/de.js b/node_modules/videojs-seek-buttons/dist/lang/de.js new file mode 100644 index 0000000000..bbd0c1da44 --- /dev/null +++ b/node_modules/videojs-seek-buttons/dist/lang/de.js @@ -0,0 +1,4 @@ +videojs.addLanguage('de', { + "Seek forward {{seconds}} seconds": "{{seconds}} Sekunden vorspulen", + "Seek back {{seconds}} seconds": "{{seconds}} Sekunden zurückspulen" +}); \ No newline at end of file diff --git a/node_modules/videojs-seek-buttons/dist/lang/en.js b/node_modules/videojs-seek-buttons/dist/lang/en.js new file mode 100644 index 0000000000..544dbd9a43 --- /dev/null +++ b/node_modules/videojs-seek-buttons/dist/lang/en.js @@ -0,0 +1,4 @@ +videojs.addLanguage('en', { + "Seek forward {{seconds}} seconds": "Seek forward {{seconds}} seconds", + "Seek back {{seconds}} seconds": "Seek back {{seconds}} seconds" +}); \ No newline at end of file diff --git a/node_modules/videojs-seek-buttons/dist/lang/fa.js b/node_modules/videojs-seek-buttons/dist/lang/fa.js new file mode 100644 index 0000000000..7060e9ed5c --- /dev/null +++ b/node_modules/videojs-seek-buttons/dist/lang/fa.js @@ -0,0 +1,4 @@ +videojs.addLanguage('fa', { + "Seek forward {{seconds}} seconds": "{{seconds}} ثانیه بعد", + "Seek back {{seconds}} seconds": "{{seconds}} ثانیه قبل" +}); \ No newline at end of file diff --git a/node_modules/videojs-seek-buttons/dist/lang/it.js b/node_modules/videojs-seek-buttons/dist/lang/it.js new file mode 100644 index 0000000000..f0ddbe0ddf --- /dev/null +++ b/node_modules/videojs-seek-buttons/dist/lang/it.js @@ -0,0 +1,4 @@ +videojs.addLanguage('it', { + "Seek forward {{seconds}} seconds": "Avanti di {{seconds}} secondi", + "Seek back {{seconds}} seconds": "Indietro di {{seconds}} secondi" +}); \ No newline at end of file diff --git a/node_modules/videojs-seek-buttons/dist/lang/ja.js b/node_modules/videojs-seek-buttons/dist/lang/ja.js new file mode 100644 index 0000000000..6b70bd0092 --- /dev/null +++ b/node_modules/videojs-seek-buttons/dist/lang/ja.js @@ -0,0 +1,4 @@ +videojs.addLanguage('ja', { + "Seek forward {{seconds}} seconds": "{{seconds}}秒進む", + "Seek back {{seconds}} seconds": "{{seconds}}秒戻る" +}); \ No newline at end of file diff --git a/node_modules/videojs-seek-buttons/dist/lang/lv.js b/node_modules/videojs-seek-buttons/dist/lang/lv.js new file mode 100644 index 0000000000..e61ad7279a --- /dev/null +++ b/node_modules/videojs-seek-buttons/dist/lang/lv.js @@ -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" +}); \ No newline at end of file diff --git a/node_modules/videojs-seek-buttons/dist/lang/nl.js b/node_modules/videojs-seek-buttons/dist/lang/nl.js new file mode 100644 index 0000000000..4ca96b3f33 --- /dev/null +++ b/node_modules/videojs-seek-buttons/dist/lang/nl.js @@ -0,0 +1,4 @@ +videojs.addLanguage('nl', { + "Seek forward {{seconds}} seconds": "{{seconds}} seconden vooruit", + "Seek back {{seconds}} seconds": "{{seconds}} seconden terug" +}); \ No newline at end of file diff --git a/node_modules/videojs-seek-buttons/dist/lang/ru.js b/node_modules/videojs-seek-buttons/dist/lang/ru.js new file mode 100644 index 0000000000..ce1d9af34e --- /dev/null +++ b/node_modules/videojs-seek-buttons/dist/lang/ru.js @@ -0,0 +1,4 @@ +videojs.addLanguage('ru', { + "Seek forward {{seconds}} seconds": "На {{seconds}} секунд вперед", + "Seek back {{seconds}} seconds": "На {{seconds}} секунд назад" +}); \ No newline at end of file diff --git a/node_modules/videojs-seek-buttons/dist/lang/zh-CN.js b/node_modules/videojs-seek-buttons/dist/lang/zh-CN.js new file mode 100644 index 0000000000..805855013f --- /dev/null +++ b/node_modules/videojs-seek-buttons/dist/lang/zh-CN.js @@ -0,0 +1,4 @@ +videojs.addLanguage('zh-CN', { + "Seek forward {{seconds}} seconds": "快进 {{seconds}} 秒", + "Seek back {{seconds}} seconds": "快退 {{seconds}} 秒" +}); \ No newline at end of file diff --git a/node_modules/videojs-seek-buttons/dist/lang/zh-TW.js b/node_modules/videojs-seek-buttons/dist/lang/zh-TW.js new file mode 100644 index 0000000000..106efe2a2d --- /dev/null +++ b/node_modules/videojs-seek-buttons/dist/lang/zh-TW.js @@ -0,0 +1,4 @@ +videojs.addLanguage('zh-TW', { + "Seek forward {{seconds}} seconds": "快轉 {{seconds}} 秒", + "Seek back {{seconds}} seconds": "倒轉 {{seconds}} 秒" +}); \ No newline at end of file diff --git a/node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.cjs.js b/node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.cjs.js new file mode 100644 index 0000000000..2d799e05e7 --- /dev/null +++ b/node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.cjs.js @@ -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; diff --git a/node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.css b/node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.css new file mode 100644 index 0000000000..06f35fe711 --- /dev/null +++ b/node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.css @@ -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)} \ No newline at end of file diff --git a/node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.es.js b/node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.es.js new file mode 100644 index 0000000000..27692fb10f --- /dev/null +++ b/node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.es.js @@ -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 }; diff --git a/node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.js b/node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.js new file mode 100644 index 0000000000..90338822b2 --- /dev/null +++ b/node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.js @@ -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; + +})); diff --git a/node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.min.js b/node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.min.js new file mode 100644 index 0000000000..83764e5ec3 --- /dev/null +++ b/node_modules/videojs-seek-buttons/dist/videojs-seek-buttons.min.js @@ -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})); diff --git a/node_modules/videojs-seek-buttons/index.html b/node_modules/videojs-seek-buttons/index.html new file mode 100644 index 0000000000..d5986f32e3 --- /dev/null +++ b/node_modules/videojs-seek-buttons/index.html @@ -0,0 +1,31 @@ + + + + + videojs-seek-buttons Demo + + + + + + + + + + + diff --git a/node_modules/videojs-seek-buttons/package.json b/node_modules/videojs-seek-buttons/package.json new file mode 100644 index 0000000000..d3f0ec5897 --- /dev/null +++ b/node_modules/videojs-seek-buttons/package.json @@ -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 ", + "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" +} diff --git a/node_modules/videojs-seek-buttons/scripts/karma.conf.js b/node_modules/videojs-seek-buttons/scripts/karma.conf.js new file mode 100644 index 0000000000..ac53a18fdb --- /dev/null +++ b/node_modules/videojs-seek-buttons/scripts/karma.conf.js @@ -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! +}; diff --git a/node_modules/videojs-seek-buttons/scripts/postcss.config.js b/node_modules/videojs-seek-buttons/scripts/postcss.config.js new file mode 100644 index 0000000000..d54b16f2f7 --- /dev/null +++ b/node_modules/videojs-seek-buttons/scripts/postcss.config.js @@ -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; +}; diff --git a/node_modules/videojs-seek-buttons/scripts/rollup.config.js b/node_modules/videojs-seek-buttons/scripts/rollup.config.js new file mode 100644 index 0000000000..ee2611c32d --- /dev/null +++ b/node_modules/videojs-seek-buttons/scripts/rollup.config.js @@ -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); diff --git a/node_modules/videojs-seek-buttons/src/plugin.css b/node_modules/videojs-seek-buttons/src/plugin.css new file mode 100644 index 0000000000..cfffcc9a88 --- /dev/null +++ b/node_modules/videojs-seek-buttons/src/plugin.css @@ -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); + } + } +} diff --git a/node_modules/videojs-seek-buttons/src/plugin.js b/node_modules/videojs-seek-buttons/src/plugin.js new file mode 100644 index 0000000000..abb3ea94b4 --- /dev/null +++ b/node_modules/videojs-seek-buttons/src/plugin.js @@ -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; diff --git a/node_modules/videojs-seek-buttons/test/plugin.test.js b/node_modules/videojs-seek-buttons/test/plugin.test.js new file mode 100644 index 0000000000..adb911ec9e --- /dev/null +++ b/node_modules/videojs-seek-buttons/test/plugin.test.js @@ -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' + ); + +}); diff --git a/package-lock.json b/package-lock.json index 4774c64964..6aaa713e3a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,6 +38,7 @@ "videojs-font": "^4.1.0", "videojs-ima": "^2.1.0", "videojs-landscape-fullscreen": "^11.1111.0", + "videojs-seek-buttons": "^4.0.3", "wow.js": "^1.2.2" } }, @@ -2062,6 +2063,21 @@ "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": { "version": "0.15.4", "resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.15.4.tgz", @@ -3688,6 +3704,14 @@ "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": { "version": "0.15.4", "resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.15.4.tgz", diff --git a/package.json b/package.json index b21d738434..1b29f58c70 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "videojs-font": "^4.1.0", "videojs-ima": "^2.1.0", "videojs-landscape-fullscreen": "^11.1111.0", + "videojs-seek-buttons": "^4.0.3", "wow.js": "^1.2.2" } } diff --git a/plugin/SeekButton/SeekButton.php b/plugin/SeekButton/SeekButton.php index 15c4a3f03b..a75ab2ea6c 100644 --- a/plugin/SeekButton/SeekButton.php +++ b/plugin/SeekButton/SeekButton.php @@ -39,7 +39,7 @@ class SeekButton extends PluginAbstract { global $global; $css = ""; if (isVideoPlayerHasProgressBar() && !isMobile()) { - $css = ''; + $css = ''; $css .= ''; $css .= ''; if(isMobile()){ @@ -55,7 +55,7 @@ class SeekButton extends PluginAbstract { $obj = $this->getDataObject(); $js = ""; if (isVideoPlayerHasProgressBar()) { - $js .= ''; + $js .= ''; $js .= '