Comparar commits
1 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 94cd59dfea |
@@ -13,8 +13,6 @@ notifications:
|
||||
on_success: never
|
||||
webhooks:
|
||||
- http://pam.videojs.com/savage/travis
|
||||
slack:
|
||||
secure: LrF8K6mCYWlUt6SvdbGHazyQZSk/opKoiB/wgoGYaGc9+3wYXkVexY0WkO1m6wBKhUqXRAMVMFszr1wqKgdcxtItmFMMj8HqTLI1MVqgKqYX4Ux3CnEHJQiwxIk0aVL7lHLsZTXV/2Y0QIOYmAnCrgy46klETrk0ZuXf5okpu2Q=
|
||||
env:
|
||||
global:
|
||||
- secure: K6JpKwMkfNaJix3Bb0tLjVMzHMJgtBXdd/dvfw1BMb9DCBpd81PqXbDs7yXCddUxnUPTBPxZCrQgWsw71Wn+qEoIG5MU3uOT5A2rBbx/yZonVAGv5ed/9w0xk0OzO383CmPMFqwqtp9YmdmqGjQBkYXVXJjTvNTOAExFSdhO+3U=
|
||||
|
||||
+3
-101
@@ -1,107 +1,9 @@
|
||||
<a name="5.20.4"></a>
|
||||
## [5.20.4](https://github.com/videojs/video.js/compare/v5.20.3...v5.20.4) (2017-10-02)
|
||||
<a name="5.18.2"></a>
|
||||
## [5.18.2](https://github.com/videojs/video.js/compare/v5.18.1...v5.18.2) (2017-03-03)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Make boolean attributes set and check both the associated property and the attribute ([#4631](https://github.com/videojs/video.js/issues/4631)) ([0f8de52](https://github.com/videojs/video.js/commit/0f8de52)), closes [#4351](https://github.com/videojs/video.js/issues/4351)
|
||||
|
||||
<a name="5.20.3"></a>
|
||||
## [5.20.3](https://github.com/videojs/video.js/compare/v5.20.2...v5.20.3) (2017-08-16)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* tracks are disabled and cuepoints are cleared in iOS native player ([#4569](https://github.com/videojs/video.js/issues/4569)) ([424d021](https://github.com/videojs/video.js/commit/424d021))
|
||||
|
||||
### Chores
|
||||
|
||||
* **CHANGELOG:** update CHANGELOG for 5.20.2 ([#4529](https://github.com/videojs/video.js/issues/4529)) ([935ec1e](https://github.com/videojs/video.js/commit/935ec1e))
|
||||
|
||||
<a name="5.20.2"></a>
|
||||
## [5.20.2](https://github.com/videojs/video.js/compare/v5.20.1...v5.20.2) (2017-07-26)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* adjust volume ranges so muted(true) and vol=0 do not use the same icons ([#4425](https://github.com/videojs/video.js/issues/4425)) ([b314268](https://github.com/videojs/video.js/commit/b314268))
|
||||
* only change focus from BPB if not a mouse click ([#4523](https://github.com/videojs/video.js/issues/4523)) ([d90c945](https://github.com/videojs/video.js/commit/d90c945))
|
||||
* Only update text track mode if changed ([#4368](https://github.com/videojs/video.js/issues/4368)) ([a1763dc](https://github.com/videojs/video.js/commit/a1763dc))
|
||||
* player.duration() should return NaN if duration is not known ([#4456](https://github.com/videojs/video.js/issues/4456)) ([2576eda](https://github.com/videojs/video.js/commit/2576eda))
|
||||
* Safari picture-in-picture triggers fullscreenchange ([#4442](https://github.com/videojs/video.js/issues/4442)) ([c17c003](https://github.com/videojs/video.js/commit/c17c003))
|
||||
* Use passive event listeners for touchstart/touchmove ([#4445](https://github.com/videojs/video.js/issues/4445)) ([8599c8e](https://github.com/videojs/video.js/commit/8599c8e)), closes [#4432](https://github.com/videojs/video.js/issues/4432)
|
||||
|
||||
### Chores
|
||||
|
||||
* add a release script to makes things easier ([#4517](https://github.com/videojs/video.js/issues/4517)) ([9ca9989](https://github.com/videojs/video.js/commit/9ca9989))
|
||||
* move imports up so bundlers wont trip up ([#4363](https://github.com/videojs/video.js/issues/4363)) ([0d725df](https://github.com/videojs/video.js/commit/0d725df))
|
||||
* **package:** update to swf 5.4.1 ([#4516](https://github.com/videojs/video.js/issues/4516)) ([a145dd2](https://github.com/videojs/video.js/commit/a145dd2))
|
||||
* **package:** update videojs-vtt.js to 0.12.4 ([#4364](https://github.com/videojs/video.js/issues/4364)) ([3f7e215](https://github.com/videojs/video.js/commit/3f7e215))
|
||||
|
||||
<a name="5.20.1"></a>
|
||||
## [5.20.1](https://github.com/videojs/video.js/compare/v5.20.0...v5.20.1) (2017-05-15)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* only disable user-selection on sliders ([#4355](https://github.com/videojs/video.js/issues/4355)) ([0d60720](https://github.com/videojs/video.js/commit/0d60720))
|
||||
* prevent dupe events on enabled ClickableComponents ([#4357](https://github.com/videojs/video.js/issues/4357)) ([3faea9f](https://github.com/videojs/video.js/commit/3faea9f))
|
||||
|
||||
<a name="5.20.0"></a>
|
||||
# [5.20.0](https://github.com/videojs/video.js/compare/v5.19.2...v5.20.0) (2017-05-11)
|
||||
|
||||
### Features
|
||||
|
||||
* add 'playsinline' player option ([#4325](https://github.com/videojs/video.js/issues/4325)) ([946f84b](https://github.com/videojs/video.js/commit/946f84b))
|
||||
* Add a version class to the player ([#4335](https://github.com/videojs/video.js/issues/4335)) ([b855bfb](https://github.com/videojs/video.js/commit/b855bfb))
|
||||
* Add getVideoPlaybackQuality API ([#4286](https://github.com/videojs/video.js/issues/4286)) ([c970474](https://github.com/videojs/video.js/commit/c970474))
|
||||
* remove playbackRate blacklist for recent Android Chrome ([#4336](https://github.com/videojs/video.js/issues/4336)) ([3fe22e9](https://github.com/videojs/video.js/commit/3fe22e9))
|
||||
|
||||
### Chores
|
||||
|
||||
* add slack travis notifications ([#4339](https://github.com/videojs/video.js/issues/4339)) ([ab110ff](https://github.com/videojs/video.js/commit/ab110ff))
|
||||
* **package:** pin karma to 1.3.0 for IE8 support ([#4340](https://github.com/videojs/video.js/issues/4340)) ([6cf7327](https://github.com/videojs/video.js/commit/6cf7327))
|
||||
|
||||
### Tests
|
||||
|
||||
* fix playsinline test for IE8 ([#4347](https://github.com/videojs/video.js/issues/4347)) ([823f6c7](https://github.com/videojs/video.js/commit/823f6c7))
|
||||
|
||||
<a name="5.19.2"></a>
|
||||
## [5.19.2](https://github.com/videojs/video.js/compare/v5.19.1...v5.19.2) (2017-04-13)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* set IE_VERSION correctly for IE11 ([#4280](https://github.com/videojs/video.js/issues/4280)) ([207730e](https://github.com/videojs/video.js/commit/207730e)), closes [#4278](https://github.com/videojs/video.js/issues/4278)
|
||||
|
||||
<a name="5.19.1"></a>
|
||||
## [5.19.1](https://github.com/videojs/video.js/compare/v5.19.0...v5.19.1) (2017-03-27)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* not showing default text tracks over video ([#4217](https://github.com/videojs/video.js/issues/4217)) ([4653922](https://github.com/videojs/video.js/commit/4653922))
|
||||
* removeCue should work with native passed in cue ([#4209](https://github.com/videojs/video.js/issues/4209)) ([3974944](https://github.com/videojs/video.js/commit/3974944))
|
||||
|
||||
### Chores
|
||||
|
||||
* **package:** update videojs-vtt.js to 0.12.3 ([#4223](https://github.com/videojs/video.js/issues/4223)) ([ad770fb](https://github.com/videojs/video.js/commit/ad770fb))
|
||||
|
||||
<a name="5.19.0"></a>
|
||||
# [5.19.0](https://github.com/videojs/video.js/compare/v5.18.4...v5.19.0) (2017-03-15)
|
||||
|
||||
### Features
|
||||
|
||||
* Make pause on open optional for ModalDialog via options ([#4187](https://github.com/videojs/video.js/issues/4187)) ([4ec3b56](https://github.com/videojs/video.js/commit/4ec3b56))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* make load progress buffered regions height 100% ([#4191](https://github.com/videojs/video.js/issues/4191)) ([398c6e9](https://github.com/videojs/video.js/commit/398c6e9))
|
||||
* make sure audio track hides with one item ([#4203](https://github.com/videojs/video.js/issues/4203)) ([c069655](https://github.com/videojs/video.js/commit/c069655))
|
||||
|
||||
<a name="5.18.4"></a>
|
||||
## [5.18.4](https://github.com/videojs/video.js/compare/v5.18.3...v5.18.4) (2017-03-08)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **vttjs:** wait till tech el in DOM before loading vttjs ([#4176](https://github.com/videojs/video.js/issues/4176)) ([ad86eec](https://github.com/videojs/video.js/commit/ad86eec))
|
||||
|
||||
<a name="5.18.3"></a>
|
||||
## [5.18.3](https://github.com/videojs/video.js/compare/v5.18.2...v5.18.3) (2017-03-06)
|
||||
* **cues:** only copy cue props that don't exist ([#4146](https://github.com/videojs/video.js/issues/4146)) ([841d135](https://github.com/videojs/video.js/commit/841d135))
|
||||
|
||||
<a name="5.18.1"></a>
|
||||
## [5.18.1](https://github.com/videojs/video.js/compare/v5.18.0...v5.18.1) (2017-03-03)
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "Release Type?"
|
||||
read -rp "> " rtype
|
||||
|
||||
echo grunt version:${rtype}
|
||||
grunt version:${rtype}
|
||||
version=$(./build/bin/version)
|
||||
|
||||
echo New version is $version
|
||||
|
||||
# echo grunt chg-release:$version
|
||||
# grunt chg-release:$version
|
||||
npm run changelog
|
||||
|
||||
echo git commit -am "v$version"
|
||||
git commit -am "v$version"
|
||||
|
||||
echo git checkout temp-release-branch
|
||||
git checkout -b temp-release-branch
|
||||
|
||||
echo grunt dist
|
||||
grunt dist
|
||||
|
||||
echo git add -f dist
|
||||
git add -f dist
|
||||
|
||||
echo git commit -m "v$version dist"
|
||||
git commit -m "v$version dist"
|
||||
|
||||
echo git tag -a "v$version" -m "v$version"
|
||||
git tag -a "v$version" -m "v$version"
|
||||
|
||||
echo git show
|
||||
git show
|
||||
|
||||
|
||||
read -p "publish? " -n 1 -r
|
||||
echo # (optional) move to a new line
|
||||
if [[ $REPLY =~ ^[Nn]$ ]]
|
||||
then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo git push upstream
|
||||
git push upstream --tags
|
||||
git push origin --tags
|
||||
|
||||
echo npm publish --tag next-5
|
||||
npm publish --tag next-5
|
||||
|
||||
echo grunt github-release:prereleease
|
||||
grunt github-release:prerelease
|
||||
|
||||
echo git checkout -
|
||||
git checkout -
|
||||
|
||||
echo git branch -D temp-release-branch
|
||||
git branch -D temp-release-branch
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "video.js",
|
||||
"description": "An HTML5 and Flash video player with a common API and skin for both.",
|
||||
"version": "5.20.4",
|
||||
"version": "5.18.2",
|
||||
"keywords": [
|
||||
"videojs",
|
||||
"html5",
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "video.js",
|
||||
"description": "An HTML5 and Flash video player with a common API and skin for both.",
|
||||
"version": "5.20.4",
|
||||
"version": "5.18.2",
|
||||
"main": "./es5/video.js",
|
||||
"style": "./dist/video-js.css",
|
||||
"copyright": "Copyright Brightcove, Inc. <https://www.brightcove.com/>",
|
||||
@@ -41,8 +41,8 @@
|
||||
"tsml": "1.0.1",
|
||||
"videojs-font": "2.0.0",
|
||||
"videojs-ie8": "1.1.2",
|
||||
"videojs-swf": "5.4.1",
|
||||
"videojs-vtt.js": "0.12.4",
|
||||
"videojs-swf": "5.3.0",
|
||||
"videojs-vtt.js": "0.12.2",
|
||||
"xhr": "2.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -91,7 +91,7 @@
|
||||
"grunt-zip": "0.17.1",
|
||||
"istanbul": "^0.4.5",
|
||||
"jsdoc": "^3.4.2",
|
||||
"karma": "1.3.0",
|
||||
"karma": "^1.2.0",
|
||||
"karma-browserify": "^5.1.0",
|
||||
"karma-browserstack-launcher": "^1.0.1",
|
||||
"karma-chrome-launcher": "^2.0.0",
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
// Avoiding helvetica: issue #376
|
||||
font-family: $text-font-family;
|
||||
|
||||
@include user-select(none);
|
||||
|
||||
// Fix for Firefox 9 fullscreen (only if it is enabled). Not needed when
|
||||
// checking fullScreenEnabled.
|
||||
&:-moz-full-screen { position: absolute; }
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
.video-js .vjs-progress-holder .vjs-load-progress div {
|
||||
position: absolute;
|
||||
display: block;
|
||||
height: 100%;
|
||||
height: 0.3em;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
// updated by javascript during playback
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
padding: 0;
|
||||
margin: 0 0.45em 0 0.45em;
|
||||
|
||||
@include user-select(none);
|
||||
|
||||
@include background-color-with-alpha($secondary-background-color, $secondary-background-transparency);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,13 +11,6 @@ import Component from './component.js';
|
||||
* @extends Button
|
||||
*/
|
||||
class BigPlayButton extends Button {
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
|
||||
this.mouseused_ = false;
|
||||
|
||||
this.on('mousedown', this.handleMouseDown);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the default DOM `className`.
|
||||
@@ -41,12 +34,7 @@ class BigPlayButton extends Button {
|
||||
* @listens click
|
||||
*/
|
||||
handleClick(event) {
|
||||
const playPromise = this.player_.play();
|
||||
|
||||
// exit early if clicked via the mouse
|
||||
if (this.mouseused_ && event.clientX && event.clientY) {
|
||||
return;
|
||||
}
|
||||
this.player_.play();
|
||||
|
||||
const cb = this.player_.getChild('controlBar');
|
||||
const playToggle = cb && cb.getChild('playToggle');
|
||||
@@ -56,25 +44,9 @@ class BigPlayButton extends Button {
|
||||
return;
|
||||
}
|
||||
|
||||
const playFocus = () => playToggle.focus();
|
||||
|
||||
if (playPromise && playPromise.then) {
|
||||
const ignoreRejectedPlayPromise = () => {};
|
||||
|
||||
playPromise.then(playFocus, ignoreRejectedPlayPromise);
|
||||
} else {
|
||||
this.setTimeout(playFocus, 1);
|
||||
}
|
||||
}
|
||||
|
||||
handleKeyPress(event) {
|
||||
this.mouseused_ = false;
|
||||
|
||||
super.handleKeyPress(event);
|
||||
}
|
||||
|
||||
handleMouseDown(event) {
|
||||
this.mouseused_ = true;
|
||||
this.setTimeout(function() {
|
||||
playToggle.focus();
|
||||
}, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -152,10 +152,8 @@ class ClickableComponent extends Component {
|
||||
if (typeof this.tabIndex_ !== 'undefined') {
|
||||
this.el_.setAttribute('tabIndex', this.tabIndex_);
|
||||
}
|
||||
this.off(['tap', 'click'], this.handleClick);
|
||||
this.off('focus', this.handleFocus);
|
||||
this.off('blur', this.handleBlur);
|
||||
this.on(['tap', 'click'], this.handleClick);
|
||||
this.on('tap', this.handleClick);
|
||||
this.on('click', this.handleClick);
|
||||
this.on('focus', this.handleFocus);
|
||||
this.on('blur', this.handleBlur);
|
||||
return this;
|
||||
@@ -173,7 +171,8 @@ class ClickableComponent extends Component {
|
||||
if (typeof this.tabIndex_ !== 'undefined') {
|
||||
this.el_.removeAttribute('tabIndex');
|
||||
}
|
||||
this.off(['tap', 'click'], this.handleClick);
|
||||
this.off('tap', this.handleClick);
|
||||
this.off('click', this.handleClick);
|
||||
this.off('focus', this.handleFocus);
|
||||
this.off('blur', this.handleBlur);
|
||||
return this;
|
||||
|
||||
@@ -49,9 +49,6 @@ class AudioTrackButton extends TrackButton {
|
||||
* 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 && this.player_.audioTracks();
|
||||
|
||||
if (!tracks) {
|
||||
|
||||
@@ -81,7 +81,7 @@ class MuteToggle extends Button {
|
||||
const vol = this.player_.volume();
|
||||
let level = 3;
|
||||
|
||||
if (this.player_.muted()) {
|
||||
if (vol === 0 || this.player_.muted()) {
|
||||
level = 0;
|
||||
} else if (vol < 0.33) {
|
||||
level = 1;
|
||||
|
||||
@@ -38,7 +38,6 @@ class TextTrackMenuItem extends MenuItem {
|
||||
if (tracks) {
|
||||
const changeHandler = Fn.bind(this, this.handleTracksChange);
|
||||
|
||||
player.on(['loadstart', 'texttrackchange'], changeHandler);
|
||||
tracks.addEventListener('change', changeHandler);
|
||||
this.on('dispose', function() {
|
||||
tracks.removeEventListener('change', changeHandler);
|
||||
@@ -103,10 +102,8 @@ class TextTrackMenuItem extends MenuItem {
|
||||
}
|
||||
|
||||
if (track === this.track) {
|
||||
if (track.mode !== 'showing') {
|
||||
track.mode = 'showing';
|
||||
}
|
||||
} else if (track.mode !== 'disabled') {
|
||||
track.mode = 'showing';
|
||||
} else {
|
||||
track.mode = 'disabled';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,6 @@ class ErrorDisplay extends ModalDialog {
|
||||
* @private
|
||||
*/
|
||||
ErrorDisplay.prototype.options_ = mergeOptions(ModalDialog.prototype.options_, {
|
||||
pauseOnOpen: false,
|
||||
fillAlways: true,
|
||||
temporary: false,
|
||||
uncloseable: true
|
||||
|
||||
@@ -180,7 +180,7 @@ class ModalDialog extends Component {
|
||||
// playing state.
|
||||
this.wasPlaying_ = !player.paused();
|
||||
|
||||
if (this.options_.pauseOnOpen && this.wasPlaying_) {
|
||||
if (this.wasPlaying_) {
|
||||
player.pause();
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ class ModalDialog extends Component {
|
||||
this.trigger('beforemodalclose');
|
||||
this.opened_ = false;
|
||||
|
||||
if (this.wasPlaying_ && this.options_.pauseOnOpen) {
|
||||
if (this.wasPlaying_) {
|
||||
player.play();
|
||||
}
|
||||
|
||||
@@ -427,7 +427,6 @@ class ModalDialog extends Component {
|
||||
* @private
|
||||
*/
|
||||
ModalDialog.prototype.options_ = {
|
||||
pauseOnOpen: true,
|
||||
temporary: true
|
||||
};
|
||||
|
||||
|
||||
+2
-48
@@ -413,11 +413,6 @@ class Player extends Component {
|
||||
// Make player easily findable by ID
|
||||
Player.players[this.id_] = this;
|
||||
|
||||
// Add a major version class to aid css in plugins
|
||||
const majorVersion = require('../../package.json').version.split('.')[0];
|
||||
|
||||
this.addClass(`vjs-v${majorVersion}`);
|
||||
|
||||
// When the player is first initialized, trigger activity so components
|
||||
// like the control bar show themselves if needed
|
||||
this.userActive(true);
|
||||
@@ -827,7 +822,6 @@ class Player extends Component {
|
||||
'textTracks': this.textTracks_,
|
||||
'audioTracks': this.audioTracks_,
|
||||
'autoplay': this.options_.autoplay,
|
||||
'playsinline': this.options_.playsinline,
|
||||
'preload': this.options_.preload,
|
||||
'loop': this.options_.loop,
|
||||
'muted': this.options_.muted,
|
||||
@@ -1694,11 +1688,10 @@ class Player extends Component {
|
||||
*/
|
||||
duration(seconds) {
|
||||
if (seconds === undefined) {
|
||||
// return NaN if the duration is not known
|
||||
return this.cache_.duration !== undefined ? this.cache_.duration : NaN;
|
||||
return this.cache_.duration || 0;
|
||||
}
|
||||
|
||||
seconds = parseFloat(seconds);
|
||||
seconds = parseFloat(seconds) || 0;
|
||||
|
||||
// Standardize on Inifity for signaling video is live
|
||||
if (seconds < 0) {
|
||||
@@ -2387,31 +2380,6 @@ class Player extends Component {
|
||||
return this.techGet_('autoplay', value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or unset the playsinline attribute.
|
||||
* Playsinline tells the browser that non-fullscreen playback is preferred.
|
||||
*
|
||||
* @param {boolean} [value]
|
||||
* - true means that we should try to play inline by default
|
||||
* - false means that we should use the browser's default playback mode,
|
||||
* which in most cases is inline. iOS Safari is a notable exception
|
||||
* and plays fullscreen by default.
|
||||
*
|
||||
* @return {string|Player}
|
||||
* - the current value of playsinline
|
||||
* - the player when setting
|
||||
*
|
||||
* @see [Spec]{@link https://html.spec.whatwg.org/#attr-video-playsinline}
|
||||
*/
|
||||
playsinline(value) {
|
||||
if (value !== undefined) {
|
||||
this.techCall_('setPlaysinline', value);
|
||||
this.options_.playsinline = value;
|
||||
return this;
|
||||
}
|
||||
return this.techGet_('playsinline');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or set the loop attribute on the video element.
|
||||
*
|
||||
@@ -3020,20 +2988,6 @@ class Player extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets available media playback quality metrics as specified by the W3C's Media
|
||||
* Playback Quality API.
|
||||
*
|
||||
* @see [Spec]{@link https://wicg.github.io/media-playback-quality}
|
||||
*
|
||||
* @return {Object|undefined}
|
||||
* An object with supported media playback quality metrics or undefined if there
|
||||
* is no tech or the tech does not support it.
|
||||
*/
|
||||
getVideoPlaybackQuality() {
|
||||
return this.techGet_('getVideoPlaybackQuality');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get video width
|
||||
*
|
||||
|
||||
@@ -341,29 +341,6 @@ class Flash extends Tech {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets available media playback quality metrics as specified by the W3C's Media
|
||||
* Playback Quality API.
|
||||
*
|
||||
* @see [Spec]{@link https://wicg.github.io/media-playback-quality}
|
||||
*
|
||||
* @return {Object}
|
||||
* An object with supported media playback quality metrics
|
||||
*/
|
||||
getVideoPlaybackQuality() {
|
||||
const videoPlaybackQuality = this.el_.vjs_getProperty('getVideoPlaybackQuality');
|
||||
|
||||
if (window.performance && typeof window.performance.now === 'function') {
|
||||
videoPlaybackQuality.creationTime = window.performance.now();
|
||||
} else if (window.performance &&
|
||||
window.performance.timing &&
|
||||
typeof window.performance.timing.navigationStart === 'number') {
|
||||
videoPlaybackQuality.creationTime =
|
||||
window.Date.now() - window.performance.timing.navigationStart;
|
||||
}
|
||||
|
||||
return videoPlaybackQuality;
|
||||
}
|
||||
}
|
||||
|
||||
// Create setters and getters for attributes
|
||||
|
||||
+125
-316
@@ -131,9 +131,6 @@ class Html5 extends Tech {
|
||||
this.proxyNativeTextTracks_();
|
||||
}
|
||||
|
||||
// prevent iOS Safari from disabling metadata text tracks during native playback
|
||||
this.restoreMetadataTracksInIOSNativePlayer_();
|
||||
|
||||
// Determine if native controls should be used
|
||||
// Our goal should be to get the custom controls on mobile solid everywhere
|
||||
// so we can remove this all together. Right now this will block custom
|
||||
@@ -176,72 +173,6 @@ class Html5 extends Tech {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* When a captions track is enabled in the iOS Safari native player, all other
|
||||
* tracks are disabled (including metadata tracks), which nulls all of their
|
||||
* associated cue points. This will restore metadata tracks to their pre-fullscreen
|
||||
* state in those cases so that cue points are not needlessly lost.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
restoreMetadataTracksInIOSNativePlayer_() {
|
||||
const textTracks = this.textTracks();
|
||||
let metadataTracksPreFullscreenState;
|
||||
|
||||
// captures a snapshot of every metadata track's current state
|
||||
const takeMetadataTrackSnapshot = () => {
|
||||
metadataTracksPreFullscreenState = [];
|
||||
|
||||
for (let i = 0; i < textTracks.length; i++) {
|
||||
const track = textTracks[i];
|
||||
|
||||
if (track.kind === 'metadata') {
|
||||
metadataTracksPreFullscreenState.push({
|
||||
track,
|
||||
storedMode: track.mode
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// snapshot each metadata track's initial state, and update the snapshot
|
||||
// each time there is a track 'change' event
|
||||
takeMetadataTrackSnapshot();
|
||||
textTracks.addEventListener('change', takeMetadataTrackSnapshot);
|
||||
|
||||
const restoreTrackMode = () => {
|
||||
for (let i = 0; i < metadataTracksPreFullscreenState.length; i++) {
|
||||
const storedTrack = metadataTracksPreFullscreenState[i];
|
||||
|
||||
if (storedTrack.track.mode === 'disabled' && storedTrack.track.mode !== storedTrack.storedMode) {
|
||||
storedTrack.track.mode = storedTrack.storedMode;
|
||||
}
|
||||
}
|
||||
// we only want this handler to be executed on the first 'change' event
|
||||
textTracks.removeEventListener('change', restoreTrackMode);
|
||||
};
|
||||
|
||||
// when we enter fullscreen playback, stop updating the snapshot and
|
||||
// restore all track modes to their pre-fullscreen state
|
||||
this.on('webkitbeginfullscreen', () => {
|
||||
textTracks.removeEventListener('change', takeMetadataTrackSnapshot);
|
||||
|
||||
// remove the listener before adding it just in case it wasn't previously removed
|
||||
textTracks.removeEventListener('change', restoreTrackMode);
|
||||
textTracks.addEventListener('change', restoreTrackMode);
|
||||
});
|
||||
|
||||
// start updating the snapshot again after leaving fullscreen
|
||||
this.on('webkitendfullscreen', () => {
|
||||
// remove the listener before adding it just in case it wasn't previously removed
|
||||
textTracks.removeEventListener('change', takeMetadataTrackSnapshot);
|
||||
textTracks.addEventListener('change', takeMetadataTrackSnapshot);
|
||||
|
||||
// remove the restoreTrackMode handler in case it wasn't triggered during fullscreen playback
|
||||
textTracks.removeEventListener('change', restoreTrackMode);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the `Html5` Tech's DOM element.
|
||||
*
|
||||
@@ -291,27 +222,17 @@ class Html5 extends Tech {
|
||||
el.playerId = this.options_.playerId;
|
||||
}
|
||||
|
||||
if (typeof this.options_.preload !== 'undefined') {
|
||||
Dom.setAttribute(el, 'preload', this.options_.preload);
|
||||
}
|
||||
|
||||
// Update specific tag settings, in case they were overridden
|
||||
// `autoplay` has to be *last* so that `muted` and `playsinline` are present
|
||||
// when iOS/Safari or other browsers attempt to autoplay.
|
||||
const settingsAttrs = ['loop', 'muted', 'playsinline', 'autoplay'];
|
||||
const settingsAttrs = ['autoplay', 'preload', 'loop', 'muted'];
|
||||
|
||||
for (let i = settingsAttrs.length - 1; i >= 0; i--) {
|
||||
const attr = settingsAttrs[i];
|
||||
const value = this.options_[attr];
|
||||
const overwriteAttrs = {};
|
||||
|
||||
if (typeof value !== 'undefined') {
|
||||
if (value) {
|
||||
Dom.setAttribute(el, attr, attr);
|
||||
} else {
|
||||
Dom.removeAttribute(el, attr);
|
||||
}
|
||||
el[attr] = value;
|
||||
if (typeof this.options_[attr] !== 'undefined') {
|
||||
overwriteAttrs[attr] = this.options_[attr];
|
||||
}
|
||||
Dom.setElAttributes(el, overwriteAttrs);
|
||||
}
|
||||
|
||||
return el;
|
||||
@@ -636,12 +557,9 @@ class Html5 extends Tech {
|
||||
};
|
||||
|
||||
const beginFn = function() {
|
||||
if ('webkitPresentationMode' in this.el_ &&
|
||||
this.el_.webkitPresentationMode !== 'picture-in-picture') {
|
||||
this.one('webkitendfullscreen', endFn);
|
||||
this.one('webkitendfullscreen', endFn);
|
||||
|
||||
this.trigger('fullscreenchange', { isFullscreen: true });
|
||||
}
|
||||
this.trigger('fullscreenchange', { isFullscreen: true });
|
||||
};
|
||||
|
||||
this.on('webkitbeginfullscreen', beginFn);
|
||||
@@ -876,40 +794,6 @@ class Html5 extends Tech {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets available media playback quality metrics as specified by the W3C's Media
|
||||
* Playback Quality API.
|
||||
*
|
||||
* @see [Spec]{@link https://wicg.github.io/media-playback-quality}
|
||||
*
|
||||
* @return {Object}
|
||||
* An object with supported media playback quality metrics
|
||||
*/
|
||||
getVideoPlaybackQuality() {
|
||||
if (typeof this.el().getVideoPlaybackQuality === 'function') {
|
||||
return this.el().getVideoPlaybackQuality();
|
||||
}
|
||||
|
||||
const videoPlaybackQuality = {};
|
||||
|
||||
if (typeof this.el().webkitDroppedFrameCount !== 'undefined' &&
|
||||
typeof this.el().webkitDecodedFrameCount !== 'undefined') {
|
||||
videoPlaybackQuality.droppedVideoFrames = this.el().webkitDroppedFrameCount;
|
||||
videoPlaybackQuality.totalVideoFrames = this.el().webkitDecodedFrameCount;
|
||||
}
|
||||
|
||||
if (window.performance && typeof window.performance.now === 'function') {
|
||||
videoPlaybackQuality.creationTime = window.performance.now();
|
||||
} else if (window.performance &&
|
||||
window.performance.timing &&
|
||||
typeof window.performance.timing.navigationStart === 'number') {
|
||||
videoPlaybackQuality.creationTime =
|
||||
window.Date.now() - window.performance.timing.navigationStart;
|
||||
}
|
||||
|
||||
return videoPlaybackQuality;
|
||||
}
|
||||
}
|
||||
|
||||
/* HTML5 Support Testing ---------------------------------------------------- */
|
||||
@@ -981,7 +865,7 @@ Html5.canControlVolume = function() {
|
||||
Html5.canControlPlaybackRate = function() {
|
||||
// Playback rate API is implemented in Android Chrome, but doesn't do anything
|
||||
// https://github.com/videojs/video.js/issues/3180
|
||||
if (browser.IS_ANDROID && browser.IS_CHROME && browser.CHROME_VERSION < 58) {
|
||||
if (browser.IS_ANDROID && browser.IS_CHROME) {
|
||||
return false;
|
||||
}
|
||||
// IE will error if Windows Media Player not installed #3315
|
||||
@@ -1238,195 +1122,7 @@ Html5.resetMediaElement = function(el) {
|
||||
};
|
||||
|
||||
/* Native HTML5 element property wrapping ----------------------------------- */
|
||||
// Wrap native boolean attributes with getters that check both property and attribute
|
||||
// The list is as followed:
|
||||
// muted, defaultMuted, autoplay, controls, loop, playsinline
|
||||
[
|
||||
/**
|
||||
* Get the value of `muted` from the media element. `muted` indicates
|
||||
* that the volume for the media should be set to silent. This does not actually change
|
||||
* the `volume` attribute.
|
||||
*
|
||||
* @method Html5#muted
|
||||
* @return {boolean}
|
||||
* - True if the value of `volume` should be ignored and the audio set to silent.
|
||||
* - False if the value of `volume` should be used.
|
||||
*
|
||||
* @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-muted}
|
||||
*/
|
||||
'muted',
|
||||
|
||||
/**
|
||||
* Get the value of `defaultMuted` from the media element. `defaultMuted` indicates
|
||||
* whether the media should start muted or not. Only changes the default state of the
|
||||
* media. `muted` and `defaultMuted` can have different values. {@link Html5#muted} indicates the
|
||||
* current state.
|
||||
*
|
||||
* @method Html5#defaultMuted
|
||||
* @return {boolean}
|
||||
* - The value of `defaultMuted` from the media element.
|
||||
* - True indicates that the media should start muted.
|
||||
* - False indicates that the media should not start muted
|
||||
*
|
||||
* @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-defaultmuted}
|
||||
*/
|
||||
'defaultMuted',
|
||||
|
||||
/**
|
||||
* Get the value of `autoplay` from the media element. `autoplay` indicates
|
||||
* that the media should start to play as soon as the page is ready.
|
||||
*
|
||||
* @method Html5#autoplay
|
||||
* @return {boolean}
|
||||
* - The value of `autoplay` from the media element.
|
||||
* - True indicates that the media should start as soon as the page loads.
|
||||
* - False indicates that the media should not start as soon as the page loads.
|
||||
*
|
||||
* @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-autoplay}
|
||||
*/
|
||||
'autoplay',
|
||||
|
||||
/**
|
||||
* Get the value of `controls` from the media element. `controls` indicates
|
||||
* whether the native media controls should be shown or hidden.
|
||||
*
|
||||
* @method Html5#controls
|
||||
* @return {boolean}
|
||||
* - The value of `controls` from the media element.
|
||||
* - True indicates that native controls should be showing.
|
||||
* - False indicates that native controls should be hidden.
|
||||
*
|
||||
* @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-controls}
|
||||
*/
|
||||
'controls',
|
||||
|
||||
/**
|
||||
* Get the value of `loop` from the media element. `loop` indicates
|
||||
* that the media should return to the start of the media and continue playing once
|
||||
* it reaches the end.
|
||||
*
|
||||
* @method Html5#loop
|
||||
* @return {boolean}
|
||||
* - The value of `loop` from the media element.
|
||||
* - True indicates that playback should seek back to start once
|
||||
* the end of a media is reached.
|
||||
* - False indicates that playback should not loop back to the start when the
|
||||
* end of the media is reached.
|
||||
*
|
||||
* @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-loop}
|
||||
*/
|
||||
'loop',
|
||||
|
||||
/**
|
||||
* Get the value of `playsinline` from the media element. `playsinline` indicates
|
||||
* to the browser that non-fullscreen playback is preferred when fullscreen
|
||||
* playback is the native default, such as in iOS Safari.
|
||||
*
|
||||
* @method Html5#playsinline
|
||||
* @return {boolean}
|
||||
* - The value of `playsinline` from the media element.
|
||||
* - True indicates that the media should play inline.
|
||||
* - False indicates that the media should not play inline.
|
||||
*
|
||||
* @see [Spec]{@link https://html.spec.whatwg.org/#attr-video-playsinline}
|
||||
*/
|
||||
'playsinline'
|
||||
].forEach(function(prop) {
|
||||
Html5.prototype[prop] = function() {
|
||||
return this.el_[prop] || this.el_.hasAttribute(prop);
|
||||
};
|
||||
});
|
||||
|
||||
// Wrap native boolean attributes with setters that set both property and attribute
|
||||
// The list is as followed:
|
||||
// setMuted, setDefaultMuted, setAutoplay, setLoop, setPlaysinline
|
||||
// setControls is special-cased above
|
||||
[
|
||||
/**
|
||||
* Set the value of `muted` on the media element. `muted` indicates that the current
|
||||
* audio level should be silent.
|
||||
*
|
||||
* @method Html5#setMuted
|
||||
* @param {boolean} muted
|
||||
* - True if the audio should be set to silent
|
||||
* - False otherwise
|
||||
*
|
||||
* @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-muted}
|
||||
*/
|
||||
'muted',
|
||||
|
||||
/**
|
||||
* Set the value of `defaultMuted` on the media element. `defaultMuted` indicates that the current
|
||||
* audio level should be silent, but will only effect the muted level on intial playback..
|
||||
*
|
||||
* @method Html5.prototype.setDefaultMuted
|
||||
* @param {boolean} defaultMuted
|
||||
* - True if the audio should be set to silent
|
||||
* - False otherwise
|
||||
*
|
||||
* @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-defaultmuted}
|
||||
*/
|
||||
'defaultMuted',
|
||||
|
||||
/**
|
||||
* Set the value of `autoplay` on the media element. `autoplay` indicates
|
||||
* that the media should start to play as soon as the page is ready.
|
||||
*
|
||||
* @method Html5#setAutoplay
|
||||
* @param {boolean} autoplay
|
||||
* - True indicates that the media should start as soon as the page loads.
|
||||
* - False indicates that the media should not start as soon as the page loads.
|
||||
*
|
||||
* @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-autoplay}
|
||||
*/
|
||||
'autoplay',
|
||||
|
||||
/**
|
||||
* Set the value of `loop` on the media element. `loop` indicates
|
||||
* that the media should return to the start of the media and continue playing once
|
||||
* it reaches the end.
|
||||
*
|
||||
* @method Html5#setLoop
|
||||
* @param {boolean} loop
|
||||
* - True indicates that playback should seek back to start once
|
||||
* the end of a media is reached.
|
||||
* - False indicates that playback should not loop back to the start when the
|
||||
* end of the media is reached.
|
||||
*
|
||||
* @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-loop}
|
||||
*/
|
||||
'loop',
|
||||
|
||||
/**
|
||||
* Set the value of `playsinline` from the media element. `playsinline` indicates
|
||||
* to the browser that non-fullscreen playback is preferred when fullscreen
|
||||
* playback is the native default, such as in iOS Safari.
|
||||
*
|
||||
* @method Html5#setPlaysinline
|
||||
* @param {boolean} playsinline
|
||||
* - True indicates that the media should play inline.
|
||||
* - False indicates that the media should not play inline.
|
||||
*
|
||||
* @see [Spec]{@link https://html.spec.whatwg.org/#attr-video-playsinline}
|
||||
*/
|
||||
'playsinline'
|
||||
].forEach(function(prop) {
|
||||
Html5.prototype['set' + toTitleCase(prop)] = function(v) {
|
||||
this.el_[prop] = v;
|
||||
|
||||
if (v) {
|
||||
this.el_.setAttribute(prop, prop);
|
||||
} else {
|
||||
this.el_.removeAttribute(prop);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// Wrap native properties with a getter
|
||||
// The list is as followed
|
||||
// paused, currentTime, buffered, volume, poster, preload, error, seeking
|
||||
// seekable, ended, playbackRate, defaultPlaybackRate, played, networkState
|
||||
// readyState, videoWidth, videoHeight
|
||||
[
|
||||
/**
|
||||
* Get the value of `paused` from the media element. `paused` indicates whether the media element
|
||||
@@ -1478,6 +1174,20 @@ Html5.resetMediaElement = function(el) {
|
||||
*/
|
||||
'volume',
|
||||
|
||||
/**
|
||||
* Get the value of `muted` from the media element. `muted` indicates
|
||||
* that the volume for the media should be set to silent. This does not actually change
|
||||
* the `volume` attribute.
|
||||
*
|
||||
* @method Html5#muted
|
||||
* @return {boolean}
|
||||
* - True if the value of `volume` should be ignored and the audio set to silent.
|
||||
* - False if the value of `volume` should be used.
|
||||
*
|
||||
* @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-muted}
|
||||
*/
|
||||
'muted',
|
||||
|
||||
/**
|
||||
* Get the value of `poster` from the media element. `poster` indicates
|
||||
* that the url of an image file that can/will be shown when no media data is available.
|
||||
@@ -1510,6 +1220,51 @@ Html5.resetMediaElement = function(el) {
|
||||
*/
|
||||
'preload',
|
||||
|
||||
/**
|
||||
* Get the value of `autoplay` from the media element. `autoplay` indicates
|
||||
* that the media should start to play as soon as the page is ready.
|
||||
*
|
||||
* @method Html5#autoplay
|
||||
* @return {boolean}
|
||||
* - The value of `autoplay` from the media element.
|
||||
* - True indicates that the media should start as soon as the page loads.
|
||||
* - False indicates that the media should not start as soon as the page loads.
|
||||
*
|
||||
* @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-autoplay}
|
||||
*/
|
||||
'autoplay',
|
||||
|
||||
/**
|
||||
* Get the value of `controls` from the media element. `controls` indicates
|
||||
* whether the native media controls should be shown or hidden.
|
||||
*
|
||||
* @method Html5#controls
|
||||
* @return {boolean}
|
||||
* - The value of `controls` from the media element.
|
||||
* - True indicates that native controls should be showing.
|
||||
* - False indicates that native controls should be hidden.
|
||||
*
|
||||
* @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-controls}
|
||||
*/
|
||||
'controls',
|
||||
|
||||
/**
|
||||
* Get the value of `loop` from the media element. `loop` indicates
|
||||
* that the media should return to the start of the media and continue playing once
|
||||
* it reaches the end.
|
||||
*
|
||||
* @method Html5#loop
|
||||
* @return {boolean}
|
||||
* - The value of `loop` from the media element.
|
||||
* - True indicates that playback should seek back to start once
|
||||
* the end of a media is reached.
|
||||
* - False indicates that playback should not loop back to the start when the
|
||||
* end of the media is reached.
|
||||
*
|
||||
* @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-loop}
|
||||
*/
|
||||
'loop',
|
||||
|
||||
/**
|
||||
* Get the value of the `error` from the media element. `error` indicates any
|
||||
* MediaError that may have occured during playback. If error returns null there is no
|
||||
@@ -1565,6 +1320,22 @@ Html5.resetMediaElement = function(el) {
|
||||
*/
|
||||
'ended',
|
||||
|
||||
/**
|
||||
* Get the value of `defaultMuted` from the media element. `defaultMuted` indicates
|
||||
* whether the media should start muted or not. Only changes the default state of the
|
||||
* media. `muted` and `defaultMuted` can have different values. `muted` indicates the
|
||||
* current state.
|
||||
*
|
||||
* @method Html5#defaultMuted
|
||||
* @return {boolean}
|
||||
* - The value of `defaultMuted` from the media element.
|
||||
* - True indicates that the media should start muted.
|
||||
* - False indicates that the media should not start muted
|
||||
*
|
||||
* @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-defaultmuted}
|
||||
*/
|
||||
'defaultMuted',
|
||||
|
||||
/**
|
||||
* Get the value of `playbackRate` from the media element. `playbackRate` indicates
|
||||
* the rate at which the media is currently playing back. Examples:
|
||||
@@ -1662,8 +1433,6 @@ Html5.resetMediaElement = function(el) {
|
||||
|
||||
// Wrap native properties with a setter in this format:
|
||||
// set + toTitleCase(name)
|
||||
// The list is as follows:
|
||||
// setVolume, setSrc, setPoster, setPreload, setPlaybackRate, setDefaultPlaybackRate
|
||||
[
|
||||
/**
|
||||
* Set the value of `volume` on the media element. `volume` indicates the current
|
||||
@@ -1678,6 +1447,19 @@ Html5.resetMediaElement = function(el) {
|
||||
*/
|
||||
'volume',
|
||||
|
||||
/**
|
||||
* Set the value of `muted` on the media element. `muted` indicates the current
|
||||
* audio level should be silent.
|
||||
*
|
||||
* @method Html5#setMuted
|
||||
* @param {boolean} muted
|
||||
* - True if the audio should be set to silent
|
||||
* - False otherwise
|
||||
*
|
||||
* @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-muted}
|
||||
*/
|
||||
'muted',
|
||||
|
||||
/**
|
||||
* Set the value of `src` on the media element. `src` indicates the current
|
||||
* {@link Tech~SourceObject} for the media.
|
||||
@@ -1722,6 +1504,35 @@ Html5.resetMediaElement = function(el) {
|
||||
*/
|
||||
'preload',
|
||||
|
||||
/**
|
||||
* Set the value of `autoplay` on the media element. `autoplay` indicates
|
||||
* that the media should start to play as soon as the page is ready.
|
||||
*
|
||||
* @method Html5#setAutoplay
|
||||
* @param {boolean} autoplay
|
||||
* - True indicates that the media should start as soon as the page loads.
|
||||
* - False indicates that the media should not start as soon as the page loads.
|
||||
*
|
||||
* @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-autoplay}
|
||||
*/
|
||||
'autoplay',
|
||||
|
||||
/**
|
||||
* Set the value of `loop` on the media element. `loop` indicates
|
||||
* that the media should return to the start of the media and continue playing once
|
||||
* it reaches the end.
|
||||
*
|
||||
* @method Html5#setLoop
|
||||
* @param {boolean} loop
|
||||
* - True indicates that playback should seek back to start once
|
||||
* the end of a media is reached.
|
||||
* - False indicates that playback should not loop back to the start when the
|
||||
* end of the media is reached.
|
||||
*
|
||||
* @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-loop}
|
||||
*/
|
||||
'loop',
|
||||
|
||||
/**
|
||||
* Set the value of `playbackRate` on the media element. `playbackRate` indicates
|
||||
* the rate at which the media should play back. Examples:
|
||||
@@ -1743,8 +1554,6 @@ Html5.resetMediaElement = function(el) {
|
||||
});
|
||||
|
||||
// wrap native functions with a function
|
||||
// The list is as follows:
|
||||
// pause, load play
|
||||
[
|
||||
/**
|
||||
* A wrapper around the media elements `pause` function. This will call the `HTML5`
|
||||
|
||||
+2
-35
@@ -536,7 +536,7 @@ class Tech extends Component {
|
||||
// Initially, Tech.el_ is a child of a dummy-div wait until the Component system
|
||||
// signals that the Tech is ready at which point Tech.el_ is part of the DOM
|
||||
// before inserting the WebVTT script
|
||||
if (document.body.contains(this.el())) {
|
||||
if (this.el().parentNode !== null && this.el().parentNode !== undefined) {
|
||||
const vtt = require('videojs-vtt.js');
|
||||
|
||||
// load via require if available and vtt.js script location was not passed in
|
||||
@@ -551,7 +551,7 @@ class Tech extends Component {
|
||||
// passed in
|
||||
const script = document.createElement('script');
|
||||
|
||||
script.src = this.options_['vtt.js'] || 'https://vjs.zencdn.net/vttjs/0.12.4/vtt.min.js';
|
||||
script.src = this.options_['vtt.js'] || 'https://cdn.rawgit.com/gkatsev/vtt.js/vjs-v0.12.1/dist/vtt.min.js';
|
||||
script.onload = () => {
|
||||
/**
|
||||
* Fired when vtt.js is loaded.
|
||||
@@ -622,15 +622,11 @@ class Tech extends Component {
|
||||
|
||||
textTracksChanges();
|
||||
tracks.addEventListener('change', textTracksChanges);
|
||||
tracks.addEventListener('addtrack', textTracksChanges);
|
||||
tracks.addEventListener('removetrack', textTracksChanges);
|
||||
|
||||
this.on('dispose', function() {
|
||||
remoteTracks.off('addtrack', handleAddTrack);
|
||||
remoteTracks.off('removetrack', handleRemoveTrack);
|
||||
tracks.removeEventListener('change', textTracksChanges);
|
||||
tracks.removeEventListener('addtrack', textTracksChanges);
|
||||
tracks.removeEventListener('removetrack', textTracksChanges);
|
||||
|
||||
for (let i = 0; i < tracks.length; i++) {
|
||||
const track = tracks[i];
|
||||
@@ -805,21 +801,6 @@ class Tech extends Component {
|
||||
this.autoRemoteTextTracks_.removeTrack_(track);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets available media playback quality metrics as specified by the W3C's Media
|
||||
* Playback Quality API.
|
||||
*
|
||||
* @see [Spec]{@link https://wicg.github.io/media-playback-quality}
|
||||
*
|
||||
* @return {Object}
|
||||
* An object with supported media playback quality metrics
|
||||
*
|
||||
* @abstract
|
||||
*/
|
||||
getVideoPlaybackQuality() {
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* A method to set a poster from a `Tech`.
|
||||
*
|
||||
@@ -827,20 +808,6 @@ class Tech extends Component {
|
||||
*/
|
||||
setPoster() {}
|
||||
|
||||
/**
|
||||
* A method to check for the presence of the 'playsinine' <video> attribute.
|
||||
*
|
||||
* @abstract
|
||||
*/
|
||||
playsinline() {}
|
||||
|
||||
/**
|
||||
* A method to set or unset the 'playsinine' <video> attribute.
|
||||
*
|
||||
* @abstract
|
||||
*/
|
||||
setPlaysinline() {}
|
||||
|
||||
/*
|
||||
* Check if the tech can support the given mime-type.
|
||||
*
|
||||
|
||||
@@ -346,7 +346,6 @@ class TextTrack extends Track {
|
||||
|
||||
// make sure that `id` is copied over
|
||||
cue.id = originalCue.id;
|
||||
cue.originalCue_ = originalCue;
|
||||
}
|
||||
|
||||
const tracks = this.tech_.textTracks();
|
||||
@@ -370,17 +369,20 @@ class TextTrack extends Track {
|
||||
* The cue to remove from our internal list
|
||||
*/
|
||||
removeCue(removeCue) {
|
||||
let i = this.cues_.length;
|
||||
let removed = false;
|
||||
|
||||
while (i--) {
|
||||
for (let i = 0, l = this.cues_.length; i < l; i++) {
|
||||
const cue = this.cues_[i];
|
||||
|
||||
if (cue === removeCue || (cue.originalCue_ && cue.originalCue_ === removeCue)) {
|
||||
if (cue === removeCue) {
|
||||
this.cues_.splice(i, 1);
|
||||
this.cues.setCues_(this.cues_);
|
||||
break;
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (removed) {
|
||||
this.cues.setCues_(this.cues_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,26 +62,10 @@ export const IS_NATIVE_ANDROID = IS_ANDROID && ANDROID_VERSION < 5 && appleWebki
|
||||
export const IS_FIREFOX = (/Firefox/i).test(USER_AGENT);
|
||||
export const IS_EDGE = (/Edge/i).test(USER_AGENT);
|
||||
export const IS_CHROME = !IS_EDGE && (/Chrome/i).test(USER_AGENT);
|
||||
export const CHROME_VERSION = (function() {
|
||||
const match = USER_AGENT.match(/Chrome\/(\d+)/);
|
||||
|
||||
if (match && match[1]) {
|
||||
return parseFloat(match[1]);
|
||||
}
|
||||
return null;
|
||||
}());
|
||||
export const IS_IE8 = (/MSIE\s8\.0/).test(USER_AGENT);
|
||||
export const IE_VERSION = (function() {
|
||||
const result = (/MSIE\s(\d+)\.\d/).exec(USER_AGENT);
|
||||
let version = result && parseFloat(result[1]);
|
||||
|
||||
if (!version && (/Trident\/7.0/i).test(USER_AGENT) && (/rv:11.0/).test(USER_AGENT)) {
|
||||
// IE 11 has a different user agent string than other IE versions
|
||||
version = 11.0;
|
||||
}
|
||||
|
||||
return version;
|
||||
}());
|
||||
export const IE_VERSION = (function(result) {
|
||||
return result && parseFloat(result[1]);
|
||||
}((/MSIE\s(\d+)\.\d/).exec(USER_AGENT)));
|
||||
|
||||
export const IS_SAFARI = (/Safari/i).test(USER_AGENT) && !IS_CHROME && !IS_ANDROID && !IS_EDGE;
|
||||
export const IS_ANY_SAFARI = IS_SAFARI || IS_IOS;
|
||||
|
||||
@@ -485,7 +485,7 @@ export function getElAttributes(tag) {
|
||||
// known boolean attributes
|
||||
// we can check for matching boolean properties, but older browsers
|
||||
// won't know about HTML5 boolean attributes that we still read from
|
||||
const knownBooleans = ',' + 'autoplay,controls,playsinline,loop,muted,default,defaultMuted' + ',';
|
||||
const knownBooleans = ',' + 'autoplay,controls,loop,muted,default' + ',';
|
||||
|
||||
if (tag && tag.attributes && tag.attributes.length > 0) {
|
||||
const attrs = tag.attributes;
|
||||
|
||||
@@ -202,33 +202,6 @@ export function fixEvent(event) {
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether passive event listeners are supported
|
||||
*/
|
||||
let _supportsPassive = false;
|
||||
|
||||
(function() {
|
||||
try {
|
||||
const opts = Object.defineProperty({}, 'passive', {
|
||||
get() {
|
||||
_supportsPassive = true;
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('test', null, opts);
|
||||
} catch (e) {
|
||||
// disregard
|
||||
}
|
||||
})();
|
||||
|
||||
/**
|
||||
* Touch events Chrome expects to be passive
|
||||
*/
|
||||
const passiveEvents = [
|
||||
'touchstart',
|
||||
'touchmove'
|
||||
];
|
||||
|
||||
/**
|
||||
* Add an event listener to element
|
||||
* It stores the handler function in a separate cache object
|
||||
@@ -300,13 +273,7 @@ export function on(elem, type, fn) {
|
||||
|
||||
if (data.handlers[type].length === 1) {
|
||||
if (elem.addEventListener) {
|
||||
let options = false;
|
||||
|
||||
if (_supportsPassive &&
|
||||
passiveEvents.indexOf(type) > -1) {
|
||||
options = {passive: true};
|
||||
}
|
||||
elem.addEventListener(type, data.dispatcher, options);
|
||||
elem.addEventListener(type, data.dispatcher, false);
|
||||
} else if (elem.attachEvent) {
|
||||
elem.attachEvent('on' + type, data.dispatcher);
|
||||
}
|
||||
|
||||
+2
-2
@@ -7,8 +7,6 @@
|
||||
|
||||
import window from 'global/window';
|
||||
import document from 'global/document';
|
||||
import * as browser from './utils/browser.js';
|
||||
import * as Dom from './utils/dom.js';
|
||||
import * as setup from './setup';
|
||||
import * as stylesheet from './utils/stylesheet.js';
|
||||
import Component from './component';
|
||||
@@ -25,6 +23,8 @@ import VideoTrack from './tracks/video-track.js';
|
||||
import { createTimeRanges } from './utils/time-ranges.js';
|
||||
import formatTime from './utils/format-time.js';
|
||||
import log from './utils/log.js';
|
||||
import * as Dom from './utils/dom.js';
|
||||
import * as browser from './utils/browser.js';
|
||||
import * as Url from './utils/url.js';
|
||||
import {isObject} from './utils/obj';
|
||||
import computedStyle from './utils/computed-style.js';
|
||||
|
||||
@@ -59,7 +59,6 @@ QUnit.test('should be able to access expected player API methods', function(asse
|
||||
assert.ok(player.userActive, 'userActive exists');
|
||||
assert.ok(player.usingNativeControls, 'usingNativeControls exists');
|
||||
assert.ok(player.isFullscreen, 'isFullscreen exists');
|
||||
assert.ok(player.getVideoPlaybackQuality, 'getVideoPlaybackQuality exists');
|
||||
|
||||
// Track methods
|
||||
assert.ok(player.audioTracks, 'audioTracks exists');
|
||||
|
||||
@@ -71,25 +71,3 @@ QUnit.test('handleClick should not be triggered when disabled', function() {
|
||||
testClickableComponent.dispose();
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
QUnit.test('handleClick should not be triggered more than once when enabled', function() {
|
||||
let clicks = 0;
|
||||
|
||||
class TestClickableComponent extends ClickableComponent {
|
||||
handleClick() {
|
||||
clicks++;
|
||||
}
|
||||
}
|
||||
|
||||
const player = TestHelpers.makePlayer({});
|
||||
const testClickableComponent = new TestClickableComponent(player);
|
||||
const el = testClickableComponent.el();
|
||||
|
||||
testClickableComponent.enable();
|
||||
// Click should still be handled just once
|
||||
Events.trigger(el, 'click');
|
||||
QUnit.equal(clicks, 1, 'no additional click handler when already enabled ClickableComponent has been enabled again');
|
||||
|
||||
testClickableComponent.dispose();
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
@@ -208,35 +208,6 @@ QUnit.test('open() pauses playback, close() resumes', function(assert) {
|
||||
assert.strictEqual(playSpy.callCount, 1, 'player is resumed when the modal closes');
|
||||
});
|
||||
|
||||
QUnit.test('open() does not pause, close() does not play() with pauseOnOpen set to false', function(assert) {
|
||||
const playSpy = sinon.spy();
|
||||
const pauseSpy = sinon.spy();
|
||||
|
||||
// don't pause the video on modal open
|
||||
this.modal.options_.pauseOnOpen = false;
|
||||
|
||||
// Quick and dirty; make it looks like the player is playing.
|
||||
this.player.paused = function() {
|
||||
return false;
|
||||
};
|
||||
|
||||
this.player.play = function() {
|
||||
playSpy();
|
||||
};
|
||||
|
||||
this.player.pause = function() {
|
||||
pauseSpy();
|
||||
};
|
||||
|
||||
this.modal.open();
|
||||
|
||||
assert.expect(2);
|
||||
assert.strictEqual(pauseSpy.callCount, 0, 'player remains playing when the modal opens');
|
||||
|
||||
this.modal.close();
|
||||
assert.strictEqual(playSpy.callCount, 0, 'player is resumed when the modal closes');
|
||||
});
|
||||
|
||||
QUnit.test('open() hides controls, close() shows controls', function(assert) {
|
||||
this.modal.open();
|
||||
|
||||
|
||||
@@ -830,35 +830,6 @@ QUnit.test('should restore attributes from the original video tag when creating
|
||||
assert.equal(el.getAttribute('webkit-playsinline'), '', 'webkit-playsinline attribute was set properly');
|
||||
});
|
||||
|
||||
if (Html5.isSupported()) {
|
||||
QUnit.test('player.playsinline() should be able to get/set playsinline attribute', function(assert) {
|
||||
assert.expect(5);
|
||||
|
||||
const video = document.createElement('video');
|
||||
const player = TestHelpers.makePlayer({techOrder: ['html5']}, video);
|
||||
|
||||
// test setter
|
||||
assert.ok(!player.tech_.el().hasAttribute('playsinline'), 'playsinline has not yet been added');
|
||||
|
||||
player.playsinline(true);
|
||||
|
||||
assert.ok(player.tech_.el().hasAttribute('playsinline'), 'playsinline attribute added');
|
||||
|
||||
player.playsinline(false);
|
||||
|
||||
assert.ok(!player.tech_.el().hasAttribute('playsinline'), 'playsinline attribute removed');
|
||||
|
||||
// test getter
|
||||
player.tech_.el().setAttribute('playsinline', 'playsinline');
|
||||
|
||||
assert.ok(player.playsinline(), 'correctly detects playsinline attribute');
|
||||
|
||||
player.tech_.el().removeAttribute('playsinline');
|
||||
|
||||
assert.ok(!player.playsinline(), 'correctly detects absence of playsinline attribute');
|
||||
});
|
||||
}
|
||||
|
||||
QUnit.test('if tag exists and movingMediaElementInDOM, re-use the tag', function(assert) {
|
||||
// simulate attributes stored from the original tag
|
||||
const tag = Dom.createEl('video');
|
||||
@@ -1416,40 +1387,3 @@ QUnit.test('should not allow to register custom player when any player has been
|
||||
// reset the Player to the original value;
|
||||
videojs.registerComponent('Player', Player);
|
||||
});
|
||||
|
||||
QUnit.test('should add a class with major version', function(assert) {
|
||||
const majorVersion = require('../../package.json').version.split('.')[0];
|
||||
const player = TestHelpers.makePlayer();
|
||||
|
||||
assert.ok(player.hasClass('vjs-v' + majorVersion), 'the version class should be added to the player');
|
||||
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
QUnit.test('player.duration() returns NaN if player.cache_.duration is undefined', function(assert) {
|
||||
const player = TestHelpers.makePlayer();
|
||||
|
||||
player.cache_.duration = undefined;
|
||||
assert.ok(Number.isNaN(player.duration()), 'returned NaN for unkown duration');
|
||||
});
|
||||
|
||||
QUnit.test('player.duration() returns player.cache_.duration if it is defined', function(assert) {
|
||||
const player = TestHelpers.makePlayer();
|
||||
|
||||
player.cache_.duration = 200;
|
||||
assert.equal(player.duration(), 200, 'returned correct integer duration');
|
||||
player.cache_.duration = 942;
|
||||
assert.equal(player.duration(), 942, 'returned correct integer duration');
|
||||
});
|
||||
|
||||
QUnit.test('player.duration() sets the value of player.cache_.duration', function(assert) {
|
||||
const player = TestHelpers.makePlayer();
|
||||
|
||||
// set an arbitrary initial cached duration value for testing the setter functionality
|
||||
player.cache_.duration = 1;
|
||||
|
||||
player.duration(NaN);
|
||||
assert.ok(Number.isNaN(player.duration()), 'duration() set and get NaN duration value');
|
||||
player.duration(200);
|
||||
assert.equal(player.duration(), 200, 'duration() set and get integer duration value');
|
||||
});
|
||||
|
||||
@@ -7,13 +7,12 @@ QUnit.test('should set options from data-setup even if autoSetup is not called b
|
||||
const el = TestHelpers.makeTag();
|
||||
|
||||
el.setAttribute('data-setup',
|
||||
'{"controls": true, "autoplay": false, "preload": "auto", "playsinline": true}');
|
||||
'{"controls": true, "autoplay": false, "preload": "auto"}');
|
||||
|
||||
const player = TestHelpers.makePlayer({}, el);
|
||||
|
||||
assert.ok(player.options_.controls === true);
|
||||
assert.ok(player.options_.autoplay === false);
|
||||
assert.ok(player.options_.preload === 'auto');
|
||||
assert.ok(player.options_.playsinline === true);
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
import Flash from '../../../src/js/tech/flash.js';
|
||||
import { createTimeRange } from '../../../src/js/utils/time-ranges.js';
|
||||
import document from 'global/document';
|
||||
import window from 'global/window';
|
||||
import sinon from 'sinon';
|
||||
|
||||
// fake out the <object> interaction but leave all the other logic intact
|
||||
@@ -262,78 +261,3 @@ QUnit.test('duration returns NaN, Infinity or duration according to the HTML sta
|
||||
'duration returns duration property when readyState' +
|
||||
' and duration property are both higher than 0');
|
||||
});
|
||||
|
||||
QUnit.test('getVideoPlaybackQuality API exists', function(assert) {
|
||||
const propertyCalls = [];
|
||||
const videoPlaybackQuality = { test: 'test' };
|
||||
const mockFlash = {
|
||||
el_: {
|
||||
/* eslint-disable camelcase */
|
||||
vjs_getProperty(attr) {
|
||||
propertyCalls.push(attr);
|
||||
return videoPlaybackQuality;
|
||||
}
|
||||
/* eslint-enable camelcase */
|
||||
}
|
||||
};
|
||||
|
||||
assert.deepEqual(Flash.prototype.getVideoPlaybackQuality.call(mockFlash),
|
||||
videoPlaybackQuality,
|
||||
'called to get property from flash');
|
||||
assert.equal(propertyCalls.length, 1, 'only one property call');
|
||||
assert.equal(propertyCalls[0],
|
||||
'getVideoPlaybackQuality',
|
||||
'called for getVideoPlaybackQuality');
|
||||
});
|
||||
|
||||
QUnit.test('getVideoPlaybackQuality uses best available creationTime', function(assert) {
|
||||
const origPerformance = window.performance;
|
||||
const origDate = window.Date;
|
||||
const videoPlaybackQuality = {};
|
||||
const mockFlash = {
|
||||
el_: {
|
||||
/* eslint-disable camelcase */
|
||||
vjs_getProperty(attr) {
|
||||
return videoPlaybackQuality;
|
||||
}
|
||||
/* eslint-enable camelcase */
|
||||
}
|
||||
};
|
||||
|
||||
window.performance = void 0;
|
||||
assert.notOk(Flash.prototype.getVideoPlaybackQuality.call(mockFlash).creationTime,
|
||||
'no creationTime when no performance API available');
|
||||
|
||||
window.performance = {
|
||||
timing: {}
|
||||
};
|
||||
assert.notOk(Flash.prototype.getVideoPlaybackQuality.call(mockFlash).creationTime,
|
||||
'no creationTime when performance API insufficient');
|
||||
|
||||
window.performance = {
|
||||
now: () => 4
|
||||
};
|
||||
assert.equal(Flash.prototype.getVideoPlaybackQuality.call(mockFlash).creationTime,
|
||||
4,
|
||||
'creationTime is performance.now when available');
|
||||
|
||||
window.Date = {
|
||||
now: () => 10
|
||||
};
|
||||
window.performance = {
|
||||
timing: {
|
||||
navigationStart: 3
|
||||
}
|
||||
};
|
||||
assert.equal(Flash.prototype.getVideoPlaybackQuality.call(mockFlash).creationTime,
|
||||
7,
|
||||
'creationTime uses Date.now() - navigationStart when available');
|
||||
|
||||
window.performance.now = () => 4;
|
||||
assert.equal(Flash.prototype.getVideoPlaybackQuality.call(mockFlash).creationTime,
|
||||
4,
|
||||
'creationTime prioritizes performance.now when available');
|
||||
|
||||
window.Date = origDate;
|
||||
window.performance = origPerformance;
|
||||
});
|
||||
|
||||
@@ -50,19 +50,6 @@ QUnit.module('HTML5', {
|
||||
}
|
||||
});
|
||||
|
||||
QUnit.test('should be able to set playsinline attribute', function(assert) {
|
||||
assert.expect(2);
|
||||
|
||||
tech.createEl();
|
||||
tech.setPlaysinline(true);
|
||||
|
||||
assert.ok(tech.el().hasAttribute('playsinline'), 'playsinline attribute was added');
|
||||
|
||||
tech.setPlaysinline(false);
|
||||
|
||||
assert.ok(!tech.el().hasAttribute('playsinline'), 'playsinline attribute was removed');
|
||||
});
|
||||
|
||||
QUnit.test('should detect whether the volume can be changed', function(assert) {
|
||||
|
||||
if (!{}.__defineSetter__) {
|
||||
@@ -97,32 +84,6 @@ QUnit.test('test playbackRate', function(assert) {
|
||||
assert.strictEqual(tech.playbackRate(), 0.75);
|
||||
});
|
||||
|
||||
QUnit.test('blacklist playbackRate support on older verisons of Chrome on Android', function(assert) {
|
||||
if (!Html5.canControlPlaybackRate()) {
|
||||
assert.ok(true, 'playbackRate is not supported');
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset playbackrate - Firefox's rounding of playbackRate causes the rate not to change in canControlPlaybackRate() after a few instances
|
||||
Html5.TEST_VID.playbackRate = 1;
|
||||
|
||||
const oldIsAndroid = browser.IS_ANDROID;
|
||||
const oldIsChrome = browser.IS_CHROME;
|
||||
const oldChromeVersion = browser.CHROME_VERSION;
|
||||
|
||||
browser.IS_ANDROID = true;
|
||||
browser.IS_CHROME = true;
|
||||
browser.CHROME_VERSION = 50;
|
||||
assert.strictEqual(Html5.canControlPlaybackRate(), false, 'canControlPlaybackRate should return false on older Chrome');
|
||||
|
||||
browser.CHROME_VERSION = 58;
|
||||
assert.strictEqual(Html5.canControlPlaybackRate(), true, 'canControlPlaybackRate should return true on newer Chrome');
|
||||
|
||||
browser.IS_ANDROID = oldIsAndroid;
|
||||
browser.IS_CHROME = oldIsChrome;
|
||||
browser.CHROME_VERSION = oldChromeVersion;
|
||||
});
|
||||
|
||||
QUnit.test('should export played', function(assert) {
|
||||
tech.createEl();
|
||||
assert.deepEqual(tech.played(), tech.el().played, 'returns the played attribute');
|
||||
@@ -680,83 +641,3 @@ test('When Android Chrome reports Infinity duration with currentTime 0, return N
|
||||
browser.IS_CHROME = oldIsChrome;
|
||||
tech.el_ = oldEl;
|
||||
});
|
||||
|
||||
QUnit.test('supports getting available media playback quality metrics', function(assert) {
|
||||
const origPerformance = window.performance;
|
||||
const origDate = window.Date;
|
||||
const oldEl = tech.el_;
|
||||
const videoPlaybackQuality = {
|
||||
creationTime: 1,
|
||||
corruptedVideoFrames: 2,
|
||||
droppedVideoFrames: 3,
|
||||
totalVideoFrames: 5
|
||||
};
|
||||
|
||||
tech.el_ = {
|
||||
getVideoPlaybackQuality: () => videoPlaybackQuality
|
||||
};
|
||||
assert.deepEqual(tech.getVideoPlaybackQuality(),
|
||||
videoPlaybackQuality,
|
||||
'uses native implementation when supported');
|
||||
|
||||
tech.el_ = {
|
||||
webkitDroppedFrameCount: 1,
|
||||
webkitDecodedFrameCount: 2
|
||||
};
|
||||
window.performance = {
|
||||
now: () => 4
|
||||
};
|
||||
assert.deepEqual(tech.getVideoPlaybackQuality(),
|
||||
{ droppedVideoFrames: 1, totalVideoFrames: 2, creationTime: 4 },
|
||||
'uses webkit prefixed metrics and performance.now when supported');
|
||||
|
||||
tech.el_ = {
|
||||
webkitDroppedFrameCount: 1,
|
||||
webkitDecodedFrameCount: 2
|
||||
};
|
||||
window.Date = {
|
||||
now: () => 10
|
||||
};
|
||||
window.performance = {
|
||||
timing: {
|
||||
navigationStart: 3
|
||||
}
|
||||
};
|
||||
assert.deepEqual(tech.getVideoPlaybackQuality(),
|
||||
{ droppedVideoFrames: 1, totalVideoFrames: 2, creationTime: 7 },
|
||||
'uses webkit prefixed metrics and Date.now() - navigationStart when ' +
|
||||
'supported');
|
||||
|
||||
tech.el_ = {};
|
||||
window.performance = void 0;
|
||||
assert.deepEqual(tech.getVideoPlaybackQuality(), {}, 'empty object when not supported');
|
||||
|
||||
window.performance = {
|
||||
now: () => 5
|
||||
};
|
||||
assert.deepEqual(tech.getVideoPlaybackQuality(),
|
||||
{ creationTime: 5 },
|
||||
'only creation time when it\'s the only piece available');
|
||||
|
||||
window.performance = {
|
||||
timing: {
|
||||
navigationStart: 3
|
||||
}
|
||||
};
|
||||
assert.deepEqual(tech.getVideoPlaybackQuality(),
|
||||
{ creationTime: 7 },
|
||||
'only creation time when it\'s the only piece available');
|
||||
|
||||
tech.el_ = {
|
||||
getVideoPlaybackQuality: () => videoPlaybackQuality,
|
||||
webkitDroppedFrameCount: 1,
|
||||
webkitDecodedFrameCount: 2
|
||||
};
|
||||
assert.deepEqual(tech.getVideoPlaybackQuality(),
|
||||
videoPlaybackQuality,
|
||||
'prefers native implementation when supported');
|
||||
|
||||
tech.el_ = oldEl;
|
||||
window.performance = origPerformance;
|
||||
window.Date = origDate;
|
||||
});
|
||||
|
||||
@@ -631,9 +631,3 @@ QUnit.test('setSource after previous setSource should dispose source handler onc
|
||||
|
||||
});
|
||||
|
||||
QUnit.test('returns an empty object for getVideoPlaybackQuality', function(assert) {
|
||||
const tech = new Tech();
|
||||
|
||||
assert.deepEqual(tech.getVideoPlaybackQuality(), {}, 'returns an empty object');
|
||||
});
|
||||
|
||||
|
||||
@@ -205,46 +205,6 @@ QUnit.test('cues can be added and removed from a TextTrack', function(assert) {
|
||||
assert.equal(cues.length, 3, 'we now have 3 cues');
|
||||
});
|
||||
|
||||
QUnit.test('original cue can be used to remove cue from cues list', function(assert) {
|
||||
const tt = new TextTrack({
|
||||
tech: this.tech
|
||||
});
|
||||
const Cue = window.VTTCue ||
|
||||
window.vttjs && window.vttjs.VTTCue ||
|
||||
window.TextTrackCue;
|
||||
|
||||
const cue1 = new Cue(0, 1, 'some-cue');
|
||||
|
||||
assert.equal(tt.cues.length, 0, 'start with zero cues');
|
||||
tt.addCue(cue1);
|
||||
assert.equal(tt.cues.length, 1, 'we have one cue');
|
||||
|
||||
tt.removeCue(cue1);
|
||||
assert.equal(tt.cues.length, 0, 'we have removed cue1');
|
||||
});
|
||||
|
||||
QUnit.test('can only remove one cue at a time', function(assert) {
|
||||
const tt = new TextTrack({
|
||||
tech: this.tech
|
||||
});
|
||||
const Cue = window.VTTCue ||
|
||||
window.vttjs && window.vttjs.VTTCue ||
|
||||
window.TextTrackCue;
|
||||
|
||||
const cue1 = new Cue(0, 1, 'some-cue');
|
||||
|
||||
assert.equal(tt.cues.length, 0, 'start with zero cues');
|
||||
tt.addCue(cue1);
|
||||
tt.addCue(cue1);
|
||||
assert.equal(tt.cues.length, 2, 'we have two cues');
|
||||
|
||||
tt.removeCue(cue1);
|
||||
assert.equal(tt.cues.length, 1, 'we have removed one instance of cue1');
|
||||
|
||||
tt.removeCue(cue1);
|
||||
assert.equal(tt.cues.length, 0, 'we have removed the other instance of cue1');
|
||||
});
|
||||
|
||||
QUnit.test('fires cuechange when cues become active and inactive', function(assert) {
|
||||
const player = TestHelpers.makePlayer();
|
||||
let changes = 0;
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário