diff options
| author | Lester Caine <lester@lsces.co.uk> | 2026-05-15 11:14:51 +0100 |
|---|---|---|
| committer | Lester Caine <lester@lsces.co.uk> | 2026-05-15 11:14:51 +0100 |
| commit | 38c22f210f393eeca49e6f2fb19136fa0f76c759 (patch) | |
| tree | 404833b583341e9d1a6a47851858847554920711 /javascript/videojs/src/js/control-bar | |
| parent | 29de8af87d6545347c6a76793f26905d132a1bc6 (diff) | |
| download | util-38c22f210f393eeca49e6f2fb19136fa0f76c759.tar.gz util-38c22f210f393eeca49e6f2fb19136fa0f76c759.tar.bz2 util-38c22f210f393eeca49e6f2fb19136fa0f76c759.zip | |
Remove legacy javascript that is currently not used in compact package set
Diffstat (limited to 'javascript/videojs/src/js/control-bar')
46 files changed, 0 insertions, 5434 deletions
diff --git a/javascript/videojs/src/js/control-bar/audio-track-controls/audio-track-button.js b/javascript/videojs/src/js/control-bar/audio-track-controls/audio-track-button.js deleted file mode 100644 index 80eb7f0..0000000 --- a/javascript/videojs/src/js/control-bar/audio-track-controls/audio-track-button.js +++ /dev/null @@ -1,85 +0,0 @@ -/** - * @file audio-track-button.js - */ -import TrackButton from '../track-button.js'; -import Component from '../../component.js'; -import AudioTrackMenuItem from './audio-track-menu-item.js'; - -/** - * The base class for buttons that toggle specific {@link AudioTrack} types. - * - * @extends TrackButton - */ -class AudioTrackButton extends TrackButton { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options={}] - * The key/value store of player options. - */ - constructor(player, options = {}) { - options.tracks = player.audioTracks(); - - super(player, options); - - this.setIcon('audio'); - } - - /** - * Builds the default DOM `className`. - * - * @return {string} - * The DOM `className` for this object. - */ - buildCSSClass() { - return `vjs-audio-button ${super.buildCSSClass()}`; - } - - buildWrapperCSSClass() { - return `vjs-audio-button ${super.buildWrapperCSSClass()}`; - } - - /** - * Create a menu item for each audio track - * - * @param {AudioTrackMenuItem[]} [items=[]] - * An array of existing menu items to use. - * - * @return {AudioTrackMenuItem[]} - * An array of menu items - */ - createItems(items = []) { - // if there's only one audio track, there no point in showing it - this.hideThreshold_ = 1; - - const tracks = this.player_.audioTracks(); - - for (let i = 0; i < tracks.length; i++) { - const track = tracks[i]; - - items.push(new AudioTrackMenuItem(this.player_, { - track, - // MenuItem is selectable - selectable: true, - // MenuItem is NOT multiSelectable (i.e. only one can be marked "selected" at a time) - multiSelectable: false - })); - } - - return items; - } -} - -/** - * The text that should display over the `AudioTrackButton`s controls. Added for localization. - * - * @type {string} - * @protected - */ -AudioTrackButton.prototype.controlText_ = 'Audio Track'; -Component.registerComponent('AudioTrackButton', AudioTrackButton); -export default AudioTrackButton; diff --git a/javascript/videojs/src/js/control-bar/audio-track-controls/audio-track-menu-item.js b/javascript/videojs/src/js/control-bar/audio-track-controls/audio-track-menu-item.js deleted file mode 100644 index be26f6b..0000000 --- a/javascript/videojs/src/js/control-bar/audio-track-controls/audio-track-menu-item.js +++ /dev/null @@ -1,118 +0,0 @@ -/** - * @file audio-track-menu-item.js - */ -import MenuItem from '../../menu/menu-item.js'; -import Component from '../../component.js'; -import * as Dom from '../../utils/dom.js'; - -/** @import Player from '../../player' */ - -/** - * An {@link AudioTrack} {@link MenuItem} - * - * @extends MenuItem - */ -class AudioTrackMenuItem extends MenuItem { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - */ - constructor(player, options) { - const track = options.track; - const tracks = player.audioTracks(); - - // Modify options for parent MenuItem class's init. - options.label = track.label || track.language || 'Unknown'; - options.selected = track.enabled; - - super(player, options); - - this.track = track; - - this.addClass(`vjs-${track.kind}-menu-item`); - - const changeHandler = (...args) => { - this.handleTracksChange.apply(this, args); - }; - - tracks.addEventListener('change', changeHandler); - this.on('dispose', () => { - tracks.removeEventListener('change', changeHandler); - }); - } - - createEl(type, props, attrs) { - const el = super.createEl(type, props, attrs); - const parentSpan = el.querySelector('.vjs-menu-item-text'); - - if (['main-desc', 'descriptions'].indexOf(this.options_.track.kind) >= 0) { - parentSpan.appendChild(Dom.createEl('span', { - className: 'vjs-icon-placeholder' - }, { - 'aria-hidden': true - })); - parentSpan.appendChild(Dom.createEl('span', { - className: 'vjs-control-text', - textContent: ' ' + this.localize('Descriptions') - })); - } - - return el; - } - - /** - * This gets called when an `AudioTrackMenuItem is "clicked". See {@link ClickableComponent} - * for more detailed information on what a click can be. - * - * @param {Event} [event] - * The `keydown`, `tap`, or `click` event that caused this function to be - * called. - * - * @listens tap - * @listens click - */ - handleClick(event) { - super.handleClick(event); - - // the audio track list will automatically toggle other tracks - // off for us. - this.track.enabled = true; - - // when native audio tracks are used, we want to make sure that other tracks are turned off - if (this.player_.tech_.featuresNativeAudioTracks) { - const tracks = this.player_.audioTracks(); - - for (let i = 0; i < tracks.length; i++) { - const track = tracks[i]; - - // skip the current track since we enabled it above - if (track === this.track) { - continue; - } - - track.enabled = track === this.track; - } - } - } - - /** - * Handle any {@link AudioTrack} change. - * - * @param {Event} [event] - * The {@link AudioTrackList#change} event that caused this to run. - * - * @listens AudioTrackList#change - */ - handleTracksChange(event) { - this.selected(this.track.enabled); - } -} - -Component.registerComponent('AudioTrackMenuItem', AudioTrackMenuItem); -export default AudioTrackMenuItem; diff --git a/javascript/videojs/src/js/control-bar/control-bar.js b/javascript/videojs/src/js/control-bar/control-bar.js deleted file mode 100644 index cc03fe9..0000000 --- a/javascript/videojs/src/js/control-bar/control-bar.js +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @file control-bar.js - */ -import Component from '../component.js'; - -// Required children -import './play-toggle.js'; -import './time-controls/current-time-display.js'; -import './time-controls/duration-display.js'; -import './time-controls/time-divider.js'; -import './time-controls/remaining-time-display.js'; -import './live-display.js'; -import './seek-to-live.js'; -import './progress-control/progress-control.js'; -import './picture-in-picture-toggle.js'; -import './fullscreen-toggle.js'; -import './volume-panel.js'; -import './skip-buttons/skip-forward.js'; -import './skip-buttons/skip-backward.js'; -import './text-track-controls/chapters-button.js'; -import './text-track-controls/descriptions-button.js'; -import './text-track-controls/subtitles-button.js'; -import './text-track-controls/captions-button.js'; -import './text-track-controls/subs-caps-button.js'; -import './audio-track-controls/audio-track-button.js'; -import './playback-rate-menu/playback-rate-menu-button.js'; -import './spacer-controls/custom-control-spacer.js'; - -/** - * Container of main controls. - * - * @extends Component - */ -class ControlBar extends Component { - - /** - * Create the `Component`'s DOM element - * - * @return {Element} - * The element that was created. - */ - createEl() { - return super.createEl('div', { - className: 'vjs-control-bar', - dir: 'ltr' - }); - } -} - -/** - * Default options for `ControlBar` - * - * @type {Object} - * @private - */ -ControlBar.prototype.options_ = { - children: [ - 'playToggle', - 'skipBackward', - 'skipForward', - 'volumePanel', - 'currentTimeDisplay', - 'timeDivider', - 'durationDisplay', - 'progressControl', - 'liveDisplay', - 'seekToLive', - 'remainingTimeDisplay', - 'customControlSpacer', - 'playbackRateMenuButton', - 'chaptersButton', - 'descriptionsButton', - 'subsCapsButton', - 'audioTrackButton', - 'pictureInPictureToggle', - 'fullscreenToggle' - ] -}; - -Component.registerComponent('ControlBar', ControlBar); -export default ControlBar; diff --git a/javascript/videojs/src/js/control-bar/fullscreen-toggle.js b/javascript/videojs/src/js/control-bar/fullscreen-toggle.js deleted file mode 100644 index 2c6271b..0000000 --- a/javascript/videojs/src/js/control-bar/fullscreen-toggle.js +++ /dev/null @@ -1,95 +0,0 @@ -/** - * @file fullscreen-toggle.js - */ -import Button from '../button.js'; -import Component from '../component.js'; -import document from 'global/document'; - -/** @import Player from './player' */ - -/** - * Toggle fullscreen video - * - * @extends Button - */ -class FullscreenToggle extends Button { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - */ - constructor(player, options) { - super(player, options); - this.setIcon('fullscreen-enter'); - this.on(player, 'fullscreenchange', (e) => this.handleFullscreenChange(e)); - - if (document[player.fsApi_.fullscreenEnabled] === false) { - this.disable(); - } - } - - /** - * Builds the default DOM `className`. - * - * @return {string} - * The DOM `className` for this object. - */ - buildCSSClass() { - return `vjs-fullscreen-control ${super.buildCSSClass()}`; - } - - /** - * Handles fullscreenchange on the player and change control text accordingly. - * - * @param {Event} [event] - * The {@link Player#fullscreenchange} event that caused this function to be - * called. - * - * @listens Player#fullscreenchange - */ - handleFullscreenChange(event) { - if (this.player_.isFullscreen()) { - this.controlText('Exit Fullscreen'); - this.setIcon('fullscreen-exit'); - } else { - this.controlText('Fullscreen'); - this.setIcon('fullscreen-enter'); - } - } - - /** - * This gets called when an `FullscreenToggle` is "clicked". See - * {@link ClickableComponent} for more detailed information on what a click can be. - * - * @param {Event} [event] - * The `keydown`, `tap`, or `click` event that caused this function to be - * called. - * - * @listens tap - * @listens click - */ - handleClick(event) { - if (!this.player_.isFullscreen()) { - this.player_.requestFullscreen(); - } else { - this.player_.exitFullscreen(); - } - } - -} - -/** - * The text that should display over the `FullscreenToggle`s controls. Added for localization. - * - * @type {string} - * @protected - */ -FullscreenToggle.prototype.controlText_ = 'Fullscreen'; - -Component.registerComponent('FullscreenToggle', FullscreenToggle); -export default FullscreenToggle; diff --git a/javascript/videojs/src/js/control-bar/live-display.js b/javascript/videojs/src/js/control-bar/live-display.js deleted file mode 100644 index d62c4cc..0000000 --- a/javascript/videojs/src/js/control-bar/live-display.js +++ /dev/null @@ -1,88 +0,0 @@ -/** - * @file live-display.js - */ -import Component from '../component'; -import * as Dom from '../utils/dom.js'; -import document from 'global/document'; - -/** @import Player from './player' */ - -// TODO - Future make it click to snap to live - -/** - * Displays the live indicator when duration is Infinity. - * - * @extends Component - */ -class LiveDisplay extends Component { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - */ - constructor(player, options) { - super(player, options); - - this.updateShowing(); - this.on(this.player(), 'durationchange', (e) => this.updateShowing(e)); - } - - /** - * Create the `Component`'s DOM element - * - * @return {Element} - * The element that was created. - */ - createEl() { - const el = super.createEl('div', { - className: 'vjs-live-control vjs-control' - }); - - this.contentEl_ = Dom.createEl('div', { - className: 'vjs-live-display' - }, { - 'aria-live': 'off' - }); - - this.contentEl_.appendChild(Dom.createEl('span', { - className: 'vjs-control-text', - textContent: `${this.localize('Stream Type')}\u00a0` - })); - this.contentEl_.appendChild(document.createTextNode(this.localize('LIVE'))); - - el.appendChild(this.contentEl_); - return el; - } - - dispose() { - this.contentEl_ = null; - - super.dispose(); - } - - /** - * Check the duration to see if the LiveDisplay should be showing or not. Then show/hide - * it accordingly - * - * @param {Event} [event] - * The {@link Player#durationchange} event that caused this function to run. - * - * @listens Player#durationchange - */ - updateShowing(event) { - if (this.player().duration() === Infinity) { - this.show(); - } else { - this.hide(); - } - } - -} - -Component.registerComponent('LiveDisplay', LiveDisplay); -export default LiveDisplay; diff --git a/javascript/videojs/src/js/control-bar/mute-toggle.js b/javascript/videojs/src/js/control-bar/mute-toggle.js deleted file mode 100644 index 091a739..0000000 --- a/javascript/videojs/src/js/control-bar/mute-toggle.js +++ /dev/null @@ -1,154 +0,0 @@ -/** - * @file mute-toggle.js - */ -import Button from '../button'; -import Component from '../component'; -import * as Dom from '../utils/dom.js'; -import checkMuteSupport from './volume-control/check-mute-support'; -import * as browser from '../utils/browser.js'; - -/** @import Player from './player' */ - -/** - * A button component for muting the audio. - * - * @extends Button - */ -class MuteToggle extends Button { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - */ - constructor(player, options) { - super(player, options); - - // hide this control if volume support is missing - checkMuteSupport(this, player); - - this.on(player, ['loadstart', 'volumechange'], (e) => this.update(e)); - } - - /** - * Builds the default DOM `className`. - * - * @return {string} - * The DOM `className` for this object. - */ - buildCSSClass() { - return `vjs-mute-control ${super.buildCSSClass()}`; - } - - /** - * This gets called when an `MuteToggle` is "clicked". See - * {@link ClickableComponent} for more detailed information on what a click can be. - * - * @param {Event} [event] - * The `keydown`, `tap`, or `click` event that caused this function to be - * called. - * - * @listens tap - * @listens click - */ - handleClick(event) { - const vol = this.player_.volume(); - const lastVolume = this.player_.lastVolume_(); - - if (vol === 0) { - const volumeToSet = lastVolume < 0.1 ? 0.1 : lastVolume; - - this.player_.volume(volumeToSet); - this.player_.muted(false); - } else { - this.player_.muted(this.player_.muted() ? false : true); - } - } - - /** - * Update the `MuteToggle` button based on the state of `volume` and `muted` - * on the player. - * - * @param {Event} [event] - * The {@link Player#loadstart} event if this function was called - * through an event. - * - * @listens Player#loadstart - * @listens Player#volumechange - */ - update(event) { - this.updateIcon_(); - this.updateControlText_(); - } - - /** - * Update the appearance of the `MuteToggle` icon. - * - * Possible states (given `level` variable below): - * - 0: crossed out - * - 1: zero bars of volume - * - 2: one bar of volume - * - 3: two bars of volume - * - * @private - */ - updateIcon_() { - const vol = this.player_.volume(); - let level = 3; - - this.setIcon('volume-high'); - - // in iOS when a player is loaded with muted attribute - // and volume is changed with a native mute button - // we want to make sure muted state is updated - if (browser.IS_IOS && this.player_.tech_ && this.player_.tech_.el_) { - this.player_.muted(this.player_.tech_.el_.muted); - } - - if (vol === 0 || this.player_.muted()) { - this.setIcon('volume-mute'); - level = 0; - } else if (vol < 0.33) { - this.setIcon('volume-low'); - level = 1; - } else if (vol < 0.67) { - this.setIcon('volume-medium'); - level = 2; - } - - Dom.removeClass(this.el_, [0, 1, 2, 3].reduce((str, i) => str + `${i ? ' ' : ''}vjs-vol-${i}`, '')); - Dom.addClass(this.el_, `vjs-vol-${level}`); - } - - /** - * If `muted` has changed on the player, update the control text - * (`title` attribute on `vjs-mute-control` element and content of - * `vjs-control-text` element). - * - * @private - */ - updateControlText_() { - const soundOff = this.player_.muted() || this.player_.volume() === 0; - const text = soundOff ? 'Unmute' : 'Mute'; - - if (this.controlText() !== text) { - this.controlText(text); - } - } - -} - -/** - * The text that should display over the `MuteToggle`s controls. Added for localization. - * - * @type {string} - * @protected - */ -MuteToggle.prototype.controlText_ = 'Mute'; - -Component.registerComponent('MuteToggle', MuteToggle); -export default MuteToggle; diff --git a/javascript/videojs/src/js/control-bar/picture-in-picture-toggle.js b/javascript/videojs/src/js/control-bar/picture-in-picture-toggle.js deleted file mode 100644 index 9a37643..0000000 --- a/javascript/videojs/src/js/control-bar/picture-in-picture-toggle.js +++ /dev/null @@ -1,159 +0,0 @@ -/** - * @file picture-in-picture-toggle.js - */ -import Button from '../button.js'; -import Component from '../component.js'; -import document from 'global/document'; -import window from 'global/window'; - -/** @import Player from './player' */ - -/** - * Toggle Picture-in-Picture mode - * - * @extends Button - */ -class PictureInPictureToggle extends Button { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - * - * @listens Player#enterpictureinpicture - * @listens Player#leavepictureinpicture - */ - constructor(player, options) { - super(player, options); - - this.setIcon('picture-in-picture-enter'); - - this.on(player, ['enterpictureinpicture', 'leavepictureinpicture'], (e) => this.handlePictureInPictureChange(e)); - this.on(player, ['disablepictureinpicturechanged', 'loadedmetadata'], (e) => this.handlePictureInPictureEnabledChange(e)); - this.on(player, ['loadedmetadata', 'audioonlymodechange', 'audiopostermodechange'], () => this.handlePictureInPictureAudioModeChange()); - - // TODO: Deactivate button on player emptied event. - this.disable(); - } - - /** - * Builds the default DOM `className`. - * - * @return {string} - * The DOM `className` for this object. - */ - buildCSSClass() { - return `vjs-picture-in-picture-control vjs-hidden ${super.buildCSSClass()}`; - } - - /** - * Displays or hides the button depending on the audio mode detection. - * Exits picture-in-picture if it is enabled when switching to audio mode. - */ - handlePictureInPictureAudioModeChange() { - // This audio detection will not detect HLS or DASH audio-only streams because there was no reliable way to detect them at the time - const isSourceAudio = this.player_.currentType().substring(0, 5) === 'audio'; - const isAudioMode = - isSourceAudio || this.player_.audioPosterMode() || this.player_.audioOnlyMode(); - - if (!isAudioMode) { - this.show(); - - return; - } - - if (this.player_.isInPictureInPicture()) { - this.player_.exitPictureInPicture(); - } - - this.hide(); - } - - /** - * Enables or disables button based on availability of a Picture-In-Picture mode. - * - * Enabled if - * - `player.options().enableDocumentPictureInPicture` is true and - * window.documentPictureInPicture is available; or - * - `player.disablePictureInPicture()` is false and - * element.requestPictureInPicture is available - */ - handlePictureInPictureEnabledChange() { - if ( - (document.pictureInPictureEnabled && this.player_.disablePictureInPicture() === false) || - (this.player_.options_.enableDocumentPictureInPicture && 'documentPictureInPicture' in window) - ) { - this.enable(); - } else { - this.disable(); - } - } - - /** - * Handles enterpictureinpicture and leavepictureinpicture on the player and change control text accordingly. - * - * @param {Event} [event] - * The {@link Player#enterpictureinpicture} or {@link Player#leavepictureinpicture} event that caused this function to be - * called. - * - * @listens Player#enterpictureinpicture - * @listens Player#leavepictureinpicture - */ - handlePictureInPictureChange(event) { - if (this.player_.isInPictureInPicture()) { - this.setIcon('picture-in-picture-exit'); - this.controlText('Exit Picture-in-Picture'); - } else { - this.setIcon('picture-in-picture-enter'); - this.controlText('Picture-in-Picture'); - } - this.handlePictureInPictureEnabledChange(); - } - - /** - * This gets called when an `PictureInPictureToggle` is "clicked". See - * {@link ClickableComponent} for more detailed information on what a click can be. - * - * @param {Event} [event] - * The `keydown`, `tap`, or `click` event that caused this function to be - * called. - * - * @listens tap - * @listens click - */ - handleClick(event) { - if (!this.player_.isInPictureInPicture()) { - this.player_.requestPictureInPicture(); - } else { - this.player_.exitPictureInPicture(); - } - } - - /** - * Show the `Component`s element if it is hidden by removing the - * 'vjs-hidden' class name from it only in browsers that support the Picture-in-Picture API. - */ - show() { - // Does not allow to display the pictureInPictureToggle in browsers that do not support the Picture-in-Picture API, e.g. Firefox. - if (typeof document.exitPictureInPicture !== 'function') { - return; - } - - super.show(); - } -} - -/** - * The text that should display over the `PictureInPictureToggle`s controls. Added for localization. - * - * @type {string} - * @protected - */ -PictureInPictureToggle.prototype.controlText_ = 'Picture-in-Picture'; - -Component.registerComponent('PictureInPictureToggle', PictureInPictureToggle); -export default PictureInPictureToggle; diff --git a/javascript/videojs/src/js/control-bar/play-toggle.js b/javascript/videojs/src/js/control-bar/play-toggle.js deleted file mode 100644 index 424f579..0000000 --- a/javascript/videojs/src/js/control-bar/play-toggle.js +++ /dev/null @@ -1,151 +0,0 @@ -/** - * @file play-toggle.js - */ -import Button from '../button.js'; -import Component from '../component.js'; -import {silencePromise} from '../utils/promise'; - -/** @import Player from './player' */ - -/** - * Button to toggle between play and pause. - * - * @extends Button - */ -class PlayToggle extends Button { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options={}] - * The key/value store of player options. - */ - constructor(player, options = {}) { - super(player, options); - - // show or hide replay icon - options.replay = options.replay === undefined || options.replay; - - this.setIcon('play'); - - this.on(player, 'play', (e) => this.handlePlay(e)); - this.on(player, 'pause', (e) => this.handlePause(e)); - - if (options.replay) { - this.on(player, 'ended', (e) => this.handleEnded(e)); - } - } - - /** - * Builds the default DOM `className`. - * - * @return {string} - * The DOM `className` for this object. - */ - buildCSSClass() { - return `vjs-play-control ${super.buildCSSClass()}`; - } - - /** - * This gets called when an `PlayToggle` is "clicked". See - * {@link ClickableComponent} for more detailed information on what a click can be. - * - * @param {Event} [event] - * The `keydown`, `tap`, or `click` event that caused this function to be - * called. - * - * @listens tap - * @listens click - */ - handleClick(event) { - if (this.player_.paused()) { - silencePromise(this.player_.play()); - } else { - this.player_.pause(); - } - } - - /** - * This gets called once after the video has ended and the user seeks so that - * we can change the replay button back to a play button. - * - * @param {Event} [event] - * The event that caused this function to run. - * - * @listens Player#seeked - */ - handleSeeked(event) { - this.removeClass('vjs-ended'); - - if (this.player_.paused()) { - this.handlePause(event); - } else { - this.handlePlay(event); - } - } - - /** - * Add the vjs-playing class to the element so it can change appearance. - * - * @param {Event} [event] - * The event that caused this function to run. - * - * @listens Player#play - */ - handlePlay(event) { - this.removeClass('vjs-ended', 'vjs-paused'); - this.addClass('vjs-playing'); - // change the button text to "Pause" - this.setIcon('pause'); - this.controlText('Pause'); - } - - /** - * Add the vjs-paused class to the element so it can change appearance. - * - * @param {Event} [event] - * The event that caused this function to run. - * - * @listens Player#pause - */ - handlePause(event) { - this.removeClass('vjs-playing'); - this.addClass('vjs-paused'); - // change the button text to "Play" - this.setIcon('play'); - this.controlText('Play'); - } - - /** - * Add the vjs-ended class to the element so it can change appearance - * - * @param {Event} [event] - * The event that caused this function to run. - * - * @listens Player#ended - */ - handleEnded(event) { - this.removeClass('vjs-playing'); - this.addClass('vjs-ended'); - // change the button text to "Replay" - this.setIcon('replay'); - this.controlText('Replay'); - - // on the next seek remove the replay button - this.one(this.player_, 'seeked', (e) => this.handleSeeked(e)); - } -} - -/** - * The text that should display over the `PlayToggle`s controls. Added for localization. - * - * @type {string} - * @protected - */ -PlayToggle.prototype.controlText_ = 'Play'; - -Component.registerComponent('PlayToggle', PlayToggle); -export default PlayToggle; diff --git a/javascript/videojs/src/js/control-bar/playback-rate-menu/playback-rate-menu-button.js b/javascript/videojs/src/js/control-bar/playback-rate-menu/playback-rate-menu-button.js deleted file mode 100644 index 147f040..0000000 --- a/javascript/videojs/src/js/control-bar/playback-rate-menu/playback-rate-menu-button.js +++ /dev/null @@ -1,176 +0,0 @@ -/** - * @file playback-rate-menu-button.js - */ -import MenuButton from '../../menu/menu-button.js'; -import PlaybackRateMenuItem from './playback-rate-menu-item.js'; -import Component from '../../component.js'; -import * as Dom from '../../utils/dom.js'; - -/** @import Player from '../../player' */ - -/** - * The component for controlling the playback rate. - * - * @extends MenuButton - */ -class PlaybackRateMenuButton extends MenuButton { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - */ - constructor(player, options) { - super(player, options); - - this.menuButton_.el_.setAttribute('aria-describedby', this.labelElId_); - - this.updateVisibility(); - this.updateLabel(); - - this.on(player, 'loadstart', (e) => this.updateVisibility(e)); - this.on(player, 'ratechange', (e) => this.updateLabel(e)); - this.on(player, 'playbackrateschange', (e) => this.handlePlaybackRateschange(e)); - } - - /** - * Create the `Component`'s DOM element - * - * @return {Element} - * The element that was created. - */ - createEl() { - const el = super.createEl(); - - this.labelElId_ = 'vjs-playback-rate-value-label-' + this.id_; - - this.labelEl_ = Dom.createEl('div', { - className: 'vjs-playback-rate-value', - id: this.labelElId_, - textContent: '1x' - }); - - el.appendChild(this.labelEl_); - - return el; - } - - dispose() { - this.labelEl_ = null; - - super.dispose(); - } - - /** - * Builds the default DOM `className`. - * - * @return {string} - * The DOM `className` for this object. - */ - buildCSSClass() { - return `vjs-playback-rate ${super.buildCSSClass()}`; - } - - buildWrapperCSSClass() { - return `vjs-playback-rate ${super.buildWrapperCSSClass()}`; - } - - /** - * Create the list of menu items. Specific to each subclass. - * - */ - createItems() { - const rates = this.playbackRates(); - const items = []; - - for (let i = rates.length - 1; i >= 0; i--) { - items.push(new PlaybackRateMenuItem(this.player(), {rate: rates[i] + 'x'})); - } - - return items; - } - - /** - * On playbackrateschange, update the menu to account for the new items. - * - * @listens Player#playbackrateschange - */ - handlePlaybackRateschange(event) { - this.update(); - } - - /** - * Get possible playback rates - * - * @return {Array} - * All possible playback rates - */ - playbackRates() { - const player = this.player(); - - return (player.playbackRates && player.playbackRates()) || []; - } - - /** - * Get whether playback rates is supported by the tech - * and an array of playback rates exists - * - * @return {boolean} - * Whether changing playback rate is supported - */ - playbackRateSupported() { - return this.player().tech_ && - this.player().tech_.featuresPlaybackRate && - this.playbackRates() && - this.playbackRates().length > 0 - ; - } - - /** - * Hide playback rate controls when they're no playback rate options to select - * - * @param {Event} [event] - * The event that caused this function to run. - * - * @listens Player#loadstart - */ - updateVisibility(event) { - if (this.playbackRateSupported()) { - this.removeClass('vjs-hidden'); - } else { - this.addClass('vjs-hidden'); - } - } - - /** - * Update button label when rate changed - * - * @param {Event} [event] - * The event that caused this function to run. - * - * @listens Player#ratechange - */ - updateLabel(event) { - if (this.playbackRateSupported()) { - this.labelEl_.textContent = this.player().playbackRate() + 'x'; - } - } - -} - -/** - * The text that should display over the `PlaybackRateMenuButton`s controls. - * - * Added for localization. - * - * @type {string} - * @protected - */ -PlaybackRateMenuButton.prototype.controlText_ = 'Playback Rate'; - -Component.registerComponent('PlaybackRateMenuButton', PlaybackRateMenuButton); -export default PlaybackRateMenuButton; diff --git a/javascript/videojs/src/js/control-bar/playback-rate-menu/playback-rate-menu-item.js b/javascript/videojs/src/js/control-bar/playback-rate-menu/playback-rate-menu-item.js deleted file mode 100644 index b0b145a..0000000 --- a/javascript/videojs/src/js/control-bar/playback-rate-menu/playback-rate-menu-item.js +++ /dev/null @@ -1,82 +0,0 @@ -/** - * @file playback-rate-menu-item.js - */ -import MenuItem from '../../menu/menu-item.js'; -import Component from '../../component.js'; - -/** @import Player from '../../player' */ - -/** - * The specific menu item type for selecting a playback rate. - * - * @extends MenuItem - */ -class PlaybackRateMenuItem extends MenuItem { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - */ - constructor(player, options) { - const label = options.rate; - const rate = parseFloat(label, 10); - - // Modify options for parent MenuItem class's init. - options.label = label; - options.selected = rate === player.playbackRate(); - options.selectable = true; - options.multiSelectable = false; - - super(player, options); - - this.label = label; - this.rate = rate; - - this.on(player, 'ratechange', (e) => this.update(e)); - } - - /** - * This gets called when an `PlaybackRateMenuItem` is "clicked". See - * {@link ClickableComponent} for more detailed information on what a click can be. - * - * @param {Event} [event] - * The `keydown`, `tap`, or `click` event that caused this function to be - * called. - * - * @listens tap - * @listens click - */ - handleClick(event) { - super.handleClick(); - this.player().playbackRate(this.rate); - } - - /** - * Update the PlaybackRateMenuItem when the playbackrate changes. - * - * @param {Event} [event] - * The `ratechange` event that caused this function to run. - * - * @listens Player#ratechange - */ - update(event) { - this.selected(this.player().playbackRate() === this.rate); - } - -} - -/** - * The text that should display over the `PlaybackRateMenuItem`s controls. Added for localization. - * - * @type {string} - * @private - */ -PlaybackRateMenuItem.prototype.contentElType = 'button'; - -Component.registerComponent('PlaybackRateMenuItem', PlaybackRateMenuItem); -export default PlaybackRateMenuItem; diff --git a/javascript/videojs/src/js/control-bar/progress-control/load-progress-bar.js b/javascript/videojs/src/js/control-bar/progress-control/load-progress-bar.js deleted file mode 100644 index 0da4ff2..0000000 --- a/javascript/videojs/src/js/control-bar/progress-control/load-progress-bar.js +++ /dev/null @@ -1,127 +0,0 @@ -/** - * @file load-progress-bar.js - */ -import Component from '../../component.js'; -import * as Dom from '../../utils/dom.js'; -import {clamp} from '../../utils/num'; -import document from 'global/document'; - -/** @import Player from '../../player' */ - -// get the percent width of a time compared to the total end -const percentify = (time, end) => clamp((time / end) * 100, 0, 100).toFixed(2) + '%'; - -/** - * Shows loading progress - * - * @extends Component - */ -class LoadProgressBar extends Component { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - */ - constructor(player, options) { - super(player, options); - this.partEls_ = []; - this.on(player, 'progress', (e) => this.update(e)); - } - - /** - * Create the `Component`'s DOM element - * - * @return {Element} - * The element that was created. - */ - createEl() { - const el = super.createEl('div', {className: 'vjs-load-progress'}); - const wrapper = Dom.createEl('span', {className: 'vjs-control-text'}); - const loadedText = Dom.createEl('span', {textContent: this.localize('Loaded')}); - const separator = document.createTextNode(': '); - - this.percentageEl_ = Dom.createEl('span', { - className: 'vjs-control-text-loaded-percentage', - textContent: '0%' - }); - - el.appendChild(wrapper); - wrapper.appendChild(loadedText); - wrapper.appendChild(separator); - wrapper.appendChild(this.percentageEl_); - - return el; - } - - dispose() { - this.partEls_ = null; - this.percentageEl_ = null; - - super.dispose(); - } - - /** - * Update progress bar - * - * @param {Event} [event] - * The `progress` event that caused this function to run. - * - * @listens Player#progress - */ - update(event) { - this.requestNamedAnimationFrame('LoadProgressBar#update', () => { - const liveTracker = this.player_.liveTracker; - const buffered = this.player_.buffered(); - const duration = (liveTracker && liveTracker.isLive()) ? liveTracker.seekableEnd() : this.player_.duration(); - const bufferedEnd = this.player_.bufferedEnd(); - const children = this.partEls_; - const percent = percentify(bufferedEnd, duration); - - if (this.percent_ !== percent) { - // update the width of the progress bar - this.el_.style.width = percent; - // update the control-text - Dom.textContent(this.percentageEl_, percent); - this.percent_ = percent; - } - - // add child elements to represent the individual buffered time ranges - for (let i = 0; i < buffered.length; i++) { - const start = buffered.start(i); - const end = buffered.end(i); - let part = children[i]; - - if (!part) { - part = this.el_.appendChild(Dom.createEl()); - children[i] = part; - } - - // only update if changed - if (part.dataset.start === start && part.dataset.end === end) { - continue; - } - - part.dataset.start = start; - part.dataset.end = end; - - // set the percent based on the width of the progress bar (bufferedEnd) - part.style.left = percentify(start, bufferedEnd); - part.style.width = percentify(end - start, bufferedEnd); - } - - // remove unused buffered range elements - for (let i = children.length; i > buffered.length; i--) { - this.el_.removeChild(children[i - 1]); - } - children.length = buffered.length; - }); - } -} - -Component.registerComponent('LoadProgressBar', LoadProgressBar); -export default LoadProgressBar; diff --git a/javascript/videojs/src/js/control-bar/progress-control/mouse-time-display.js b/javascript/videojs/src/js/control-bar/progress-control/mouse-time-display.js deleted file mode 100644 index f14bde1..0000000 --- a/javascript/videojs/src/js/control-bar/progress-control/mouse-time-display.js +++ /dev/null @@ -1,80 +0,0 @@ -/** - * @file mouse-time-display.js - */ -import Component from '../../component.js'; -import * as Fn from '../../utils/fn.js'; - -/** @import Player from '../../player' */ - -import './time-tooltip'; - -/** - * The {@link MouseTimeDisplay} component tracks mouse movement over the - * {@link ProgressControl}. It displays an indicator and a {@link TimeTooltip} - * indicating the time which is represented by a given point in the - * {@link ProgressControl}. - * - * @extends Component - */ -class MouseTimeDisplay extends Component { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The {@link Player} that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - */ - constructor(player, options) { - super(player, options); - this.update = Fn.throttle(Fn.bind_(this, this.update), Fn.UPDATE_REFRESH_INTERVAL); - } - - /** - * Create the DOM element for this class. - * - * @return {Element} - * The element that was created. - */ - createEl() { - return super.createEl('div', { - className: 'vjs-mouse-display' - }); - } - - /** - * Enqueues updates to its own DOM as well as the DOM of its - * {@link TimeTooltip} child. - * - * @param {Object} seekBarRect - * The `ClientRect` for the {@link SeekBar} element. - * - * @param {number} seekBarPoint - * A number from 0 to 1, representing a horizontal reference point - * from the left edge of the {@link SeekBar} - */ - update(seekBarRect, seekBarPoint) { - const time = seekBarPoint * this.player_.duration(); - - this.getChild('timeTooltip').updateTime(seekBarRect, seekBarPoint, time, () => { - this.el_.style.left = `${seekBarRect.width * seekBarPoint}px`; - }); - } -} - -/** - * Default options for `MouseTimeDisplay` - * - * @type {Object} - * @private - */ -MouseTimeDisplay.prototype.options_ = { - children: [ - 'timeTooltip' - ] -}; - -Component.registerComponent('MouseTimeDisplay', MouseTimeDisplay); -export default MouseTimeDisplay; diff --git a/javascript/videojs/src/js/control-bar/progress-control/play-progress-bar.js b/javascript/videojs/src/js/control-bar/progress-control/play-progress-bar.js deleted file mode 100644 index cc22e99..0000000 --- a/javascript/videojs/src/js/control-bar/progress-control/play-progress-bar.js +++ /dev/null @@ -1,99 +0,0 @@ -/** - * @file play-progress-bar.js - */ -import Component from '../../component.js'; -import {IS_IOS, IS_ANDROID} from '../../utils/browser.js'; -import * as Fn from '../../utils/fn.js'; - -/** @import Player from '../../player' */ - -import './time-tooltip'; - -/** - * Used by {@link SeekBar} to display media playback progress as part of the - * {@link ProgressControl}. - * - * @extends Component - */ -class PlayProgressBar extends Component { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The {@link Player} that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - */ - constructor(player, options) { - super(player, options); - this.setIcon('circle'); - this.update = Fn.throttle(Fn.bind_(this, this.update), Fn.UPDATE_REFRESH_INTERVAL); - } - - /** - * Create the the DOM element for this class. - * - * @return {Element} - * The element that was created. - */ - createEl() { - return super.createEl('div', { - className: 'vjs-play-progress vjs-slider-bar' - }, { - 'aria-hidden': 'true' - }); - } - - /** - * Enqueues updates to its own DOM as well as the DOM of its - * {@link TimeTooltip} child. - * - * @param {Object} seekBarRect - * The `ClientRect` for the {@link SeekBar} element. - * - * @param {number} seekBarPoint - * A number from 0 to 1, representing a horizontal reference point - * from the left edge of the {@link SeekBar} - * - * @param {Event} [event] - * The `timeupdate` event that caused this function to run. - */ - update(seekBarRect, seekBarPoint, event) { - const timeTooltip = this.getChild('timeTooltip'); - - if (!timeTooltip) { - return; - } - - // Combined logic: if an event with a valid pendingSeekTime getter exists, use it. - const time = (event && - event.target && - typeof event.target.pendingSeekTime === 'function') ? - event.target.pendingSeekTime() : - (this.player_.scrubbing() ? - this.player_.getCache().currentTime : - this.player_.currentTime()); - - timeTooltip.updateTime(seekBarRect, seekBarPoint, time); - } -} - -/** - * Default options for {@link PlayProgressBar}. - * - * @type {Object} - * @private - */ -PlayProgressBar.prototype.options_ = { - children: [] -}; - -// Time tooltips should not be added to a player on mobile devices -if (!IS_IOS && !IS_ANDROID) { - PlayProgressBar.prototype.options_.children.push('timeTooltip'); -} - -Component.registerComponent('PlayProgressBar', PlayProgressBar); -export default PlayProgressBar; diff --git a/javascript/videojs/src/js/control-bar/progress-control/progress-control.js b/javascript/videojs/src/js/control-bar/progress-control/progress-control.js deleted file mode 100644 index edb39d6..0000000 --- a/javascript/videojs/src/js/control-bar/progress-control/progress-control.js +++ /dev/null @@ -1,249 +0,0 @@ -/** - * @file progress-control.js - */ -import Component from '../../component.js'; -import * as Dom from '../../utils/dom.js'; -import {clamp} from '../../utils/num.js'; -import {bind_, throttle, UPDATE_REFRESH_INTERVAL} from '../../utils/fn.js'; -import {silencePromise} from '../../utils/promise'; - -/** @import Player from '../../player' */ - -import './seek-bar.js'; - -/** - * The Progress Control component contains the seek bar, load progress, - * and play progress. - * - * @extends Component - */ -class ProgressControl extends Component { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - */ - constructor(player, options) { - super(player, options); - this.handleMouseMove = throttle(bind_(this, this.handleMouseMove), UPDATE_REFRESH_INTERVAL); - this.throttledHandleMouseSeek = throttle(bind_(this, this.handleMouseSeek), UPDATE_REFRESH_INTERVAL); - this.handleMouseUpHandler_ = (e) => this.handleMouseUp(e); - this.handleMouseDownHandler_ = (e) => this.handleMouseDown(e); - - this.enable(); - } - - /** - * Create the `Component`'s DOM element - * - * @return {Element} - * The element that was created. - */ - createEl() { - return super.createEl('div', { - className: 'vjs-progress-control vjs-control' - }); - } - - /** - * When the mouse moves over the `ProgressControl`, the pointer position - * gets passed down to the `MouseTimeDisplay` component. - * - * @param {Event} event - * The `mousemove` event that caused this function to run. - * - * @listen mousemove - */ - handleMouseMove(event) { - const seekBar = this.getChild('seekBar'); - - if (!seekBar) { - return; - } - - const playProgressBar = seekBar.getChild('playProgressBar'); - const mouseTimeDisplay = seekBar.getChild('mouseTimeDisplay'); - - if (!playProgressBar && !mouseTimeDisplay) { - return; - } - - const seekBarEl = seekBar.el(); - const seekBarRect = Dom.findPosition(seekBarEl); - let seekBarPoint = Dom.getPointerPosition(seekBarEl, event).x; - - // The default skin has a gap on either side of the `SeekBar`. This means - // that it's possible to trigger this behavior outside the boundaries of - // the `SeekBar`. This ensures we stay within it at all times. - seekBarPoint = clamp(seekBarPoint, 0, 1); - - if (mouseTimeDisplay) { - mouseTimeDisplay.update(seekBarRect, seekBarPoint); - } - - if (playProgressBar) { - playProgressBar.update(seekBarRect, seekBar.getProgress()); - } - - } - - /** - * A throttled version of the {@link ProgressControl#handleMouseSeek} listener. - * - * @method ProgressControl#throttledHandleMouseSeek - * @param {Event} event - * The `mousemove` event that caused this function to run. - * - * @listen mousemove - * @listen touchmove - */ - - /** - * Handle `mousemove` or `touchmove` events on the `ProgressControl`. - * - * @param {Event} event - * `mousedown` or `touchstart` event that triggered this function - * - * @listens mousemove - * @listens touchmove - */ - handleMouseSeek(event) { - const seekBar = this.getChild('seekBar'); - - if (seekBar) { - seekBar.handleMouseMove(event); - } - } - - /** - * Are controls are currently enabled for this progress control. - * - * @return {boolean} - * true if controls are enabled, false otherwise - */ - enabled() { - return this.enabled_; - } - - /** - * Disable all controls on the progress control and its children - */ - disable() { - this.children().forEach((child) => child.disable && child.disable()); - - if (!this.enabled()) { - return; - } - - this.off(['mousedown', 'touchstart'], this.handleMouseDownHandler_); - this.off(this.el_, ['mousemove', 'touchmove'], this.handleMouseMove); - - this.removeListenersAddedOnMousedownAndTouchstart(); - - this.addClass('disabled'); - - this.enabled_ = false; - - // Restore normal playback state if controls are disabled while scrubbing - if (this.player_.scrubbing()) { - const seekBar = this.getChild('seekBar'); - - this.player_.scrubbing(false); - - if (seekBar.videoWasPlaying) { - silencePromise(this.player_.play()); - } - } - } - - /** - * Enable all controls on the progress control and its children - */ - enable() { - this.children().forEach((child) => child.enable && child.enable()); - - if (this.enabled()) { - return; - } - - this.on(['mousedown', 'touchstart'], this.handleMouseDownHandler_); - this.on(this.el_, ['mousemove', 'touchmove'], this.handleMouseMove); - this.removeClass('disabled'); - - this.enabled_ = true; - } - - /** - * Cleanup listeners after the user finishes interacting with the progress controls - */ - removeListenersAddedOnMousedownAndTouchstart() { - const doc = this.el_.ownerDocument; - - this.off(doc, 'mousemove', this.throttledHandleMouseSeek); - this.off(doc, 'touchmove', this.throttledHandleMouseSeek); - this.off(doc, 'mouseup', this.handleMouseUpHandler_); - this.off(doc, 'touchend', this.handleMouseUpHandler_); - } - - /** - * Handle `mousedown` or `touchstart` events on the `ProgressControl`. - * - * @param {Event} event - * `mousedown` or `touchstart` event that triggered this function - * - * @listens mousedown - * @listens touchstart - */ - handleMouseDown(event) { - const doc = this.el_.ownerDocument; - const seekBar = this.getChild('seekBar'); - - if (seekBar) { - seekBar.handleMouseDown(event); - } - - this.on(doc, 'mousemove', this.throttledHandleMouseSeek); - this.on(doc, 'touchmove', this.throttledHandleMouseSeek); - this.on(doc, 'mouseup', this.handleMouseUpHandler_); - this.on(doc, 'touchend', this.handleMouseUpHandler_); - } - - /** - * Handle `mouseup` or `touchend` events on the `ProgressControl`. - * - * @param {Event} event - * `mouseup` or `touchend` event that triggered this function. - * - * @listens touchend - * @listens mouseup - */ - handleMouseUp(event) { - const seekBar = this.getChild('seekBar'); - - if (seekBar) { - seekBar.handleMouseUp(event); - } - - this.removeListenersAddedOnMousedownAndTouchstart(); - } -} - -/** - * Default options for `ProgressControl` - * - * @type {Object} - * @private - */ -ProgressControl.prototype.options_ = { - children: [ - 'seekBar' - ] -}; - -Component.registerComponent('ProgressControl', ProgressControl); -export default ProgressControl; diff --git a/javascript/videojs/src/js/control-bar/progress-control/seek-bar.js b/javascript/videojs/src/js/control-bar/progress-control/seek-bar.js deleted file mode 100644 index bc7d83c..0000000 --- a/javascript/videojs/src/js/control-bar/progress-control/seek-bar.js +++ /dev/null @@ -1,610 +0,0 @@ -/** - * @file seek-bar.js - */ -import Slider from '../../slider/slider.js'; -import Component from '../../component.js'; -import {IS_IOS, IS_ANDROID} from '../../utils/browser.js'; -import * as Dom from '../../utils/dom.js'; -import * as Fn from '../../utils/fn.js'; -import {formatTime} from '../../utils/time.js'; -import {silencePromise} from '../../utils/promise'; -import {merge} from '../../utils/obj'; -import document from 'global/document'; - -/** @import Player from '../../player' */ - -import './load-progress-bar.js'; -import './play-progress-bar.js'; -import './mouse-time-display.js'; - -/** - * Seek bar and container for the progress bars. Uses {@link PlayProgressBar} - * as its `bar`. - * - * @extends Slider - */ -class SeekBar extends Slider { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - * @param {number} [options.stepSeconds=5] - * The number of seconds to increment on keyboard control - * @param {number} [options.pageMultiplier=12] - * The multiplier of stepSeconds that PgUp/PgDown move the timeline. - */ - constructor(player, options) { - options = merge(SeekBar.prototype.options_, options); - - // Avoid mutating the prototype's `children` array by creating a copy - options.children = [...options.children]; - - const shouldDisableSeekWhileScrubbing = - (player.options_.disableSeekWhileScrubbingOnMobile && (IS_IOS || IS_ANDROID)) || - (player.options_.disableSeekWhileScrubbingOnSTV); - - // Add the TimeTooltip as a child if we are on desktop, or on mobile with `disableSeekWhileScrubbingOnMobile: true` - if ((!IS_IOS && !IS_ANDROID) || shouldDisableSeekWhileScrubbing) { - options.children.splice(1, 0, 'mouseTimeDisplay'); - } - - super(player, options); - - this.shouldDisableSeekWhileScrubbing_ = shouldDisableSeekWhileScrubbing; - this.pendingSeekTime_ = null; - - this.setEventHandlers_(); - } - - /** - * Sets the event handlers - * - * @private - */ - setEventHandlers_() { - this.update_ = Fn.bind_(this, this.update); - this.update = Fn.throttle(this.update_, Fn.UPDATE_REFRESH_INTERVAL); - - this.on(this.player_, ['durationchange', 'timeupdate'], this.update); - this.on(this.player_, ['ended'], this.update_); - if (this.player_.liveTracker) { - this.on(this.player_.liveTracker, 'liveedgechange', this.update); - } - - // when playing, let's ensure we smoothly update the play progress bar - // via an interval - this.updateInterval = null; - - this.enableIntervalHandler_ = (e) => this.enableInterval_(e); - this.disableIntervalHandler_ = (e) => this.disableInterval_(e); - - this.on(this.player_, ['playing'], this.enableIntervalHandler_); - - this.on(this.player_, ['ended', 'pause', 'waiting'], this.disableIntervalHandler_); - - // we don't need to update the play progress if the document is hidden, - // also, this causes the CPU to spike and eventually crash the page on IE11. - if ('hidden' in document && 'visibilityState' in document) { - this.on(document, 'visibilitychange', this.toggleVisibility_); - } - } - - toggleVisibility_(e) { - if (document.visibilityState === 'hidden') { - this.cancelNamedAnimationFrame('SeekBar#update'); - this.cancelNamedAnimationFrame('Slider#update'); - this.disableInterval_(e); - } else { - if (!this.player_.ended() && !this.player_.paused()) { - this.enableInterval_(); - } - - // we just switched back to the page and someone may be looking, so, update ASAP - this.update(); - } - } - - enableInterval_() { - if (this.updateInterval) { - return; - - } - this.updateInterval = this.setInterval(this.update, Fn.UPDATE_REFRESH_INTERVAL); - } - - disableInterval_(e) { - if (this.player_.liveTracker && this.player_.liveTracker.isLive() && e && e.type !== 'ended') { - return; - } - - if (!this.updateInterval) { - return; - } - - this.clearInterval(this.updateInterval); - this.updateInterval = null; - } - - /** - * Create the `Component`'s DOM element - * - * @return {Element} - * The element that was created. - */ - createEl() { - return super.createEl('div', { - className: 'vjs-progress-holder' - }, { - 'aria-label': this.localize('Progress Bar') - }); - } - - /** - * This function updates the play progress bar and accessibility - * attributes to whatever is passed in. - * - * @param {Event} [event] - * The `timeupdate` or `ended` event that caused this to run. - * - * @listens Player#timeupdate - * - * @return {number} - * The current percent at a number from 0-1 - */ - update(event) { - // ignore updates while the tab is hidden - if (document.visibilityState === 'hidden') { - return; - } - - const percent = super.update(); - - this.requestNamedAnimationFrame('SeekBar#update', () => { - const currentTime = this.player_.ended() ? - this.player_.duration() : this.getCurrentTime_(); - const liveTracker = this.player_.liveTracker; - let duration = this.player_.duration(); - - if (liveTracker && liveTracker.isLive()) { - duration = this.player_.liveTracker.liveCurrentTime(); - } - - if (this.percent_ !== percent) { - // machine readable value of progress bar (percentage complete) - this.el_.setAttribute('aria-valuenow', (percent * 100).toFixed(2)); - this.percent_ = percent; - } - - if (this.currentTime_ !== currentTime || this.duration_ !== duration) { - // human readable value of progress bar (time complete) - this.el_.setAttribute( - 'aria-valuetext', - this.localize( - 'progress bar timing: currentTime={1} duration={2}', - [formatTime(currentTime, duration), - formatTime(duration, duration)], - '{1} of {2}' - ) - ); - - this.currentTime_ = currentTime; - this.duration_ = duration; - } - - // update the progress bar time tooltip with the current time - if (this.bar) { - this.bar.update(Dom.getBoundingClientRect(this.el()), this.getProgress(), event); - } - }); - - return percent; - } - - /** - * Prevent liveThreshold from causing seeks to seem like they - * are not happening from a user perspective. - * - * @param {number} ct - * current time to seek to - */ - userSeek_(ct) { - if (this.player_.liveTracker && this.player_.liveTracker.isLive()) { - this.player_.liveTracker.nextSeekedFromUser(); - } - - this.player_.currentTime(ct); - } - - /** - * Get the value of current time but allows for smooth scrubbing, - * when player can't keep up. - * - * @return {number} - * The current time value to display - * - * @private - */ - getCurrentTime_() { - return (this.player_.scrubbing()) ? - this.player_.getCache().currentTime : - this.player_.currentTime(); - } - - /** - * Getter and setter for pendingSeekTime. - * Ensures the value is clamped between 0 and duration. - * - * @param {number|null} [time] - Optional. The new pending seek time, can be a number or null. - * @return {number|null} - The current pending seek time. - */ - pendingSeekTime(time) { - if (time !== undefined) { - if (time !== null) { - const duration = this.player_.duration(); - - this.pendingSeekTime_ = Math.max(0, Math.min(time, duration)); - } else { - this.pendingSeekTime_ = null; - } - } - return this.pendingSeekTime_; - } - - /** - * Get the percentage of media played so far. - * - * @return {number} - * The percentage of media played so far (0 to 1). - */ - getPercent() { - // If we have a pending seek time, we are scrubbing on mobile and should set the slider percent - // to reflect the current scrub location. - if (this.pendingSeekTime() !== null) { - return this.pendingSeekTime() / this.player_.duration(); - } - - const currentTime = this.getCurrentTime_(); - let percent; - const liveTracker = this.player_.liveTracker; - - if (liveTracker && liveTracker.isLive()) { - percent = (currentTime - liveTracker.seekableStart()) / liveTracker.liveWindow(); - - // prevent the percent from changing at the live edge - if (liveTracker.atLiveEdge()) { - percent = 1; - } - } else { - percent = currentTime / this.player_.duration(); - } - - return percent; - } - - /** - * Handle mouse down on seek bar - * - * @param {MouseEvent} event - * The `mousedown` event that caused this to run. - * - * @listens mousedown - */ - handleMouseDown(event) { - if (!Dom.isSingleLeftClick(event)) { - return; - } - - // Stop event propagation to prevent double fire in progress-control.js - event.stopPropagation(); - - this.videoWasPlaying = !this.player_.paused(); - - // Don't pause if we are on mobile and `disableSeekWhileScrubbingOnMobile: true`. - // In that case, playback should continue while the player scrubs to a new location. - if (!this.shouldDisableSeekWhileScrubbing_) { - this.player_.pause(); - } - - super.handleMouseDown(event); - } - - /** - * Handle mouse move on seek bar - * - * @param {MouseEvent} event - * The `mousemove` event that caused this to run. - * @param {boolean} mouseDown this is a flag that should be set to true if `handleMouseMove` is called directly. It allows us to skip things that should not happen if coming from mouse down but should happen on regular mouse move handler. Defaults to false - * - * @listens mousemove - */ - handleMouseMove(event, mouseDown = false) { - if (!Dom.isSingleLeftClick(event) || isNaN(this.player_.duration())) { - return; - } - - if (!mouseDown && !this.player_.scrubbing()) { - this.player_.scrubbing(true); - } - - let newTime; - const distance = this.calculateDistance(event); - const liveTracker = this.player_.liveTracker; - - if (!liveTracker || !liveTracker.isLive()) { - newTime = distance * this.player_.duration(); - - // Don't let video end while scrubbing. - if (newTime === this.player_.duration()) { - newTime = newTime - 0.1; - } - } else { - - if (distance >= 0.99) { - liveTracker.seekToLiveEdge(); - return; - } - const seekableStart = liveTracker.seekableStart(); - const seekableEnd = liveTracker.liveCurrentTime(); - - newTime = seekableStart + (distance * liveTracker.liveWindow()); - - // Don't let video end while scrubbing. - if (newTime >= seekableEnd) { - newTime = seekableEnd; - } - - // Compensate for precision differences so that currentTime is not less - // than seekable start - if (newTime <= seekableStart) { - newTime = seekableStart + 0.1; - } - - // On android seekableEnd can be Infinity sometimes, - // this will cause newTime to be Infinity, which is - // not a valid currentTime. - if (newTime === Infinity) { - return; - } - } - - // if on mobile and `disableSeekWhileScrubbingOnMobile: true`, keep track of the desired seek point but we won't initiate the seek until 'touchend' - if (this.shouldDisableSeekWhileScrubbing_) { - this.pendingSeekTime(newTime); - } else { - this.userSeek_(newTime); - } - - if (this.player_.options_.enableSmoothSeeking) { - this.update(); - } - } - - enable() { - super.enable(); - const mouseTimeDisplay = this.getChild('mouseTimeDisplay'); - - if (!mouseTimeDisplay) { - return; - } - - mouseTimeDisplay.show(); - } - - disable() { - super.disable(); - const mouseTimeDisplay = this.getChild('mouseTimeDisplay'); - - if (!mouseTimeDisplay) { - return; - } - - mouseTimeDisplay.hide(); - } - - /** - * Handle mouse up on seek bar - * - * @param {MouseEvent} event - * The `mouseup` event that caused this to run. - * - * @listens mouseup - */ - handleMouseUp(event) { - super.handleMouseUp(event); - - // Stop event propagation to prevent double fire in progress-control.js - if (event) { - event.stopPropagation(); - } - this.player_.scrubbing(false); - - // If we have a pending seek time, then we have finished scrubbing on mobile and should initiate a seek. - if (this.pendingSeekTime() !== null) { - this.userSeek_(this.pendingSeekTime()); - - this.pendingSeekTime(null); - } - - /** - * Trigger timeupdate because we're done seeking and the time has changed. - * This is particularly useful for if the player is paused to time the time displays. - * - * @event Tech#timeupdate - * @type {Event} - */ - this.player_.trigger({ type: 'timeupdate', target: this, manuallyTriggered: true }); - if (this.videoWasPlaying) { - silencePromise(this.player_.play()); - } else { - // We're done seeking and the time has changed. - // If the player is paused, make sure we display the correct time on the seek bar. - this.update_(); - } - } - - /** - * Handles pending seek time when `disableSeekWhileScrubbingOnSTV` is enabled. - * - * @param {number} stepAmount - The number of seconds to step (positive for forward, negative for backward). - */ - handlePendingSeek_(stepAmount) { - if (!this.player_.paused()) { - this.player_.pause(); - } - - const currentPos = this.pendingSeekTime() !== null ? - this.pendingSeekTime() : - this.player_.currentTime(); - - this.pendingSeekTime(currentPos + stepAmount); - this.player_.trigger({ type: 'timeupdate', target: this, manuallyTriggered: true }); - } - - /** - * Move more quickly fast forward for keyboard-only users - */ - stepForward() { - // if `disableSeekWhileScrubbingOnSTV: true`, keep track of the desired seek point but we won't initiate the seek - if (this.shouldDisableSeekWhileScrubbing_) { - this.handlePendingSeek_(this.options().stepSeconds); - } else { - this.userSeek_(this.player_.currentTime() + this.options().stepSeconds); - } - } - - /** - * Move more quickly rewind for keyboard-only users - */ - stepBack() { - // if `disableSeekWhileScrubbingOnSTV: true`, keep track of the desired seek point but we won't initiate the seek - if (this.shouldDisableSeekWhileScrubbing_) { - this.handlePendingSeek_(-this.options().stepSeconds); - } else { - this.userSeek_(this.player_.currentTime() - this.options().stepSeconds); - } - } - - /** - * Toggles the playback state of the player - * This gets called when enter or space is used on the seekbar - * - * @param {KeyboardEvent} event - * The `keydown` event that caused this function to be called - * - */ - handleAction(event) { - if (this.pendingSeekTime() !== null) { - this.userSeek_(this.pendingSeekTime()); - this.pendingSeekTime(null); - } - if (this.player_.paused()) { - this.player_.play(); - } else { - this.player_.pause(); - } - } - - /** - * Called when this SeekBar has focus and a key gets pressed down. - * Supports the following keys: - * - * Space or Enter key fire a click event - * Home key moves to start of the timeline - * End key moves to end of the timeline - * Digit "0" through "9" keys move to 0%, 10% ... 80%, 90% of the timeline - * PageDown key moves back a larger step than ArrowDown - * PageUp key moves forward a large step - * - * @param {KeyboardEvent} event - * The `keydown` event that caused this function to be called. - * - * @listens keydown - */ - handleKeyDown(event) { - const liveTracker = this.player_.liveTracker; - - if (event.key === ' ' || event.key === 'Enter') { - event.preventDefault(); - event.stopPropagation(); - this.handleAction(event); - } else if (event.key === 'Home') { - event.preventDefault(); - event.stopPropagation(); - this.userSeek_(0); - } else if (event.key === 'End') { - event.preventDefault(); - event.stopPropagation(); - if (liveTracker && liveTracker.isLive()) { - this.userSeek_(liveTracker.liveCurrentTime()); - } else { - this.userSeek_(this.player_.duration()); - } - } else if (/^[0-9]$/.test(event.key)) { - event.preventDefault(); - event.stopPropagation(); - const gotoFraction = parseInt(event.key, 10) * 0.1; - - if (liveTracker && liveTracker.isLive()) { - this.userSeek_(liveTracker.seekableStart() + (liveTracker.liveWindow() * gotoFraction)); - } else { - this.userSeek_(this.player_.duration() * gotoFraction); - } - } else if (event.key === 'PageDown') { - event.preventDefault(); - event.stopPropagation(); - this.userSeek_(this.player_.currentTime() - (this.options().stepSeconds * this.options().pageMultiplier)); - } else if (event.key === 'PageUp') { - event.preventDefault(); - event.stopPropagation(); - this.userSeek_(this.player_.currentTime() + (this.options().stepSeconds * this.options().pageMultiplier)); - } else { - // Pass keydown handling up for unsupported keys - super.handleKeyDown(event); - } - } - - dispose() { - this.disableInterval_(); - - this.off(this.player_, ['durationchange', 'timeupdate'], this.update); - this.off(this.player_, ['ended'], this.update_); - if (this.player_.liveTracker) { - this.off(this.player_.liveTracker, 'liveedgechange', this.update); - } - - this.off(this.player_, ['playing'], this.enableIntervalHandler_); - this.off(this.player_, ['ended', 'pause', 'waiting'], this.disableIntervalHandler_); - - // we don't need to update the play progress if the document is hidden, - // also, this causes the CPU to spike and eventually crash the page on IE11. - if ('hidden' in document && 'visibilityState' in document) { - this.off(document, 'visibilitychange', this.toggleVisibility_); - } - - super.dispose(); - } -} - -/** - * Default options for the `SeekBar` - * - * @type {Object} - * @private - */ -SeekBar.prototype.options_ = { - children: [ - 'loadProgressBar', - 'playProgressBar' - ], - barName: 'playProgressBar', - stepSeconds: 5, - pageMultiplier: 12 -}; - -Component.registerComponent('SeekBar', SeekBar); -export default SeekBar; diff --git a/javascript/videojs/src/js/control-bar/progress-control/time-tooltip.js b/javascript/videojs/src/js/control-bar/progress-control/time-tooltip.js deleted file mode 100644 index aecd8b3..0000000 --- a/javascript/videojs/src/js/control-bar/progress-control/time-tooltip.js +++ /dev/null @@ -1,170 +0,0 @@ -/** - * @file time-tooltip.js - */ -import Component from '../../component'; -import * as Dom from '../../utils/dom.js'; -import {formatTime} from '../../utils/time.js'; -import * as Fn from '../../utils/fn.js'; - -/** @import Player from '../../player' */ - -/** - * Time tooltips display a time above the progress bar. - * - * @extends Component - */ -class TimeTooltip extends Component { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The {@link Player} that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - */ - constructor(player, options) { - super(player, options); - this.update = Fn.throttle(Fn.bind_(this, this.update), Fn.UPDATE_REFRESH_INTERVAL); - } - - /** - * Create the time tooltip DOM element - * - * @return {Element} - * The element that was created. - */ - createEl() { - return super.createEl('div', { - className: 'vjs-time-tooltip' - }, { - 'aria-hidden': 'true' - }); - } - - /** - * Updates the position of the time tooltip relative to the `SeekBar`. - * - * @param {Object} seekBarRect - * The `ClientRect` for the {@link SeekBar} element. - * - * @param {number} seekBarPoint - * A number from 0 to 1, representing a horizontal reference point - * from the left edge of the {@link SeekBar} - */ - update(seekBarRect, seekBarPoint, content) { - const tooltipRect = Dom.findPosition(this.el_); - const playerRect = Dom.getBoundingClientRect(this.player_.el()); - const seekBarPointPx = seekBarRect.width * seekBarPoint; - - // do nothing if either rect isn't available - // for example, if the player isn't in the DOM for testing - if (!playerRect || !tooltipRect) { - return; - } - - // This is the space left of the `seekBarPoint` available within the bounds - // of the player. We calculate any gap between the left edge of the player - // and the left edge of the `SeekBar` and add the number of pixels in the - // `SeekBar` before hitting the `seekBarPoint` - let spaceLeftOfPoint = (seekBarRect.left - playerRect.left) + seekBarPointPx; - - // This is the space right of the `seekBarPoint` available within the bounds - // of the player. We calculate the number of pixels from the `seekBarPoint` - // to the right edge of the `SeekBar` and add to that any gap between the - // right edge of the `SeekBar` and the player. - let spaceRightOfPoint = (seekBarRect.width - seekBarPointPx) + - (playerRect.right - seekBarRect.right); - - // spaceRightOfPoint is always NaN for mouse time display - // because the seekbarRect does not have a right property. This causes - // the mouse tool tip to be truncated when it's close to the right edge of the player. - // In such cases, we ignore the `playerRect.right - seekBarRect.right` value when calculating. - // For the sake of consistency, we ignore seekBarRect.left - playerRect.left for the left edge. - if (!spaceRightOfPoint) { - spaceRightOfPoint = seekBarRect.width - seekBarPointPx; - spaceLeftOfPoint = seekBarPointPx; - } - // This is the number of pixels by which the tooltip will need to be pulled - // further to the right to center it over the `seekBarPoint`. - let pullTooltipBy = tooltipRect.width / 2; - - // Adjust the `pullTooltipBy` distance to the left or right depending on - // the results of the space calculations above. - if (spaceLeftOfPoint < pullTooltipBy) { - pullTooltipBy += pullTooltipBy - spaceLeftOfPoint; - } else if (spaceRightOfPoint < pullTooltipBy) { - pullTooltipBy = spaceRightOfPoint; - } - - // Due to the imprecision of decimal/ratio based calculations and varying - // rounding behaviors, there are cases where the spacing adjustment is off - // by a pixel or two. This adds insurance to these calculations. - if (pullTooltipBy < 0) { - pullTooltipBy = 0; - } else if (pullTooltipBy > tooltipRect.width) { - pullTooltipBy = tooltipRect.width; - } - - // prevent small width fluctuations within 0.4px from - // changing the value below. - // This really helps for live to prevent the play - // progress time tooltip from jittering - pullTooltipBy = Math.round(pullTooltipBy); - - this.el_.style.right = `-${pullTooltipBy}px`; - this.write(content); - } - - /** - * Write the time to the tooltip DOM element. - * - * @param {string} content - * The formatted time for the tooltip. - */ - write(content) { - Dom.textContent(this.el_, content); - } - - /** - * Updates the position of the time tooltip relative to the `SeekBar`. - * - * @param {Object} seekBarRect - * The `ClientRect` for the {@link SeekBar} element. - * - * @param {number} seekBarPoint - * A number from 0 to 1, representing a horizontal reference point - * from the left edge of the {@link SeekBar} - * - * @param {number} time - * The time to update the tooltip to, not used during live playback - * - * @param {Function} cb - * A function that will be called during the request animation frame - * for tooltips that need to do additional animations from the default - */ - updateTime(seekBarRect, seekBarPoint, time, cb) { - this.requestNamedAnimationFrame('TimeTooltip#updateTime', () => { - let content; - const duration = this.player_.duration(); - - if (this.player_.liveTracker && this.player_.liveTracker.isLive()) { - const liveWindow = this.player_.liveTracker.liveWindow(); - const secondsBehind = liveWindow - (seekBarPoint * liveWindow); - - content = (secondsBehind < 1 ? '' : '-') + formatTime(secondsBehind, liveWindow); - } else { - content = formatTime(time, duration); - } - - this.update(seekBarRect, seekBarPoint, content); - if (cb) { - cb(); - } - }); - } -} - -Component.registerComponent('TimeTooltip', TimeTooltip); -export default TimeTooltip; diff --git a/javascript/videojs/src/js/control-bar/seek-to-live.js b/javascript/videojs/src/js/control-bar/seek-to-live.js deleted file mode 100644 index d448267..0000000 --- a/javascript/videojs/src/js/control-bar/seek-to-live.js +++ /dev/null @@ -1,108 +0,0 @@ -/** - * @file seek-to-live.js - */ -import Button from '../button'; -import Component from '../component'; -import * as Dom from '../utils/dom.js'; - -/** @import Player from './player' */ - -/** - * Displays the live indicator when duration is Infinity. - * - * @extends Component - */ -class SeekToLive extends Button { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - */ - constructor(player, options) { - super(player, options); - - this.updateLiveEdgeStatus(); - - if (this.player_.liveTracker) { - this.updateLiveEdgeStatusHandler_ = (e) => this.updateLiveEdgeStatus(e); - this.on(this.player_.liveTracker, 'liveedgechange', this.updateLiveEdgeStatusHandler_); - } - } - - /** - * Create the `Component`'s DOM element - * - * @return {Element} - * The element that was created. - */ - createEl() { - const el = super.createEl('button', { - className: 'vjs-seek-to-live-control vjs-control' - }); - - this.setIcon('circle', el); - - this.textEl_ = Dom.createEl('span', { - className: 'vjs-seek-to-live-text', - textContent: this.localize('LIVE') - }, { - 'aria-hidden': 'true' - }); - - el.appendChild(this.textEl_); - return el; - } - - /** - * Update the state of this button if we are at the live edge - * or not - */ - updateLiveEdgeStatus() { - // default to live edge - if (!this.player_.liveTracker || this.player_.liveTracker.atLiveEdge()) { - this.setAttribute('aria-disabled', true); - this.addClass('vjs-at-live-edge'); - this.controlText('Seek to live, currently playing live'); - } else { - this.setAttribute('aria-disabled', false); - this.removeClass('vjs-at-live-edge'); - this.controlText('Seek to live, currently behind live'); - } - } - - /** - * On click bring us as near to the live point as possible. - * This requires that we wait for the next `live-seekable-change` - * event which will happen every segment length seconds. - */ - handleClick() { - this.player_.liveTracker.seekToLiveEdge(); - } - - /** - * Dispose of the element and stop tracking - */ - dispose() { - if (this.player_.liveTracker) { - this.off(this.player_.liveTracker, 'liveedgechange', this.updateLiveEdgeStatusHandler_); - } - this.textEl_ = null; - - super.dispose(); - } -} -/** - * The text that should display over the `SeekToLive`s control. Added for localization. - * - * @type {string} - * @protected - */ -SeekToLive.prototype.controlText_ = 'Seek to live, currently playing live'; - -Component.registerComponent('SeekToLive', SeekToLive); -export default SeekToLive; diff --git a/javascript/videojs/src/js/control-bar/skip-buttons/skip-backward.js b/javascript/videojs/src/js/control-bar/skip-buttons/skip-backward.js deleted file mode 100644 index 90b8fa5..0000000 --- a/javascript/videojs/src/js/control-bar/skip-buttons/skip-backward.js +++ /dev/null @@ -1,77 +0,0 @@ -import Button from '../../button'; -import Component from '../../component'; - -/** - * Button to skip backward a configurable amount of time - * through a video. Renders in the control bar. - * - * * e.g. options: {controlBar: {skipButtons: backward: 5}} - * - * @extends Button - */ -class SkipBackward extends Button { - constructor(player, options) { - super(player, options); - - this.validOptions = [5, 10, 30]; - this.skipTime = this.getSkipBackwardTime(); - - if (this.skipTime && this.validOptions.includes(this.skipTime)) { - this.setIcon(`replay-${this.skipTime}`); - this.controlText(this.localize('Skip backward {1} seconds', [this.skipTime.toLocaleString(player.language())])); - this.show(); - } else { - this.hide(); - } - } - - getSkipBackwardTime() { - const playerOptions = this.options_.playerOptions; - - return playerOptions.controlBar && playerOptions.controlBar.skipButtons && playerOptions.controlBar.skipButtons.backward; - } - - buildCSSClass() { - return `vjs-skip-backward-${this.getSkipBackwardTime()} ${super.buildCSSClass()}`; - } - - /** - * On click, skips backward in the video by a configurable amount of seconds. - * If the current time in the video is less than the configured 'skip backward' time, - * skips to beginning of video or seekable range. - * - * Handle a click on a `SkipBackward` button - * - * @param {EventTarget~Event} event - * The `click` event that caused this function - * to be called - */ - handleClick(event) { - const currentVideoTime = this.player_.currentTime(); - const liveTracker = this.player_.liveTracker; - const seekableStart = liveTracker && liveTracker.isLive() && liveTracker.seekableStart(); - let newTime; - - if (seekableStart && (currentVideoTime - this.skipTime <= seekableStart)) { - newTime = seekableStart; - } else if (currentVideoTime >= this.skipTime) { - newTime = currentVideoTime - this.skipTime; - } else { - newTime = 0; - } - this.player_.currentTime(newTime); - } - - /** - * Update control text on languagechange - */ - handleLanguagechange() { - this.controlText(this.localize('Skip backward {1} seconds', [this.skipTime])); - } -} - -SkipBackward.prototype.controlText_ = 'Skip Backward'; - -Component.registerComponent('SkipBackward', SkipBackward); - -export default SkipBackward; diff --git a/javascript/videojs/src/js/control-bar/skip-buttons/skip-forward.js b/javascript/videojs/src/js/control-bar/skip-buttons/skip-forward.js deleted file mode 100644 index 602bdc6..0000000 --- a/javascript/videojs/src/js/control-bar/skip-buttons/skip-forward.js +++ /dev/null @@ -1,80 +0,0 @@ -import Button from '../../button'; -import Component from '../../component'; - -/** - * Button to skip forward a configurable amount of time - * through a video. Renders in the control bar. - * - * e.g. options: {controlBar: {skipButtons: forward: 5}} - * - * @extends Button - */ -class SkipForward extends Button { - constructor(player, options) { - super(player, options); - - this.validOptions = [5, 10, 30]; - this.skipTime = this.getSkipForwardTime(); - - if (this.skipTime && this.validOptions.includes(this.skipTime)) { - this.setIcon(`forward-${this.skipTime}`); - this.controlText(this.localize('Skip forward {1} seconds', [this.skipTime.toLocaleString(player.language())])); - this.show(); - } else { - this.hide(); - } - } - - getSkipForwardTime() { - const playerOptions = this.options_.playerOptions; - - return playerOptions.controlBar && playerOptions.controlBar.skipButtons && playerOptions.controlBar.skipButtons.forward; - } - - buildCSSClass() { - return `vjs-skip-forward-${this.getSkipForwardTime()} ${super.buildCSSClass()}`; - } - - /** - * On click, skips forward in the duration/seekable range by a configurable amount of seconds. - * If the time left in the duration/seekable range is less than the configured 'skip forward' time, - * skips to end of duration/seekable range. - * - * Handle a click on a `SkipForward` button - * - * @param {EventTarget~Event} event - * The `click` event that caused this function - * to be called - */ - handleClick(event) { - if (isNaN(this.player_.duration())) { - return; - } - - const currentVideoTime = this.player_.currentTime(); - const liveTracker = this.player_.liveTracker; - const duration = (liveTracker && liveTracker.isLive()) ? liveTracker.seekableEnd() : this.player_.duration(); - let newTime; - - if (currentVideoTime + this.skipTime <= duration) { - newTime = currentVideoTime + this.skipTime; - } else { - newTime = duration; - } - - this.player_.currentTime(newTime); - } - - /** - * Update control text on languagechange - */ - handleLanguagechange() { - this.controlText(this.localize('Skip forward {1} seconds', [this.skipTime])); - } -} - -SkipForward.prototype.controlText_ = 'Skip Forward'; - -Component.registerComponent('SkipForward', SkipForward); - -export default SkipForward; diff --git a/javascript/videojs/src/js/control-bar/spacer-controls/custom-control-spacer.js b/javascript/videojs/src/js/control-bar/spacer-controls/custom-control-spacer.js deleted file mode 100644 index 3913a8a..0000000 --- a/javascript/videojs/src/js/control-bar/spacer-controls/custom-control-spacer.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @file custom-control-spacer.js - */ -import Spacer from './spacer.js'; -import Component from '../../component.js'; - -/** - * Spacer specifically meant to be used as an insertion point for new plugins, etc. - * - * @extends Spacer - */ -class CustomControlSpacer extends Spacer { - - /** - * Builds the default DOM `className`. - * - * @return {string} - * The DOM `className` for this object. - */ - buildCSSClass() { - return `vjs-custom-control-spacer ${super.buildCSSClass()}`; - } - - /** - * Create the `Component`'s DOM element - * - * @return {Element} - * The element that was created. - */ - createEl() { - return super.createEl('div', { - className: this.buildCSSClass(), - // No-flex/table-cell mode requires there be some content - // in the cell to fill the remaining space of the table. - textContent: '\u00a0' - }); - } -} - -Component.registerComponent('CustomControlSpacer', CustomControlSpacer); -export default CustomControlSpacer; diff --git a/javascript/videojs/src/js/control-bar/spacer-controls/spacer.js b/javascript/videojs/src/js/control-bar/spacer-controls/spacer.js deleted file mode 100644 index eff67f9..0000000 --- a/javascript/videojs/src/js/control-bar/spacer-controls/spacer.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @file spacer.js - */ -import Component from '../../component.js'; - -/** - * Just an empty spacer element that can be used as an append point for plugins, etc. - * Also can be used to create space between elements when necessary. - * - * @extends Component - */ -class Spacer extends Component { - - /** - * Builds the default DOM `className`. - * - * @return {string} - * The DOM `className` for this object. - */ - buildCSSClass() { - return `vjs-spacer ${super.buildCSSClass()}`; - } - - /** - * Create the `Component`'s DOM element - * - * @return {Element} - * The element that was created. - */ - createEl(tag = 'div', props = {}, attributes = {}) { - if (!props.className) { - props.className = this.buildCSSClass(); - } - - return super.createEl(tag, props, attributes); - } -} - -Component.registerComponent('Spacer', Spacer); - -export default Spacer; diff --git a/javascript/videojs/src/js/control-bar/text-track-controls/caption-settings-menu-item.js b/javascript/videojs/src/js/control-bar/text-track-controls/caption-settings-menu-item.js deleted file mode 100644 index 5d08e6d..0000000 --- a/javascript/videojs/src/js/control-bar/text-track-controls/caption-settings-menu-item.js +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @file caption-settings-menu-item.js - */ -import TextTrackMenuItem from './text-track-menu-item.js'; -import Component from '../../component.js'; - -/** @import Player from '../../player' */ - -/** - * The menu item for caption track settings menu - * - * @extends TextTrackMenuItem - */ -class CaptionSettingsMenuItem extends TextTrackMenuItem { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - */ - constructor(player, options) { - options.track = { - player, - kind: options.kind, - label: options.kind + ' settings', - selectable: false, - default: false, - mode: 'disabled' - }; - - // CaptionSettingsMenuItem has no concept of 'selected' - options.selectable = false; - - options.name = 'CaptionSettingsMenuItem'; - - super(player, options); - this.addClass('vjs-texttrack-settings'); - this.controlText(', opens ' + options.kind + ' settings dialog'); - } - - /** - * This gets called when an `CaptionSettingsMenuItem` is "clicked". See - * {@link ClickableComponent} for more detailed information on what a click can be. - * - * @param {Event} [event] - * The `keydown`, `tap`, or `click` event that caused this function to be - * called. - * - * @listens tap - * @listens click - */ - handleClick(event) { - this.player().getChild('textTrackSettings').open(); - } - - /** - * Update control text and label on languagechange - */ - handleLanguagechange() { - this.$('.vjs-menu-item-text').textContent = this.player_.localize(this.options_.kind + ' settings'); - - super.handleLanguagechange(); - } -} - -Component.registerComponent('CaptionSettingsMenuItem', CaptionSettingsMenuItem); -export default CaptionSettingsMenuItem; diff --git a/javascript/videojs/src/js/control-bar/text-track-controls/captions-button.js b/javascript/videojs/src/js/control-bar/text-track-controls/captions-button.js deleted file mode 100644 index 8f5f6da..0000000 --- a/javascript/videojs/src/js/control-bar/text-track-controls/captions-button.js +++ /dev/null @@ -1,87 +0,0 @@ -/** - * @file captions-button.js - */ -import TextTrackButton from './text-track-button.js'; -import Component from '../../component.js'; -import CaptionSettingsMenuItem from './caption-settings-menu-item.js'; - -/** @import Player from '../../player' */ - -/** - * The button component for toggling and selecting captions - * - * @extends TextTrackButton - */ -class CaptionsButton extends TextTrackButton { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - * - * @param {Function} [ready] - * The function to call when this component is ready. - */ - constructor(player, options, ready) { - super(player, options, ready); - - this.setIcon('captions'); - } - - /** - * Builds the default DOM `className`. - * - * @return {string} - * The DOM `className` for this object. - */ - buildCSSClass() { - return `vjs-captions-button ${super.buildCSSClass()}`; - } - - buildWrapperCSSClass() { - return `vjs-captions-button ${super.buildWrapperCSSClass()}`; - } - - /** - * Create caption menu items - * - * @return {CaptionSettingsMenuItem[]} - * The array of current menu items. - */ - createItems() { - const items = []; - - if (!(this.player().tech_ && this.player().tech_.featuresNativeTextTracks) && - this.player().getChild('textTrackSettings')) { - items.push(new CaptionSettingsMenuItem(this.player_, {kind: this.kind_})); - - this.hideThreshold_ += 1; - } - - return super.createItems(items); - } - -} - -/** - * `kind` of TextTrack to look for to associate it with this menu. - * - * @type {string} - * @private - */ -CaptionsButton.prototype.kind_ = 'captions'; - -/** - * The text that should display over the `CaptionsButton`s controls. Added for localization. - * - * @type {string} - * @protected - */ -CaptionsButton.prototype.controlText_ = 'Captions'; - -Component.registerComponent('CaptionsButton', CaptionsButton); -export default CaptionsButton; diff --git a/javascript/videojs/src/js/control-bar/text-track-controls/chapters-button.js b/javascript/videojs/src/js/control-bar/text-track-controls/chapters-button.js deleted file mode 100644 index 8366179..0000000 --- a/javascript/videojs/src/js/control-bar/text-track-controls/chapters-button.js +++ /dev/null @@ -1,224 +0,0 @@ -/** - * @file chapters-button.js - */ -import TextTrackButton from './text-track-button.js'; -import Component from '../../component.js'; -import ChaptersTrackMenuItem from './chapters-track-menu-item.js'; -import {toTitleCase} from '../../utils/str.js'; - -/** @import Player from '../../player' */ -/** @import Menu from '../../menu/menu' */ -/** @import TextTrack from '../../tracks/text-track' */ -/** @import TextTrackMenuItem from '../text-track-controls/text-track-menu-item' */ - -/** - * The button component for toggling and selecting chapters - * Chapters act much differently than other text tracks - * Cues are navigation vs. other tracks of alternative languages - * - * @extends TextTrackButton - */ -class ChaptersButton extends TextTrackButton { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - * - * @param {Function} [ready] - * The function to call when this function is ready. - */ - constructor(player, options, ready) { - super(player, options, ready); - - this.setIcon('chapters'); - - this.selectCurrentItem_ = () => { - this.items.forEach(item => { - item.selected(this.track_.activeCues[0] === item.cue); - }); - }; - } - - /** - * Builds the default DOM `className`. - * - * @return {string} - * The DOM `className` for this object. - */ - buildCSSClass() { - return `vjs-chapters-button ${super.buildCSSClass()}`; - } - - buildWrapperCSSClass() { - return `vjs-chapters-button ${super.buildWrapperCSSClass()}`; - } - - /** - * Update the menu based on the current state of its items. - * - * @param {Event} [event] - * An event that triggered this function to run. - * - * @listens TextTrackList#addtrack - * @listens TextTrackList#removetrack - * @listens TextTrackList#change - */ - update(event) { - if (event && event.track && event.track.kind !== 'chapters') { - return; - } - - const track = this.findChaptersTrack(); - - if (track !== this.track_) { - this.setTrack(track); - super.update(); - } else if (!this.items || (track && track.cues && track.cues.length !== this.items.length)) { - // Update the menu initially or if the number of cues has changed since set - super.update(); - } - } - - /** - * Set the currently selected track for the chapters button. - * - * @param {TextTrack} track - * The new track to select. Nothing will change if this is the currently selected - * track. - */ - setTrack(track) { - if (this.track_ === track) { - return; - } - - if (!this.updateHandler_) { - this.updateHandler_ = this.update.bind(this); - } - - // here this.track_ refers to the old track instance - if (this.track_) { - const remoteTextTrackEl = this.player_.remoteTextTrackEls().getTrackElementByTrack_(this.track_); - - if (remoteTextTrackEl) { - remoteTextTrackEl.removeEventListener('load', this.updateHandler_); - } - - this.track_.removeEventListener('cuechange', this.selectCurrentItem_); - - this.track_ = null; - } - - this.track_ = track; - - // here this.track_ refers to the new track instance - if (this.track_) { - this.track_.mode = 'hidden'; - - const remoteTextTrackEl = this.player_.remoteTextTrackEls().getTrackElementByTrack_(this.track_); - - if (remoteTextTrackEl) { - remoteTextTrackEl.addEventListener('load', this.updateHandler_); - } - - this.track_.addEventListener('cuechange', this.selectCurrentItem_); - } - } - - /** - * Find the track object that is currently in use by this ChaptersButton - * - * @return {TextTrack|undefined} - * The current track or undefined if none was found. - */ - findChaptersTrack() { - const tracks = this.player_.textTracks() || []; - - for (let i = tracks.length - 1; i >= 0; i--) { - // We will always choose the last track as our chaptersTrack - const track = tracks[i]; - - if (track.kind === this.kind_) { - return track; - } - } - } - - /** - * Get the caption for the ChaptersButton based on the track label. This will also - * use the current tracks localized kind as a fallback if a label does not exist. - * - * @return {string} - * The tracks current label or the localized track kind. - */ - getMenuCaption() { - if (this.track_ && this.track_.label) { - return this.track_.label; - } - return this.localize(toTitleCase(this.kind_)); - } - - /** - * Create menu from chapter track - * - * @return {Menu} - * New menu for the chapter buttons - */ - createMenu() { - this.options_.title = this.getMenuCaption(); - return super.createMenu(); - } - - /** - * Create a menu item for each text track - * - * @return {TextTrackMenuItem[]} - * Array of menu items - */ - createItems() { - const items = []; - - if (!this.track_) { - return items; - } - - const cues = this.track_.cues; - - if (!cues) { - return items; - } - - for (let i = 0, l = cues.length; i < l; i++) { - const cue = cues[i]; - const mi = new ChaptersTrackMenuItem(this.player_, { track: this.track_, cue }); - - items.push(mi); - } - - return items; - } - -} - -/** - * `kind` of TextTrack to look for to associate it with this menu. - * - * @type {string} - * @private - */ -ChaptersButton.prototype.kind_ = 'chapters'; - -/** - * The text that should display over the `ChaptersButton`s controls. Added for localization. - * - * @type {string} - * @protected - */ -ChaptersButton.prototype.controlText_ = 'Chapters'; - -Component.registerComponent('ChaptersButton', ChaptersButton); -export default ChaptersButton; diff --git a/javascript/videojs/src/js/control-bar/text-track-controls/chapters-track-menu-item.js b/javascript/videojs/src/js/control-bar/text-track-controls/chapters-track-menu-item.js deleted file mode 100644 index 2463564..0000000 --- a/javascript/videojs/src/js/control-bar/text-track-controls/chapters-track-menu-item.js +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @file chapters-track-menu-item.js - */ -import MenuItem from '../../menu/menu-item.js'; -import Component from '../../component.js'; - -/** @import Player from '../../player' */ - -/** - * The chapter track menu item - * - * @extends MenuItem - */ -class ChaptersTrackMenuItem extends MenuItem { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - */ - constructor(player, options) { - const track = options.track; - const cue = options.cue; - const currentTime = player.currentTime(); - - // Modify options for parent MenuItem class's init. - options.selectable = true; - options.multiSelectable = false; - options.label = cue.text; - options.selected = (cue.startTime <= currentTime && currentTime < cue.endTime); - super(player, options); - - this.track = track; - this.cue = cue; - } - - /** - * This gets called when an `ChaptersTrackMenuItem` is "clicked". See - * {@link ClickableComponent} for more detailed information on what a click can be. - * - * @param {Event} [event] - * The `keydown`, `tap`, or `click` event that caused this function to be - * called. - * - * @listens tap - * @listens click - */ - handleClick(event) { - super.handleClick(); - this.player_.currentTime(this.cue.startTime); - } - -} - -Component.registerComponent('ChaptersTrackMenuItem', ChaptersTrackMenuItem); -export default ChaptersTrackMenuItem; diff --git a/javascript/videojs/src/js/control-bar/text-track-controls/descriptions-button.js b/javascript/videojs/src/js/control-bar/text-track-controls/descriptions-button.js deleted file mode 100644 index 320cc35..0000000 --- a/javascript/videojs/src/js/control-bar/text-track-controls/descriptions-button.js +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @file descriptions-button.js - */ -import TextTrackButton from './text-track-button.js'; -import Component from '../../component.js'; -import * as Fn from '../../utils/fn.js'; - -/** @import Player from '../../player' */ - -/** - * The button component for toggling and selecting descriptions - * - * @extends TextTrackButton - */ -class DescriptionsButton extends TextTrackButton { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - * - * @param {Function} [ready] - * The function to call when this component is ready. - */ - constructor(player, options, ready) { - super(player, options, ready); - - this.setIcon('audio-description'); - - const tracks = player.textTracks(); - const changeHandler = Fn.bind_(this, this.handleTracksChange); - - tracks.addEventListener('change', changeHandler); - this.on('dispose', function() { - tracks.removeEventListener('change', changeHandler); - }); - } - - /** - * Handle text track change - * - * @param {Event} event - * The event that caused this function to run - * - * @listens TextTrackList#change - */ - handleTracksChange(event) { - const tracks = this.player().textTracks(); - let disabled = false; - - // Check whether a track of a different kind is showing - for (let i = 0, l = tracks.length; i < l; i++) { - const track = tracks[i]; - - if (track.kind !== this.kind_ && track.mode === 'showing') { - disabled = true; - break; - } - } - - // If another track is showing, disable this menu button - if (disabled) { - this.disable(); - } else { - this.enable(); - } - } - - /** - * Builds the default DOM `className`. - * - * @return {string} - * The DOM `className` for this object. - */ - buildCSSClass() { - return `vjs-descriptions-button ${super.buildCSSClass()}`; - } - - buildWrapperCSSClass() { - return `vjs-descriptions-button ${super.buildWrapperCSSClass()}`; - } -} - -/** - * `kind` of TextTrack to look for to associate it with this menu. - * - * @type {string} - * @private - */ -DescriptionsButton.prototype.kind_ = 'descriptions'; - -/** - * The text that should display over the `DescriptionsButton`s controls. Added for localization. - * - * @type {string} - * @protected - */ -DescriptionsButton.prototype.controlText_ = 'Descriptions'; - -Component.registerComponent('DescriptionsButton', DescriptionsButton); -export default DescriptionsButton; diff --git a/javascript/videojs/src/js/control-bar/text-track-controls/off-text-track-menu-item.js b/javascript/videojs/src/js/control-bar/text-track-controls/off-text-track-menu-item.js deleted file mode 100644 index 7f117a1..0000000 --- a/javascript/videojs/src/js/control-bar/text-track-controls/off-text-track-menu-item.js +++ /dev/null @@ -1,115 +0,0 @@ -/** - * @file off-text-track-menu-item.js - */ -import TextTrackMenuItem from './text-track-menu-item.js'; -import Component from '../../component.js'; - -/** @import Player from '../../player' */ - -/** - * A special menu item for turning off a specific type of text track - * - * @extends TextTrackMenuItem - */ -class OffTextTrackMenuItem extends TextTrackMenuItem { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - */ - constructor(player, options) { - // Create pseudo track info - // Requires options['kind'] - options.track = { - player, - // it is no longer necessary to store `kind` or `kinds` on the track itself - // since they are now stored in the `kinds` property of all instances of - // TextTrackMenuItem, but this will remain for backwards compatibility - kind: options.kind, - kinds: options.kinds, - default: false, - mode: 'disabled' - }; - - if (!options.kinds) { - options.kinds = [options.kind]; - } - - if (options.label) { - options.track.label = options.label; - } else { - options.track.label = options.kinds.join(' and ') + ' off'; - } - - // MenuItem is selectable - options.selectable = true; - // MenuItem is NOT multiSelectable (i.e. only one can be marked "selected" at a time) - options.multiSelectable = false; - - super(player, options); - } - - /** - * Handle text track change - * - * @param {Event} event - * The event that caused this function to run - */ - handleTracksChange(event) { - const tracks = this.player().textTracks(); - let shouldBeSelected = true; - - for (let i = 0, l = tracks.length; i < l; i++) { - const track = tracks[i]; - - if ((this.options_.kinds.indexOf(track.kind) > -1) && track.mode === 'showing') { - shouldBeSelected = false; - break; - } - } - - // Prevent redundant selected() calls because they may cause - // screen readers to read the appended control text unnecessarily - if (shouldBeSelected !== this.isSelected_) { - this.selected(shouldBeSelected); - } - } - - handleSelectedLanguageChange(event) { - const tracks = this.player().textTracks(); - let allHidden = true; - - for (let i = 0, l = tracks.length; i < l; i++) { - const track = tracks[i]; - - if ((['captions', 'descriptions', 'subtitles'].indexOf(track.kind) > -1) && track.mode === 'showing') { - allHidden = false; - break; - } - } - - if (allHidden) { - this.player_.cache_.selectedLanguage = { - enabled: false - }; - } - } - - /** - * Update control text and label on languagechange - */ - handleLanguagechange() { - this.$('.vjs-menu-item-text').textContent = this.player_.localize(this.options_.label); - - super.handleLanguagechange(); - } - -} - -Component.registerComponent('OffTextTrackMenuItem', OffTextTrackMenuItem); -export default OffTextTrackMenuItem; diff --git a/javascript/videojs/src/js/control-bar/text-track-controls/subs-caps-button.js b/javascript/videojs/src/js/control-bar/text-track-controls/subs-caps-button.js deleted file mode 100644 index 576b4d0..0000000 --- a/javascript/videojs/src/js/control-bar/text-track-controls/subs-caps-button.js +++ /dev/null @@ -1,99 +0,0 @@ -/** - * @file sub-caps-button.js - */ -import TextTrackButton from './text-track-button.js'; -import Component from '../../component.js'; -import CaptionSettingsMenuItem from './caption-settings-menu-item.js'; -import SubsCapsMenuItem from './subs-caps-menu-item.js'; -import {toTitleCase} from '../../utils/str.js'; - -/** @import Player from '../../player' */ - -/** - * The button component for toggling and selecting captions and/or subtitles - * - * @extends TextTrackButton - */ -class SubsCapsButton extends TextTrackButton { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - * - * @param {Function} [ready] - * The function to call when this component is ready. - */ - constructor(player, options = {}) { - super(player, options); - - // Although North America uses "captions" in most cases for - // "captions and subtitles" other locales use "subtitles" - this.label_ = 'subtitles'; - this.setIcon('subtitles'); - if (['en', 'en-us', 'en-ca', 'fr-ca'].indexOf(this.player_.language_) > -1) { - this.label_ = 'captions'; - this.setIcon('captions'); - } - this.menuButton_.controlText(toTitleCase(this.label_)); - } - - /** - * Builds the default DOM `className`. - * - * @return {string} - * The DOM `className` for this object. - */ - buildCSSClass() { - return `vjs-subs-caps-button ${super.buildCSSClass()}`; - } - - buildWrapperCSSClass() { - return `vjs-subs-caps-button ${super.buildWrapperCSSClass()}`; - } - - /** - * Create caption/subtitles menu items - * - * @return {CaptionSettingsMenuItem[]} - * The array of current menu items. - */ - createItems() { - let items = []; - - if (!(this.player().tech_ && this.player().tech_.featuresNativeTextTracks) && - this.player().getChild('textTrackSettings')) { - items.push(new CaptionSettingsMenuItem(this.player_, {kind: this.label_})); - - this.hideThreshold_ += 1; - } - - items = super.createItems(items, SubsCapsMenuItem); - return items; - } - -} - -/** - * `kind`s of TextTrack to look for to associate it with this menu. - * - * @type {array} - * @private - */ -SubsCapsButton.prototype.kinds_ = ['captions', 'subtitles']; - -/** - * The text that should display over the `SubsCapsButton`s controls. - * - * - * @type {string} - * @protected - */ -SubsCapsButton.prototype.controlText_ = 'Subtitles'; - -Component.registerComponent('SubsCapsButton', SubsCapsButton); -export default SubsCapsButton; diff --git a/javascript/videojs/src/js/control-bar/text-track-controls/subs-caps-menu-item.js b/javascript/videojs/src/js/control-bar/text-track-controls/subs-caps-menu-item.js deleted file mode 100644 index 7bcbe30..0000000 --- a/javascript/videojs/src/js/control-bar/text-track-controls/subs-caps-menu-item.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @file subs-caps-menu-item.js - */ -import TextTrackMenuItem from './text-track-menu-item.js'; -import Component from '../../component.js'; -import {createEl} from '../../utils/dom.js'; - -/** - * SubsCapsMenuItem has an [cc] icon to distinguish captions from subtitles - * in the SubsCapsMenu. - * - * @extends TextTrackMenuItem - */ -class SubsCapsMenuItem extends TextTrackMenuItem { - - createEl(type, props, attrs) { - const el = super.createEl(type, props, attrs); - const parentSpan = el.querySelector('.vjs-menu-item-text'); - - if (this.options_.track.kind === 'captions') { - if (this.player_.options_.experimentalSvgIcons) { - this.setIcon('captions', el); - } else { - parentSpan.appendChild(createEl('span', { - className: 'vjs-icon-placeholder' - }, { - 'aria-hidden': true - })); - } - parentSpan.appendChild(createEl('span', { - className: 'vjs-control-text', - // space added as the text will visually flow with the - // label - textContent: ` ${this.localize('Captions')}` - })); - } - - return el; - } -} - -Component.registerComponent('SubsCapsMenuItem', SubsCapsMenuItem); -export default SubsCapsMenuItem; diff --git a/javascript/videojs/src/js/control-bar/text-track-controls/subtitles-button.js b/javascript/videojs/src/js/control-bar/text-track-controls/subtitles-button.js deleted file mode 100644 index f7c530c..0000000 --- a/javascript/videojs/src/js/control-bar/text-track-controls/subtitles-button.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @file subtitles-button.js - */ -import TextTrackButton from './text-track-button.js'; -import Component from '../../component.js'; - -/** @import Player from '../../player' */ - -/** - * The button component for toggling and selecting subtitles - * - * @extends TextTrackButton - */ -class SubtitlesButton extends TextTrackButton { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - * - * @param {Function} [ready] - * The function to call when this component is ready. - */ - constructor(player, options, ready) { - super(player, options, ready); - - this.setIcon('subtitles'); - } - - /** - * Builds the default DOM `className`. - * - * @return {string} - * The DOM `className` for this object. - */ - buildCSSClass() { - return `vjs-subtitles-button ${super.buildCSSClass()}`; - } - - buildWrapperCSSClass() { - return `vjs-subtitles-button ${super.buildWrapperCSSClass()}`; - } -} - -/** - * `kind` of TextTrack to look for to associate it with this menu. - * - * @type {string} - * @private - */ -SubtitlesButton.prototype.kind_ = 'subtitles'; - -/** - * The text that should display over the `SubtitlesButton`s controls. Added for localization. - * - * @type {string} - * @protected - */ -SubtitlesButton.prototype.controlText_ = 'Subtitles'; - -Component.registerComponent('SubtitlesButton', SubtitlesButton); -export default SubtitlesButton; diff --git a/javascript/videojs/src/js/control-bar/text-track-controls/text-track-button.js b/javascript/videojs/src/js/control-bar/text-track-controls/text-track-button.js deleted file mode 100644 index 0744986..0000000 --- a/javascript/videojs/src/js/control-bar/text-track-controls/text-track-button.js +++ /dev/null @@ -1,93 +0,0 @@ -/** - * @file text-track-button.js - */ -import TrackButton from '../track-button.js'; -import Component from '../../component.js'; -import TextTrackMenuItem from './text-track-menu-item.js'; -import OffTextTrackMenuItem from './off-text-track-menu-item.js'; - -/** @import Player from '../../player' */ - -/** - * The base class for buttons that toggle specific text track types (e.g. subtitles) - * - * @extends MenuButton - */ -class TextTrackButton extends TrackButton { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options={}] - * The key/value store of player options. - */ - constructor(player, options = {}) { - options.tracks = player.textTracks(); - - super(player, options); - } - - /** - * Create a menu item for each text track - * - * @param {TextTrackMenuItem[]} [items=[]] - * Existing array of items to use during creation - * - * @return {TextTrackMenuItem[]} - * Array of menu items that were created - */ - createItems(items = [], TrackMenuItem = TextTrackMenuItem) { - - // Label is an override for the [track] off label - // USed to localise captions/subtitles - let label; - - if (this.label_) { - label = `${this.label_} off`; - } - // Add an OFF menu item to turn all tracks off - items.push(new OffTextTrackMenuItem(this.player_, { - kinds: this.kinds_, - kind: this.kind_, - label - })); - - this.hideThreshold_ += 1; - - const tracks = this.player_.textTracks(); - - if (!Array.isArray(this.kinds_)) { - this.kinds_ = [this.kind_]; - } - - for (let i = 0; i < tracks.length; i++) { - const track = tracks[i]; - - // only add tracks that are of an appropriate kind and have a label - if (this.kinds_.indexOf(track.kind) > -1) { - - const item = new TrackMenuItem(this.player_, { - track, - kinds: this.kinds_, - kind: this.kind_, - // MenuItem is selectable - selectable: true, - // MenuItem is NOT multiSelectable (i.e. only one can be marked "selected" at a time) - multiSelectable: false - }); - - item.addClass(`vjs-${track.kind}-menu-item`); - items.push(item); - } - } - - return items; - } - -} - -Component.registerComponent('TextTrackButton', TextTrackButton); -export default TextTrackButton; diff --git a/javascript/videojs/src/js/control-bar/text-track-controls/text-track-menu-item.js b/javascript/videojs/src/js/control-bar/text-track-controls/text-track-menu-item.js deleted file mode 100644 index 757e18b..0000000 --- a/javascript/videojs/src/js/control-bar/text-track-controls/text-track-menu-item.js +++ /dev/null @@ -1,182 +0,0 @@ -/** - * @file text-track-menu-item.js - */ -import MenuItem from '../../menu/menu-item.js'; -import Component from '../../component.js'; -import window from 'global/window'; -import document from 'global/document'; - -/** @import Player from '../../player' */ - -/** - * The specific menu item type for selecting a language within a text track kind - * - * @extends MenuItem - */ -class TextTrackMenuItem extends MenuItem { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - */ - constructor(player, options) { - const track = options.track; - const tracks = player.textTracks(); - - // Modify options for parent MenuItem class's init. - options.label = track.label || track.language || 'Unknown'; - options.selected = track.mode === 'showing'; - - super(player, options); - - this.track = track; - // Determine the relevant kind(s) of tracks for this component and filter - // out empty kinds. - this.kinds = (options.kinds || [options.kind || this.track.kind]).filter(Boolean); - - const changeHandler = (...args) => { - this.handleTracksChange.apply(this, args); - }; - const selectedLanguageChangeHandler = (...args) => { - this.handleSelectedLanguageChange.apply(this, args); - }; - - player.on(['loadstart', 'texttrackchange'], changeHandler); - tracks.addEventListener('change', changeHandler); - tracks.addEventListener('selectedlanguagechange', selectedLanguageChangeHandler); - this.on('dispose', function() { - player.off(['loadstart', 'texttrackchange'], changeHandler); - tracks.removeEventListener('change', changeHandler); - tracks.removeEventListener('selectedlanguagechange', selectedLanguageChangeHandler); - }); - - // iOS7 doesn't dispatch change events to TextTrackLists when an - // associated track's mode changes. Without something like - // Object.observe() (also not present on iOS7), it's not - // possible to detect changes to the mode attribute and polyfill - // the change event. As a poor substitute, we manually dispatch - // change events whenever the controls modify the mode. - if (tracks.onchange === undefined) { - let event; - - this.on(['tap', 'click'], function() { - if (typeof window.Event !== 'object') { - // Android 2.3 throws an Illegal Constructor error for window.Event - try { - event = new window.Event('change'); - } catch (err) { - // continue regardless of error - } - } - - if (!event) { - event = document.createEvent('Event'); - event.initEvent('change', true, true); - } - - tracks.dispatchEvent(event); - }); - } - - // set the default state based on current tracks - this.handleTracksChange(); - } - - /** - * This gets called when an `TextTrackMenuItem` is "clicked". See - * {@link ClickableComponent} for more detailed information on what a click can be. - * - * @param {Event} event - * The `keydown`, `tap`, or `click` event that caused this function to be - * called. - * - * @listens tap - * @listens click - */ - handleClick(event) { - const referenceTrack = this.track; - const tracks = this.player_.textTracks(); - - super.handleClick(event); - - if (!tracks) { - return; - } - - for (let i = 0; i < tracks.length; i++) { - const track = tracks[i]; - - // If the track from the text tracks list is not of the right kind, - // skip it. We do not want to affect tracks of incompatible kind(s). - if (this.kinds.indexOf(track.kind) === -1) { - continue; - } - - // If this text track is the component's track and it is not showing, - // set it to showing. - if (track === referenceTrack) { - if (track.mode !== 'showing') { - track.mode = 'showing'; - } - - // If this text track is not the component's track and it is not - // disabled, set it to disabled. - } else if (track.mode !== 'disabled') { - track.mode = 'disabled'; - } - } - } - - /** - * Handle text track list change - * - * @param {Event} event - * The `change` event that caused this function to be called. - * - * @listens TextTrackList#change - */ - handleTracksChange(event) { - const shouldBeSelected = this.track.mode === 'showing'; - - // Prevent redundant selected() calls because they may cause - // screen readers to read the appended control text unnecessarily - if (shouldBeSelected !== this.isSelected_) { - this.selected(shouldBeSelected); - } - } - - handleSelectedLanguageChange(event) { - if (this.track.mode === 'showing') { - const selectedLanguage = this.player_.cache_.selectedLanguage; - - // Don't replace the kind of track across the same language - if (selectedLanguage && selectedLanguage.enabled && - selectedLanguage.language === this.track.language && - selectedLanguage.kind !== this.track.kind) { - return; - } - - this.player_.cache_.selectedLanguage = { - enabled: true, - language: this.track.language, - kind: this.track.kind - }; - } - } - - dispose() { - // remove reference to track object on dispose - this.track = null; - - super.dispose(); - } - -} - -Component.registerComponent('TextTrackMenuItem', TextTrackMenuItem); -export default TextTrackMenuItem; diff --git a/javascript/videojs/src/js/control-bar/time-controls/current-time-display.js b/javascript/videojs/src/js/control-bar/time-controls/current-time-display.js deleted file mode 100644 index 5047df6..0000000 --- a/javascript/videojs/src/js/control-bar/time-controls/current-time-display.js +++ /dev/null @@ -1,67 +0,0 @@ -/** - * @file current-time-display.js - */ -import TimeDisplay from './time-display'; -import Component from '../../component.js'; - -/** - * Displays the current time - * - * @extends Component - */ -class CurrentTimeDisplay extends TimeDisplay { - - /** - * Builds the default DOM `className`. - * - * @return {string} - * The DOM `className` for this object. - */ - buildCSSClass() { - return 'vjs-current-time'; - } - - /** - * Update current time display - * - * @param {Event} [event] - * The `timeupdate` event that caused this function to run. - * - * @listens Player#timeupdate - */ - updateContent(event) { - // Allows for smooth scrubbing, when player can't keep up. - let time; - - if (this.player_.ended()) { - time = this.player_.duration(); - } else if (event && event.target && typeof event.target.pendingSeekTime === 'function' && event.target.pendingSeekTime() !== null) { - time = event.target.pendingSeekTime(); - } else { - time = (this.player_.scrubbing()) ? this.player_.getCache().currentTime : this.player_.currentTime(); - } - - this.updateTextNode_(time); - } -} - -/** - * The text that is added to the `CurrentTimeDisplay` for screen reader users. - * - * @type {string} - * @private - */ -CurrentTimeDisplay.prototype.labelText_ = 'Current Time'; - -/** - * The text that should display over the `CurrentTimeDisplay`s controls. Added to for localization. - * - * @type {string} - * @protected - * - * @deprecated in v7; controlText_ is not used in non-active display Components - */ -CurrentTimeDisplay.prototype.controlText_ = 'Current Time'; - -Component.registerComponent('CurrentTimeDisplay', CurrentTimeDisplay); -export default CurrentTimeDisplay; diff --git a/javascript/videojs/src/js/control-bar/time-controls/duration-display.js b/javascript/videojs/src/js/control-bar/time-controls/duration-display.js deleted file mode 100644 index bd02d69..0000000 --- a/javascript/videojs/src/js/control-bar/time-controls/duration-display.js +++ /dev/null @@ -1,93 +0,0 @@ -/** - * @file duration-display.js - */ -import TimeDisplay from './time-display'; -import Component from '../../component.js'; - -/** @import Player from '../../player' */ - -/** - * Displays the duration - * - * @extends Component - */ -class DurationDisplay extends TimeDisplay { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - */ - constructor(player, options) { - super(player, options); - - const updateContent = (e) => this.updateContent(e); - - // we do not want to/need to throttle duration changes, - // as they should always display the changed duration as - // it has changed - this.on(player, 'durationchange', updateContent); - - // Listen to loadstart because the player duration is reset when a new media element is loaded, - // but the durationchange on the user agent will not fire. - // @see [Spec]{@link https://www.w3.org/TR/2011/WD-html5-20110113/video.html#media-element-load-algorithm} - this.on(player, 'loadstart', updateContent); - - // Also listen for timeupdate (in the parent) and loadedmetadata because removing those - // listeners could have broken dependent applications/libraries. These - // can likely be removed for 7.0. - this.on(player, 'loadedmetadata', updateContent); - } - - /** - * Builds the default DOM `className`. - * - * @return {string} - * The DOM `className` for this object. - */ - buildCSSClass() { - return 'vjs-duration'; - } - - /** - * Update duration time display. - * - * @param {Event} [event] - * The `durationchange`, `timeupdate`, or `loadedmetadata` event that caused - * this function to be called. - * - * @listens Player#durationchange - * @listens Player#timeupdate - * @listens Player#loadedmetadata - */ - updateContent(event) { - const duration = this.player_.duration(); - - this.updateTextNode_(duration); - } -} - -/** - * The text that is added to the `DurationDisplay` for screen reader users. - * - * @type {string} - * @private - */ -DurationDisplay.prototype.labelText_ = 'Duration'; - -/** - * The text that should display over the `DurationDisplay`s controls. Added to for localization. - * - * @type {string} - * @protected - * - * @deprecated in v7; controlText_ is not used in non-active display Components - */ -DurationDisplay.prototype.controlText_ = 'Duration'; - -Component.registerComponent('DurationDisplay', DurationDisplay); -export default DurationDisplay; diff --git a/javascript/videojs/src/js/control-bar/time-controls/remaining-time-display.js b/javascript/videojs/src/js/control-bar/time-controls/remaining-time-display.js deleted file mode 100644 index b3842c8..0000000 --- a/javascript/videojs/src/js/control-bar/time-controls/remaining-time-display.js +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @file remaining-time-display.js - */ -import TimeDisplay from './time-display'; -import Component from '../../component.js'; -import * as Dom from '../../utils/dom.js'; - -/** @import Player from '../../player' */ - -/** - * Displays the time left in the video - * - * @extends Component - */ -class RemainingTimeDisplay extends TimeDisplay { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - */ - constructor(player, options) { - super(player, options); - this.on(player, 'durationchange', (e) => this.updateContent(e)); - } - - /** - * Builds the default DOM `className`. - * - * @return {string} - * The DOM `className` for this object. - */ - buildCSSClass() { - return 'vjs-remaining-time'; - } - - /** - * Create the `Component`'s DOM element with the "minus" character prepend to the time - * - * @return {Element} - * The element that was created. - */ - createEl() { - const el = super.createEl(); - - if (this.options_.displayNegative !== false) { - el.insertBefore(Dom.createEl('span', {}, {'aria-hidden': true}, '-'), this.contentEl_); - } - return el; - } - - /** - * Update remaining time display. - * - * @param {Event} [event] - * The `timeupdate` or `durationchange` event that caused this to run. - * - * @listens Player#timeupdate - * @listens Player#durationchange - */ - updateContent(event) { - if (typeof this.player_.duration() !== 'number') { - return; - } - - let time; - - // @deprecated We should only use remainingTimeDisplay - // as of video.js 7 - if (this.player_.ended()) { - time = 0; - } else if (this.player_.remainingTimeDisplay) { - time = this.player_.remainingTimeDisplay(); - } else { - time = this.player_.remainingTime(); - } - - this.updateTextNode_(time); - } -} - -/** - * The text that is added to the `RemainingTimeDisplay` for screen reader users. - * - * @type {string} - * @private - */ -RemainingTimeDisplay.prototype.labelText_ = 'Remaining Time'; - -/** - * The text that should display over the `RemainingTimeDisplay`s controls. Added to for localization. - * - * @type {string} - * @protected - * - * @deprecated in v7; controlText_ is not used in non-active display Components - */ -RemainingTimeDisplay.prototype.controlText_ = 'Remaining Time'; - -Component.registerComponent('RemainingTimeDisplay', RemainingTimeDisplay); -export default RemainingTimeDisplay; diff --git a/javascript/videojs/src/js/control-bar/time-controls/time-display.js b/javascript/videojs/src/js/control-bar/time-controls/time-display.js deleted file mode 100644 index 2fa558d..0000000 --- a/javascript/videojs/src/js/control-bar/time-controls/time-display.js +++ /dev/null @@ -1,164 +0,0 @@ -/** - * @file time-display.js - */ -import document from 'global/document'; -import Component from '../../component.js'; -import * as Dom from '../../utils/dom.js'; -import {formatTime} from '../../utils/time.js'; -import log from '../../utils/log.js'; - -/** @import Player from '../../player' */ - -/** - * Displays time information about the video - * - * @extends Component - */ -class TimeDisplay extends Component { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - */ - constructor(player, options) { - super(player, options); - - this.on(player, ['timeupdate', 'ended', 'seeking'], (e) => this.update(e)); - this.updateTextNode_(); - } - - /** - * Create the `Component`'s DOM element - * - * @return {Element} - * The element that was created. - */ - createEl() { - const className = this.buildCSSClass(); - const el = super.createEl('div', { - className: `${className} vjs-time-control vjs-control` - }); - const span = Dom.createEl('span', { - className: 'vjs-control-text', - textContent: `${this.localize(this.labelText_)}\u00a0` - }, { - role: 'presentation' - }); - - el.appendChild(span); - - this.contentEl_ = Dom.createEl('span', { - className: `${className}-display` - }, { - // span elements have no implicit role, but some screen readers (notably VoiceOver) - // treat them as a break between items in the DOM when using arrow keys - // (or left-to-right swipes on iOS) to read contents of a page. Using - // role='presentation' causes VoiceOver to NOT treat this span as a break. - role: 'presentation' - }); - - el.appendChild(this.contentEl_); - return el; - } - - dispose() { - this.contentEl_ = null; - this.textNode_ = null; - - super.dispose(); - } - - /** - * Updates the displayed time according to the `updateContent` function which is defined in the child class. - * - * @param {Event} [event] - * The `timeupdate`, `ended` or `seeking` (if enableSmoothSeeking is true) event that caused this function to be called. - */ - update(event) { - if (!this.player_.options_.enableSmoothSeeking && event.type === 'seeking') { - return; - } - - this.updateContent(event); - } - - /** - * Updates the time display text node with a new time - * - * @param {number} [time=0] the time to update to - * - * @private - */ - updateTextNode_(time = 0) { - time = formatTime(time); - - if (this.formattedTime_ === time) { - return; - } - - this.formattedTime_ = time; - - this.requestNamedAnimationFrame('TimeDisplay#updateTextNode_', () => { - if (!this.contentEl_) { - return; - } - - let oldNode = this.textNode_; - - if (oldNode && this.contentEl_.firstChild !== oldNode) { - oldNode = null; - - log.warn('TimeDisplay#updateTextnode_: Prevented replacement of text node element since it was no longer a child of this node. Appending a new node instead.'); - } - - this.textNode_ = document.createTextNode(this.formattedTime_); - - if (!this.textNode_) { - return; - } - - if (oldNode) { - this.contentEl_.replaceChild(this.textNode_, oldNode); - } else { - this.contentEl_.appendChild(this.textNode_); - } - }); - } - - /** - * To be filled out in the child class, should update the displayed time - * in accordance with the fact that the current time has changed. - * - * @param {Event} [event] - * The `timeupdate` event that caused this to run. - * - * @listens Player#timeupdate - */ - updateContent(event) {} -} - -/** - * The text that is added to the `TimeDisplay` for screen reader users. - * - * @type {string} - * @private - */ -TimeDisplay.prototype.labelText_ = 'Time'; - -/** - * The text that should display over the `TimeDisplay`s controls. Added to for localization. - * - * @type {string} - * @protected - * - * @deprecated in v7; controlText_ is not used in non-active display Components - */ -TimeDisplay.prototype.controlText_ = 'Time'; - -Component.registerComponent('TimeDisplay', TimeDisplay); -export default TimeDisplay; diff --git a/javascript/videojs/src/js/control-bar/time-controls/time-divider.js b/javascript/videojs/src/js/control-bar/time-controls/time-divider.js deleted file mode 100644 index 970e2d1..0000000 --- a/javascript/videojs/src/js/control-bar/time-controls/time-divider.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @file time-divider.js - */ -import Component from '../../component.js'; - -/** - * The separator between the current time and duration. - * Can be hidden if it's not needed in the design. - * - * @extends Component - */ -class TimeDivider extends Component { - - /** - * Create the component's DOM element - * - * @return {Element} - * The element that was created. - */ - createEl() { - const el = super.createEl('div', { - className: 'vjs-time-control vjs-time-divider' - }, { - // this element and its contents can be hidden from assistive techs since - // it is made extraneous by the announcement of the control text - // for the current time and duration displays - 'aria-hidden': true - }); - - const div = super.createEl('div'); - const span = super.createEl('span', { - textContent: '/' - }); - - div.appendChild(span); - el.appendChild(div); - - return el; - } - -} - -Component.registerComponent('TimeDivider', TimeDivider); -export default TimeDivider; diff --git a/javascript/videojs/src/js/control-bar/track-button.js b/javascript/videojs/src/js/control-bar/track-button.js deleted file mode 100644 index 99ab39c..0000000 --- a/javascript/videojs/src/js/control-bar/track-button.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @file track-button.js - */ -import MenuButton from '../menu/menu-button.js'; -import Component from '../component.js'; -import * as Fn from '../utils/fn.js'; - -/** @import Player from './player' */ - -/** - * The base class for buttons that toggle specific track types (e.g. subtitles). - * - * @extends MenuButton - */ -class TrackButton extends MenuButton { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - */ - constructor(player, options) { - const tracks = options.tracks; - - super(player, options); - - if (this.items.length <= 1) { - this.hide(); - } - - if (!tracks) { - return; - } - - const updateHandler = Fn.bind_(this, this.update); - - tracks.addEventListener('removetrack', updateHandler); - tracks.addEventListener('addtrack', updateHandler); - tracks.addEventListener('labelchange', updateHandler); - this.player_.on('ready', updateHandler); - - this.player_.on('dispose', function() { - tracks.removeEventListener('removetrack', updateHandler); - tracks.removeEventListener('addtrack', updateHandler); - tracks.removeEventListener('labelchange', updateHandler); - }); - } - -} - -Component.registerComponent('TrackButton', TrackButton); -export default TrackButton; diff --git a/javascript/videojs/src/js/control-bar/volume-control/check-mute-support.js b/javascript/videojs/src/js/control-bar/volume-control/check-mute-support.js deleted file mode 100644 index 8665883..0000000 --- a/javascript/videojs/src/js/control-bar/volume-control/check-mute-support.js +++ /dev/null @@ -1,31 +0,0 @@ -/** @import Component from '../../component' */ -/** @import Player from '../../player' */ - -/** - * Check if muting volume is supported and if it isn't hide the mute toggle - * button. - * - * @param {Component} self - * A reference to the mute toggle button - * - * @param {Player} player - * A reference to the player - * - * @private - */ -const checkMuteSupport = function(self, player) { - // hide mute toggle button if it's not supported by the current tech - if (player.tech_ && !player.tech_.featuresMuteControl) { - self.addClass('vjs-hidden'); - } - - self.on(player, 'loadstart', function() { - if (!player.tech_.featuresMuteControl) { - self.addClass('vjs-hidden'); - } else { - self.removeClass('vjs-hidden'); - } - }); -}; - -export default checkMuteSupport; diff --git a/javascript/videojs/src/js/control-bar/volume-control/check-volume-support.js b/javascript/videojs/src/js/control-bar/volume-control/check-volume-support.js deleted file mode 100644 index 88f287b..0000000 --- a/javascript/videojs/src/js/control-bar/volume-control/check-volume-support.js +++ /dev/null @@ -1,31 +0,0 @@ -/** @import Component from '../../component' */ -/** @import Player from '../../player' */ - -/** - * Check if volume control is supported and if it isn't hide the - * `Component` that was passed using the `vjs-hidden` class. - * - * @param {Component} self - * The component that should be hidden if volume is unsupported - * - * @param {Player} player - * A reference to the player - * - * @private - */ -const checkVolumeSupport = function(self, player) { - // hide volume controls when they're not supported by the current tech - if (player.tech_ && !player.tech_.featuresVolumeControl) { - self.addClass('vjs-hidden'); - } - - self.on(player, 'loadstart', function() { - if (!player.tech_.featuresVolumeControl) { - self.addClass('vjs-hidden'); - } else { - self.removeClass('vjs-hidden'); - } - }); -}; - -export default checkVolumeSupport; diff --git a/javascript/videojs/src/js/control-bar/volume-control/mouse-volume-level-display.js b/javascript/videojs/src/js/control-bar/volume-control/mouse-volume-level-display.js deleted file mode 100644 index 467d7b5..0000000 --- a/javascript/videojs/src/js/control-bar/volume-control/mouse-volume-level-display.js +++ /dev/null @@ -1,89 +0,0 @@ -/** - * @file mouse-volume-level-display.js - */ -import Component from '../../component.js'; -import * as Fn from '../../utils/fn.js'; - -/** @import Player from '../../player' */ - -import './volume-level-tooltip'; - -/** - * The {@link MouseVolumeLevelDisplay} component tracks mouse movement over the - * {@link VolumeControl}. It displays an indicator and a {@link VolumeLevelTooltip} - * indicating the volume level which is represented by a given point in the - * {@link VolumeBar}. - * - * @extends Component - */ -class MouseVolumeLevelDisplay extends Component { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The {@link Player} that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - */ - constructor(player, options) { - super(player, options); - this.update = Fn.throttle(Fn.bind_(this, this.update), Fn.UPDATE_REFRESH_INTERVAL); - } - - /** - * Create the DOM element for this class. - * - * @return {Element} - * The element that was created. - */ - createEl() { - return super.createEl('div', { - className: 'vjs-mouse-display' - }); - } - - /** - * Enquires updates to its own DOM as well as the DOM of its - * {@link VolumeLevelTooltip} child. - * - * @param {Object} rangeBarRect - * The `ClientRect` for the {@link VolumeBar} element. - * - * @param {number} rangeBarPoint - * A number from 0 to 1, representing a horizontal/vertical reference point - * from the left edge of the {@link VolumeBar} - * - * @param {boolean} vertical - * Referees to the Volume control position - * in the control bar{@link VolumeControl} - * - */ - update(rangeBarRect, rangeBarPoint, vertical) { - const volume = 100 * rangeBarPoint; - - this.getChild('volumeLevelTooltip').updateVolume(rangeBarRect, rangeBarPoint, vertical, volume, () => { - if (vertical) { - this.el_.style.bottom = `${rangeBarRect.height * rangeBarPoint}px`; - } else { - this.el_.style.left = `${rangeBarRect.width * rangeBarPoint}px`; - } - }); - } -} - -/** - * Default options for `MouseVolumeLevelDisplay` - * - * @type {Object} - * @private - */ -MouseVolumeLevelDisplay.prototype.options_ = { - children: [ - 'volumeLevelTooltip' - ] -}; - -Component.registerComponent('MouseVolumeLevelDisplay', MouseVolumeLevelDisplay); -export default MouseVolumeLevelDisplay; diff --git a/javascript/videojs/src/js/control-bar/volume-control/volume-bar.js b/javascript/videojs/src/js/control-bar/volume-control/volume-bar.js deleted file mode 100644 index 4e2a02c..0000000 --- a/javascript/videojs/src/js/control-bar/volume-control/volume-bar.js +++ /dev/null @@ -1,212 +0,0 @@ -/** - * @file volume-bar.js - */ -import Slider from '../../slider/slider.js'; -import Component from '../../component.js'; -import * as Dom from '../../utils/dom.js'; -import {clamp} from '../../utils/num.js'; -import {IS_IOS, IS_ANDROID} from '../../utils/browser.js'; - -/** @import Player from '../../player' */ - -// Required children -import './volume-level.js'; -import './mouse-volume-level-display.js'; - -/** - * The bar that contains the volume level and can be clicked on to adjust the level - * - * @extends Slider - */ -class VolumeBar extends Slider { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - */ - constructor(player, options) { - super(player, options); - this.on('slideractive', (e) => this.updateLastVolume_(e)); - this.on(player, 'volumechange', (e) => this.updateARIAAttributes(e)); - player.ready(() => this.updateARIAAttributes()); - } - - /** - * Create the `Component`'s DOM element - * - * @return {Element} - * The element that was created. - */ - createEl() { - return super.createEl('div', { - className: 'vjs-volume-bar vjs-slider-bar' - }, { - 'aria-label': this.localize('Volume Level'), - 'aria-live': 'polite' - }); - } - - /** - * Handle mouse down on volume bar - * - * @param {Event} event - * The `mousedown` event that caused this to run. - * - * @listens mousedown - */ - handleMouseDown(event) { - if (!Dom.isSingleLeftClick(event)) { - return; - } - - super.handleMouseDown(event); - } - - /** - * Handle movement events on the {@link VolumeMenuButton}. - * - * @param {Event} event - * The event that caused this function to run. - * - * @listens mousemove - */ - handleMouseMove(event) { - const mouseVolumeLevelDisplay = this.getChild('mouseVolumeLevelDisplay'); - - if (mouseVolumeLevelDisplay) { - const volumeBarEl = this.el(); - const volumeBarRect = Dom.getBoundingClientRect(volumeBarEl); - const vertical = this.vertical(); - let volumeBarPoint = Dom.getPointerPosition(volumeBarEl, event); - - volumeBarPoint = vertical ? volumeBarPoint.y : volumeBarPoint.x; - // The default skin has a gap on either side of the `VolumeBar`. This means - // that it's possible to trigger this behavior outside the boundaries of - // the `VolumeBar`. This ensures we stay within it at all times. - volumeBarPoint = clamp(volumeBarPoint, 0, 1); - - mouseVolumeLevelDisplay.update(volumeBarRect, volumeBarPoint, vertical); - } - - if (!Dom.isSingleLeftClick(event)) { - return; - } - - this.checkMuted(); - this.player_.volume(this.calculateDistance(event)); - } - - /** - * If the player is muted unmute it. - */ - checkMuted() { - if (this.player_.muted()) { - this.player_.muted(false); - } - } - - /** - * Get percent of volume level - * - * @return {number} - * Volume level percent as a decimal number. - */ - getPercent() { - if (this.player_.muted()) { - return 0; - } - return this.player_.volume(); - } - - /** - * Increase volume level for keyboard users - */ - stepForward() { - this.checkMuted(); - this.player_.volume(this.player_.volume() + 0.1); - } - - /** - * Decrease volume level for keyboard users - */ - stepBack() { - this.checkMuted(); - this.player_.volume(this.player_.volume() - 0.1); - } - - /** - * Update ARIA accessibility attributes - * - * @param {Event} [event] - * The `volumechange` event that caused this function to run. - * - * @listens Player#volumechange - */ - updateARIAAttributes(event) { - const ariaValue = this.player_.muted() ? 0 : this.volumeAsPercentage_(); - - this.el_.setAttribute('aria-valuenow', ariaValue); - this.el_.setAttribute('aria-valuetext', ariaValue + '%'); - } - - /** - * Returns the current value of the player volume as a percentage - * - * @private - */ - volumeAsPercentage_() { - return Math.round(this.player_.volume() * 100); - } - - /** - * When user starts dragging the VolumeBar, store the volume and listen for - * the end of the drag. When the drag ends, if the volume was set to zero, - * set lastVolume to the stored volume. - * - * @listens slideractive - * @private - */ - updateLastVolume_() { - const volumeBeforeDrag = this.player_.volume(); - - this.one('sliderinactive', () => { - if (this.player_.volume() === 0) { - this.player_.lastVolume_(volumeBeforeDrag); - } - }); - } - -} - -/** - * Default options for the `VolumeBar` - * - * @type {Object} - * @private - */ -VolumeBar.prototype.options_ = { - children: [ - 'volumeLevel' - ], - barName: 'volumeLevel' -}; - -// MouseVolumeLevelDisplay tooltip should not be added to a player on mobile devices -if (!IS_IOS && !IS_ANDROID) { - VolumeBar.prototype.options_.children.splice(0, 0, 'mouseVolumeLevelDisplay'); -} - -/** - * Call the update event for this Slider when this event happens on the player. - * - * @type {string} - */ -VolumeBar.prototype.playerEvent = 'volumechange'; - -Component.registerComponent('VolumeBar', VolumeBar); -export default VolumeBar; diff --git a/javascript/videojs/src/js/control-bar/volume-control/volume-control.js b/javascript/videojs/src/js/control-bar/volume-control/volume-control.js deleted file mode 100644 index 723e9c3..0000000 --- a/javascript/videojs/src/js/control-bar/volume-control/volume-control.js +++ /dev/null @@ -1,148 +0,0 @@ -/** - * @file volume-control.js - */ -import Component from '../../component.js'; -import checkVolumeSupport from './check-volume-support'; -import {isPlain} from '../../utils/obj'; -import {throttle, bind_, UPDATE_REFRESH_INTERVAL} from '../../utils/fn.js'; - -/** @import Player from '../../player' */ - -// Required children -import './volume-bar.js'; - -/** - * The component for controlling the volume level - * - * @extends Component - */ -class VolumeControl extends Component { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options={}] - * The key/value store of player options. - */ - constructor(player, options = {}) { - options.vertical = options.vertical || false; - - // Pass the vertical option down to the VolumeBar if - // the VolumeBar is turned on. - if (typeof options.volumeBar === 'undefined' || isPlain(options.volumeBar)) { - options.volumeBar = options.volumeBar || {}; - options.volumeBar.vertical = options.vertical; - } - - super(player, options); - - // hide this control if volume support is missing - checkVolumeSupport(this, player); - - this.throttledHandleMouseMove = throttle(bind_(this, this.handleMouseMove), UPDATE_REFRESH_INTERVAL); - this.handleMouseUpHandler_ = (e) => this.handleMouseUp(e); - - this.on('mousedown', (e) => this.handleMouseDown(e)); - this.on('touchstart', (e) => this.handleMouseDown(e)); - this.on('mousemove', (e) => this.handleMouseMove(e)); - - // while the slider is active (the mouse has been pressed down and - // is dragging) or in focus we do not want to hide the VolumeBar - this.on(this.volumeBar, ['focus', 'slideractive'], () => { - this.volumeBar.addClass('vjs-slider-active'); - this.addClass('vjs-slider-active'); - this.trigger('slideractive'); - }); - - this.on(this.volumeBar, ['blur', 'sliderinactive'], () => { - this.volumeBar.removeClass('vjs-slider-active'); - this.removeClass('vjs-slider-active'); - this.trigger('sliderinactive'); - }); - } - - /** - * Create the `Component`'s DOM element - * - * @return {Element} - * The element that was created. - */ - createEl() { - let orientationClass = 'vjs-volume-horizontal'; - - if (this.options_.vertical) { - orientationClass = 'vjs-volume-vertical'; - } - - return super.createEl('div', { - className: `vjs-volume-control vjs-control ${orientationClass}` - }); - } - - /** - * Handle `mousedown` or `touchstart` events on the `VolumeControl`. - * - * @param {Event} event - * `mousedown` or `touchstart` event that triggered this function - * - * @listens mousedown - * @listens touchstart - */ - handleMouseDown(event) { - const doc = this.el_.ownerDocument; - - this.on(doc, 'mousemove', this.throttledHandleMouseMove); - this.on(doc, 'touchmove', this.throttledHandleMouseMove); - this.on(doc, 'mouseup', this.handleMouseUpHandler_); - this.on(doc, 'touchend', this.handleMouseUpHandler_); - } - - /** - * Handle `mouseup` or `touchend` events on the `VolumeControl`. - * - * @param {Event} event - * `mouseup` or `touchend` event that triggered this function. - * - * @listens touchend - * @listens mouseup - */ - handleMouseUp(event) { - const doc = this.el_.ownerDocument; - - this.off(doc, 'mousemove', this.throttledHandleMouseMove); - this.off(doc, 'touchmove', this.throttledHandleMouseMove); - this.off(doc, 'mouseup', this.handleMouseUpHandler_); - this.off(doc, 'touchend', this.handleMouseUpHandler_); - } - - /** - * Handle `mousedown` or `touchstart` events on the `VolumeControl`. - * - * @param {Event} event - * `mousedown` or `touchstart` event that triggered this function - * - * @listens mousedown - * @listens touchstart - */ - handleMouseMove(event) { - this.volumeBar.handleMouseMove(event); - } -} - -/** - * Default options for the `VolumeControl` - * - * @type {Object} - * @private - */ -VolumeControl.prototype.options_ = { - children: [ - 'volumeBar' - ] -}; - -Component.registerComponent('VolumeControl', VolumeControl); -export default VolumeControl; diff --git a/javascript/videojs/src/js/control-bar/volume-control/volume-level-tooltip.js b/javascript/videojs/src/js/control-bar/volume-control/volume-level-tooltip.js deleted file mode 100644 index 9df9843..0000000 --- a/javascript/videojs/src/js/control-bar/volume-control/volume-level-tooltip.js +++ /dev/null @@ -1,135 +0,0 @@ -/** - * @file volume-level-tooltip.js - */ -import Component from '../../component'; -import * as Dom from '../../utils/dom.js'; -import * as Fn from '../../utils/fn.js'; - -/** @import Player from '../../player' */ - -/** - * Volume level tooltips display a volume above or side by side the volume bar. - * - * @extends Component - */ -class VolumeLevelTooltip extends Component { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The {@link Player} that this class should be attached to. - * - * @param {Object} [options] - * The key/value store of player options. - */ - constructor(player, options) { - super(player, options); - this.update = Fn.throttle(Fn.bind_(this, this.update), Fn.UPDATE_REFRESH_INTERVAL); - } - - /** - * Create the volume tooltip DOM element - * - * @return {Element} - * The element that was created. - */ - createEl() { - return super.createEl('div', { - className: 'vjs-volume-tooltip' - }, { - 'aria-hidden': 'true' - }); - } - - /** - * Updates the position of the tooltip relative to the `VolumeBar` and - * its content text. - * - * @param {Object} rangeBarRect - * The `ClientRect` for the {@link VolumeBar} element. - * - * @param {number} rangeBarPoint - * A number from 0 to 1, representing a horizontal/vertical reference point - * from the left edge of the {@link VolumeBar} - * - * @param {boolean} vertical - * Referees to the Volume control position - * in the control bar{@link VolumeControl} - * - */ - update(rangeBarRect, rangeBarPoint, vertical, content) { - if (!vertical) { - const tooltipRect = Dom.getBoundingClientRect(this.el_); - const playerRect = Dom.getBoundingClientRect(this.player_.el()); - const volumeBarPointPx = rangeBarRect.width * rangeBarPoint; - - if (!playerRect || !tooltipRect) { - return; - } - - const spaceLeftOfPoint = (rangeBarRect.left - playerRect.left) + volumeBarPointPx; - const spaceRightOfPoint = (rangeBarRect.width - volumeBarPointPx) + - (playerRect.right - rangeBarRect.right); - let pullTooltipBy = tooltipRect.width / 2; - - if (spaceLeftOfPoint < pullTooltipBy) { - pullTooltipBy += pullTooltipBy - spaceLeftOfPoint; - } else if (spaceRightOfPoint < pullTooltipBy) { - pullTooltipBy = spaceRightOfPoint; - } - - if (pullTooltipBy < 0) { - pullTooltipBy = 0; - } else if (pullTooltipBy > tooltipRect.width) { - pullTooltipBy = tooltipRect.width; - } - - this.el_.style.right = `-${pullTooltipBy}px`; - } - this.write(`${content}%`); - } - - /** - * Write the volume to the tooltip DOM element. - * - * @param {string} content - * The formatted volume for the tooltip. - */ - write(content) { - Dom.textContent(this.el_, content); - } - - /** - * Updates the position of the volume tooltip relative to the `VolumeBar`. - * - * @param {Object} rangeBarRect - * The `ClientRect` for the {@link VolumeBar} element. - * - * @param {number} rangeBarPoint - * A number from 0 to 1, representing a horizontal/vertical reference point - * from the left edge of the {@link VolumeBar} - * - * @param {boolean} vertical - * Referees to the Volume control position - * in the control bar{@link VolumeControl} - * - * @param {number} volume - * The volume level to update the tooltip to - * - * @param {Function} cb - * A function that will be called during the request animation frame - * for tooltips that need to do additional animations from the default - */ - updateVolume(rangeBarRect, rangeBarPoint, vertical, volume, cb) { - this.requestNamedAnimationFrame('VolumeLevelTooltip#updateVolume', () => { - this.update(rangeBarRect, rangeBarPoint, vertical, volume.toFixed(0)); - if (cb) { - cb(); - } - }); - } -} - -Component.registerComponent('VolumeLevelTooltip', VolumeLevelTooltip); -export default VolumeLevelTooltip; diff --git a/javascript/videojs/src/js/control-bar/volume-control/volume-level.js b/javascript/videojs/src/js/control-bar/volume-control/volume-level.js deleted file mode 100644 index f5de046..0000000 --- a/javascript/videojs/src/js/control-bar/volume-control/volume-level.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @file volume-level.js - */ -import Component from '../../component.js'; - -/** - * Shows volume level - * - * @extends Component - */ -class VolumeLevel extends Component { - - /** - * Create the `Component`'s DOM element - * - * @return {Element} - * The element that was created. - */ - createEl() { - const el = super.createEl('div', { - className: 'vjs-volume-level' - }); - - this.setIcon('circle', el); - - el.appendChild(super.createEl('span', { - className: 'vjs-control-text' - })); - - return el; - } - -} - -Component.registerComponent('VolumeLevel', VolumeLevel); -export default VolumeLevel; diff --git a/javascript/videojs/src/js/control-bar/volume-panel.js b/javascript/videojs/src/js/control-bar/volume-panel.js deleted file mode 100644 index 209b493..0000000 --- a/javascript/videojs/src/js/control-bar/volume-panel.js +++ /dev/null @@ -1,207 +0,0 @@ -/** - * @file volume-control.js - */ -import Component from '../component.js'; -import {isPlain} from '../utils/obj'; -import * as Events from '../utils/events.js'; -import document from 'global/document'; - -/** @import Player from './player' */ - -// Required children -import './volume-control/volume-control.js'; -import './mute-toggle.js'; - -/** - * A Component to contain the MuteToggle and VolumeControl so that - * they can work together. - * - * @extends Component - */ -class VolumePanel extends Component { - - /** - * Creates an instance of this class. - * - * @param {Player} player - * The `Player` that this class should be attached to. - * - * @param {Object} [options={}] - * The key/value store of player options. - */ - constructor(player, options = {}) { - if (typeof options.inline !== 'undefined') { - options.inline = options.inline; - } else { - options.inline = true; - } - - // pass the inline option down to the VolumeControl as vertical if - // the VolumeControl is on. - if (typeof options.volumeControl === 'undefined' || isPlain(options.volumeControl)) { - options.volumeControl = options.volumeControl || {}; - options.volumeControl.vertical = !options.inline; - } - - super(player, options); - - // this handler is used by mouse handler methods below - this.handleKeyPressHandler_ = (e) => this.handleKeyPress(e); - - this.on(player, ['loadstart'], (e) => this.volumePanelState_(e)); - this.on(this.muteToggle, 'keyup', (e) => this.handleKeyPress(e)); - this.on(this.volumeControl, 'keyup', (e) => this.handleVolumeControlKeyUp(e)); - this.on('keydown', (e) => this.handleKeyPress(e)); - this.on('mouseover', (e) => this.handleMouseOver(e)); - this.on('mouseout', (e) => this.handleMouseOut(e)); - - // while the slider is active (the mouse has been pressed down and - // is dragging) we do not want to hide the VolumeBar - this.on(this.volumeControl, ['slideractive'], this.sliderActive_); - - this.on(this.volumeControl, ['sliderinactive'], this.sliderInactive_); - } - - /** - * Add vjs-slider-active class to the VolumePanel - * - * @listens VolumeControl#slideractive - * @private - */ - sliderActive_() { - this.addClass('vjs-slider-active'); - } - - /** - * Removes vjs-slider-active class to the VolumePanel - * - * @listens VolumeControl#sliderinactive - * @private - */ - sliderInactive_() { - this.removeClass('vjs-slider-active'); - } - - /** - * Adds vjs-hidden or vjs-mute-toggle-only to the VolumePanel - * depending on MuteToggle and VolumeControl state - * - * @listens Player#loadstart - * @private - */ - volumePanelState_() { - // hide volume panel if neither volume control or mute toggle - // are displayed - if (this.volumeControl.hasClass('vjs-hidden') && this.muteToggle.hasClass('vjs-hidden')) { - this.addClass('vjs-hidden'); - } - - // if only mute toggle is visible we don't want - // volume panel expanding when hovered or active - if (this.volumeControl.hasClass('vjs-hidden') && !this.muteToggle.hasClass('vjs-hidden')) { - this.addClass('vjs-mute-toggle-only'); - } - } - - /** - * Create the `Component`'s DOM element - * - * @return {Element} - * The element that was created. - */ - createEl() { - let orientationClass = 'vjs-volume-panel-horizontal'; - - if (!this.options_.inline) { - orientationClass = 'vjs-volume-panel-vertical'; - } - - return super.createEl('div', { - className: `vjs-volume-panel vjs-control ${orientationClass}` - }); - } - - /** - * Dispose of the `volume-panel` and all child components. - */ - dispose() { - this.handleMouseOut(); - super.dispose(); - } - - /** - * Handles `keyup` events on the `VolumeControl`, looking for ESC, which closes - * the volume panel and sets focus on `MuteToggle`. - * - * @param {Event} event - * The `keyup` event that caused this function to be called. - * - * @listens keyup - */ - handleVolumeControlKeyUp(event) { - if (event.key === 'Escape') { - this.muteToggle.focus(); - } - } - - /** - * This gets called when a `VolumePanel` gains hover via a `mouseover` event. - * Turns on listening for `mouseover` event. When they happen it - * calls `this.handleMouseOver`. - * - * @param {Event} event - * The `mouseover` event that caused this function to be called. - * - * @listens mouseover - */ - handleMouseOver(event) { - this.addClass('vjs-hover'); - Events.on(document, 'keyup', this.handleKeyPressHandler_); - } - - /** - * This gets called when a `VolumePanel` gains hover via a `mouseout` event. - * Turns on listening for `mouseout` event. When they happen it - * calls `this.handleMouseOut`. - * - * @param {Event} event - * The `mouseout` event that caused this function to be called. - * - * @listens mouseout - */ - handleMouseOut(event) { - this.removeClass('vjs-hover'); - Events.off(document, 'keyup', this.handleKeyPressHandler_); - } - - /** - * Handles `keyup` event on the document or `keydown` event on the `VolumePanel`, - * looking for ESC, which hides the `VolumeControl`. - * - * @param {Event} event - * The keypress that triggered this event. - * - * @listens keydown | keyup - */ - handleKeyPress(event) { - if (event.key === 'Escape') { - this.handleMouseOut(); - } - } -} - -/** - * Default options for the `VolumeControl` - * - * @type {Object} - * @private - */ -VolumePanel.prototype.options_ = { - children: [ - 'muteToggle', - 'volumeControl' - ] -}; - -Component.registerComponent('VolumePanel', VolumePanel); -export default VolumePanel; |
