Comparar commits
34 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 269e504d26 | |||
| 971f633c73 | |||
| 03fd402ea9 | |||
| 3a600d0eea | |||
| 1e80e59614 | |||
| 7579fc1800 | |||
| 4f43616160 | |||
| 687aae50ff | |||
| 6986dbb851 | |||
| 39ff0f4fb6 | |||
| 82c8b80548 | |||
| f5cc165cad | |||
| b4dc4f85b0 | |||
| b63666379d | |||
| 77ba3d13d9 | |||
| 7f7ea70cb7 | |||
| e0824c8294 | |||
| cc6e82442f | |||
| 97021554cd | |||
| c4bbe5d120 | |||
| 66a0d23e05 | |||
| 4bce4a2954 | |||
| f87b12c3af | |||
| 9329e3ef8e | |||
| 546bef5321 | |||
| c31836c30c | |||
| a5a68e819a | |||
| 98160700e5 | |||
| e5e1c7f269 | |||
| 0c16c5f3cf | |||
| d57f09f7cf | |||
| 2a26c7f87b | |||
| eade52e174 | |||
| 188ead1c81 |
+6
-2
@@ -1,4 +1,8 @@
|
||||
{
|
||||
"presets": [ "es3", ["es2015", {"loose": true}] ],
|
||||
"plugins": ["inline-json"]
|
||||
"presets": [
|
||||
"es3",
|
||||
["es2015", {
|
||||
"loose": true
|
||||
}]
|
||||
]
|
||||
}
|
||||
|
||||
+2
-1
@@ -35,6 +35,7 @@
|
||||
},
|
||||
"plugins": ["plugins/markdown"],
|
||||
"markdown": {
|
||||
"tags": ["example"]
|
||||
"tags": ["example"],
|
||||
"idInHeadings": true
|
||||
}
|
||||
}
|
||||
|
||||
+9
-1
@@ -2,9 +2,13 @@ language: node_js
|
||||
node_js:
|
||||
- 4.4
|
||||
before_install:
|
||||
- export CHROME_BIN=chromium-browser
|
||||
- export CHROME_BIN=/usr/bin/google-chrome
|
||||
- export DISPLAY=:99.0
|
||||
- sh -e /etc/init.d/xvfb start
|
||||
after_failure:
|
||||
- npm ls --depth=1
|
||||
after_success:
|
||||
- npm run assets
|
||||
notifications:
|
||||
irc:
|
||||
channels:
|
||||
@@ -22,8 +26,12 @@ env:
|
||||
- secure: gglh7xDnURKfXp9T543DD7NG1pQ8HeWh1XtRspBAwr0H7RqJBVDqqODSYSPRFhfld7M6sYmvQIXgil7XlyefnKNTXqCarvaoTg3lbip8kSltXMiNw2V6AVpsQGuja7+XbaM0do70ETTKjW4Kw6wnxEHb78BvGN/hXIeqizUAjanlDAjd7fouaxpTBIbMESe2rI+WRHPis1cmnv8v70Mrh/8Un/NO4gkebGyvA47LTDNIaVqIVjonsndr8WjMv1/PNxQ8LyCO6D64MufrobS7Sec+VuN30apwEsBw8v82MK/MZ3qXu0lUp4+ERTbuc/rymh2wDFTQeG20Kf/NTauSaH6f414KNzIRFj0/xyLAzVZKIscXM2DKXMuskkZuvHLZvaspnZWcPYTjPZl0P88N0RBqnoLdR80dR5bDljNwU2QnSBeol/q1wXNEr6I1VTRFOB+qsHrD1blVMB1I5W3I0ti1aQ7XtgMOGi1kcPb4oFcJdl+3dLFDnyRyaNfdMOnOZYBBHdQCo19Mj/L+nqPGWeeYiEAM6JsuhNjHn5Za5nGf1ztXTimVPOQjyATin0x9kST3soLWSVmdW2dBHUGDVSMhvoLLR+nKSdNQ0KfpqtgrzeLxoVnRYHVBlih41tapM9IG/6BMYnDMaRcc0i54YeUP4oxlxGSyASIenkAgC6w=
|
||||
- secure: WtIEOSnqDkCZuTlBsxwlVwaRpVTbz7ol8+XSJIZb0aFo1lLisF9cz6s9WrAfX36MaxIcDN9LFZkpXzMvNrNkZWQa1kacGWH1rbx0SiiQ8LMweAcKdnZ5uXlSplBxbJ8bZfXKB1sIHsOsYw/vWhHKkcsDUkAEzQrIiMOhuoUV3s0uKM0knKXIAfNIF0EbDzLIojm+nm+F0n5vM60LRdKesaSt/o2p2LKxdZVoFGrg48D7bdA9VEfMWWRL/evDxJmnX4p+AjBc7mklqZ5F2pYsY6XXQuuS+2Sy+lnxz01kLg+RC4Cpv5dyYfK3h0j8KeyK8IuixycVONWVe9rANq8UaIsMrRN+6uDSC8zXiH4P+h6UDMm3jetc2ZyAfhBA8OyIs5QEShae2Rd7Y3WFJxBp6UVgyj6SkXGxrEdb1ZJgTTl4dyqiP0bYrLePNP2qSJ6OTfNdG791HF077uzXI96ABdMG54Wv9N9T/hmxKwV2Lajx/GZJMmHuwT9tkHKhkcxWea1HYam9QYSFUyJ5THfNk2A9u/r8DkL62MZ85zIQBisrlFjbPAGRejq6qyirBJPAy+FCjhM+oO/i2f2bGkkAfHGT0Og1BcrWVXs54yWdO7UZgie2F+Rmdwinb/GxebZJ+21ZQ4OkVr2t1Skr/PRni9+U7q/6xCLwUJgx45XJ0FE=
|
||||
sudo: false
|
||||
dist: trusty
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
addons:
|
||||
firefox: latest
|
||||
apt:
|
||||
packages:
|
||||
- google-chrome-stable
|
||||
|
||||
@@ -1,3 +1,76 @@
|
||||
<a name="6.2.2"></a>
|
||||
## [6.2.2](https://github.com/videojs/video.js/compare/v6.2.1...v6.2.2) (2017-07-14)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **playback rate menu:** cycling rates via click ([#4486](https://github.com/videojs/video.js/issues/4486)) ([4f43616](https://github.com/videojs/video.js/commit/4f43616))
|
||||
|
||||
### Chores
|
||||
|
||||
* **build:** remove unused var in build/version.js ([#4458](https://github.com/videojs/video.js/issues/4458)) ([6986dbb](https://github.com/videojs/video.js/commit/6986dbb))
|
||||
* add automatic github release ([#4466](https://github.com/videojs/video.js/issues/4466)) ([3a600d0](https://github.com/videojs/video.js/commit/3a600d0))
|
||||
* switch to using chrome for testing PRs on travis ([#4462](https://github.com/videojs/video.js/issues/4462)) ([687aae5](https://github.com/videojs/video.js/commit/687aae5))
|
||||
* **package:** update rollup to version 0.45.2 ([#4487](https://github.com/videojs/video.js/issues/4487)) ([971f633](https://github.com/videojs/video.js/commit/971f633)), closes [#4475](https://github.com/videojs/video.js/issues/4475)
|
||||
|
||||
### Documentation
|
||||
|
||||
* Fix Player#src API documentation. ([#4454](https://github.com/videojs/video.js/issues/4454)) ([7579fc1](https://github.com/videojs/video.js/commit/7579fc1))
|
||||
* make jsdoc generate anchor names so ToC links work ([#4471](https://github.com/videojs/video.js/issues/4471)) ([03fd402](https://github.com/videojs/video.js/commit/03fd402))
|
||||
|
||||
### Tests
|
||||
|
||||
* add unit tests for player.duration() ([#4459](https://github.com/videojs/video.js/issues/4459)) ([1e80e59](https://github.com/videojs/video.js/commit/1e80e59))
|
||||
|
||||
<a name="6.2.1"></a>
|
||||
## [6.2.1](https://github.com/videojs/video.js/compare/v6.2.0...v6.2.1) (2017-06-28)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* auto-removal remote text tracks being removed when not supposed to ([#4450](https://github.com/videojs/video.js/issues/4450)) ([82c8b80](https://github.com/videojs/video.js/commit/82c8b80)), closes [#4403](https://github.com/videojs/video.js/issues/4403) [#4315](https://github.com/videojs/video.js/issues/4315)
|
||||
* IE10 issue for disableOthers when property access results in "permission denied" ([#4395](https://github.com/videojs/video.js/issues/4395)) ([7f7ea70](https://github.com/videojs/video.js/commit/7f7ea70)), closes [#4378](https://github.com/videojs/video.js/issues/4378)
|
||||
* player.duration() should return NaN if duration is not known ([#4443](https://github.com/videojs/video.js/issues/4443)) ([f5cc165](https://github.com/videojs/video.js/commit/f5cc165))
|
||||
* Safari picture-in-picture triggers fullscreenchange ([#4437](https://github.com/videojs/video.js/issues/4437)) ([b636663](https://github.com/videojs/video.js/commit/b636663))
|
||||
* Update translations to match correct string ([#4383](https://github.com/videojs/video.js/issues/4383)) ([e0824c8](https://github.com/videojs/video.js/commit/e0824c8))
|
||||
* Use passive event listeners for touchstart/touchmove ([#4440](https://github.com/videojs/video.js/issues/4440)) ([b4dc4f8](https://github.com/videojs/video.js/commit/b4dc4f8)), closes [#4432](https://github.com/videojs/video.js/issues/4432)
|
||||
|
||||
### Chores
|
||||
|
||||
* **package:** update husky to version 0.14.1 ([#4444](https://github.com/videojs/video.js/issues/4444)) ([66a0d23](https://github.com/videojs/video.js/commit/66a0d23)), closes [#4436](https://github.com/videojs/video.js/issues/4436)
|
||||
* **package:** update rollup to version 0.42.0 ([#4392](https://github.com/videojs/video.js/issues/4392)) ([f87b12c](https://github.com/videojs/video.js/commit/f87b12c))
|
||||
* **package:** update rollup-watch to version 4.0.0 ([#4396](https://github.com/videojs/video.js/issues/4396)) ([4bce4a2](https://github.com/videojs/video.js/commit/4bce4a2))
|
||||
* **sandbox:** Fix paths in sandbox files. ([#4416](https://github.com/videojs/video.js/issues/4416)) ([c4bbe5d](https://github.com/videojs/video.js/commit/c4bbe5d))
|
||||
|
||||
### Documentation
|
||||
|
||||
* Fix links in API docs for several Player events. ([#4427](https://github.com/videojs/video.js/issues/4427)) ([cc6e824](https://github.com/videojs/video.js/commit/cc6e824))
|
||||
* Fixing player.remoteTextTracks jsdoc ([#4417](https://github.com/videojs/video.js/issues/4417)) ([9329e3e](https://github.com/videojs/video.js/commit/9329e3e))
|
||||
* Update name of FullscreenToggle in documentation ([#4410](https://github.com/videojs/video.js/issues/4410)) ([9702155](https://github.com/videojs/video.js/commit/9702155))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* Various small performance improvements. ([#4426](https://github.com/videojs/video.js/issues/4426)) ([77ba3d1](https://github.com/videojs/video.js/commit/77ba3d1))
|
||||
|
||||
<a name="6.2.0"></a>
|
||||
# [6.2.0](https://github.com/videojs/video.js/compare/v6.1.0...v6.2.0) (2017-05-30)
|
||||
|
||||
### Features
|
||||
|
||||
* Persist caption/description choice over source changes in emulated tracks ([#4295](https://github.com/videojs/video.js/issues/4295)) ([188ead1](https://github.com/videojs/video.js/commit/188ead1))
|
||||
* **lang:** Adding galician ([#4334](https://github.com/videojs/video.js/issues/4334)) ([2a26c7f](https://github.com/videojs/video.js/commit/2a26c7f))
|
||||
* **lang:** Create sk.json ([#4374](https://github.com/videojs/video.js/issues/4374)) ([e5e1c7f](https://github.com/videojs/video.js/commit/e5e1c7f))
|
||||
* **lang:** Update zh-CN.json ([#4370](https://github.com/videojs/video.js/issues/4370)) ([0c16c5f](https://github.com/videojs/video.js/commit/0c16c5f))
|
||||
* Use Rollup to generate dist files ([#4301](https://github.com/videojs/video.js/issues/4301)) ([c31836c](https://github.com/videojs/video.js/commit/c31836c))
|
||||
|
||||
### Chores
|
||||
|
||||
* **package:** update grunt-contrib-cssmin to version 2.2.0 ([#4345](https://github.com/videojs/video.js/issues/4345)) ([d57f09f](https://github.com/videojs/video.js/commit/d57f09f))
|
||||
* **package:** update videojs-flash to version 2.0.0 ([#4375](https://github.com/videojs/video.js/issues/4375)) ([9816070](https://github.com/videojs/video.js/commit/9816070))
|
||||
* update translations needed ([#4380](https://github.com/videojs/video.js/issues/4380)) ([a5a68e8](https://github.com/videojs/video.js/commit/a5a68e8))
|
||||
|
||||
### Tests
|
||||
|
||||
* **TextTrackDisplay:** Removing incorrect test techOrder ([#4379](https://github.com/videojs/video.js/issues/4379)) ([eade52e](https://github.com/videojs/video.js/commit/eade52e))
|
||||
|
||||
<a name="6.1.0"></a>
|
||||
# [6.1.0](https://github.com/videojs/video.js/compare/v6.0.1...v6.1.0) (2017-05-15)
|
||||
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
const fs = require('fs');
|
||||
const zlib = require('zlib');
|
||||
const Promise = require('bluebird');
|
||||
const klawSync = require('klaw-sync');
|
||||
const filesize = require('filesize');
|
||||
const Table = require('cli-table');
|
||||
|
||||
const files = klawSync('dist/', {
|
||||
ignore: ['examples', 'lang', 'font', 'ie8', '*.zip', '*.gz'],
|
||||
nodir: true
|
||||
});
|
||||
|
||||
Promise.all(files.map(gzipAndStat))
|
||||
.then(mapFiles)
|
||||
.then(function(files) {
|
||||
logTable(files);
|
||||
|
||||
return files;
|
||||
})
|
||||
.then(cleanup)
|
||||
.catch(function(err) {
|
||||
console.error(err.stack);
|
||||
});
|
||||
|
||||
function cleanup(files) {
|
||||
files.forEach(function(file) {
|
||||
fs.unlinkSync('dist/' + file[0] + '.gz');
|
||||
});
|
||||
}
|
||||
|
||||
function mapFiles(files) {
|
||||
return files.map(function(file) {
|
||||
const path = file[0].path;
|
||||
const fileStat = file[0].stats;
|
||||
const gzStat = file[1];
|
||||
return [file[0].path.split('dist/')[1], filesize(fileStat.size), filesize(gzStat.size)];
|
||||
});
|
||||
}
|
||||
|
||||
function gzipAndStat(file) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
const readStream = fs.createReadStream(file.path);
|
||||
const writeStream = fs.createWriteStream(file.path + '.gz');
|
||||
const gzip = zlib.createGzip();
|
||||
readStream.pipe(gzip).pipe(writeStream).on('close', function() {
|
||||
const gzStat = fs.statSync(file.path + '.gz');
|
||||
|
||||
resolve([file, gzStat]);
|
||||
})
|
||||
.on('error', reject);
|
||||
});
|
||||
}
|
||||
|
||||
function logTable(files) {
|
||||
const table = new Table({
|
||||
head: ['filename', 'size', 'gzipped'],
|
||||
colAligns: ['left', 'right', 'right'],
|
||||
style: {
|
||||
border: ['white']
|
||||
}
|
||||
});
|
||||
|
||||
table.push.apply(table, files);
|
||||
console.log(table.toString());
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
var unified = require('unified');
|
||||
var markdown = require('remark-parse');
|
||||
var stringify = require('remark-stringify');
|
||||
var fs = require('fs');
|
||||
|
||||
module.exports = function() {
|
||||
var processor = unified()
|
||||
.use(markdown, {commonmark: true})
|
||||
.use(stringify);
|
||||
|
||||
var ast = processor.parse(fs.readFileSync('./CHANGELOG.md'));
|
||||
|
||||
var changelog = [];
|
||||
changelog.push(processor.stringify(ast.children[0]));
|
||||
|
||||
// start at 1 so we get the first anchor tag
|
||||
// and can break on the second
|
||||
for (var i = 1; i < ast.children.length; i++) {
|
||||
var item = processor.stringify(ast.children[i]);
|
||||
|
||||
if (/^<a name="/.test(item)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (/^###/.test(item)) {
|
||||
item = '\n' + item + '\n';
|
||||
}
|
||||
|
||||
changelog.push(item);
|
||||
}
|
||||
|
||||
return changelog.join('\n');
|
||||
};
|
||||
+25
-1
@@ -5,7 +5,31 @@ var apiPath = path.join(__dirname, '..', 'docs', 'api');
|
||||
var replacements = [
|
||||
{find: /\/docs\/guides\/(.+)\.md/g, replace: 'tutorial-$1.html'},
|
||||
{find: /tutorial-tech.html/g, replace: 'tutorial-tech_.html'},
|
||||
{find: /\/docs\/guides\//g, replace: '#'}
|
||||
{find: /\/docs\/guides\//g, replace: '#'},
|
||||
{find: /(\<h[1-6] id="(?:.*)?)video-js(.*)?"\>/g, replace: '$1videojs$2">'},
|
||||
{find: /(\<h[1-6] id="(?:.*)?)don-t(.*)?"\>/g, replace: '$1dont$2">'},
|
||||
{find: /(\<h[1-6] id="(?:.*)?)node-js(.*)?"\>/g, replace: '$1nodejs$2">'},
|
||||
{find: /(\<h[1-6] id="(?:.*)?)vtt-js(.*)?"\>/g, replace: '$1vttjs$2">'},
|
||||
{find: /(\<h[1-6] id=")-(.*)("\>)/g, replace: '$1$2$3'},
|
||||
{find: /(\<h[1-6] id=")(.*)-("\>)/g, replace: '$1$2$3'},
|
||||
{find: /(\<h[1-6] id=".*)-docs-guides-.*-md("\>)/g, replace: '$1$2'},
|
||||
// replace all children with children-1
|
||||
{find: /\<h3 id="children"\>/g, replace: '<h3 id="children-1">'},
|
||||
// remove the -1 from the first item
|
||||
{find: /\<h3 id="children-1"\>/, replace: '<h3 id="children">'},
|
||||
{find: '<h4 id="nativecontrolsfortouch">', replace: '<h4 id="nativecontrolsfortouch-1">'},
|
||||
{find: '<h3 id="videojs-(audio|video)track">', replace: '<h3 id="videojs$1track">'},
|
||||
{find: '<h3 id="text-tracks">', replace: '<h3 id="text-tracks-1">'},
|
||||
{find: '<h2 id="q-how-can-i-hide-the-links-to-my-video-subtitles-audio-tracks">',
|
||||
replace: '<h2 id="q-how-can-i-hide-the-links-to-my-videosubtitlesaudiotracks">'},
|
||||
{find: '<h3 id="dispose-http-docs-videojs-com-player-html-dispose">',
|
||||
replace: '<h3 id="dispose">'},
|
||||
{find: '<h4 id="effect-on-player-width-and-player-height">',
|
||||
replace: '<h4 id="effect-on-playerwidth-and-playerheight">'},
|
||||
{find: '<h4 id="i-want-to-have-a-single-source-and-dont-care-about-live-adaptive-streaming">',
|
||||
replace: '<h4 id="i-want-to-have-a-single-source-and-dont-care-about-liveadaptive-streaming">'},
|
||||
{find: '<h2 id="api-docs-api">', replace: '<h2 id="api-docs">'},
|
||||
{find: '<h2 id="guides-docs-guides">', replace: '<h2 id="guides">'}
|
||||
];
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
var ghrelease = require('gh-release');
|
||||
var currentChangelog = require('./current-changelog.js');
|
||||
var safeParse = require('safe-json-parse/tuple');
|
||||
var pkg = require('../package.json')
|
||||
|
||||
var options = {
|
||||
owner: 'videojs',
|
||||
repo: 'video.js',
|
||||
body: currentChangelog(),
|
||||
assets: ['./dist/videojs-'+pkg.version+'.zip'],
|
||||
endpoint: 'https://api.github.com',
|
||||
auth: {
|
||||
username: process.env.VJS_GITHUB_USER,
|
||||
password: process.env.VJS_GITHUB_TOKEN
|
||||
}
|
||||
};
|
||||
|
||||
var tuple = safeParse(process.env.npm_config_argv);
|
||||
var npmargs = tuple[0] ? [] : tuple[1].cooked;
|
||||
|
||||
if (npmargs.some(function(arg) { return /next/.test(arg); })) {
|
||||
options.prerelease = true;
|
||||
}
|
||||
|
||||
ghrelease(options, function(err, result) {
|
||||
if (err) {
|
||||
console.log('Unable to publish release to github');
|
||||
console.log(err);
|
||||
} else {
|
||||
console.log('Publish release to github!');
|
||||
console.log(result);
|
||||
}
|
||||
});
|
||||
+20
-8
@@ -408,8 +408,7 @@ module.exports = function(grunt) {
|
||||
],
|
||||
dev: [
|
||||
'shell:babel',
|
||||
'browserify:watch',
|
||||
'browserify:watchnovtt',
|
||||
'shell:rollupwatch',
|
||||
'browserify:tests',
|
||||
'watch:skin',
|
||||
'watch:lang',
|
||||
@@ -448,6 +447,24 @@ module.exports = function(grunt) {
|
||||
}
|
||||
},
|
||||
shell: {
|
||||
rollup: {
|
||||
command: 'npm run rollup',
|
||||
options: {
|
||||
preferLocal: true
|
||||
}
|
||||
},
|
||||
rollupall: {
|
||||
command: 'npm run rollup -- --no-progress && npm run rollup-minify -- --no-progress',
|
||||
options: {
|
||||
preferLocal: true
|
||||
}
|
||||
},
|
||||
rollupwatch: {
|
||||
command: 'npm run rollup-dev',
|
||||
optoins: {
|
||||
preferLocal: true
|
||||
}
|
||||
},
|
||||
babel: {
|
||||
command: 'npm run babel -- --watch',
|
||||
options: {
|
||||
@@ -509,12 +526,7 @@ module.exports = function(grunt) {
|
||||
'shell:lint',
|
||||
'clean:build',
|
||||
|
||||
'babel:es5',
|
||||
'browserify:build',
|
||||
'browserify:buildnovtt',
|
||||
'usebanner:novtt',
|
||||
'usebanner:vtt',
|
||||
'uglify',
|
||||
'shell:rollupall',
|
||||
|
||||
'skin',
|
||||
'version:css',
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
import { rollup } from 'rollup';
|
||||
import duration from 'humanize-duration';
|
||||
import watch from 'rollup-watch';
|
||||
import babel from 'rollup-plugin-babel';
|
||||
import resolve from 'rollup-plugin-node-resolve';
|
||||
import commonjs from 'rollup-plugin-commonjs';
|
||||
import json from 'rollup-plugin-json';
|
||||
import filesize from 'rollup-plugin-filesize';
|
||||
import progress from 'rollup-plugin-progress';
|
||||
import ignore from 'rollup-plugin-ignore';
|
||||
import uglify from 'rollup-plugin-uglify';
|
||||
import minimist from 'minimist';
|
||||
import _ from 'lodash';
|
||||
import pkg from '../package.json';
|
||||
import fs from 'fs';
|
||||
|
||||
const args = minimist(process.argv.slice(2), {
|
||||
boolean: ['watch', 'minify', 'progress'],
|
||||
default: {
|
||||
progress: true
|
||||
},
|
||||
alias: {
|
||||
w: 'watch',
|
||||
m: 'minify',
|
||||
p: 'progress'
|
||||
}
|
||||
});
|
||||
|
||||
const compiledLicense = _.template(fs.readFileSync('./build/license-header.txt', 'utf8'));
|
||||
const bannerData = _.pick(pkg, ['version', 'copyright']);
|
||||
|
||||
const primedResolve = resolve({
|
||||
jsnext: true,
|
||||
main: true,
|
||||
browser: true
|
||||
});
|
||||
const primedCjs = commonjs({
|
||||
sourceMap: false
|
||||
});
|
||||
const primedBabel = babel({
|
||||
babelrc: false,
|
||||
exclude: 'node_modules/**',
|
||||
presets: [
|
||||
'es3',
|
||||
['es2015', {
|
||||
loose: true,
|
||||
modules: false
|
||||
}]
|
||||
],
|
||||
plugins: ['external-helpers']
|
||||
});
|
||||
|
||||
const es = {
|
||||
options: {
|
||||
entry: 'src/js/video.js',
|
||||
plugins: [
|
||||
json(),
|
||||
primedBabel,
|
||||
args.progress ? progress() : {},
|
||||
filesize()
|
||||
],
|
||||
onwarn(warning) {
|
||||
if (warning.code === 'UNUSED_EXTERNAL_IMPORT' ||
|
||||
warning.code === 'UNRESOLVED_IMPORT') {
|
||||
return;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(warning.message);
|
||||
},
|
||||
legacy: true
|
||||
},
|
||||
banner: compiledLicense(Object.assign({includesVtt: true}, bannerData)),
|
||||
format: 'es',
|
||||
dest: 'dist/video.es.js'
|
||||
};
|
||||
|
||||
const cjs = Object.assign({}, es, {
|
||||
format: 'cjs',
|
||||
dest: 'dist/video.cjs.js'
|
||||
});
|
||||
|
||||
const umd = {
|
||||
options: {
|
||||
entry: 'src/js/video.js',
|
||||
plugins: [
|
||||
primedResolve,
|
||||
json(),
|
||||
primedCjs,
|
||||
primedBabel,
|
||||
args.progress ? progress() : {},
|
||||
filesize()
|
||||
],
|
||||
legacy: true
|
||||
},
|
||||
banner: compiledLicense(Object.assign({includesVtt: true}, bannerData)),
|
||||
format: 'umd',
|
||||
dest: 'dist/video.js'
|
||||
};
|
||||
|
||||
const minifiedUmd = Object.assign({}, _.cloneDeep(umd), {
|
||||
dest: 'dist/video.min.js'
|
||||
});
|
||||
|
||||
minifiedUmd.options.plugins.splice(4, 0, uglify({
|
||||
preserveComments: 'some',
|
||||
screwIE8: false,
|
||||
mangle: true,
|
||||
compress: {
|
||||
/* eslint-disable camelcase */
|
||||
sequences: true,
|
||||
dead_code: true,
|
||||
conditionals: true,
|
||||
booleans: true,
|
||||
unused: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
drop_console: true
|
||||
/* eslint-enable camelcase */
|
||||
}
|
||||
}));
|
||||
|
||||
const novttUmd = Object.assign({}, _.cloneDeep(umd), {
|
||||
banner: compiledLicense(Object.assign({includesVtt: false}, bannerData)),
|
||||
dest: 'dist/alt/video.novtt.js'
|
||||
});
|
||||
|
||||
novttUmd.options.plugins.unshift(ignore(['videojs-vtt.js']));
|
||||
|
||||
const minifiedNovttUmd = Object.assign({}, _.cloneDeep(minifiedUmd), {
|
||||
banner: compiledLicense(Object.assign({includesVtt: false}, bannerData)),
|
||||
dest: 'dist/alt/video.novtt.min.js'
|
||||
});
|
||||
|
||||
minifiedNovttUmd.options.plugins.unshift(ignore(['videojs-vtt.js']));
|
||||
|
||||
function runRollup({options, format, dest, banner}) {
|
||||
rollup(options)
|
||||
.then(function(bundle) {
|
||||
bundle.write({
|
||||
format,
|
||||
dest,
|
||||
banner,
|
||||
moduleName: 'videojs',
|
||||
sourceMap: false
|
||||
});
|
||||
}, function(err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
if (!args.watch) {
|
||||
if (args.minify) {
|
||||
runRollup(minifiedUmd);
|
||||
runRollup(minifiedNovttUmd);
|
||||
} else {
|
||||
runRollup(es);
|
||||
runRollup(cjs);
|
||||
runRollup(umd);
|
||||
runRollup(novttUmd);
|
||||
}
|
||||
} else {
|
||||
const props = ['format', 'dest', 'banner'];
|
||||
const watchers = [
|
||||
['es', watch({rollup},
|
||||
Object.assign({},
|
||||
es.options,
|
||||
_.pick(es, props)))],
|
||||
['cjs', watch({rollup},
|
||||
Object.assign({},
|
||||
cjs.options,
|
||||
_.pick(cjs, props)))],
|
||||
['umd', watch({rollup},
|
||||
Object.assign({moduleName: 'videojs'},
|
||||
umd.options,
|
||||
_.pick(umd, props)))],
|
||||
['novtt', watch({rollup},
|
||||
Object.assign({moduleName: 'videojs'},
|
||||
novttUmd.options,
|
||||
_.pick(novttUmd, props)))]
|
||||
];
|
||||
|
||||
watchers.forEach(function([type, watcher]) {
|
||||
watcher.on('event', (details) => {
|
||||
if (details.code === 'BUILD_START') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Bundling ${type}...`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (details.code === 'BUILD_END') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Bundled ${type} in %s`, duration(details.duration));
|
||||
return;
|
||||
}
|
||||
|
||||
if (details.code === 'ERROR') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(details.error.toString());
|
||||
return;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -7,7 +7,6 @@ if (tuple[0]) {
|
||||
}
|
||||
|
||||
var sh = require('shelljs');
|
||||
var version = process.env.npm_package_version;
|
||||
var prereleaseType = npm_config_argv['remain'][0];
|
||||
var approvedTypes = {
|
||||
'major': 1,
|
||||
|
||||
@@ -318,7 +318,7 @@ The `children` options can also be passed as an `Object`. In this case, it is us
|
||||
videojs('my-player', {
|
||||
children: {
|
||||
controlBar: {
|
||||
fullscreenControl: false
|
||||
fullscreenToggle: false
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -333,7 +333,7 @@ Components can be given custom options via the _lower-camel-case variant of the
|
||||
```js
|
||||
videojs('my-player', {
|
||||
controlBar: {
|
||||
fullscreenControl: false
|
||||
fullscreenToggle: false
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
@@ -13,7 +13,6 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
## Status of translations
|
||||
|
||||
<!-- START langtable -->
|
||||
|
||||
| Language file | Missing translations |
|
||||
| ----------------------- | ----------------------------------------------------------------------------------- |
|
||||
| ar.json (missing 50) | Audio Player |
|
||||
@@ -61,7 +60,7 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
@@ -119,7 +118,7 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
@@ -177,7 +176,7 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
@@ -235,7 +234,7 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
@@ -293,7 +292,7 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
@@ -351,19 +350,12 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
| | End of dialog window. |
|
||||
| de.json (missing 8) | Audio Player |
|
||||
| | Video Player |
|
||||
| | Progress Bar |
|
||||
| | progress bar timing: currentTime={1} duration={2} |
|
||||
| | Volume Level |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | End of dialog window. |
|
||||
| de.json (Complete) | |
|
||||
| el.json (missing 44) | Audio Player |
|
||||
| | Video Player |
|
||||
| | Replay |
|
||||
@@ -403,7 +395,7 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
@@ -460,7 +452,7 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
@@ -518,7 +510,7 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
@@ -576,12 +568,69 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
| | End of dialog window. |
|
||||
| fr.json (Complete) | |
|
||||
| gl.json (missing 57) | Audio Player |
|
||||
| | Video Player |
|
||||
| | Replay |
|
||||
| | Progress Bar |
|
||||
| | progress bar timing: currentTime={1} duration={2} |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | Volume Level |
|
||||
| | The media is encrypted and we do not have the keys to decrypt it. |
|
||||
| | Close |
|
||||
| | Close Modal Dialog |
|
||||
| | Modal Window |
|
||||
| | This is a modal window |
|
||||
| | This modal can be closed by pressing the Escape key or activating the close button. |
|
||||
| | , opens captions settings dialog |
|
||||
| | , opens subtitles settings dialog |
|
||||
| | , opens descriptions settings dialog |
|
||||
| | , selected |
|
||||
| | captions settings |
|
||||
| | subtitles settings |
|
||||
| | descriptions settings |
|
||||
| | Text |
|
||||
| | White |
|
||||
| | Black |
|
||||
| | Red |
|
||||
| | Green |
|
||||
| | Blue |
|
||||
| | Yellow |
|
||||
| | Magenta |
|
||||
| | Cyan |
|
||||
| | Background |
|
||||
| | Window |
|
||||
| | Transparent |
|
||||
| | Semi-Transparent |
|
||||
| | Opaque |
|
||||
| | Font Size |
|
||||
| | Text Edge Style |
|
||||
| | None |
|
||||
| | Raised |
|
||||
| | Depressed |
|
||||
| | Uniform |
|
||||
| | Dropshadow |
|
||||
| | Font Family |
|
||||
| | Proportional Sans-Serif |
|
||||
| | Monospace Sans-Serif |
|
||||
| | Proportional Serif |
|
||||
| | Monospace Serif |
|
||||
| | Casual |
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
| | End of dialog window. |
|
||||
| hr.json (missing 58) | Audio Player |
|
||||
| | Video Player |
|
||||
| | Replay |
|
||||
@@ -635,7 +684,7 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
@@ -693,7 +742,7 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
@@ -751,7 +800,7 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
@@ -809,7 +858,7 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
@@ -867,7 +916,7 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
@@ -925,7 +974,7 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
@@ -972,7 +1021,7 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
@@ -1030,7 +1079,7 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
@@ -1081,7 +1130,7 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
@@ -1139,7 +1188,7 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
@@ -1182,7 +1231,7 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
@@ -1226,11 +1275,12 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
| | End of dialog window. |
|
||||
| sk.json (Complete) | |
|
||||
| sr.json (missing 58) | Audio Player |
|
||||
| | Video Player |
|
||||
| | Replay |
|
||||
@@ -1284,7 +1334,7 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
@@ -1342,7 +1392,7 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
@@ -1353,7 +1403,7 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | progress bar timing: currentTime={1} duration={2} |
|
||||
| | Volume Level |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | End of dialog window. |
|
||||
| uk.json (missing 44) | Audio Player |
|
||||
| | Video Player |
|
||||
@@ -1394,7 +1444,7 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
@@ -1437,30 +1487,17 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
| | End of dialog window. |
|
||||
| zh-CN.json (missing 57) | Audio Player |
|
||||
| zh-CN.json (missing 44) | Audio Player |
|
||||
| | Video Player |
|
||||
| | Replay |
|
||||
| | Progress Bar |
|
||||
| | progress bar timing: currentTime={1} duration={2} |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | Volume Level |
|
||||
| | Play Video |
|
||||
| | Close |
|
||||
| | Close Modal Dialog |
|
||||
| | Modal Window |
|
||||
| | This is a modal window |
|
||||
| | This modal can be closed by pressing the Escape key or activating the close button. |
|
||||
| | , opens captions settings dialog |
|
||||
| | , opens subtitles settings dialog |
|
||||
| | , opens descriptions settings dialog |
|
||||
| | , selected |
|
||||
| | captions settings |
|
||||
| | subtitles settings |
|
||||
| | descriptions settings |
|
||||
@@ -1494,7 +1531,7 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
@@ -1538,10 +1575,9 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Script |
|
||||
| | Small Caps |
|
||||
| | Reset |
|
||||
| | all settings to the default values |
|
||||
| | restore all settings to the default values |
|
||||
| | Done |
|
||||
| | Caption Settings Dialog |
|
||||
| | Beginning of dialog window. Escape will cancel and close the window. |
|
||||
| | End of dialog window. |
|
||||
|
||||
<!-- END langtable -->
|
||||
|
||||
+9
-1
@@ -70,7 +70,15 @@
|
||||
"Casual": "Zwanglos",
|
||||
"Script": "Schreibeschrift",
|
||||
"Small Caps": "Small-Caps",
|
||||
"Reset": "Zurücksetzen",
|
||||
"restore all settings to the default values": "Alle Einstellungen auf die Standardwerte zurücksetzen",
|
||||
"Done": "Fertig",
|
||||
"Caption Settings Dialog": "Einstellungsdialog für Untertitel",
|
||||
"Beginning of dialog window. Escape will cancel and close the window.": "Anfang des Dialogfensters. Esc bricht ab und schließt das Fenster."
|
||||
"Beginning of dialog window. Escape will cancel and close the window.": "Anfang des Dialogfensters. Esc bricht ab und schließt das Fenster.",
|
||||
"End of dialog window.": "Ende des Dialogfensters.",
|
||||
"Audio Player": "Audio-Player",
|
||||
"Video Player": "Video-Player",
|
||||
"Progress Bar": "Forschrittsbalken",
|
||||
"progress bar timing: currentTime={1} duration={2}": "{1} von {2}",
|
||||
"Volume Level": "Lautstärkestufe"
|
||||
}
|
||||
|
||||
+1
-1
@@ -76,7 +76,7 @@
|
||||
"Script": "Script",
|
||||
"Small Caps": "Small Caps",
|
||||
"Reset": "Reset",
|
||||
"all settings to the default values": "all settings to the default values",
|
||||
"restore all settings to the default values": "restore all settings to the default values",
|
||||
"Done": "Done",
|
||||
"Caption Settings Dialog": "Caption Settings Dialog",
|
||||
"Beginning of dialog window. Escape will cancel and close the window.": "Beginning of dialog window. Escape will cancel and close the window.",
|
||||
|
||||
+1
-1
@@ -76,7 +76,7 @@
|
||||
"Script": "Scripte",
|
||||
"Small Caps": "Petites capitales",
|
||||
"Reset": "Réinitialiser",
|
||||
"all settings to the default values": "tous les paramètres aux valeurs par défaut",
|
||||
"restore all settings to the default values": "Restaurer tous les paramètres aux valeurs par défaut",
|
||||
"Done": "Terminé",
|
||||
"Caption Settings Dialog": "Boîte de dialogue des paramètres des sous-titres transcrits",
|
||||
"Beginning of dialog window. Escape will cancel and close the window.": "Début de la fenêtre de dialogue. La touche d'échappement annulera et fermera la fenêtre.",
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"Play": "Reprodución",
|
||||
"Play Video": "Reprodución Vídeo",
|
||||
"Pause": "Pausa",
|
||||
"Current Time": "Tempo reproducido",
|
||||
"Duration Time": "Duración total",
|
||||
"Remaining Time": "Tempo restante",
|
||||
"Stream Type": "Tipo de secuencia",
|
||||
"LIVE": "DIRECTO",
|
||||
"Loaded": "Cargado",
|
||||
"Progress": "Progreso",
|
||||
"Fullscreen": "Pantalla completa",
|
||||
"Non-Fullscreen": "Pantalla non completa",
|
||||
"Mute": "Silenciar",
|
||||
"Unmute": "Non silenciado",
|
||||
"Playback Rate": "Velocidade de reprodución",
|
||||
"Subtitles": "Subtítulos",
|
||||
"subtitles off": "Subtítulos desactivados",
|
||||
"Captions": "Subtítulos con lenda",
|
||||
"captions off": "Subtítulos con lenda desactivados",
|
||||
"Chapters": "Capítulos",
|
||||
"You aborted the media playback": "Interrompeches a reprodución do vídeo.",
|
||||
"A network error caused the media download to fail part-way.": "Un erro de rede interrompeu a descarga do vídeo.",
|
||||
"The media could not be loaded, either because the server or network failed or because the format is not supported.": "Non se puido cargar o vídeo debido a un fallo de rede ou do servidor ou porque o formato é incompatible.",
|
||||
"The media playback was aborted due to a corruption problem or because the media used features your browser did not support.": "A reproducción de vídeo interrompeuse por un problema de corrupción de datos ou porque o vídeo precisa funcións que o teu navegador non ofrece.",
|
||||
"No compatible source was found for this media.": "Non se atopou ningunha fonte compatible con este vídeo."
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"Audio Player": "Zvukový prehrávač",
|
||||
"Video Player": "Video prehrávač",
|
||||
"Play": "Prehrať",
|
||||
"Pause": "Pozastaviť",
|
||||
"Replay": "Prehrať znova",
|
||||
"Current Time": "Aktuálny čas",
|
||||
"Duration Time": "Čas trvania",
|
||||
"Remaining Time": "Zostávajúci čas",
|
||||
"Stream Type": "Typ stopy",
|
||||
"LIVE": "NAŽIVO",
|
||||
"Loaded": "Načítané",
|
||||
"Progress": "Priebeh",
|
||||
"Progress Bar": "Ukazovateľ priebehu",
|
||||
"progress bar timing: currentTime={1} duration={2}": "časovanie ukazovateľa priebehu: currentTime={1} duration={2}",
|
||||
"Fullscreen": "Režim celej obrazovky",
|
||||
"Non-Fullscreen": "Režim normálnej obrazovky",
|
||||
"Mute": "Stlmiť",
|
||||
"Unmute": "Zrušiť stlmenie",
|
||||
"Playback Rate": "Rýchlosť prehrávania",
|
||||
"Subtitles": "Titulky",
|
||||
"subtitles off": "titulky vypnuté",
|
||||
"Captions": "Popisky",
|
||||
"captions off": "popisky vypnuté",
|
||||
"Chapters": "Kapitoly",
|
||||
"Descriptions": "Opisy",
|
||||
"descriptions off": "opisy vypnuté",
|
||||
"Audio Track": "Zvuková stopa",
|
||||
"Volume Level": "Úroveň hlasitosti",
|
||||
"You aborted the media playback": "Prerušili ste prehrávanie",
|
||||
"A network error caused the media download to fail part-way.": "Sťahovanie súboru bolo zrušené pre chybu na sieti.",
|
||||
"The media could not be loaded, either because the server or network failed or because the format is not supported.": "Súbor sa nepodarilo načítať pre chybu servera, sieťového pripojenia, alebo je formát súboru nepodporovaný.",
|
||||
"The media playback was aborted due to a corruption problem or because the media used features your browser did not support.": "Prehrávanie súboru bolo prerušené pre poškodené dáta, alebo súbor používa vlastnosti, ktoré váš prehliadač nepodporuje.",
|
||||
"No compatible source was found for this media.": "Nebol nájdený žiaden kompatibilný zdroj pre tento súbor.",
|
||||
"The media is encrypted and we do not have the keys to decrypt it.": "Súbor je zašifrovaný a nie je k dispozícii kľúč na rozšifrovanie.",
|
||||
"Play Video": "Prehrať video",
|
||||
"Close": "Zatvoriť",
|
||||
"Close Modal Dialog": "Zatvoriť modálne okno",
|
||||
"Modal Window": "Modálne okno",
|
||||
"This is a modal window": "Toto je modálne okno",
|
||||
"This modal can be closed by pressing the Escape key or activating the close button.": "Toto modálne okno je možné zatvoriť stlačením klávesy Escape, alebo aktivovaním tlačidla na zatvorenie.",
|
||||
", opens captions settings dialog": ", otvorí okno nastavení popiskov",
|
||||
", opens subtitles settings dialog": ", otvorí okno nastavení titulkov",
|
||||
", opens descriptions settings dialog": ", otvorí okno nastavení opisov",
|
||||
", selected": ", označené",
|
||||
"captions settings": "nastavenia popiskov",
|
||||
"subtitles settings": "nastavenia titulkov",
|
||||
"descriptions settings": "nastavenia opisov",
|
||||
"Text": "Text",
|
||||
"White": "Biela",
|
||||
"Black": "Čierna",
|
||||
"Red": "Červená",
|
||||
"Green": "Zelená",
|
||||
"Blue": "Modrá",
|
||||
"Yellow": "Žltá",
|
||||
"Magenta": "Ružová",
|
||||
"Cyan": "Tyrkysová",
|
||||
"Background": "Pozadie",
|
||||
"Window": "Okno",
|
||||
"Transparent": "Priesvitné",
|
||||
"Semi-Transparent": "Polopriesvitné",
|
||||
"Opaque": "Plné",
|
||||
"Font Size": "Veľkosť písma",
|
||||
"Text Edge Style": "Typ okrajov písma",
|
||||
"None": "Žiadne",
|
||||
"Raised": "Zvýšené",
|
||||
"Depressed": "Znížené",
|
||||
"Uniform": "Pravidelné",
|
||||
"Dropshadow": "S tieňom",
|
||||
"Font Family": "Typ písma",
|
||||
"Proportional Sans-Serif": "Proporčné bezpätkové",
|
||||
"Monospace Sans-Serif": "Pravidelné, bezpätkové",
|
||||
"Proportional Serif": "Proporčné pätkové",
|
||||
"Monospace Serif": "Pravidelné pätkové",
|
||||
"Casual": "Bežné",
|
||||
"Script": "Písané",
|
||||
"Small Caps": "Malé kapitálky",
|
||||
"Reset": "Resetovať",
|
||||
"restore all settings to the default values": "všetky nastavenia na základné hodnoty",
|
||||
"Done": "Hotovo",
|
||||
"Caption Settings Dialog": "Okno nastavení popiskov",
|
||||
"Beginning of dialog window. Escape will cancel and close the window.": "Začiatok okna. Klávesa Escape zruší a zavrie okno.",
|
||||
"End of dialog window.": "Koniec okna."
|
||||
}
|
||||
+17
-4
@@ -12,16 +12,29 @@
|
||||
"Non-Fullscreen": "退出全屏",
|
||||
"Mute": "静音",
|
||||
"Unmute": "取消静音",
|
||||
"Playback Rate": "播放码率",
|
||||
"Playback Rate": "播放速度",
|
||||
"Subtitles": "字幕",
|
||||
"subtitles off": "字幕关闭",
|
||||
"subtitles off": "关闭字幕",
|
||||
"Captions": "内嵌字幕",
|
||||
"captions off": "内嵌字幕关闭",
|
||||
"captions off": "关闭内嵌字幕",
|
||||
"Chapters": "节目段落",
|
||||
"Close Modal Dialog": "关闭弹窗",
|
||||
"Descriptions": "描述",
|
||||
"descriptions off": "关闭描述",
|
||||
"Audio Track": "音轨",
|
||||
"You aborted the media playback": "视频播放被终止",
|
||||
"A network error caused the media download to fail part-way.": "网络错误导致视频下载中途失败。",
|
||||
"The media could not be loaded, either because the server or network failed or because the format is not supported.": "视频因格式不支持或者服务器或网络的问题无法加载。",
|
||||
"The media playback was aborted due to a corruption problem or because the media used features your browser did not support.": "由于视频文件损坏或是该视频使用了你的浏览器不支持的功能,播放终止。",
|
||||
"No compatible source was found for this media.": "无法找到此视频兼容的源。",
|
||||
"The media is encrypted and we do not have the keys to decrypt it.": "视频已加密,无法解密。"
|
||||
"The media is encrypted and we do not have the keys to decrypt it.": "视频已加密,无法解密。",
|
||||
"Play Video": "播放视频",
|
||||
"Close": "关闭",
|
||||
"Modal Window": "弹窗",
|
||||
"This is a modal window": "这是一个弹窗",
|
||||
"This modal can be closed by pressing the Escape key or activating the close button.": "可以按ESC按键或启用关闭按钮来关闭此弹窗。",
|
||||
", opens captions settings dialog": ", 开启标题设置弹窗",
|
||||
", opens subtitles settings dialog": ", 开启字幕设置弹窗",
|
||||
", opens descriptions settings dialog": ", 开启描述设置弹窗",
|
||||
", selected": ", 选择"
|
||||
}
|
||||
|
||||
+36
-8
@@ -1,8 +1,9 @@
|
||||
{
|
||||
"name": "video.js",
|
||||
"description": "An HTML5 and Flash video player with a common API and skin for both.",
|
||||
"version": "6.1.0",
|
||||
"main": "./es5/video.js",
|
||||
"version": "6.2.2",
|
||||
"main": "./dist/video.cjs.js",
|
||||
"module": "./dist/video.es.js",
|
||||
"style": "./dist/video-js.css",
|
||||
"copyright": "Copyright Brightcove, Inc. <https://www.brightcove.com/>",
|
||||
"license": "Apache-2.0",
|
||||
@@ -18,6 +19,11 @@
|
||||
"scripts": {
|
||||
"changelog": "conventional-changelog -p videojs -i CHANGELOG.md -s",
|
||||
"build": "grunt dist",
|
||||
"rollup-all": "npm run rollup && npm run rollup-minify",
|
||||
"rollup": "babel-node build/rollup.js",
|
||||
"rollup-minify": "babel-node build/rollup.js --minify",
|
||||
"rollup-dev": "babel-node build/rollup.js --watch",
|
||||
"assets": "node build/assets.js",
|
||||
"change": "grunt chg-add",
|
||||
"clean": "grunt clean",
|
||||
"grunt": "grunt",
|
||||
@@ -33,6 +39,7 @@
|
||||
"docs:fix": "remark --output -- './**/*.md'",
|
||||
"babel": "babel src/js -d es5",
|
||||
"prepublish": "not-in-install && run-p docs:api build || in-install",
|
||||
"publish": "node build/gh-release.js",
|
||||
"prepush": "npm run lint -- --errors",
|
||||
"version": "node build/version.js && git add CHANGELOG.md"
|
||||
},
|
||||
@@ -47,28 +54,32 @@
|
||||
"tsml": "1.0.1",
|
||||
"videojs-font": "2.0.0",
|
||||
"videojs-ie8": "1.1.2",
|
||||
"videojs-vtt.js": "0.12.3",
|
||||
"videojs-vtt.js": "0.12.4",
|
||||
"xhr": "2.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"aliasify": "^2.1.0",
|
||||
"babel-cli": "^6.11.4",
|
||||
"babel-plugin-inline-json": "^1.1.1",
|
||||
"babel-plugin-external-helpers": "^6.22.0",
|
||||
"babel-plugin-transform-runtime": "^6.9.0",
|
||||
"babel-preset-es2015": "^6.14.0",
|
||||
"babel-preset-es3": "^1.0.1",
|
||||
"babel-register": "^6.9.0",
|
||||
"babelify": "^7.3.0",
|
||||
"blanket": "^1.1.6",
|
||||
"bluebird": "^3.5.0",
|
||||
"browserify-derequire": "^0.9.4",
|
||||
"browserify-istanbul": "^2.0.0",
|
||||
"browserify-versionify": "^1.0.4",
|
||||
"bundle-collapser": "^1.2.1",
|
||||
"chg": "^0.3.2",
|
||||
"cli-table": "^0.3.1",
|
||||
"conventional-changelog-cli": "^1.2.0",
|
||||
"conventional-changelog-videojs": "^3.0.0",
|
||||
"es5-shim": "^4.1.3",
|
||||
"es6-shim": "^0.35.1",
|
||||
"filesize": "^3.5.6",
|
||||
"gh-release": "^3.0.0",
|
||||
"grunt": "^0.4.5",
|
||||
"grunt-accessibility": "^5.0.0",
|
||||
"grunt-babel": "^6.0.0",
|
||||
@@ -80,7 +91,7 @@
|
||||
"grunt-contrib-concat": "^1.0.1",
|
||||
"grunt-contrib-connect": "~1.0.2",
|
||||
"grunt-contrib-copy": "^1.0.0",
|
||||
"grunt-contrib-cssmin": "~1.0.2",
|
||||
"grunt-contrib-cssmin": "~2.2.0",
|
||||
"grunt-contrib-uglify": "^2.0.0",
|
||||
"grunt-contrib-watch": "~1.0.0",
|
||||
"grunt-coveralls": "^1.0.0",
|
||||
@@ -92,7 +103,8 @@
|
||||
"grunt-version": "~1.1.1",
|
||||
"grunt-videojs-languages": "0.0.4",
|
||||
"grunt-zip": "0.17.1",
|
||||
"husky": "^0.13.1",
|
||||
"humanize-duration": "^3.10.0",
|
||||
"husky": "^0.14.1",
|
||||
"in-publish": "^2.0.0",
|
||||
"istanbul": "^0.4.5",
|
||||
"jsdoc": "^3.4.2",
|
||||
@@ -108,33 +120,49 @@
|
||||
"karma-qunit": "^1.2.0",
|
||||
"karma-safari-launcher": "^1.0.0",
|
||||
"karma-sinon": "^1.0.5",
|
||||
"klaw-sync": "^1.1.2",
|
||||
"load-grunt-tasks": "^3.1.0",
|
||||
"lodash": "^4.16.6",
|
||||
"markdown-table": "^1.0.0",
|
||||
"minimist": "^1.2.0",
|
||||
"npm-run": "^4.1.0",
|
||||
"npm-run-all": "^4.0.2",
|
||||
"proxyquireify": "^3.0.0",
|
||||
"qunitjs": "1.23.1",
|
||||
"remark-cli": "^3.0.0",
|
||||
"remark-lint": "^6.0.0",
|
||||
"remark-parse": "^3.0.1",
|
||||
"remark-stringify": "^3.0.1",
|
||||
"remark-toc": "^4.0.0",
|
||||
"remark-validate-links": "^6.0.0",
|
||||
"replace": "^0.3.0",
|
||||
"rollup": "^0.45.2",
|
||||
"rollup-plugin-babel": "^2.7.1",
|
||||
"rollup-plugin-commonjs": "^8.0.2",
|
||||
"rollup-plugin-filesize": "^1.2.1",
|
||||
"rollup-plugin-ignore": "^1.0.3",
|
||||
"rollup-plugin-json": "^2.1.1",
|
||||
"rollup-plugin-node-resolve": "^3.0.0",
|
||||
"rollup-plugin-progress": "^0.2.1",
|
||||
"rollup-plugin-uglify": "^1.0.2",
|
||||
"rollup-watch": "^4.0.0",
|
||||
"shelljs": "^0.7.5",
|
||||
"sinon": "^1.16.1",
|
||||
"time-grunt": "^1.1.1",
|
||||
"tui-jsdoc-template": "^1.1.0",
|
||||
"uglify-js": "~2.8.8",
|
||||
"unified": "^6.1.5",
|
||||
"videojs-doc-generator": "0.0.1",
|
||||
"videojs-flash": "^1.1.0",
|
||||
"videojs-flash": "^2.0.0",
|
||||
"videojs-standard": "^6.0.1",
|
||||
"webpack": "^2.3.0"
|
||||
"webpack": "^1.15.0"
|
||||
},
|
||||
"vjsstandard": {
|
||||
"ignore": [
|
||||
"**/Gruntfile.js",
|
||||
"**/es5/**",
|
||||
"**/build/**",
|
||||
"!build/rollup.js",
|
||||
"**/dist/**",
|
||||
"**/docs/**",
|
||||
"**/lang/**",
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
<title>Video.js Sandbox</title>
|
||||
|
||||
<!-- Add ES5 shim and sham for IE8 -->
|
||||
<script src="../build/temp/ie8/videojs-ie8.js"></script>
|
||||
<script src="../dist/ie8/videojs-ie8.js"></script>
|
||||
|
||||
<!-- Load the source files -->
|
||||
<link href="../build/temp/video-js.css" rel="stylesheet" type="text/css">
|
||||
<script src="../build/temp/video.js"></script>
|
||||
<script src="../dist/video.js"></script>
|
||||
<script src="../node_modules/videojs-flash/dist/videojs-flash.js"></script>
|
||||
|
||||
<!-- Set the location of the flash SWF -->
|
||||
<script>
|
||||
videojs.options.flash.swf = '../build/temp/video-js.swf';
|
||||
videojs.options.flash.swf = '../node_modules/videojs-flash/node_modules/videojs-swf/dist/video-js.swf';
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
<title>Video.js Text Descriptions, Chapters & Captions Example</title>
|
||||
|
||||
<!-- Add ES5 shim and sham for IE8 -->
|
||||
<script src="../build/temp/ie8/videojs-ie8.js"></script>
|
||||
<script src="../dist/ie8/videojs-ie8.js"></script>
|
||||
|
||||
<!-- Load the source files -->
|
||||
<link href="../build/temp/video-js.css" rel="stylesheet" type="text/css">
|
||||
<script src="../build/temp/video.js"></script>
|
||||
<script src="../dist/video.js"></script>
|
||||
|
||||
<!-- Set the location of the flash SWF -->
|
||||
<script>
|
||||
videojs.options.flash.swf = '../build/temp/video-js.swf';
|
||||
videojs.options.flash.swf = '../node_modules/videojs-flash/node_modules/videojs-swf/dist/video-js.swf';
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
<title>Video.js Sandbox</title>
|
||||
|
||||
<!-- Add ES5 shim and sham for IE8 -->
|
||||
<script src="../build/temp/ie8/videojs-ie8.js"></script>
|
||||
<script src="../dist/ie8/videojs-ie8.js"></script>
|
||||
|
||||
<!-- Load the source files -->
|
||||
<link href="../build/temp/video-js.css" rel="stylesheet" type="text/css">
|
||||
<script src="../build/temp/video.js"></script>
|
||||
<script src="../dist/video.js"></script>
|
||||
<script src="../node_modules/videojs-flash/dist/videojs-flash.js"></script>
|
||||
|
||||
<!-- Set the location of the flash SWF -->
|
||||
<script>
|
||||
videojs.options.flash.swf = '../build/temp/video-js.swf';
|
||||
videojs.options.flash.swf = '../node_modules/videojs-flash/node_modules/videojs-swf/dist/video-js.swf';
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
<title>Video.js Sandbox</title>
|
||||
|
||||
<!-- Add ES5 shim and sham for IE8 -->
|
||||
<script src="../build/temp/ie8/videojs-ie8.js"></script>
|
||||
<script src="../dist/ie8/videojs-ie8.js"></script>
|
||||
|
||||
<!-- Load the source files -->
|
||||
<link href="../build/temp/video-js.css" rel="stylesheet" type="text/css">
|
||||
<script src="../build/temp/video.js"></script>
|
||||
<script src="../dist/video.js"></script>
|
||||
<script src="../node_modules/videojs-flash/dist/videojs-flash.js"></script>
|
||||
|
||||
<!-- Set the location of the flash SWF -->
|
||||
<script>
|
||||
videojs.options.flash.swf = '../build/temp/video-js.swf';
|
||||
videojs.options.flash.swf = '../node_modules/videojs-flash/node_modules/videojs-swf/dist/video-js.swf';
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
@@ -6,15 +6,15 @@
|
||||
<title>VideoJS Languages Demo</title>
|
||||
|
||||
<!-- Add ES5 shim and sham for IE8 -->
|
||||
<script src="../build/temp/ie8/videojs-ie8.js"></script>
|
||||
<script src="../dist/ie8/videojs-ie8.js"></script>
|
||||
|
||||
<!-- Load the source files -->
|
||||
<link href="../build/temp/video-js.css" rel="stylesheet" type="text/css">
|
||||
<script src="../build/temp/video.js"></script>
|
||||
<script src="../dist/video.js"></script>
|
||||
|
||||
<!-- Set the location of the flash SWF -->
|
||||
<script>
|
||||
videojs.options.flash.swf = '../build/temp/video-js.swf';
|
||||
videojs.options.flash.swf = '../node_modules/videojs-flash/node_modules/videojs-swf/dist/video-js.swf';
|
||||
</script>
|
||||
|
||||
<!-- Add support for Spanish 'es' -->
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
<title>Video.js Plugin Example</title>
|
||||
|
||||
<!-- Add ES5 shim and sham for IE8 -->
|
||||
<script src="../build/temp/ie8/videojs-ie8.js"></script>
|
||||
<script src="../dist/ie8/videojs-ie8.js"></script>
|
||||
|
||||
<!-- Load the source files -->
|
||||
<link href="../build/temp/video-js.css" rel="stylesheet" type="text/css">
|
||||
<script src="../build/temp/video.js"></script>
|
||||
<script src="../dist/video.js"></script>
|
||||
|
||||
<!-- Set the location of the flash SWF -->
|
||||
<script>
|
||||
videojs.options.flash.swf = '../build/temp/video-js.swf';
|
||||
videojs.options.flash.swf = '../node_modules/videojs-flash/node_modules/videojs-swf/dist/video-js.swf';
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
// TODO: I feel like this should be a generic menu. Research later.
|
||||
.vjs-playback-rate > .vjs-menu-button,
|
||||
.vjs-playback-rate .vjs-playback-rate-value {
|
||||
font-size: 1.5em;
|
||||
line-height: 2;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.vjs-playback-rate .vjs-playback-rate-value {
|
||||
pointer-events: none;
|
||||
font-size: 1.5em;
|
||||
line-height: 2;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ class ClickableComponent extends Component {
|
||||
const localizedText = this.localize(text);
|
||||
|
||||
this.controlText_ = text;
|
||||
this.controlTextEl_.innerHTML = localizedText;
|
||||
Dom.textContent(this.controlTextEl_, localizedText);
|
||||
if (!this.nonIconControl) {
|
||||
// Set title attribute if only an icon is shown
|
||||
el.setAttribute('title', localizedText);
|
||||
|
||||
@@ -70,6 +70,26 @@ class OffTextTrackMenuItem extends TextTrackMenuItem {
|
||||
this.selected(selected);
|
||||
}
|
||||
|
||||
handleSelectedLanguageChange(event) {
|
||||
const tracks = this.player().textTracks();
|
||||
let allHidden = true;
|
||||
|
||||
for (let i = 0, l = tracks.length; i < l; i++) {
|
||||
const track = tracks[i];
|
||||
|
||||
if ((['captions', 'descriptions', 'subtitles'].indexOf(track.kind) > -1) && track.mode === 'showing') {
|
||||
allHidden = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (allHidden) {
|
||||
this.player_.cache_.selectedLanguage = {
|
||||
enabled: false
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Component.registerComponent('OffTextTrackMenuItem', OffTextTrackMenuItem);
|
||||
|
||||
@@ -66,6 +66,7 @@ class TextTrackButton extends TrackButton {
|
||||
|
||||
// only add tracks that are of an appropriate kind and have a label
|
||||
if (this.kinds_.indexOf(track.kind) > -1) {
|
||||
|
||||
const item = new TrackMenuItem(this.player_, {
|
||||
track,
|
||||
// MenuItem is selectable
|
||||
|
||||
@@ -29,17 +29,20 @@ class TextTrackMenuItem extends MenuItem {
|
||||
|
||||
// Modify options for parent MenuItem class's init.
|
||||
options.label = track.label || track.language || 'Unknown';
|
||||
options.selected = track.default || track.mode === 'showing';
|
||||
options.selected = track.mode === 'showing';
|
||||
|
||||
super(player, options);
|
||||
|
||||
this.track = track;
|
||||
const changeHandler = Fn.bind(this, this.handleTracksChange);
|
||||
const selectedLanguageChangeHandler = Fn.bind(this, this.handleSelectedLanguageChange);
|
||||
|
||||
player.on(['loadstart', 'texttrackchange'], changeHandler);
|
||||
tracks.addEventListener('change', changeHandler);
|
||||
tracks.addEventListener('selectedlanguagechange', selectedLanguageChangeHandler);
|
||||
this.on('dispose', function() {
|
||||
tracks.removeEventListener('change', changeHandler);
|
||||
tracks.removeEventListener('selectedlanguagechange', selectedLanguageChangeHandler);
|
||||
});
|
||||
|
||||
// iOS7 doesn't dispatch change events to TextTrackLists when an
|
||||
@@ -122,6 +125,25 @@ class TextTrackMenuItem extends MenuItem {
|
||||
this.selected(this.track.mode === 'showing');
|
||||
}
|
||||
|
||||
handleSelectedLanguageChange(event) {
|
||||
if (this.track.mode === 'showing') {
|
||||
const selectedLanguage = this.player_.cache_.selectedLanguage;
|
||||
|
||||
// Don't replace the kind of track across the same language
|
||||
if (selectedLanguage && selectedLanguage.enabled &&
|
||||
selectedLanguage.language === this.track.language &&
|
||||
selectedLanguage.kind !== this.track.kind) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.player_.cache_.selectedLanguage = {
|
||||
enabled: true,
|
||||
language: this.track.language,
|
||||
kind: this.track.kind
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Component.registerComponent('TextTrackMenuItem', TextTrackMenuItem);
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* @file current-time-display.js
|
||||
*/
|
||||
import document from 'global/document';
|
||||
import Component from '../../component.js';
|
||||
import * as Dom from '../../utils/dom.js';
|
||||
import {bind, throttle} from '../../utils/fn.js';
|
||||
import formatTime from '../../utils/format-time.js';
|
||||
|
||||
/**
|
||||
@@ -23,8 +25,8 @@ class CurrentTimeDisplay extends Component {
|
||||
*/
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
|
||||
this.on(player, 'timeupdate', this.updateContent);
|
||||
this.throttledUpdateContent = throttle(bind(this, this.updateContent), 25);
|
||||
this.on(player, 'timeupdate', this.throttledUpdateContent);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,18 +41,34 @@ class CurrentTimeDisplay extends Component {
|
||||
});
|
||||
|
||||
this.contentEl_ = Dom.createEl('div', {
|
||||
className: 'vjs-current-time-display',
|
||||
// label the current time for screen reader users
|
||||
innerHTML: '<span class="vjs-control-text">Current Time </span>' + '0:00'
|
||||
className: 'vjs-current-time-display'
|
||||
}, {
|
||||
// tell screen readers not to automatically read the time as it changes
|
||||
'aria-live': 'off'
|
||||
});
|
||||
}, Dom.createEl('span', {
|
||||
className: 'vjs-control-text',
|
||||
textContent: this.localize('Current Time')
|
||||
}));
|
||||
|
||||
this.updateTextNode_();
|
||||
el.appendChild(this.contentEl_);
|
||||
return el;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the "current time" text node with new content using the
|
||||
* contents of the `formattedTime_` property.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
updateTextNode_() {
|
||||
if (this.textNode_) {
|
||||
this.contentEl_.removeChild(this.textNode_);
|
||||
}
|
||||
this.textNode_ = document.createTextNode(` ${this.formattedTime_ || '0:00'}`);
|
||||
this.contentEl_.appendChild(this.textNode_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update current time display
|
||||
*
|
||||
@@ -62,12 +80,11 @@ class CurrentTimeDisplay extends Component {
|
||||
updateContent(event) {
|
||||
// Allows for smooth scrubbing, when player can't keep up.
|
||||
const time = (this.player_.scrubbing()) ? this.player_.getCache().currentTime : this.player_.currentTime();
|
||||
const localizedText = this.localize('Current Time');
|
||||
const formattedTime = formatTime(time, this.player_.duration());
|
||||
|
||||
if (formattedTime !== this.formattedTime_) {
|
||||
this.formattedTime_ = formattedTime;
|
||||
this.contentEl_.innerHTML = `<span class="vjs-control-text">${localizedText}</span> ${formattedTime}`;
|
||||
this.requestAnimationFrame(this.updateTextNode_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* @file duration-display.js
|
||||
*/
|
||||
import document from 'global/document';
|
||||
import Component from '../../component.js';
|
||||
import * as Dom from '../../utils/dom.js';
|
||||
import {bind, throttle} from '../../utils/fn.js';
|
||||
import formatTime from '../../utils/format-time.js';
|
||||
|
||||
/**
|
||||
@@ -24,13 +26,17 @@ class DurationDisplay extends Component {
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
|
||||
this.on(player, 'durationchange', this.updateContent);
|
||||
this.throttledUpdateContent = throttle(bind(this, this.updateContent), 25);
|
||||
|
||||
// Also listen for timeupdate and loadedmetadata because removing those
|
||||
// listeners could have broken dependent applications/libraries. These
|
||||
// can likely be removed for 6.0.
|
||||
this.on(player, 'timeupdate', this.updateContent);
|
||||
this.on(player, 'loadedmetadata', this.updateContent);
|
||||
this.on(player, [
|
||||
'durationchange',
|
||||
|
||||
// Also listen for timeupdate and loadedmetadata because removing those
|
||||
// listeners could have broken dependent applications/libraries. These
|
||||
// can likely be removed for 7.0.
|
||||
'loadedmetadata',
|
||||
'timeupdate'
|
||||
], this.throttledUpdateContent);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -45,18 +51,34 @@ class DurationDisplay extends Component {
|
||||
});
|
||||
|
||||
this.contentEl_ = Dom.createEl('div', {
|
||||
className: 'vjs-duration-display',
|
||||
// label the duration time for screen reader users
|
||||
innerHTML: `<span class="vjs-control-text">${this.localize('Duration Time')}</span> 0:00`
|
||||
className: 'vjs-duration-display'
|
||||
}, {
|
||||
// tell screen readers not to automatically read the time as it changes
|
||||
'aria-live': 'off'
|
||||
});
|
||||
}, Dom.createEl('span', {
|
||||
className: 'vjs-control-text',
|
||||
textContent: this.localize('Duration Time')
|
||||
}));
|
||||
|
||||
this.updateTextNode_();
|
||||
el.appendChild(this.contentEl_);
|
||||
return el;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the "current time" text node with new content using the
|
||||
* contents of the `formattedTime_` property.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
updateTextNode_() {
|
||||
if (this.textNode_) {
|
||||
this.contentEl_.removeChild(this.textNode_);
|
||||
}
|
||||
this.textNode_ = document.createTextNode(` ${this.formattedTime_ || '0:00'}`);
|
||||
this.contentEl_.appendChild(this.textNode_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update duration time display.
|
||||
*
|
||||
@@ -73,14 +95,10 @@ class DurationDisplay extends Component {
|
||||
|
||||
if (duration && this.duration_ !== duration) {
|
||||
this.duration_ = duration;
|
||||
const localizedText = this.localize('Duration Time');
|
||||
const formattedTime = formatTime(duration);
|
||||
|
||||
// label the duration time for screen reader users
|
||||
this.contentEl_.innerHTML = `<span class="vjs-control-text">${localizedText}</span> ${formattedTime}`;
|
||||
this.formattedTime_ = formatTime(duration);
|
||||
this.requestAnimationFrame(this.updateTextNode_);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Component.registerComponent('DurationDisplay', DurationDisplay);
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* @file remaining-time-display.js
|
||||
*/
|
||||
import document from 'global/document';
|
||||
import Component from '../../component.js';
|
||||
import * as Dom from '../../utils/dom.js';
|
||||
import {bind, throttle} from '../../utils/fn.js';
|
||||
import formatTime from '../../utils/format-time.js';
|
||||
|
||||
/**
|
||||
@@ -23,9 +25,8 @@ class RemainingTimeDisplay extends Component {
|
||||
*/
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
|
||||
this.on(player, 'timeupdate', this.updateContent);
|
||||
this.on(player, 'durationchange', this.updateContent);
|
||||
this.throttledUpdateContent = throttle(bind(this, this.updateContent), 25);
|
||||
this.on(player, ['timeupdate', 'durationchange'], this.throttledUpdateContent);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -40,18 +41,34 @@ class RemainingTimeDisplay extends Component {
|
||||
});
|
||||
|
||||
this.contentEl_ = Dom.createEl('div', {
|
||||
className: 'vjs-remaining-time-display',
|
||||
// label the remaining time for screen reader users
|
||||
innerHTML: `<span class="vjs-control-text">${this.localize('Remaining Time')}</span> -0:00`
|
||||
className: 'vjs-remaining-time-display'
|
||||
}, {
|
||||
// tell screen readers not to automatically read the time as it changes
|
||||
'aria-live': 'off'
|
||||
});
|
||||
}, Dom.createEl('span', {
|
||||
className: 'vjs-control-text',
|
||||
textContent: this.localize('Remaining Time')
|
||||
}));
|
||||
|
||||
this.updateTextNode_();
|
||||
el.appendChild(this.contentEl_);
|
||||
return el;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the "remaining time" text node with new content using the
|
||||
* contents of the `formattedTime_` property.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
updateTextNode_() {
|
||||
if (this.textNode_) {
|
||||
this.contentEl_.removeChild(this.textNode_);
|
||||
}
|
||||
this.textNode_ = document.createTextNode(` -${this.formattedTime_ || '0:00'}`);
|
||||
this.contentEl_.appendChild(this.textNode_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update remaining time display.
|
||||
*
|
||||
@@ -63,20 +80,14 @@ class RemainingTimeDisplay extends Component {
|
||||
*/
|
||||
updateContent(event) {
|
||||
if (this.player_.duration()) {
|
||||
const localizedText = this.localize('Remaining Time');
|
||||
const formattedTime = formatTime(this.player_.remainingTime());
|
||||
|
||||
if (formattedTime !== this.formattedTime_) {
|
||||
this.formattedTime_ = formattedTime;
|
||||
this.contentEl_.innerHTML = `<span class="vjs-control-text">${localizedText}</span> -${formattedTime}`;
|
||||
this.requestAnimationFrame(this.updateTextNode_);
|
||||
}
|
||||
}
|
||||
|
||||
// Allows for smooth scrubbing, when player can't keep up.
|
||||
// var time = (this.player_.scrubbing()) ? this.player_.getCache().currentTime : this.player_.currentTime();
|
||||
// this.contentEl_.innerHTML = vjs.formatTime(time, this.player_.duration());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Component.registerComponent('RemainingTimeDisplay', RemainingTimeDisplay);
|
||||
|
||||
+22
-18
@@ -4,6 +4,7 @@
|
||||
// Subclasses Component
|
||||
import Component from './component.js';
|
||||
|
||||
import {version} from '../../package.json';
|
||||
import document from 'global/document';
|
||||
import window from 'global/window';
|
||||
import tsml from 'tsml';
|
||||
@@ -147,7 +148,7 @@ const TECH_EVENTS_RETRIGGER = [
|
||||
/**
|
||||
* Fires when the browser has loaded the current frame of the audio/video.
|
||||
*
|
||||
* @event player#loadeddata
|
||||
* @event Player#loadeddata
|
||||
* @type {event}
|
||||
*/
|
||||
/**
|
||||
@@ -163,7 +164,7 @@ const TECH_EVENTS_RETRIGGER = [
|
||||
/**
|
||||
* Fires when the current playback position has changed.
|
||||
*
|
||||
* @event player#timeupdate
|
||||
* @event Player#timeupdate
|
||||
* @type {event}
|
||||
*/
|
||||
/**
|
||||
@@ -179,7 +180,7 @@ const TECH_EVENTS_RETRIGGER = [
|
||||
/**
|
||||
* Fires when the playing speed of the audio/video is changed
|
||||
*
|
||||
* @event player#ratechange
|
||||
* @event Player#ratechange
|
||||
* @type {event}
|
||||
*/
|
||||
/**
|
||||
@@ -211,7 +212,7 @@ const TECH_EVENTS_RETRIGGER = [
|
||||
/**
|
||||
* Fires when the volume has been changed
|
||||
*
|
||||
* @event player#volumechange
|
||||
* @event Player#volumechange
|
||||
* @type {event}
|
||||
*/
|
||||
/**
|
||||
@@ -227,7 +228,7 @@ const TECH_EVENTS_RETRIGGER = [
|
||||
/**
|
||||
* Fires when the text track has been changed
|
||||
*
|
||||
* @event player#texttrackchange
|
||||
* @event Player#texttrackchange
|
||||
* @type {event}
|
||||
*/
|
||||
/**
|
||||
@@ -443,7 +444,7 @@ class Player extends Component {
|
||||
Player.players[this.id_] = this;
|
||||
|
||||
// Add a major version class to aid css in plugins
|
||||
const majorVersion = require('../../package.json').version.split('.')[0];
|
||||
const majorVersion = version.split('.')[0];
|
||||
|
||||
this.addClass(`vjs-v${majorVersion}`);
|
||||
|
||||
@@ -1746,10 +1747,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) {
|
||||
@@ -2245,17 +2247,19 @@ class Player extends Component {
|
||||
}
|
||||
|
||||
/**
|
||||
* The source function updates the video source
|
||||
* There are three types of variables you can pass as the argument.
|
||||
* **URL string**: A URL to the the video file. Use this method if you are sure
|
||||
* the current playback technology (HTML5/Flash) can support the source you
|
||||
* provide. Currently only MP4 files can be used in both HTML5 and Flash.
|
||||
* Get or set the video source.
|
||||
*
|
||||
* @param {Tech~SourceObject|Tech~SourceObject[]} [source]
|
||||
* One SourceObject or an array of SourceObjects
|
||||
* @param {Tech~SourceObject|Tech~SourceObject[]|string} [source]
|
||||
* A SourceObject, an array of SourceObjects, or a string referencing
|
||||
* a URL to a media source. It is _highly recommended_ that an object
|
||||
* or array of objects is used here, so that source selection
|
||||
* algorithms can take the `type` into account.
|
||||
*
|
||||
* @return {string}
|
||||
* The current video source when getting
|
||||
* If not provided, this method acts as a getter.
|
||||
*
|
||||
* @return {string|undefined}
|
||||
* If the `source` argument is missing, returns the current source
|
||||
* URL. Otherwise, returns nothing/undefined.
|
||||
*/
|
||||
src(source) {
|
||||
// getter usage
|
||||
@@ -3265,7 +3269,7 @@ class Player extends Component {
|
||||
* @return {TextTrackList}
|
||||
* The current remote text track list
|
||||
*
|
||||
* @method Player.prototype.textTracks
|
||||
* @method Player.prototype.remoteTextTracks
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
+23
-18
@@ -368,24 +368,26 @@ class Html5 extends Tech {
|
||||
// playback has started, which triggers the live display erroneously.
|
||||
// Return NaN if playback has not started and trigger a durationupdate once
|
||||
// the duration can be reliably known.
|
||||
if (this.el_.duration === Infinity &&
|
||||
browser.IS_ANDROID && browser.IS_CHROME) {
|
||||
if (this.el_.currentTime === 0) {
|
||||
// Wait for the first `timeupdate` with currentTime > 0 - there may be
|
||||
// several with 0
|
||||
const checkProgress = () => {
|
||||
if (this.el_.currentTime > 0) {
|
||||
// Trigger durationchange for genuinely live video
|
||||
if (this.el_.duration === Infinity) {
|
||||
this.trigger('durationchange');
|
||||
}
|
||||
this.off('timeupdate', checkProgress);
|
||||
if (
|
||||
this.el_.duration === Infinity &&
|
||||
browser.IS_ANDROID &&
|
||||
browser.IS_CHROME &&
|
||||
this.el_.currentTime === 0
|
||||
) {
|
||||
// Wait for the first `timeupdate` with currentTime > 0 - there may be
|
||||
// several with 0
|
||||
const checkProgress = () => {
|
||||
if (this.el_.currentTime > 0) {
|
||||
// Trigger durationchange for genuinely live video
|
||||
if (this.el_.duration === Infinity) {
|
||||
this.trigger('durationchange');
|
||||
}
|
||||
};
|
||||
this.off('timeupdate', checkProgress);
|
||||
}
|
||||
};
|
||||
|
||||
this.on('timeupdate', checkProgress);
|
||||
return NaN;
|
||||
}
|
||||
this.on('timeupdate', checkProgress);
|
||||
return NaN;
|
||||
}
|
||||
return this.el_.duration || NaN;
|
||||
}
|
||||
@@ -430,9 +432,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);
|
||||
|
||||
@@ -14,6 +14,7 @@ import document from 'global/document';
|
||||
import {isPlain} from '../utils/obj';
|
||||
import * as TRACK_TYPES from '../tracks/track-types';
|
||||
import toTitleCase from '../utils/to-title-case';
|
||||
import vtt from 'videojs-vtt.js';
|
||||
|
||||
/**
|
||||
* An Object containing a structure like: `{src: 'url', type: 'mimetype'}` or string
|
||||
@@ -516,7 +517,6 @@ class Tech extends Component {
|
||||
// signals that the Tech is ready at which point Tech.el_ is part of the DOM
|
||||
// before inserting the WebVTT script
|
||||
if (document.body.contains(this.el())) {
|
||||
const vtt = require('videojs-vtt.js');
|
||||
|
||||
// load via require if available and vtt.js script location was not passed in
|
||||
// as an option. novtt builds will turn the above require call into an empty object
|
||||
@@ -530,7 +530,7 @@ class Tech extends Component {
|
||||
// passed in
|
||||
const script = document.createElement('script');
|
||||
|
||||
script.src = this.options_['vtt.js'] || 'https://vjs.zencdn.net/vttjs/0.12.3/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.
|
||||
@@ -700,7 +700,7 @@ class Tech extends Component {
|
||||
|
||||
if (manualCleanup !== true) {
|
||||
// create the TextTrackList if it doesn't exist
|
||||
this.autoRemoteTextTracks_.addTrack(htmlTrackElement.track);
|
||||
this.ready(() => this.autoRemoteTextTracks_.addTrack(htmlTrackElement.track));
|
||||
}
|
||||
|
||||
return htmlTrackElement;
|
||||
|
||||
@@ -19,7 +19,7 @@ import document from 'global/document';
|
||||
*/
|
||||
const disableOthers = function(list, track) {
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
if (track.id === list[i].id) {
|
||||
if (!Object.keys(list[i]).length || track.id === list[i].id) {
|
||||
continue;
|
||||
}
|
||||
// another audio track is enabled, disable it
|
||||
|
||||
@@ -92,6 +92,7 @@ class TextTrackDisplay extends Component {
|
||||
|
||||
player.on('loadstart', Fn.bind(this, this.toggleDisplay));
|
||||
player.on('texttrackchange', Fn.bind(this, this.updateDisplay));
|
||||
player.on('loadstart', Fn.bind(this, this.preselectTrack));
|
||||
|
||||
// This used to be called during player init, but was causing an error
|
||||
// if a track should show by default and the display hadn't loaded yet.
|
||||
@@ -111,33 +112,66 @@ class TextTrackDisplay extends Component {
|
||||
this.player_.addRemoteTextTrack(tracks[i], true);
|
||||
}
|
||||
|
||||
const modes = {captions: 1, subtitles: 1};
|
||||
const trackList = this.player_.textTracks();
|
||||
let firstDesc;
|
||||
let firstCaptions;
|
||||
this.preselectTrack();
|
||||
}));
|
||||
}
|
||||
|
||||
for (let i = 0; i < trackList.length; i++) {
|
||||
const track = trackList[i];
|
||||
/**
|
||||
* Preselect a track following this precedence:
|
||||
* - matches the previously selected {@link TextTrack}'s language and kind
|
||||
* - matches the previously selected {@link TextTrack}'s language only
|
||||
* - is the first default captions track
|
||||
* - is the first default descriptions track
|
||||
*
|
||||
* @listens Player#loadstart
|
||||
*/
|
||||
preselectTrack() {
|
||||
const modes = {captions: 1, subtitles: 1};
|
||||
const trackList = this.player_.textTracks();
|
||||
const userPref = this.player_.cache_.selectedLanguage;
|
||||
let firstDesc;
|
||||
let firstCaptions;
|
||||
let preferredTrack;
|
||||
|
||||
if (track.default) {
|
||||
if (track.kind === 'descriptions' && !firstDesc) {
|
||||
firstDesc = track;
|
||||
} else if (track.kind in modes && !firstCaptions) {
|
||||
firstCaptions = track;
|
||||
}
|
||||
for (let i = 0; i < trackList.length; i++) {
|
||||
const track = trackList[i];
|
||||
|
||||
if (userPref && userPref.enabled &&
|
||||
userPref.language === track.language) {
|
||||
// Always choose the track that matches both language and kind
|
||||
if (track.kind === userPref.kind) {
|
||||
preferredTrack = track;
|
||||
// or choose the first track that matches language
|
||||
} else if (!preferredTrack) {
|
||||
preferredTrack = track;
|
||||
}
|
||||
|
||||
// clear everything if offTextTrackMenuItem was clicked
|
||||
} else if (userPref && !userPref.enabled) {
|
||||
preferredTrack = null;
|
||||
firstDesc = null;
|
||||
firstCaptions = null;
|
||||
|
||||
} else if (track.default) {
|
||||
if (track.kind === 'descriptions' && !firstDesc) {
|
||||
firstDesc = track;
|
||||
} else if (track.kind in modes && !firstCaptions) {
|
||||
firstCaptions = track;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We want to show the first default track but captions and subtitles
|
||||
// take precedence over descriptions.
|
||||
// So, display the first default captions or subtitles track
|
||||
// and otherwise the first default descriptions track.
|
||||
if (firstCaptions) {
|
||||
firstCaptions.mode = 'showing';
|
||||
} else if (firstDesc) {
|
||||
firstDesc.mode = 'showing';
|
||||
}
|
||||
}));
|
||||
// The preferredTrack matches the user preference and takes
|
||||
// precendence over all the other tracks.
|
||||
// So, display the preferredTrack before the first default track
|
||||
// and the subtitles/captions track before the descriptions track
|
||||
if (preferredTrack) {
|
||||
preferredTrack.mode = 'showing';
|
||||
} else if (firstCaptions) {
|
||||
firstCaptions.mode = 'showing';
|
||||
} else if (firstDesc) {
|
||||
firstDesc.mode = 'showing';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -61,6 +61,14 @@ class TextTrackList extends TrackList {
|
||||
track.addEventListener('modechange', Fn.bind(this, function() {
|
||||
this.trigger('change');
|
||||
}));
|
||||
|
||||
const nonLanguageTextTrackKind = ['metadata', 'chapters'];
|
||||
|
||||
if (nonLanguageTextTrackKind.indexOf(track.kind) === -1) {
|
||||
track.addEventListener('modechange', Fn.bind(this, function() {
|
||||
this.trigger('selectedlanguagechange');
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
export default TextTrackList;
|
||||
|
||||
@@ -299,8 +299,9 @@ class TextTrackSettings extends ModalDialog {
|
||||
* @param {string} key
|
||||
* Configuration key to use during creation.
|
||||
*
|
||||
* @return {Element}
|
||||
* The DOM element that gets created.
|
||||
* @return {string}
|
||||
* An HTML string.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
createElSelect_(key, legendId = '', type = 'label') {
|
||||
@@ -308,101 +309,94 @@ class TextTrackSettings extends ModalDialog {
|
||||
const id = config.id.replace('%s', this.id_);
|
||||
|
||||
return [
|
||||
createEl(type, {
|
||||
id,
|
||||
className: type === 'label' ? 'vjs-label' : '',
|
||||
textContent: this.localize(config.label)
|
||||
}, {
|
||||
}),
|
||||
createEl('select', {}, {
|
||||
'aria-labelledby': `${legendId} ${id}`
|
||||
}, config.options.map(o => {
|
||||
`<${type} id="${id}" class="${type === 'label' ? 'vjs-label' : ''}">`,
|
||||
this.localize(config.label),
|
||||
`</${type}>`,
|
||||
`<select aria-labelledby="${legendId} ${id}">`
|
||||
].
|
||||
concat(config.options.map(o => {
|
||||
const optionId = id + '-' + o[1];
|
||||
|
||||
return createEl('option', {
|
||||
id: optionId,
|
||||
textContent: this.localize(o[1]),
|
||||
value: o[0]
|
||||
}, {
|
||||
'aria-labelledby': `${legendId} ${id} ${optionId}`
|
||||
});
|
||||
}))
|
||||
];
|
||||
return [
|
||||
`<option id="${optionId}" value="${o[0]}" `,
|
||||
`aria-labelledby="${legendId} ${id} ${optionId}">`,
|
||||
this.localize(o[1]),
|
||||
'</option>'
|
||||
].join('');
|
||||
})).
|
||||
concat('</select>').join('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create foreground color element for the component
|
||||
*
|
||||
* @return {Element}
|
||||
* The element that was created.
|
||||
* @return {string}
|
||||
* An HTML string.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
createElFgColor_() {
|
||||
const legend = createEl('legend', {
|
||||
id: `captions-text-legend-${this.id_}`,
|
||||
textContent: this.localize('Text')
|
||||
});
|
||||
const legendId = `captions-text-legend-${this.id_}`;
|
||||
|
||||
const select = this.createElSelect_('color', legend.id);
|
||||
|
||||
const opacity = createEl('span', {
|
||||
className: 'vjs-text-opacity vjs-opacity'
|
||||
}, undefined, this.createElSelect_('textOpacity', legend.id));
|
||||
|
||||
return createEl('fieldset', {
|
||||
className: 'vjs-fg-color vjs-track-setting'
|
||||
}, undefined, [legend].concat(select, opacity));
|
||||
return [
|
||||
'<fieldset class="vjs-fg-color vjs-track-setting">',
|
||||
`<legend id="${legendId}">`,
|
||||
this.localize('Text'),
|
||||
'</legend>',
|
||||
this.createElSelect_('color', legendId),
|
||||
'<span class="vjs-text-opacity vjs-opacity">',
|
||||
this.createElSelect_('textOpacity', legendId),
|
||||
'</span>',
|
||||
'</fieldset>'
|
||||
].join('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create background color element for the component
|
||||
*
|
||||
* @return {Element}
|
||||
* The element that was created
|
||||
* @return {string}
|
||||
* An HTML string.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
createElBgColor_() {
|
||||
const legend = createEl('legend', {
|
||||
id: `captions-background-${this.id_}`,
|
||||
textContent: this.localize('Background')
|
||||
});
|
||||
const legendId = `captions-background-${this.id_}`;
|
||||
|
||||
const select = this.createElSelect_('backgroundColor', legend.id);
|
||||
|
||||
const opacity = createEl('span', {
|
||||
className: 'vjs-bg-opacity vjs-opacity'
|
||||
}, undefined, this.createElSelect_('backgroundOpacity', legend.id));
|
||||
|
||||
return createEl('fieldset', {
|
||||
className: 'vjs-bg-color vjs-track-setting'
|
||||
}, undefined, [legend].concat(select, opacity));
|
||||
return [
|
||||
'<fieldset class="vjs-bg-color vjs-track-setting">',
|
||||
`<legend id="${legendId}">`,
|
||||
this.localize('Background'),
|
||||
'</legend>',
|
||||
this.createElSelect_('backgroundColor', legendId),
|
||||
'<span class="vjs-bg-opacity vjs-opacity">',
|
||||
this.createElSelect_('backgroundOpacity', legendId),
|
||||
'</span>',
|
||||
'</fieldset>'
|
||||
].join('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create window color element for the component
|
||||
*
|
||||
* @return {Element}
|
||||
* The element that was created
|
||||
* @return {string}
|
||||
* An HTML string.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
createElWinColor_() {
|
||||
const legend = createEl('legend', {
|
||||
id: `captions-window-${this.id_}`,
|
||||
textContent: this.localize('Window')
|
||||
});
|
||||
const legendId = `captions-window-${this.id_}`;
|
||||
|
||||
const select = this.createElSelect_('windowColor', legend.id);
|
||||
|
||||
const opacity = createEl('span', {
|
||||
className: 'vjs-window-opacity vjs-opacity'
|
||||
}, undefined, this.createElSelect_('windowOpacity', legend.id));
|
||||
|
||||
return createEl('fieldset', {
|
||||
className: 'vjs-window-color vjs-track-setting'
|
||||
}, undefined, [legend].concat(select, opacity));
|
||||
return [
|
||||
'<fieldset class="vjs-window-color vjs-track-setting">',
|
||||
`<legend id="${legendId}">`,
|
||||
this.localize('Window'),
|
||||
'</legend>',
|
||||
this.createElSelect_('windowColor', legendId),
|
||||
'<span class="vjs-window-opacity vjs-opacity">',
|
||||
this.createElSelect_('windowOpacity', legendId),
|
||||
'</span>',
|
||||
'</fieldset>'
|
||||
].join('');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -415,12 +409,13 @@ class TextTrackSettings extends ModalDialog {
|
||||
*/
|
||||
createElColors_() {
|
||||
return createEl('div', {
|
||||
className: 'vjs-track-settings-colors'
|
||||
}, undefined, [
|
||||
this.createElFgColor_(),
|
||||
this.createElBgColor_(),
|
||||
this.createElWinColor_()
|
||||
]);
|
||||
className: 'vjs-track-settings-colors',
|
||||
innerHTML: [
|
||||
this.createElFgColor_(),
|
||||
this.createElBgColor_(),
|
||||
this.createElWinColor_()
|
||||
].join('')
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -432,21 +427,20 @@ class TextTrackSettings extends ModalDialog {
|
||||
* @private
|
||||
*/
|
||||
createElFont_() {
|
||||
const fontPercent = createEl('fieldset', {
|
||||
className: 'vjs-font-percent vjs-track-setting'
|
||||
}, undefined, this.createElSelect_('fontPercent', '', 'legend'));
|
||||
|
||||
const edgeStyle = createEl('fieldset', {
|
||||
className: 'vjs-edge-style vjs-track-setting'
|
||||
}, undefined, this.createElSelect_('edgeStyle', '', 'legend'));
|
||||
|
||||
const fontFamily = createEl('fieldset', {
|
||||
className: 'vjs-font-family vjs-track-setting'
|
||||
}, undefined, this.createElSelect_('fontFamily', '', 'legend'));
|
||||
|
||||
return createEl('div', {
|
||||
className: 'vjs-track-settings-font'
|
||||
}, undefined, [fontPercent, edgeStyle, fontFamily]);
|
||||
className: 'vjs-track-settings-font">',
|
||||
innerHTML: [
|
||||
'<fieldset class="vjs-font-percent vjs-track-setting">',
|
||||
this.createElSelect_('fontPercent', '', 'legend'),
|
||||
'</fieldset>',
|
||||
'<fieldset class="vjs-edge-style vjs-track-setting">',
|
||||
this.createElSelect_('edgeStyle', '', 'legend'),
|
||||
'</fieldset>',
|
||||
'<fieldset class="vjs-font-family vjs-track-setting">',
|
||||
this.createElSelect_('fontFamily', '', 'legend'),
|
||||
'</fieldset>'
|
||||
].join('')
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -459,30 +453,17 @@ class TextTrackSettings extends ModalDialog {
|
||||
*/
|
||||
createElControls_() {
|
||||
const defaultsDescription = this.localize('restore all settings to the default values');
|
||||
const defaultsButton = createEl('button', {
|
||||
className: 'vjs-default-button',
|
||||
title: defaultsDescription,
|
||||
innerHTML: `${this.localize('Reset')}<span class='vjs-control-text'> ${defaultsDescription}</span>`
|
||||
});
|
||||
|
||||
const doneButton = createEl('button', {
|
||||
className: 'vjs-done-button',
|
||||
textContent: this.localize('Done')
|
||||
});
|
||||
|
||||
return createEl('div', {
|
||||
className: 'vjs-track-settings-controls'
|
||||
}, undefined, [defaultsButton, doneButton]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @return {Element}
|
||||
* The element that was created.
|
||||
*/
|
||||
createEl() {
|
||||
return super.createEl();
|
||||
className: 'vjs-track-settings-controls',
|
||||
innerHTML: [
|
||||
`<button class="vjs-default-button" title="${defaultsDescription}">`,
|
||||
this.localize('Reset'),
|
||||
`<span class="vjs-control-text"> ${defaultsDescription}</span>`,
|
||||
'</button>',
|
||||
`<button class="vjs-done-button">${this.localize('Done')}</button>`
|
||||
].join('')
|
||||
});
|
||||
}
|
||||
|
||||
content() {
|
||||
|
||||
@@ -253,6 +253,7 @@ class TextTrack extends Track {
|
||||
* @type {EventTarget~Event}
|
||||
*/
|
||||
this.trigger('modechange');
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ import document from 'global/document';
|
||||
*/
|
||||
const disableOthers = function(list, track) {
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
if (track.id === list[i].id) {
|
||||
if (!Object.keys(list[i]).length || track.id === list[i].id) {
|
||||
continue;
|
||||
}
|
||||
// another video track is enabled, disable it
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+3
-4
@@ -2,6 +2,7 @@
|
||||
* @file video.js
|
||||
* @module videojs
|
||||
*/
|
||||
import {version} from '../../package.json';
|
||||
import window from 'global/window';
|
||||
import document from 'global/document';
|
||||
import * as setup from './setup';
|
||||
@@ -225,7 +226,7 @@ setup.autoSetupTimeout(1, videojs);
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
videojs.VERSION = require('../../package.json').version;
|
||||
videojs.VERSION = version;
|
||||
|
||||
/**
|
||||
* The global options object. These are the settings that take effect
|
||||
@@ -722,7 +723,5 @@ videojs.dom = Dom;
|
||||
*/
|
||||
videojs.url = Url;
|
||||
|
||||
// We use Node-style module.exports here instead of ES6 because it is more
|
||||
// compatible with different module systems.
|
||||
module.exports = videojs;
|
||||
export default videojs;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ module.exports = function(config) {
|
||||
// Compling tests here
|
||||
files: [
|
||||
'../build/temp/video-js.css',
|
||||
'../build/temp/ie8/videojs-ie8.min.js',
|
||||
'../build/temp/ie8/videojs-ie8.js',
|
||||
'../test/globals-shim.js',
|
||||
'../test/unit/**/*.js',
|
||||
'../build/temp/browserify.js',
|
||||
@@ -124,7 +124,7 @@ module.exports = function(config) {
|
||||
'ie8_bs'
|
||||
];
|
||||
} else {
|
||||
settings.browsers = ['Firefox'];
|
||||
settings.browsers = ['chrome_travis'];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,6 +133,11 @@ module.exports = function(config) {
|
||||
|
||||
function getCustomLaunchers(){
|
||||
return {
|
||||
chrome_travis: {
|
||||
base: 'Chrome',
|
||||
flags: ['--no-sandbox']
|
||||
},
|
||||
|
||||
chrome_bs: {
|
||||
base: 'BrowserStack',
|
||||
browser: 'chrome',
|
||||
|
||||
@@ -1655,3 +1655,31 @@ QUnit.test('should add a class with major version', function(assert) {
|
||||
|
||||
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');
|
||||
});
|
||||
|
||||
@@ -214,11 +214,14 @@ QUnit.test('switching sources should clear all remote tracks that are added with
|
||||
|
||||
const tech = new MyTech();
|
||||
|
||||
tech.triggerReady();
|
||||
|
||||
// set the initial source
|
||||
tech.setSource({src: 'foo.mp4', type: 'mp4'});
|
||||
|
||||
// default value for manualCleanup is true
|
||||
tech.addRemoteTextTrack({});
|
||||
this.clock.tick(1);
|
||||
|
||||
assert.equal(warning,
|
||||
'Calling addRemoteTextTrack without explicitly setting the "manualCleanup" parameter to `true` is deprecated and default to `false` in future version of video.js',
|
||||
@@ -226,6 +229,7 @@ QUnit.test('switching sources should clear all remote tracks that are added with
|
||||
|
||||
// should be automatically cleaned up when source changes
|
||||
tech.addRemoteTextTrack({}, false);
|
||||
this.clock.tick(1);
|
||||
|
||||
assert.equal(tech.textTracks().length, 2, 'should have two text tracks at the start');
|
||||
assert.equal(tech.remoteTextTrackEls().length,
|
||||
@@ -238,6 +242,7 @@ QUnit.test('switching sources should clear all remote tracks that are added with
|
||||
|
||||
// change source to force cleanup of auto remote text tracks
|
||||
tech.setSource({src: 'bar.mp4', type: 'mp4'});
|
||||
this.clock.tick(1);
|
||||
|
||||
assert.equal(tech.textTracks().length,
|
||||
1,
|
||||
|
||||
@@ -0,0 +1,322 @@
|
||||
/* eslint-env qunit */
|
||||
import Html5 from '../../../src/js/tech/html5.js';
|
||||
import Component from '../../../src/js/component.js';
|
||||
|
||||
import * as browser from '../../../src/js/utils/browser.js';
|
||||
import TestHelpers from '../test-helpers.js';
|
||||
import document from 'global/document';
|
||||
import sinon from 'sinon';
|
||||
|
||||
QUnit.module('Text Track Display', {
|
||||
beforeEach(assert) {
|
||||
this.clock = sinon.useFakeTimers();
|
||||
},
|
||||
afterEach(assert) {
|
||||
this.clock.restore();
|
||||
}
|
||||
});
|
||||
|
||||
const getMenuItemByLanguage = function(items, language) {
|
||||
for (let i = items.length - 1; i > 0; i--) {
|
||||
const captionMenuItem = items[i];
|
||||
const trackLanguage = captionMenuItem.track.language;
|
||||
|
||||
if (trackLanguage && trackLanguage === language) {
|
||||
return captionMenuItem;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
QUnit.test('if native text tracks are not supported, create a texttrackdisplay', function(assert) {
|
||||
const oldTestVid = Html5.TEST_VID;
|
||||
const oldIsFirefox = browser.IS_FIREFOX;
|
||||
const oldTextTrackDisplay = Component.getComponent('TextTrackDisplay');
|
||||
const tag = document.createElement('video');
|
||||
const track1 = document.createElement('track');
|
||||
const track2 = document.createElement('track');
|
||||
|
||||
track1.kind = 'captions';
|
||||
track1.label = 'en';
|
||||
track1.language = 'English';
|
||||
track1.src = 'en.vtt';
|
||||
tag.appendChild(track1);
|
||||
|
||||
track2.kind = 'captions';
|
||||
track2.label = 'es';
|
||||
track2.language = 'Spanish';
|
||||
track2.src = 'es.vtt';
|
||||
tag.appendChild(track2);
|
||||
|
||||
Html5.TEST_VID = {
|
||||
textTracks: []
|
||||
};
|
||||
|
||||
browser.IS_FIREFOX = true;
|
||||
|
||||
const fakeTTDSpy = sinon.spy();
|
||||
|
||||
class FakeTTD extends Component {
|
||||
constructor() {
|
||||
super();
|
||||
fakeTTDSpy();
|
||||
}
|
||||
}
|
||||
|
||||
Component.registerComponent('TextTrackDisplay', FakeTTD);
|
||||
|
||||
const player = TestHelpers.makePlayer({}, tag);
|
||||
|
||||
assert.strictEqual(fakeTTDSpy.callCount, 1, 'text track display was created');
|
||||
|
||||
Html5.TEST_VID = oldTestVid;
|
||||
browser.IS_FIREFOX = oldIsFirefox;
|
||||
Component.registerComponent('TextTrackDisplay', oldTextTrackDisplay);
|
||||
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
QUnit.test('shows the default caption track first', function(assert) {
|
||||
const player = TestHelpers.makePlayer();
|
||||
const track1 = {
|
||||
kind: 'captions',
|
||||
label: 'English',
|
||||
language: 'en',
|
||||
src: 'en.vtt',
|
||||
default: true
|
||||
};
|
||||
const track2 = {
|
||||
kind: 'captions',
|
||||
label: 'Spanish',
|
||||
language: 'es',
|
||||
src: 'es.vtt'
|
||||
};
|
||||
|
||||
// Add the text tracks
|
||||
const englishTrack = player.addRemoteTextTrack(track1).track;
|
||||
const spanishTrack = player.addRemoteTextTrack(track2).track;
|
||||
|
||||
// Make sure the ready handler runs
|
||||
this.clock.tick(1);
|
||||
|
||||
assert.ok(englishTrack.mode === 'showing', 'English track should be showing');
|
||||
assert.ok(spanishTrack.mode === 'disabled', 'Spanish track should not be showing');
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
if (!Html5.supportsNativeTextTracks()) {
|
||||
QUnit.test('selectedlanguagechange is triggered by a track mode change', function(assert) {
|
||||
const player = TestHelpers.makePlayer();
|
||||
const track1 = {
|
||||
kind: 'captions',
|
||||
label: 'English',
|
||||
language: 'en',
|
||||
src: 'en.vtt'
|
||||
};
|
||||
const spy = sinon.spy();
|
||||
const selectedLanguageHandler = function(event) {
|
||||
spy();
|
||||
};
|
||||
const englishTrack = player.addRemoteTextTrack(track1).track;
|
||||
|
||||
player.textTracks().addEventListener('selectedlanguagechange', selectedLanguageHandler);
|
||||
englishTrack.mode = 'showing';
|
||||
|
||||
assert.strictEqual(spy.callCount, 1, 'selectedlanguagechange event was fired');
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
QUnit.test("if user-selected language is unavailable, don't pick a track to show", function(assert) {
|
||||
// The video has no default language but has ‘English’ captions only
|
||||
const player = TestHelpers.makePlayer();
|
||||
const track1 = {
|
||||
kind: 'captions',
|
||||
label: 'English',
|
||||
language: 'en',
|
||||
src: 'en.vtt'
|
||||
};
|
||||
const captionsButton = player.controlBar.getChild('SubsCapsButton');
|
||||
|
||||
player.src({type: 'video/mp4', src: 'http://google.com'});
|
||||
// manualCleanUp = true by default
|
||||
const englishTrack = player.addRemoteTextTrack(track1).track;
|
||||
|
||||
// Force 'es' as user-selected track
|
||||
player.cache_.selectedLanguage = { language: 'es', kind: 'captions' };
|
||||
|
||||
this.clock.tick(1);
|
||||
player.play();
|
||||
|
||||
assert.ok(!captionsButton.hasClass('vjs-hidden'), 'The captions button is shown');
|
||||
assert.ok(englishTrack.mode === 'disabled', 'English track should be disabled');
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
QUnit.test('the user-selected language takes priority over default language', function(assert) {
|
||||
// The video has ‘English’ captions as default, but has ‘Spanish’ captions also
|
||||
const player = TestHelpers.makePlayer();
|
||||
const track1 = {
|
||||
kind: 'captions',
|
||||
label: 'English',
|
||||
language: 'en',
|
||||
src: 'en.vtt',
|
||||
default: true
|
||||
};
|
||||
const track2 = {
|
||||
kind: 'captions',
|
||||
label: 'Spanish',
|
||||
language: 'es',
|
||||
src: 'es.vtt'
|
||||
};
|
||||
|
||||
player.src({type: 'video/mp4', src: 'http://google.com'});
|
||||
// manualCleanUp = true by default
|
||||
const englishTrack = player.addRemoteTextTrack(track1).track;
|
||||
const spanishTrack = player.addRemoteTextTrack(track2).track;
|
||||
|
||||
// Force 'es' as user-selected track
|
||||
player.cache_.selectedLanguage = { enabled: true, language: 'es', kind: 'captions' };
|
||||
this.clock.tick(1);
|
||||
|
||||
assert.ok(spanishTrack.mode === 'showing', 'Spanish captions should be shown');
|
||||
assert.ok(englishTrack.mode === 'disabled', 'English captions should be hidden');
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
QUnit.test("matching both the selectedLanguage's language and kind takes priority over just matching the language", function(assert) {
|
||||
const player = TestHelpers.makePlayer();
|
||||
const track1 = {
|
||||
kind: 'captions',
|
||||
label: 'English',
|
||||
language: 'en',
|
||||
src: 'en.vtt'
|
||||
};
|
||||
const track2 = {
|
||||
kind: 'subtitles',
|
||||
label: 'English',
|
||||
language: 'en',
|
||||
src: 'en.vtt'
|
||||
};
|
||||
|
||||
player.src({type: 'video/mp4', src: 'http://google.com'});
|
||||
// manualCleanUp = true by default
|
||||
const captionTrack = player.addRemoteTextTrack(track1).track;
|
||||
const subsTrack = player.addRemoteTextTrack(track2).track;
|
||||
|
||||
// Force English captions as user-selected track
|
||||
player.cache_.selectedLanguage = { enabled: true, language: 'en', kind: 'captions' };
|
||||
this.clock.tick(1);
|
||||
|
||||
assert.ok(captionTrack.mode === 'showing', 'Captions track should be preselected');
|
||||
assert.ok(subsTrack.mode === 'disabled', 'Subtitles track should remain disabled');
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
QUnit.test('the user-selected language is used for subsequent source changes', function(assert) {
|
||||
// Start with two captions tracks: English and Spanish
|
||||
const player = TestHelpers.makePlayer();
|
||||
const track1 = {
|
||||
kind: 'captions',
|
||||
label: 'English',
|
||||
language: 'en',
|
||||
src: 'en.vtt'
|
||||
};
|
||||
const track2 = {
|
||||
kind: 'captions',
|
||||
label: 'Spanish',
|
||||
language: 'es',
|
||||
src: 'es.vtt'
|
||||
};
|
||||
const tracks = player.tech_.remoteTextTracks();
|
||||
const captionsButton = player.controlBar.getChild('SubsCapsButton');
|
||||
let esCaptionMenuItem;
|
||||
let enCaptionMenuItem;
|
||||
|
||||
player.src({type: 'video/mp4', src: 'http://google.com'});
|
||||
// manualCleanUp = true by default
|
||||
player.addRemoteTextTrack(track1);
|
||||
player.addRemoteTextTrack(track2);
|
||||
|
||||
// Keep track of menu items
|
||||
esCaptionMenuItem = getMenuItemByLanguage(captionsButton.items, 'es');
|
||||
enCaptionMenuItem = getMenuItemByLanguage(captionsButton.items, 'en');
|
||||
|
||||
// The user chooses Spanish
|
||||
player.play();
|
||||
esCaptionMenuItem.trigger('click');
|
||||
|
||||
// Track mode changes on user-selection
|
||||
assert.ok(esCaptionMenuItem.track.mode === 'showing',
|
||||
'Spanish should be showing after selection');
|
||||
assert.ok(enCaptionMenuItem.track.mode === 'disabled',
|
||||
'English should be disabled after selecting Spanish');
|
||||
assert.deepEqual(player.cache_.selectedLanguage,
|
||||
{ enabled: true, language: 'es', kind: 'captions' });
|
||||
|
||||
// Switch source and remove old tracks
|
||||
player.tech_.src({type: 'video/mp4', src: 'http://example.com'});
|
||||
while (tracks.length > 0) {
|
||||
player.removeRemoteTextTrack(tracks[0]);
|
||||
}
|
||||
// Add tracks for the new source
|
||||
// change the kind of track to subtitles
|
||||
track1.kind = 'subtitles';
|
||||
track2.kind = 'subtitles';
|
||||
const englishTrack = player.addRemoteTextTrack(track1).track;
|
||||
const spanishTrack = player.addRemoteTextTrack(track2).track;
|
||||
|
||||
// Make sure player ready handler runs
|
||||
this.clock.tick(1);
|
||||
|
||||
// Keep track of menu items
|
||||
esCaptionMenuItem = getMenuItemByLanguage(captionsButton.items, 'es');
|
||||
enCaptionMenuItem = getMenuItemByLanguage(captionsButton.items, 'en');
|
||||
|
||||
// The user-selection should have persisted
|
||||
assert.ok(esCaptionMenuItem.track.mode === 'showing',
|
||||
'Spanish should remain showing');
|
||||
assert.ok(enCaptionMenuItem.track.mode === 'disabled',
|
||||
'English should remain disabled');
|
||||
assert.deepEqual(player.cache_.selectedLanguage,
|
||||
{ enabled: true, language: 'es', kind: 'captions' });
|
||||
|
||||
assert.ok(spanishTrack.mode === 'showing', 'Spanish track remains showing');
|
||||
assert.ok(englishTrack.mode === 'disabled', 'English track remains disabled');
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
QUnit.test('the user-selected language is cleared on turning off captions', function(assert) {
|
||||
const player = TestHelpers.makePlayer();
|
||||
const track1 = {
|
||||
kind: 'captions',
|
||||
label: 'English',
|
||||
language: 'en',
|
||||
src: 'en.vtt'
|
||||
};
|
||||
const captionsButton = player.controlBar.getChild('SubsCapsButton');
|
||||
// we know the postition of the OffTextTrackMenuItem
|
||||
const offMenuItem = captionsButton.items[1];
|
||||
|
||||
player.src({type: 'video/mp4', src: 'http://google.com'});
|
||||
// manualCleanUp = true by default
|
||||
const englishTrack = player.addRemoteTextTrack(track1).track;
|
||||
// Keep track of menu items
|
||||
const enCaptionMenuItem = getMenuItemByLanguage(captionsButton.items, 'en');
|
||||
|
||||
// Select English initially
|
||||
player.play();
|
||||
enCaptionMenuItem.trigger('click');
|
||||
|
||||
assert.deepEqual(player.cache_.selectedLanguage,
|
||||
{ enabled: true, language: 'en', kind: 'captions' }, 'English track is selected');
|
||||
assert.ok(englishTrack.mode === 'showing', 'English track should be showing');
|
||||
|
||||
// Select the off button
|
||||
offMenuItem.trigger('click');
|
||||
|
||||
assert.deepEqual(player.cache_.selectedLanguage,
|
||||
{ enabled: false }, 'selectedLanguage is cleared');
|
||||
assert.ok(englishTrack.mode === 'disabled', 'English track is disabled');
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import TextTrack from '../../../src/js/tracks/text-track.js';
|
||||
import TextTrackDisplay from '../../../src/js/tracks/text-track-display.js';
|
||||
import Html5 from '../../../src/js/tech/html5.js';
|
||||
import Tech from '../../../src/js/tech/tech.js';
|
||||
import Component from '../../../src/js/component.js';
|
||||
|
||||
import * as browser from '../../../src/js/utils/browser.js';
|
||||
import TestHelpers from '../test-helpers.js';
|
||||
@@ -221,54 +220,6 @@ QUnit.test('update texttrack buttons on removetrack or addtrack', function(asser
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
QUnit.test('if native text tracks are not supported, create a texttrackdisplay', function(assert) {
|
||||
const oldTestVid = Html5.TEST_VID;
|
||||
const oldIsFirefox = browser.IS_FIREFOX;
|
||||
const oldTextTrackDisplay = Component.getComponent('TextTrackDisplay');
|
||||
const tag = document.createElement('video');
|
||||
const track1 = document.createElement('track');
|
||||
const track2 = document.createElement('track');
|
||||
|
||||
track1.kind = 'captions';
|
||||
track1.label = 'en';
|
||||
track1.language = 'English';
|
||||
track1.src = 'en.vtt';
|
||||
tag.appendChild(track1);
|
||||
|
||||
track2.kind = 'captions';
|
||||
track2.label = 'es';
|
||||
track2.language = 'Spanish';
|
||||
track2.src = 'es.vtt';
|
||||
tag.appendChild(track2);
|
||||
|
||||
Html5.TEST_VID = {
|
||||
textTracks: []
|
||||
};
|
||||
|
||||
browser.IS_FIREFOX = true;
|
||||
|
||||
const fakeTTDSpy = sinon.spy();
|
||||
|
||||
class FakeTTD extends Component {
|
||||
constructor() {
|
||||
super();
|
||||
fakeTTDSpy();
|
||||
}
|
||||
}
|
||||
|
||||
Component.registerComponent('TextTrackDisplay', FakeTTD);
|
||||
|
||||
const player = TestHelpers.makePlayer({}, tag);
|
||||
|
||||
assert.strictEqual(fakeTTDSpy.callCount, 1, 'text track display was created');
|
||||
|
||||
Html5.TEST_VID = oldTestVid;
|
||||
browser.IS_FIREFOX = oldIsFirefox;
|
||||
Component.registerComponent('TextTrackDisplay', oldTextTrackDisplay);
|
||||
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
QUnit.test('emulated tracks are always used, except in safari', function(assert) {
|
||||
const oldTestVid = Html5.TEST_VID;
|
||||
const oldIsAnySafari = browser.IS_ANY_SAFARI;
|
||||
@@ -577,3 +528,55 @@ QUnit.test('removeRemoteTextTrack should be able to take both a track and the re
|
||||
'the track element was removed correctly');
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
if (Html5.isSupported()) {
|
||||
QUnit.test('auto remove tracks should not clean up tracks added while source is being added', function(assert) {
|
||||
const player = TestHelpers.makePlayer({
|
||||
techOrder: ['html5'],
|
||||
html5: {
|
||||
nativeTextTracks: false
|
||||
}
|
||||
});
|
||||
|
||||
const track = {
|
||||
kind: 'kind',
|
||||
src: 'src',
|
||||
language: 'language',
|
||||
label: 'label',
|
||||
default: 'default'
|
||||
};
|
||||
|
||||
player.src({src: 'example.mp4', type: 'video/mp4'});
|
||||
player.addRemoteTextTrack(track, false);
|
||||
|
||||
this.clock.tick(1);
|
||||
assert.equal(player.textTracks().length, 1, 'we have one text track');
|
||||
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
QUnit.test('auto remove tracks added right before a source change will be cleaned up', function(assert) {
|
||||
const player = TestHelpers.makePlayer({
|
||||
techOrder: ['html5'],
|
||||
html5: {
|
||||
nativeTextTracks: false
|
||||
}
|
||||
});
|
||||
|
||||
const track = {
|
||||
kind: 'kind',
|
||||
src: 'src',
|
||||
language: 'language',
|
||||
label: 'label',
|
||||
default: 'default'
|
||||
};
|
||||
|
||||
player.addRemoteTextTrack(track, false);
|
||||
player.src({src: 'example.mp4', type: 'video/mp4'});
|
||||
|
||||
this.clock.tick(1);
|
||||
assert.equal(player.textTracks().length, 0, 'we do not have any tracks left');
|
||||
|
||||
player.dispose();
|
||||
});
|
||||
}
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário