Comparar commits

...

15 Commits

Autor SHA1 Mensagem Data
brandonocasey a48c9a6c07 fix: a possible breaking change caused by the use of remainingTimeDisplay 2017-10-10 11:22:48 -04:00
TaeSoo 태수 6738f765da docs(hooks): Fix Typo (#4652) 2017-10-06 18:01:54 -07:00
Pat O'Neill 8ec61bbb20 6.3.2 2017-10-04 10:37:26 -04:00
Thijs Triemstra 85a34d1b49 docs: Document how to add a version number to a plugin (#4642) 2017-10-04 10:32:18 -04:00
Pat O'Neill 4658c7bad6 fix: Fix a typo in current time display component. (#4647) 2017-10-04 10:31:10 -04:00
Pat O'Neill 8878acc040 6.3.1 2017-10-03 13:11:27 -04:00
Pat O'Neill 20f7fe991f fix: Make sure time displays use correctly-formatted time. (#4643) 2017-10-03 12:52:58 -04:00
Pat O'Neill f0d9c240fe 6.3.0 2017-10-03 11:04:07 -04:00
Brandon Casey 445eb26722 feat: Add remainingTimeDisplay method to Player (#4620) 2017-10-02 16:29:40 -04:00
Thom 5ca0992cf1 chore(lang): Update Dutch (#4588) 2017-10-02 16:08:04 -04:00
ngoisaosang ac58dbf13a chore(lang): Update Vietnamese (#4625) 2017-10-02 16:04:57 -04:00
Alex Barstow 1ac8065ea6 feat: Do not set focus in sub-menus to prevent undesirable scrolling behavior in iOS (#4607) 2017-10-02 15:29:34 -04:00
Brandon Casey f51d36b053 feat: display currentTime as duration and remainingTime as 0 on ended (#4634) 2017-10-02 11:19:29 -04:00
Brandon Casey fa6f884409 refactor: Create a base time display class, and use it (#4633) 2017-10-02 10:58:30 -04:00
Brandon Casey 335bcded98 fix: reset to a play/pause button when seeking after ended (#4614) 2017-09-20 13:45:47 -04:00
14 arquivos alterados com 483 adições e 171 exclusões
+48
Ver Arquivo
@@ -1,3 +1,51 @@
<a name="6.3.2"></a>
## [6.3.2](https://github.com/videojs/video.js/compare/v6.3.1...v6.3.2) (2017-10-04)
### Bug Fixes
* Fix a typo in current time display component. ([#4647](https://github.com/videojs/video.js/issues/4647)) ([4658c7b](https://github.com/videojs/video.js/commit/4658c7b))
### Documentation
* Document how to add a version number to a plugin ([#4642](https://github.com/videojs/video.js/issues/4642)) ([85a34d1](https://github.com/videojs/video.js/commit/85a34d1))
<a name="6.3.1"></a>
## [6.3.1](https://github.com/videojs/video.js/compare/v6.3.0...v6.3.1) (2017-10-03)
### Bug Fixes
* Make sure time displays use correctly-formatted time. ([#4643](https://github.com/videojs/video.js/issues/4643)) ([20f7fe9](https://github.com/videojs/video.js/commit/20f7fe9))
<a name="6.3.0"></a>
# [6.3.0](https://github.com/videojs/video.js/compare/v6.2.8...v6.3.0) (2017-10-03)
### Features
* Add remainingTimeDisplay method to Player ([#4620](https://github.com/videojs/video.js/issues/4620)) ([445eb26](https://github.com/videojs/video.js/commit/445eb26))
* display currentTime as duration and remainingTime as 0 on ended ([#4634](https://github.com/videojs/video.js/issues/4634)) ([f51d36b](https://github.com/videojs/video.js/commit/f51d36b))
* Do not set focus in sub-menus to prevent undesirable scrolling behavior in iOS ([#4607](https://github.com/videojs/video.js/issues/4607)) ([1ac8065](https://github.com/videojs/video.js/commit/1ac8065))
### Bug Fixes
* reset to a play/pause button when seeking after ended ([#4614](https://github.com/videojs/video.js/issues/4614)) ([335bcde](https://github.com/videojs/video.js/commit/335bcde))
### Chores
* alias rollup-dev to watch for development ([#4615](https://github.com/videojs/video.js/issues/4615)) ([edde614](https://github.com/videojs/video.js/commit/edde614))
* **lang:** Update Dutch ([#4588](https://github.com/videojs/video.js/issues/4588)) ([5ca0992](https://github.com/videojs/video.js/commit/5ca0992))
* **lang:** Update Vietnamese ([#4625](https://github.com/videojs/video.js/issues/4625)) ([ac58dbf](https://github.com/videojs/video.js/commit/ac58dbf))
* **package:** update grunt-browserify to version 5.2.0 ([#4578](https://github.com/videojs/video.js/issues/4578)) ([6cd785a](https://github.com/videojs/video.js/commit/6cd785a))
* **package:** update remark-validate-links to version 7.0.0 ([#4585](https://github.com/videojs/video.js/issues/4585)) ([7929677](https://github.com/videojs/video.js/commit/7929677))
### Code Refactoring
* Create a base time display class, and use it ([#4633](https://github.com/videojs/video.js/issues/4633)) ([fa6f884](https://github.com/videojs/video.js/commit/fa6f884))
### Documentation
* Document playbackRates ([#4602](https://github.com/videojs/video.js/issues/4602)) ([9d249bb](https://github.com/videojs/video.js/commit/9d249bb))
* update player reference in advanced plugins doc ([#4622](https://github.com/videojs/video.js/issues/4622)) ([d8ea23e](https://github.com/videojs/video.js/commit/d8ea23e))
<a name="6.2.8"></a>
## [6.2.8](https://github.com/videojs/video.js/compare/v6.2.7...v6.2.8) (2017-09-01)
+1 -1
Ver Arquivo
@@ -14,7 +14,7 @@ Hooks exist so that users can "hook" on to certain Video.js player lifecycle
## Current Hooks
Currently, the following hooks are avialable:
Currently, the following hooks are available:
### beforesetup
+19
Ver Arquivo
@@ -225,6 +225,25 @@ The `dispose` method has several effects:
In addition, if the player is disposed, the disposal of all its advanced plugin instances will be triggered as well.
#### Version
Adding a version number to a plugin is done by defining a `VERSION` property on the plugin before registering it:
```js
ExamplePlugin.VERSION = '1.0.1';
videojs.registerPlugin('examplePlugin', ExamplePlugin);
```
Retrieve it using `videojs.getPluginVersion`:
```js
var version = videojs.getPluginVersion('examplePlugin');
console.log(version); // 1.0.1
```
Note that the [plugin generator](https://github.com/videojs/generator-videojs-plugin) already takes care of adding a version number for you.
### Advanced Example Advanced Plugin
What follows is a complete ES6 advanced plugin that logs a custom message when the player's state changes between playing and paused. It uses all the described advanced features:
+68 -21
Ver Arquivo
@@ -1,37 +1,84 @@
{
"Audio Player": "Audiospeler",
"Video Player": "Videospeler",
"Play": "Afspelen",
"Pause": "Pauze",
"Pause": "Pauzeren",
"Replay": "Opnieuw afspelen",
"Current Time": "Huidige tijd",
"Duration Time": "Looptijd",
"Duration Time": "Tijdsduur",
"Remaining Time": "Resterende tijd",
"Stream Type": "Streamtype",
"LIVE": "LIVE",
"Loaded": "Geladen",
"Progress": "Status",
"Progress": "Voortgang",
"Progress Bar": "Voortgangsbalk",
"progress bar timing: currentTime={1} duration={2}": "{1} van {2}",
"Fullscreen": "Volledig scherm",
"Non-Fullscreen": "Geen volledig scherm",
"Mute": "Geluid uit",
"Unmute": "Geluid aan",
"Playback Rate": "Weergavesnelheid",
"Mute": "Dempen",
"Unmute": "Niet dempen",
"Playback Rate": "Afspeelsnelheid",
"Subtitles": "Ondertiteling",
"subtitles off": "ondertiteling uit",
"Captions": "Bijschriften",
"captions off": "bijschriften uit",
"Chapters": "Hoofdstukken",
"Descriptions": "Beschrijvingen",
"descriptions off": "beschrijvingen off",
"You aborted the media playback": "U hebt de mediaweergave afgebroken.",
"A network error caused the media download to fail part-way.": "De mediadownload is mislukt door een netwerkfout.",
"The media could not be loaded, either because the server or network failed or because the format is not supported.": "De media kon niet worden geladen, vanwege een server- of netwerkfout of doordat het formaat niet wordt ondersteund.",
"The media playback was aborted due to a corruption problem or because the media used features your browser did not support.": "De mediaweergave is afgebroken vanwege beschadigde data of het mediabestand gebruikt functies die niet door uw browser worden ondersteund.",
"No compatible source was found for this media.": "Voor deze media is geen ondersteunde bron gevonden.",
"Play Video": "Video Afspelen",
"descriptions off": "beschrijvingen uit",
"Audio Track": "Audiospoor",
"Volume Level": "Geluidsniveau",
"You aborted the media playback": "U heeft het afspelen van de media afgebroken",
"A network error caused the media download to fail part-way.": "Een netwerkfout heeft ervoor gezorgd dat het downloaden van de media halverwege is mislukt.",
"The media could not be loaded, either because the server or network failed or because the format is not supported.": "De media kon niet worden geladen, dit komt doordat of de server of het netwerk mislukt of doordat het formaat niet wordt ondersteund.",
"The media playback was aborted due to a corruption problem or because the media used features your browser did not support.": "Het afspelen van de media is afgebroken door een probleem met beschadeigde gegevens of doordat de media functies gebruikt die uw browser niet ondersteund.",
"No compatible source was found for this media.": "Er is geen geschikte bron voor deze media gevonden.",
"The media is encrypted and we do not have the keys to decrypt it.": "De media is versleuteld en we hebben de sleutels niet om deze te ontsleutelen.",
"Play Video": "Video afspelen",
"Close": "Sluiten",
"Modal Window": "Modal Venster",
"This is a modal window": "Dit is een modaal venster",
"This modal can be closed by pressing the Escape key or activating the close button.": "Dit modaal venster kan gesloten worden door op Escape te drukken of de 'sluiten' knop te activeren.",
", opens captions settings dialog": ", opent bijschriften instellingen venster",
", opens subtitles settings dialog": ", opent ondertiteling instellingen venster",
", opens descriptions settings dialog": ", opent beschrijvingen instellingen venster",
", selected": ", selected"
}
"Close Modal Dialog": "Extra venster sluiten",
"Modal Window": "Extra venster",
"This is a modal window": "Dit is een extra venster",
"This modal can be closed by pressing the Escape key or activating the close button.": "Dit venster kan worden gesloten door op de Escape-toets te drukken of door de sluiten-knop te activeren.",
", opens captions settings dialog": ", opent instellingen-venster voor bijschriften",
", opens subtitles settings dialog": ", opent instellingen-venster voor ondertitelingen",
", opens descriptions settings dialog": ", opent instellingen-venster voor beschrijvingen",
", selected": ", geselecteerd",
"captions settings": "bijschriften-instellingen",
"subtitles settings": "ondertiteling-instellingen",
"descriptions settings": "beschrijvingen-instellingen",
"Text": "Tekst",
"White": "Wit",
"Black": "Zwart",
"Red": "Rood",
"Green": "Groen",
"Blue": "Blauw",
"Yellow": "Geel",
"Magenta": "Magenta",
"Cyan": "Cyaan",
"Background": "Achtergrond",
"Window": "Venster",
"Transparent": "Transparant",
"Semi-Transparent": "Semi-transparant",
"Opaque": "Ondoorzichtig",
"Font Size": "Lettergrootte",
"Text Edge Style": "Stijl tekstrand",
"None": "Geen",
"Raised": "Verhoogd",
"Depressed": "Ingedrukt",
"Uniform": "Uniform",
"Dropshadow": "Schaduw",
"Font Family": "Lettertype",
"Proportional Sans-Serif": "Proportioneel sans-serif",
"Monospace Sans-Serif": "Monospace sans-serif",
"Proportional Serif": "Proportioneel serif",
"Monospace Serif": "Monospace serif",
"Casual": "Luchtig",
"Script": "Script",
"Small Caps": "Kleine hoofdletters",
"Reset": "Herstellen",
"restore all settings to the default values": "alle instellingen naar de standaardwaarden herstellen",
"Done": "Klaar",
"Caption Settings Dialog": "Venster voor bijschriften-instellingen",
"Beginning of dialog window. Escape will cancel and close the window.": "Begin van dialoogvenster. Escape zal annuleren en het venster sluiten.",
"End of dialog window.": "Einde van dialoogvenster."
}
+51 -8
Ver Arquivo
@@ -1,4 +1,6 @@
{
"Audio Player": "Trình phát Audio",
"Video Player": "Trình phát Video",
"Play": "Phát",
"Pause": "Tạm dừng",
"Replay": "Phát lại",
@@ -9,6 +11,8 @@
"LIVE": "TRỰC TIẾP",
"Loaded": "Đã tải",
"Progress": "Tiến trình",
"Progress Bar": "Thanh tiến trình",
"progress bar timing: currentTime={1} duration={2}": "{1} của {2}",
"Fullscreen": "Toàn màn hình",
"Non-Fullscreen": "Thoát toàn màn hình",
"Mute": "Tắt tiếng",
@@ -19,23 +23,62 @@
"Captions": "Chú thích",
"captions off": "tắt chú thích",
"Chapters": "Chương",
"Close Modal Dialog": "Đóng hộp thoại",
"Descriptions": "Mô tả",
"descriptions off": "tắt mô tả",
"Audio Track": "Track âm thanh",
"Volume Level": "Mức âm lượng",
"You aborted the media playback": "Bạn đã hủy việc phát lại media.",
"A network error caused the media download to fail part-way.": "Một lỗi mạng dẫn đến việc tải media bị lỗi.",
"The media could not be loaded, either because the server or network failed or because the format is not supported.": "Video không tải được, mạng hay server có lỗi hoặc định dạng không được hỗ trợ.",
"The media playback was aborted due to a corruption problem or because the media used features your browser did not support.": "Phát media đã bị hủy do một sai lỗi hoặc media sử dụng những tính năng trình duyệt không hỗ trợ.",
"No compatible source was found for this media.": "Không có nguồn tương thích cho media này.",
"The media is encrypted and we do not have the keys to decrypt it.": "Media đã được mã hóa và chúng tôi không thể giải mã nó.",
"The media is encrypted and we do not have the keys to decrypt it.": "Media đã được mã hóa và chúng tôi không có để giải mã nó.",
"Play Video": "Phát Video",
"Close": "Đóng",
"Close Modal Dialog": "Đóng cửa sổ",
"Modal Window": "Cửa sổ",
"This is a modal window": "Đây là một cửa sổ",
"This modal can be closed by pressing the Escape key or activating the close button.": "Cửa sổ này có thể đóng lại bằng việc nhấn phím Esc hoặc kích hoạt nút đóng.",
", opens captions settings dialog": ", mở hộp thoại thiết lập chú thích",
", opens subtitles settings dialog": ", mở hộp thoại thiết lập phụ đề",
", opens descriptions settings dialog": ", mở hộp thoại thiết lập mô tả",
", selected": ", đã chọn"
}
"This modal can be closed by pressing the Escape key or activating the close button.": "Cửa sổ này có thể thoát bằng việc nhấn phím Esc hoặc kích hoạt nút đóng.",
", opens captions settings dialog": ", mở hộp thoại cài đặt chú thích",
", opens subtitles settings dialog": ", mở hộp thoại cài đặt phụ đề",
", opens descriptions settings dialog": ", mở hộp thoại cài đặt mô tả",
", selected": ", đã chọn",
"captions settings": "cài đặt chú thích",
"subtitles settings": "cài đặt phụ đề",
"descriptions settings": "cài đặt mô tả",
"Text": "Văn bản",
"White": "Trắng",
"Black": "Đen",
"Red": "Đỏ",
"Green": "Xanh lá cây",
"Blue": "Xanh da trời",
"Yellow": "Vàng",
"Magenta": "Đỏ tươi",
"Cyan": "Lam",
"Background": "Nền",
"Window": "Cửa sổ",
"Transparent": "Trong suốt",
"Semi-Transparent": "Bán trong suốt",
"Opaque": "Mờ",
"Font Size": "Kích cỡ phông chữ",
"Text Edge Style": "Dạng viền văn bản",
"None": "None",
"Raised": "Raised",
"Depressed": "Depressed",
"Uniform": "Uniform",
"Dropshadow": "Dropshadow",
"Font Family": "Phông chữ",
"Proportional Sans-Serif": "Proportional Sans-Serif",
"Monospace Sans-Serif": "Monospace Sans-Serif",
"Proportional Serif": "Proportional Serif",
"Monospace Serif": "Monospace Serif",
"Casual": "Casual",
"Script": "Script",
"Small Caps": "Small Caps",
"Reset": "Đặt lại",
"restore all settings to the default values": "khôi phục lại tất cả các cài đặt về giá trị mặc định",
"Done": "Xong",
"Caption Settings Dialog": "Hộp thoại cài đặt chú thích",
"Beginning of dialog window. Escape will cancel and close the window.": "Bắt đầu cửa sổ hộp thoại. Esc sẽ thoát và đóng cửa sổ.",
"End of dialog window.": "Kết thúc cửa sổ hộp thoại."
}
+1 -1
Ver Arquivo
@@ -1,7 +1,7 @@
{
"name": "video.js",
"description": "An HTML5 and Flash video player with a common API and skin for both.",
"version": "6.2.8",
"version": "6.3.2",
"main": "./dist/video.cjs.js",
"style": "./dist/video-js.css",
"copyright": "Copyright Brightcove, Inc. <https://www.brightcove.com/>",
+27 -1
Ver Arquivo
@@ -57,6 +57,26 @@ class PlayToggle extends Button {
}
}
/**
* 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 {EventTarget~Event} [event]
* The event that caused this function to run.
*
* @listens Player#seeked
*/
handleSeeked(event) {
// remove the ended class
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.
*
@@ -66,7 +86,6 @@ class PlayToggle extends Button {
* @listens Player#play
*/
handlePlay(event) {
this.removeClass('vjs-ended');
this.removeClass('vjs-paused');
this.addClass('vjs-playing');
// change the button text to "Pause"
@@ -91,12 +110,19 @@ class PlayToggle extends Button {
/**
* Add the vjs-ended class to the element so it can change appearance
*
* @param {EventTarget~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.controlText('Replay');
// on the next seek remove the replay button
this.one(this.player_, 'seeked', this.handleSeeked);
}
}
@@ -1,18 +1,15 @@
/**
* @file current-time-display.js
*/
import document from 'global/document';
import TimeDisplay from './time-display';
import Component from '../../component.js';
import * as Dom from '../../utils/dom.js';
import {bind, throttle} from '../../utils/fn.js';
import formatTime from '../../utils/format-time.js';
/**
* Displays the current time
*
* @extends Component
*/
class CurrentTimeDisplay extends Component {
class CurrentTimeDisplay extends TimeDisplay {
/**
* Creates an instance of this class.
@@ -25,48 +22,17 @@ class CurrentTimeDisplay extends Component {
*/
constructor(player, options) {
super(player, options);
this.throttledUpdateContent = throttle(bind(this, this.updateContent), 25);
this.on(player, 'timeupdate', this.throttledUpdateContent);
this.on(player, 'ended', this.handleEnded);
}
/**
* Create the `Component`'s DOM element
* Builds the default DOM `className`.
*
* @return {Element}
* The element that was created.
* @return {string}
* The DOM `className` for this object.
*/
createEl() {
const el = super.createEl('div', {
className: 'vjs-current-time vjs-time-control vjs-control'
});
this.contentEl_ = Dom.createEl('div', {
className: 'vjs-current-time-display'
}, {
// tell screen readers not to automatically read the time as it changes
'aria-live': 'off'
}, Dom.createEl('span', {
className: 'vjs-control-text',
textContent: this.localize('Current Time')
}));
this.updateTextNode_();
el.appendChild(this.contentEl_);
return el;
}
/**
* Updates the "current time" text node with new content using the
* contents of the `formattedTime_` property.
*
* @private
*/
updateTextNode_() {
if (this.textNode_) {
this.contentEl_.removeChild(this.textNode_);
}
this.textNode_ = document.createTextNode(` ${this.formattedTime_ || '0:00'}`);
this.contentEl_.appendChild(this.textNode_);
buildCSSClass() {
return 'vjs-current-time';
}
/**
@@ -80,15 +46,36 @@ class CurrentTimeDisplay extends Component {
updateContent(event) {
// Allows for smooth scrubbing, when player can't keep up.
const time = (this.player_.scrubbing()) ? this.player_.getCache().currentTime : this.player_.currentTime();
const formattedTime = formatTime(time, this.player_.duration());
if (formattedTime !== this.formattedTime_) {
this.formattedTime_ = formattedTime;
this.requestAnimationFrame(this.updateTextNode_);
this.updateFormattedTime_(time);
}
/**
* When the player fires ended there should be no time left. Sadly
* this is not always the case, lets make it seem like that is the case
* for users.
*
* @param {EventTarget~Event} [event]
* The `ended` event that caused this to run.
*
* @listens Player#ended
*/
handleEnded(event) {
if (!this.player_.duration()) {
return;
}
this.updateFormattedTime_(this.player_.duration());
}
}
/**
* The text that should display over the `CurrentTimeDisplay`s controls. Added to for localization.
*
* @type {string}
* @private
*/
CurrentTimeDisplay.prototype.controlText_ = 'Current Time';
Component.registerComponent('CurrentTimeDisplay', CurrentTimeDisplay);
export default CurrentTimeDisplay;
@@ -1,18 +1,15 @@
/**
* @file duration-display.js
*/
import document from 'global/document';
import TimeDisplay from './time-display';
import Component from '../../component.js';
import * as Dom from '../../utils/dom.js';
import {bind, throttle} from '../../utils/fn.js';
import formatTime from '../../utils/format-time.js';
/**
* Displays the duration
*
* @extends Component
*/
class DurationDisplay extends Component {
class DurationDisplay extends TimeDisplay {
/**
* Creates an instance of this class.
@@ -26,57 +23,24 @@ class DurationDisplay extends Component {
constructor(player, options) {
super(player, options);
this.throttledUpdateContent = throttle(bind(this, this.updateContent), 25);
this.on(player, [
'durationchange',
// Also listen for timeupdate and loadedmetadata because removing those
// 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.
'loadedmetadata',
'timeupdate'
'loadedmetadata'
], this.throttledUpdateContent);
}
/**
* Create the `Component`'s DOM element
* Builds the default DOM `className`.
*
* @return {Element}
* The element that was created.
* @return {string}
* The DOM `className` for this object.
*/
createEl() {
const el = super.createEl('div', {
className: 'vjs-duration vjs-time-control vjs-control'
});
this.contentEl_ = Dom.createEl('div', {
className: 'vjs-duration-display'
}, {
// tell screen readers not to automatically read the time as it changes
'aria-live': 'off'
}, Dom.createEl('span', {
className: 'vjs-control-text',
textContent: this.localize('Duration Time')
}));
this.updateTextNode_();
el.appendChild(this.contentEl_);
return el;
}
/**
* Updates the "current time" text node with new content using the
* contents of the `formattedTime_` property.
*
* @private
*/
updateTextNode_() {
if (this.textNode_) {
this.contentEl_.removeChild(this.textNode_);
}
this.textNode_ = document.createTextNode(` ${this.formattedTime_ || '0:00'}`);
this.contentEl_.appendChild(this.textNode_);
buildCSSClass() {
return 'vjs-duration';
}
/**
@@ -95,11 +59,18 @@ class DurationDisplay extends Component {
if (duration && this.duration_ !== duration) {
this.duration_ = duration;
this.formattedTime_ = formatTime(duration);
this.requestAnimationFrame(this.updateTextNode_);
this.updateFormattedTime_(duration);
}
}
}
/**
* The text that should display over the `DurationDisplay`s controls. Added to for localization.
*
* @type {string}
* @private
*/
DurationDisplay.prototype.controlText_ = 'Duration Time';
Component.registerComponent('DurationDisplay', DurationDisplay);
export default DurationDisplay;
@@ -1,18 +1,14 @@
/**
* @file remaining-time-display.js
*/
import document from 'global/document';
import TimeDisplay from './time-display';
import Component from '../../component.js';
import * as Dom from '../../utils/dom.js';
import {bind, throttle} from '../../utils/fn.js';
import formatTime from '../../utils/format-time.js';
/**
* Displays the time left in the video
*
* @extends Component
*/
class RemainingTimeDisplay extends Component {
class RemainingTimeDisplay extends TimeDisplay {
/**
* Creates an instance of this class.
@@ -25,48 +21,33 @@ class RemainingTimeDisplay extends Component {
*/
constructor(player, options) {
super(player, options);
this.throttledUpdateContent = throttle(bind(this, this.updateContent), 25);
this.on(player, ['timeupdate', 'durationchange'], this.throttledUpdateContent);
this.on(player, 'durationchange', this.throttledUpdateContent);
this.on(player, 'ended', this.handleEnded);
}
/**
* Create the `Component`'s DOM element
* Builds the default DOM `className`.
*
* @return {Element}
* The element that was created.
* @return {string}
* The DOM `className` for this object.
*/
createEl() {
const el = super.createEl('div', {
className: 'vjs-remaining-time vjs-time-control vjs-control'
});
this.contentEl_ = Dom.createEl('div', {
className: 'vjs-remaining-time-display'
}, {
// tell screen readers not to automatically read the time as it changes
'aria-live': 'off'
}, Dom.createEl('span', {
className: 'vjs-control-text',
textContent: this.localize('Remaining Time')
}));
this.updateTextNode_();
el.appendChild(this.contentEl_);
return el;
buildCSSClass() {
return 'vjs-remaining-time';
}
/**
* Updates the "remaining time" text node with new content using the
* contents of the `formattedTime_` property.
* The remaining time display prefixes numbers with a "minus" character.
*
* @param {number} time
* A numeric time, in seconds.
*
* @return {string}
* A formatted time
*
* @private
*/
updateTextNode_() {
if (this.textNode_) {
this.contentEl_.removeChild(this.textNode_);
}
this.textNode_ = document.createTextNode(` -${this.formattedTime_ || '0:00'}`);
this.contentEl_.appendChild(this.textNode_);
formatTime_(time) {
return '-' + super.formatTime_(time);
}
/**
@@ -79,16 +60,44 @@ class RemainingTimeDisplay extends Component {
* @listens Player#durationchange
*/
updateContent(event) {
if (this.player_.duration()) {
const formattedTime = formatTime(this.player_.remainingTime());
if (formattedTime !== this.formattedTime_) {
this.formattedTime_ = formattedTime;
this.requestAnimationFrame(this.updateTextNode_);
}
if (!this.player_.duration()) {
return;
}
// @deprecated We should only use remainingTimeDisplay
// as of video.js 7
if (this.player_.remainingTimeDisplay) {
this.updateFormattedTime_(this.player_.remainingTimeDisplay());
} else {
this.updateFormattedTime_(this.player_.remainingTime());
}
}
/**
* When the player fires ended there should be no time left. Sadly
* this is not always the case, lets make it seem like that is the case
* for users.
*
* @param {EventTarget~Event} [event]
* The `ended` event that caused this to run.
*
* @listens Player#ended
*/
handleEnded(event) {
if (!this.player_.duration()) {
return;
}
this.updateFormattedTime_(0);
}
}
/**
* The text that should display over the `RemainingTimeDisplay`s controls. Added to for localization.
*
* @type {string}
* @private
*/
RemainingTimeDisplay.prototype.controlText_ = 'Remaining Time';
Component.registerComponent('RemainingTimeDisplay', RemainingTimeDisplay);
export default RemainingTimeDisplay;
@@ -0,0 +1,129 @@
/**
* @file time-display.js
*/
import document from 'global/document';
import Component from '../../component.js';
import * as Dom from '../../utils/dom.js';
import {bind, throttle} from '../../utils/fn.js';
import formatTime from '../../utils/format-time.js';
/**
* Displays the time left in 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.throttledUpdateContent = throttle(bind(this, this.updateContent), 25);
this.on(player, 'timeupdate', this.throttledUpdateContent);
}
/**
* Create the `Component`'s DOM element
*
* @return {Element}
* The element that was created.
*/
createEl(plainName) {
const className = this.buildCSSClass();
const el = super.createEl('div', {
className: `${className} vjs-time-control vjs-control`
});
this.contentEl_ = Dom.createEl('div', {
className: `${className}-display`
}, {
// tell screen readers not to automatically read the time as it changes
'aria-live': 'off'
}, Dom.createEl('span', {
className: 'vjs-control-text',
textContent: this.localize(this.contentText_)
}));
this.updateTextNode_();
el.appendChild(this.contentEl_);
return el;
}
/**
* Updates the "remaining time" text node with new content using the
* contents of the `formattedTime_` property.
*
* @private
*/
updateTextNode_() {
if (this.textNode_) {
this.contentEl_.removeChild(this.textNode_);
}
this.textNode_ = document.createTextNode(this.formattedTime_ || '0:00');
this.contentEl_.appendChild(this.textNode_);
}
/**
* Generates a formatted time for this component to use in display.
*
* @param {number} time
* A numeric time, in seconds.
*
* @return {string}
* A formatted time
*
* @private
*/
formatTime_(time) {
return formatTime(time);
}
/**
* Updates the time display text node if it has what was passed in changed
* the formatted time.
*
* @param {number} time
* The time to update to
*
* @private
*/
updateFormattedTime_(time) {
const formattedTime = this.formatTime_(time);
if (formattedTime === this.formattedTime_) {
return;
}
this.formattedTime_ = formattedTime;
this.requestAnimationFrame(this.updateTextNode_);
}
/**
* 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 {EventTarget~Event} [event]
* The `timeupdate` event that caused this to run.
*
* @listens Player#timeupdate
*/
updateContent(event) {}
}
/**
* The text that should display over the `TimeDisplay`s controls. Added to for localization.
*
* @type {string}
* @private
*/
TimeDisplay.prototype.controlText_ = 'Time';
Component.registerComponent('TimeDisplay', TimeDisplay);
export default TimeDisplay;
+7 -2
Ver Arquivo
@@ -8,6 +8,7 @@ import * as Dom from '../utils/dom.js';
import * as Fn from '../utils/fn.js';
import * as Events from '../utils/events.js';
import toTitleCase from '../utils/to-title-case.js';
import { IS_IOS } from '../utils/browser.js';
import document from 'global/document';
/**
@@ -339,8 +340,12 @@ class MenuButton extends Component {
this.buttonPressed_ = true;
this.menu.lockShowing();
this.menuButton_.el_.setAttribute('aria-expanded', 'true');
// set the focus into the submenu
this.menu.focus();
// set the focus into the submenu, except on iOS where it is resulting in
// undesired scrolling behavior when the player is in an iframe
if (!IS_IOS && !Dom.isInFrame()) {
this.menu.focus();
}
}
}
+11
Ver Arquivo
@@ -1787,6 +1787,17 @@ class Player extends Component {
return this.duration() - this.currentTime();
}
/**
* A remaining time function that is intented to be used when
* the time is to be displayed directly to the user.
*
* @return {number}
* The rounded time remaining in seconds
*/
remainingTimeDisplay() {
return Math.floor(this.duration()) - Math.floor(this.currentTime());
}
//
// Kind of like an array of portions of the video that have been downloaded.
+17
Ver Arquivo
@@ -85,6 +85,23 @@ export function isEl(value) {
return isObject(value) && value.nodeType === 1;
}
/**
* Determines if the current DOM is embedded in an iframe.
*
* @return {boolean}
*
*/
export function isInFrame() {
// We need a try/catch here because Safari will throw errors when attempting
// to get either `parent` or `self`
try {
return window.parent !== window.self;
} catch (x) {
return true;
}
}
/**
* Creates functions to query the DOM using a given method.
*