Comparar commits
39 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 667db29143 | |||
| b48797bf17 | |||
| dcf2a300ef | |||
| 088f47af2e | |||
| 984085a048 | |||
| 67840aabbe | |||
| 93f2f83723 | |||
| 867fec910f | |||
| aa4700b098 | |||
| b84be556a6 | |||
| 0f219b1f1d | |||
| 49cc73f980 | |||
| 8ad286a768 | |||
| 5f239d7cf1 | |||
| 35203f613f | |||
| 692608270e | |||
| d99ce79954 | |||
| 01a7e7509e | |||
| 09f182db60 | |||
| 7838fe2ec3 | |||
| 45d43ec904 | |||
| c61e9e49ab | |||
| 4cb14eb420 | |||
| 1d88ef066d | |||
| 16f2e4113a | |||
| 4424a06a3d | |||
| 08f03c160c | |||
| 565dba8671 | |||
| a528e44d9b | |||
| 996822ba68 | |||
| 359df7148b | |||
| c6bf2b847a | |||
| 44edb12700 | |||
| 5bb1a76c4e | |||
| 8f2bc92412 | |||
| e78e26b8a4 | |||
| 9e3a7b6159 | |||
| 0b7a2e41b3 | |||
| f225d4e68a |
@@ -6,6 +6,51 @@ _(none)_
|
||||
|
||||
--------------------
|
||||
|
||||
## 5.5.2 (2016-01-14)
|
||||
* make sure that styleEl_ is in DOM before removing on dispose ([view](https://github.com/videojs/video.js/pull/3004))
|
||||
|
||||
## 5.5.1 (2016-01-08)
|
||||
* @gkatsev fixed sass if else for icons ([view](https://github.com/videojs/video.js/pull/2988))
|
||||
|
||||
## 5.5.0 (2016-01-07)
|
||||
* @hartman fixed usage of lighten in progress component. Fixes #2793 ([view](https://github.com/videojs/video.js/pull/2875))
|
||||
* @misteroneill exposed createEl on videojs ([view](https://github.com/videojs/video.js/pull/2926))
|
||||
* @huitsing updated docstrings for autoplay and loop methods ([view](https://github.com/videojs/video.js/pull/2960))
|
||||
* @rcrooks fixed some broken links in guides ([view](https://github.com/videojs/video.js/pull/2965))
|
||||
* @forbesjo fixed errorDisplay erroring on subsequent openings ([view](https://github.com/videojs/video.js/pull/2966))
|
||||
* @incompl updated build command in CONTRIBUTING.md ([view](https://github.com/videojs/video.js/pull/2967))
|
||||
* @forbesjo updated player to not autoplay if there is no source ([view](https://github.com/videojs/video.js/pull/2971))
|
||||
* @gkatsev updated css to have ascii codepoints for fonticons. Expose new scss file ([view](https://github.com/videojs/video.js/pull/2973))
|
||||
|
||||
## 5.4.6 (2015-12-22)
|
||||
* @gkatsev fixed vertical slider alignment in volume menu button ([view](https://github.com/videojs/video.js/pull/2943))
|
||||
|
||||
## 5.4.5 (2015-12-15)
|
||||
* @gkatsev added mouse/touch listeners to volume menu button ([view](https://github.com/videojs/video.js/pull/2638))
|
||||
* @gkatsev updated styles for inline menu and volume bar ([view](https://github.com/videojs/video.js/pull/2913))
|
||||
* @BrandonOCasey updated sandbox to to use newer CDN urls ([view](https://github.com/videojs/video.js/pull/2917))
|
||||
* @hartman updated options guide doc ([view](https://github.com/videojs/video.js/pull/2908))
|
||||
* @rcrooks fixed simple embed example ([view](https://github.com/videojs/video.js/pull/2915))
|
||||
|
||||
## 5.4.4 (2015-12-09)
|
||||
* @gkatsev switched to use custom vtt.js from npm ([view](https://github.com/videojs/video.js/pull/2905))
|
||||
|
||||
## 5.4.3 (2015-12-08)
|
||||
* @gkatsev updated options customizer and github-release options ([view](https://github.com/videojs/video.js/pull/2903))
|
||||
|
||||
## 5.4.2 (2015-12-08)
|
||||
* @gkatsev updated grunt-release config ([view](https://github.com/videojs/video.js/pull/2900))
|
||||
|
||||
## 5.4.1 (2015-12-08)
|
||||
* @misteroneill updated videojs-ie8 to 1.1.1 ([view](https://github.com/videojs/video.js/pull/2869))
|
||||
* @gkatsev added Player#tech. Fixes #2617 ([view](https://github.com/videojs/video.js/pull/2883))
|
||||
* @nick11703 changed multiline comments in sass with single-line comments ([view](https://github.com/videojs/video.js/pull/2827))
|
||||
* @gkatsev added a Player#reset method. Fixes #2852 ([view](https://github.com/videojs/video.js/pull/2880))
|
||||
* @chemoish emulated HTMLTrackElement to enable track load events ([view](https://github.com/videojs/video.js/pull/2804))
|
||||
* @gkatsev added nullcheck for cues in updateForTrack. Fixes #2870 ([view](https://github.com/videojs/video.js/pull/2896))
|
||||
* @gkatsev added ability to release next tag from master ([view](https://github.com/videojs/video.js/pull/2894))
|
||||
* @gkatsev added chg- and github- release for next releases ([view](https://github.com/videojs/video.js/pull/2899))
|
||||
|
||||
## 5.3.0 (2015-11-25)
|
||||
* @forbesjo updated formatTime to not go negative ([view](https://github.com/videojs/video.js/pull/2821))
|
||||
* @imbcmdth added sourceOrder option for source-first ordering in selectSource ([view](https://github.com/videojs/video.js/pull/2847))
|
||||
|
||||
+1
-1
@@ -144,7 +144,7 @@ npm install
|
||||
Build a local copy of video.js and run tests
|
||||
|
||||
```bash
|
||||
grunt
|
||||
grunt dist
|
||||
grunt test
|
||||
```
|
||||
|
||||
|
||||
+42
-19
@@ -1,3 +1,4 @@
|
||||
import {gruntCustomizer, gruntOptionsMaker} from './options-customizer.js';
|
||||
module.exports = function(grunt) {
|
||||
require('time-grunt')(grunt);
|
||||
|
||||
@@ -41,6 +42,19 @@ module.exports = function(grunt) {
|
||||
]
|
||||
};
|
||||
|
||||
const githubReleaseDefaults = {
|
||||
options: {
|
||||
release: {
|
||||
tag_name: 'v'+ version.full,
|
||||
name: version.full,
|
||||
body: require('chg').find(version.full).changesRaw
|
||||
},
|
||||
},
|
||||
files: {
|
||||
src: [`dist/video-js-${version.full}.zip`] // Files that you want to attach to Release
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Customizes _.merge behavior in `browserifyGruntOptions` to concatenate
|
||||
* arrays. This can be overridden on a per-call basis to
|
||||
@@ -52,11 +66,7 @@ module.exports = function(grunt) {
|
||||
* @param {Mixed} sourceValue
|
||||
* @return {Object}
|
||||
*/
|
||||
function browserifyGruntCustomizer(objectValue, sourceValue) {
|
||||
if (Array.isArray(objectValue)) {
|
||||
return objectValue.concat(sourceValue);
|
||||
}
|
||||
}
|
||||
const browserifyGruntCustomizer = gruntCustomizer;
|
||||
|
||||
/**
|
||||
* Creates a unique object of Browserify Grunt task options.
|
||||
@@ -70,9 +80,10 @@ module.exports = function(grunt) {
|
||||
*
|
||||
* @return {Object}
|
||||
*/
|
||||
function browserifyGruntOptions(options = null, customizer = browserifyGruntCustomizer) {
|
||||
return _.merge({}, browserifyGruntDefaults, options, customizer);
|
||||
}
|
||||
const browserifyGruntOptions = gruntOptionsMaker(browserifyGruntDefaults, browserifyGruntCustomizer);
|
||||
|
||||
const githubReleaseCustomizer = gruntCustomizer;
|
||||
const githubReleaseOptions = gruntOptionsMaker(githubReleaseDefaults, githubReleaseCustomizer);
|
||||
|
||||
/**
|
||||
* Creates processor functions for license banners.
|
||||
@@ -140,7 +151,7 @@ module.exports = function(grunt) {
|
||||
watch: {
|
||||
skin: {
|
||||
files: ['src/css/**/*'],
|
||||
tasks: 'sass'
|
||||
tasks: ['sass', 'wrapcodepoints']
|
||||
},
|
||||
jshint: {
|
||||
files: ['src/**/*', 'test/unit/**/*.js', 'Gruntfile.js'],
|
||||
@@ -185,7 +196,7 @@ module.exports = function(grunt) {
|
||||
sass: {
|
||||
build: {
|
||||
files: {
|
||||
'build/temp/video-js.css': 'src/css/video-js.scss'
|
||||
'build/temp/video-js.css': 'src/css/vjs.scss'
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -294,16 +305,16 @@ module.exports = function(grunt) {
|
||||
auth: {
|
||||
user: process.env.VJS_GITHUB_USER,
|
||||
password: process.env.VJS_GITHUB_TOKEN
|
||||
},
|
||||
release: {
|
||||
tag_name: 'v'+ version.full,
|
||||
name: version.full,
|
||||
body: require('chg').find(version.full).changesRaw
|
||||
}
|
||||
},
|
||||
files: {
|
||||
src: [`dist/video-js-${version.full}.zip`] // Files that you want to attach to Release
|
||||
}
|
||||
release: githubReleaseOptions(),
|
||||
prerelease: githubReleaseOptions({
|
||||
options: {
|
||||
release: {
|
||||
prerelease: true
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
browserify: {
|
||||
options: browserifyGruntOptions(),
|
||||
@@ -316,7 +327,7 @@ module.exports = function(grunt) {
|
||||
options: browserifyGruntOptions({
|
||||
transform: [
|
||||
['browserify-versionify', {
|
||||
placeholder: '../node_modules/vtt.js/dist/vtt.js',
|
||||
placeholder: '../node_modules/videojs-vtt.js/dist/vtt.js',
|
||||
version: 'https://cdn.rawgit.com/gkatsev/vtt.js/vjs-v0.12.1/dist/vtt.min.js'
|
||||
}],
|
||||
]
|
||||
@@ -444,6 +455,7 @@ module.exports = function(grunt) {
|
||||
'uglify',
|
||||
|
||||
'sass',
|
||||
'wrapcodepoints',
|
||||
'version:css',
|
||||
'cssmin',
|
||||
|
||||
@@ -468,6 +480,17 @@ module.exports = function(grunt) {
|
||||
'zip:dist'
|
||||
]);
|
||||
|
||||
// Sass turns unicode codepoints into utf8 characters.
|
||||
// We don't want that so we unwrapped them in the templates/scss.hbs file.
|
||||
// After sass has generated our css file, we need to wrap the codepoints
|
||||
// in quotes for it to work.
|
||||
grunt.registerTask('wrapcodepoints', function() {
|
||||
const sassConfig = grunt.config.get('sass.build.files');
|
||||
const cssPath = Object.keys(sassConfig)[0];
|
||||
const css = grunt.file.read(cssPath);
|
||||
grunt.file.write(cssPath, css.replace(/(\\f\w+);/g, "'$1';"));
|
||||
});
|
||||
|
||||
// Default task - build and test
|
||||
grunt.registerTask('default', ['test']);
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import _ from 'lodash-compat';
|
||||
/**
|
||||
* Customizes _.merge behavior in `gruntOptions` to concatenate
|
||||
* arrays. This can be overridden on a per-call basis to
|
||||
*
|
||||
* @see https://lodash.com/docs#merge
|
||||
* @function GruntCustomizer
|
||||
* @private
|
||||
* @param {Mixed} objectValue
|
||||
* @param {Mixed} sourceValue
|
||||
* @return {Object}
|
||||
*/
|
||||
function gruntCustomizer(objectValue, sourceValue) {
|
||||
if (Array.isArray(objectValue)) {
|
||||
return objectValue.concat(sourceValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a gruntOptions instance for the specific defaultOptions and gruntCustomizer
|
||||
*
|
||||
* @function browserifyGruntOptions
|
||||
* @private
|
||||
* @param {Object} [options]
|
||||
* @param {Function} [customizer=gruntCustomizer]
|
||||
* If the default array-concatenation behavior is not desireable,
|
||||
* pass _.noop or a unique customizer (https://lodash.com/docs#merge).
|
||||
*
|
||||
* @return {Function}
|
||||
*/
|
||||
function gruntOptionsMaker(defaultOptions, gruntCustomizer) {
|
||||
/**
|
||||
* Creates a unique object of Browserify Grunt task options.
|
||||
*
|
||||
* @function gruntOptions
|
||||
* @private
|
||||
* @param {Object} [options]
|
||||
* @param {Function} [customizer=browserifyGruntCustomizer]
|
||||
* If the default array-concatenation behavior is not desireable,
|
||||
* pass _.noop or a unique customizer (https://lodash.com/docs#merge).
|
||||
*
|
||||
* @return {Object}
|
||||
*/
|
||||
return function gruntOptions(options = null, customizer = gruntCustomizer) {
|
||||
return _.merge({}, defaultOptions, options, customizer);
|
||||
}
|
||||
};
|
||||
|
||||
export { gruntCustomizer, gruntOptionsMaker };
|
||||
+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.3.0",
|
||||
"version": "5.5.2",
|
||||
"keywords": [
|
||||
"videojs",
|
||||
"html5",
|
||||
|
||||
+27
-3
@@ -250,15 +250,37 @@
|
||||
]
|
||||
},
|
||||
|
||||
"next": {
|
||||
"patch": {
|
||||
"description": "Create a patch release and tag it @next on npm",
|
||||
"release_type": "patch",
|
||||
"steps": [{ "include": "release run_next" }]
|
||||
},
|
||||
"minor": {
|
||||
"description": "Create a minor release and tag it @next on npm",
|
||||
"release_type": "minor",
|
||||
"steps": [{ "include": "release run_next" }]
|
||||
},
|
||||
"major": {
|
||||
"description": "Create a major release and tag it @next on npm",
|
||||
"release_type": "major",
|
||||
"steps": [{ "include": "release run_next" }]
|
||||
}
|
||||
},
|
||||
|
||||
"prerelease": {
|
||||
"release_type": "prerelease",
|
||||
"steps": [{ "include": "release run_next" }]
|
||||
},
|
||||
|
||||
"run_next": {
|
||||
"steps": [
|
||||
[ "git checkout master", "Checkout the developmet branch" ],
|
||||
[ "git pull upstream master", "Update the developmet branch" ],
|
||||
{ "include": "branch check" },
|
||||
{ "include": "update local master" },
|
||||
[ "git checkout -b temp-release-branch master","Create a temporary branch for the dist" ],
|
||||
[ "grunt version:{{release_type}}", "Bump package versions" ],
|
||||
[ "./build/bin/version", "Return the current VJS Version from the package.json file", "version" ],
|
||||
[ "grunt chg-release:{{version}}", "Update the changelog with the new release" ],
|
||||
[ "git commit -am 'v{{version}}'", "Add and commit the package changes" ],
|
||||
[ "git checkout master", "Checkout the developmet branch" ],
|
||||
[ "git merge temp-release-branch", "Merge package changes into the dev brach" ],
|
||||
@@ -269,11 +291,13 @@
|
||||
[ "git commit -m 'v{{version}} dist'", "Commit the dist changes" ],
|
||||
[ "git tag -a v{{version}} -m 'v{{version}}'", "Tag the release" ],
|
||||
[ "git push upstream --tags", "Push the new tag to the repo" ],
|
||||
[ "grunt github-release:prerelease", "Create a new pre-release on Github" ],
|
||||
[ "npm publish --tag next", "Publish to npm as 'next'" ],
|
||||
[ "git checkout master", "Checkout the developmet branch" ],
|
||||
[ "git branch -D temp-release-branch", "Delete the temp release branch" ]
|
||||
]
|
||||
},
|
||||
|
||||
"run": {
|
||||
"steps": [
|
||||
{ "include": "branch check" },
|
||||
@@ -292,7 +316,7 @@
|
||||
[ "git tag -a v{{version}} -m 'v{{version}}'", "Tag the release" ],
|
||||
[ "git push upstream --tags", "Push the new tag to the repo" ],
|
||||
[ "npm publish", "Publish to npm" ],
|
||||
[ "grunt github-release", "Create a new release on Github" ],
|
||||
[ "grunt github-release:release", "Create a new release on Github" ],
|
||||
[ "git checkout stable", "Checkout the developmet branch" ],
|
||||
[ "git branch -D temp-release-branch", "Delete the temp release branch" ]
|
||||
]
|
||||
|
||||
externo
+561
-120
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
externo
+11
-8
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
externo
+1
-1
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
+17
-24
@@ -1,37 +1,30 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Video.js | HTML5 Video Player</title>
|
||||
|
||||
<!-- Chang URLs to wherever Video.js files will be hosted -->
|
||||
<!-- Default URLs assume the examples folder is included alongside video.js -->
|
||||
<link href="../../video-js.min.css" rel="stylesheet" type="text/css">
|
||||
<head>
|
||||
<title>Video.js | HTML5 Video Player</title>
|
||||
<link href="http://vjs.zencdn.net/5.0.2/video-js.css" rel="stylesheet">
|
||||
<script src="http://vjs.zencdn.net/ie8/1.1.0/videojs-ie8.min.js"></script>
|
||||
<script src="http://vjs.zencdn.net/5.0.2/video.js"></script>
|
||||
|
||||
<!-- Include ES5 shim, sham and html5 shiv for ie8 support -->
|
||||
<!-- Exclude this if you don't need ie8 support -->
|
||||
<script src="../../ie8/videojs-ie8.min.js"></script>
|
||||
|
||||
<!-- video.js must be in the <head> for older IEs to work. -->
|
||||
<script src="../../video.min.js"></script>
|
||||
|
||||
<!-- Unless using the CDN hosted version, update the URL to the Flash SWF -->
|
||||
<script>
|
||||
videojs.options.flash.swf = "../../video-js.swf";
|
||||
</script>
|
||||
</head>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<video id="example_video_1" class="video-js vjs-default-skin" controls preload="none" width="640" height="264"
|
||||
poster="http://video-js.zencoder.com/oceans-clip.png"
|
||||
data-setup="{}">
|
||||
<source src="http://video-js.zencoder.com/oceans-clip.mp4" type='video/mp4' />
|
||||
<source src="http://video-js.zencoder.com/oceans-clip.webm" type='video/webm' />
|
||||
<source src="http://video-js.zencoder.com/oceans-clip.ogv" type='video/ogg' />
|
||||
<track kind="captions" src="../shared/example-captions.vtt" srclang="en" label="English"></track><!-- Tracks need an ending tag thanks to IE9 -->
|
||||
<track kind="subtitles" src="../shared/example-captions.vtt" srclang="en" label="English"></track><!-- Tracks need an ending tag thanks to IE9 -->
|
||||
<video id="example_video_1" class="video-js vjs-default-skin" controls preload="none" width="640" height="264" poster="http://vjs.zencdn.net/v/oceans.png" data-setup="{}">
|
||||
<source src="http://vjs.zencdn.net/v/oceans.mp4" type="video/mp4">
|
||||
<source src="http://vjs.zencdn.net/v/oceans.webm" type="video/webm">
|
||||
<source src="http://vjs.zencdn.net/v/oceans.ogv" type="video/ogg">
|
||||
<track kind="captions" src="../shared/example-captions.vtt" srclang="en" label="English"></track>
|
||||
<!-- Tracks need an ending tag thanks to IE9 -->
|
||||
<track kind="subtitles" src="../shared/example-captions.vtt" srclang="en" label="English"></track>
|
||||
<!-- Tracks need an ending tag thanks to IE9 -->
|
||||
<p class="vjs-no-js">To view this video please enable JavaScript, and consider upgrading to a web browser that <a href="http://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a></p>
|
||||
</video>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
externo
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
externo
+652
-321
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
externo
+1
-1
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
Arquivo binário não exibido.
externo
+41
-135
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
externo
+1
-1
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
externo
+561
-120
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
externo
+16
-12
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
externo
+11
-9
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
externo
+1
-1
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
@@ -1,37 +1,30 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Video.js | HTML5 Video Player</title>
|
||||
|
||||
<!-- Chang URLs to wherever Video.js files will be hosted -->
|
||||
<!-- Default URLs assume the examples folder is included alongside video.js -->
|
||||
<link href="../../video-js.min.css" rel="stylesheet" type="text/css">
|
||||
<head>
|
||||
<title>Video.js | HTML5 Video Player</title>
|
||||
<link href="http://vjs.zencdn.net/5.0.2/video-js.css" rel="stylesheet">
|
||||
<script src="http://vjs.zencdn.net/ie8/1.1.0/videojs-ie8.min.js"></script>
|
||||
<script src="http://vjs.zencdn.net/5.0.2/video.js"></script>
|
||||
|
||||
<!-- Include ES5 shim, sham and html5 shiv for ie8 support -->
|
||||
<!-- Exclude this if you don't need ie8 support -->
|
||||
<script src="../../ie8/videojs-ie8.min.js"></script>
|
||||
|
||||
<!-- video.js must be in the <head> for older IEs to work. -->
|
||||
<script src="../../video.min.js"></script>
|
||||
|
||||
<!-- Unless using the CDN hosted version, update the URL to the Flash SWF -->
|
||||
<script>
|
||||
videojs.options.flash.swf = "../../video-js.swf";
|
||||
</script>
|
||||
</head>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<video id="example_video_1" class="video-js vjs-default-skin" controls preload="none" width="640" height="264"
|
||||
poster="http://video-js.zencoder.com/oceans-clip.png"
|
||||
data-setup="{}">
|
||||
<source src="http://video-js.zencoder.com/oceans-clip.mp4" type='video/mp4' />
|
||||
<source src="http://video-js.zencoder.com/oceans-clip.webm" type='video/webm' />
|
||||
<source src="http://video-js.zencoder.com/oceans-clip.ogv" type='video/ogg' />
|
||||
<track kind="captions" src="../shared/example-captions.vtt" srclang="en" label="English"></track><!-- Tracks need an ending tag thanks to IE9 -->
|
||||
<track kind="subtitles" src="../shared/example-captions.vtt" srclang="en" label="English"></track><!-- Tracks need an ending tag thanks to IE9 -->
|
||||
<video id="example_video_1" class="video-js vjs-default-skin" controls preload="none" width="640" height="264" poster="http://vjs.zencdn.net/v/oceans.png" data-setup="{}">
|
||||
<source src="http://vjs.zencdn.net/v/oceans.mp4" type="video/mp4">
|
||||
<source src="http://vjs.zencdn.net/v/oceans.webm" type="video/webm">
|
||||
<source src="http://vjs.zencdn.net/v/oceans.ogv" type="video/ogg">
|
||||
<track kind="captions" src="../shared/example-captions.vtt" srclang="en" label="English"></track>
|
||||
<!-- Tracks need an ending tag thanks to IE9 -->
|
||||
<track kind="subtitles" src="../shared/example-captions.vtt" srclang="en" label="English"></track>
|
||||
<!-- Tracks need an ending tag thanks to IE9 -->
|
||||
<p class="vjs-no-js">To view this video please enable JavaScript, and consider upgrading to a web browser that <a href="http://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a></p>
|
||||
</video>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
@@ -153,7 +153,7 @@ Language Codes
|
||||
--------------
|
||||
The following is a list of official language codes.
|
||||
|
||||
**NOTE:** For supported language translations, please see the [Languages Folder (/lang)](../../lang) folder located in the project root.
|
||||
**NOTE:** For supported language translations, please see the [Languages Folder (/lang)](https://github.com/videojs/video.js/tree/master/lang) folder located in the project root.
|
||||
|
||||
<table border="0" cellspacing="5" cellpadding="5">
|
||||
<tr>
|
||||
|
||||
@@ -135,4 +135,4 @@ notation.
|
||||
```
|
||||
|
||||
The [components guide](components.md) has an excellent breakdown of the structure of a player, you
|
||||
just need to remember to nest child components in a `children` object for each level.
|
||||
just need to remember to nest child components in a `children` array for each level.
|
||||
|
||||
@@ -45,3 +45,7 @@ If you've already initialized your video tag, you can activate a plugin at any t
|
||||
video.examplePlugin({ exampleOption: true });
|
||||
|
||||
That's it. Head on over to the [Video.js wiki](https://github.com/videojs/video.js/wiki/Plugins) and add your plugin to the list so everyone else can check it out.
|
||||
|
||||
## How should I use the Video.js icons in my plugin?
|
||||
|
||||
If you'd like to use any of the icons available in the [Video.js icon set](http://videojs.github.io/font/), please target them via the CSS class names instead of codepoints. The codepoints *may* change between versions of the font, so using the class names ensures that your plugin will stay up to date with any font changes.
|
||||
|
||||
@@ -6,11 +6,11 @@ Sometimes, you want to remove players after page load (in single page apps or mo
|
||||
Call `.dispose()`
|
||||
-----------------
|
||||
|
||||
To remove the html associated with your videojs player from the page always call the player's [`dispose()`](https://github.com/videojs/video.js/blob/stable/docs/api/vjs.Player.md#dispose) method:
|
||||
To remove the html associated with your videojs player from the page always call the player's [`dispose()`](http://docs.videojs.com/docs/api/player.html#Methodsdispose) method:
|
||||
|
||||
```javascript```
|
||||
var oldPlayer = document.getElementById('my-player');
|
||||
videojs(oldPlayer).dispose();
|
||||
videojs(oldPlayer).dispose();
|
||||
```
|
||||
|
||||
This method will:
|
||||
|
||||
@@ -9,7 +9,7 @@ Step 1: Include the Video.js Javascript and CSS files in the head of your page.
|
||||
You can download the Video.js source and host it on your own servers, or use the free CDN hosted version. As of Video.js 5.0, the source is [transpiled from ES2015](http://babeljs.io/) (formerly known as ES6) to [ES5](https://es5.github.io/), but IE8 only supports ES3. In order to continue to support IE8, we've bundled an [ES5 shim and sham](https://github.com/es-shims/es5-shim) together and hosted it on the CDN.
|
||||
|
||||
```html
|
||||
<script src="//vjs.zencdn.net/ie8/1.1.0/videojs-ie8.min.js"></script>
|
||||
<script src="//vjs.zencdn.net/ie8/1.1.1/videojs-ie8.min.js"></script>
|
||||
```
|
||||
|
||||
### CDN Version ###
|
||||
|
||||
@@ -9,7 +9,7 @@ enabled, you'll need to manually include them.
|
||||
|
||||
## Icons
|
||||
|
||||
You can view all of the icons available in the base theme by renaming and viewing [`icons.html.example`](../../sandbox/icons.html.example) in the sandbox directory.
|
||||
You can view all of the icons available in the base theme by renaming and viewing [`icons.html.example`](https://github.com/videojs/video.js/blob/master/sandbox/icons.html.example) in the sandbox directory.
|
||||
|
||||
## Customization
|
||||
|
||||
|
||||
+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.3.0",
|
||||
"version": "5.5.2",
|
||||
"copyright": "Copyright Brightcove, Inc. <https://www.brightcove.com/>",
|
||||
"license": "Apache-2.0",
|
||||
"keywords": [
|
||||
@@ -28,10 +28,10 @@
|
||||
"object.assign": "^4.0.1",
|
||||
"safe-json-parse": "^4.0.0",
|
||||
"tsml": "1.0.1",
|
||||
"videojs-font": "1.4.0",
|
||||
"videojs-ie8": "1.1.0",
|
||||
"videojs-font": "1.5.1",
|
||||
"videojs-ie8": "1.1.1",
|
||||
"videojs-swf": "5.0.1",
|
||||
"vtt.js": "git+https://github.com/gkatsev/vtt.js.git#vjs-v0.12.1",
|
||||
"videojs-vtt.js": "^0.12.1",
|
||||
"xhr": "~2.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -27,11 +27,11 @@
|
||||
</div>
|
||||
|
||||
<video id="vid1" class="video-js vjs-default-skin" controls preload="auto" width="640" height="264"
|
||||
poster="http://video-js.zencoder.com/oceans-clip.png"
|
||||
poster="http://vjs.zencdn.net/v/oceans.png"
|
||||
data-setup='{}'>
|
||||
<source src="http://video-js.zencoder.com/oceans-clip.mp4" type='video/mp4'>
|
||||
<source src="http://video-js.zencoder.com/oceans-clip.webm" type='video/webm'>
|
||||
<source src="http://video-js.zencoder.com/oceans-clip.ogv" type='video/ogg'>
|
||||
<source src="http://vjs.zencdn.net/v/oceans.mp4" type='video/mp4'>
|
||||
<source src="http://vjs.zencdn.net/v/oceans.webm" type='video/webm'>
|
||||
<source src="http://vjs.zencdn.net/v/oceans.ogv" type='video/ogg'>
|
||||
<track kind="captions" src="../docs/examples/shared/example-captions.vtt" srclang="en" label="English"></track><!-- Tracks need an ending tag thanks to IE9 -->
|
||||
<p class="vjs-no-js">To view this video please enable JavaScript, and consider upgrading to a web browser that <a href="http://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a></p>
|
||||
</video>
|
||||
|
||||
@@ -20,10 +20,10 @@
|
||||
<body>
|
||||
<p style="background-color:#eee; border: 1px solid #777; padding: 10px; font-size: .8em; line-height: 1.5em; font-family: Verdana, sans-serif;">This page shows you how to create, register and initialize a Video.js plugin.</p>
|
||||
|
||||
<video id="vid1" class="video-js vjs-default-skin" controls preload="auto" width="640" height="264" poster="http://video-js.zencoder.com/oceans-clip.png">
|
||||
<source src="http://video-js.zencoder.com/oceans-clip.mp4" type='video/mp4'>
|
||||
<source src="http://video-js.zencoder.com/oceans-clip.webm" type='video/webm'>
|
||||
<source src="http://video-js.zencoder.com/oceans-clip.ogv" type='video/ogg'>
|
||||
<video id="vid1" class="video-js vjs-default-skin" controls preload="auto" width="640" height="264" poster="http://vjs.zencdn.net/v/oceans.png">
|
||||
<source src="http://vjs.zencdn.net/v/oceans.mp4" type='video/mp4'>
|
||||
<source src="http://vjs.zencdn.net/v/oceans.webm" type='video/webm'>
|
||||
<source src="http://vjs.zencdn.net/v/oceans.ogv" type='video/ogg'>
|
||||
<p>Video Playback Not Supported</p>
|
||||
</video>
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
$icon-font-path: 'font' !default;
|
||||
$icon-codepoints: false !default;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
opacity: 1;
|
||||
border: 0.06666em solid $primary-foreground-color;
|
||||
|
||||
/* Need a slightly gray bg so it can be seen on black backgrounds */
|
||||
// Need a slightly gray bg so it can be seen on black backgrounds
|
||||
@include background-color-with-alpha($primary-background-color, $primary-background-transparency);
|
||||
@include border-radius(0.3em);
|
||||
@include transition(all 0.4s);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
}
|
||||
|
||||
.vjs-chapters-button .vjs-menu {
|
||||
left: -10em; /* (Width of vjs-menu - width of vjs-control) / 2 */
|
||||
left: -10em; // (Width of vjs-menu - width of vjs-control) / 2
|
||||
width: 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
.vjs-controls-disabled .vjs-control-bar,
|
||||
.vjs-using-native-controls .vjs-control-bar,
|
||||
.vjs-error .vjs-control-bar {
|
||||
/* !important is ok in this context. */
|
||||
// !important is ok in this context.
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
@@ -42,17 +42,16 @@
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
/* IE8 is flakey with fonts, and you have to change the actual content to force
|
||||
fonts to show/hide properly.
|
||||
- "\9" IE8 hack didn't work for this
|
||||
- Found in XP IE8 from http://modern.ie. Does not show up in "IE8 mode" in IE9
|
||||
*/
|
||||
// IE8 is flakey with fonts, and you have to change the actual content to force
|
||||
// fonts to show/hide properly.
|
||||
// - "\9" IE8 hack didn't work for this
|
||||
// Found in XP IE8 from http://modern.ie. Does not show up in "IE8 mode" in IE9
|
||||
$ie8screen: "\0screen";
|
||||
.vjs-user-inactive.vjs-playing .vjs-control-bar :before {
|
||||
@media #{$ie8screen} { content: ""; }
|
||||
}
|
||||
|
||||
/* IE 8 + 9 Support */
|
||||
// IE 8 + 9 Support
|
||||
.vjs-has-started.vjs-no-flex .vjs-control-bar {
|
||||
display: table;
|
||||
}
|
||||
|
||||
@@ -19,19 +19,19 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* Replacement for focus outline */
|
||||
// Replacement for focus outline
|
||||
.video-js .vjs-control:focus:before,
|
||||
.video-js .vjs-control:hover:before,
|
||||
.video-js .vjs-control:focus {
|
||||
text-shadow: 0em 0em 1em rgba($primary-foreground-color, 1);
|
||||
}
|
||||
|
||||
/* Hide control text visually, but have it available for screenreaders */
|
||||
// Hide control text visually, but have it available for screenreaders
|
||||
.video-js .vjs-control-text {
|
||||
@include hide-visually;
|
||||
}
|
||||
|
||||
/* IE 8 + 9 Support */
|
||||
// IE 8 + 9 Support
|
||||
.vjs-no-flex .vjs-control {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
.video-js .vjs-fullscreen-control {
|
||||
@extend .vjs-icon-fullscreen-enter;
|
||||
}
|
||||
/* Switch to the exit icon when the player is in fullscreen */
|
||||
// Switch to the exit icon when the player is in fullscreen
|
||||
.video-js.vjs-fullscreen .vjs-fullscreen-control {
|
||||
@extend .vjs-icon-fullscreen-exit;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
.video-js {
|
||||
/* display:inline-block would be closer to the video el's display:inline
|
||||
* but it results in flash reloading when going into fullscreen [#2205]
|
||||
*/
|
||||
// display:inline-block would be closer to the video el's display:inline
|
||||
// but it results in flash reloading when going into fullscreen [#2205]
|
||||
display: block;
|
||||
/* Make video.js videos align top when next to video elements */
|
||||
// Make video.js videos align top when next to video elements
|
||||
vertical-align: top;
|
||||
box-sizing: border-box;
|
||||
|
||||
@@ -11,21 +10,21 @@
|
||||
background-color: #000;
|
||||
position: relative;
|
||||
padding: 0;
|
||||
/* Start with 10px for base font size so other dimensions can be em based and
|
||||
easily calculable. */
|
||||
// Start with 10px for base font size so other dimensions can be em based and
|
||||
// easily calculable.
|
||||
font-size: 10px;
|
||||
line-height: 1;
|
||||
|
||||
/* Provide some basic defaults for fonts */
|
||||
// Provide some basic defaults for fonts
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
/* Avoiding helvetica: issue #376 */
|
||||
// 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. */
|
||||
// Fix for Firefox 9 fullscreen (only if it is enabled). Not needed when
|
||||
// checking fullScreenEnabled.
|
||||
&:-moz-full-screen { position: absolute; }
|
||||
|
||||
&:-webkit-full-screen {
|
||||
@@ -34,35 +33,35 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* All elements inherit border-box sizing */
|
||||
// All elements inherit border-box sizing
|
||||
.video-js *,
|
||||
.video-js *:before,
|
||||
.video-js *:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
/* List style reset */
|
||||
// List style reset
|
||||
.video-js ul {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
list-style-position: outside;
|
||||
|
||||
/* Important to specify each */
|
||||
// Important to specify each
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Fill the width of the containing element and use padding to create the
|
||||
desired aspect ratio. Default to 16x9 unless another ratio is given. */
|
||||
// Fill the width of the containing element and use padding to create the
|
||||
// desired aspect ratio. Default to 16x9 unless another ratio is given.
|
||||
@mixin apply-aspect-ratio($width, $height) {
|
||||
padding-top: 100% * ($height/$width);
|
||||
}
|
||||
|
||||
/* Not including a default AR in vjs-fluid because it would override
|
||||
the user set AR injected into the header. */
|
||||
// Not including a default AR in vjs-fluid because it would override
|
||||
// the user set AR injected into the header.
|
||||
.video-js.vjs-fluid,
|
||||
.video-js.vjs-16-9,
|
||||
.video-js.vjs-4-3 {
|
||||
@@ -84,8 +83,8 @@
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Playback technology elements expand to the width/height of the containing div
|
||||
<video> or <object> */
|
||||
// Playback technology elements expand to the width/height of the containing div
|
||||
// <video> or <object>
|
||||
.video-js .vjs-tech {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@@ -94,12 +93,12 @@
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Fullscreen Styles */
|
||||
// Fullscreen Styles
|
||||
body.vjs-full-window {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
/* Fix for IE6 full-window. http://www.cssplay.co.uk/layouts/fixed.html */
|
||||
// Fix for IE6 full-window. http://www.cssplay.co.uk/layouts/fixed.html
|
||||
overflow-y: auto;
|
||||
}
|
||||
.vjs-full-window .video-js.vjs-fullscreen {
|
||||
@@ -114,7 +113,7 @@ body.vjs-full-window {
|
||||
.video-js.vjs-fullscreen {
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
/* Undo any aspect ratio padding for fluid layouts */
|
||||
// Undo any aspect ratio padding for fluid layouts
|
||||
padding-top: 0 !important;
|
||||
}
|
||||
.video-js.vjs-fullscreen.vjs-user-inactive {
|
||||
@@ -122,7 +121,7 @@ body.vjs-full-window {
|
||||
}
|
||||
|
||||
|
||||
/* Hide disabled or unsupported controls. */
|
||||
// Hide disabled or unsupported controls.
|
||||
.vjs-hidden { display: none !important; }
|
||||
|
||||
// Visually hidden offscreen, but accessible to screen readers.
|
||||
@@ -140,10 +139,10 @@ body.vjs-full-window {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
/* In IE8 w/ no JavaScript (no HTML5 shim), the video tag doesn't register.
|
||||
The .video-js classname on the video tag also isn't considered.
|
||||
This optional paragraph inside the video tag can provide a message to users
|
||||
about what's required to play video. */
|
||||
// In IE8 w/ no JavaScript (no HTML5 shim), the video tag doesn't register.
|
||||
// The .video-js classname on the video tag also isn't considered.
|
||||
// This optional paragraph inside the video tag can provide a message to users
|
||||
// about what's required to play video.
|
||||
.vjs-no-js {
|
||||
padding: 20px;
|
||||
color: #fff;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
margin: -25px 0 0 -25px;
|
||||
opacity: 0.85;
|
||||
|
||||
/* Need to fix centered page layouts */
|
||||
// Need to fix centered page layouts
|
||||
text-align: left;
|
||||
|
||||
border: 6px solid rgba($primary-background-color, $primary-background-transparency);
|
||||
@@ -33,14 +33,14 @@
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
border-radius: inherit;
|
||||
/* Keep 100% opacity so they don't show through each other */
|
||||
// Keep 100% opacity so they don't show through each other
|
||||
opacity: 1;
|
||||
border: inherit;
|
||||
border-color: transparent;
|
||||
border-top-color: white;
|
||||
}
|
||||
|
||||
/* only animate when showing because it can be processor heavy */
|
||||
// only animate when showing because it can be processor heavy
|
||||
.vjs-seeking .vjs-loading-spinner:before,
|
||||
.vjs-seeking .vjs-loading-spinner:after,
|
||||
.vjs-waiting .vjs-loading-spinner:before,
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Used for IE8 fallback */
|
||||
// Used for IE8 fallback
|
||||
.vjs-poster img {
|
||||
display: block;
|
||||
vertical-align: middle;
|
||||
@@ -25,23 +25,23 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Hide the poster after the video has started playing */
|
||||
// Hide the poster after the video has started playing
|
||||
.vjs-has-started .vjs-poster {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Don't hide the poster if we're playing audio */
|
||||
// Don't hide the poster if we're playing audio
|
||||
.vjs-audio.vjs-has-started .vjs-poster {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Hide the poster when controls are disabled because it's clickable
|
||||
and the native poster can take over */
|
||||
// Hide the poster when controls are disabled because it's clickable
|
||||
// and the native poster can take over
|
||||
.vjs-controls-disabled .vjs-poster {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Hide the poster when native controls are used otherwise it covers them */
|
||||
// Hide the poster when native controls are used otherwise it covers them
|
||||
.vjs-using-native-controls .vjs-poster {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
/**
|
||||
* Let's talk pixel math!
|
||||
* Start with a base font size of 10px (assuming that hasn't changed)
|
||||
* No Hover:
|
||||
* - Progress holder is 3px
|
||||
* - Progress handle is 9px
|
||||
* - Progress handle is pulled up 3px to center it.
|
||||
*
|
||||
* Hover:
|
||||
* - Progress holder becomes 5px
|
||||
* - Progress handle becomes 15px
|
||||
* - Progress handle is pulled up 5px to center it
|
||||
*/
|
||||
//
|
||||
// Let's talk pixel math!
|
||||
// Start with a base font size of 10px (assuming that hasn't changed)
|
||||
// No Hover:
|
||||
// - Progress holder is 3px
|
||||
// - Progress handle is 9px
|
||||
// - Progress handle is pulled up 3px to center it.
|
||||
//
|
||||
// Hover:
|
||||
// - Progress holder becomes 5px
|
||||
// - Progress handle becomes 15px
|
||||
// - Progress handle is pulled up 5px to center it
|
||||
//
|
||||
|
||||
.video-js .vjs-progress-control {
|
||||
@include flex(auto);
|
||||
@@ -21,30 +21,30 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Box containing play and load progresses. Also acts as seek scrubber. */
|
||||
// Box containing play and load progresses. Also acts as seek scrubber.
|
||||
.video-js .vjs-progress-holder {
|
||||
@include flex(auto);
|
||||
@include transition(all 0.2s);
|
||||
height: 0.3em;
|
||||
}
|
||||
|
||||
/* We need an increased hit area on hover */
|
||||
// We need an increased hit area on hover
|
||||
.video-js .vjs-progress-control:hover .vjs-progress-holder {
|
||||
font-size: 1.666666666666666666em
|
||||
}
|
||||
|
||||
/* Also show the current time tooltip */
|
||||
/* If we let the font size grow as much as everything else, the current time tooltip ends up
|
||||
ginormous. If you'd like to enable the current time tooltip all the time, this should be disabled
|
||||
to avoid a weird hitch when you roll off the hover. */
|
||||
|
||||
// Also show the current time tooltip
|
||||
.video-js .vjs-progress-control:hover .vjs-mouse-display:after,
|
||||
.video-js .vjs-progress-control:hover .vjs-play-progress:after {
|
||||
display: block;
|
||||
|
||||
/* If we let the font size grow as much as everything else, the current time tooltip ends up
|
||||
ginormous. If you'd like to enable the current time tooltip all the time, this should be disabled
|
||||
to avoid a weird hitch when you roll off the hover. */
|
||||
font-size: 0.6em;
|
||||
}
|
||||
|
||||
/* Progress Bars */
|
||||
// Progress Bars
|
||||
.video-js .vjs-progress-holder .vjs-play-progress,
|
||||
.video-js .vjs-progress-holder .vjs-load-progress,
|
||||
.video-js .vjs-progress-holder .vjs-load-progress div {
|
||||
@@ -53,9 +53,9 @@
|
||||
height: 0.3em;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
/* updated by javascript during playback */
|
||||
// updated by javascript during playback
|
||||
width: 0;
|
||||
/* Needed for IE6 *///
|
||||
// Needed for IE6
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
@@ -81,9 +81,9 @@
|
||||
}
|
||||
|
||||
// Current Time "tooltip"
|
||||
// By default this is hidden and only shown when hovering over the progress control
|
||||
.video-js .vjs-mouse-display:after,
|
||||
.video-js .vjs-play-progress:after {
|
||||
/* By default this is hidden and only shown when hovering over the progress control */
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: -2.4em;
|
||||
@@ -101,18 +101,18 @@
|
||||
}
|
||||
|
||||
.video-js .vjs-load-progress {
|
||||
/* For IE8 we'll lighten the color */
|
||||
background: ligthen($secondary-background-color, 25%);
|
||||
/* Otherwise we'll rely on stacked opacities */
|
||||
// For IE8 we'll lighten the color
|
||||
background: lighten($secondary-background-color, 25%);
|
||||
// Otherwise we'll rely on stacked opacities
|
||||
background: rgba($secondary-background-color, $secondary-background-transparency);
|
||||
}
|
||||
|
||||
/* there are child elements of the load progress bar that represent the
|
||||
specific time ranges that have been buffered */
|
||||
// there are child elements of the load progress bar that represent the
|
||||
// specific time ranges that have been buffered
|
||||
.video-js .vjs-load-progress div {
|
||||
/* For IE8 we'll lighten the color */
|
||||
background: ligthen($secondary-background-color, 50%);
|
||||
/* Otherwise we'll rely on stacked opacities */
|
||||
// For IE8 we'll lighten the color
|
||||
background: lighten($secondary-background-color, 50%);
|
||||
// Otherwise we'll rely on stacked opacities
|
||||
background: rgba($secondary-background-color, 0.75);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Emulated tracks */
|
||||
// Emulated tracks
|
||||
.vjs-text-track-display {
|
||||
position: absolute;
|
||||
bottom: 3em;
|
||||
@@ -8,30 +8,30 @@
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Move captions down when controls aren't being shown */
|
||||
// Move captions down when controls aren't being shown
|
||||
.video-js.vjs-user-inactive.vjs-playing .vjs-text-track-display {
|
||||
bottom: 1em;
|
||||
}
|
||||
|
||||
/* Individual tracks */
|
||||
// Individual tracks
|
||||
.video-js .vjs-text-track {
|
||||
font-size: 1.4em;
|
||||
text-align: center;
|
||||
margin-bottom: 0.1em;
|
||||
/* Transparent black background, or fallback to all black (oldIE) */
|
||||
// Transparent black background, or fallback to all black (oldIE)
|
||||
@include background-color-with-alpha(#000, 0.5);
|
||||
}
|
||||
|
||||
.vjs-subtitles { color: #fff /* Subtitles are white */; }
|
||||
.vjs-captions { color: #fc6 /* Captions are yellow */; }
|
||||
.vjs-subtitles { color: #fff; } // Subtitles are white
|
||||
.vjs-captions { color: #fc6; } // Captions are yellow
|
||||
.vjs-tt-cue { display: block; }
|
||||
|
||||
/* Native tracks */
|
||||
// Native tracks
|
||||
video::-webkit-media-text-track-display {
|
||||
@include transform(translateY(-3em));
|
||||
}
|
||||
|
||||
/* Move captions down when controls aren't being shown */
|
||||
// Move captions down when controls aren't being shown
|
||||
.video-js.vjs-user-inactive.vjs-playing video::-webkit-media-text-track-display {
|
||||
@include transform(translateY(-1.5em));
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* We need the extra specificity that referencing .vjs-no-flex provides. */
|
||||
// We need the extra specificity that referencing .vjs-no-flex provides.
|
||||
.video-js .vjs-current-time,
|
||||
.vjs-no-flex .vjs-current-time {
|
||||
display: none;
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
}
|
||||
|
||||
.video-js .vjs-volume-bar {
|
||||
margin: 1.35em;
|
||||
margin: 1.35em 0.45em;
|
||||
}
|
||||
|
||||
.vjs-volume-bar.vjs-slider-horizontal {
|
||||
@@ -36,6 +36,7 @@
|
||||
.vjs-volume-bar.vjs-slider-vertical {
|
||||
width: 0.3em;
|
||||
height: 5em;
|
||||
margin: 1.35em auto;
|
||||
}
|
||||
|
||||
.video-js .vjs-volume-level {
|
||||
@@ -73,7 +74,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* Assumes volume starts at 1.0. */
|
||||
// Assumes volume starts at 1.0.
|
||||
.vjs-volume-bar.vjs-slider-vertical .vjs-volume-level {
|
||||
height: 100%;
|
||||
}
|
||||
@@ -82,11 +83,11 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* The volume menu button is like menu buttons (captions/subtitles) but works
|
||||
a little differently. It needs to be possible to tab to the volume slider
|
||||
without hitting space bar on the menu button. To do this we're not using
|
||||
display:none to hide the slider menu by default, and instead setting the
|
||||
width and height to zero. */
|
||||
// The volume menu button is like menu buttons (captions/subtitles) but works
|
||||
// a little differently. It needs to be possible to tab to the volume slider
|
||||
// without hitting space bar on the menu button. To do this we're not using
|
||||
// display:none to hide the slider menu by default, and instead setting the
|
||||
// width and height to zero.
|
||||
.vjs-menu-button-popup.vjs-volume-menu-button .vjs-menu {
|
||||
display: block;
|
||||
width: 0;
|
||||
@@ -124,7 +125,7 @@ width and height to zero. */
|
||||
}
|
||||
|
||||
.vjs-volume-menu-button.vjs-menu-button-inline .vjs-menu-content {
|
||||
/* An inline volume should never have a menu background color.
|
||||
This protects it from external changes to background colors. */
|
||||
// An inline volume should never have a menu background color.
|
||||
// This protects it from external changes to background colors.
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
width: auto;
|
||||
|
||||
position: absolute;
|
||||
left: 2.2222222em;
|
||||
left: 4em;
|
||||
top: 0;
|
||||
|
||||
padding: 0;
|
||||
|
||||
@@ -3,19 +3,19 @@
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 10em;
|
||||
left: -3em; /* (Width of vjs-menu - width of button) / 2 */
|
||||
left: -3em; // (Width of vjs-menu - width of button) / 2
|
||||
height: 0em;
|
||||
margin-bottom: 1.5em;
|
||||
border-top-color: rgba($primary-background-color, $primary-background-transparency); /* Same as ul background */
|
||||
border-top-color: rgba($primary-background-color, $primary-background-transparency); // Same as ul background
|
||||
}
|
||||
|
||||
/* Button Pop-up Menu */
|
||||
// Button Pop-up Menu
|
||||
.vjs-menu-button-popup .vjs-menu .vjs-menu-content {
|
||||
@include background-color-with-alpha($primary-background-color, $primary-background-transparency);
|
||||
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
bottom: 1.5em; /* Same bottom as vjs-menu border-top */
|
||||
bottom: 1.5em; // Same bottom as vjs-menu border-top
|
||||
max-height: 15em;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* prevent menus from opening while scrubbing (FF, IE) */
|
||||
// prevent menus from opening while scrubbing (FF, IE)
|
||||
.vjs-scrubbing .vjs-menu-button:hover .vjs-menu {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,11 @@
|
||||
@import "private-variables";
|
||||
@import "utilities";
|
||||
|
||||
@import "../../node_modules/videojs-font/scss/icons";
|
||||
@if $icon-codepoints {
|
||||
@import "../../node_modules/videojs-font/scss/icons-codepoints";
|
||||
} @else {
|
||||
@import "../../node_modules/videojs-font/scss/icons";
|
||||
}
|
||||
|
||||
@import "components/layout";
|
||||
@import "components/big-play";
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
$icon-codepoints: true;
|
||||
|
||||
@import "video-js";
|
||||
@@ -77,21 +77,13 @@ class ChaptersButton extends TextTrackButton {
|
||||
let chaptersTrack;
|
||||
let items = this.items = [];
|
||||
|
||||
for (let i = 0, l = tracks.length; i < l; i++) {
|
||||
for (let i = 0, length = tracks.length; i < length; i++) {
|
||||
let track = tracks[i];
|
||||
|
||||
if (track['kind'] === this.kind_) {
|
||||
if (!track.cues) {
|
||||
track['mode'] = 'hidden';
|
||||
/* jshint loopfunc:true */
|
||||
// TODO see if we can figure out a better way of doing this https://github.com/videojs/video.js/issues/1864
|
||||
window.setTimeout(Fn.bind(this, function() {
|
||||
this.createMenu();
|
||||
}), 100);
|
||||
/* jshint loopfunc:false */
|
||||
} else {
|
||||
chaptersTrack = track;
|
||||
break;
|
||||
}
|
||||
chaptersTrack = track;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +97,17 @@ class ChaptersButton extends TextTrackButton {
|
||||
}));
|
||||
}
|
||||
|
||||
if (chaptersTrack) {
|
||||
if (chaptersTrack && chaptersTrack.cues == null) {
|
||||
chaptersTrack['mode'] = 'hidden';
|
||||
|
||||
let remoteTextTrackEl = this.player_.remoteTextTrackEls().getTrackElementByTrack_(chaptersTrack);
|
||||
|
||||
if (remoteTextTrackEl) {
|
||||
remoteTextTrackEl.addEventListener('load', (event) => this.update());
|
||||
}
|
||||
}
|
||||
|
||||
if (chaptersTrack && chaptersTrack.cues && chaptersTrack.cues.length > 0) {
|
||||
let cues = chaptersTrack['cues'], cue;
|
||||
|
||||
for (let i = 0, l = cues.length; i < l; i++) {
|
||||
@@ -120,6 +122,7 @@ class ChaptersButton extends TextTrackButton {
|
||||
|
||||
menu.addChild(mi);
|
||||
}
|
||||
|
||||
this.addChild(menu);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
* @file volume-menu-button.js
|
||||
*/
|
||||
import Button from '../button.js';
|
||||
import * as Fn from '../utils/fn.js';
|
||||
import Component from '../component.js';
|
||||
import Menu from '../menu/menu.js';
|
||||
import MenuButton from '../menu/menu-button.js';
|
||||
import MuteToggle from './mute-toggle.js';
|
||||
import VolumeBar from './volume-control/volume-bar.js';
|
||||
import document from 'global/document';
|
||||
|
||||
/**
|
||||
* Button for volume menu
|
||||
@@ -100,6 +102,9 @@ class VolumeMenuButton extends MenuButton {
|
||||
menu.addChild(vb);
|
||||
|
||||
this.volumeBar = vb;
|
||||
|
||||
this.attachVolumeBarEvents();
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
@@ -113,6 +118,18 @@ class VolumeMenuButton extends MenuButton {
|
||||
super.handleClick();
|
||||
}
|
||||
|
||||
attachVolumeBarEvents() {
|
||||
this.on(['mousedown', 'touchdown'], this.handleMouseDown);
|
||||
}
|
||||
|
||||
handleMouseDown(event) {
|
||||
this.on(['mousemove', 'touchmove'], Fn.bind(this.volumeBar, this.volumeBar.handleMouseMove));
|
||||
this.on(document, ['mouseup', 'touchend'], this.handleMouseUp);
|
||||
}
|
||||
|
||||
handleMouseUp(event) {
|
||||
this.off(['mousemove', 'touchmove'], Fn.bind(this.volumeBar, this.volumeBar.handleMouseMove));
|
||||
}
|
||||
}
|
||||
|
||||
VolumeMenuButton.prototype.volumeUpdate = MuteToggle.prototype.update;
|
||||
|
||||
@@ -52,6 +52,7 @@ class ErrorDisplay extends ModalDialog {
|
||||
|
||||
ErrorDisplay.prototype.options_ = mergeOptions(ModalDialog.prototype.options_, {
|
||||
fillAlways: true,
|
||||
temporary: false,
|
||||
uncloseable: true
|
||||
});
|
||||
|
||||
|
||||
+51
-4
@@ -224,7 +224,7 @@ class Player extends Component {
|
||||
// prevent dispose from being called twice
|
||||
this.off('dispose');
|
||||
|
||||
if (this.styleEl_) {
|
||||
if (this.styleEl_ && this.styleEl_.parentNode) {
|
||||
this.styleEl_.parentNode.removeChild(this.styleEl_);
|
||||
}
|
||||
|
||||
@@ -612,6 +612,30 @@ class Player extends Component {
|
||||
this.tech_ = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a reference to the current tech.
|
||||
* It will only return a reference to the tech if given an object with the
|
||||
* `IWillNotUseThisInPlugins` property on it. This is try and prevent misuse
|
||||
* of techs by plugins.
|
||||
*
|
||||
* @param {Object}
|
||||
* @return {Object} The Tech
|
||||
* @method tech
|
||||
*/
|
||||
tech(safety) {
|
||||
if (safety && safety.IWillNotUseThisInPlugins) {
|
||||
return this.tech_;
|
||||
}
|
||||
let errorText = `
|
||||
Please make sure that you are not using this inside of a plugin.
|
||||
To disable this alert and error, please pass in an object with
|
||||
\`IWillNotUseThisInPlugins\` to the \`tech\` method. See
|
||||
https://github.com/videojs/video.js/issues/2617 for more info.
|
||||
`;
|
||||
window.alert(errorText);
|
||||
throw new Error(errorText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up click and touch listeners for the playback element
|
||||
*
|
||||
@@ -696,7 +720,7 @@ class Player extends Component {
|
||||
// In Safari (5.1.1), when we move the video element into the container div, autoplay doesn't work.
|
||||
// In Chrome (15), if you have autoplay + a poster + no controls, the video gets hidden (but audio plays)
|
||||
// This fixes both issues. Need to wait for API, so it updates displays correctly
|
||||
if (this.tag && this.options_.autoplay && this.paused()) {
|
||||
if (this.src() && this.tag && this.options_.autoplay && this.paused()) {
|
||||
delete this.tag.poster; // Chrome Fix. Fixed in Chrome v16.
|
||||
this.play();
|
||||
}
|
||||
@@ -1899,6 +1923,19 @@ class Player extends Component {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the player. Loads the first tech in the techOrder,
|
||||
* and calls `reset` on the tech`.
|
||||
*
|
||||
* @return {Player} Returns the player
|
||||
* @method reset
|
||||
*/
|
||||
reset() {
|
||||
this.loadTech_(toTitleCase(this.options_.techOrder[0]), null);
|
||||
this.techCall_('reset');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fully qualified URL of the current source value e.g. http://mysite.com/video.mp4
|
||||
* Can be used in conjuction with `currentType` to assist in rebuilding the current source object.
|
||||
@@ -1942,7 +1979,7 @@ class Player extends Component {
|
||||
/**
|
||||
* Get or set the autoplay attribute.
|
||||
*
|
||||
* @param {Boolean} value Boolean to determine if preload should be used
|
||||
* @param {Boolean} value Boolean to determine if video should autoplay
|
||||
* @return {String} The autoplay attribute value when getting
|
||||
* @return {Player} Returns the player when setting
|
||||
* @method autoplay
|
||||
@@ -1959,7 +1996,7 @@ class Player extends Component {
|
||||
/**
|
||||
* Get or set the loop attribute on the video element.
|
||||
*
|
||||
* @param {Boolean} value Boolean to determine if preload should be used
|
||||
* @param {Boolean} value Boolean to determine if video should loop
|
||||
* @return {String} The loop attribute value when getting
|
||||
* @return {Player} Returns the player when setting
|
||||
* @method loop
|
||||
@@ -2455,6 +2492,16 @@ class Player extends Component {
|
||||
return this.tech_ && this.tech_['remoteTextTracks']();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of remote html track elements
|
||||
*
|
||||
* @return {HTMLTrackElement[]}
|
||||
* @method remoteTextTrackEls
|
||||
*/
|
||||
remoteTextTrackEls() {
|
||||
return this.tech_ && this.tech_['remoteTextTrackEls']();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a text track
|
||||
* In addition to the W3C settings we allow adding additional info through options.
|
||||
|
||||
+60
-19
@@ -49,6 +49,7 @@ class Html5 extends Tech {
|
||||
while (nodesLength--) {
|
||||
let node = nodes[nodesLength];
|
||||
let nodeName = node.nodeName.toLowerCase();
|
||||
|
||||
if (nodeName === 'track') {
|
||||
if (!this.featuresNativeTextTracks) {
|
||||
// Empty video tag tracks so the built-in player doesn't use them also.
|
||||
@@ -57,6 +58,8 @@ class Html5 extends Tech {
|
||||
// captions and subtitles. videoElement.textTracks
|
||||
removeNodes.push(node);
|
||||
} else {
|
||||
// store HTMLTrackElement and TextTrack to remote list
|
||||
this.remoteTextTrackEls().addTrackElement_(node);
|
||||
this.remoteTextTracks().addTrack_(node.track);
|
||||
}
|
||||
}
|
||||
@@ -486,6 +489,15 @@ class Html5 extends Tech {
|
||||
this.el_.load();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the tech. Removes all sources and calls `load`.
|
||||
*
|
||||
* @method reset
|
||||
*/
|
||||
reset() {
|
||||
Html5.resetMediaElement(this.el_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current source
|
||||
*
|
||||
@@ -722,11 +734,11 @@ class Html5 extends Tech {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a remote text track object
|
||||
* Creates a remote text track object and returns a html track element
|
||||
*
|
||||
* @param {Object} options The object should contain values for
|
||||
* kind, language, label and src (location of the WebVTT file)
|
||||
* @return {TextTrackObject}
|
||||
* @return {HTMLTrackElement}
|
||||
* @method addRemoteTextTrack
|
||||
*/
|
||||
addRemoteTextTrack(options={}) {
|
||||
@@ -734,32 +746,34 @@ class Html5 extends Tech {
|
||||
return super.addRemoteTextTrack(options);
|
||||
}
|
||||
|
||||
var track = document.createElement('track');
|
||||
let htmlTrackElement = document.createElement('track');
|
||||
|
||||
if (options['kind']) {
|
||||
track['kind'] = options['kind'];
|
||||
if (options.kind) {
|
||||
htmlTrackElement.kind = options.kind;
|
||||
}
|
||||
if (options['label']) {
|
||||
track['label'] = options['label'];
|
||||
if (options.label) {
|
||||
htmlTrackElement.label = options.label;
|
||||
}
|
||||
if (options['language'] || options['srclang']) {
|
||||
track['srclang'] = options['language'] || options['srclang'];
|
||||
if (options.language || options.srclang) {
|
||||
htmlTrackElement.srclang = options.language || options.srclang;
|
||||
}
|
||||
if (options['default']) {
|
||||
track['default'] = options['default'];
|
||||
if (options.default) {
|
||||
htmlTrackElement.default = options.default;
|
||||
}
|
||||
if (options['id']) {
|
||||
track['id'] = options['id'];
|
||||
if (options.id) {
|
||||
htmlTrackElement.id = options.id;
|
||||
}
|
||||
if (options['src']) {
|
||||
track['src'] = options['src'];
|
||||
if (options.src) {
|
||||
htmlTrackElement.src = options.src;
|
||||
}
|
||||
|
||||
this.el().appendChild(track);
|
||||
this.el().appendChild(htmlTrackElement);
|
||||
|
||||
this.remoteTextTracks().addTrack_(track.track);
|
||||
// store HTMLTrackElement and TextTrack to remote list
|
||||
this.remoteTextTrackEls().addTrackElement_(htmlTrackElement);
|
||||
this.remoteTextTracks().addTrack_(htmlTrackElement.track);
|
||||
|
||||
return track;
|
||||
return htmlTrackElement;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -773,8 +787,12 @@ class Html5 extends Tech {
|
||||
return super.removeRemoteTextTrack(track);
|
||||
}
|
||||
|
||||
var tracks, i;
|
||||
let tracks, i;
|
||||
|
||||
let trackElement = this.remoteTextTrackEls().getTrackElementByTrack_(track);
|
||||
|
||||
// remove HTMLTrackElement and TextTrack from remote list
|
||||
this.remoteTextTrackEls().removeTrackElement_(trackElement);
|
||||
this.remoteTextTracks().removeTrack_(track);
|
||||
|
||||
tracks = this.$$('track');
|
||||
@@ -1092,6 +1110,29 @@ Html5.disposeMediaElement = function(el){
|
||||
}
|
||||
};
|
||||
|
||||
Html5.resetMediaElement = function(el){
|
||||
if (!el) { return; }
|
||||
|
||||
let sources = el.querySelectorAll('source');
|
||||
let i = sources.length;
|
||||
while (i--) {
|
||||
el.removeChild(sources[i]);
|
||||
}
|
||||
|
||||
// remove any src reference.
|
||||
// not setting `src=''` because that throws an error
|
||||
el.removeAttribute('src');
|
||||
|
||||
if (typeof el.load === 'function') {
|
||||
// wrapping in an iife so it's not deoptimized (#1060#discussion_r10324473)
|
||||
(function() {
|
||||
try {
|
||||
el.load();
|
||||
} catch (e) {}
|
||||
})();
|
||||
}
|
||||
};
|
||||
|
||||
Component.registerComponent('Html5', Html5);
|
||||
Tech.registerTech('Html5', Html5);
|
||||
export default Html5;
|
||||
|
||||
+44
-9
@@ -5,6 +5,9 @@
|
||||
*/
|
||||
|
||||
import Component from '../component';
|
||||
import HTMLTrackElement from '../tracks/html-track-element';
|
||||
import HTMLTrackElementList from '../tracks/html-track-element-list';
|
||||
import mergeOptions from '../utils/merge-options.js';
|
||||
import TextTrack from '../tracks/text-track';
|
||||
import TextTrackList from '../tracks/text-track-list';
|
||||
import * as Fn from '../utils/fn.js';
|
||||
@@ -233,6 +236,13 @@ class Tech extends Component {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the tech. Removes all sources and resets readyState.
|
||||
*
|
||||
* @method reset
|
||||
*/
|
||||
reset() {}
|
||||
|
||||
/**
|
||||
* When invoked without an argument, returns a MediaError object
|
||||
* representing the current error state of the player or null if
|
||||
@@ -316,7 +326,7 @@ class Tech extends Component {
|
||||
|
||||
if (!window['WebVTT'] && this.el().parentNode != null) {
|
||||
let script = document.createElement('script');
|
||||
script.src = this.options_['vtt.js'] || '../node_modules/vtt.js/dist/vtt.js';
|
||||
script.src = this.options_['vtt.js'] || '../node_modules/videojs-vtt.js/dist/vtt.js';
|
||||
this.el().parentNode.appendChild(script);
|
||||
window['WebVTT'] = true;
|
||||
}
|
||||
@@ -370,6 +380,17 @@ class Tech extends Component {
|
||||
return this.remoteTextTracks_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get remote htmltrackelements
|
||||
*
|
||||
* @returns {HTMLTrackElementList}
|
||||
* @method remoteTextTrackEls
|
||||
*/
|
||||
remoteTextTrackEls() {
|
||||
this.remoteTextTrackEls_ = this.remoteTextTrackEls_ || new HTMLTrackElementList();
|
||||
return this.remoteTextTrackEls_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a remote text track object
|
||||
*
|
||||
@@ -389,19 +410,28 @@ class Tech extends Component {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a remote text track object
|
||||
* Creates a remote text track object and returns a emulated html track element
|
||||
*
|
||||
* @param {Object} options The object should contain values for
|
||||
* kind, language, label and src (location of the WebVTT file)
|
||||
* @return {TextTrackObject}
|
||||
* @return {HTMLTrackElement}
|
||||
* @method addRemoteTextTrack
|
||||
*/
|
||||
addRemoteTextTrack(options) {
|
||||
let track = createTrackHelper(this, options.kind, options.label, options.language, options);
|
||||
this.remoteTextTracks().addTrack_(track);
|
||||
return {
|
||||
track: track
|
||||
};
|
||||
let track = mergeOptions(options, {
|
||||
tech: this
|
||||
});
|
||||
|
||||
let htmlTrackElement = new HTMLTrackElement(track);
|
||||
|
||||
// store HTMLTrackElement and TextTrack to remote list
|
||||
this.remoteTextTrackEls().addTrackElement_(htmlTrackElement);
|
||||
this.remoteTextTracks().addTrack_(htmlTrackElement.track);
|
||||
|
||||
// must come after remoteTextTracks()
|
||||
this.textTracks().addTrack_(htmlTrackElement.track);
|
||||
|
||||
return htmlTrackElement;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -412,6 +442,11 @@ class Tech extends Component {
|
||||
*/
|
||||
removeRemoteTextTrack(track) {
|
||||
this.textTracks().removeTrack_(track);
|
||||
|
||||
let trackElement = this.remoteTextTrackEls().getTrackElementByTrack_(track);
|
||||
|
||||
// remove HTMLTrackElement and TextTrack from remote list
|
||||
this.remoteTextTrackEls().removeTrackElement_(trackElement);
|
||||
this.remoteTextTracks().removeTrack_(track);
|
||||
}
|
||||
|
||||
@@ -440,7 +475,7 @@ class Tech extends Component {
|
||||
/*
|
||||
* Return whether the argument is a Tech or not.
|
||||
* Can be passed either a Class like `Html5` or a instance like `player.tech_`
|
||||
*
|
||||
*
|
||||
* @param {Object} component An item to check
|
||||
* @return {Boolean} Whether it is a tech or not
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* @file html-track-element.js
|
||||
*/
|
||||
|
||||
import * as browser from '../utils/browser.js';
|
||||
import document from 'global/document';
|
||||
|
||||
class HtmlTrackElementList {
|
||||
constructor(trackElements = []) {
|
||||
let list = this;
|
||||
|
||||
if (browser.IS_IE8) {
|
||||
list = document.createElement('custom');
|
||||
|
||||
for (let prop in HtmlTrackElementList.prototype) {
|
||||
if (prop !== 'constructor') {
|
||||
list[prop] = HtmlTrackElementList.prototype[prop];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list.trackElements_ = [];
|
||||
|
||||
Object.defineProperty(list, 'length', {
|
||||
get() {
|
||||
return this.trackElements_.length;
|
||||
}
|
||||
});
|
||||
|
||||
for (let i = 0, length = trackElements.length; i < length; i++) {
|
||||
list.addTrackElement_(trackElements[i]);
|
||||
}
|
||||
|
||||
if (browser.IS_IE8) {
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
addTrackElement_(trackElement) {
|
||||
this.trackElements_.push(trackElement);
|
||||
}
|
||||
|
||||
getTrackElementByTrack_(track) {
|
||||
let trackElement_;
|
||||
|
||||
for (let i = 0, length = this.trackElements_.length; i < length; i++) {
|
||||
if (track === this.trackElements_[i].track) {
|
||||
trackElement_ = this.trackElements_[i];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return trackElement_;
|
||||
}
|
||||
|
||||
removeTrackElement_(trackElement) {
|
||||
for (let i = 0, length = this.trackElements_.length; i < length; i++) {
|
||||
if (trackElement === this.trackElements_[i]) {
|
||||
this.trackElements_.splice(i, 1);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default HtmlTrackElementList;
|
||||
@@ -0,0 +1,97 @@
|
||||
import * as browser from '../utils/browser.js';
|
||||
import document from 'global/document';
|
||||
import EventTarget from '../event-target';
|
||||
import TextTrack from '../tracks/text-track';
|
||||
|
||||
const NONE = 0;
|
||||
const LOADING = 1;
|
||||
const LOADED = 2;
|
||||
const ERROR = 3;
|
||||
|
||||
/**
|
||||
* https://html.spec.whatwg.org/multipage/embedded-content.html#htmltrackelement
|
||||
*
|
||||
* interface HTMLTrackElement : HTMLElement {
|
||||
* attribute DOMString kind;
|
||||
* attribute DOMString src;
|
||||
* attribute DOMString srclang;
|
||||
* attribute DOMString label;
|
||||
* attribute boolean default;
|
||||
*
|
||||
* const unsigned short NONE = 0;
|
||||
* const unsigned short LOADING = 1;
|
||||
* const unsigned short LOADED = 2;
|
||||
* const unsigned short ERROR = 3;
|
||||
* readonly attribute unsigned short readyState;
|
||||
*
|
||||
* readonly attribute TextTrack track;
|
||||
* };
|
||||
*
|
||||
* @param {Object} options TextTrack configuration
|
||||
* @class HTMLTrackElement
|
||||
*/
|
||||
|
||||
class HTMLTrackElement extends EventTarget {
|
||||
constructor(options = {}) {
|
||||
super();
|
||||
|
||||
let readyState,
|
||||
trackElement = this;
|
||||
|
||||
if (browser.IS_IE8) {
|
||||
trackElement = document.createElement('custom');
|
||||
|
||||
for (let prop in HTMLTrackElement.prototype) {
|
||||
if (prop !== 'constructor') {
|
||||
trackElement[prop] = HTMLTrackElement.prototype[prop];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let track = new TextTrack(options);
|
||||
|
||||
trackElement.kind = track.kind;
|
||||
trackElement.src = track.src;
|
||||
trackElement.srclang = track.language;
|
||||
trackElement.label = track.label;
|
||||
trackElement.default = track.default;
|
||||
|
||||
Object.defineProperty(trackElement, 'readyState', {
|
||||
get() {
|
||||
return readyState;
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(trackElement, 'track', {
|
||||
get() {
|
||||
return track;
|
||||
}
|
||||
});
|
||||
|
||||
readyState = NONE;
|
||||
|
||||
track.addEventListener('loadeddata', function() {
|
||||
readyState = LOADED;
|
||||
|
||||
trackElement.trigger({
|
||||
type: 'load',
|
||||
target: trackElement
|
||||
});
|
||||
});
|
||||
|
||||
if (browser.IS_IE8) {
|
||||
return trackElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HTMLTrackElement.prototype.allowedEvents_ = {
|
||||
load: 'load'
|
||||
};
|
||||
|
||||
HTMLTrackElement.NONE = NONE;
|
||||
HTMLTrackElement.LOADING = LOADING;
|
||||
HTMLTrackElement.LOADED = LOADED;
|
||||
HTMLTrackElement.ERROR = ERROR;
|
||||
|
||||
export default HTMLTrackElement;
|
||||
@@ -141,7 +141,12 @@ class TextTrackDisplay extends Component {
|
||||
|
||||
let i = cues.length;
|
||||
while (i--) {
|
||||
let cueDiv = cues[i].displayState;
|
||||
let cue = cues[i];
|
||||
if (!cue) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let cueDiv = cue.displayState;
|
||||
if (overrides.color) {
|
||||
cueDiv.firstChild.style.color = overrides.color;
|
||||
}
|
||||
|
||||
@@ -69,6 +69,13 @@ for (let event in TextTrackList.prototype.allowedEvents_) {
|
||||
TextTrackList.prototype['on' + event] = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add TextTrack from TextTrackList
|
||||
*
|
||||
* @param {TextTrack} track
|
||||
* @method addTrack_
|
||||
* @private
|
||||
*/
|
||||
TextTrackList.prototype.addTrack_ = function(track) {
|
||||
let index = this.tracks_.length;
|
||||
if (!(''+index in this)) {
|
||||
@@ -90,18 +97,31 @@ TextTrackList.prototype.addTrack_ = function(track) {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove TextTrack from TextTrackList
|
||||
* NOTE: Be mindful of what is passed in as it may be a HTMLTrackElement
|
||||
*
|
||||
* @param {TextTrack} rtrack
|
||||
* @method removeTrack_
|
||||
* @private
|
||||
*/
|
||||
TextTrackList.prototype.removeTrack_ = function(rtrack) {
|
||||
let result = null;
|
||||
let track;
|
||||
|
||||
for (let i = 0, l = this.length; i < l; i++) {
|
||||
track = this[i];
|
||||
if (track === rtrack) {
|
||||
if (this[i] === rtrack) {
|
||||
track = this[i];
|
||||
|
||||
this.tracks_.splice(i, 1);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!track) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.trigger({
|
||||
type: 'removetrack',
|
||||
track: track
|
||||
|
||||
@@ -45,7 +45,9 @@ let TextTrack = function(options={}) {
|
||||
tt = document.createElement('custom');
|
||||
|
||||
for (let prop in TextTrack.prototype) {
|
||||
tt[prop] = TextTrack.prototype[prop];
|
||||
if (prop !== 'constructor') {
|
||||
tt[prop] = TextTrack.prototype[prop];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,24 +235,25 @@ TextTrack.prototype.removeCue = function(removeCue) {
|
||||
* Downloading stuff happens below this point
|
||||
*/
|
||||
var parseCues = function(srcContent, track) {
|
||||
if (typeof window['WebVTT'] !== 'function') {
|
||||
//try again a bit later
|
||||
return window.setTimeout(function() {
|
||||
parseCues(srcContent, track);
|
||||
}, 25);
|
||||
}
|
||||
let parser = new window.WebVTT.Parser(window, window.vttjs, window.WebVTT.StringDecoder());
|
||||
|
||||
let parser = new window['WebVTT']['Parser'](window, window['vttjs'], window['WebVTT']['StringDecoder']());
|
||||
|
||||
parser['oncue'] = function(cue) {
|
||||
parser.oncue = function(cue) {
|
||||
track.addCue(cue);
|
||||
};
|
||||
parser['onparsingerror'] = function(error) {
|
||||
|
||||
parser.onparsingerror = function(error) {
|
||||
log.error(error);
|
||||
};
|
||||
|
||||
parser['parse'](srcContent);
|
||||
parser['flush']();
|
||||
parser.onflush = function() {
|
||||
track.trigger({
|
||||
type: 'loadeddata',
|
||||
target: track
|
||||
});
|
||||
};
|
||||
|
||||
parser.parse(srcContent);
|
||||
parser.flush();
|
||||
};
|
||||
|
||||
var loadTrack = function(src, track) {
|
||||
@@ -269,7 +272,15 @@ var loadTrack = function(src, track) {
|
||||
}
|
||||
|
||||
track.loaded_ = true;
|
||||
parseCues(responseBody, track);
|
||||
|
||||
// NOTE: this is only used for the alt/video.novtt.js build
|
||||
if (typeof window.WebVTT !== 'function') {
|
||||
window.setTimeout(function() {
|
||||
parseCues(responseBody, track);
|
||||
}, 100);
|
||||
} else {
|
||||
parseCues(responseBody, track);
|
||||
}
|
||||
}));
|
||||
};
|
||||
|
||||
|
||||
@@ -79,8 +79,9 @@ export function getEl(id){
|
||||
/**
|
||||
* Creates an element and applies properties.
|
||||
*
|
||||
* @param {String=} tagName Name of tag to be created.
|
||||
* @param {Object=} properties Element properties to be applied.
|
||||
* @param {String} [tagName='div'] Name of tag to be created.
|
||||
* @param {Object} [properties={}] Element properties to be applied.
|
||||
* @param {Object} [attributes={}] Element attributes to be applied.
|
||||
* @return {Element}
|
||||
* @function createEl
|
||||
*/
|
||||
|
||||
@@ -563,6 +563,17 @@ videojs.isEl = Dom.isEl;
|
||||
*/
|
||||
videojs.isTextNode = Dom.isTextNode;
|
||||
|
||||
/**
|
||||
* Creates an element and applies properties.
|
||||
*
|
||||
* @method createEl
|
||||
* @param {String} [tagName='div'] Name of tag to be created.
|
||||
* @param {Object} [properties={}] Element properties to be applied.
|
||||
* @param {Object} [attributes={}] Element attributes to be applied.
|
||||
* @return {Element}
|
||||
*/
|
||||
videojs.createEl = Dom.createEl;
|
||||
|
||||
/**
|
||||
* Check if an element has a CSS class
|
||||
*
|
||||
|
||||
@@ -61,6 +61,7 @@ test('should be able to access expected player API methods', function() {
|
||||
|
||||
// TextTrack methods
|
||||
ok(player.textTracks, 'textTracks exists');
|
||||
ok(player.remoteTextTrackEls, 'remoteTextTrackEls exists');
|
||||
ok(player.remoteTextTracks, 'remoteTextTracks exists');
|
||||
ok(player.addTextTrack, 'addTextTrack exists');
|
||||
ok(player.addRemoteTextTrack, 'addRemoteTextTrack exists');
|
||||
|
||||
@@ -7,6 +7,7 @@ import MediaError from '../../src/js/media-error.js';
|
||||
import Html5 from '../../src/js/tech/html5.js';
|
||||
import TestHelpers from './test-helpers.js';
|
||||
import document from 'global/document';
|
||||
import window from 'global/window';
|
||||
import Tech from '../../src/js/tech/tech.js';
|
||||
import TechFaker from './tech/tech-faker.js';
|
||||
|
||||
@@ -29,6 +30,15 @@ test('should create player instance that inherits from component and dispose it'
|
||||
ok(player.el() === null, 'element disposed');
|
||||
});
|
||||
|
||||
test('dispose should not throw if styleEl is missing', function(){
|
||||
var player = TestHelpers.makePlayer();
|
||||
|
||||
player.styleEl_.parentNode.removeChild(player.styleEl_);
|
||||
|
||||
player.dispose();
|
||||
ok(player.el() === null, 'element disposed');
|
||||
});
|
||||
|
||||
// technically, all uses of videojs.options should be replaced with
|
||||
// Player.prototype.options_ in this file and a equivalent test using
|
||||
// videojs.options should be made in video.test.js. Keeping this here
|
||||
@@ -861,3 +871,75 @@ test('you can clear error in the error event', function() {
|
||||
|
||||
log.error.restore();
|
||||
});
|
||||
|
||||
test('Player#tech will return tech given the appropriate input', function() {
|
||||
let tech_ = {};
|
||||
let returnedTech = Player.prototype.tech.call({tech_}, {IWillNotUseThisInPlugins: true});
|
||||
|
||||
equal(returnedTech, tech_, 'We got back the tech we wanted');
|
||||
});
|
||||
|
||||
test('Player#tech alerts and throws without the appropriate input', function() {
|
||||
let alertCalled;
|
||||
let oldAlert = window.alert;
|
||||
window.alert = () => alertCalled = true;
|
||||
|
||||
let tech_ = {};
|
||||
throws(function() {
|
||||
Player.prototype.tech.call({tech_});
|
||||
}, new RegExp('https://github.com/videojs/video.js/issues/2617'),
|
||||
'we threw an error');
|
||||
|
||||
ok(alertCalled, 'we called an alert');
|
||||
window.alert = oldAlert;
|
||||
});
|
||||
|
||||
test('player#reset loads the Html5 tech and then techCalls reset', function() {
|
||||
let loadedTech;
|
||||
let loadedSource;
|
||||
let techCallMethod;
|
||||
|
||||
let testPlayer = {
|
||||
options_: {
|
||||
techOrder: ['html5', 'flash'],
|
||||
},
|
||||
loadTech_(tech, source) {
|
||||
loadedTech = tech;
|
||||
loadedSource = source;
|
||||
},
|
||||
techCall_(method) {
|
||||
techCallMethod = method;
|
||||
}
|
||||
};
|
||||
|
||||
Player.prototype.reset.call(testPlayer);
|
||||
|
||||
equal(loadedTech, 'Html5', 'we loaded the html5 tech');
|
||||
equal(loadedSource, null, 'with a null source');
|
||||
equal(techCallMethod, 'reset', 'we then reset the tech');
|
||||
});
|
||||
|
||||
test('player#reset loads the first item in the techOrder and then techCalls reset', function() {
|
||||
let loadedTech;
|
||||
let loadedSource;
|
||||
let techCallMethod;
|
||||
|
||||
let testPlayer = {
|
||||
options_: {
|
||||
techOrder: ['flash', 'html5'],
|
||||
},
|
||||
loadTech_(tech, source) {
|
||||
loadedTech = tech;
|
||||
loadedSource = source;
|
||||
},
|
||||
techCall_(method) {
|
||||
techCallMethod = method;
|
||||
}
|
||||
};
|
||||
|
||||
Player.prototype.reset.call(testPlayer);
|
||||
|
||||
equal(loadedTech, 'Flash', 'we loaded the Flash tech');
|
||||
equal(loadedSource, null, 'with a null source');
|
||||
equal(techCallMethod, 'reset', 'we then reset the tech');
|
||||
});
|
||||
|
||||
@@ -304,3 +304,50 @@ test('should fire makeup events when a video tag is initialized late', function(
|
||||
testStates({ networkState: 1, readyState: 3 }, ['loadstart', 'loadedmetadata', 'loadeddata', 'canplay']);
|
||||
testStates({ networkState: 1, readyState: 4 }, ['loadstart', 'loadedmetadata', 'loadeddata', 'canplay', 'canplaythrough']);
|
||||
});
|
||||
|
||||
test('Html5.resetMediaElement should remove sources and call load', function() {
|
||||
let selector;
|
||||
let removedChildren = [];
|
||||
let removedAttribute;
|
||||
let loaded;
|
||||
|
||||
let children = ['source1', 'source2', 'source3'];
|
||||
let testEl = {
|
||||
querySelectorAll(input) {
|
||||
selector = input;
|
||||
return children;
|
||||
},
|
||||
|
||||
removeChild(child) {
|
||||
removedChildren.push(child);
|
||||
},
|
||||
|
||||
removeAttribute(attr) {
|
||||
removedAttribute = attr;
|
||||
},
|
||||
|
||||
load() {
|
||||
loaded = true;
|
||||
}
|
||||
};
|
||||
|
||||
Html5.resetMediaElement(testEl);
|
||||
equal(selector, 'source', 'we got the source elements from the test el');
|
||||
deepEqual(removedChildren, children.reverse(), 'we removed the children that were present');
|
||||
equal(removedAttribute, 'src', 'we removed the src attribute');
|
||||
ok(loaded, 'we called load on the element');
|
||||
});
|
||||
|
||||
test('Html5#reset calls Html5.resetMediaElement when called', function() {
|
||||
let oldResetMedia = Html5.resetMediaElement;
|
||||
let resetEl;
|
||||
|
||||
Html5.resetMediaElement = (el) => resetEl = el;
|
||||
|
||||
let el = {};
|
||||
Html5.prototype.reset.call({el_: el});
|
||||
|
||||
equal(resetEl, el, 'we called resetMediaElement with the tech\'s el');
|
||||
|
||||
Html5.resetMediaElement = oldResetMedia;
|
||||
});
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import HTMLTrackElement from '../../../src/js/tracks/html-track-element.js';
|
||||
import HTMLTrackElementList from '../../../src/js/tracks/html-track-element-list.js';
|
||||
import TextTrack from '../../../src/js/tracks/text-track.js';
|
||||
|
||||
let noop = Function.prototype;
|
||||
let defaultTech = {
|
||||
textTracks: noop,
|
||||
on: noop,
|
||||
off: noop,
|
||||
currentTime: noop
|
||||
};
|
||||
|
||||
let track1 = new TextTrack({
|
||||
id: 1,
|
||||
tech: defaultTech
|
||||
});
|
||||
let track2 = new TextTrack({
|
||||
id: 2,
|
||||
tech: defaultTech
|
||||
});
|
||||
|
||||
var genericHtmlTrackElements = [{
|
||||
kind: 'captions',
|
||||
tech: noop,
|
||||
track: track1
|
||||
}, {
|
||||
kind: 'chapters',
|
||||
tech: noop,
|
||||
track: track2
|
||||
}];
|
||||
|
||||
q.module('HTML Track Element List');
|
||||
|
||||
test('HTMLTrackElementList\'s length is set correctly', function() {
|
||||
let htmlTrackElementList = new HTMLTrackElementList(genericHtmlTrackElements);
|
||||
|
||||
equal(htmlTrackElementList.length, genericHtmlTrackElements.length, `the length is ${genericHtmlTrackElements.length}`);
|
||||
});
|
||||
|
||||
test('can get html track element by track', function() {
|
||||
let htmlTrackElementList = new HTMLTrackElementList(genericHtmlTrackElements);
|
||||
|
||||
equal(htmlTrackElementList.getTrackElementByTrack_(track1).kind, 'captions', 'track1 has kind of captions');
|
||||
equal(htmlTrackElementList.getTrackElementByTrack_(track2).kind, 'chapters', 'track2 has kind of captions');
|
||||
});
|
||||
|
||||
test('length is updated when new tracks are added or removed', function() {
|
||||
let htmlTrackElementList = new HTMLTrackElementList(genericHtmlTrackElements);
|
||||
|
||||
htmlTrackElementList.addTrackElement_({tech: noop});
|
||||
equal(htmlTrackElementList.length, genericHtmlTrackElements.length + 1, `the length is ${genericHtmlTrackElements.length + 1}`);
|
||||
htmlTrackElementList.addTrackElement_({tech: noop});
|
||||
equal(htmlTrackElementList.length, genericHtmlTrackElements.length + 2, `the length is ${genericHtmlTrackElements.length + 2}`);
|
||||
|
||||
htmlTrackElementList.removeTrackElement_(htmlTrackElementList.getTrackElementByTrack_(track1));
|
||||
equal(htmlTrackElementList.length, genericHtmlTrackElements.length + 1, `the length is ${genericHtmlTrackElements.length + 1}`);
|
||||
htmlTrackElementList.removeTrackElement_(htmlTrackElementList.getTrackElementByTrack_(track2));
|
||||
equal(htmlTrackElementList.length, genericHtmlTrackElements.length, `the length is ${genericHtmlTrackElements.length}`);
|
||||
});
|
||||
@@ -0,0 +1,81 @@
|
||||
import HTMLTrackElement from '../../../src/js/tracks/html-track-element.js';
|
||||
import TextTrack from '../../../src/js/tracks/text-track.js';
|
||||
import window from 'global/window';
|
||||
|
||||
let noop = Function.prototype;
|
||||
let defaultTech = {
|
||||
textTracks: noop,
|
||||
on: noop,
|
||||
off: noop,
|
||||
currentTime: noop
|
||||
};
|
||||
|
||||
q.module('HTML Track Element');
|
||||
|
||||
test('html track element requires a tech', function() {
|
||||
window.throws(
|
||||
function() {
|
||||
new HTMLTrackElement();
|
||||
},
|
||||
new Error('A tech was not provided.'),
|
||||
'a tech is required for html track element'
|
||||
);
|
||||
});
|
||||
|
||||
test('can create a html track element with various properties', function() {
|
||||
let kind = 'chapters',
|
||||
label = 'English',
|
||||
language = 'en',
|
||||
src = 'http://www.example.com';
|
||||
|
||||
let htmlTrackElement = new HTMLTrackElement({
|
||||
kind,
|
||||
label,
|
||||
language,
|
||||
src,
|
||||
tech: defaultTech
|
||||
});
|
||||
|
||||
equal(htmlTrackElement.default, undefined, 'we have a default');
|
||||
equal(htmlTrackElement.kind, kind, 'we have a kind');
|
||||
equal(htmlTrackElement.label, label, 'we have a label');
|
||||
equal(htmlTrackElement.readyState, 0, 'we have a readyState');
|
||||
equal(htmlTrackElement.src, src, 'we have a src');
|
||||
equal(htmlTrackElement.srclang, language, 'we have a srclang');
|
||||
equal(htmlTrackElement.track.cues, null, 'we have a track');
|
||||
});
|
||||
|
||||
test('defaults when items not provided', function() {
|
||||
let htmlTrackElement = new HTMLTrackElement({
|
||||
tech: defaultTech
|
||||
});
|
||||
|
||||
equal(htmlTrackElement.default, undefined, 'we have a default');
|
||||
equal(htmlTrackElement.kind, 'subtitles', 'we have a kind');
|
||||
equal(htmlTrackElement.label, '', 'we have a label');
|
||||
equal(htmlTrackElement.readyState, 0, 'we have a readyState');
|
||||
equal(htmlTrackElement.src, undefined, 'we have a src');
|
||||
equal(htmlTrackElement.srclang, '', 'we have a srclang');
|
||||
equal(htmlTrackElement.track.cues.length, 0, 'we have a track');
|
||||
});
|
||||
|
||||
test('fires loadeddata when track cues become populated', function() {
|
||||
let changes = 0,
|
||||
loadHandler;
|
||||
|
||||
loadHandler = function() {
|
||||
changes++;
|
||||
};
|
||||
|
||||
let htmlTrackElement = new HTMLTrackElement({
|
||||
tech: noop
|
||||
});
|
||||
|
||||
htmlTrackElement.addEventListener('load', loadHandler);
|
||||
|
||||
// trigger loaded cues event
|
||||
htmlTrackElement.track.trigger('loadeddata');
|
||||
|
||||
equal(changes, 1, 'a loadeddata event trigger addEventListener');
|
||||
equal(htmlTrackElement.readyState, 2, 'readyState is loaded');
|
||||
});
|
||||
@@ -166,7 +166,7 @@ test('trigger "change" event when "modechange" is fired on a track', function()
|
||||
equal(changes, 2, 'two change events should have fired');
|
||||
});
|
||||
|
||||
test('trigger "change" event when mode changes on a TextTracl', function() {
|
||||
test('trigger "change" event when mode changes on a TextTrack', function() {
|
||||
var tt = new TextTrack({
|
||||
tech: {
|
||||
on: noop
|
||||
|
||||
@@ -15,7 +15,14 @@ import document from 'global/document';
|
||||
import window from 'global/window';
|
||||
import TechFaker from '../tech/tech-faker.js';
|
||||
|
||||
q.module('Tracks');
|
||||
q.module('Tracks', {
|
||||
'setup': function() {
|
||||
this.clock = sinon.useFakeTimers();
|
||||
},
|
||||
'teardown': function() {
|
||||
this.clock.restore();
|
||||
}
|
||||
});
|
||||
|
||||
test('should place title list item into ul', function() {
|
||||
var player, chaptersButton;
|
||||
@@ -398,3 +405,66 @@ test('removes cuechange event when text track is hidden for emulated tracks', fu
|
||||
equal(numTextTrackChanges, 4,
|
||||
'texttrackchange should be not be called since mode is hidden');
|
||||
});
|
||||
|
||||
test('should return correct remote text track values', function () {
|
||||
let fixture = document.getElementById('qunit-fixture');
|
||||
|
||||
let html = '<video id="example_1" class="video-js" autoplay preload="none">';
|
||||
html += '<source src="http://google.com" type="video/mp4">';
|
||||
html += '<source src="http://google.com" type="video/webm">';
|
||||
html += '<track kind="captions" label="label">';
|
||||
html += '</video>';
|
||||
|
||||
fixture.innerHTML += html;
|
||||
|
||||
let tag = document.getElementById('example_1');
|
||||
|
||||
let player = TestHelpers.makePlayer({}, tag);
|
||||
|
||||
this.clock.tick(1);
|
||||
|
||||
equal(player.remoteTextTracks().length, 1, 'add text track via html');
|
||||
equal(player.remoteTextTrackEls().length, 1, 'add html track element via html');
|
||||
|
||||
let htmlTrackElement = player.addRemoteTextTrack({
|
||||
kind: 'captions',
|
||||
label: 'label'
|
||||
});
|
||||
|
||||
equal(player.remoteTextTracks().length, 2, 'add text track via method');
|
||||
equal(player.remoteTextTrackEls().length, 2, 'add html track element via method');
|
||||
|
||||
player.removeRemoteTextTrack(htmlTrackElement.track);
|
||||
|
||||
equal(player.remoteTextTracks().length, 1, 'remove text track via method');
|
||||
equal(player.remoteTextTrackEls().length, 1, 'remove html track element via method');
|
||||
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
test('should uniformly create html track element when adding text track', function () {
|
||||
let player = TestHelpers.makePlayer();
|
||||
|
||||
let track = {
|
||||
kind: 'kind',
|
||||
src: 'src',
|
||||
language: 'language',
|
||||
label: 'label',
|
||||
default: 'default'
|
||||
};
|
||||
|
||||
equal(player.remoteTextTrackEls().length, 0, 'no html text tracks');
|
||||
|
||||
let htmlTrackElement = player.addRemoteTextTrack(track);
|
||||
|
||||
equal(htmlTrackElement.kind, htmlTrackElement.track.kind, 'verify html track element kind');
|
||||
equal(htmlTrackElement.src, htmlTrackElement.track.src, 'verify html track element src');
|
||||
equal(htmlTrackElement.srclang, htmlTrackElement.track.language, 'verify html track element language');
|
||||
equal(htmlTrackElement.label, htmlTrackElement.track.label, 'verify html track element label');
|
||||
equal(htmlTrackElement.default, htmlTrackElement.track.default, 'verify html track element default');
|
||||
|
||||
equal(player.remoteTextTrackEls().length, 1, 'html track element exist');
|
||||
equal(player.remoteTextTrackEls().getTrackElementByTrack_(htmlTrackElement.track), htmlTrackElement, 'verify same html track element');
|
||||
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
@@ -86,6 +86,7 @@ test('should expose DOM functions', function() {
|
||||
let methods = {
|
||||
isEl: 'isEl',
|
||||
isTextNode: 'isTextNode',
|
||||
createEl: 'createEl',
|
||||
hasClass: 'hasElClass',
|
||||
addClass: 'addElClass',
|
||||
removeClass: 'removeElClass',
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário