Comparar commits

..

36 Commits

Autor SHA1 Mensagem Data
Pat O'Neill d4a6c252b6 v5.20.4 dist 2017-10-02 17:07:27 -04:00
Pat O'Neill 66c0cf5ac6 v5.20.4 2017-10-02 17:07:07 -04:00
Gary Katsevman 0f8de5204e fix: Make boolean attributes set and check both the associated property and the attribute (#4631)
Make boolean attributes like muted set the property video.muted = {{boolean}} and the attribute video.setAttribute('muted', 'muted') when changing the value.
Also, in html5's createEl, we were setting/updating attributes for various properties but we were only setting the attributes and not also the properties but also autoplay was happening first rather than last which caused autoplay to fail because muted and playsinline weren't necessary set by that time.

This is the 5.x version of #4562.

Fix #4351.
2017-10-02 16:08:52 -04:00
Gary Katsevman 23c7f263c6 v5.20.3 2017-08-16 17:40:06 -04:00
Alex Barstow 424d021517 fix: tracks are disabled and cuepoints are cleared in iOS native player (#4569)
In the HTML5 tech, when we go fullscreen to the native player, listen for change events and restore previous mode state for the metadata text tracks.
This is 5.x version of #4496.
2017-08-16 12:04:49 -04:00
Gary Katsevman 935ec1e854 chore(CHANGELOG): update CHANGELOG for 5.20.2 (#4529) 2017-07-28 16:58:39 -04:00
Gary Katsevman 08aad15c04 v5.20.2 2017-07-26 16:58:21 -04:00
Gary Katsevman d90c94584d fix: only change focus from BPB if not a mouse click (#4523) 2017-07-26 16:09:40 -04:00
marguinbc b314268c2b fix: adjust volume ranges so muted(true) and vol=0 do not use the same icons (#4425) 2017-07-26 15:41:03 -04:00
Gary Katsevman a145dd287f chore(package): update to swf 5.4.1 (#4516) 2017-07-26 15:40:09 -04:00
Gary Katsevman 9ca9989494 chore: add a release script to makes things easier (#4517) 2017-07-26 15:37:19 -04:00
Alex Barstow 2576eda2f7 fix: player.duration() should return NaN if duration is not known (#4456) 2017-07-06 13:47:27 +10:00
mister-ben 8599c8ede0 fix: Use passive event listeners for touchstart/touchmove (#4445)
If passive event listening is supported, we should use it.

5.x version of #4440.

Fixes #4432.
2017-07-05 09:53:55 +10:00
mister-ben c17c003771 fix: Safari picture-in-picture triggers fullscreenchange (#4442)
When picture-in-picture mode is entered on Safari, `webkitbeginfullscreen` is triggered which results in a proxied `fullscreenchange` event and adding the fullscreen class to the player. That causes the tech element to collapse to zero height so that the "this video is playing in picture in picture" placeholder is not visible.

As with #4437 for v6, on `webkitbeginfullscreen` check whether the presentation mode is picture-in-picture' before proxying a `fullscreenchange` event.
2017-07-05 09:52:45 +10:00
Gary Katsevman a1763dcc56 fix: Only update text track mode if changed (#4368) 2017-05-18 13:12:18 -04:00
Gary Katsevman 3f7e215e7b chore(package): update videojs-vtt.js to 0.12.4 (#4364) 2017-05-16 16:51:00 -04:00
Gary Katsevman 0d725dfec7 chore: move imports up so bundlers wont trip up (#4363) 2017-05-16 11:39:53 -04:00
Gary Katsevman f194ca56eb v5.20.1 2017-05-15 13:57:32 -04:00
Gary Katsevman 0d6072078d fix: only disable user-selection on sliders (#4355) 2017-05-15 12:04:53 -04:00
mister-ben 3faea9fc63 fix: prevent dupe events on enabled ClickableComponents (#4357)
Like #4316 for v6, this prevents multiple click handlers being added if an already enabled component is enabled. In the PR for six, ClickableComponent was tracking this.enabled_ but this is incompatible with v5 on a MenuButton which also changes the state of this.enabled_.
Removes event handlers in enable() before adding them.
2017-05-15 11:33:01 -04:00
Gary Katsevman 69179673e1 v5.20.0 2017-05-11 11:25:38 -04:00
Gary Katsevman 823f6c7a47 test: fix playsinline test for IE8 (#4347)
This test is more of an integration test and uses the html5 tech to make
sure the setter and getter work properly. This causes issues with IE8
which doesn't work well with the Html5 tech.

Instead, we wrap the test in an if that checks whether Html5 is
supported.
2017-05-10 17:08:14 -04:00
Alex Barstow 946f84b4de feat: add 'playsinline' player option (#4325)
Video.js players can accept a number of standard <video> element options (autoplay, muted, loop, etc), but not currently playsinline, which is now part of the [HTML spec](https://html.spec.whatwg.org/multipage/embedded-content.html#attr-video-playsinline). We should add it to the list of <video> attributes that can be provided to the player as options.
2017-05-10 15:55:39 -04:00
Gary Katsevman 6cf7327fd4 chore(package): pin karma to 1.3.0 for IE8 support (#4340)
* chore: pin karma to 1.3.0 for IE8 support
* remove function assertion that breaks IE8
2017-05-09 15:47:23 -04:00
Gary Katsevman ab110ff191 chore: add slack travis notifications (#4339) 2017-05-09 14:54:16 -04:00
Garrett c970474e10 feat: Add getVideoPlaybackQuality API (#4286)
Provides a tech getter for getVideoPlaybackQuality as specified by the W3C's Media Playback Quality API: https://wicg.github.io/media-playback-quality/.
2017-05-09 14:32:40 -04:00
mister-ben b855bfb9de feat: Add a version class to the player (#4335)
Adds `vjs-v5` class so you can target that version of Video.js.
2017-05-09 14:18:01 -04:00
mister-ben 3fe22e93b0 feat: remove playbackRate blacklist for recent Android Chrome (#4336)
Android Chrome now supports playbackRate properly, so removes the blacklist added in #3246 for newer Chrome versions.
Adds `browser.CHROME_VERSION` as a necessary evil.
No longer blacklists for Chrome 58+ -- this could possibly be fixed since 52, but 58 is all I've been able to test on and most users should keep Chrome up to date.
2017-05-09 14:16:12 -04:00
Gary Katsevman eb05ff7f00 v5.19.2 2017-04-13 17:09:30 -04:00
Matthew Neil 207730ed6f fix: set IE_VERSION correctly for IE11 (#4280)
videojs.browser.IE_VERSION is null in IE11 because IE11 uses a different user agent string than other IE versions

Fixes #4278
2017-04-13 11:27:51 -04:00
Gary Katsevman 969d32551b v5.19.1 2017-03-27 15:29:19 -04:00
Matthew Neil ad770fb196 chore(package): update videojs-vtt.js to 0.12.3 (#4223) 2017-03-24 14:39:05 -04:00
Brandon Casey 3974944007 fix: removeCue should work with native passed in cue (#4209) 2017-03-23 14:32:01 -04:00
Brandon Casey 465392215c fix: not showing default text tracks over video (#4217)
This allows default tracks or tracks with a `mode`of `showing` to be seen
when they are added (as we would expect). Rather than only being seen
after the first `modechange` event (aka a selection from the menu). This is done by watching for `loadstart` on Player.
2017-03-23 14:30:50 -04:00
Gary Katsevman 6cf4ef8545 remove incorrect 5.19.0 changelog entry 2017-03-15 14:53:06 -04:00
Gary Katsevman c1ed22c39f fix CHANGELOG 2017-03-15 14:51:37 -04:00
38 arquivos alterados com 4393 adições e 2926 exclusões
+2
Ver Arquivo
@@ -13,6 +13,8 @@ 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=
+88 -27
Ver Arquivo
@@ -1,36 +1,97 @@
<a name="5.19.0"></a>
# [5.19.0](https://github.com/videojs/video.js/compare/v6.0.0-RC.5...v5.19.0) (2017-03-15)
### Features
* focus play toggle from Big Play Btn on play ([#4132](https://github.com/videojs/video.js/issues/4132)) ([dcc615a](https://github.com/videojs/video.js/commit/dcc615a)), closes [#2729](https://github.com/videojs/video.js/issues/2729)
* 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))
* update videojs-vtt.js and wrap native cues in TextTrack ([#4131](https://github.com/videojs/video.js/issues/4131)) ([3d4aebc](https://github.com/videojs/video.js/commit/3d4aebc)), closes [#4093](https://github.com/videojs/video.js/issues/4093)
<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)
### Bug Fixes
* addChild instance names should be toTitleCased ([#4117](https://github.com/videojs/video.js/issues/4117)) ([fa97309](https://github.com/videojs/video.js/commit/fa97309))
* cue-points with a startTime of 0 ([#4148](https://github.com/videojs/video.js/issues/4148)) ([e7d4b47](https://github.com/videojs/video.js/commit/e7d4b47))
* 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 mergeOptions behave the same across browsers ([#4090](https://github.com/videojs/video.js/issues/4090)) ([ce19ed5](https://github.com/videojs/video.js/commit/ce19ed5))
* 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))
* **cues:** only copy cue props that don't exist ([#4146](https://github.com/videojs/video.js/issues/4146)) ([de08669](https://github.com/videojs/video.js/commit/de08669))
* **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))
* **MenuButton:** Unify behavior of showing/hiding ([#3993](https://github.com/videojs/video.js/issues/3993)) ([4367c69](https://github.com/videojs/video.js/commit/4367c69))
* **playback rate menu:** playback rate menu items should be selectable ([#4150](https://github.com/videojs/video.js/issues/4150)) ([288edd1](https://github.com/videojs/video.js/commit/288edd1))
* **sass:** import path has cwd once again ([#4076](https://github.com/videojs/video.js/issues/4076)) ([c02c6c6](https://github.com/videojs/video.js/commit/c02c6c6))
* **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))
* make sure that cues copy over their id ([#4154](https://github.com/videojs/video.js/issues/4154)) ([072c277](https://github.com/videojs/video.js/commit/072c277))
* Patch a memory leak caused by un-removed track listener(s). ([#3975](https://github.com/videojs/video.js/issues/3975)) ([bca44c0](https://github.com/videojs/video.js/commit/bca44c0))
* remove title attribute on menu items, fixes [#3699](https://github.com/videojs/video.js/issues/3699) ([#4009](https://github.com/videojs/video.js/issues/4009)) ([91874a3](https://github.com/videojs/video.js/commit/91874a3))
* synchronously shim vtt.js when possible ([#4082](https://github.com/videojs/video.js/issues/4082)) ([b5727a6](https://github.com/videojs/video.js/commit/b5727a6))
* 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
* change accessibility test in grunt.js to remove unnecessary warning message. ([#4008](https://github.com/videojs/video.js/issues/4008)) ([daad492](https://github.com/videojs/video.js/commit/daad492))
* **build:** lint errors only and silence webpack ([#4153](https://github.com/videojs/video.js/issues/4153)) ([b1ca344](https://github.com/videojs/video.js/commit/b1ca344))
* **package:** update swf to 5.2.0 ([#4040](https://github.com/videojs/video.js/issues/4040)) ([dab893b](https://github.com/videojs/video.js/commit/dab893b))
* **package:** update video-js-swf to 5.3.0 ([#4161](https://github.com/videojs/video.js/issues/4161)) ([2bcfe21](https://github.com/videojs/video.js/commit/2bcfe21))
* **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)
Arquivo executável
+59
Ver Arquivo
@@ -0,0 +1,59 @@
#!/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
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": "5.19.0",
"version": "5.20.4",
"keywords": [
"videojs",
"html5",
+5 -5
Ver Arquivo
@@ -248,11 +248,7 @@
line-height: 1;
font-weight: normal;
font-style: normal;
font-family: Arial, Helvetica, sans-serif;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none; }
font-family: Arial, Helvetica, sans-serif; }
.video-js:-moz-full-screen {
position: absolute; }
.video-js:-webkit-full-screen {
@@ -794,6 +790,10 @@ body.vjs-full-window {
cursor: pointer;
padding: 0;
margin: 0 0.45em 0 0.45em;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-color: #73859f;
background-color: rgba(115, 133, 159, 0.5); }
+1 -1
Ver Arquivo
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
+752 -381
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+9 -9
Ver Arquivo
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
Arquivo binário não exibido.
+5 -5
Ver Arquivo
@@ -248,11 +248,7 @@
line-height: 1;
font-weight: normal;
font-style: normal;
font-family: Arial, Helvetica, sans-serif;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none; }
font-family: Arial, Helvetica, sans-serif; }
.video-js:-moz-full-screen {
position: absolute; }
.video-js:-webkit-full-screen {
@@ -794,6 +790,10 @@ body.vjs-full-window {
cursor: pointer;
padding: 0;
margin: 0 0.45em 0 0.45em;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-color: #73859f;
background-color: rgba(115, 133, 159, 0.5); }
+1 -1
Ver Arquivo
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
BIN
Ver Arquivo
Arquivo binário não exibido.
+2597 -2326
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+9 -9
Ver Arquivo
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
+4 -4
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": "5.19.0",
"version": "5.20.4",
"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.3.0",
"videojs-vtt.js": "0.12.2",
"videojs-swf": "5.4.1",
"videojs-vtt.js": "0.12.4",
"xhr": "2.2.2"
},
"devDependencies": {
@@ -91,7 +91,7 @@
"grunt-zip": "0.17.1",
"istanbul": "^0.4.5",
"jsdoc": "^3.4.2",
"karma": "^1.2.0",
"karma": "1.3.0",
"karma-browserify": "^5.1.0",
"karma-browserstack-launcher": "^1.0.1",
"karma-chrome-launcher": "^2.0.0",
-2
Ver Arquivo
@@ -21,8 +21,6 @@
// 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; }
+2
Ver Arquivo
@@ -5,6 +5,8 @@
padding: 0;
margin: 0 0.45em 0 0.45em;
@include user-select(none);
@include background-color-with-alpha($secondary-background-color, $secondary-background-transparency);
}
+32 -4
Ver Arquivo
@@ -11,6 +11,13 @@ 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`.
@@ -34,7 +41,12 @@ class BigPlayButton extends Button {
* @listens click
*/
handleClick(event) {
this.player_.play();
const playPromise = this.player_.play();
// exit early if clicked via the mouse
if (this.mouseused_ && event.clientX && event.clientY) {
return;
}
const cb = this.player_.getChild('controlBar');
const playToggle = cb && cb.getChild('playToggle');
@@ -44,9 +56,25 @@ class BigPlayButton extends Button {
return;
}
this.setTimeout(function() {
playToggle.focus();
}, 1);
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;
}
}
+5 -4
Ver Arquivo
@@ -152,8 +152,10 @@ class ClickableComponent extends Component {
if (typeof this.tabIndex_ !== 'undefined') {
this.el_.setAttribute('tabIndex', this.tabIndex_);
}
this.on('tap', this.handleClick);
this.on('click', this.handleClick);
this.off(['tap', 'click'], this.handleClick);
this.off('focus', this.handleFocus);
this.off('blur', this.handleBlur);
this.on(['tap', 'click'], this.handleClick);
this.on('focus', this.handleFocus);
this.on('blur', this.handleBlur);
return this;
@@ -171,8 +173,7 @@ class ClickableComponent extends Component {
if (typeof this.tabIndex_ !== 'undefined') {
this.el_.removeAttribute('tabIndex');
}
this.off('tap', this.handleClick);
this.off('click', this.handleClick);
this.off(['tap', 'click'], this.handleClick);
this.off('focus', this.handleFocus);
this.off('blur', this.handleBlur);
return this;
+1 -1
Ver Arquivo
@@ -81,7 +81,7 @@ class MuteToggle extends Button {
const vol = this.player_.volume();
let level = 3;
if (vol === 0 || this.player_.muted()) {
if (this.player_.muted()) {
level = 0;
} else if (vol < 0.33) {
level = 1;
@@ -38,6 +38,7 @@ 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);
@@ -102,8 +103,10 @@ class TextTrackMenuItem extends MenuItem {
}
if (track === this.track) {
track.mode = 'showing';
} else {
if (track.mode !== 'showing') {
track.mode = 'showing';
}
} else if (track.mode !== 'disabled') {
track.mode = 'disabled';
}
}
+48 -2
Ver Arquivo
@@ -413,6 +413,11 @@ 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);
@@ -822,6 +827,7 @@ 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,
@@ -1688,10 +1694,11 @@ class Player extends Component {
*/
duration(seconds) {
if (seconds === undefined) {
return this.cache_.duration || 0;
// return NaN if the duration is not known
return this.cache_.duration !== undefined ? this.cache_.duration : NaN;
}
seconds = parseFloat(seconds) || 0;
seconds = parseFloat(seconds);
// Standardize on Inifity for signaling video is live
if (seconds < 0) {
@@ -2380,6 +2387,31 @@ 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.
*
@@ -2988,6 +3020,20 @@ 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
*
+23
Ver Arquivo
@@ -341,6 +341,29 @@ 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
+316 -125
Ver Arquivo
@@ -131,6 +131,9 @@ 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
@@ -173,6 +176,72 @@ 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.
*
@@ -222,17 +291,27 @@ 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
const settingsAttrs = ['autoplay', 'preload', 'loop', 'muted'];
// `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'];
for (let i = settingsAttrs.length - 1; i >= 0; i--) {
const attr = settingsAttrs[i];
const overwriteAttrs = {};
const value = this.options_[attr];
if (typeof this.options_[attr] !== 'undefined') {
overwriteAttrs[attr] = this.options_[attr];
if (typeof value !== 'undefined') {
if (value) {
Dom.setAttribute(el, attr, attr);
} else {
Dom.removeAttribute(el, attr);
}
el[attr] = value;
}
Dom.setElAttributes(el, overwriteAttrs);
}
return el;
@@ -557,9 +636,12 @@ class Html5 extends Tech {
};
const beginFn = function() {
this.one('webkitendfullscreen', endFn);
if ('webkitPresentationMode' in this.el_ &&
this.el_.webkitPresentationMode !== 'picture-in-picture') {
this.one('webkitendfullscreen', endFn);
this.trigger('fullscreenchange', { isFullscreen: true });
this.trigger('fullscreenchange', { isFullscreen: true });
}
};
this.on('webkitbeginfullscreen', beginFn);
@@ -794,6 +876,40 @@ 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 ---------------------------------------------------- */
@@ -865,7 +981,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) {
if (browser.IS_ANDROID && browser.IS_CHROME && browser.CHROME_VERSION < 58) {
return false;
}
// IE will error if Windows Media Player not installed #3315
@@ -1122,7 +1238,195 @@ 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
@@ -1174,20 +1478,6 @@ 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.
@@ -1220,51 +1510,6 @@ 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
@@ -1320,22 +1565,6 @@ 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:
@@ -1433,6 +1662,8 @@ 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
@@ -1447,19 +1678,6 @@ 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.
@@ -1504,35 +1722,6 @@ 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:
@@ -1554,6 +1743,8 @@ 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`
+34 -1
Ver Arquivo
@@ -551,7 +551,7 @@ class Tech extends Component {
// passed in
const script = document.createElement('script');
script.src = this.options_['vtt.js'] || 'https://cdn.rawgit.com/gkatsev/vtt.js/vjs-v0.12.1/dist/vtt.min.js';
script.src = this.options_['vtt.js'] || 'https://vjs.zencdn.net/vttjs/0.12.4/vtt.min.js';
script.onload = () => {
/**
* Fired when vtt.js is loaded.
@@ -622,11 +622,15 @@ 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];
@@ -801,6 +805,21 @@ 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`.
*
@@ -808,6 +827,20 @@ 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.
*
+6 -8
Ver Arquivo
@@ -346,6 +346,7 @@ class TextTrack extends Track {
// make sure that `id` is copied over
cue.id = originalCue.id;
cue.originalCue_ = originalCue;
}
const tracks = this.tech_.textTracks();
@@ -369,20 +370,17 @@ class TextTrack extends Track {
* The cue to remove from our internal list
*/
removeCue(removeCue) {
let removed = false;
let i = this.cues_.length;
for (let i = 0, l = this.cues_.length; i < l; i++) {
while (i--) {
const cue = this.cues_[i];
if (cue === removeCue) {
if (cue === removeCue || (cue.originalCue_ && cue.originalCue_ === removeCue)) {
this.cues_.splice(i, 1);
removed = true;
this.cues.setCues_(this.cues_);
break;
}
}
if (removed) {
this.cues.setCues_(this.cues_);
}
}
}
+19 -3
Ver Arquivo
@@ -62,10 +62,26 @@ 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(result) {
return result && parseFloat(result[1]);
}((/MSIE\s(\d+)\.\d/).exec(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 IS_SAFARI = (/Safari/i).test(USER_AGENT) && !IS_CHROME && !IS_ANDROID && !IS_EDGE;
export const IS_ANY_SAFARI = IS_SAFARI || IS_IOS;
+1 -1
Ver Arquivo
@@ -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,loop,muted,default' + ',';
const knownBooleans = ',' + 'autoplay,controls,playsinline,loop,muted,default,defaultMuted' + ',';
if (tag && tag.attributes && tag.attributes.length > 0) {
const attrs = tag.attributes;
+34 -1
Ver Arquivo
@@ -202,6 +202,33 @@ 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
@@ -273,7 +300,13 @@ export function on(elem, type, fn) {
if (data.handlers[type].length === 1) {
if (elem.addEventListener) {
elem.addEventListener(type, data.dispatcher, false);
let options = false;
if (_supportsPassive &&
passiveEvents.indexOf(type) > -1) {
options = {passive: true};
}
elem.addEventListener(type, data.dispatcher, options);
} else if (elem.attachEvent) {
elem.attachEvent('on' + type, data.dispatcher);
}
+2 -2
Ver Arquivo
@@ -7,6 +7,8 @@
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';
@@ -23,8 +25,6 @@ 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';
+1
Ver Arquivo
@@ -59,6 +59,7 @@ 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');
+22
Ver Arquivo
@@ -71,3 +71,25 @@ 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();
});
+66
Ver Arquivo
@@ -830,6 +830,35 @@ 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');
@@ -1387,3 +1416,40 @@ 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');
});
+2 -1
Ver Arquivo
@@ -7,12 +7,13 @@ 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"}');
'{"controls": true, "autoplay": false, "preload": "auto", "playsinline": true}');
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();
});
+76
Ver Arquivo
@@ -2,6 +2,7 @@
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
@@ -261,3 +262,78 @@ 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;
});
+119
Ver Arquivo
@@ -50,6 +50,19 @@ 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__) {
@@ -84,6 +97,32 @@ 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');
@@ -641,3 +680,83 @@ 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;
});
+6
Ver Arquivo
@@ -631,3 +631,9 @@ 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');
});
+40
Ver Arquivo
@@ -205,6 +205,46 @@ 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;