Comparar commits
67 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 4944f85888 | |||
| 5f95e413e3 | |||
| 057588f6c7 | |||
| 7cf2de30ac | |||
| d520d29fd6 | |||
| 3a927523c3 | |||
| ecc95331a7 | |||
| 282bda7e34 | |||
| 3a859f97d0 | |||
| 0d0ff90ca1 | |||
| b4265a8468 | |||
| fac52046f3 | |||
| a17de688f3 | |||
| fdd8550307 | |||
| 83b372c0d4 | |||
| daab267736 | |||
| 8beab2791a | |||
| 2d9d6b9e46 | |||
| 94f22bb995 | |||
| 0b10b69775 | |||
| f37383784d | |||
| eff1cf34db | |||
| a2167a6b95 | |||
| af6beb21c3 | |||
| ebf7718f1b | |||
| 80851ea7ca | |||
| c154518df4 | |||
| 1d2d08584e | |||
| 46d713589b | |||
| 23d1fcd882 | |||
| b56ed61523 | |||
| b90f04fc3b | |||
| 141ecf221b | |||
| c859d8e104 | |||
| f787cbad18 | |||
| 46058ddb0f | |||
| 955185379f | |||
| d58be409a6 | |||
| 13d16c1d76 | |||
| 773b5ab1c1 | |||
| 5178c122a5 | |||
| db0e821f38 | |||
| fa1c6430f4 | |||
| bf2eabf82d | |||
| 2f5a0ca48b | |||
| 2c84f45ff3 | |||
| 6385d1d429 | |||
| 4ae370c1a2 | |||
| 72c44daaf3 | |||
| b3e4e95f9c | |||
| ab82bf0008 | |||
| 1bb40b8d14 | |||
| f2a21d4aa2 | |||
| c15d64adf5 | |||
| a0e9318862 | |||
| 56fc3356dc | |||
| f947ed7791 | |||
| 1ff9f381a2 | |||
| d86d4b2222 | |||
| 052c2ce1a9 | |||
| 4f6cb03add | |||
| 485524882e | |||
| 945711855a | |||
| 272d5eed83 | |||
| 86068a5b45 | |||
| e85c1c0391 | |||
| c89b75699e |
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"presets": ["es2015-loose"],
|
||||
"plugins": ["transform-es3-property-literals", "transform-es3-member-expression-literals", "inline-json"]
|
||||
}
|
||||
@@ -28,5 +28,6 @@ test/coverage/*
|
||||
.sass-cache
|
||||
|
||||
dist/*
|
||||
es5/*
|
||||
|
||||
.idea/
|
||||
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
{
|
||||
"evil" : true,
|
||||
"validthis": true,
|
||||
"node" : true,
|
||||
"debug" : true,
|
||||
"boss" : true,
|
||||
"expr" : true,
|
||||
"eqnull" : true,
|
||||
"quotmark" : "single",
|
||||
"sub" : true,
|
||||
"trailing" : true,
|
||||
"undef" : true,
|
||||
"laxbreak" : true,
|
||||
"esnext" : true,
|
||||
"eqeqeq" : true,
|
||||
"predef" : [
|
||||
"_V_",
|
||||
"goog",
|
||||
"console",
|
||||
|
||||
"require",
|
||||
"define",
|
||||
"module",
|
||||
"exports",
|
||||
"process",
|
||||
|
||||
"q",
|
||||
"asyncTest",
|
||||
"deepEqual",
|
||||
"equal",
|
||||
"expect",
|
||||
"module",
|
||||
"notDeepEqual",
|
||||
"notEqual",
|
||||
"notStrictEqual",
|
||||
"ok",
|
||||
"throws",
|
||||
"QUnit",
|
||||
"raises",
|
||||
"start",
|
||||
"stop",
|
||||
"strictEqual",
|
||||
"test",
|
||||
"throws",
|
||||
"sinon"
|
||||
]
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
# Exclude everything but the contents of the dist directory.
|
||||
**/*
|
||||
!dist/**
|
||||
!es5/**
|
||||
!src/css/**
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 0.12
|
||||
- 4.4
|
||||
before_install:
|
||||
- export CHROME_BIN=chromium-browser
|
||||
- export DISPLAY=:99.0
|
||||
|
||||
@@ -6,6 +6,58 @@ _(none)_
|
||||
|
||||
--------------------
|
||||
|
||||
## 5.12.2 (2016-09-28)
|
||||
* Changes from 5.11.7 on the 5.12 branch
|
||||
|
||||
## 5.12.1 (2016-08-25)
|
||||
* Changes from 5.11.6 on the 5.12 branch
|
||||
|
||||
## 5.13.0 (2016-08-25)
|
||||
* Ignored release
|
||||
|
||||
## 5.12.0 (2016-08-25)
|
||||
* @misteroneill, @BrandonOCasey, and @pagarwal123 updates all the code to pass the linter ([view](https://github.com/videojs/video.js/pull/3459))
|
||||
* @misteroneill added ghooks to run linter on git push ([view](https://github.com/videojs/video.js/pull/3459))
|
||||
* @BrandonOCasey removed unused base-styles.js file ([view](https://github.com/videojs/video.js/pull/3486))
|
||||
* @erikyuzwa, @gkatsev updated CSS build to inlcude the IE8-specific CSS from a separate file instead of it being inside of sass ([view](https://github.com/videojs/video.js/pull/3380)) ([view2](https://github.com/erikyuzwa/video.js/pull/1))
|
||||
* @gkatsev added null checks around navigator.userAgent ([view](https://github.com/videojs/video.js/pull/3502))
|
||||
* greenkeeper updated karma dependencies ([view](https://github.com/videojs/video.js/pull/3523))
|
||||
* @BrandonOCasey updated language docs to link to IANA language registry ([view](https://github.com/videojs/video.js/pull/3493))
|
||||
* @gkatsev removed unused dependencies ([view](https://github.com/videojs/video.js/pull/3516))
|
||||
* @misteroneill enabled and updated videojs-standard and fixed an issue with linting ([view](https://github.com/videojs/video.js/pull/3508))
|
||||
* @misteroneill updated tests to qunit 2.0 ([view](https://github.com/videojs/video.js/pull/3509))
|
||||
* @gkatsev added slack badge to README ([view](https://github.com/videojs/video.js/pull/3527))
|
||||
* @gkatsev reverted back to qunitjs 1.x to unbreak IE8. Added es5-shim to tests ([view](https://github.com/videojs/video.js/pull/3533))
|
||||
* @gkatsev updated build system to open es5 folder for bundles and dist folder other users ([view](https://github.com/videojs/video.js/pull/3445))
|
||||
* greenkeeper updated uglify ([view](https://github.com/videojs/video.js/pull/3547))
|
||||
* greenkeeper updated grunt-concurrent ([view](https://github.com/videojs/video.js/pull/3532))
|
||||
* greenkeeper updated karma-chrome-launcher ([view](https://github.com/videojs/video.js/pull/3553))
|
||||
* @gkatsev added tests for webpack and browserify bundling and node.js requiring ([view](https://github.com/videojs/video.js/pull/3558))
|
||||
* @rlchung fixed tests that weren't disposing players when they finished ([view](https://github.com/videojs/video.js/pull/3524))
|
||||
|
||||
## 5.11.7 (2016-09-28)
|
||||
* @gkatsev checked throwIfWhitespace first in hasElClass ([view](https://github.com/videojs/video.js/pull/3640))
|
||||
* @misteroneill pinned grunt-contrib-uglify to ~0.11 to pin uglify to ~2.6 ([view](https://github.com/videojs/video.js/pull/3634))
|
||||
* @gkatsev set playerId on new el created for movingMediaElementInDOM. Fixes #3283 ([view](https://github.com/videojs/video.js/pull/3648))
|
||||
|
||||
## 5.11.6 (2016-08-25)
|
||||
* @imbcmdth Added exception handling to event dispatcher ([view](https://github.com/videojs/video.js/pull/3580))
|
||||
|
||||
## 5.11.5 (2016-08-25)
|
||||
* @misteroneill fixed wrapping native and emulated MediaErrors ([view](https://github.com/videojs/video.js/pull/3562))
|
||||
* @snyderizer fixed switching between audio tracks. Fixes #3510 ([view](https://github.com/videojs/video.js/pull/3538))
|
||||
* @jbarabander added title attribute to audio button. Fixes #3528 ([view](https://github.com/videojs/video.js/pull/3565))
|
||||
* @misteroneill fixed IE8 media error test failure ([view](https://github.com/videojs/video.js/pull/3568))
|
||||
|
||||
## 5.11.4 (2016-08-16)
|
||||
_(none)_
|
||||
|
||||
## 5.11.3 (2016-08-15)
|
||||
* @vdeshpande fixed control text for fullscreen button ([view](https://github.com/videojs/video.js/pull/3485))
|
||||
* @mister-ben fixed android treating swipe as a tap ([view](https://github.com/videojs/video.js/pull/3514))
|
||||
* @mboles updated duration() method documentation ([view](https://github.com/videojs/video.js/pull/3515))
|
||||
* @mister-ben silenced chrome's play() request was interrupted by pause() error ([view](https://github.com/videojs/video.js/pull/3518))
|
||||
|
||||
## 5.11.2 (2016-08-09)
|
||||
_(none)_
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
require('babel/register');
|
||||
require('babel-register');
|
||||
|
||||
// Need to `require` a separate Grunt file so we can use ES6 syntax via
|
||||
// Babel's require hook.
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
# [Video.js - HTML5 Video Player](http://videojs.com)
|
||||
[](https://travis-ci.org/videojs/video.js)
|
||||
[](https://coveralls.io/github/videojs/video.js?branch=master)
|
||||
[](http://slack.videojs.com)
|
||||
|
||||
|
||||
[](https://nodei.co/npm/video.js/)
|
||||
|
||||
|
||||
+73
-58
@@ -1,4 +1,6 @@
|
||||
import {gruntCustomizer, gruntOptionsMaker} from './options-customizer.js';
|
||||
import chg from 'chg';
|
||||
|
||||
module.exports = function(grunt) {
|
||||
require('time-grunt')(grunt);
|
||||
|
||||
@@ -16,29 +18,10 @@ module.exports = function(grunt) {
|
||||
|
||||
const browserifyGruntDefaults = {
|
||||
browserifyOptions: {
|
||||
debug: true,
|
||||
standalone: 'videojs'
|
||||
},
|
||||
plugin: [
|
||||
['browserify-derequire']
|
||||
],
|
||||
transform: [
|
||||
require('babelify').configure({
|
||||
sourceMapRelative: './',
|
||||
loose: ['all']
|
||||
}),
|
||||
['browserify-versionify', {
|
||||
placeholder: '__VERSION__',
|
||||
version: pkg.version
|
||||
}],
|
||||
['browserify-versionify', {
|
||||
placeholder: '__VERSION_NO_PATCH__',
|
||||
version: version.majorMinor
|
||||
}],
|
||||
['browserify-versionify', {
|
||||
placeholder: '__SWF_VERSION__',
|
||||
version: pkg.dependencies['videojs-swf']
|
||||
}]
|
||||
]
|
||||
};
|
||||
|
||||
@@ -47,7 +30,7 @@ module.exports = function(grunt) {
|
||||
release: {
|
||||
tag_name: 'v'+ version.full,
|
||||
name: version.full,
|
||||
body: require('chg').find(version.full).changesRaw
|
||||
body: chg.find(version.full).changesRaw
|
||||
},
|
||||
},
|
||||
files: {
|
||||
@@ -111,22 +94,11 @@ module.exports = function(grunt) {
|
||||
grunt.initConfig({
|
||||
pkg,
|
||||
clean: {
|
||||
build: ['build/temp/*'],
|
||||
build: ['build/temp/*', 'es5'],
|
||||
dist: ['dist/*']
|
||||
},
|
||||
jshint: {
|
||||
src: {
|
||||
src: ['src/js/**/*.js', 'Gruntfile.js', 'test/unit/**/*.js'],
|
||||
options: {
|
||||
jshintrc: '.jshintrc'
|
||||
}
|
||||
}
|
||||
},
|
||||
uglify: {
|
||||
options: {
|
||||
sourceMap: true,
|
||||
sourceMapIn: 'build/temp/video.js.map',
|
||||
sourceMapRoot: '../../src/js',
|
||||
preserveComments: 'some',
|
||||
mangle: true,
|
||||
compress: {
|
||||
@@ -159,7 +131,11 @@ module.exports = function(grunt) {
|
||||
},
|
||||
skin: {
|
||||
files: ['src/css/**/*'],
|
||||
tasks: ['sass']
|
||||
tasks: ['skin']
|
||||
},
|
||||
babel: {
|
||||
files: ['src/js/**/*.js'],
|
||||
tasks: ['babel:es5']
|
||||
},
|
||||
jshint: {
|
||||
files: ['src/**/*', 'test/unit/**/*.js', 'Gruntfile.js'],
|
||||
@@ -325,11 +301,21 @@ module.exports = function(grunt) {
|
||||
}
|
||||
})
|
||||
},
|
||||
babel: {
|
||||
es5: {
|
||||
files: [{
|
||||
expand: true,
|
||||
cwd: 'src/js/',
|
||||
src: ['**/*.js', '!base-styles.js'],
|
||||
dest: 'es5/'
|
||||
}]
|
||||
}
|
||||
},
|
||||
browserify: {
|
||||
options: browserifyGruntOptions(),
|
||||
build: {
|
||||
files: {
|
||||
'build/temp/video.js': ['src/js/video.js']
|
||||
'build/temp/video.js': ['es5/video.js']
|
||||
}
|
||||
},
|
||||
dist: {
|
||||
@@ -342,7 +328,7 @@ module.exports = function(grunt) {
|
||||
]
|
||||
}),
|
||||
files: {
|
||||
'build/temp/video.js': ['src/js/video.js']
|
||||
'build/temp/video.js': ['es5/video.js']
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -351,14 +337,15 @@ module.exports = function(grunt) {
|
||||
keepAlive: true
|
||||
},
|
||||
files: {
|
||||
'build/temp/video.js': ['src/js/video.js']
|
||||
'build/temp/video.js': ['es5/video.js']
|
||||
}
|
||||
},
|
||||
tests: {
|
||||
options: {
|
||||
browserifyOptions: {
|
||||
debug: true,
|
||||
standalone: false
|
||||
verbose: true,
|
||||
standalone: false,
|
||||
transform: ['babelify']
|
||||
},
|
||||
plugin: [
|
||||
['proxyquireify/plugin']
|
||||
@@ -375,14 +362,6 @@ module.exports = function(grunt) {
|
||||
}
|
||||
}
|
||||
},
|
||||
exorcise: {
|
||||
build: {
|
||||
options: {},
|
||||
files: {
|
||||
'build/temp/video.js.map': ['build/temp/video.js'],
|
||||
}
|
||||
}
|
||||
},
|
||||
coveralls: {
|
||||
options: {
|
||||
// warn instead of failing when coveralls errors
|
||||
@@ -394,25 +373,30 @@ module.exports = function(grunt) {
|
||||
}
|
||||
},
|
||||
concat: {
|
||||
options: {
|
||||
separator: '\n'
|
||||
},
|
||||
novtt: {
|
||||
options: {
|
||||
separator: '\n'
|
||||
},
|
||||
src: ['build/temp/video.js'],
|
||||
dest: 'build/temp/alt/video.novtt.js'
|
||||
},
|
||||
vtt: {
|
||||
options: {
|
||||
separator: '\n',
|
||||
},
|
||||
src: ['build/temp/video.js', 'node_modules/videojs-vtt.js/dist/vtt.js'],
|
||||
dest: 'build/temp/video.js',
|
||||
dest: 'build/temp/video.js'
|
||||
},
|
||||
ie8_addition: {
|
||||
src: ['build/temp/video-js.css', 'src/css/ie8.css'],
|
||||
dest: 'build/temp/video-js.css'
|
||||
}
|
||||
},
|
||||
concurrent: {
|
||||
options: {
|
||||
logConcurrentOutput: true
|
||||
},
|
||||
tests: [
|
||||
'watch:babel',
|
||||
'browserify:tests'
|
||||
],
|
||||
// Run multiple watch tasks in parallel
|
||||
// Needed so watchify can cache intelligently
|
||||
watchAll: [
|
||||
@@ -443,6 +427,32 @@ module.exports = function(grunt) {
|
||||
src: ['build/temp/video.js']
|
||||
}
|
||||
}
|
||||
},
|
||||
shell: {
|
||||
lint: {
|
||||
command: 'npm run lint',
|
||||
options: {
|
||||
preferLocal: true
|
||||
}
|
||||
},
|
||||
noderequire: {
|
||||
command: 'node test/require/node.js',
|
||||
options: {
|
||||
failOnError: true
|
||||
}
|
||||
},
|
||||
browserify: {
|
||||
command: 'browserify test/require/browserify.js -o build/temp/browserify.js',
|
||||
options: {
|
||||
preferLocal: true
|
||||
}
|
||||
},
|
||||
webpack: {
|
||||
command: 'webpack test/require/webpack.js build/temp/webpack.js',
|
||||
options: {
|
||||
preferLocal: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -453,18 +463,18 @@ module.exports = function(grunt) {
|
||||
grunt.loadNpmTasks('gkatsev-grunt-sass');
|
||||
|
||||
const buildDependents = [
|
||||
'shell:lint',
|
||||
'clean:build',
|
||||
|
||||
'jshint',
|
||||
'babel:es5',
|
||||
'browserify:build',
|
||||
'exorcise:build',
|
||||
'concat:novtt',
|
||||
'concat:vtt',
|
||||
'usebanner:novtt',
|
||||
'usebanner:vtt',
|
||||
'uglify',
|
||||
|
||||
'sass',
|
||||
'skin',
|
||||
'version:css',
|
||||
'cssmin',
|
||||
|
||||
@@ -489,13 +499,18 @@ module.exports = function(grunt) {
|
||||
'zip:dist'
|
||||
]);
|
||||
|
||||
grunt.registerTask('skin', ['sass']);
|
||||
grunt.registerTask('skin', ['sass', 'concat:ie8_addition']);
|
||||
|
||||
// Default task - build and test
|
||||
grunt.registerTask('default', ['test']);
|
||||
|
||||
// The test script includes coveralls only when the TRAVIS env var is set.
|
||||
grunt.registerTask('test', ['build', 'karma:defaults'].concat(process.env.TRAVIS && 'coveralls').filter(Boolean));
|
||||
grunt.registerTask('test', [
|
||||
'build',
|
||||
'shell:noderequire',
|
||||
'shell:browserify',
|
||||
'shell:webpack',
|
||||
'karma:defaults'].concat(process.env.TRAVIS && 'coveralls').filter(Boolean));
|
||||
|
||||
// Run while developing
|
||||
grunt.registerTask('dev', ['build', 'connect:dev', 'concurrent:watchSandbox']);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
module.exports = function(grunt) {
|
||||
grunt.registerTask('cdn-links', 'Update the version of CDN links in docs', function(){
|
||||
let doc = grunt.file.read('docs/guides/setup.md');
|
||||
let version = require('../package.json').version;
|
||||
let version = require('../../package.json').version;
|
||||
|
||||
// remove the patch version to point to the latest patch
|
||||
version = version.replace(/(\d+\.\d+)\.\d+/, '$1');
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
module.exports = function(grunt) {
|
||||
grunt.registerTask('check-translations', 'Check that translations are up to date', function(){
|
||||
const source = require('../../lang/en.json');
|
||||
const table = require('markdown-table');
|
||||
let doc = grunt.file.read('docs/translations-needed.md');
|
||||
const tableRegex = /(<!-- START langtable -->)(.|\n)*(<!-- END langtable -->)/;
|
||||
let tableData = [['Language file', 'Missing translations']];
|
||||
|
||||
grunt.file.recurse('lang', (abspath, rootdir, subdir, filename) => {
|
||||
if (filename === 'en.json') {
|
||||
return;
|
||||
}
|
||||
const target = require(`../../${abspath}`);
|
||||
let missing = [];
|
||||
for (const string in source) {
|
||||
if (!target[string]) {
|
||||
grunt.log.writeln(`${filename} missing "${string}"`);
|
||||
missing.push(string);
|
||||
}
|
||||
}
|
||||
if (missing.length > 0) {
|
||||
grunt.log.error(`${filename} is missing ${missing.length} translations.`);
|
||||
tableData.push([`${filename} (missing ${missing.length})`, missing[0]]);
|
||||
for (var i = 1; i < missing.length; i++) {
|
||||
tableData.push(['', missing[i]]);
|
||||
}
|
||||
} else {
|
||||
grunt.log.ok(`${filename} is up to date.`);
|
||||
tableData.push([`${filename} (Complete)`, '']);
|
||||
}
|
||||
});
|
||||
doc = doc.replace(tableRegex, `$1\n` + table(tableData) + `\n$3`);
|
||||
grunt.file.write('docs/translations-needed.md', doc);
|
||||
});
|
||||
};
|
||||
@@ -1,24 +0,0 @@
|
||||
module.exports = function(grunt) {
|
||||
grunt.registerTask('saucelabs', function() {
|
||||
const exec = require('child_process').exec;
|
||||
const done = this.async();
|
||||
|
||||
if (this.args[0] == 'connect') {
|
||||
exec('curl https://gist.githubusercontent.com/santiycr/5139565/raw/sauce_connect_setup.sh | bash',
|
||||
function(error, stdout, stderr) {
|
||||
if (error) {
|
||||
grunt.log.error(error);
|
||||
return done();
|
||||
}
|
||||
|
||||
grunt.verbose.error(stderr.toString());
|
||||
grunt.verbose.writeln(stdout.toString());
|
||||
grunt.task.run(['karma:saucelabs']);
|
||||
done();
|
||||
});
|
||||
} else {
|
||||
grunt.task.run(['karma:saucelabs']);
|
||||
done();
|
||||
}
|
||||
});
|
||||
}
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "video.js",
|
||||
"description": "An HTML5 and Flash video player with a common API and skin for both.",
|
||||
"version": "5.11.2",
|
||||
"version": "5.12.2",
|
||||
"keywords": [
|
||||
"videojs",
|
||||
"html5",
|
||||
|
||||
externo
-7
@@ -585,9 +585,6 @@ body.vjs-full-window {
|
||||
-moz-transition: visibility 1s, opacity 1s;
|
||||
-o-transition: visibility 1s, opacity 1s;
|
||||
transition: visibility 1s, opacity 1s; }
|
||||
@media \0screen {
|
||||
.vjs-has-started.vjs-user-inactive.vjs-playing .vjs-control-bar {
|
||||
visibility: hidden; } }
|
||||
|
||||
.vjs-controls-disabled .vjs-control-bar,
|
||||
.vjs-using-native-controls .vjs-control-bar,
|
||||
@@ -598,10 +595,6 @@ body.vjs-full-window {
|
||||
opacity: 1;
|
||||
visibility: visible; }
|
||||
|
||||
@media \0screen {
|
||||
.vjs-user-inactive.vjs-playing .vjs-control-bar :before {
|
||||
content: ""; } }
|
||||
|
||||
.vjs-has-started.vjs-no-flex .vjs-control-bar {
|
||||
display: table; }
|
||||
|
||||
|
||||
externo
+1
-1
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
externo
+20416
-19897
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
externo
+10
-11
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
externo
-1
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
externo
+7
-1
@@ -30,5 +30,11 @@ videojs.addLanguage("de",{
|
||||
"This modal can be closed by pressing the Escape key or activating the close button.": "Durch Drücken der Esc-Taste bzw. Betätigung der Schaltfläche \"Schließen\" wird dieses modale Fenster geschlossen.",
|
||||
", opens captions settings dialog": ", öffnet Einstellungen für Untertitel",
|
||||
", opens subtitles settings dialog": ", öffnet Einstellungen für Untertitel",
|
||||
", selected": " (ausgewählt)"
|
||||
", selected": ", ausgewählt",
|
||||
"Close Modal Dialog": "Modales Fenster schließen",
|
||||
"Descriptions": "Beschreibungen",
|
||||
"descriptions off": "Beschreibungen aus",
|
||||
"The media is encrypted and we do not have the keys to decrypt it.": "Die Entschlüsselungsschlüssel für den verschlüsselten Medieninhalt sind nicht verfügbar.",
|
||||
", opens descriptions settings dialog": ", öffnet Einstellungen für Beschreibungen",
|
||||
"Audio Track": "Tonspur"
|
||||
});
|
||||
externo
+2
@@ -21,11 +21,13 @@ videojs.addLanguage("en",{
|
||||
"Close Modal Dialog": "Close Modal Dialog",
|
||||
"Descriptions": "Descriptions",
|
||||
"descriptions off": "descriptions off",
|
||||
"Audio Track": "Audio Track",
|
||||
"You aborted the media playback": "You aborted the media playback",
|
||||
"A network error caused the media download to fail part-way.": "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 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.": "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.": "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": "Play Video",
|
||||
"Close": "Close",
|
||||
"Modal Window": "Modal Window",
|
||||
|
||||
externo
+16
-3
@@ -15,12 +15,25 @@ videojs.addLanguage("fr",{
|
||||
"Playback Rate": "Vitesse de lecture",
|
||||
"Subtitles": "Sous-titres",
|
||||
"subtitles off": "Sous-titres désactivés",
|
||||
"Captions": "Sous-titres",
|
||||
"captions off": "Sous-titres désactivés",
|
||||
"Captions": "Sous-titres transcrits",
|
||||
"captions off": "Sous-titres transcrits désactivés",
|
||||
"Chapters": "Chapitres",
|
||||
"Close Modal Dialog": "Fermer la boîte de dialogue modale",
|
||||
"Descriptions": "Descriptions",
|
||||
"descriptions off": "descriptions désactivées",
|
||||
"Audio Track": "Piste audio",
|
||||
"You aborted the media playback": "Vous avez interrompu la lecture de la vidéo.",
|
||||
"A network error caused the media download to fail part-way.": "Une erreur de réseau a interrompu le téléchargement de la vidéo.",
|
||||
"The media could not be loaded, either because the server or network failed or because the format is not supported.": "Cette vidéo n'a pas pu être chargée, soit parce que le serveur ou le réseau a échoué ou parce que le format n'est pas reconnu.",
|
||||
"The media playback was aborted due to a corruption problem or because the media used features your browser did not support.": "La lecture de la vidéo a été interrompue à cause d'un problème de corruption ou parce que la vidéo utilise des fonctionnalités non prises en charge par votre navigateur.",
|
||||
"No compatible source was found for this media.": "Aucune source compatible n'a été trouvée pour cette vidéo."
|
||||
"No compatible source was found for this media.": "Aucune source compatible n'a été trouvée pour cette vidéo.",
|
||||
"Play Video": "Lire la vidéo",
|
||||
"Close": "Fermer",
|
||||
"Modal Window": "Fenêtre modale",
|
||||
"This is a modal window": "Ceci est une fenêtre modale",
|
||||
"This modal can be closed by pressing the Escape key or activating the close button.": "Ce modal peut être fermé en appuyant sur la touche Échap ou activer le bouton de fermeture.",
|
||||
", opens captions settings dialog": ", ouvrir les paramètres des sous-titres transcrits",
|
||||
", opens subtitles settings dialog": ", ouvrir les paramètres des sous-titres",
|
||||
", opens descriptions settings dialog": ", ouvrir les paramètres des descriptions",
|
||||
", selected": ", sélectionné"
|
||||
});
|
||||
externo
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
externo
+31
-7
@@ -585,9 +585,6 @@ body.vjs-full-window {
|
||||
-moz-transition: visibility 1s, opacity 1s;
|
||||
-o-transition: visibility 1s, opacity 1s;
|
||||
transition: visibility 1s, opacity 1s; }
|
||||
@media \0screen {
|
||||
.vjs-has-started.vjs-user-inactive.vjs-playing .vjs-control-bar {
|
||||
visibility: hidden; } }
|
||||
|
||||
.vjs-controls-disabled .vjs-control-bar,
|
||||
.vjs-using-native-controls .vjs-control-bar,
|
||||
@@ -598,10 +595,6 @@ body.vjs-full-window {
|
||||
opacity: 1;
|
||||
visibility: visible; }
|
||||
|
||||
@media \0screen {
|
||||
.vjs-user-inactive.vjs-playing .vjs-control-bar :before {
|
||||
content: ""; } }
|
||||
|
||||
.vjs-has-started.vjs-no-flex .vjs-control-bar {
|
||||
display: table; }
|
||||
|
||||
@@ -1300,3 +1293,34 @@ video::-webkit-media-text-track-display {
|
||||
@media print {
|
||||
.video-js > *:not(.vjs-tech):not(.vjs-poster) {
|
||||
visibility: hidden; } }
|
||||
|
||||
/**
|
||||
// IE 8 hack for media queries which the sass parser can encounter problems with
|
||||
$ie8screen: "\\0screen";
|
||||
|
||||
// original home: css/components/_control-bar.scss
|
||||
// IE8 is flakey with fonts, and you have to change the actual content to force
|
||||
// fonts to show/hide properly.
|
||||
// - "\9" IE8 hack didn't work for this
|
||||
// Found in XP IE8 from http://modern.ie. Does not show up in "IE8 mode" in IE9
|
||||
.vjs-user-inactive.vjs-playing .vjs-control-bar :before {
|
||||
@media #{$ie8screen} { content: ""; }
|
||||
}
|
||||
|
||||
// Video has started playing AND user is inactive
|
||||
.vjs-has-started.vjs-user-inactive.vjs-playing .vjs-control-bar {
|
||||
|
||||
// Make controls hidden in IE8 for now
|
||||
@media #{$ie8screen} {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@media \0screen {
|
||||
.vjs-user-inactive.vjs-playing .vjs-control-bar :before {
|
||||
content: ""; } }
|
||||
|
||||
@media \0screen {
|
||||
.vjs-has-started.vjs-user-inactive.vjs-playing .vjs-control-bar {
|
||||
visibility: hidden; } }
|
||||
|
||||
externo
+1
-1
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
externo
BIN
Arquivo binário não exibido.
externo
+20415
-19896
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
externo
-319
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
externo
+11
-11
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
externo
-1
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
+6
-154
@@ -110,6 +110,10 @@ NOTE: These need to be added after the core Video.js script.
|
||||
Notes:
|
||||
- This will add your language key/values to the Video.js player instances individually. If these values already exist in the global dictionary via the process above, those will be overridden for the player instance in question.
|
||||
|
||||
Updating default translations
|
||||
-----------------------------
|
||||
|
||||
A list of the current translations and any strings that need translation are at [docs/translations-needed.md](../translations-needed.md). After updating the language files in /lang/ running `grunt check-languages` will update that list.
|
||||
|
||||
Setting Default Language in a Video.js Player
|
||||
---------------------------------------------
|
||||
@@ -157,159 +161,7 @@ var details = '<div class="vjs-errors-details">' + player.localize('Technical de
|
||||
|
||||
Language Codes
|
||||
--------------
|
||||
The following is a list of official language codes.
|
||||
A list of languages codes can be found [here](http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry)
|
||||
|
||||
**NOTE:** For supported language translations, please see the [Languages Folder (/lang)](https://github.com/videojs/video.js/tree/master/lang) folder located in the project root.
|
||||
For supported language translations, please see the [Languages Folder (/lang)](https://github.com/videojs/video.js/tree/master/lang) folder located in the project root.
|
||||
|
||||
<table border="0" cellspacing="5" cellpadding="5">
|
||||
<tr>
|
||||
<table>
|
||||
<tr><th>ab<th><td>Abkhazian</td></tr>
|
||||
<tr><th>aa<th><td>Afar</td></tr>
|
||||
<tr><th>af<th><td>Afrikaans</td></tr>
|
||||
<tr><th>sq<th><td>Albanian</td></tr>
|
||||
<tr><th>am<th><td>Amharic</td></tr>
|
||||
<tr><th>ar<th><td>Arabic</td></tr>
|
||||
<tr><th>an<th><td>Aragonese</td></tr>
|
||||
<tr><th>hy<th><td>Armenian</td></tr>
|
||||
<tr><th>as<th><td>Assamese</td></tr>
|
||||
<tr><th>ay<th><td>Aymara</td></tr>
|
||||
<tr><th>az<th><td>Azerbaijani</td></tr>
|
||||
<tr><th>ba<th><td>Bashkir</td></tr>
|
||||
<tr><th>eu<th><td>Basque</td></tr>
|
||||
<tr><th>bn<th><td>Bengali (Bangla)</td></tr>
|
||||
<tr><th>dz<th><td>Bhutani</td></tr>
|
||||
<tr><th>bh<th><td>Bihari</td></tr>
|
||||
<tr><th>bi<th><td>Bislama</td></tr>
|
||||
<tr><th>br<th><td>Breton</td></tr>
|
||||
<tr><th>bg<th><td>Bulgarian</td></tr>
|
||||
<tr><th>my<th><td>Burmese</td></tr>
|
||||
<tr><th>be<th><td>Byelorussian (Belarusian)</td></tr>
|
||||
<tr><th>km<th><td>Cambodian</td></tr>
|
||||
<tr><th>ca<th><td>Catalan</td></tr>
|
||||
<tr><th>zh<th><td>Chinese (Simplified)</td></tr>
|
||||
<tr><th>zh<th><td>Chinese (Traditional)</td></tr>
|
||||
<tr><th>co<th><td>Corsican</td></tr>
|
||||
<tr><th>hr<th><td>Croatian</td></tr>
|
||||
<tr><th>cs<th><td>Czech</td></tr>
|
||||
<tr><th>da<th><td>Danish</td></tr>
|
||||
<tr><th>nl<th><td>Dutch</td></tr>
|
||||
<tr><th>en<th><td>English</td></tr>
|
||||
<tr><th>eo<th><td>Esperanto</td></tr>
|
||||
<tr><th>et<th><td>Estonian</td></tr>
|
||||
<tr><th>fo<th><td>Faeroese</td></tr>
|
||||
<tr><th>fa<th><td>Farsi</td></tr>
|
||||
<tr><th>fj<th><td>Fiji</td></tr>
|
||||
<tr><th>fi<th><td>Finnish</td></tr>
|
||||
<tr><th>fr<th><td>French</td></tr>
|
||||
<tr><th>fy<th><td>Frisian</td></tr>
|
||||
<tr><th>gl<th><td>Galician</td></tr>
|
||||
<tr><th>gd<th><td>Gaelic (Scottish)</td></tr>
|
||||
<tr><th>gv<th><td>Gaelic (Manx)</td></tr>
|
||||
<tr><th>ka<th><td>Georgian</td></tr>
|
||||
<tr><th>de<th><td>German</td></tr>
|
||||
<tr><th>el<th><td>Greek</td></tr>
|
||||
<tr><th>kl<th><td>Greenlandic</td></tr>
|
||||
<tr><th>gn<th><td>Guarani</td></tr>
|
||||
<tr><th>gu<th><td>Gujarati</td></tr>
|
||||
<tr><th>ht<th><td>Haitian Creole</td></tr>
|
||||
<tr><th>ha<th><td>Hausa</td></tr>
|
||||
<tr><th>he<th><td>Hebrew</td></tr>
|
||||
<tr><th>hi<th><td>Hindi</td></tr>
|
||||
<tr><th>hu<th><td>Hungarian</td></tr>
|
||||
<tr><th>is<th><td>Icelandic</td></tr>
|
||||
<tr><th>io<th><td>Ido</td></tr>
|
||||
<tr><th>id<th><td>Indonesian</td></tr>
|
||||
<tr><th>ia<th><td>Interlingua</td></tr>
|
||||
<tr><th>ie<th><td>Interlingue</td></tr>
|
||||
<tr><th>iu<th><td>Inuktitut</td></tr>
|
||||
<tr><th>ik<th><td>Inupiak</td></tr>
|
||||
<tr><th>ga<th><td>Irish</td></tr>
|
||||
<tr><th>it<th><td>Italian</td></tr>
|
||||
<tr><th>ja<th><td>Japanese</td></tr>
|
||||
<tr><th>jv<th><td>Javanese</td></tr>
|
||||
<tr><th>kn<th><td>Kannada</td></tr>
|
||||
<tr><th>ks<th><td>Kashmiri</td></tr>
|
||||
<tr><th>kk<th><td>Kazakh</td></tr>
|
||||
<tr><th>rw<th><td>Kinyarwanda (Ruanda)</td></tr>
|
||||
<tr><th>ky<th><td>Kirghiz</td></tr>
|
||||
<tr><th>rn<th><td>Kirundi (Rundi)</td></tr>
|
||||
<tr><th>ko<th><td>Korean</td></tr>
|
||||
<tr><th>ku<th><td>Kurdish</td></tr>
|
||||
<tr><th>lo<th><td>Laothian</td></tr>
|
||||
<tr><th>la<th><td>Latin</td></tr>
|
||||
<tr><th>lv<th><td>Latvian (Lettish)</td></tr>
|
||||
<tr><th>li<th><td>Limburgish ( Limburger)</td></tr>
|
||||
<tr><th>ln<th><td>Lingala</td></tr>
|
||||
<tr><th>lt<th><td>Lithuanian</td></tr>
|
||||
<tr><th>mk<th><td>Macedonian</td></tr>
|
||||
<tr><th>mg<th><td>Malagasy</td></tr>
|
||||
<tr><th>ms<th><td>Malay</td></tr>
|
||||
<tr><th>ml<th><td>Malayalam</td></tr>
|
||||
<tr><th>mt<th><td>Maltese</td></tr>
|
||||
<tr><th>mi<th><td>Maori</td></tr>
|
||||
<tr><th>mr<th><td>Marathi</td></tr>
|
||||
<tr><th>mo<th><td>Moldavian</td></tr>
|
||||
<tr><th>mn<th><td>Mongolian</td></tr>
|
||||
<tr><th>na<th><td>Nauru</td></tr>
|
||||
<tr><th>ne<th><td>Nepali</td></tr>
|
||||
<tr><th>no<th><td>Norwegian</td></tr>
|
||||
<tr><th>oc<th><td>Occitan</td></tr>
|
||||
<tr><th>or<th><td>Oriya</td></tr>
|
||||
<tr><th>om<th><td>Oromo (Afan, Galla)</td></tr>
|
||||
<tr><th>ps<th><td>Pashto (Pushto)</td></tr>
|
||||
<tr><th>pl<th><td>Polish</td></tr>
|
||||
<tr><th>pt<th><td>Portuguese</td></tr>
|
||||
<tr><th>pa<th><td>Punjabi</td></tr>
|
||||
<tr><th>qu<th><td>Quechua</td></tr>
|
||||
<tr><th>rm<th><td>Rhaeto-Romance</td></tr>
|
||||
<tr><th>ro<th><td>Romanian</td></tr>
|
||||
<tr><th>ru<th><td>Russian</td></tr>
|
||||
<tr><th>sm<th><td>Samoan</td></tr>
|
||||
<tr><th>sg<th><td>Sangro</td></tr>
|
||||
<tr><th>sa<th><td>Sanskrit</td></tr>
|
||||
<tr><th>sr<th><td>Serbian</td></tr>
|
||||
<tr><th>sh<th><td>Serbo-Croatian</td></tr>
|
||||
<tr><th>st<th><td>Sesotho</td></tr>
|
||||
<tr><th>tn<th><td>Setswana</td></tr>
|
||||
<tr><th>sn<th><td>Shona</td></tr>
|
||||
<tr><th>ii<th><td>Sichuan Yi</td></tr>
|
||||
<tr><th>sd<th><td>Sindhi</td></tr>
|
||||
<tr><th>si<th><td>Sinhalese</td></tr>
|
||||
<tr><th>ss<th><td>Siswati</td></tr>
|
||||
<tr><th>sk<th><td>Slovak</td></tr>
|
||||
<tr><th>sl<th><td>Slovenian</td></tr>
|
||||
<tr><th>so<th><td>Somali</td></tr>
|
||||
<tr><th>es<th><td>Spanish</td></tr>
|
||||
<tr><th>su<th><td>Sundanese</td></tr>
|
||||
<tr><th>sw<th><td>Swahili (Kiswahili)</td></tr>
|
||||
<tr><th>sv<th><td>Swedish</td></tr>
|
||||
<tr><th>tl<th><td>Tagalog</td></tr>
|
||||
<tr><th>tg<th><td>Tajik</td></tr>
|
||||
<tr><th>ta<th><td>Tamil</td></tr>
|
||||
<tr><th>tt<th><td>Tatar</td></tr>
|
||||
<tr><th>te<th><td>Telugu</td></tr>
|
||||
<tr><th>th<th><td>Thai</td></tr>
|
||||
<tr><th>bo<th><td>Tibetan</td></tr>
|
||||
<tr><th>ti<th><td>Tigrinya</td></tr>
|
||||
<tr><th>to<th><td>Tonga</td></tr>
|
||||
<tr><th>ts<th><td>Tsonga</td></tr>
|
||||
<tr><th>tr<th><td>Turkish</td></tr>
|
||||
<tr><th>tk<th><td>Turkmen</td></tr>
|
||||
<tr><th>tw<th><td>Twi</td></tr>
|
||||
<tr><th>ug<th><td>Uighur</td></tr>
|
||||
<tr><th>uk<th><td>Ukrainian</td></tr>
|
||||
<tr><th>ur<th><td>Urdu</td></tr>
|
||||
<tr><th>uz<th><td>Uzbek</td></tr>
|
||||
<tr><th>vi<th><td>Vietnamese</td></tr>
|
||||
<tr><th>vo<th><td>Volapük</td></tr>
|
||||
<tr><th>wa<th><td>Wallon</td></tr>
|
||||
<tr><th>cy<th><td>Welsh</td></tr>
|
||||
<tr><th>wo<th><td>Wolof</td></tr>
|
||||
<tr><th>xh<th><td>Xhosa</td></tr>
|
||||
<tr><th>yi<th><td>Yiddish</td></tr>
|
||||
<tr><th>yo<th><td>Yoruba</td></tr>
|
||||
<tr><th>zu<th><td>Zulu</td></tr>
|
||||
</table>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -0,0 +1,363 @@
|
||||
# Translations needed
|
||||
|
||||
The currently available translations are in the lang dir. This table shows the completeness of those translations. Anything not listed does not exist yet, so go ahead and create it by copying `en.json`.
|
||||
|
||||
If you add or update a translation run `grunt check-translations` to update the list and include this modified doc in the pull request.
|
||||
|
||||
## Status of translations
|
||||
|
||||
<!-- START langtable -->
|
||||
| Language file | Missing translations |
|
||||
| ----------------------- | ----------------------------------------------------------------------------------- |
|
||||
| ar.json (missing 6) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | The media is encrypted and we do not have the keys to decrypt it. |
|
||||
| | , opens descriptions settings dialog |
|
||||
| ba.json (missing 14) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | 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. |
|
||||
| | , opens captions settings dialog |
|
||||
| | , opens subtitles settings dialog |
|
||||
| | , opens descriptions settings dialog |
|
||||
| | , selected |
|
||||
| bg.json (missing 14) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | 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. |
|
||||
| | , opens captions settings dialog |
|
||||
| | , opens subtitles settings dialog |
|
||||
| | , opens descriptions settings dialog |
|
||||
| | , selected |
|
||||
| ca.json (missing 14) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | 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. |
|
||||
| | , opens captions settings dialog |
|
||||
| | , opens subtitles settings dialog |
|
||||
| | , opens descriptions settings dialog |
|
||||
| | , selected |
|
||||
| cs.json (missing 14) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | 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. |
|
||||
| | , opens captions settings dialog |
|
||||
| | , opens subtitles settings dialog |
|
||||
| | , opens descriptions settings dialog |
|
||||
| | , selected |
|
||||
| da.json (missing 14) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | 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. |
|
||||
| | , opens captions settings dialog |
|
||||
| | , opens subtitles settings dialog |
|
||||
| | , opens descriptions settings dialog |
|
||||
| | , selected |
|
||||
| de.json (Complete) | |
|
||||
| el.json (missing 7) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | The media is encrypted and we do not have the keys to decrypt it. |
|
||||
| | Play Video |
|
||||
| | , opens descriptions settings dialog |
|
||||
| es.json (missing 14) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | 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. |
|
||||
| | , opens captions settings dialog |
|
||||
| | , opens subtitles settings dialog |
|
||||
| | , opens descriptions settings dialog |
|
||||
| | , selected |
|
||||
| fa.json (missing 14) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | 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. |
|
||||
| | , opens captions settings dialog |
|
||||
| | , opens subtitles settings dialog |
|
||||
| | , opens descriptions settings dialog |
|
||||
| | , selected |
|
||||
| fi.json (missing 14) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | 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. |
|
||||
| | , opens captions settings dialog |
|
||||
| | , opens subtitles settings dialog |
|
||||
| | , opens descriptions settings dialog |
|
||||
| | , selected |
|
||||
| fr.json (missing 1) | The media is encrypted and we do not have the keys to decrypt it. |
|
||||
| hr.json (missing 14) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | 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. |
|
||||
| | , opens captions settings dialog |
|
||||
| | , opens subtitles settings dialog |
|
||||
| | , opens descriptions settings dialog |
|
||||
| | , selected |
|
||||
| hu.json (missing 14) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | 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. |
|
||||
| | , opens captions settings dialog |
|
||||
| | , opens subtitles settings dialog |
|
||||
| | , opens descriptions settings dialog |
|
||||
| | , selected |
|
||||
| it.json (missing 14) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | 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. |
|
||||
| | , opens captions settings dialog |
|
||||
| | , opens subtitles settings dialog |
|
||||
| | , opens descriptions settings dialog |
|
||||
| | , selected |
|
||||
| ja.json (missing 14) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | 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. |
|
||||
| | , opens captions settings dialog |
|
||||
| | , opens subtitles settings dialog |
|
||||
| | , opens descriptions settings dialog |
|
||||
| | , selected |
|
||||
| ko.json (missing 14) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | 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. |
|
||||
| | , opens captions settings dialog |
|
||||
| | , opens subtitles settings dialog |
|
||||
| | , opens descriptions settings dialog |
|
||||
| | , selected |
|
||||
| nb.json (missing 14) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | 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. |
|
||||
| | , opens captions settings dialog |
|
||||
| | , opens subtitles settings dialog |
|
||||
| | , opens descriptions settings dialog |
|
||||
| | , selected |
|
||||
| nl.json (missing 3) | Close Modal Dialog |
|
||||
| | Audio Track |
|
||||
| | The media is encrypted and we do not have the keys to decrypt it. |
|
||||
| nn.json (missing 14) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | 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. |
|
||||
| | , opens captions settings dialog |
|
||||
| | , opens subtitles settings dialog |
|
||||
| | , opens descriptions settings dialog |
|
||||
| | , selected |
|
||||
| pl.json (missing 7) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | The media is encrypted and we do not have the keys to decrypt it. |
|
||||
| | Play Video |
|
||||
| | , opens descriptions settings dialog |
|
||||
| pt-BR.json (missing 14) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | 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. |
|
||||
| | , opens captions settings dialog |
|
||||
| | , opens subtitles settings dialog |
|
||||
| | , opens descriptions settings dialog |
|
||||
| | , selected |
|
||||
| ru.json (missing 14) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | 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. |
|
||||
| | , opens captions settings dialog |
|
||||
| | , opens subtitles settings dialog |
|
||||
| | , opens descriptions settings dialog |
|
||||
| | , selected |
|
||||
| sr.json (missing 14) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | 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. |
|
||||
| | , opens captions settings dialog |
|
||||
| | , opens subtitles settings dialog |
|
||||
| | , opens descriptions settings dialog |
|
||||
| | , selected |
|
||||
| sv.json (missing 14) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | 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. |
|
||||
| | , opens captions settings dialog |
|
||||
| | , opens subtitles settings dialog |
|
||||
| | , opens descriptions settings dialog |
|
||||
| | , selected |
|
||||
| tr.json (missing 6) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | The media is encrypted and we do not have the keys to decrypt it. |
|
||||
| | , opens descriptions settings dialog |
|
||||
| uk.json (missing 14) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | 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. |
|
||||
| | , opens captions settings dialog |
|
||||
| | , opens subtitles settings dialog |
|
||||
| | , opens descriptions settings dialog |
|
||||
| | , selected |
|
||||
| vi.json (missing 14) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | 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. |
|
||||
| | , opens captions settings dialog |
|
||||
| | , opens subtitles settings dialog |
|
||||
| | , opens descriptions settings dialog |
|
||||
| | , selected |
|
||||
| zh-CN.json (missing 13) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | 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. |
|
||||
| | , opens captions settings dialog |
|
||||
| | , opens subtitles settings dialog |
|
||||
| | , opens descriptions settings dialog |
|
||||
| | , selected |
|
||||
| zh-TW.json (missing 13) | Close Modal Dialog |
|
||||
| | Descriptions |
|
||||
| | descriptions off |
|
||||
| | Audio Track |
|
||||
| | 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. |
|
||||
| | , opens captions settings dialog |
|
||||
| | , opens subtitles settings dialog |
|
||||
| | , opens descriptions settings dialog |
|
||||
| | , selected |
|
||||
<!-- END langtable -->
|
||||
+7
-1
@@ -30,5 +30,11 @@
|
||||
"This modal can be closed by pressing the Escape key or activating the close button.": "Durch Drücken der Esc-Taste bzw. Betätigung der Schaltfläche \"Schließen\" wird dieses modale Fenster geschlossen.",
|
||||
", opens captions settings dialog": ", öffnet Einstellungen für Untertitel",
|
||||
", opens subtitles settings dialog": ", öffnet Einstellungen für Untertitel",
|
||||
", selected": " (ausgewählt)"
|
||||
", selected": ", ausgewählt",
|
||||
"Close Modal Dialog": "Modales Fenster schließen",
|
||||
"Descriptions": "Beschreibungen",
|
||||
"descriptions off": "Beschreibungen aus",
|
||||
"The media is encrypted and we do not have the keys to decrypt it.": "Die Entschlüsselungsschlüssel für den verschlüsselten Medieninhalt sind nicht verfügbar.",
|
||||
", opens descriptions settings dialog": ", öffnet Einstellungen für Beschreibungen",
|
||||
"Audio Track": "Tonspur"
|
||||
}
|
||||
|
||||
@@ -21,11 +21,13 @@
|
||||
"Close Modal Dialog": "Close Modal Dialog",
|
||||
"Descriptions": "Descriptions",
|
||||
"descriptions off": "descriptions off",
|
||||
"Audio Track": "Audio Track",
|
||||
"You aborted the media playback": "You aborted the media playback",
|
||||
"A network error caused the media download to fail part-way.": "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 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.": "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.": "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": "Play Video",
|
||||
"Close": "Close",
|
||||
"Modal Window": "Modal Window",
|
||||
|
||||
+16
-3
@@ -15,12 +15,25 @@
|
||||
"Playback Rate": "Vitesse de lecture",
|
||||
"Subtitles": "Sous-titres",
|
||||
"subtitles off": "Sous-titres désactivés",
|
||||
"Captions": "Sous-titres",
|
||||
"captions off": "Sous-titres désactivés",
|
||||
"Captions": "Sous-titres transcrits",
|
||||
"captions off": "Sous-titres transcrits désactivés",
|
||||
"Chapters": "Chapitres",
|
||||
"Close Modal Dialog": "Fermer la boîte de dialogue modale",
|
||||
"Descriptions": "Descriptions",
|
||||
"descriptions off": "descriptions désactivées",
|
||||
"Audio Track": "Piste audio",
|
||||
"You aborted the media playback": "Vous avez interrompu la lecture de la vidéo.",
|
||||
"A network error caused the media download to fail part-way.": "Une erreur de réseau a interrompu le téléchargement de la vidéo.",
|
||||
"The media could not be loaded, either because the server or network failed or because the format is not supported.": "Cette vidéo n'a pas pu être chargée, soit parce que le serveur ou le réseau a échoué ou parce que le format n'est pas reconnu.",
|
||||
"The media playback was aborted due to a corruption problem or because the media used features your browser did not support.": "La lecture de la vidéo a été interrompue à cause d'un problème de corruption ou parce que la vidéo utilise des fonctionnalités non prises en charge par votre navigateur.",
|
||||
"No compatible source was found for this media.": "Aucune source compatible n'a été trouvée pour cette vidéo."
|
||||
"No compatible source was found for this media.": "Aucune source compatible n'a été trouvée pour cette vidéo.",
|
||||
"Play Video": "Lire la vidéo",
|
||||
"Close": "Fermer",
|
||||
"Modal Window": "Fenêtre modale",
|
||||
"This is a modal window": "Ceci est une fenêtre modale",
|
||||
"This modal can be closed by pressing the Escape key or activating the close button.": "Ce modal peut être fermé en appuyant sur la touche Échap ou activer le bouton de fermeture.",
|
||||
", opens captions settings dialog": ", ouvrir les paramètres des sous-titres transcrits",
|
||||
", opens subtitles settings dialog": ", ouvrir les paramètres des sous-titres",
|
||||
", opens descriptions settings dialog": ", ouvrir les paramètres des descriptions",
|
||||
", selected": ", sélectionné"
|
||||
}
|
||||
|
||||
+52
-30
@@ -1,7 +1,9 @@
|
||||
{
|
||||
"name": "video.js",
|
||||
"description": "An HTML5 and Flash video player with a common API and skin for both.",
|
||||
"version": "5.11.2",
|
||||
"version": "5.12.2",
|
||||
"main": "./es5/video.js",
|
||||
"style": "./dist/video-js.css",
|
||||
"copyright": "Copyright Brightcove, Inc. <https://www.brightcove.com/>",
|
||||
"license": "Apache-2.0",
|
||||
"keywords": [
|
||||
@@ -14,15 +16,19 @@
|
||||
"homepage": "http://videojs.com",
|
||||
"author": "Steve Heffernan",
|
||||
"scripts": {
|
||||
"build": "grunt dist",
|
||||
"change": "grunt chg-add",
|
||||
"clean": "grunt clean",
|
||||
"lint": "vjsstandard",
|
||||
"start": "grunt watchAll",
|
||||
"test": "grunt test"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/videojs/video.js.git"
|
||||
},
|
||||
"main": "./dist/video.js",
|
||||
"style": "./dist/video-js.css",
|
||||
"dependencies": {
|
||||
"babel-runtime": "^6.9.2",
|
||||
"global": "4.3.0",
|
||||
"lodash-compat": "3.10.2",
|
||||
"object.assign": "4.0.3",
|
||||
@@ -35,69 +41,85 @@
|
||||
"xhr": "2.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel": "^5.2.2",
|
||||
"babelify": "^6.0.1",
|
||||
"babel-cli": "^6.11.4",
|
||||
"babel-plugin-inline-json": "^1.1.1",
|
||||
"babel-plugin-transform-es3-member-expression-literals": "^6.8.0",
|
||||
"babel-plugin-transform-es3-property-literals": "^6.8.0",
|
||||
"babel-plugin-transform-runtime": "^6.9.0",
|
||||
"babel-preset-es2015": "^6.14.0",
|
||||
"babel-preset-es2015-loose": "^7.0.0",
|
||||
"babel-register": "^6.9.0",
|
||||
"babelify": "^7.3.0",
|
||||
"blanket": "^1.1.6",
|
||||
"browserify-derequire": "^0.9.4",
|
||||
"browserify-istanbul": "^0.2.1",
|
||||
"browserify-versionify": "^1.0.4",
|
||||
"chg": "^0.3.2",
|
||||
"css": "^2.2.0",
|
||||
"es5-shim": "^4.1.3",
|
||||
"es6-shim": "^0.35.1",
|
||||
"ghooks": "^1.3.2",
|
||||
"gkatsev-grunt-sass": "^1.1.1",
|
||||
"grunt": "^0.4.4",
|
||||
"grunt-aws-s3": "^0.12.1",
|
||||
"grunt-babel": "^6.0.0",
|
||||
"grunt-banner": "^0.4.0",
|
||||
"grunt-browserify": "3.5.1",
|
||||
"grunt-cli": "~0.1.13",
|
||||
"grunt-concurrent": "^1.0.0",
|
||||
"grunt-concurrent": "^2.3.1",
|
||||
"grunt-contrib-clean": "~0.4.0a",
|
||||
"grunt-contrib-concat": "^0.5.1",
|
||||
"grunt-contrib-connect": "~0.7.1",
|
||||
"grunt-contrib-copy": "^0.8.0",
|
||||
"grunt-contrib-cssmin": "~0.6.0",
|
||||
"grunt-contrib-jshint": "~0.11.3",
|
||||
"grunt-contrib-less": "~0.6.4",
|
||||
"grunt-contrib-uglify": "^0.8.0",
|
||||
"grunt-contrib-uglify": "~0.11.0",
|
||||
"grunt-contrib-watch": "~0.1.4",
|
||||
"grunt-coveralls": "^1.0.0",
|
||||
"grunt-exorcise": "^1.0.1",
|
||||
"grunt-fastly": "^0.1.3",
|
||||
"grunt-github-releaser": "^0.1.17",
|
||||
"grunt-karma": "^0.8.3",
|
||||
"grunt-karma": "^2.0.0",
|
||||
"grunt-shell": "^1.3.0",
|
||||
"grunt-version": "~0.3.0",
|
||||
"grunt-videojs-languages": "0.0.4",
|
||||
"grunt-zip": "0.10.2",
|
||||
"karma": "^0.12.36",
|
||||
"karma-browserify": "^4.0.0",
|
||||
"karma-browserstack-launcher": "^0.1.4",
|
||||
"karma-chrome-launcher": "^0.1.3",
|
||||
"karma-coverage": "^0.4.0",
|
||||
"karma-detect-browsers": "^2.0.2",
|
||||
"karma-firefox-launcher": "^0.1.3",
|
||||
"karma-ie-launcher": "^0.1.5",
|
||||
"karma-opera-launcher": "~0.1.0",
|
||||
"karma-qunit": "^0.1.2",
|
||||
"karma-safari-launcher": "^0.1.1",
|
||||
"karma-sinon": "^1.0.3",
|
||||
"karma": "^1.2.0",
|
||||
"karma-browserify": "^5.1.0",
|
||||
"karma-browserstack-launcher": "^1.0.1",
|
||||
"karma-chrome-launcher": "^2.0.0",
|
||||
"karma-coverage": "^1.1.1",
|
||||
"karma-detect-browsers": "^2.1.0",
|
||||
"karma-firefox-launcher": "^1.0.0",
|
||||
"karma-ie-launcher": "^1.0.0",
|
||||
"karma-opera-launcher": "^1.0.0",
|
||||
"karma-qunit": "^1.2.0",
|
||||
"karma-safari-launcher": "^1.0.0",
|
||||
"karma-sinon": "^1.0.5",
|
||||
"load-grunt-tasks": "^3.1.0",
|
||||
"markdown-table": "^1.0.0",
|
||||
"proxyquireify": "^3.0.0",
|
||||
"qunitjs": "^1.18.0",
|
||||
"qunitjs": "^1.23.1",
|
||||
"sinon": "^1.16.1",
|
||||
"time-grunt": "^1.1.1",
|
||||
"uglify-js": "~2.3.6",
|
||||
"videojs-doc-generator": "0.0.1"
|
||||
"uglify-js": "~2.7.3",
|
||||
"videojs-doc-generator": "0.0.1",
|
||||
"videojs-standard": "^5.2.0",
|
||||
"webpack": "^1.13.2"
|
||||
},
|
||||
"standard": {
|
||||
"vjsstandard": {
|
||||
"ignore": [
|
||||
"**/Gruntfile.js",
|
||||
"**/es5/**",
|
||||
"**/build/**",
|
||||
"**/dist/**",
|
||||
"**/docs/**",
|
||||
"**/lang/**",
|
||||
"**/sandbox/**",
|
||||
"**/test/**"
|
||||
"**/test/api/**",
|
||||
"**/test/coverage/**",
|
||||
"**/test/karma.conf.js"
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"ghooks": {
|
||||
"pre-push": "npm run lint -- --errors"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
-webkit-user-select: $string;
|
||||
-moz-user-select: $string;
|
||||
-ms-user-select: $string;
|
||||
user-select: $string
|
||||
user-select: $string;
|
||||
}
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow
|
||||
|
||||
@@ -20,9 +20,6 @@
|
||||
@include transition($trans);
|
||||
}
|
||||
|
||||
// IE 8 hack for media queries
|
||||
$ie8screen: "\\0screen";
|
||||
|
||||
// Video has started playing AND user is inactive
|
||||
.vjs-has-started.vjs-user-inactive.vjs-playing .vjs-control-bar {
|
||||
// Remain visible for screen reader and keyboard users
|
||||
@@ -32,10 +29,6 @@ $ie8screen: "\\0screen";
|
||||
$trans: visibility 1.0s, opacity 1.0s;
|
||||
@include transition($trans);
|
||||
|
||||
// Make controls hidden in IE8 for now
|
||||
@media #{$ie8screen} {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.vjs-controls-disabled .vjs-control-bar,
|
||||
@@ -51,15 +44,6 @@ $ie8screen: "\\0screen";
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
|
||||
// IE8 is flakey with fonts, and you have to change the actual content to force
|
||||
// fonts to show/hide properly.
|
||||
// - "\9" IE8 hack didn't work for this
|
||||
// Found in XP IE8 from http://modern.ie. Does not show up in "IE8 mode" in IE9
|
||||
.vjs-user-inactive.vjs-playing .vjs-control-bar :before {
|
||||
@media #{$ie8screen} { content: ""; }
|
||||
}
|
||||
|
||||
// IE 8 + 9 Support
|
||||
.vjs-has-started.vjs-no-flex .vjs-control-bar {
|
||||
display: table;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
.video-js .vjs-fullscreen-control {
|
||||
cursor: pointer;
|
||||
@include flex(none);
|
||||
}
|
||||
.video-js .vjs-fullscreen-control {
|
||||
@extend .vjs-icon-fullscreen-enter;
|
||||
}
|
||||
// Switch to the exit icon when the player is in fullscreen
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
.video-js .vjs-play-control {
|
||||
cursor: pointer;
|
||||
@include flex(none);
|
||||
}
|
||||
.video-js .vjs-play-control {
|
||||
@extend .vjs-icon-play;
|
||||
}
|
||||
.video-js .vjs-play-control.vjs-playing {
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
// We need an increased hit area on hover
|
||||
.video-js .vjs-progress-control:hover .vjs-progress-holder {
|
||||
font-size: 1.666666666666666666em
|
||||
font-size: 1.666666666666666666em;
|
||||
}
|
||||
|
||||
/* If we let the font size grow as much as everything else, the current time tooltip ends up
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
|
||||
.vjs-menu .vjs-menu-content {
|
||||
display: block;
|
||||
padding: 0; margin: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: auto;
|
||||
font-family: $text-font-family;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
// IE 8 hack for media queries which the sass parser can encounter problems with
|
||||
$ie8screen: "\\0screen";
|
||||
|
||||
// original home: css/components/_control-bar.scss
|
||||
// IE8 is flakey with fonts, and you have to change the actual content to force
|
||||
// fonts to show/hide properly.
|
||||
// - "\9" IE8 hack didn't work for this
|
||||
// Found in XP IE8 from http://modern.ie. Does not show up in "IE8 mode" in IE9
|
||||
.vjs-user-inactive.vjs-playing .vjs-control-bar :before {
|
||||
@media #{$ie8screen} { content: ""; }
|
||||
}
|
||||
|
||||
// Video has started playing AND user is inactive
|
||||
.vjs-has-started.vjs-user-inactive.vjs-playing .vjs-control-bar {
|
||||
|
||||
// Make controls hidden in IE8 for now
|
||||
@media #{$ie8screen} {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@media \0screen {
|
||||
.vjs-user-inactive.vjs-playing .vjs-control-bar :before {
|
||||
content: ""; } }
|
||||
|
||||
@media \0screen {
|
||||
.vjs-has-started.vjs-user-inactive.vjs-playing .vjs-control-bar {
|
||||
visibility: hidden; } }
|
||||
@@ -1,18 +0,0 @@
|
||||
/**
|
||||
* @file base-styles.js
|
||||
*
|
||||
* This code injects the required base styles in the head of the document.
|
||||
*/
|
||||
import window from 'global/window';
|
||||
import document from 'global/document';
|
||||
|
||||
if (window.VIDEOJS_NO_BASE_THEME) return;
|
||||
|
||||
const styles = '{{GENERATED_STYLES}}';
|
||||
|
||||
if (styles === '{{GENERATED'+'_STYLES}}');
|
||||
|
||||
const styleNode = document.createElement('style');
|
||||
styleNode.innerHTML = styles;
|
||||
|
||||
document.head.insertBefore(styleNode, document.head.firstChild);
|
||||
+16
-12
@@ -3,10 +3,7 @@
|
||||
*/
|
||||
import ClickableComponent from './clickable-component.js';
|
||||
import Component from './component';
|
||||
import * as Events from './utils/events.js';
|
||||
import * as Fn from './utils/fn.js';
|
||||
import log from './utils/log.js';
|
||||
import document from 'global/document';
|
||||
import assign from 'object.assign';
|
||||
|
||||
/**
|
||||
@@ -32,7 +29,7 @@ class Button extends ClickableComponent {
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl(tag='button', props={}, attributes={}) {
|
||||
createEl(tag = 'button', props = {}, attributes = {}) {
|
||||
props = assign({
|
||||
className: this.buildCSSClass()
|
||||
}, props);
|
||||
@@ -53,11 +50,15 @@ class Button extends ClickableComponent {
|
||||
|
||||
// Add attributes for button element
|
||||
attributes = assign({
|
||||
type: 'button', // Necessary since the default button type is "submit"
|
||||
'aria-live': 'polite' // let the screen reader user know that the text of the button may change
|
||||
|
||||
// Necessary since the default button type is "submit"
|
||||
'type': 'button',
|
||||
|
||||
// let the screen reader user know that the text of the button may change
|
||||
'aria-live': 'polite'
|
||||
}, attributes);
|
||||
|
||||
let el = Component.prototype.createEl.call(this, tag, props, attributes);
|
||||
const el = Component.prototype.createEl.call(this, tag, props, attributes);
|
||||
|
||||
this.createControlTextEl(el);
|
||||
|
||||
@@ -73,8 +74,9 @@ class Button extends ClickableComponent {
|
||||
* @deprecated
|
||||
* @method addChild
|
||||
*/
|
||||
addChild(child, options={}) {
|
||||
let className = this.constructor.name;
|
||||
addChild(child, options = {}) {
|
||||
const className = this.constructor.name;
|
||||
|
||||
log.warn(`Adding an actionable (user controllable) child to a Button (${className}) is not supported; use a ClickableComponent instead.`);
|
||||
|
||||
// Avoid the error message generated by ClickableComponent's addChild method
|
||||
@@ -87,13 +89,15 @@ class Button extends ClickableComponent {
|
||||
* @method handleKeyPress
|
||||
*/
|
||||
handleKeyPress(event) {
|
||||
|
||||
// Ignore Space (32) or Enter (13) key operation, which is handled by the browser for a button.
|
||||
if (event.which === 32 || event.which === 13) {
|
||||
} else {
|
||||
super.handleKeyPress(event); // Pass keypress handling up for unsupported keys
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Pass keypress handling up for unsupported keys
|
||||
super.handleKeyPress(event);
|
||||
}
|
||||
}
|
||||
|
||||
Component.registerComponent('Button', Button);
|
||||
|
||||
@@ -39,7 +39,7 @@ class ClickableComponent extends Component {
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl(tag='div', props={}, attributes={}) {
|
||||
createEl(tag = 'div', props = {}, attributes = {}) {
|
||||
props = assign({
|
||||
className: this.buildCSSClass(),
|
||||
tabIndex: 0
|
||||
@@ -51,11 +51,13 @@ class ClickableComponent extends Component {
|
||||
|
||||
// Add ARIA attributes for clickable element which is not a native HTML button
|
||||
attributes = assign({
|
||||
role: 'button',
|
||||
'aria-live': 'polite' // let the screen reader user know that the text of the element may change
|
||||
'role': 'button',
|
||||
|
||||
// let the screen reader user know that the text of the element may change
|
||||
'aria-live': 'polite'
|
||||
}, attributes);
|
||||
|
||||
let el = super.createEl(tag, props, attributes);
|
||||
const el = super.createEl(tag, props, attributes);
|
||||
|
||||
this.createControlTextEl(el);
|
||||
|
||||
@@ -91,9 +93,11 @@ class ClickableComponent extends Component {
|
||||
* @return {String}
|
||||
* @method controlText
|
||||
*/
|
||||
controlText(text, el=this.el()) {
|
||||
if (!text) return this.controlText_ || 'Need Text';
|
||||
|
||||
controlText(text, el = this.el()) {
|
||||
if (!text) {
|
||||
return this.controlText_ || 'Need Text';
|
||||
}
|
||||
|
||||
const localizedText = this.localize(text);
|
||||
|
||||
this.controlText_ = text;
|
||||
@@ -121,14 +125,14 @@ class ClickableComponent extends Component {
|
||||
* @return {Component} The child component (created by this process if a string was used)
|
||||
* @method addChild
|
||||
*/
|
||||
addChild(child, options={}) {
|
||||
addChild(child, options = {}) {
|
||||
// TODO: Fix adding an actionable child to a ClickableComponent; currently
|
||||
// it will cause issues with assistive technology (e.g. screen readers)
|
||||
// which support ARIA, since an element with role="button" cannot have
|
||||
// actionable child elements.
|
||||
|
||||
//let className = this.constructor.name;
|
||||
//log.warn(`Adding a child to a ClickableComponent (${className}) can cause issues with assistive technology which supports ARIA, since an element with role="button" cannot have actionable child elements.`);
|
||||
// let className = this.constructor.name;
|
||||
// log.warn(`Adding a child to a ClickableComponent (${className}) can cause issues with assistive technology which supports ARIA, since an element with role="button" cannot have actionable child elements.`);
|
||||
|
||||
return super.addChild(child, options);
|
||||
}
|
||||
@@ -179,12 +183,15 @@ class ClickableComponent extends Component {
|
||||
* @method handleKeyPress
|
||||
*/
|
||||
handleKeyPress(event) {
|
||||
|
||||
// Support Space (32) or Enter (13) key operation to fire a click event
|
||||
if (event.which === 32 || event.which === 13) {
|
||||
event.preventDefault();
|
||||
this.handleClick(event);
|
||||
} else if (super.handleKeyPress) {
|
||||
super.handleKeyPress(event); // Pass keypress handling up for unsupported keys
|
||||
|
||||
// Pass keypress handling up for unsupported keys
|
||||
super.handleKeyPress(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+46
-41
@@ -3,7 +3,6 @@
|
||||
*
|
||||
* Player Component - Base class for all UI objects
|
||||
*/
|
||||
|
||||
import window from 'global/window';
|
||||
import * as Dom from './utils/dom.js';
|
||||
import * as Fn from './utils/fn.js';
|
||||
@@ -11,10 +10,8 @@ import * as Guid from './utils/guid.js';
|
||||
import * as Events from './utils/events.js';
|
||||
import log from './utils/log.js';
|
||||
import toTitleCase from './utils/to-title-case.js';
|
||||
import assign from 'object.assign';
|
||||
import mergeOptions from './utils/merge-options.js';
|
||||
|
||||
|
||||
/**
|
||||
* Base UI Component class
|
||||
* Components are embeddable UI objects that are represented by both a
|
||||
@@ -32,7 +29,7 @@ import mergeOptions from './utils/merge-options.js';
|
||||
* ```
|
||||
* Components are also event targets.
|
||||
* ```js
|
||||
* button.on('click', function(){
|
||||
* button.on('click', function() {
|
||||
* console.log('Button Clicked!');
|
||||
* });
|
||||
* button.trigger('customevent');
|
||||
@@ -66,7 +63,7 @@ class Component {
|
||||
// If there was no ID from the options, generate one
|
||||
if (!this.id_) {
|
||||
// Don't require the player ID function in the case of mock players
|
||||
let id = player && player.id && player.id() || 'no_player';
|
||||
const id = player && player.id && player.id() || 'no_player';
|
||||
|
||||
this.id_ = `${id}_component_${Guid.newGUID()}`;
|
||||
}
|
||||
@@ -219,21 +216,21 @@ class Component {
|
||||
}
|
||||
|
||||
localize(string) {
|
||||
let code = this.player_.language && this.player_.language();
|
||||
let languages = this.player_.languages && this.player_.languages();
|
||||
const code = this.player_.language && this.player_.language();
|
||||
const languages = this.player_.languages && this.player_.languages();
|
||||
|
||||
if (!code || !languages) {
|
||||
return string;
|
||||
}
|
||||
|
||||
let language = languages[code];
|
||||
const language = languages[code];
|
||||
|
||||
if (language && language[string]) {
|
||||
return language[string];
|
||||
}
|
||||
|
||||
let primaryCode = code.split('-')[0];
|
||||
let primaryLang = languages[primaryCode];
|
||||
const primaryCode = code.split('-')[0];
|
||||
const primaryLang = languages[primaryCode];
|
||||
|
||||
if (primaryLang && primaryLang[string]) {
|
||||
return primaryLang[string];
|
||||
@@ -340,7 +337,7 @@ class Component {
|
||||
* @return {Component} The child component (created by this process if a string was used)
|
||||
* @method addChild
|
||||
*/
|
||||
addChild(child, options={}, index=this.children_.length) {
|
||||
addChild(child, options = {}, index = this.children_.length) {
|
||||
let component;
|
||||
let componentName;
|
||||
|
||||
@@ -361,14 +358,14 @@ class Component {
|
||||
|
||||
// If no componentClass in options, assume componentClass is the name lowercased
|
||||
// (e.g. playButton)
|
||||
let componentClassName = options.componentClass || toTitleCase(componentName);
|
||||
const componentClassName = options.componentClass || toTitleCase(componentName);
|
||||
|
||||
// Set name through options
|
||||
options.name = componentName;
|
||||
|
||||
// Create a new object & element for this controls set
|
||||
// If there's no .player_, this is a player
|
||||
let ComponentClass = Component.getComponent(componentClassName);
|
||||
const ComponentClass = Component.getComponent(componentClassName);
|
||||
|
||||
if (!ComponentClass) {
|
||||
throw new Error(`Component ${componentClassName} does not exist`);
|
||||
@@ -406,8 +403,9 @@ class Component {
|
||||
// Add the UI object's element to the container div (box)
|
||||
// Having an element is not required
|
||||
if (typeof component.el === 'function' && component.el()) {
|
||||
let childNodes = this.contentEl().children;
|
||||
let refNode = childNodes[index] || null;
|
||||
const childNodes = this.contentEl().children;
|
||||
const refNode = childNodes[index] || null;
|
||||
|
||||
this.contentEl().insertBefore(component.el(), refNode);
|
||||
}
|
||||
|
||||
@@ -448,7 +446,7 @@ class Component {
|
||||
this.childIndex_[component.id()] = null;
|
||||
this.childNameIndex_[component.name()] = null;
|
||||
|
||||
let compEl = component.el();
|
||||
const compEl = component.el();
|
||||
|
||||
if (compEl && compEl.parentNode === this.contentEl()) {
|
||||
this.contentEl().removeChild(component.el());
|
||||
@@ -502,14 +500,14 @@ class Component {
|
||||
* @method initChildren
|
||||
*/
|
||||
initChildren() {
|
||||
let children = this.options_.children;
|
||||
const children = this.options_.children;
|
||||
|
||||
if (children) {
|
||||
// `this` is `parent`
|
||||
let parentOptions = this.options_;
|
||||
const parentOptions = this.options_;
|
||||
|
||||
let handleAdd = (child) => {
|
||||
let name = child.name;
|
||||
const handleAdd = (child) => {
|
||||
const name = child.name;
|
||||
let opts = child.opts;
|
||||
|
||||
// Allow options for children to be set at the parent options
|
||||
@@ -539,7 +537,8 @@ class Component {
|
||||
// Add a direct reference to the child by name on the parent instance.
|
||||
// If two of the same component are used, different names should be supplied
|
||||
// for each
|
||||
let newChild = this.addChild(name, opts);
|
||||
const newChild = this.addChild(name, opts);
|
||||
|
||||
if (newChild) {
|
||||
this[name] = newChild;
|
||||
}
|
||||
@@ -547,7 +546,7 @@ class Component {
|
||||
|
||||
// Allow for an array of children details to passed in the options
|
||||
let workingChildren;
|
||||
let Tech = Component.getComponent('Tech');
|
||||
const Tech = Component.getComponent('Tech');
|
||||
|
||||
if (Array.isArray(children)) {
|
||||
workingChildren = children;
|
||||
@@ -563,13 +562,13 @@ class Component {
|
||||
return !workingChildren.some(function(wchild) {
|
||||
if (typeof wchild === 'string') {
|
||||
return child === wchild;
|
||||
} else {
|
||||
return child === wchild.name;
|
||||
}
|
||||
return child === wchild.name;
|
||||
});
|
||||
}))
|
||||
.map((child) => {
|
||||
let name, opts;
|
||||
let name;
|
||||
let opts;
|
||||
|
||||
if (typeof child === 'string') {
|
||||
name = child;
|
||||
@@ -585,8 +584,9 @@ class Component {
|
||||
// we have to make sure that child.name isn't in the techOrder since
|
||||
// techs are registerd as Components but can't aren't compatible
|
||||
// See https://github.com/videojs/video.js/issues/2772
|
||||
let c = Component.getComponent(child.opts.componentClass ||
|
||||
const c = Component.getComponent(child.opts.componentClass ||
|
||||
toTitleCase(child.name));
|
||||
|
||||
return c && !Tech.isTech(c);
|
||||
})
|
||||
.forEach(handleAdd);
|
||||
@@ -608,7 +608,7 @@ class Component {
|
||||
/**
|
||||
* Add an event listener to this component's element
|
||||
* ```js
|
||||
* var myFunc = function(){
|
||||
* var myFunc = function() {
|
||||
* var myComponent = this;
|
||||
* // Do something when the event is fired
|
||||
* };
|
||||
@@ -797,7 +797,7 @@ class Component {
|
||||
* @return {Component}
|
||||
* @method ready
|
||||
*/
|
||||
ready(fn, sync=false) {
|
||||
ready(fn, sync = false) {
|
||||
if (fn) {
|
||||
if (this.isReady_) {
|
||||
if (sync) {
|
||||
@@ -824,14 +824,14 @@ class Component {
|
||||
this.isReady_ = true;
|
||||
|
||||
// Ensure ready is triggerd asynchronously
|
||||
this.setTimeout(function(){
|
||||
let readyQueue = this.readyQueue_;
|
||||
this.setTimeout(function() {
|
||||
const readyQueue = this.readyQueue_;
|
||||
|
||||
// Reset Ready Queue
|
||||
this.readyQueue_ = [];
|
||||
|
||||
if (readyQueue && readyQueue.length > 0) {
|
||||
readyQueue.forEach(function(fn){
|
||||
readyQueue.forEach(function(fn) {
|
||||
fn.call(this);
|
||||
}, this);
|
||||
}
|
||||
@@ -1077,8 +1077,8 @@ class Component {
|
||||
}
|
||||
|
||||
// Get dimension value from style
|
||||
let val = this.el_.style[widthOrHeight];
|
||||
let pxIndex = val.indexOf('px');
|
||||
const val = this.el_.style[widthOrHeight];
|
||||
const pxIndex = val.indexOf('px');
|
||||
|
||||
if (pxIndex !== -1) {
|
||||
// Return the pixel value with no 'px'
|
||||
@@ -1106,11 +1106,13 @@ class Component {
|
||||
|
||||
if (typeof window.getComputedStyle === 'function') {
|
||||
const computedStyle = window.getComputedStyle(this.el_);
|
||||
|
||||
computedWidthOrHeight = computedStyle.getPropertyValue(widthOrHeight) || computedStyle[widthOrHeight];
|
||||
} else if (this.el_.currentStyle) {
|
||||
// ie 8 doesn't support computed style, shim it
|
||||
// return clientWidth or clientHeight instead for better accuracy
|
||||
const rule = `offset${toTitleCase(widthOrHeight)}`;
|
||||
|
||||
computedWidthOrHeight = this.el_[rule];
|
||||
}
|
||||
|
||||
@@ -1176,8 +1178,11 @@ class Component {
|
||||
this.on('touchstart', function(event) {
|
||||
// If more than one finger, don't consider treating this as a click
|
||||
if (event.touches.length === 1) {
|
||||
// Copy the touches object to prevent modifying the original
|
||||
firstTouch = assign({}, event.touches[0]);
|
||||
// Copy pageX/pageY from the object
|
||||
firstTouch = {
|
||||
pageX: event.touches[0].pageX,
|
||||
pageY: event.touches[0].pageY
|
||||
};
|
||||
// Record start time so we can detect a tap vs. "touch and hold"
|
||||
touchStart = new Date().getTime();
|
||||
// Reset couldBeTap tracking
|
||||
@@ -1194,7 +1199,7 @@ class Component {
|
||||
// So, if we moved only a small distance, this could still be a tap
|
||||
const xdiff = event.touches[0].pageX - firstTouch.pageX;
|
||||
const ydiff = event.touches[0].pageY - firstTouch.pageY;
|
||||
const touchDistance = Math.sqrt(xdiff * xdiff + ydiff * ydiff);
|
||||
const touchDistance = Math.sqrt(xdiff * xdiff + ydiff * ydiff);
|
||||
|
||||
if (touchDistance > tapMovementThreshold) {
|
||||
couldBeTap = false;
|
||||
@@ -1297,7 +1302,7 @@ class Component {
|
||||
fn = Fn.bind(this, fn);
|
||||
|
||||
// window.setTimeout would be preferable here, but due to some bizarre issue with Sinon and/or Phantomjs, we can't.
|
||||
let timeoutId = window.setTimeout(fn, timeout);
|
||||
const timeoutId = window.setTimeout(fn, timeout);
|
||||
|
||||
const disposeFn = function() {
|
||||
this.clearTimeout(timeoutId);
|
||||
@@ -1340,7 +1345,7 @@ class Component {
|
||||
setInterval(fn, interval) {
|
||||
fn = Fn.bind(this, fn);
|
||||
|
||||
let intervalId = window.setInterval(fn, interval);
|
||||
const intervalId = window.setInterval(fn, interval);
|
||||
|
||||
const disposeFn = function() {
|
||||
this.clearInterval(intervalId);
|
||||
@@ -1425,7 +1430,7 @@ class Component {
|
||||
// Set up the constructor using the supplied init method
|
||||
// or using the init of the parent object
|
||||
// Make sure to check the unobfuscated version for external libs
|
||||
let init = props.init || props.init || this.prototype.init || this.prototype.init || function() {};
|
||||
const init = props.init || props.init || this.prototype.init || this.prototype.init || function() {};
|
||||
// In Resig's simple class inheritance (previously used) the constructor
|
||||
// is a function that calls `this.init.apply(arguments)`
|
||||
// However that would prevent us from using `ParentObject.call(this);`
|
||||
@@ -1435,7 +1440,7 @@ class Component {
|
||||
// `ParentObject.prototype.init.apply(this, arguments);`
|
||||
// Bleh. We're not creating a _super() function, so it's good to keep
|
||||
// the parent constructor reference simple.
|
||||
let subObj = function() {
|
||||
const subObj = function() {
|
||||
init.apply(this, arguments);
|
||||
};
|
||||
|
||||
@@ -1449,7 +1454,7 @@ class Component {
|
||||
subObj.extend = Component.extend;
|
||||
|
||||
// Extend subObj's prototype with functions and other properties from props
|
||||
for (let name in props) {
|
||||
for (const name in props) {
|
||||
if (props.hasOwnProperty(name)) {
|
||||
subObj.prototype[name] = props[name];
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*/
|
||||
import TrackButton from '../track-button.js';
|
||||
import Component from '../../component.js';
|
||||
import * as Fn from '../../utils/fn.js';
|
||||
import AudioTrackMenuItem from './audio-track-menu-item.js';
|
||||
|
||||
/**
|
||||
@@ -40,25 +39,25 @@ class AudioTrackButton extends TrackButton {
|
||||
* @method createItems
|
||||
*/
|
||||
createItems(items = []) {
|
||||
let tracks = this.player_.audioTracks && this.player_.audioTracks();
|
||||
const tracks = this.player_.audioTracks && this.player_.audioTracks();
|
||||
|
||||
if (!tracks) {
|
||||
return items;
|
||||
}
|
||||
|
||||
for (let i = 0; i < tracks.length; i++) {
|
||||
let track = tracks[i];
|
||||
const track = tracks[i];
|
||||
|
||||
items.push(new AudioTrackMenuItem(this.player_, {
|
||||
track,
|
||||
// MenuItem is selectable
|
||||
'selectable': true,
|
||||
'track': track
|
||||
selectable: true
|
||||
}));
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
}
|
||||
|
||||
AudioTrackButton.prototype.controlText_ = 'Audio Track';
|
||||
Component.registerComponent('AudioTrackButton', AudioTrackButton);
|
||||
export default AudioTrackButton;
|
||||
|
||||
@@ -15,8 +15,8 @@ import * as Fn from '../../utils/fn.js';
|
||||
*/
|
||||
class AudioTrackMenuItem extends MenuItem {
|
||||
constructor(player, options) {
|
||||
let track = options.track;
|
||||
let tracks = player.audioTracks();
|
||||
const track = options.track;
|
||||
const tracks = player.audioTracks();
|
||||
|
||||
// Modify options for parent MenuItem class's init.
|
||||
options.label = track.label || track.language || 'Unknown';
|
||||
@@ -27,7 +27,7 @@ class AudioTrackMenuItem extends MenuItem {
|
||||
this.track = track;
|
||||
|
||||
if (tracks) {
|
||||
let changeHandler = Fn.bind(this, this.handleTracksChange);
|
||||
const changeHandler = Fn.bind(this, this.handleTracksChange);
|
||||
|
||||
tracks.addEventListener('change', changeHandler);
|
||||
this.on('dispose', () => {
|
||||
@@ -42,18 +42,18 @@ class AudioTrackMenuItem extends MenuItem {
|
||||
* @method handleClick
|
||||
*/
|
||||
handleClick(event) {
|
||||
let tracks = this.player_.audioTracks();
|
||||
const tracks = this.player_.audioTracks();
|
||||
|
||||
super.handleClick(event);
|
||||
|
||||
if (!tracks) return;
|
||||
if (!tracks) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0; i < tracks.length; i++) {
|
||||
let track = tracks[i];
|
||||
const track = tracks[i];
|
||||
|
||||
if (track === this.track) {
|
||||
track.enabled = true;
|
||||
}
|
||||
track.enabled = track === this.track;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,24 +4,24 @@
|
||||
import Component from '../component.js';
|
||||
|
||||
// Required children
|
||||
import PlayToggle from './play-toggle.js';
|
||||
import CurrentTimeDisplay from './time-controls/current-time-display.js';
|
||||
import DurationDisplay from './time-controls/duration-display.js';
|
||||
import TimeDivider from './time-controls/time-divider.js';
|
||||
import RemainingTimeDisplay from './time-controls/remaining-time-display.js';
|
||||
import LiveDisplay from './live-display.js';
|
||||
import ProgressControl from './progress-control/progress-control.js';
|
||||
import FullscreenToggle from './fullscreen-toggle.js';
|
||||
import VolumeControl from './volume-control/volume-control.js';
|
||||
import VolumeMenuButton from './volume-menu-button.js';
|
||||
import MuteToggle from './mute-toggle.js';
|
||||
import ChaptersButton from './text-track-controls/chapters-button.js';
|
||||
import DescriptionsButton from './text-track-controls/descriptions-button.js';
|
||||
import SubtitlesButton from './text-track-controls/subtitles-button.js';
|
||||
import CaptionsButton from './text-track-controls/captions-button.js';
|
||||
import AudioTrackButton from './audio-track-controls/audio-track-button.js';
|
||||
import PlaybackRateMenuButton from './playback-rate-menu/playback-rate-menu-button.js';
|
||||
import CustomControlSpacer from './spacer-controls/custom-control-spacer.js';
|
||||
import './play-toggle.js';
|
||||
import './time-controls/current-time-display.js';
|
||||
import './time-controls/duration-display.js';
|
||||
import './time-controls/time-divider.js';
|
||||
import './time-controls/remaining-time-display.js';
|
||||
import './live-display.js';
|
||||
import './progress-control/progress-control.js';
|
||||
import './fullscreen-toggle.js';
|
||||
import './volume-control/volume-control.js';
|
||||
import './volume-menu-button.js';
|
||||
import './mute-toggle.js';
|
||||
import './text-track-controls/chapters-button.js';
|
||||
import './text-track-controls/descriptions-button.js';
|
||||
import './text-track-controls/subtitles-button.js';
|
||||
import './text-track-controls/captions-button.js';
|
||||
import './audio-track-controls/audio-track-button.js';
|
||||
import './playback-rate-menu/playback-rate-menu-button.js';
|
||||
import './spacer-controls/custom-control-spacer.js';
|
||||
|
||||
/**
|
||||
* Container of main controls
|
||||
@@ -42,7 +42,8 @@ class ControlBar extends Component {
|
||||
className: 'vjs-control-bar',
|
||||
dir: 'ltr'
|
||||
}, {
|
||||
'role': 'group' // The control bar is a group, so it can contain menuitems
|
||||
// The control bar is a group, so it can contain menuitems
|
||||
role: 'group'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,11 @@ import Component from '../component.js';
|
||||
*/
|
||||
class FullscreenToggle extends Button {
|
||||
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
this.on(player, 'fullscreenchange', this.handleFullscreenChange);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow sub components to stack CSS class names
|
||||
*
|
||||
@@ -21,7 +26,18 @@ class FullscreenToggle extends Button {
|
||||
buildCSSClass() {
|
||||
return `vjs-fullscreen-control ${super.buildCSSClass()}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles Fullscreenchange on the component and change control text accordingly
|
||||
*
|
||||
* @method handleFullscreenChange
|
||||
*/
|
||||
handleFullscreenChange() {
|
||||
if (this.player_.isFullscreen()) {
|
||||
this.controlText('Non-Fullscreen');
|
||||
} else {
|
||||
this.controlText('Fullscreen');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Handles click for full screen
|
||||
*
|
||||
@@ -30,10 +46,8 @@ class FullscreenToggle extends Button {
|
||||
handleClick() {
|
||||
if (!this.player_.isFullscreen()) {
|
||||
this.player_.requestFullscreen();
|
||||
this.controlText('Non-Fullscreen');
|
||||
} else {
|
||||
this.player_.exitFullscreen();
|
||||
this.controlText('Fullscreen');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ class LiveDisplay extends Component {
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
var el = super.createEl('div', {
|
||||
const el = super.createEl('div', {
|
||||
className: 'vjs-live-control vjs-control'
|
||||
});
|
||||
|
||||
|
||||
@@ -21,14 +21,15 @@ class MuteToggle extends Button {
|
||||
this.on(player, 'volumechange', this.update);
|
||||
|
||||
// hide mute toggle if the current tech doesn't support volume control
|
||||
if (player.tech_ && player.tech_['featuresVolumeControl'] === false) {
|
||||
if (player.tech_ && player.tech_.featuresVolumeControl === false) {
|
||||
this.addClass('vjs-hidden');
|
||||
}
|
||||
|
||||
this.on(player, 'loadstart', function() {
|
||||
this.update(); // We need to update the button to account for a default muted state.
|
||||
// We need to update the button to account for a default muted state.
|
||||
this.update();
|
||||
|
||||
if (player.tech_['featuresVolumeControl'] === false) {
|
||||
if (player.tech_.featuresVolumeControl === false) {
|
||||
this.addClass('vjs-hidden');
|
||||
} else {
|
||||
this.removeClass('vjs-hidden');
|
||||
@@ -52,7 +53,7 @@ class MuteToggle extends Button {
|
||||
* @method handleClick
|
||||
*/
|
||||
handleClick() {
|
||||
this.player_.muted( this.player_.muted() ? false : true );
|
||||
this.player_.muted(this.player_.muted() ? false : true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,8 +62,8 @@ class MuteToggle extends Button {
|
||||
* @method update
|
||||
*/
|
||||
update() {
|
||||
var vol = this.player_.volume(),
|
||||
level = 3;
|
||||
const vol = this.player_.volume();
|
||||
let level = 3;
|
||||
|
||||
if (vol === 0 || this.player_.muted()) {
|
||||
level = 0;
|
||||
@@ -75,13 +76,14 @@ class MuteToggle extends Button {
|
||||
// Don't rewrite the button text if the actual text doesn't change.
|
||||
// This causes unnecessary and confusing information for screen reader users.
|
||||
// This check is needed because this function gets called every time the volume level is changed.
|
||||
let toMute = this.player_.muted() ? 'Unmute' : 'Mute';
|
||||
const toMute = this.player_.muted() ? 'Unmute' : 'Mute';
|
||||
|
||||
if (this.controlText() !== toMute) {
|
||||
this.controlText(toMute);
|
||||
}
|
||||
|
||||
/* TODO improve muted icon classes */
|
||||
for (var i = 0; i < 4; i++) {
|
||||
// TODO improve muted icon classes
|
||||
for (let i = 0; i < 4; i++) {
|
||||
Dom.removeElClass(this.el_, `vjs-vol-${i}`);
|
||||
}
|
||||
Dom.addElClass(this.el_, `vjs-vol-${level}`);
|
||||
|
||||
@@ -14,7 +14,7 @@ import Component from '../component.js';
|
||||
*/
|
||||
class PlayToggle extends Button {
|
||||
|
||||
constructor(player, options){
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
|
||||
this.on(player, 'play', this.handlePlay);
|
||||
@@ -52,7 +52,8 @@ class PlayToggle extends Button {
|
||||
handlePlay() {
|
||||
this.removeClass('vjs-paused');
|
||||
this.addClass('vjs-playing');
|
||||
this.controlText('Pause'); // change the button text to "Pause"
|
||||
// change the button text to "Pause"
|
||||
this.controlText('Pause');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,7 +64,8 @@ class PlayToggle extends Button {
|
||||
handlePause() {
|
||||
this.removeClass('vjs-playing');
|
||||
this.addClass('vjs-paused');
|
||||
this.controlText('Play'); // change the button text to "Play"
|
||||
// change the button text to "Play"
|
||||
this.controlText('Play');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import * as Dom from '../../utils/dom.js';
|
||||
*/
|
||||
class PlaybackRateMenuButton extends MenuButton {
|
||||
|
||||
constructor(player, options){
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
|
||||
this.updateVisibility();
|
||||
@@ -34,7 +34,7 @@ class PlaybackRateMenuButton extends MenuButton {
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
let el = super.createEl();
|
||||
const el = super.createEl();
|
||||
|
||||
this.labelEl_ = Dom.createEl('div', {
|
||||
className: 'vjs-playback-rate-value',
|
||||
@@ -63,13 +63,13 @@ class PlaybackRateMenuButton extends MenuButton {
|
||||
* @method createMenu
|
||||
*/
|
||||
createMenu() {
|
||||
let menu = new Menu(this.player());
|
||||
let rates = this.playbackRates();
|
||||
const menu = new Menu(this.player());
|
||||
const rates = this.playbackRates();
|
||||
|
||||
if (rates) {
|
||||
for (let i = rates.length - 1; i >= 0; i--) {
|
||||
menu.addChild(
|
||||
new PlaybackRateMenuItem(this.player(), { 'rate': rates[i] + 'x'})
|
||||
new PlaybackRateMenuItem(this.player(), {rate: rates[i] + 'x'})
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -94,12 +94,13 @@ class PlaybackRateMenuButton extends MenuButton {
|
||||
*/
|
||||
handleClick() {
|
||||
// select next rate option
|
||||
let currentRate = this.player().playbackRate();
|
||||
let rates = this.playbackRates();
|
||||
const currentRate = this.player().playbackRate();
|
||||
const rates = this.playbackRates();
|
||||
|
||||
// this will select first one if the last one currently selected
|
||||
let newRate = rates[0];
|
||||
for (let i = 0; i < rates.length ; i++) {
|
||||
|
||||
for (let i = 0; i < rates.length; i++) {
|
||||
if (rates[i] > currentRate) {
|
||||
newRate = rates[i];
|
||||
break;
|
||||
@@ -115,7 +116,7 @@ class PlaybackRateMenuButton extends MenuButton {
|
||||
* @method playbackRates
|
||||
*/
|
||||
playbackRates() {
|
||||
return this.options_['playbackRates'] || (this.options_.playerOptions && this.options_.playerOptions['playbackRates']);
|
||||
return this.options_.playbackRates || (this.options_.playerOptions && this.options_.playerOptions.playbackRates);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -126,10 +127,10 @@ class PlaybackRateMenuButton extends MenuButton {
|
||||
* @method playbackRateSupported
|
||||
*/
|
||||
playbackRateSupported() {
|
||||
return this.player().tech_
|
||||
&& this.player().tech_['featuresPlaybackRate']
|
||||
&& this.playbackRates()
|
||||
&& this.playbackRates().length > 0
|
||||
return this.player().tech_ &&
|
||||
this.player().tech_.featuresPlaybackRate &&
|
||||
this.playbackRates() &&
|
||||
this.playbackRates().length > 0
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,13 +14,13 @@ import Component from '../../component.js';
|
||||
*/
|
||||
class PlaybackRateMenuItem extends MenuItem {
|
||||
|
||||
constructor(player, options){
|
||||
let label = options['rate'];
|
||||
let rate = parseFloat(label, 10);
|
||||
constructor(player, options) {
|
||||
const label = options.rate;
|
||||
const rate = parseFloat(label, 10);
|
||||
|
||||
// Modify options for parent MenuItem class's init.
|
||||
options['label'] = label;
|
||||
options['selected'] = rate === 1;
|
||||
options.label = label;
|
||||
options.selected = rate === 1;
|
||||
super(player, options);
|
||||
|
||||
this.label = label;
|
||||
|
||||
@@ -14,7 +14,7 @@ import * as Dom from '../../utils/dom.js';
|
||||
*/
|
||||
class LoadProgressBar extends Component {
|
||||
|
||||
constructor(player, options){
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
this.on(player, 'progress', this.update);
|
||||
}
|
||||
@@ -38,14 +38,16 @@ class LoadProgressBar extends Component {
|
||||
* @method update
|
||||
*/
|
||||
update() {
|
||||
let buffered = this.player_.buffered();
|
||||
let duration = this.player_.duration();
|
||||
let bufferedEnd = this.player_.bufferedEnd();
|
||||
let children = this.el_.children;
|
||||
const buffered = this.player_.buffered();
|
||||
const duration = this.player_.duration();
|
||||
const bufferedEnd = this.player_.bufferedEnd();
|
||||
const children = this.el_.children;
|
||||
|
||||
// get the percent width of a time compared to the total end
|
||||
let percentify = function (time, end){
|
||||
let percent = (time / end) || 0; // no NaN
|
||||
const percentify = function(time, end) {
|
||||
// no NaN
|
||||
const percent = (time / end) || 0;
|
||||
|
||||
return ((percent >= 1 ? 1 : percent) * 100) + '%';
|
||||
};
|
||||
|
||||
@@ -54,8 +56,8 @@ class LoadProgressBar extends Component {
|
||||
|
||||
// add child elements to represent the individual buffered time ranges
|
||||
for (let i = 0; i < buffered.length; i++) {
|
||||
let start = buffered.start(i);
|
||||
let end = buffered.end(i);
|
||||
const start = buffered.start(i);
|
||||
const end = buffered.end(i);
|
||||
let part = children[i];
|
||||
|
||||
if (!part) {
|
||||
@@ -69,7 +71,7 @@ class LoadProgressBar extends Component {
|
||||
|
||||
// remove unused buffered range elements
|
||||
for (let i = children.length; i > buffered.length; i--) {
|
||||
this.el_.removeChild(children[i-1]);
|
||||
this.el_.removeChild(children[i - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,24 +55,24 @@ class MouseTimeDisplay extends Component {
|
||||
}
|
||||
|
||||
handleMouseMove(event) {
|
||||
let duration = this.player_.duration();
|
||||
let newTime = this.calculateDistance(event) * duration;
|
||||
let position = event.pageX - Dom.findElPosition(this.el().parentNode).left;
|
||||
const duration = this.player_.duration();
|
||||
const newTime = this.calculateDistance(event) * duration;
|
||||
const position = event.pageX - Dom.findElPosition(this.el().parentNode).left;
|
||||
|
||||
this.update(newTime, position);
|
||||
}
|
||||
|
||||
update(newTime, position) {
|
||||
let time = formatTime(newTime, this.player_.duration());
|
||||
const time = formatTime(newTime, this.player_.duration());
|
||||
|
||||
this.el().style.left = position + 'px';
|
||||
this.el().setAttribute('data-current-time', time);
|
||||
|
||||
if (this.keepTooltipsInside) {
|
||||
let clampedPosition = this.clampPosition_(position);
|
||||
let difference = position - clampedPosition + 1;
|
||||
let tooltipWidth = parseFloat(window.getComputedStyle(this.tooltip).width);
|
||||
let tooltipWidthHalf = tooltipWidth / 2;
|
||||
const clampedPosition = this.clampPosition_(position);
|
||||
const difference = position - clampedPosition + 1;
|
||||
const tooltipWidth = parseFloat(window.getComputedStyle(this.tooltip).width);
|
||||
const tooltipWidthHalf = tooltipWidth / 2;
|
||||
|
||||
this.tooltip.innerHTML = time;
|
||||
this.tooltip.style.right = `-${tooltipWidthHalf - difference}px`;
|
||||
@@ -98,9 +98,9 @@ class MouseTimeDisplay extends Component {
|
||||
return position;
|
||||
}
|
||||
|
||||
let playerWidth = parseFloat(window.getComputedStyle(this.player().el()).width);
|
||||
let tooltipWidth = parseFloat(window.getComputedStyle(this.tooltip).width);
|
||||
let tooltipWidthHalf = tooltipWidth / 2;
|
||||
const playerWidth = parseFloat(window.getComputedStyle(this.player().el()).width);
|
||||
const tooltipWidth = parseFloat(window.getComputedStyle(this.tooltip).width);
|
||||
const tooltipWidthHalf = tooltipWidth / 2;
|
||||
let actualPosition = position;
|
||||
|
||||
if (position < tooltipWidthHalf) {
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*/
|
||||
import Component from '../../component.js';
|
||||
import * as Fn from '../../utils/fn.js';
|
||||
import * as Dom from '../../utils/dom.js';
|
||||
import formatTime from '../../utils/format-time.js';
|
||||
|
||||
/**
|
||||
@@ -16,7 +15,7 @@ import formatTime from '../../utils/format-time.js';
|
||||
*/
|
||||
class PlayProgressBar extends Component {
|
||||
|
||||
constructor(player, options){
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
this.updateDataAttr();
|
||||
this.on(player, 'timeupdate', this.updateDataAttr);
|
||||
@@ -48,7 +47,8 @@ class PlayProgressBar extends Component {
|
||||
}
|
||||
|
||||
updateDataAttr() {
|
||||
let time = (this.player_.scrubbing()) ? this.player_.getCache().currentTime : this.player_.currentTime();
|
||||
const time = (this.player_.scrubbing()) ? this.player_.getCache().currentTime : this.player_.currentTime();
|
||||
|
||||
this.el_.setAttribute('data-current-time', formatTime(time, this.player_.duration()));
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
* @file progress-control.js
|
||||
*/
|
||||
import Component from '../../component.js';
|
||||
import SeekBar from './seek-bar.js';
|
||||
import MouseTimeDisplay from './mouse-time-display.js';
|
||||
|
||||
import './seek-bar.js';
|
||||
import './mouse-time-display.js';
|
||||
|
||||
/**
|
||||
* The Progress Control component contains the seek bar, load progress,
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
import window from 'global/window';
|
||||
import Slider from '../../slider/slider.js';
|
||||
import Component from '../../component.js';
|
||||
import LoadProgressBar from './load-progress-bar.js';
|
||||
import PlayProgressBar from './play-progress-bar.js';
|
||||
import TooltipProgressBar from './tooltip-progress-bar.js';
|
||||
import * as Fn from '../../utils/fn.js';
|
||||
import formatTime from '../../utils/format-time.js';
|
||||
import assign from 'object.assign';
|
||||
|
||||
import './load-progress-bar.js';
|
||||
import './play-progress-bar.js';
|
||||
import './tooltip-progress-bar.js';
|
||||
|
||||
/**
|
||||
* Seek Bar and holder for the progress bars
|
||||
@@ -21,7 +21,7 @@ import assign from 'object.assign';
|
||||
*/
|
||||
class SeekBar extends Slider {
|
||||
|
||||
constructor(player, options){
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
this.on(player, 'timeupdate', this.updateProgress);
|
||||
this.on(player, 'ended', this.updateProgress);
|
||||
@@ -65,9 +65,10 @@ class SeekBar extends Slider {
|
||||
this.updateAriaAttributes(this.tooltipProgressBar.el_);
|
||||
this.tooltipProgressBar.el_.style.width = this.bar.el_.style.width;
|
||||
|
||||
let playerWidth = parseFloat(window.getComputedStyle(this.player().el()).width);
|
||||
let tooltipWidth = parseFloat(window.getComputedStyle(this.tooltipProgressBar.tooltip).width);
|
||||
let tooltipStyle = this.tooltipProgressBar.el().style;
|
||||
const playerWidth = parseFloat(window.getComputedStyle(this.player().el()).width);
|
||||
const tooltipWidth = parseFloat(window.getComputedStyle(this.tooltipProgressBar.tooltip).width);
|
||||
const tooltipStyle = this.tooltipProgressBar.el().style;
|
||||
|
||||
tooltipStyle.maxWidth = Math.floor(playerWidth - (tooltipWidth / 2)) + 'px';
|
||||
tooltipStyle.minWidth = Math.ceil(tooltipWidth / 2) + 'px';
|
||||
tooltipStyle.right = `-${tooltipWidth / 2}px`;
|
||||
@@ -76,9 +77,12 @@ class SeekBar extends Slider {
|
||||
|
||||
updateAriaAttributes(el) {
|
||||
// Allows for smooth scrubbing, when player can't keep up.
|
||||
let time = (this.player_.scrubbing()) ? this.player_.getCache().currentTime : this.player_.currentTime();
|
||||
el.setAttribute('aria-valuenow', (this.getPercent() * 100).toFixed(2)); // machine readable value of progress bar (percentage complete)
|
||||
el.setAttribute('aria-valuetext', formatTime(time, this.player_.duration())); // human readable value of progress bar (time complete)
|
||||
const time = (this.player_.scrubbing()) ? this.player_.getCache().currentTime : this.player_.currentTime();
|
||||
|
||||
// machine readable value of progress bar (percentage complete)
|
||||
el.setAttribute('aria-valuenow', (this.getPercent() * 100).toFixed(2));
|
||||
// human readable value of progress bar (time complete)
|
||||
el.setAttribute('aria-valuetext', formatTime(time, this.player_.duration()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,7 +92,8 @@ class SeekBar extends Slider {
|
||||
* @method getPercent
|
||||
*/
|
||||
getPercent() {
|
||||
let percent = this.player_.currentTime() / this.player_.duration();
|
||||
const percent = this.player_.currentTime() / this.player_.duration();
|
||||
|
||||
return percent >= 1 ? 1 : percent;
|
||||
}
|
||||
|
||||
@@ -115,7 +120,9 @@ class SeekBar extends Slider {
|
||||
let newTime = this.calculateDistance(event) * this.player_.duration();
|
||||
|
||||
// Don't let video end while scrubbing.
|
||||
if (newTime === this.player_.duration()) { newTime = newTime - 0.1; }
|
||||
if (newTime === this.player_.duration()) {
|
||||
newTime = newTime - 0.1;
|
||||
}
|
||||
|
||||
// Set new time (tell player to seek to new time)
|
||||
this.player_.currentTime(newTime);
|
||||
@@ -141,7 +148,8 @@ class SeekBar extends Slider {
|
||||
* @method stepForward
|
||||
*/
|
||||
stepForward() {
|
||||
this.player_.currentTime(this.player_.currentTime() + 5); // more quickly fast forward for keyboard-only users
|
||||
// more quickly fast forward for keyboard-only users
|
||||
this.player_.currentTime(this.player_.currentTime() + 5);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,7 +158,8 @@ class SeekBar extends Slider {
|
||||
* @method stepBack
|
||||
*/
|
||||
stepBack() {
|
||||
this.player_.currentTime(this.player_.currentTime() - 5); // more quickly rewind for keyboard-only users
|
||||
// more quickly rewind for keyboard-only users
|
||||
this.player_.currentTime(this.player_.currentTime() - 5);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -161,7 +170,7 @@ SeekBar.prototype.options_ = {
|
||||
'mouseTimeDisplay',
|
||||
'playProgressBar'
|
||||
],
|
||||
'barName': 'playProgressBar'
|
||||
barName: 'playProgressBar'
|
||||
};
|
||||
|
||||
SeekBar.prototype.playerEvent = 'timeupdate';
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*/
|
||||
import Component from '../../component.js';
|
||||
import * as Fn from '../../utils/fn.js';
|
||||
import * as Dom from '../../utils/dom.js';
|
||||
import formatTime from '../../utils/format-time.js';
|
||||
|
||||
/**
|
||||
@@ -16,7 +15,7 @@ import formatTime from '../../utils/format-time.js';
|
||||
*/
|
||||
class TooltipProgressBar extends Component {
|
||||
|
||||
constructor(player, options){
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
this.updateDataAttr();
|
||||
this.on(player, 'timeupdate', this.updateDataAttr);
|
||||
@@ -30,7 +29,7 @@ class TooltipProgressBar extends Component {
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
let el = super.createEl('div', {
|
||||
const el = super.createEl('div', {
|
||||
className: 'vjs-tooltip-progress-bar vjs-slider-bar',
|
||||
innerHTML: `<div class="vjs-time-tooltip"></div>
|
||||
<span class="vjs-control-text"><span>${this.localize('Progress')}</span>: 0%</span>`
|
||||
@@ -42,8 +41,9 @@ class TooltipProgressBar extends Component {
|
||||
}
|
||||
|
||||
updateDataAttr() {
|
||||
let time = (this.player_.scrubbing()) ? this.player_.getCache().currentTime : this.player_.currentTime();
|
||||
let formattedTime = formatTime(time, this.player_.duration());
|
||||
const time = (this.player_.scrubbing()) ? this.player_.getCache().currentTime : this.player_.currentTime();
|
||||
const formattedTime = formatTime(time, this.player_.duration());
|
||||
|
||||
this.el_.setAttribute('data-current-time', formattedTime);
|
||||
this.tooltip.innerHTML = formattedTime;
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@ class CustomControlSpacer extends Spacer {
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
let el = super.createEl({
|
||||
className: this.buildCSSClass(),
|
||||
const el = super.createEl({
|
||||
className: this.buildCSSClass()
|
||||
});
|
||||
|
||||
// No-flex/table-cell mode requires there be some content
|
||||
|
||||
@@ -12,24 +12,24 @@ import Component from '../../component.js';
|
||||
* @extends TextTrackMenuItem
|
||||
* @class CaptionSettingsMenuItem
|
||||
*/
|
||||
class CaptionSettingsMenuItem extends TextTrackMenuItem {
|
||||
class CaptionSettingsMenuItem extends TextTrackMenuItem {
|
||||
|
||||
constructor(player, options) {
|
||||
options['track'] = {
|
||||
'kind': options['kind'],
|
||||
'player': player,
|
||||
'label': options['kind'] + ' settings',
|
||||
'selectable': false,
|
||||
'default': false,
|
||||
options.track = {
|
||||
player,
|
||||
kind: options.kind,
|
||||
label: options.kind + ' settings',
|
||||
selectable: false,
|
||||
default: false,
|
||||
mode: 'disabled'
|
||||
};
|
||||
|
||||
// CaptionSettingsMenuItem has no concept of 'selected'
|
||||
options['selectable'] = false;
|
||||
options.selectable = false;
|
||||
|
||||
super(player, options);
|
||||
this.addClass('vjs-texttrack-settings');
|
||||
this.controlText(', opens ' + options['kind'] + ' settings dialog');
|
||||
this.controlText(', opens ' + options.kind + ' settings dialog');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,9 +16,9 @@ import CaptionSettingsMenuItem from './caption-settings-menu-item.js';
|
||||
*/
|
||||
class CaptionsButton extends TextTrackButton {
|
||||
|
||||
constructor(player, options, ready){
|
||||
constructor(player, options, ready) {
|
||||
super(player, options, ready);
|
||||
this.el_.setAttribute('aria-label','Captions Menu');
|
||||
this.el_.setAttribute('aria-label', 'Captions Menu');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -38,10 +38,11 @@ class CaptionsButton extends TextTrackButton {
|
||||
*/
|
||||
update() {
|
||||
let threshold = 2;
|
||||
|
||||
super.update();
|
||||
|
||||
// if native, then threshold is 1 because no settings button
|
||||
if (this.player().tech_ && this.player().tech_['featuresNativeTextTracks']) {
|
||||
if (this.player().tech_ && this.player().tech_.featuresNativeTextTracks) {
|
||||
threshold = 1;
|
||||
}
|
||||
|
||||
@@ -59,10 +60,10 @@ class CaptionsButton extends TextTrackButton {
|
||||
* @method createItems
|
||||
*/
|
||||
createItems() {
|
||||
let items = [];
|
||||
const items = [];
|
||||
|
||||
if (!(this.player().tech_ && this.player().tech_['featuresNativeTextTracks'])) {
|
||||
items.push(new CaptionSettingsMenuItem(this.player_, { 'kind': this.kind_ }));
|
||||
if (!(this.player().tech_ && this.player().tech_.featuresNativeTextTracks)) {
|
||||
items.push(new CaptionSettingsMenuItem(this.player_, {kind: this.kind_}));
|
||||
}
|
||||
|
||||
return super.createItems(items);
|
||||
|
||||
@@ -7,9 +7,7 @@ import TextTrackMenuItem from './text-track-menu-item.js';
|
||||
import ChaptersTrackMenuItem from './chapters-track-menu-item.js';
|
||||
import Menu from '../../menu/menu.js';
|
||||
import * as Dom from '../../utils/dom.js';
|
||||
import * as Fn from '../../utils/fn.js';
|
||||
import toTitleCase from '../../utils/to-title-case.js';
|
||||
import window from 'global/window';
|
||||
|
||||
/**
|
||||
* The button component for toggling and selecting chapters
|
||||
@@ -24,9 +22,9 @@ import window from 'global/window';
|
||||
*/
|
||||
class ChaptersButton extends TextTrackButton {
|
||||
|
||||
constructor(player, options, ready){
|
||||
constructor(player, options, ready) {
|
||||
super(player, options, ready);
|
||||
this.el_.setAttribute('aria-label','Chapters Menu');
|
||||
this.el_.setAttribute('aria-label', 'Chapters Menu');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,20 +44,18 @@ class ChaptersButton extends TextTrackButton {
|
||||
* @method createItems
|
||||
*/
|
||||
createItems() {
|
||||
let items = [];
|
||||
|
||||
let tracks = this.player_.textTracks();
|
||||
const items = [];
|
||||
const tracks = this.player_.textTracks();
|
||||
|
||||
if (!tracks) {
|
||||
return items;
|
||||
}
|
||||
|
||||
for (let i = 0; i < tracks.length; i++) {
|
||||
let track = tracks[i];
|
||||
if (track['kind'] === this.kind_) {
|
||||
items.push(new TextTrackMenuItem(this.player_, {
|
||||
'track': track
|
||||
}));
|
||||
const track = tracks[i];
|
||||
|
||||
if (track.kind === this.kind_) {
|
||||
items.push(new TextTrackMenuItem(this.player_, {track}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,16 +69,16 @@ class ChaptersButton extends TextTrackButton {
|
||||
* @method createMenu
|
||||
*/
|
||||
createMenu() {
|
||||
let tracks = this.player_.textTracks() || [];
|
||||
const tracks = this.player_.textTracks() || [];
|
||||
let chaptersTrack;
|
||||
let items = this.items || [];
|
||||
|
||||
for (let i = tracks.length - 1; i >= 0; i--) {
|
||||
|
||||
// We will always choose the last track as our chaptersTrack
|
||||
let track = tracks[i];
|
||||
const track = tracks[i];
|
||||
|
||||
if (track['kind'] === this.kind_) {
|
||||
if (track.kind === this.kind_) {
|
||||
chaptersTrack = track;
|
||||
|
||||
break;
|
||||
@@ -90,27 +86,30 @@ class ChaptersButton extends TextTrackButton {
|
||||
}
|
||||
|
||||
let menu = this.menu;
|
||||
|
||||
if (menu === undefined) {
|
||||
menu = new Menu(this.player_);
|
||||
let title = Dom.createEl('li', {
|
||||
|
||||
const title = Dom.createEl('li', {
|
||||
className: 'vjs-menu-title',
|
||||
innerHTML: toTitleCase(this.kind_),
|
||||
tabIndex: -1
|
||||
});
|
||||
|
||||
menu.children_.unshift(title);
|
||||
Dom.insertElFirst(title, menu.contentEl());
|
||||
} else {
|
||||
// We will empty out the menu children each time because we want a
|
||||
// fresh new menu child list each time
|
||||
items.forEach(item => menu.removeChild(item));
|
||||
// Empty out the ChaptersButton menu items because we no longer need them
|
||||
items = [];
|
||||
// We will empty out the menu children each time because we want a
|
||||
// fresh new menu child list each time
|
||||
items.forEach(item => menu.removeChild(item));
|
||||
// Empty out the ChaptersButton menu items because we no longer need them
|
||||
items = [];
|
||||
}
|
||||
|
||||
if (chaptersTrack && chaptersTrack.cues == null) {
|
||||
chaptersTrack['mode'] = 'hidden';
|
||||
if (chaptersTrack && (chaptersTrack.cues === null || chaptersTrack.cues === undefined)) {
|
||||
chaptersTrack.mode = 'hidden';
|
||||
|
||||
let remoteTextTrackEl = this.player_.remoteTextTrackEls().getTrackElementByTrack_(chaptersTrack);
|
||||
const remoteTextTrackEl = this.player_.remoteTextTrackEls().getTrackElementByTrack_(chaptersTrack);
|
||||
|
||||
if (remoteTextTrackEl) {
|
||||
remoteTextTrackEl.addEventListener('load', (event) => this.update());
|
||||
@@ -118,14 +117,14 @@ class ChaptersButton extends TextTrackButton {
|
||||
}
|
||||
|
||||
if (chaptersTrack && chaptersTrack.cues && chaptersTrack.cues.length > 0) {
|
||||
let cues = chaptersTrack['cues'], cue;
|
||||
const cues = chaptersTrack.cues;
|
||||
|
||||
for (let i = 0, l = cues.length; i < l; i++) {
|
||||
cue = cues[i];
|
||||
const cue = cues[i];
|
||||
|
||||
let mi = new ChaptersTrackMenuItem(this.player_, {
|
||||
'track': chaptersTrack,
|
||||
'cue': cue
|
||||
const mi = new ChaptersTrackMenuItem(this.player_, {
|
||||
cue,
|
||||
track: chaptersTrack
|
||||
});
|
||||
|
||||
items.push(mi);
|
||||
|
||||
@@ -15,14 +15,14 @@ import * as Fn from '../../utils/fn.js';
|
||||
*/
|
||||
class ChaptersTrackMenuItem extends MenuItem {
|
||||
|
||||
constructor(player, options){
|
||||
let track = options['track'];
|
||||
let cue = options['cue'];
|
||||
let currentTime = player.currentTime();
|
||||
constructor(player, options) {
|
||||
const track = options.track;
|
||||
const cue = options.cue;
|
||||
const currentTime = player.currentTime();
|
||||
|
||||
// Modify options for parent MenuItem class's init.
|
||||
options['label'] = cue.text;
|
||||
options['selected'] = (cue['startTime'] <= currentTime && currentTime < cue['endTime']);
|
||||
options.label = cue.text;
|
||||
options.selected = (cue.startTime <= currentTime && currentTime < cue.endTime);
|
||||
super(player, options);
|
||||
|
||||
this.track = track;
|
||||
@@ -47,11 +47,11 @@ class ChaptersTrackMenuItem extends MenuItem {
|
||||
* @method update
|
||||
*/
|
||||
update() {
|
||||
let cue = this.cue;
|
||||
let currentTime = this.player_.currentTime();
|
||||
const cue = this.cue;
|
||||
const currentTime = this.player_.currentTime();
|
||||
|
||||
// vjs.log(currentTime, cue.startTime);
|
||||
this.selected(cue['startTime'] <= currentTime && currentTime < cue['endTime']);
|
||||
this.selected(cue.startTime <= currentTime && currentTime < cue.endTime);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,14 +16,14 @@ import * as Fn from '../../utils/fn.js';
|
||||
*/
|
||||
class DescriptionsButton extends TextTrackButton {
|
||||
|
||||
constructor(player, options, ready){
|
||||
constructor(player, options, ready) {
|
||||
super(player, options, ready);
|
||||
this.el_.setAttribute('aria-label', 'Descriptions Menu');
|
||||
|
||||
let tracks = player.textTracks();
|
||||
const tracks = player.textTracks();
|
||||
|
||||
if (tracks) {
|
||||
let changeHandler = Fn.bind(this, this.handleTracksChange);
|
||||
const changeHandler = Fn.bind(this, this.handleTracksChange);
|
||||
|
||||
tracks.addEventListener('change', changeHandler);
|
||||
this.on('dispose', function() {
|
||||
@@ -37,14 +37,15 @@ class DescriptionsButton extends TextTrackButton {
|
||||
*
|
||||
* @method handleTracksChange
|
||||
*/
|
||||
handleTracksChange(event){
|
||||
let tracks = this.player().textTracks();
|
||||
handleTracksChange(event) {
|
||||
const tracks = this.player().textTracks();
|
||||
let disabled = false;
|
||||
|
||||
// Check whether a track of a different kind is showing
|
||||
for (let i = 0, l = tracks.length; i < l; i++) {
|
||||
let track = tracks[i];
|
||||
if (track['kind'] !== this.kind_ && track['mode'] === 'showing') {
|
||||
const track = tracks[i];
|
||||
|
||||
if (track.kind !== this.kind_ && track.mode === 'showing') {
|
||||
disabled = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -14,19 +14,19 @@ import Component from '../../component.js';
|
||||
*/
|
||||
class OffTextTrackMenuItem extends TextTrackMenuItem {
|
||||
|
||||
constructor(player, options){
|
||||
constructor(player, options) {
|
||||
// Create pseudo track info
|
||||
// Requires options['kind']
|
||||
options['track'] = {
|
||||
'kind': options['kind'],
|
||||
'player': player,
|
||||
'label': options['kind'] + ' off',
|
||||
'default': false,
|
||||
'mode': 'disabled'
|
||||
options.track = {
|
||||
player,
|
||||
kind: options.kind,
|
||||
label: options.kind + ' off',
|
||||
default: false,
|
||||
mode: 'disabled'
|
||||
};
|
||||
|
||||
// MenuItem is selectable
|
||||
options['selectable'] = true;
|
||||
options.selectable = true;
|
||||
|
||||
super(player, options);
|
||||
this.selected(true);
|
||||
@@ -38,13 +38,14 @@ class OffTextTrackMenuItem extends TextTrackMenuItem {
|
||||
* @param {Object} event Event object
|
||||
* @method handleTracksChange
|
||||
*/
|
||||
handleTracksChange(event){
|
||||
let tracks = this.player().textTracks();
|
||||
handleTracksChange(event) {
|
||||
const tracks = this.player().textTracks();
|
||||
let selected = true;
|
||||
|
||||
for (let i = 0, l = tracks.length; i < l; i++) {
|
||||
let track = tracks[i];
|
||||
if (track['kind'] === this.track['kind'] && track['mode'] === 'showing') {
|
||||
const track = tracks[i];
|
||||
|
||||
if (track.kind === this.track.kind && track.mode === 'showing') {
|
||||
selected = false;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@ import Component from '../../component.js';
|
||||
*/
|
||||
class SubtitlesButton extends TextTrackButton {
|
||||
|
||||
constructor(player, options, ready){
|
||||
constructor(player, options, ready) {
|
||||
super(player, options, ready);
|
||||
this.el_.setAttribute('aria-label','Subtitles Menu');
|
||||
this.el_.setAttribute('aria-label', 'Subtitles Menu');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*/
|
||||
import TrackButton from '../track-button.js';
|
||||
import Component from '../../component.js';
|
||||
import * as Fn from '../../utils/fn.js';
|
||||
import TextTrackMenuItem from './text-track-menu-item.js';
|
||||
import OffTextTrackMenuItem from './off-text-track-menu-item.js';
|
||||
|
||||
@@ -17,7 +16,7 @@ import OffTextTrackMenuItem from './off-text-track-menu-item.js';
|
||||
*/
|
||||
class TextTrackButton extends TrackButton {
|
||||
|
||||
constructor(player, options = {}){
|
||||
constructor(player, options = {}) {
|
||||
options.tracks = player.textTracks();
|
||||
|
||||
super(player, options);
|
||||
@@ -29,25 +28,25 @@ class TextTrackButton extends TrackButton {
|
||||
* @return {Array} Array of menu items
|
||||
* @method createItems
|
||||
*/
|
||||
createItems(items=[]) {
|
||||
createItems(items = []) {
|
||||
// Add an OFF menu item to turn all tracks off
|
||||
items.push(new OffTextTrackMenuItem(this.player_, { 'kind': this.kind_ }));
|
||||
items.push(new OffTextTrackMenuItem(this.player_, {kind: this.kind_}));
|
||||
|
||||
let tracks = this.player_.textTracks();
|
||||
const tracks = this.player_.textTracks();
|
||||
|
||||
if (!tracks) {
|
||||
return items;
|
||||
}
|
||||
|
||||
for (let i = 0; i < tracks.length; i++) {
|
||||
let track = tracks[i];
|
||||
const track = tracks[i];
|
||||
|
||||
// only add tracks that are of the appropriate kind and have a label
|
||||
if (track['kind'] === this.kind_) {
|
||||
if (track.kind === this.kind_) {
|
||||
items.push(new TextTrackMenuItem(this.player_, {
|
||||
track,
|
||||
// MenuItem is selectable
|
||||
'selectable': true,
|
||||
'track': track
|
||||
selectable: true
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,20 +17,20 @@ import document from 'global/document';
|
||||
*/
|
||||
class TextTrackMenuItem extends MenuItem {
|
||||
|
||||
constructor(player, options){
|
||||
let track = options['track'];
|
||||
let tracks = player.textTracks();
|
||||
constructor(player, options) {
|
||||
const track = options.track;
|
||||
const tracks = player.textTracks();
|
||||
|
||||
// Modify options for parent MenuItem class's init.
|
||||
options['label'] = track['label'] || track['language'] || 'Unknown';
|
||||
options['selected'] = track['default'] || track['mode'] === 'showing';
|
||||
options.label = track.label || track.language || 'Unknown';
|
||||
options.selected = track.default || track.mode === 'showing';
|
||||
|
||||
super(player, options);
|
||||
|
||||
this.track = track;
|
||||
|
||||
if (tracks) {
|
||||
let changeHandler = Fn.bind(this, this.handleTracksChange);
|
||||
const changeHandler = Fn.bind(this, this.handleTracksChange);
|
||||
|
||||
tracks.addEventListener('change', changeHandler);
|
||||
this.on('dispose', function() {
|
||||
@@ -52,7 +52,9 @@ class TextTrackMenuItem extends MenuItem {
|
||||
// Android 2.3 throws an Illegal Constructor error for window.Event
|
||||
try {
|
||||
event = new window.Event('change');
|
||||
} catch(err){}
|
||||
} catch (err) {
|
||||
// continue regardless of error
|
||||
}
|
||||
}
|
||||
|
||||
if (!event) {
|
||||
@@ -71,24 +73,26 @@ class TextTrackMenuItem extends MenuItem {
|
||||
* @method handleClick
|
||||
*/
|
||||
handleClick(event) {
|
||||
let kind = this.track['kind'];
|
||||
let tracks = this.player_.textTracks();
|
||||
const kind = this.track.kind;
|
||||
const tracks = this.player_.textTracks();
|
||||
|
||||
super.handleClick(event);
|
||||
|
||||
if (!tracks) return;
|
||||
if (!tracks) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0; i < tracks.length; i++) {
|
||||
let track = tracks[i];
|
||||
const track = tracks[i];
|
||||
|
||||
if (track['kind'] !== kind) {
|
||||
if (track.kind !== kind) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (track === this.track) {
|
||||
track['mode'] = 'showing';
|
||||
track.mode = 'showing';
|
||||
} else {
|
||||
track['mode'] = 'disabled';
|
||||
track.mode = 'disabled';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,8 +102,8 @@ class TextTrackMenuItem extends MenuItem {
|
||||
*
|
||||
* @method handleTracksChange
|
||||
*/
|
||||
handleTracksChange(event){
|
||||
this.selected(this.track['mode'] === 'showing');
|
||||
handleTracksChange(event) {
|
||||
this.selected(this.track.mode === 'showing');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import formatTime from '../../utils/format-time.js';
|
||||
*/
|
||||
class CurrentTimeDisplay extends Component {
|
||||
|
||||
constructor(player, options){
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
|
||||
this.on(player, 'timeupdate', this.updateContent);
|
||||
@@ -28,14 +28,14 @@ class CurrentTimeDisplay extends Component {
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
let el = super.createEl('div', {
|
||||
const el = super.createEl('div', {
|
||||
className: 'vjs-current-time vjs-time-control vjs-control'
|
||||
});
|
||||
|
||||
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',
|
||||
innerHTML: '<span class="vjs-control-text">Current Time </span>' + '0:00'
|
||||
}, {
|
||||
// tell screen readers not to automatically read the time as it changes
|
||||
'aria-live': 'off'
|
||||
@@ -52,9 +52,10 @@ class CurrentTimeDisplay extends Component {
|
||||
*/
|
||||
updateContent() {
|
||||
// Allows for smooth scrubbing, when player can't keep up.
|
||||
let time = (this.player_.scrubbing()) ? this.player_.getCache().currentTime : this.player_.currentTime();
|
||||
let localizedText = this.localize('Current Time');
|
||||
let formattedTime = formatTime(time, this.player_.duration());
|
||||
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}`;
|
||||
|
||||
@@ -15,7 +15,7 @@ import formatTime from '../../utils/format-time.js';
|
||||
*/
|
||||
class DurationDisplay extends Component {
|
||||
|
||||
constructor(player, options){
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
|
||||
this.on(player, 'durationchange', this.updateContent);
|
||||
@@ -28,7 +28,7 @@ class DurationDisplay extends Component {
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
let el = super.createEl('div', {
|
||||
const el = super.createEl('div', {
|
||||
className: 'vjs-duration vjs-time-control vjs-control'
|
||||
});
|
||||
|
||||
@@ -51,12 +51,15 @@ class DurationDisplay extends Component {
|
||||
* @method updateContent
|
||||
*/
|
||||
updateContent() {
|
||||
let duration = this.player_.duration();
|
||||
const duration = this.player_.duration();
|
||||
|
||||
if (duration && this.duration_ !== duration) {
|
||||
this.duration_ = duration;
|
||||
let localizedText = this.localize('Duration Time');
|
||||
let formattedTime = formatTime(duration);
|
||||
this.contentEl_.innerHTML = `<span class="vjs-control-text">${localizedText}</span> ${formattedTime}`; // label the duration time for screen reader users
|
||||
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}`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import formatTime from '../../utils/format-time.js';
|
||||
*/
|
||||
class RemainingTimeDisplay extends Component {
|
||||
|
||||
constructor(player, options){
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
|
||||
this.on(player, 'timeupdate', this.updateContent);
|
||||
@@ -29,14 +29,14 @@ class RemainingTimeDisplay extends Component {
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
let el = super.createEl('div', {
|
||||
const el = super.createEl('div', {
|
||||
className: 'vjs-remaining-time vjs-time-control vjs-control'
|
||||
});
|
||||
|
||||
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`,
|
||||
innerHTML: `<span class="vjs-control-text">${this.localize('Remaining Time')}</span> -0:00`
|
||||
}, {
|
||||
// tell screen readers not to automatically read the time as it changes
|
||||
'aria-live': 'off'
|
||||
@@ -55,6 +55,7 @@ class RemainingTimeDisplay extends Component {
|
||||
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}`;
|
||||
|
||||
@@ -15,8 +15,8 @@ import * as Fn from '../utils/fn.js';
|
||||
*/
|
||||
class TrackButton extends MenuButton {
|
||||
|
||||
constructor(player, options){
|
||||
let tracks = options.tracks;
|
||||
constructor(player, options) {
|
||||
const tracks = options.tracks;
|
||||
|
||||
super(player, options);
|
||||
|
||||
@@ -28,7 +28,8 @@ class TrackButton extends MenuButton {
|
||||
return;
|
||||
}
|
||||
|
||||
let updateHandler = Fn.bind(this, this.update);
|
||||
const updateHandler = Fn.bind(this, this.update);
|
||||
|
||||
tracks.addEventListener('removetrack', updateHandler);
|
||||
tracks.addEventListener('addtrack', updateHandler);
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import Component from '../../component.js';
|
||||
import * as Fn from '../../utils/fn.js';
|
||||
|
||||
// Required children
|
||||
import VolumeLevel from './volume-level.js';
|
||||
import './volume-level.js';
|
||||
|
||||
/**
|
||||
* The bar that contains the volume level and can be clicked on to adjust the level
|
||||
@@ -18,7 +18,7 @@ import VolumeLevel from './volume-level.js';
|
||||
*/
|
||||
class VolumeBar extends Slider {
|
||||
|
||||
constructor(player, options){
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
this.on(player, 'volumechange', this.updateARIAAttributes);
|
||||
player.ready(Fn.bind(this, this.updateARIAAttributes));
|
||||
@@ -63,9 +63,8 @@ class VolumeBar extends Slider {
|
||||
getPercent() {
|
||||
if (this.player_.muted()) {
|
||||
return 0;
|
||||
} else {
|
||||
return this.player_.volume();
|
||||
}
|
||||
return this.player_.volume();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,7 +94,8 @@ class VolumeBar extends Slider {
|
||||
*/
|
||||
updateARIAAttributes() {
|
||||
// Current value of volume bar as a percentage
|
||||
let volume = (this.player_.volume() * 100).toFixed(2);
|
||||
const volume = (this.player_.volume() * 100).toFixed(2);
|
||||
|
||||
this.el_.setAttribute('aria-valuenow', volume);
|
||||
this.el_.setAttribute('aria-valuetext', volume + '%');
|
||||
}
|
||||
@@ -106,7 +106,7 @@ VolumeBar.prototype.options_ = {
|
||||
children: [
|
||||
'volumeLevel'
|
||||
],
|
||||
'barName': 'volumeLevel'
|
||||
barName: 'volumeLevel'
|
||||
};
|
||||
|
||||
VolumeBar.prototype.playerEvent = 'volumechange';
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import Component from '../../component.js';
|
||||
|
||||
// Required children
|
||||
import VolumeBar from './volume-bar.js';
|
||||
import './volume-bar.js';
|
||||
|
||||
/**
|
||||
* The component for controlling the volume level
|
||||
@@ -16,15 +16,15 @@ import VolumeBar from './volume-bar.js';
|
||||
*/
|
||||
class VolumeControl extends Component {
|
||||
|
||||
constructor(player, options){
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
|
||||
// hide volume controls when they're not supported by the current tech
|
||||
if (player.tech_ && player.tech_['featuresVolumeControl'] === false) {
|
||||
if (player.tech_ && player.tech_.featuresVolumeControl === false) {
|
||||
this.addClass('vjs-hidden');
|
||||
}
|
||||
this.on(player, 'loadstart', function(){
|
||||
if (player.tech_['featuresVolumeControl'] === false) {
|
||||
this.on(player, 'loadstart', function() {
|
||||
if (player.tech_.featuresVolumeControl === false) {
|
||||
this.addClass('vjs-hidden');
|
||||
} else {
|
||||
this.removeClass('vjs-hidden');
|
||||
|
||||
@@ -18,7 +18,7 @@ import VolumeBar from './volume-control/volume-bar.js';
|
||||
*/
|
||||
class VolumeMenuButton extends PopupButton {
|
||||
|
||||
constructor(player, options={}){
|
||||
constructor(player, options = {}) {
|
||||
// Default to inline
|
||||
if (options.inline === undefined) {
|
||||
options.inline = true;
|
||||
@@ -48,7 +48,7 @@ class VolumeMenuButton extends PopupButton {
|
||||
|
||||
// hide mute toggle if the current tech doesn't support volume control
|
||||
function updateVisibility() {
|
||||
if (player.tech_ && player.tech_['featuresVolumeControl'] === false) {
|
||||
if (player.tech_ && player.tech_.featuresVolumeControl === false) {
|
||||
this.addClass('vjs-hidden');
|
||||
} else {
|
||||
this.removeClass('vjs-hidden');
|
||||
@@ -58,19 +58,19 @@ class VolumeMenuButton extends PopupButton {
|
||||
updateVisibility.call(this);
|
||||
this.on(player, 'loadstart', updateVisibility);
|
||||
|
||||
this.on(this.volumeBar, ['slideractive', 'focus'], function(){
|
||||
this.on(this.volumeBar, ['slideractive', 'focus'], function() {
|
||||
this.addClass('vjs-slider-active');
|
||||
});
|
||||
|
||||
this.on(this.volumeBar, ['sliderinactive', 'blur'], function(){
|
||||
this.on(this.volumeBar, ['sliderinactive', 'blur'], function() {
|
||||
this.removeClass('vjs-slider-active');
|
||||
});
|
||||
|
||||
this.on(this.volumeBar, ['focus'], function(){
|
||||
this.on(this.volumeBar, ['focus'], function() {
|
||||
this.addClass('vjs-lock-showing');
|
||||
});
|
||||
|
||||
this.on(this.volumeBar, ['blur'], function(){
|
||||
this.on(this.volumeBar, ['blur'], function() {
|
||||
this.removeClass('vjs-lock-showing');
|
||||
});
|
||||
}
|
||||
@@ -83,7 +83,8 @@ class VolumeMenuButton extends PopupButton {
|
||||
*/
|
||||
buildCSSClass() {
|
||||
let orientationClass = '';
|
||||
if (!!this.options_.vertical) {
|
||||
|
||||
if (this.options_.vertical) {
|
||||
orientationClass = 'vjs-volume-menu-button-vertical';
|
||||
} else {
|
||||
orientationClass = 'vjs-volume-menu-button-horizontal';
|
||||
@@ -99,11 +100,11 @@ class VolumeMenuButton extends PopupButton {
|
||||
* @method createPopup
|
||||
*/
|
||||
createPopup() {
|
||||
let popup = new Popup(this.player_, {
|
||||
const popup = new Popup(this.player_, {
|
||||
contentElType: 'div'
|
||||
});
|
||||
|
||||
let vb = new VolumeBar(this.player_, this.options_.volumeBar);
|
||||
const vb = new VolumeBar(this.player_, this.options_.volumeBar);
|
||||
|
||||
popup.addChild(vb);
|
||||
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
*/
|
||||
import Component from './component';
|
||||
import ModalDialog from './modal-dialog';
|
||||
|
||||
import * as Dom from './utils/dom';
|
||||
import mergeOptions from './utils/merge-options';
|
||||
|
||||
/**
|
||||
@@ -45,7 +43,8 @@ class ErrorDisplay extends ModalDialog {
|
||||
* @return {String|Null}
|
||||
*/
|
||||
content() {
|
||||
let error = this.player().error();
|
||||
const error = this.player().error();
|
||||
|
||||
return error ? this.localize(error.message) : '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,41 +3,43 @@
|
||||
*/
|
||||
import * as Events from './utils/events.js';
|
||||
|
||||
var EventTarget = function() {};
|
||||
const EventTarget = function() {};
|
||||
|
||||
EventTarget.prototype.allowedEvents_ = {};
|
||||
|
||||
EventTarget.prototype.on = function(type, fn) {
|
||||
// Remove the addEventListener alias before calling Events.on
|
||||
// so we don't get into an infinite type loop
|
||||
let ael = this.addEventListener;
|
||||
const ael = this.addEventListener;
|
||||
|
||||
this.addEventListener = () => {};
|
||||
Events.on(this, type, fn);
|
||||
this.addEventListener = ael;
|
||||
};
|
||||
|
||||
EventTarget.prototype.addEventListener = EventTarget.prototype.on;
|
||||
|
||||
EventTarget.prototype.off = function(type, fn) {
|
||||
Events.off(this, type, fn);
|
||||
};
|
||||
|
||||
EventTarget.prototype.removeEventListener = EventTarget.prototype.off;
|
||||
|
||||
EventTarget.prototype.one = function(type, fn) {
|
||||
// Remove the addEventListener alias before calling Events.on
|
||||
// so we don't get into an infinite type loop
|
||||
let ael = this.addEventListener;
|
||||
const ael = this.addEventListener;
|
||||
|
||||
this.addEventListener = () => {};
|
||||
Events.one(this, type, fn);
|
||||
this.addEventListener = ael;
|
||||
};
|
||||
|
||||
EventTarget.prototype.trigger = function(event) {
|
||||
let type = event.type || event;
|
||||
const type = event.type || event;
|
||||
|
||||
if (typeof event === 'string') {
|
||||
event = {
|
||||
type: type
|
||||
};
|
||||
event = {type};
|
||||
}
|
||||
event = Events.fixEvent(event);
|
||||
|
||||
@@ -47,6 +49,7 @@ EventTarget.prototype.trigger = function(event) {
|
||||
|
||||
Events.trigger(this, event);
|
||||
};
|
||||
|
||||
// The standard DOM EventTarget.dispatchEvent() is aliased to trigger()
|
||||
EventTarget.prototype.dispatchEvent = EventTarget.prototype.trigger;
|
||||
|
||||
|
||||
+4
-3
@@ -7,7 +7,7 @@ import log from './utils/log';
|
||||
* Both work the same but node adds `super_` to the subClass
|
||||
* and Bable adds the superClass as __proto__. Both seem useful.
|
||||
*/
|
||||
const _inherits = function (subClass, superClass) {
|
||||
const _inherits = function(subClass, superClass) {
|
||||
if (typeof superClass !== 'function' && superClass !== null) {
|
||||
throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass);
|
||||
}
|
||||
@@ -44,10 +44,11 @@ const _inherits = function (subClass, superClass) {
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
const extendFn = function(superClass, subClassMethods={}) {
|
||||
const extendFn = function(superClass, subClassMethods = {}) {
|
||||
let subClass = function() {
|
||||
superClass.apply(this, arguments);
|
||||
};
|
||||
|
||||
let methods = {};
|
||||
|
||||
if (typeof subClassMethods === 'object') {
|
||||
@@ -66,7 +67,7 @@ const extendFn = function(superClass, subClassMethods={}) {
|
||||
_inherits(subClass, superClass);
|
||||
|
||||
// Extend subObj's prototype with functions and other properties from props
|
||||
for (var name in methods) {
|
||||
for (const name in methods) {
|
||||
if (methods.hasOwnProperty(name)) {
|
||||
subClass.prototype[name] = methods[name];
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import document from 'global/document';
|
||||
* @type {Object|undefined}
|
||||
* @private
|
||||
*/
|
||||
let FullscreenApi = {};
|
||||
const FullscreenApi = {};
|
||||
|
||||
// browser API methods
|
||||
// map approach from Screenful.js - https://github.com/sindresorhus/screenfull.js
|
||||
@@ -60,7 +60,7 @@ const apiMap = [
|
||||
]
|
||||
];
|
||||
|
||||
let specApi = apiMap[0];
|
||||
const specApi = apiMap[0];
|
||||
let browserApi;
|
||||
|
||||
// determine the supported set of functions
|
||||
@@ -74,7 +74,7 @@ for (let i = 0; i < apiMap.length; i++) {
|
||||
|
||||
// map the browser API names to the spec API names
|
||||
if (browserApi) {
|
||||
for (let i=0; i<browserApi.length; i++) {
|
||||
for (let i = 0; i < browserApi.length; i++) {
|
||||
FullscreenApi[specApi[i]] = browserApi[i];
|
||||
}
|
||||
}
|
||||
|
||||
+40
-17
@@ -4,24 +4,45 @@
|
||||
import assign from 'object.assign';
|
||||
|
||||
/*
|
||||
* Custom MediaError to mimic the HTML5 MediaError
|
||||
* Custom MediaError class which mimics the standard HTML5 MediaError class.
|
||||
*
|
||||
* @param {Number} code The media error code
|
||||
* @param {Number|String|Object|MediaError} value
|
||||
* This can be of multiple types:
|
||||
* - Number: should be a standard error code
|
||||
* - String: an error message (the code will be 0)
|
||||
* - Object: arbitrary properties
|
||||
* - MediaError (native): used to populate a video.js MediaError object
|
||||
* - MediaError (video.js): will return itself if it's already a
|
||||
* video.js MediaError object.
|
||||
*/
|
||||
let MediaError = function(code){
|
||||
if (typeof code === 'number') {
|
||||
this.code = code;
|
||||
} else if (typeof code === 'string') {
|
||||
function MediaError(value) {
|
||||
|
||||
// Allow redundant calls to this constructor to avoid having `instanceof`
|
||||
// checks peppered around the code.
|
||||
if (value instanceof MediaError) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (typeof value === 'number') {
|
||||
this.code = value;
|
||||
} else if (typeof value === 'string') {
|
||||
// default code is zero, so this is a custom error
|
||||
this.message = code;
|
||||
} else if (typeof code === 'object') { // object
|
||||
assign(this, code);
|
||||
this.message = value;
|
||||
} else if (typeof value === 'object') {
|
||||
|
||||
// We assign the `code` property manually because native MediaError objects
|
||||
// do not expose it as an own/enumerable property of the object.
|
||||
if (typeof value.code === 'number') {
|
||||
this.code = value.code;
|
||||
}
|
||||
|
||||
assign(this, value);
|
||||
}
|
||||
|
||||
if (!this.message) {
|
||||
this.message = MediaError.defaultMessages[this.code] || '';
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* The error code that refers two one of the defined
|
||||
@@ -52,13 +73,15 @@ MediaError.prototype.message = '';
|
||||
*/
|
||||
MediaError.prototype.status = null;
|
||||
|
||||
// These errors are indexed by the W3C standard numeric value. The order
|
||||
// should not be changed!
|
||||
MediaError.errorTypes = [
|
||||
'MEDIA_ERR_CUSTOM', // = 0
|
||||
'MEDIA_ERR_ABORTED', // = 1
|
||||
'MEDIA_ERR_NETWORK', // = 2
|
||||
'MEDIA_ERR_DECODE', // = 3
|
||||
'MEDIA_ERR_SRC_NOT_SUPPORTED', // = 4
|
||||
'MEDIA_ERR_ENCRYPTED' // = 5
|
||||
'MEDIA_ERR_CUSTOM',
|
||||
'MEDIA_ERR_ABORTED',
|
||||
'MEDIA_ERR_NETWORK',
|
||||
'MEDIA_ERR_DECODE',
|
||||
'MEDIA_ERR_SRC_NOT_SUPPORTED',
|
||||
'MEDIA_ERR_ENCRYPTED'
|
||||
];
|
||||
|
||||
MediaError.defaultMessages = {
|
||||
@@ -71,7 +94,7 @@ MediaError.defaultMessages = {
|
||||
|
||||
// Add types as properties on MediaError
|
||||
// e.g. MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED = 4;
|
||||
for (var errNum = 0; errNum < MediaError.errorTypes.length; errNum++) {
|
||||
for (let errNum = 0; errNum < MediaError.errorTypes.length; errNum++) {
|
||||
MediaError[MediaError.errorTypes[errNum]] = errNum;
|
||||
// values should be accessible on both the class and instance
|
||||
MediaError.prototype[MediaError.errorTypes[errNum]] = errNum;
|
||||
|
||||
@@ -18,7 +18,7 @@ import toTitleCase from '../utils/to-title-case.js';
|
||||
*/
|
||||
class MenuButton extends ClickableComponent {
|
||||
|
||||
constructor(player, options={}){
|
||||
constructor(player, options = {}) {
|
||||
super(player, options);
|
||||
|
||||
this.update();
|
||||
@@ -36,7 +36,7 @@ class MenuButton extends ClickableComponent {
|
||||
* @method update
|
||||
*/
|
||||
update() {
|
||||
let menu = this.createMenu();
|
||||
const menu = this.createMenu();
|
||||
|
||||
if (this.menu) {
|
||||
this.removeChild(this.menu);
|
||||
@@ -68,24 +68,25 @@ class MenuButton extends ClickableComponent {
|
||||
* @method createMenu
|
||||
*/
|
||||
createMenu() {
|
||||
var menu = new Menu(this.player_);
|
||||
const menu = new Menu(this.player_);
|
||||
|
||||
// Add a title list item to the top
|
||||
if (this.options_.title) {
|
||||
let title = Dom.createEl('li', {
|
||||
const title = Dom.createEl('li', {
|
||||
className: 'vjs-menu-title',
|
||||
innerHTML: toTitleCase(this.options_.title),
|
||||
tabIndex: -1
|
||||
});
|
||||
|
||||
menu.children_.unshift(title);
|
||||
Dom.insertElFirst(title, menu.contentEl());
|
||||
}
|
||||
|
||||
this.items = this['createItems']();
|
||||
this.items = this.createItems();
|
||||
|
||||
if (this.items) {
|
||||
// Add menu items to the menu
|
||||
for (var i = 0; i < this.items.length; i++) {
|
||||
for (let i = 0; i < this.items.length; i++) {
|
||||
menu.addItem(this.items[i]);
|
||||
}
|
||||
}
|
||||
@@ -98,7 +99,7 @@ class MenuButton extends ClickableComponent {
|
||||
*
|
||||
* @method createItems
|
||||
*/
|
||||
createItems(){}
|
||||
createItems() {}
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
@@ -119,7 +120,7 @@ class MenuButton extends ClickableComponent {
|
||||
* @method buildCSSClass
|
||||
*/
|
||||
buildCSSClass() {
|
||||
var menuButtonClass = 'vjs-menu-button';
|
||||
let menuButtonClass = 'vjs-menu-button';
|
||||
|
||||
// If the inline option is passed, we want to use different styles altogether.
|
||||
if (this.options_.inline === true) {
|
||||
@@ -141,11 +142,11 @@ class MenuButton extends ClickableComponent {
|
||||
* @method handleClick
|
||||
*/
|
||||
handleClick() {
|
||||
this.one(this.menu.contentEl(), 'mouseleave', Fn.bind(this, function(e){
|
||||
this.one(this.menu.contentEl(), 'mouseleave', Fn.bind(this, function(e) {
|
||||
this.unpressButton();
|
||||
this.el_.blur();
|
||||
}));
|
||||
if (this.buttonPressed_){
|
||||
if (this.buttonPressed_) {
|
||||
this.unpressButton();
|
||||
} else {
|
||||
this.pressButton();
|
||||
@@ -189,8 +190,8 @@ class MenuButton extends ClickableComponent {
|
||||
handleSubmenuKeyPress(event) {
|
||||
|
||||
// Escape (27) key or Tab (9) key unpress the 'button'
|
||||
if (event.which === 27 || event.which === 9){
|
||||
if (this.buttonPressed_){
|
||||
if (event.which === 27 || event.which === 9) {
|
||||
if (this.buttonPressed_) {
|
||||
this.unpressButton();
|
||||
}
|
||||
// Don't preventDefault for Tab key - we still want to lose focus
|
||||
@@ -210,7 +211,8 @@ class MenuButton extends ClickableComponent {
|
||||
this.buttonPressed_ = true;
|
||||
this.menu.lockShowing();
|
||||
this.el_.setAttribute('aria-expanded', 'true');
|
||||
this.menu.focus(); // set the focus into the submenu
|
||||
// set the focus into the submenu
|
||||
this.menu.focus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,7 +226,8 @@ class MenuButton extends ClickableComponent {
|
||||
this.buttonPressed_ = false;
|
||||
this.menu.unlockShowing();
|
||||
this.el_.setAttribute('aria-expanded', 'false');
|
||||
this.el_.focus(); // Set focus back to this menu button
|
||||
// Set focus back to this menu button
|
||||
this.el_.focus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,9 +18,9 @@ class MenuItem extends ClickableComponent {
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
|
||||
this.selectable = options['selectable'];
|
||||
this.selectable = options.selectable;
|
||||
|
||||
this.selected(options['selected']);
|
||||
this.selected(options.selected);
|
||||
|
||||
if (this.selectable) {
|
||||
// TODO: May need to be either menuitemcheckbox or menuitemradio,
|
||||
@@ -42,7 +42,7 @@ class MenuItem extends ClickableComponent {
|
||||
createEl(type, props, attrs) {
|
||||
return super.createEl('li', assign({
|
||||
className: 'vjs-menu-item',
|
||||
innerHTML: this.localize(this.options_['label']),
|
||||
innerHTML: this.localize(this.options_.label),
|
||||
tabIndex: -1
|
||||
}, props), attrs);
|
||||
}
|
||||
@@ -66,13 +66,13 @@ class MenuItem extends ClickableComponent {
|
||||
if (this.selectable) {
|
||||
if (selected) {
|
||||
this.addClass('vjs-selected');
|
||||
this.el_.setAttribute('aria-checked','true');
|
||||
this.el_.setAttribute('aria-checked', 'true');
|
||||
// aria-checked isn't fully supported by browsers/screen readers,
|
||||
// so indicate selected state to screen reader in the control text.
|
||||
this.controlText(', selected');
|
||||
} else {
|
||||
this.removeClass('vjs-selected');
|
||||
this.el_.setAttribute('aria-checked','false');
|
||||
this.el_.setAttribute('aria-checked', 'false');
|
||||
// Indicate un-selected state to screen reader
|
||||
// Note that a space clears out the selected state text
|
||||
this.controlText(' ');
|
||||
|
||||
+33
-26
@@ -15,7 +15,7 @@ import * as Events from '../utils/events.js';
|
||||
*/
|
||||
class Menu extends Component {
|
||||
|
||||
constructor (player, options) {
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
|
||||
this.focusedChild_ = -1;
|
||||
@@ -31,9 +31,9 @@ class Menu extends Component {
|
||||
*/
|
||||
addItem(component) {
|
||||
this.addChild(component);
|
||||
component.on('click', Fn.bind(this, function(){
|
||||
component.on('click', Fn.bind(this, function() {
|
||||
this.unlockShowing();
|
||||
//TODO: Need to set keyboard focus back to the menuButton
|
||||
// TODO: Need to set keyboard focus back to the menuButton
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -44,21 +44,25 @@ class Menu extends Component {
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
let contentElType = this.options_.contentElType || 'ul';
|
||||
const contentElType = this.options_.contentElType || 'ul';
|
||||
|
||||
this.contentEl_ = Dom.createEl(contentElType, {
|
||||
className: 'vjs-menu-content'
|
||||
});
|
||||
|
||||
this.contentEl_.setAttribute('role', 'menu');
|
||||
var el = super.createEl('div', {
|
||||
|
||||
const el = super.createEl('div', {
|
||||
append: this.contentEl_,
|
||||
className: 'vjs-menu'
|
||||
});
|
||||
|
||||
el.setAttribute('role', 'presentation');
|
||||
el.appendChild(this.contentEl_);
|
||||
|
||||
// Prevent clicks from bubbling up. Needed for Menu Buttons,
|
||||
// where a click on the parent is significant
|
||||
Events.on(el, 'click', function(event){
|
||||
Events.on(el, 'click', function(event) {
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
});
|
||||
@@ -72,11 +76,14 @@ class Menu extends Component {
|
||||
* @param {Object} event Event object
|
||||
* @method handleKeyPress
|
||||
*/
|
||||
handleKeyPress (event) {
|
||||
if (event.which === 37 || event.which === 40) { // Left and Down Arrows
|
||||
handleKeyPress(event) {
|
||||
// Left and Down Arrows
|
||||
if (event.which === 37 || event.which === 40) {
|
||||
event.preventDefault();
|
||||
this.stepForward();
|
||||
} else if (event.which === 38 || event.which === 39) { // Up and Right Arrows
|
||||
|
||||
// Up and Right Arrows
|
||||
} else if (event.which === 38 || event.which === 39) {
|
||||
event.preventDefault();
|
||||
this.stepBack();
|
||||
}
|
||||
@@ -87,21 +94,21 @@ class Menu extends Component {
|
||||
*
|
||||
* @method stepForward
|
||||
*/
|
||||
stepForward () {
|
||||
let stepChild = 0;
|
||||
stepForward() {
|
||||
let stepChild = 0;
|
||||
|
||||
if (this.focusedChild_ !== undefined) {
|
||||
stepChild = this.focusedChild_ + 1;
|
||||
}
|
||||
this.focus(stepChild);
|
||||
}
|
||||
if (this.focusedChild_ !== undefined) {
|
||||
stepChild = this.focusedChild_ + 1;
|
||||
}
|
||||
this.focus(stepChild);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move to previous (higher) menu item for keyboard users
|
||||
*
|
||||
* @method stepBack
|
||||
*/
|
||||
stepBack () {
|
||||
/**
|
||||
* Move to previous (higher) menu item for keyboard users
|
||||
*
|
||||
* @method stepBack
|
||||
*/
|
||||
stepBack() {
|
||||
let stepChild = 0;
|
||||
|
||||
if (this.focusedChild_ !== undefined) {
|
||||
@@ -116,10 +123,10 @@ class Menu extends Component {
|
||||
* @param {Object|String} item Index of child item set focus on
|
||||
* @method focus
|
||||
*/
|
||||
focus (item = 0) {
|
||||
let children = this.children().slice();
|
||||
let haveTitle = children.length && children[0].className &&
|
||||
/vjs-menu-title/.test(children[0].className);
|
||||
focus(item = 0) {
|
||||
const children = this.children().slice();
|
||||
const haveTitle = children.length && children[0].className &&
|
||||
(/vjs-menu-title/).test(children[0].className);
|
||||
|
||||
if (haveTitle) {
|
||||
children.shift();
|
||||
|
||||
@@ -3,10 +3,7 @@
|
||||
*/
|
||||
import * as Dom from './utils/dom';
|
||||
import * as Fn from './utils/fn';
|
||||
import log from './utils/log';
|
||||
|
||||
import Component from './component';
|
||||
import CloseButton from './close-button';
|
||||
|
||||
const MODAL_CLASS_NAME = 'vjs-modal-dialog';
|
||||
const ESC = 27;
|
||||
@@ -92,7 +89,7 @@ class ModalDialog extends Component {
|
||||
'aria-describedby': `${this.id()}_description`,
|
||||
'aria-hidden': 'true',
|
||||
'aria-label': this.label(),
|
||||
role: 'dialog'
|
||||
'role': 'dialog'
|
||||
});
|
||||
}
|
||||
|
||||
@@ -153,7 +150,7 @@ class ModalDialog extends Component {
|
||||
*/
|
||||
open() {
|
||||
if (!this.opened_) {
|
||||
let player = this.player();
|
||||
const player = this.player();
|
||||
|
||||
this.trigger('beforemodalopen');
|
||||
this.opened_ = true;
|
||||
@@ -209,7 +206,7 @@ class ModalDialog extends Component {
|
||||
*/
|
||||
close() {
|
||||
if (this.opened_) {
|
||||
let player = this.player();
|
||||
const player = this.player();
|
||||
|
||||
this.trigger('beforemodalclose');
|
||||
this.opened_ = false;
|
||||
@@ -245,7 +242,7 @@ class ModalDialog extends Component {
|
||||
*/
|
||||
closeable(value) {
|
||||
if (typeof value === 'boolean') {
|
||||
let closeable = this.closeable_ = !!value;
|
||||
const closeable = this.closeable_ = !!value;
|
||||
let close = this.getChild('closeButton');
|
||||
|
||||
// If this is being made closeable and has no close button, add one.
|
||||
@@ -253,7 +250,8 @@ class ModalDialog extends Component {
|
||||
|
||||
// The close button should be a child of the modal - not its
|
||||
// content element, so temporarily change the content element.
|
||||
let temp = this.contentEl_;
|
||||
const temp = this.contentEl_;
|
||||
|
||||
this.contentEl_ = this.el_;
|
||||
close = this.addChild('closeButton', {controlText: 'Close Modal Dialog'});
|
||||
this.contentEl_ = temp;
|
||||
@@ -294,9 +292,9 @@ class ModalDialog extends Component {
|
||||
* @return {ModalDialog}
|
||||
*/
|
||||
fillWith(content) {
|
||||
let contentEl = this.contentEl();
|
||||
let parentEl = contentEl.parentNode;
|
||||
let nextSiblingEl = contentEl.nextSibling;
|
||||
const contentEl = this.contentEl();
|
||||
const parentEl = contentEl.parentNode;
|
||||
const nextSiblingEl = contentEl.nextSibling;
|
||||
|
||||
this.trigger('beforemodalfill');
|
||||
this.hasBeenFilled_ = true;
|
||||
|
||||
+218
-166
@@ -22,23 +22,27 @@ import safeParseTuple from 'safe-json-parse/tuple';
|
||||
import assign from 'object.assign';
|
||||
import mergeOptions from './utils/merge-options.js';
|
||||
import textTrackConverter from './tracks/text-track-list-converter.js';
|
||||
import ModalDialog from './modal-dialog';
|
||||
import Tech from './tech/tech.js';
|
||||
import AudioTrackList from './tracks/audio-track-list.js';
|
||||
import VideoTrackList from './tracks/video-track-list.js';
|
||||
|
||||
// Include required child components (importing also registers them)
|
||||
import MediaLoader from './tech/loader.js';
|
||||
import PosterImage from './poster-image.js';
|
||||
import TextTrackDisplay from './tracks/text-track-display.js';
|
||||
import LoadingSpinner from './loading-spinner.js';
|
||||
import BigPlayButton from './big-play-button.js';
|
||||
import ControlBar from './control-bar/control-bar.js';
|
||||
import ErrorDisplay from './error-display.js';
|
||||
import TextTrackSettings from './tracks/text-track-settings.js';
|
||||
import ModalDialog from './modal-dialog';
|
||||
// The following imports are used only to ensure that the corresponding modules
|
||||
// are always included in the video.js package. Importing the modules will
|
||||
// execute them and they will register themselves with video.js.
|
||||
import './tech/loader.js';
|
||||
import './tech/flash.js';
|
||||
import './poster-image.js';
|
||||
import './tracks/text-track-display.js';
|
||||
import './loading-spinner.js';
|
||||
import './big-play-button.js';
|
||||
import './close-button.js';
|
||||
import './control-bar/control-bar.js';
|
||||
import './error-display.js';
|
||||
import './tracks/text-track-settings.js';
|
||||
|
||||
// Require html5 tech, at least for disposing the original video tag
|
||||
import Tech from './tech/tech.js';
|
||||
import Html5 from './tech/html5.js';
|
||||
// Import Html5 tech, at least for disposing the original video tag.
|
||||
import './tech/html5.js';
|
||||
|
||||
/**
|
||||
* An instance of the `Player` class is created when any of the Video.js setup methods are used to initialize a video.
|
||||
@@ -70,7 +74,7 @@ class Player extends Component {
|
||||
* @param {Object=} options Player options
|
||||
* @param {Function=} ready Ready callback function
|
||||
*/
|
||||
constructor(tag, options, ready){
|
||||
constructor(tag, options, ready) {
|
||||
// Make sure tag ID exists
|
||||
tag.id = tag.id || `vjs_video_${Guid.newGUID()}`;
|
||||
|
||||
@@ -95,12 +99,14 @@ class Player extends Component {
|
||||
// If language is not set, get the closest lang attribute
|
||||
if (!options.language) {
|
||||
if (typeof tag.closest === 'function') {
|
||||
let closest = tag.closest('[lang]');
|
||||
const closest = tag.closest('[lang]');
|
||||
|
||||
if (closest) {
|
||||
options.language = closest.getAttribute('lang');
|
||||
}
|
||||
} else {
|
||||
let element = tag;
|
||||
|
||||
while (element && element.nodeType === 1) {
|
||||
if (Dom.getElAttributes(element).hasOwnProperty('lang')) {
|
||||
options.language = element.getAttribute('lang');
|
||||
@@ -124,7 +130,8 @@ class Player extends Component {
|
||||
'properties you want to override?');
|
||||
}
|
||||
|
||||
this.tag = tag; // Store the original tag used to set options
|
||||
// Store the original tag used to set options
|
||||
this.tag = tag;
|
||||
|
||||
// Store the tag attributes used to restore html5 element
|
||||
this.tagAttributes = tag && Dom.getElAttributes(tag);
|
||||
@@ -135,7 +142,7 @@ class Player extends Component {
|
||||
// Update Supported Languages
|
||||
if (options.languages) {
|
||||
// Normalise player option languages to lowercase
|
||||
let languagesToLower = {};
|
||||
const languagesToLower = {};
|
||||
|
||||
Object.getOwnPropertyNames(options.languages).forEach(function(name) {
|
||||
languagesToLower[name.toLowerCase()] = options.languages[name];
|
||||
@@ -173,13 +180,13 @@ class Player extends Component {
|
||||
// as well so they don't need to reach back into the player for options later.
|
||||
// We also need to do another copy of this.options_ so we don't end up with
|
||||
// an infinite loop.
|
||||
let playerOptionsCopy = mergeOptions(this.options_);
|
||||
const playerOptionsCopy = mergeOptions(this.options_);
|
||||
|
||||
// Load plugins
|
||||
if (options.plugins) {
|
||||
let plugins = options.plugins;
|
||||
const plugins = options.plugins;
|
||||
|
||||
Object.getOwnPropertyNames(plugins).forEach(function(name){
|
||||
Object.getOwnPropertyNames(plugins).forEach(function(name) {
|
||||
if (typeof this[name] === 'function') {
|
||||
this[name](plugins[name]);
|
||||
} else {
|
||||
@@ -264,10 +271,18 @@ class Player extends Component {
|
||||
|
||||
// Kill reference to this player
|
||||
Player.players[this.id_] = null;
|
||||
if (this.tag && this.tag.player) { this.tag.player = null; }
|
||||
if (this.el_ && this.el_.player) { this.el_.player = null; }
|
||||
|
||||
if (this.tech_) { this.tech_.dispose(); }
|
||||
if (this.tag && this.tag.player) {
|
||||
this.tag.player = null;
|
||||
}
|
||||
|
||||
if (this.el_ && this.el_.player) {
|
||||
this.el_.player = null;
|
||||
}
|
||||
|
||||
if (this.tech_) {
|
||||
this.tech_.dispose();
|
||||
}
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
@@ -279,8 +294,8 @@ class Player extends Component {
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
let el = this.el_ = super.createEl('div');
|
||||
let tag = this.tag;
|
||||
const el = this.el_ = super.createEl('div');
|
||||
const tag = this.tag;
|
||||
|
||||
// Remove width/height attrs from tag so CSS can make it 100% width/height
|
||||
tag.removeAttribute('width');
|
||||
@@ -290,7 +305,7 @@ class Player extends Component {
|
||||
// ID will now reference player box, not the video tag
|
||||
const attrs = Dom.getElAttributes(tag);
|
||||
|
||||
Object.getOwnPropertyNames(attrs).forEach(function(attr){
|
||||
Object.getOwnPropertyNames(attrs).forEach(function(attr) {
|
||||
// workaround so we don't totally break IE7
|
||||
// http://stackoverflow.com/questions/3653444/css-styles-not-applied-on-dynamic-elements-in-internet-explorer-7
|
||||
if (attr === 'class') {
|
||||
@@ -317,8 +332,9 @@ class Player extends Component {
|
||||
// video element
|
||||
if (window.VIDEOJS_NO_DYNAMIC_STYLE !== true) {
|
||||
this.styleEl_ = stylesheet.createStyleElement('vjs-styles-dimensions');
|
||||
let defaultsStyleEl = Dom.$('.vjs-styles-defaults');
|
||||
let head = Dom.$('head');
|
||||
const defaultsStyleEl = Dom.$('.vjs-styles-defaults');
|
||||
const head = Dom.$('head');
|
||||
|
||||
head.insertBefore(this.styleEl_, defaultsStyleEl ? defaultsStyleEl.nextSibling : head.firstChild);
|
||||
}
|
||||
|
||||
@@ -329,9 +345,11 @@ class Player extends Component {
|
||||
this.aspectRatio(this.options_.aspectRatio);
|
||||
|
||||
// Hide any links within the video/audio tag, because IE doesn't hide them completely.
|
||||
let links = tag.getElementsByTagName('a');
|
||||
const links = tag.getElementsByTagName('a');
|
||||
|
||||
for (let i = 0; i < links.length; i++) {
|
||||
let linkEl = links.item(i);
|
||||
const linkEl = links.item(i);
|
||||
|
||||
Dom.addElClass(linkEl, 'vjs-hidden');
|
||||
linkEl.setAttribute('hidden', 'hidden');
|
||||
}
|
||||
@@ -348,7 +366,9 @@ class Player extends Component {
|
||||
// insert the tag as the first child of the player element
|
||||
// then manually add it to the children array so that this.addChild
|
||||
// will work properly for other components
|
||||
Dom.insertElFirst(tag, el); // Breaks iPhone, fixed in HTML5 setup.
|
||||
//
|
||||
// Breaks iPhone, fixed in HTML5 setup.
|
||||
Dom.insertElFirst(tag, el);
|
||||
this.children_.unshift(tag);
|
||||
|
||||
this.el_ = el;
|
||||
@@ -387,7 +407,7 @@ class Player extends Component {
|
||||
* @method dimension
|
||||
*/
|
||||
dimension(dimension, value) {
|
||||
let privDimension = dimension + '_';
|
||||
const privDimension = dimension + '_';
|
||||
|
||||
if (value === undefined) {
|
||||
return this[privDimension] || 0;
|
||||
@@ -397,7 +417,7 @@ class Player extends Component {
|
||||
// If an empty string is given, reset the dimension to be automatic
|
||||
this[privDimension] = undefined;
|
||||
} else {
|
||||
let parsedVal = parseFloat(value);
|
||||
const parsedVal = parseFloat(value);
|
||||
|
||||
if (isNaN(parsedVal)) {
|
||||
log.error(`Improper value "${value}" supplied for for ${dimension}`);
|
||||
@@ -444,7 +464,7 @@ class Player extends Component {
|
||||
}
|
||||
|
||||
// Check for width:height format
|
||||
if (!/^\d+\:\d+$/.test(ratio)) {
|
||||
if (!(/^\d+\:\d+$/).test(ratio)) {
|
||||
throw new Error('Improper value supplied for aspect ratio. The format should be width:height, for example 16:9.');
|
||||
}
|
||||
this.aspectRatio_ = ratio;
|
||||
@@ -465,7 +485,7 @@ class Player extends Component {
|
||||
if (window.VIDEOJS_NO_DYNAMIC_STYLE === true) {
|
||||
const width = typeof this.width_ === 'number' ? this.width_ : this.options_.width;
|
||||
const height = typeof this.height_ === 'number' ? this.height_ : this.options_.height;
|
||||
let techEl = this.tech_ && this.tech_.el();
|
||||
const techEl = this.tech_ && this.tech_.el();
|
||||
|
||||
if (techEl) {
|
||||
if (width >= 0) {
|
||||
@@ -497,8 +517,8 @@ class Player extends Component {
|
||||
}
|
||||
|
||||
// Get the ratio as a decimal we can use to calculate dimensions
|
||||
let ratioParts = aspectRatio.split(':');
|
||||
let ratioMultiplier = ratioParts[1] / ratioParts[0];
|
||||
const ratioParts = aspectRatio.split(':');
|
||||
const ratioMultiplier = ratioParts[1] / ratioParts[0];
|
||||
|
||||
if (this.width_ !== undefined) {
|
||||
// Use any width that's been specifically set
|
||||
@@ -516,14 +536,14 @@ class Player extends Component {
|
||||
height = this.height_;
|
||||
} else {
|
||||
// Otherwise calculate the height from the ratio and the width
|
||||
height = width * ratioMultiplier;
|
||||
height = width * ratioMultiplier;
|
||||
}
|
||||
|
||||
// Ensure the CSS class is valid by starting with an alpha character
|
||||
if (/^[^a-zA-Z]/.test(this.id())) {
|
||||
idClass = 'dimensions-'+this.id();
|
||||
if ((/^[^a-zA-Z]/).test(this.id())) {
|
||||
idClass = 'dimensions-' + this.id();
|
||||
} else {
|
||||
idClass = this.id()+'-dimensions';
|
||||
idClass = this.id() + '-dimensions';
|
||||
}
|
||||
|
||||
// Ensure the right class is still on the player for the style element
|
||||
@@ -571,9 +591,9 @@ class Player extends Component {
|
||||
this.isReady_ = false;
|
||||
|
||||
// Grab tech-specific options from player options and add source and parent element to use.
|
||||
var techOptions = assign({
|
||||
const techOptions = assign({
|
||||
source,
|
||||
'nativeControlsForTouch': this.options_.nativeControlsForTouch,
|
||||
'source': source,
|
||||
'playerId': this.id(),
|
||||
'techId': `${this.id()}_${techName}_api`,
|
||||
'videoTracks': this.videoTracks_,
|
||||
@@ -602,13 +622,14 @@ class Player extends Component {
|
||||
}
|
||||
|
||||
// Initialize tech instance
|
||||
let techComponent = Tech.getTech(techName);
|
||||
let TechComponent = Tech.getTech(techName);
|
||||
|
||||
// Support old behavior of techs being registered as components.
|
||||
// Remove once that deprecated behavior is removed.
|
||||
if (!techComponent) {
|
||||
techComponent = Component.getComponent(techName);
|
||||
if (!TechComponent) {
|
||||
TechComponent = Component.getComponent(techName);
|
||||
}
|
||||
this.tech_ = new techComponent(techOptions);
|
||||
this.tech_ = new TechComponent(techOptions);
|
||||
|
||||
// player.triggerReady is always async, so don't need this to be async
|
||||
this.tech_.ready(Fn.bind(this, this.handleTechReady_), true);
|
||||
@@ -698,12 +719,13 @@ class Player extends Component {
|
||||
if (safety && safety.IWillNotUseThisInPlugins) {
|
||||
return this.tech_;
|
||||
}
|
||||
let errorText = `
|
||||
const errorText = `
|
||||
Please make sure that you are not using this inside of a plugin.
|
||||
To disable this alert and error, please pass in an object with
|
||||
\`IWillNotUseThisInPlugins\` to the \`tech\` method. See
|
||||
https://github.com/videojs/video.js/issues/2617 for more info.
|
||||
`;
|
||||
|
||||
window.alert(errorText);
|
||||
throw new Error(errorText);
|
||||
}
|
||||
@@ -794,9 +816,9 @@ class Player extends Component {
|
||||
// This fixes both issues. Need to wait for API, so it updates displays correctly
|
||||
if ((this.src() || this.currentSrc()) && this.tag && this.options_.autoplay && this.paused()) {
|
||||
try {
|
||||
delete this.tag.poster; // Chrome Fix. Fixed in Chrome v16.
|
||||
}
|
||||
catch (e) {
|
||||
// Chrome Fix. Fixed in Chrome v16.
|
||||
delete this.tag.poster;
|
||||
} catch (e) {
|
||||
log('deleting tag.poster throws in some browsers', e);
|
||||
}
|
||||
this.play();
|
||||
@@ -954,9 +976,9 @@ class Player extends Component {
|
||||
* @method handleTechFirstPlay_
|
||||
*/
|
||||
handleTechFirstPlay_() {
|
||||
//If the first starttime attribute is specified
|
||||
//then we will start at the given offset in seconds
|
||||
if(this.options_.starttime){
|
||||
// If the first starttime attribute is specified
|
||||
// then we will start at the given offset in seconds
|
||||
if (this.options_.starttime) {
|
||||
this.currentTime(this.options_.starttime);
|
||||
}
|
||||
|
||||
@@ -1024,7 +1046,9 @@ class Player extends Component {
|
||||
handleTechClick_(event) {
|
||||
// We're using mousedown to detect clicks thanks to Flash, but mousedown
|
||||
// will also be triggered with right-clicks, so we need to prevent that
|
||||
if (event.button !== 0) return;
|
||||
if (event.button !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// When controls are disabled a click should not toggle playback because
|
||||
// the click is considered a control
|
||||
@@ -1065,7 +1089,7 @@ class Player extends Component {
|
||||
* @method handleTechTouchMove_
|
||||
*/
|
||||
handleTechTouchMove_() {
|
||||
if (this.userWasActive){
|
||||
if (this.userWasActive) {
|
||||
this.reportUserActivity();
|
||||
}
|
||||
}
|
||||
@@ -1126,7 +1150,8 @@ class Player extends Component {
|
||||
* @method handleTechError_
|
||||
*/
|
||||
handleTechError_() {
|
||||
let error = this.tech_.error();
|
||||
const error = this.tech_.error();
|
||||
|
||||
this.error(error);
|
||||
}
|
||||
|
||||
@@ -1181,7 +1206,8 @@ class Player extends Component {
|
||||
}
|
||||
|
||||
handleTechTextData_() {
|
||||
var data = null;
|
||||
let data = null;
|
||||
|
||||
if (arguments.length > 1) {
|
||||
data = arguments[1];
|
||||
}
|
||||
@@ -1259,15 +1285,17 @@ class Player extends Component {
|
||||
techCall_(method, arg) {
|
||||
// If it's not ready yet, call method when it is
|
||||
if (this.tech_ && !this.tech_.isReady_) {
|
||||
this.tech_.ready(function(){
|
||||
this.tech_.ready(function() {
|
||||
this[method](arg);
|
||||
}, true);
|
||||
|
||||
// Otherwise call method now
|
||||
} else {
|
||||
try {
|
||||
this.tech_ && this.tech_[method](arg);
|
||||
} catch(e) {
|
||||
if (this.tech_) {
|
||||
this.tech_[method](arg);
|
||||
}
|
||||
} catch (e) {
|
||||
log(e);
|
||||
throw e;
|
||||
}
|
||||
@@ -1290,18 +1318,17 @@ class Player extends Component {
|
||||
// When that happens we'll catch the errors and inform tech that it's not ready any more.
|
||||
try {
|
||||
return this.tech_[method]();
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
// When building additional tech libs, an expected method may not be defined yet
|
||||
if (this.tech_[method] === undefined) {
|
||||
log(`Video.js: ${method} method not defined for ${this.techName_} playback technology.`, e);
|
||||
|
||||
// When a method isn't available on the object it throws a TypeError
|
||||
} else if (e.name === 'TypeError') {
|
||||
log(`Video.js: ${method} unavailable on ${this.techName_} playback technology element.`, e);
|
||||
this.tech_.isReady_ = false;
|
||||
} else {
|
||||
// When a method isn't available on the object it throws a TypeError
|
||||
if (e.name === 'TypeError') {
|
||||
log(`Video.js: ${method} unavailable on ${this.techName_} playback technology element.`, e);
|
||||
this.tech_.isReady_ = false;
|
||||
} else {
|
||||
log(e);
|
||||
}
|
||||
log(e);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
@@ -1414,11 +1441,13 @@ class Player extends Component {
|
||||
// currentTime when scrubbing, but may not provide much performance benefit afterall.
|
||||
// Should be tested. Also something has to read the actual current time or the cache will
|
||||
// never get updated.
|
||||
return this.cache_.currentTime = (this.techGet_('currentTime') || 0);
|
||||
this.cache_.currentTime = (this.techGet_('currentTime') || 0);
|
||||
return this.cache_.currentTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the length in time of the video in seconds
|
||||
* Normally gets the length in time of the video in seconds;
|
||||
* in all but the rarest use cases an argument will NOT be passed to the method
|
||||
* ```js
|
||||
* var lengthOfVideo = myPlayer.duration();
|
||||
* ```
|
||||
@@ -1495,10 +1524,10 @@ class Player extends Component {
|
||||
* @method buffered
|
||||
*/
|
||||
buffered() {
|
||||
var buffered = this.techGet_('buffered');
|
||||
let buffered = this.techGet_('buffered');
|
||||
|
||||
if (!buffered || !buffered.length) {
|
||||
buffered = createTimeRange(0,0);
|
||||
buffered = createTimeRange(0, 0);
|
||||
}
|
||||
|
||||
return buffered;
|
||||
@@ -1527,9 +1556,9 @@ class Player extends Component {
|
||||
* @method bufferedEnd
|
||||
*/
|
||||
bufferedEnd() {
|
||||
var buffered = this.buffered(),
|
||||
duration = this.duration(),
|
||||
end = buffered.end(buffered.length-1);
|
||||
const buffered = this.buffered();
|
||||
const duration = this.duration();
|
||||
let end = buffered.end(buffered.length - 1);
|
||||
|
||||
if (end > duration) {
|
||||
end = duration;
|
||||
@@ -1557,7 +1586,8 @@ class Player extends Component {
|
||||
let vol;
|
||||
|
||||
if (percentAsDecimal !== undefined) {
|
||||
vol = Math.max(0, Math.min(1, parseFloat(percentAsDecimal))); // Force value to between 0 and 1
|
||||
// Force value to between 0 and 1
|
||||
vol = Math.max(0, Math.min(1, parseFloat(percentAsDecimal)));
|
||||
this.cache_.volume = vol;
|
||||
this.techCall_('setVolume', vol);
|
||||
|
||||
@@ -1569,7 +1599,6 @@ class Player extends Component {
|
||||
return (isNaN(vol)) ? 1 : vol;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the current muted state, or turn mute on or off
|
||||
* ```js
|
||||
@@ -1589,7 +1618,7 @@ class Player extends Component {
|
||||
this.techCall_('setMuted', muted);
|
||||
return this;
|
||||
}
|
||||
return this.techGet_('muted') || false; // Default to false
|
||||
return this.techGet_('muted') || false;
|
||||
}
|
||||
|
||||
// Check if current tech can support native fullscreen
|
||||
@@ -1645,7 +1674,7 @@ class Player extends Component {
|
||||
* @method requestFullscreen
|
||||
*/
|
||||
requestFullscreen() {
|
||||
var fsApi = FullscreenApi;
|
||||
const fsApi = FullscreenApi;
|
||||
|
||||
this.isFullscreen(true);
|
||||
|
||||
@@ -1658,7 +1687,7 @@ class Player extends Component {
|
||||
// when canceling fullscreen. Otherwise if there's multiple
|
||||
// players on a page, they would all be reacting to the same fullscreen
|
||||
// events
|
||||
Events.on(document, fsApi.fullscreenchange, Fn.bind(this, function documentFullscreenChange(e){
|
||||
Events.on(document, fsApi.fullscreenchange, Fn.bind(this, function documentFullscreenChange(e) {
|
||||
this.isFullscreen(document[fsApi.fullscreenElement]);
|
||||
|
||||
// If cancelling fullscreen, remove event listener.
|
||||
@@ -1695,17 +1724,18 @@ class Player extends Component {
|
||||
* @method exitFullscreen
|
||||
*/
|
||||
exitFullscreen() {
|
||||
var fsApi = FullscreenApi;
|
||||
const fsApi = FullscreenApi;
|
||||
|
||||
this.isFullscreen(false);
|
||||
|
||||
// Check for browser element fullscreen support
|
||||
if (fsApi.requestFullscreen) {
|
||||
document[fsApi.exitFullscreen]();
|
||||
} else if (this.tech_.supportsFullScreen()) {
|
||||
this.techCall_('exitFullScreen');
|
||||
this.techCall_('exitFullScreen');
|
||||
} else {
|
||||
this.exitFullWindow();
|
||||
this.trigger('fullscreenchange');
|
||||
this.exitFullWindow();
|
||||
this.trigger('fullscreenchange');
|
||||
}
|
||||
|
||||
return this;
|
||||
@@ -1782,7 +1812,7 @@ class Player extends Component {
|
||||
|
||||
// Loop through each playback technology in the options order
|
||||
for (let i = 0, j = this.options_.techOrder; i < j.length; i++) {
|
||||
let techName = toTitleCase(j[i]);
|
||||
const techName = toTitleCase(j[i]);
|
||||
let tech = Tech.getTech(techName);
|
||||
|
||||
// Support old behavior of techs being registered as components.
|
||||
@@ -1822,7 +1852,7 @@ class Player extends Component {
|
||||
selectSource(sources) {
|
||||
// Get only the techs specified in `techOrder` that exist and are supported by the
|
||||
// current platform
|
||||
let techs =
|
||||
const techs =
|
||||
this.options_.techOrder
|
||||
.map(toTitleCase)
|
||||
.map((techName) => {
|
||||
@@ -1845,7 +1875,7 @@ class Player extends Component {
|
||||
// Iterate over each `innerArray` element once per `outerArray` element and execute
|
||||
// `tester` with both. If `tester` returns a non-falsy value, exit early and return
|
||||
// that value.
|
||||
let findFirstPassingTechSourcePair = function (outerArray, innerArray, tester) {
|
||||
const findFirstPassingTechSourcePair = function(outerArray, innerArray, tester) {
|
||||
let found;
|
||||
|
||||
outerArray.some((outerChoice) => {
|
||||
@@ -1862,10 +1892,10 @@ class Player extends Component {
|
||||
};
|
||||
|
||||
let foundSourceAndTech;
|
||||
let flip = (fn) => (a, b) => fn(b, a);
|
||||
let finder = ([techName, tech], source) => {
|
||||
const flip = (fn) => (a, b) => fn(b, a);
|
||||
const finder = ([techName, tech], source) => {
|
||||
if (tech.canPlaySource(source, this.options_[techName.toLowerCase()])) {
|
||||
return {source: source, tech: techName};
|
||||
return {source, tech: techName};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1920,6 +1950,7 @@ class Player extends Component {
|
||||
}
|
||||
|
||||
let currentTech = Tech.getTech(this.techName_);
|
||||
|
||||
// Support old behavior of techs being registered as components.
|
||||
// Remove once that deprecated behavior is removed.
|
||||
if (!currentTech) {
|
||||
@@ -1948,7 +1979,7 @@ class Player extends Component {
|
||||
this.currentType_ = source.type || '';
|
||||
|
||||
// wait until the tech is ready to set the source
|
||||
this.ready(function(){
|
||||
this.ready(function() {
|
||||
|
||||
// The setSource tech method was added with source handlers
|
||||
// so older techs won't support it
|
||||
@@ -1984,7 +2015,7 @@ class Player extends Component {
|
||||
* @method sourceList_
|
||||
*/
|
||||
sourceList_(sources) {
|
||||
var sourceTech = this.selectSource(sources);
|
||||
const sourceTech = this.selectSource(sources);
|
||||
|
||||
if (sourceTech) {
|
||||
if (sourceTech.tech === this.techName_) {
|
||||
@@ -1996,7 +2027,7 @@ class Player extends Component {
|
||||
}
|
||||
} else {
|
||||
// We need to wrap this in a timeout to give folks a chance to add error event handlers
|
||||
this.setTimeout( function() {
|
||||
this.setTimeout(function() {
|
||||
this.error({ code: 4, message: this.localize(this.options_.notSupportedMessage) });
|
||||
}, 0);
|
||||
|
||||
@@ -2098,7 +2129,7 @@ class Player extends Component {
|
||||
loop(value) {
|
||||
if (value !== undefined) {
|
||||
this.techCall_('setLoop', value);
|
||||
this.options_['loop'] = value;
|
||||
this.options_.loop = value;
|
||||
return this;
|
||||
}
|
||||
return this.techGet_('loop');
|
||||
@@ -2172,7 +2203,8 @@ class Player extends Component {
|
||||
*/
|
||||
controls(bool) {
|
||||
if (bool !== undefined) {
|
||||
bool = !!bool; // force boolean
|
||||
bool = !!bool;
|
||||
|
||||
// Don't trigger a change event unless it actually changed
|
||||
if (this.controls_ !== bool) {
|
||||
this.controls_ = bool;
|
||||
@@ -2218,7 +2250,8 @@ class Player extends Component {
|
||||
*/
|
||||
usingNativeControls(bool) {
|
||||
if (bool !== undefined) {
|
||||
bool = !!bool; // force boolean
|
||||
bool = !!bool;
|
||||
|
||||
// Don't trigger a change event unless it actually changed
|
||||
if (this.usingNativeControls_ !== bool) {
|
||||
this.usingNativeControls_ = bool;
|
||||
@@ -2276,12 +2309,7 @@ class Player extends Component {
|
||||
return this;
|
||||
}
|
||||
|
||||
// error instance
|
||||
if (err instanceof MediaError) {
|
||||
this.error_ = err;
|
||||
} else {
|
||||
this.error_ = new MediaError(err);
|
||||
}
|
||||
this.error_ = new MediaError(err);
|
||||
|
||||
// add the vjs-error classname to the player
|
||||
this.addClass('vjs-error');
|
||||
@@ -2302,7 +2330,9 @@ class Player extends Component {
|
||||
* @return {Boolean} True if the player is in the ended state, false if not.
|
||||
* @method ended
|
||||
*/
|
||||
ended() { return this.techGet_('ended'); }
|
||||
ended() {
|
||||
return this.techGet_('ended');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the player is in the "seeking" state.
|
||||
@@ -2310,7 +2340,9 @@ class Player extends Component {
|
||||
* @return {Boolean} True if the player is in the seeking state, false if not.
|
||||
* @method seeking
|
||||
*/
|
||||
seeking() { return this.techGet_('seeking'); }
|
||||
seeking() {
|
||||
return this.techGet_('seeking');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the TimeRanges of the media that are currently available
|
||||
@@ -2319,7 +2351,9 @@ class Player extends Component {
|
||||
* @return {TimeRanges} the seekable intervals of the media timeline
|
||||
* @method seekable
|
||||
*/
|
||||
seekable() { return this.techGet_('seekable'); }
|
||||
seekable() {
|
||||
return this.techGet_('seekable');
|
||||
}
|
||||
|
||||
/**
|
||||
* Report user activity
|
||||
@@ -2363,8 +2397,8 @@ class Player extends Component {
|
||||
//
|
||||
// When this gets resolved in ALL browsers it can be removed
|
||||
// https://code.google.com/p/chromium/issues/detail?id=103041
|
||||
if(this.tech_) {
|
||||
this.tech_.one('mousemove', function(e){
|
||||
if (this.tech_) {
|
||||
this.tech_.one('mousemove', function(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
@@ -2387,21 +2421,22 @@ class Player extends Component {
|
||||
* @method listenForUserActivity_
|
||||
*/
|
||||
listenForUserActivity_() {
|
||||
let mouseInProgress, lastMoveX, lastMoveY;
|
||||
let mouseInProgress;
|
||||
let lastMoveX;
|
||||
let lastMoveY;
|
||||
const handleActivity = Fn.bind(this, this.reportUserActivity);
|
||||
|
||||
let handleActivity = Fn.bind(this, this.reportUserActivity);
|
||||
|
||||
let handleMouseMove = function(e) {
|
||||
const handleMouseMove = function(e) {
|
||||
// #1068 - Prevent mousemove spamming
|
||||
// Chrome Bug: https://code.google.com/p/chromium/issues/detail?id=366970
|
||||
if(e.screenX !== lastMoveX || e.screenY !== lastMoveY) {
|
||||
if (e.screenX !== lastMoveX || e.screenY !== lastMoveY) {
|
||||
lastMoveX = e.screenX;
|
||||
lastMoveY = e.screenY;
|
||||
handleActivity();
|
||||
}
|
||||
};
|
||||
|
||||
let handleMouseDown = function() {
|
||||
const handleMouseDown = function() {
|
||||
handleActivity();
|
||||
// For as long as the they are touching the device or have their mouse down,
|
||||
// we consider them active even if they're not moving their finger or mouse.
|
||||
@@ -2413,7 +2448,7 @@ class Player extends Component {
|
||||
mouseInProgress = this.setInterval(handleActivity, 250);
|
||||
};
|
||||
|
||||
let handleMouseUp = function(event) {
|
||||
const handleMouseUp = function(event) {
|
||||
handleActivity();
|
||||
// Stop the interval that maintains activity if the mouse/touch is down
|
||||
this.clearInterval(mouseInProgress);
|
||||
@@ -2435,7 +2470,8 @@ class Player extends Component {
|
||||
// then gets picked up by this loop
|
||||
// http://ejohn.org/blog/learning-from-twitter/
|
||||
let inactivityTimeout;
|
||||
let activityCheck = this.setInterval(function() {
|
||||
|
||||
this.setInterval(function() {
|
||||
// Check to see if mouse/touch activity has happened
|
||||
if (this.userActivity_) {
|
||||
// Reset the activity tracker
|
||||
@@ -2447,16 +2483,17 @@ class Player extends Component {
|
||||
// Clear any existing inactivity timeout to start the timer over
|
||||
this.clearTimeout(inactivityTimeout);
|
||||
|
||||
var timeout = this.options_['inactivityTimeout'];
|
||||
const timeout = this.options_.inactivityTimeout;
|
||||
|
||||
if (timeout > 0) {
|
||||
// In <timeout> milliseconds, if no more activity has occurred the
|
||||
// user will be considered inactive
|
||||
inactivityTimeout = this.setTimeout(function () {
|
||||
inactivityTimeout = this.setTimeout(function() {
|
||||
// Protect against the case where the inactivityTimeout can trigger just
|
||||
// before the next user activity is picked up by the activityCheck loop
|
||||
// before the next user activity is picked up by the activity check loop
|
||||
// causing a flicker
|
||||
if (!this.userActivity_) {
|
||||
this.userActive(false);
|
||||
this.userActive(false);
|
||||
}
|
||||
}, timeout);
|
||||
}
|
||||
@@ -2481,11 +2518,10 @@ class Player extends Component {
|
||||
return this;
|
||||
}
|
||||
|
||||
if (this.tech_ && this.tech_['featuresPlaybackRate']) {
|
||||
if (this.tech_ && this.tech_.featuresPlaybackRate) {
|
||||
return this.techGet_('playbackRate');
|
||||
} else {
|
||||
return 1.0;
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2611,7 +2647,9 @@ class Player extends Component {
|
||||
textTracks() {
|
||||
// cannot use techGet_ directly because it checks to see whether the tech is ready.
|
||||
// Flash is unlikely to be ready in time but textTracks should still work.
|
||||
return this.tech_ && this.tech_['textTracks']();
|
||||
if (this.tech_) {
|
||||
return this.tech_.textTracks();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2621,7 +2659,9 @@ class Player extends Component {
|
||||
* @method remoteTextTracks
|
||||
*/
|
||||
remoteTextTracks() {
|
||||
return this.tech_ && this.tech_['remoteTextTracks']();
|
||||
if (this.tech_) {
|
||||
return this.tech_.remoteTextTracks();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2631,7 +2671,9 @@ class Player extends Component {
|
||||
* @method remoteTextTrackEls
|
||||
*/
|
||||
remoteTextTrackEls() {
|
||||
return this.tech_ && this.tech_['remoteTextTrackEls']();
|
||||
if (this.tech_) {
|
||||
return this.tech_.remoteTextTrackEls();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2645,7 +2687,9 @@ class Player extends Component {
|
||||
* @method addTextTrack
|
||||
*/
|
||||
addTextTrack(kind, label, language) {
|
||||
return this.tech_ && this.tech_['addTextTrack'](kind, label, language);
|
||||
if (this.tech_) {
|
||||
return this.tech_.addTextTrack(kind, label, language);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2655,7 +2699,9 @@ class Player extends Component {
|
||||
* @method addRemoteTextTrack
|
||||
*/
|
||||
addRemoteTextTrack(options) {
|
||||
return this.tech_ && this.tech_['addRemoteTextTrack'](options);
|
||||
if (this.tech_) {
|
||||
return this.tech_.addRemoteTextTrack(options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2666,8 +2712,10 @@ class Player extends Component {
|
||||
*/
|
||||
// destructure the input into an object with a track argument, defaulting to arguments[0]
|
||||
// default the whole argument to an empty object if nothing was passed in
|
||||
removeRemoteTextTrack({track = arguments[0]} = {}) { // jshint ignore:line
|
||||
this.tech_ && this.tech_['removeRemoteTextTrack'](track);
|
||||
removeRemoteTextTrack({track = arguments[0]} = {}) {
|
||||
if (this.tech_) {
|
||||
return this.tech_.removeRemoteTextTrack(track);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2691,11 +2739,11 @@ class Player extends Component {
|
||||
}
|
||||
|
||||
// Methods to add support for
|
||||
// initialTime: function(){ return this.techCall_('initialTime'); },
|
||||
// startOffsetTime: function(){ return this.techCall_('startOffsetTime'); },
|
||||
// played: function(){ return this.techCall_('played'); },
|
||||
// defaultPlaybackRate: function(){ return this.techCall_('defaultPlaybackRate'); },
|
||||
// defaultMuted: function(){ return this.techCall_('defaultMuted'); }
|
||||
// initialTime: function() { return this.techCall_('initialTime'); },
|
||||
// startOffsetTime: function() { return this.techCall_('startOffsetTime'); },
|
||||
// played: function() { return this.techCall_('played'); },
|
||||
// defaultPlaybackRate: function() { return this.techCall_('defaultPlaybackRate'); },
|
||||
// defaultMuted: function() { return this.techCall_('defaultMuted'); }
|
||||
|
||||
/**
|
||||
* The player's language code
|
||||
@@ -2713,7 +2761,7 @@ class Player extends Component {
|
||||
return this.language_;
|
||||
}
|
||||
|
||||
this.language_ = (''+code).toLowerCase();
|
||||
this.language_ = String(code).toLowerCase();
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -2726,7 +2774,7 @@ class Player extends Component {
|
||||
* @method languages
|
||||
*/
|
||||
languages() {
|
||||
return mergeOptions(Player.prototype.options_.languages, this.languages_);
|
||||
return mergeOptions(Player.prototype.options_.languages, this.languages_);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2736,8 +2784,8 @@ class Player extends Component {
|
||||
* @method toJSON
|
||||
*/
|
||||
toJSON() {
|
||||
let options = mergeOptions(this.options_);
|
||||
let tracks = options.tracks;
|
||||
const options = mergeOptions(this.options_);
|
||||
const tracks = options.tracks;
|
||||
|
||||
options.tracks = [];
|
||||
|
||||
@@ -2770,16 +2818,14 @@ class Player extends Component {
|
||||
* @return {ModalDialog}
|
||||
*/
|
||||
createModal(content, options) {
|
||||
let player = this;
|
||||
|
||||
options = options || {};
|
||||
options.content = content || '';
|
||||
|
||||
let modal = new ModalDialog(player, options);
|
||||
const modal = new ModalDialog(this, options);
|
||||
|
||||
player.addChild(modal);
|
||||
modal.on('dispose', function() {
|
||||
player.removeChild(modal);
|
||||
this.addChild(modal);
|
||||
modal.on('dispose', () => {
|
||||
this.removeChild(modal);
|
||||
});
|
||||
|
||||
return modal.open();
|
||||
@@ -2794,19 +2840,20 @@ class Player extends Component {
|
||||
* @method getTagSettings
|
||||
*/
|
||||
static getTagSettings(tag) {
|
||||
let baseOptions = {
|
||||
'sources': [],
|
||||
'tracks': []
|
||||
const baseOptions = {
|
||||
sources: [],
|
||||
tracks: []
|
||||
};
|
||||
|
||||
const tagOptions = Dom.getElAttributes(tag);
|
||||
const dataSetup = tagOptions['data-setup'];
|
||||
|
||||
// Check if data-setup attr exists.
|
||||
if (dataSetup !== null){
|
||||
if (dataSetup !== null) {
|
||||
// Parse options JSON
|
||||
// If empty string, make it a parsable json object.
|
||||
const [err, data] = safeParseTuple(dataSetup || '{}');
|
||||
|
||||
if (err) {
|
||||
log.error(err);
|
||||
}
|
||||
@@ -2819,10 +2866,11 @@ class Player extends Component {
|
||||
if (tag.hasChildNodes()) {
|
||||
const children = tag.childNodes;
|
||||
|
||||
for (let i=0, j=children.length; i<j; i++) {
|
||||
for (let i = 0, j = children.length; i < j; i++) {
|
||||
const child = children[i];
|
||||
// Change case needed: http://ejohn.org/blog/nodename-case-sensitivity/
|
||||
const childName = child.nodeName.toLowerCase();
|
||||
|
||||
if (childName === 'source') {
|
||||
baseOptions.sources.push(Dom.getElAttributes(child));
|
||||
} else if (childName === 'track') {
|
||||
@@ -2843,7 +2891,8 @@ class Player extends Component {
|
||||
*/
|
||||
Player.players = {};
|
||||
|
||||
let navigator = window.navigator;
|
||||
const navigator = window.navigator;
|
||||
|
||||
/*
|
||||
* Player instance options, surfaced using options
|
||||
* options = Player.prototype.options_
|
||||
@@ -2854,14 +2903,14 @@ let navigator = window.navigator;
|
||||
*/
|
||||
Player.prototype.options_ = {
|
||||
// Default order of fallback technology
|
||||
techOrder: ['html5','flash'],
|
||||
techOrder: ['html5', 'flash'],
|
||||
// techOrder: ['flash','html5'],
|
||||
|
||||
html5: {},
|
||||
flash: {},
|
||||
|
||||
// defaultVolume: 0.85,
|
||||
defaultVolume: 0.00, // The freakin seaguls are driving me crazy!
|
||||
defaultVolume: 0.00,
|
||||
|
||||
// default inactivity timeout
|
||||
inactivityTimeout: 2000,
|
||||
@@ -2883,7 +2932,7 @@ Player.prototype.options_ = {
|
||||
'textTrackSettings'
|
||||
],
|
||||
|
||||
language: navigator.languages && navigator.languages[0] || navigator.userLanguage || navigator.language || 'en',
|
||||
language: navigator && (navigator.languages && navigator.languages[0] || navigator.userLanguage || navigator.language) || 'en',
|
||||
|
||||
// locales and their language translations
|
||||
languages: {},
|
||||
@@ -2892,47 +2941,49 @@ Player.prototype.options_ = {
|
||||
notSupportedMessage: 'No compatible source was found for this media.'
|
||||
};
|
||||
|
||||
// The following no-op expressions are here only for purposes of documentation.
|
||||
|
||||
/**
|
||||
* Fired when the user agent begins looking for media data
|
||||
*
|
||||
* @event loadstart
|
||||
*/
|
||||
Player.prototype.handleTechLoadStart_;
|
||||
Player.prototype.handleTechLoadStart_; // eslint-disable-line
|
||||
|
||||
/**
|
||||
* Fired when the player has initial duration and dimension information
|
||||
*
|
||||
* @event loadedmetadata
|
||||
*/
|
||||
Player.prototype.handleLoadedMetaData_;
|
||||
Player.prototype.handleLoadedMetaData_; // eslint-disable-line
|
||||
|
||||
/**
|
||||
* Fired when the player receives text data
|
||||
*
|
||||
* @event textdata
|
||||
*/
|
||||
Player.prototype.handleTextData_;
|
||||
Player.prototype.handleTextData_; // eslint-disable-line
|
||||
|
||||
/**
|
||||
* Fired when the player has downloaded data at the current playback position
|
||||
*
|
||||
* @event loadeddata
|
||||
*/
|
||||
Player.prototype.handleLoadedData_;
|
||||
Player.prototype.handleLoadedData_; // eslint-disable-line
|
||||
|
||||
/**
|
||||
* Fired when the user is active, e.g. moves the mouse over the player
|
||||
*
|
||||
* @event useractive
|
||||
*/
|
||||
Player.prototype.handleUserActive_;
|
||||
Player.prototype.handleUserActive_; // eslint-disable-line
|
||||
|
||||
/**
|
||||
* Fired when the user is inactive, e.g. a short delay after the last mouse move or control interaction
|
||||
*
|
||||
* @event userinactive
|
||||
*/
|
||||
Player.prototype.handleUserInactive_;
|
||||
Player.prototype.handleUserInactive_; // eslint-disable-line
|
||||
|
||||
/**
|
||||
* Fired when the current playback position has changed *
|
||||
@@ -2941,31 +2992,31 @@ Player.prototype.handleUserInactive_;
|
||||
*
|
||||
* @event timeupdate
|
||||
*/
|
||||
Player.prototype.handleTimeUpdate_;
|
||||
Player.prototype.handleTimeUpdate_; // eslint-disable-line
|
||||
|
||||
/**
|
||||
* Fired when video playback ends
|
||||
*
|
||||
* @event ended
|
||||
*/
|
||||
Player.prototype.handleTechEnded_;
|
||||
Player.prototype.handleTechEnded_; // eslint-disable-line
|
||||
|
||||
/**
|
||||
* Fired when the volume changes
|
||||
*
|
||||
* @event volumechange
|
||||
*/
|
||||
Player.prototype.handleVolumeChange_;
|
||||
Player.prototype.handleVolumeChange_; // eslint-disable-line
|
||||
|
||||
/**
|
||||
* Fired when an error occurs
|
||||
*
|
||||
* @event error
|
||||
*/
|
||||
Player.prototype.handleError_;
|
||||
Player.prototype.handleError_; // eslint-disable-line
|
||||
|
||||
Player.prototype.flexNotSupported_ = function() {
|
||||
var elem = document.createElement('i');
|
||||
const elem = document.createElement('i');
|
||||
|
||||
// Note: We don't actually use flexBasis (or flexOrder), but it's one of the more
|
||||
// common flex features that we can rely on when checking for flex support.
|
||||
@@ -2973,7 +3024,8 @@ Player.prototype.flexNotSupported_ = function() {
|
||||
'webkitFlexBasis' in elem.style ||
|
||||
'mozFlexBasis' in elem.style ||
|
||||
'msFlexBasis' in elem.style ||
|
||||
'msFlexOrder' in elem.style /* IE10-specific (2012 flex spec) */);
|
||||
// IE10-specific (2012 flex spec)
|
||||
'msFlexOrder' in elem.style);
|
||||
};
|
||||
|
||||
Component.registerComponent('Player', Player);
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ import Player from './player.js';
|
||||
* @param {Function} init The function that is run when the player inits
|
||||
* @method plugin
|
||||
*/
|
||||
var plugin = function(name, init){
|
||||
const plugin = function(name, init) {
|
||||
Player.prototype[name] = init;
|
||||
};
|
||||
|
||||
|
||||
@@ -3,10 +3,6 @@
|
||||
*/
|
||||
import ClickableComponent from '../clickable-component.js';
|
||||
import Component from '../component.js';
|
||||
import Popup from './popup.js';
|
||||
import * as Dom from '../utils/dom.js';
|
||||
import * as Fn from '../utils/fn.js';
|
||||
import toTitleCase from '../utils/to-title-case.js';
|
||||
|
||||
/**
|
||||
* A button class with a popup control
|
||||
@@ -18,7 +14,7 @@ import toTitleCase from '../utils/to-title-case.js';
|
||||
*/
|
||||
class PopupButton extends ClickableComponent {
|
||||
|
||||
constructor(player, options={}){
|
||||
constructor(player, options = {}) {
|
||||
super(player, options);
|
||||
|
||||
this.update();
|
||||
@@ -30,7 +26,7 @@ class PopupButton extends ClickableComponent {
|
||||
* @method update
|
||||
*/
|
||||
update() {
|
||||
let popup = this.createPopup();
|
||||
const popup = this.createPopup();
|
||||
|
||||
if (this.popup) {
|
||||
this.removeChild(this.popup);
|
||||
@@ -73,7 +69,7 @@ class PopupButton extends ClickableComponent {
|
||||
* @method buildCSSClass
|
||||
*/
|
||||
buildCSSClass() {
|
||||
var menuButtonClass = 'vjs-menu-button';
|
||||
let menuButtonClass = 'vjs-menu-button';
|
||||
|
||||
// If the inline option is passed, we want to use different styles altogether.
|
||||
if (this.options_.inline === true) {
|
||||
|
||||
@@ -22,7 +22,7 @@ class Popup extends Component {
|
||||
*/
|
||||
addItem(component) {
|
||||
this.addChild(component);
|
||||
component.on('click', Fn.bind(this, function(){
|
||||
component.on('click', Fn.bind(this, function() {
|
||||
this.unlockShowing();
|
||||
}));
|
||||
}
|
||||
@@ -34,19 +34,22 @@ class Popup extends Component {
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
let contentElType = this.options_.contentElType || 'ul';
|
||||
const contentElType = this.options_.contentElType || 'ul';
|
||||
|
||||
this.contentEl_ = Dom.createEl(contentElType, {
|
||||
className: 'vjs-menu-content'
|
||||
});
|
||||
var el = super.createEl('div', {
|
||||
|
||||
const el = super.createEl('div', {
|
||||
append: this.contentEl_,
|
||||
className: 'vjs-menu'
|
||||
});
|
||||
|
||||
el.appendChild(this.contentEl_);
|
||||
|
||||
// Prevent clicks from bubbling up. Needed for Popup Buttons,
|
||||
// where a click on the parent is significant
|
||||
Events.on(el, 'click', function(event){
|
||||
Events.on(el, 'click', function(event) {
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
});
|
||||
|
||||
@@ -17,7 +17,7 @@ import * as browser from './utils/browser.js';
|
||||
*/
|
||||
class PosterImage extends ClickableComponent {
|
||||
|
||||
constructor(player, options){
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
|
||||
this.update();
|
||||
@@ -41,7 +41,7 @@ class PosterImage extends ClickableComponent {
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
let el = Dom.createEl('div', {
|
||||
const el = Dom.createEl('div', {
|
||||
className: 'vjs-poster',
|
||||
|
||||
// Don't want poster to be tabbable.
|
||||
@@ -66,7 +66,7 @@ class PosterImage extends ClickableComponent {
|
||||
* @method update
|
||||
*/
|
||||
update() {
|
||||
let url = this.player().poster();
|
||||
const url = this.player().poster();
|
||||
|
||||
this.setSrc(url);
|
||||
|
||||
@@ -90,6 +90,7 @@ class PosterImage extends ClickableComponent {
|
||||
this.fallbackImg_.src = url;
|
||||
} else {
|
||||
let backgroundImage = '';
|
||||
|
||||
// Any falsey values should stay as an empty string, otherwise
|
||||
// this will throw an extra error
|
||||
if (url) {
|
||||
|
||||
+21
-19
@@ -11,26 +11,27 @@ import window from 'global/window';
|
||||
let _windowLoaded = false;
|
||||
let videojs;
|
||||
|
||||
|
||||
// Automatically set up any tags that have a data-setup attribute
|
||||
var autoSetup = function(){
|
||||
const autoSetup = function() {
|
||||
// One day, when we stop supporting IE8, go back to this, but in the meantime...*hack hack hack*
|
||||
// var vids = Array.prototype.slice.call(document.getElementsByTagName('video'));
|
||||
// var audios = Array.prototype.slice.call(document.getElementsByTagName('audio'));
|
||||
// var mediaEls = vids.concat(audios);
|
||||
|
||||
// Because IE8 doesn't support calling slice on a node list, we need to loop through each list of elements
|
||||
// to build up a new, combined list of elements.
|
||||
var vids = document.getElementsByTagName('video');
|
||||
var audios = document.getElementsByTagName('audio');
|
||||
var mediaEls = [];
|
||||
// Because IE8 doesn't support calling slice on a node list, we need to loop
|
||||
// through each list of elements to build up a new, combined list of elements.
|
||||
const vids = document.getElementsByTagName('video');
|
||||
const audios = document.getElementsByTagName('audio');
|
||||
const mediaEls = [];
|
||||
|
||||
if (vids && vids.length > 0) {
|
||||
for(let i=0, e=vids.length; i<e; i++) {
|
||||
for (let i = 0, e = vids.length; i < e; i++) {
|
||||
mediaEls.push(vids[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (audios && audios.length > 0) {
|
||||
for(let i=0, e=audios.length; i<e; i++) {
|
||||
for (let i = 0, e = audios.length; i < e; i++) {
|
||||
mediaEls.push(audios[i]);
|
||||
}
|
||||
}
|
||||
@@ -38,22 +39,23 @@ var autoSetup = function(){
|
||||
// Check if any media elements exist
|
||||
if (mediaEls && mediaEls.length > 0) {
|
||||
|
||||
for (let i=0, e=mediaEls.length; i<e; i++) {
|
||||
let mediaEl = mediaEls[i];
|
||||
for (let i = 0, e = mediaEls.length; i < e; i++) {
|
||||
const mediaEl = mediaEls[i];
|
||||
|
||||
// Check if element exists, has getAttribute func.
|
||||
// IE seems to consider typeof el.getAttribute == 'object' instead of 'function' like expected, at least when loading the player immediately.
|
||||
// IE seems to consider typeof el.getAttribute == 'object' instead of
|
||||
// 'function' like expected, at least when loading the player immediately.
|
||||
if (mediaEl && mediaEl.getAttribute) {
|
||||
|
||||
// Make sure this player hasn't already been set up.
|
||||
if (mediaEl['player'] === undefined) {
|
||||
let options = mediaEl.getAttribute('data-setup');
|
||||
if (mediaEl.player === undefined) {
|
||||
const options = mediaEl.getAttribute('data-setup');
|
||||
|
||||
// Check if data-setup attr exists.
|
||||
// We only auto-setup if they've added the data-setup attr.
|
||||
if (options !== null) {
|
||||
// Create new video.js instance.
|
||||
let player = videojs(mediaEl);
|
||||
videojs(mediaEl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,23 +73,23 @@ var autoSetup = function(){
|
||||
};
|
||||
|
||||
// Pause to let the DOM keep processing
|
||||
var autoSetupTimeout = function(wait, vjs){
|
||||
function autoSetupTimeout(wait, vjs) {
|
||||
if (vjs) {
|
||||
videojs = vjs;
|
||||
}
|
||||
|
||||
setTimeout(autoSetup, wait);
|
||||
};
|
||||
}
|
||||
|
||||
if (document.readyState === 'complete') {
|
||||
_windowLoaded = true;
|
||||
} else {
|
||||
Events.one(window, 'load', function(){
|
||||
Events.one(window, 'load', function() {
|
||||
_windowLoaded = true;
|
||||
});
|
||||
}
|
||||
|
||||
var hasLoaded = function() {
|
||||
const hasLoaded = function() {
|
||||
return _windowLoaded;
|
||||
};
|
||||
|
||||
|
||||
+21
-13
@@ -42,7 +42,7 @@ class Slider extends Component {
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl(type, props={}, attributes={}) {
|
||||
createEl(type, props = {}, attributes = {}) {
|
||||
// Add the slider element class to all sub classes
|
||||
props.className = props.className + ' vjs-slider';
|
||||
props = assign({
|
||||
@@ -54,7 +54,7 @@ class Slider extends Component {
|
||||
'aria-valuenow': 0,
|
||||
'aria-valuemin': 0,
|
||||
'aria-valuemax': 100,
|
||||
tabIndex: 0
|
||||
'tabIndex': 0
|
||||
}, attributes);
|
||||
|
||||
return super.createEl(type, props, attributes);
|
||||
@@ -67,7 +67,7 @@ class Slider extends Component {
|
||||
* @method handleMouseDown
|
||||
*/
|
||||
handleMouseDown(event) {
|
||||
let doc = this.bar.el_.ownerDocument;
|
||||
const doc = this.bar.el_.ownerDocument;
|
||||
|
||||
event.preventDefault();
|
||||
Dom.blockTextSelection();
|
||||
@@ -96,7 +96,7 @@ class Slider extends Component {
|
||||
* @method handleMouseUp
|
||||
*/
|
||||
handleMouseUp() {
|
||||
let doc = this.bar.el_.ownerDocument;
|
||||
const doc = this.bar.el_.ownerDocument;
|
||||
|
||||
Dom.unblockTextSelection();
|
||||
|
||||
@@ -119,27 +119,31 @@ class Slider extends Component {
|
||||
update() {
|
||||
// In VolumeBar init we have a setTimeout for update that pops and update to the end of the
|
||||
// execution stack. The player is destroyed before then update will cause an error
|
||||
if (!this.el_) return;
|
||||
if (!this.el_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If scrubbing, we could use a cached value to make the handle keep up with the user's mouse.
|
||||
// On HTML5 browsers scrubbing is really smooth, but some flash players are slow, so we might want to utilize this later.
|
||||
// var progress = (this.player_.scrubbing()) ? this.player_.getCache().currentTime / this.player_.duration() : this.player_.currentTime() / this.player_.duration();
|
||||
let progress = this.getPercent();
|
||||
let bar = this.bar;
|
||||
const bar = this.bar;
|
||||
|
||||
// If there's no bar...
|
||||
if (!bar) return;
|
||||
if (!bar) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Protect against no duration and other division issues
|
||||
if (typeof progress !== 'number' ||
|
||||
progress !== progress ||
|
||||
progress < 0 ||
|
||||
progress === Infinity) {
|
||||
progress = 0;
|
||||
progress = 0;
|
||||
}
|
||||
|
||||
// Convert to a percentage for setting
|
||||
let percentage = (progress * 100).toFixed(2) + '%';
|
||||
const percentage = (progress * 100).toFixed(2) + '%';
|
||||
|
||||
// Set the new bar width or height
|
||||
if (this.vertical()) {
|
||||
@@ -155,8 +159,9 @@ class Slider extends Component {
|
||||
* @param {Object} event Event object
|
||||
* @method calculateDistance
|
||||
*/
|
||||
calculateDistance(event){
|
||||
let position = Dom.getPointerPosition(this.el_, event);
|
||||
calculateDistance(event) {
|
||||
const position = Dom.getPointerPosition(this.el_, event);
|
||||
|
||||
if (this.vertical()) {
|
||||
return position.y;
|
||||
}
|
||||
@@ -179,10 +184,13 @@ class Slider extends Component {
|
||||
* @method handleKeyPress
|
||||
*/
|
||||
handleKeyPress(event) {
|
||||
if (event.which === 37 || event.which === 40) { // Left and Down Arrows
|
||||
// Left and Down Arrows
|
||||
if (event.which === 37 || event.which === 40) {
|
||||
event.preventDefault();
|
||||
this.stepBack();
|
||||
} else if (event.which === 38 || event.which === 39) { // Up and Right Arrows
|
||||
|
||||
// Up and Right Arrows
|
||||
} else if (event.which === 38 || event.which === 39) {
|
||||
event.preventDefault();
|
||||
this.stepForward();
|
||||
}
|
||||
|
||||
+14
-11
@@ -12,22 +12,24 @@ function FlashRtmpDecorator(Flash) {
|
||||
};
|
||||
|
||||
Flash.streamToParts = function(src) {
|
||||
let parts = {
|
||||
const parts = {
|
||||
connection: '',
|
||||
stream: ''
|
||||
};
|
||||
|
||||
if (!src) return parts;
|
||||
if (!src) {
|
||||
return parts;
|
||||
}
|
||||
|
||||
// Look for the normal URL separator we expect, '&'.
|
||||
// If found, we split the URL into two pieces around the
|
||||
// first '&'.
|
||||
let connEnd = src.search(/&(?!\w+=)/);
|
||||
let streamBegin;
|
||||
|
||||
if (connEnd !== -1) {
|
||||
streamBegin = connEnd + 1;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// If there's not a '&', we use the last '/' as the delimiter.
|
||||
connEnd = streamBegin = src.lastIndexOf('/') + 1;
|
||||
if (connEnd === 0) {
|
||||
@@ -35,6 +37,7 @@ function FlashRtmpDecorator(Flash) {
|
||||
connEnd = streamBegin = src.length;
|
||||
}
|
||||
}
|
||||
|
||||
parts.connection = src.substring(0, connEnd);
|
||||
parts.stream = src.substring(streamBegin, src.length);
|
||||
|
||||
@@ -64,7 +67,7 @@ function FlashRtmpDecorator(Flash) {
|
||||
* @param {String} type The mimetype to check
|
||||
* @return {String} 'probably', 'maybe', or '' (empty string)
|
||||
*/
|
||||
Flash.rtmpSourceHandler.canPlayType = function(type){
|
||||
Flash.rtmpSourceHandler.canPlayType = function(type) {
|
||||
if (Flash.isStreamingType(type)) {
|
||||
return 'maybe';
|
||||
}
|
||||
@@ -78,8 +81,8 @@ function FlashRtmpDecorator(Flash) {
|
||||
* @param {Object} options The options passed to the tech
|
||||
* @return {String} 'probably', 'maybe', or '' (empty string)
|
||||
*/
|
||||
Flash.rtmpSourceHandler.canHandleSource = function(source, options){
|
||||
let can = Flash.rtmpSourceHandler.canPlayType(source.type);
|
||||
Flash.rtmpSourceHandler.canHandleSource = function(source, options) {
|
||||
const can = Flash.rtmpSourceHandler.canPlayType(source.type);
|
||||
|
||||
if (can) {
|
||||
return can;
|
||||
@@ -100,11 +103,11 @@ function FlashRtmpDecorator(Flash) {
|
||||
* @param {Flash} tech The instance of the Flash tech
|
||||
* @param {Object} options The options to pass to the source
|
||||
*/
|
||||
Flash.rtmpSourceHandler.handleSource = function(source, tech, options){
|
||||
let srcParts = Flash.streamToParts(source.src);
|
||||
Flash.rtmpSourceHandler.handleSource = function(source, tech, options) {
|
||||
const srcParts = Flash.streamToParts(source.src);
|
||||
|
||||
tech['setRtmpConnection'](srcParts.connection);
|
||||
tech['setRtmpStream'](srcParts.stream);
|
||||
tech.setRtmpConnection(srcParts.connection);
|
||||
tech.setRtmpStream(srcParts.stream);
|
||||
};
|
||||
|
||||
// Register the native source handler
|
||||
|
||||
+88
-69
@@ -14,7 +14,8 @@ import Component from '../component';
|
||||
import window from 'global/window';
|
||||
import assign from 'object.assign';
|
||||
|
||||
let navigator = window.navigator;
|
||||
const navigator = window.navigator;
|
||||
|
||||
/**
|
||||
* Flash Media Controller - Wrapper for fallback SWF API
|
||||
*
|
||||
@@ -25,12 +26,12 @@ let navigator = window.navigator;
|
||||
*/
|
||||
class Flash extends Tech {
|
||||
|
||||
constructor(options, ready){
|
||||
constructor(options, ready) {
|
||||
super(options, ready);
|
||||
|
||||
// Set the source when ready
|
||||
if (options.source) {
|
||||
this.ready(function(){
|
||||
this.ready(function() {
|
||||
this.setSource(options.source);
|
||||
}, true);
|
||||
}
|
||||
@@ -38,7 +39,7 @@ class Flash extends Tech {
|
||||
// Having issues with Flash reloading on certain page actions (hide/resize/fullscreen) in certain browsers
|
||||
// This allows resetting the playhead when we catch the reload
|
||||
if (options.startTime) {
|
||||
this.ready(function(){
|
||||
this.ready(function() {
|
||||
this.load();
|
||||
this.play();
|
||||
this.currentTime(options.startTime);
|
||||
@@ -67,46 +68,51 @@ class Flash extends Tech {
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
let options = this.options_;
|
||||
const options = this.options_;
|
||||
|
||||
// If video.js is hosted locally you should also set the location
|
||||
// for the hosted swf, which should be relative to the page (not video.js)
|
||||
// Otherwise this adds a CDN url.
|
||||
// The CDN also auto-adds a swf URL for that specific version.
|
||||
if (!options.swf) {
|
||||
options.swf = '//vjs.zencdn.net/swf/__SWF_VERSION__/video-js.swf';
|
||||
const ver = require('videojs-swf/package.json').version;
|
||||
|
||||
options.swf = `//vjs.zencdn.net/swf/${ver}/video-js.swf`;
|
||||
}
|
||||
|
||||
// Generate ID for swf object
|
||||
let objId = options.techId;
|
||||
const objId = options.techId;
|
||||
|
||||
// Merge default flashvars with ones passed in to init
|
||||
let flashVars = assign({
|
||||
const flashVars = assign({
|
||||
|
||||
// SWF Callback Functions
|
||||
'readyFunction': 'videojs.Flash.onReady',
|
||||
'eventProxyFunction': 'videojs.Flash.onEvent',
|
||||
'errorEventProxyFunction': 'videojs.Flash.onError',
|
||||
readyFunction: 'videojs.Flash.onReady',
|
||||
eventProxyFunction: 'videojs.Flash.onEvent',
|
||||
errorEventProxyFunction: 'videojs.Flash.onError',
|
||||
|
||||
// Player Settings
|
||||
'autoplay': options.autoplay,
|
||||
'preload': options.preload,
|
||||
'loop': options.loop,
|
||||
'muted': options.muted
|
||||
autoplay: options.autoplay,
|
||||
preload: options.preload,
|
||||
loop: options.loop,
|
||||
muted: options.muted
|
||||
|
||||
}, options.flashVars);
|
||||
|
||||
// Merge default parames with ones passed in
|
||||
let params = assign({
|
||||
'wmode': 'opaque', // Opaque is needed to overlay controls, but can affect playback performance
|
||||
'bgcolor': '#000000' // Using bgcolor prevents a white flash when the object is loading
|
||||
const params = assign({
|
||||
// Opaque is needed to overlay controls, but can affect playback performance
|
||||
wmode: 'opaque',
|
||||
// Using bgcolor prevents a white flash when the object is loading
|
||||
bgcolor: '#000000'
|
||||
}, options.params);
|
||||
|
||||
// Merge default attributes with ones passed in
|
||||
let attributes = assign({
|
||||
'id': objId,
|
||||
'name': objId, // Both ID and Name needed or swf to identify itself
|
||||
'class': 'vjs-tech'
|
||||
const attributes = assign({
|
||||
// Both ID and Name needed or swf to identify itself
|
||||
id: objId,
|
||||
name: objId,
|
||||
class: 'vjs-tech'
|
||||
}, options.attributes);
|
||||
|
||||
this.el_ = Flash.embed(options.swf, flashVars, params, attributes);
|
||||
@@ -167,8 +173,7 @@ class Flash extends Tech {
|
||||
// Currently the SWF doesn't autoplay if you load a source later.
|
||||
// e.g. Load player w/ no source, wait 2s, set src.
|
||||
if (this.autoplay()) {
|
||||
var tech = this;
|
||||
this.setTimeout(function(){ tech.play(); }, 0);
|
||||
this.setTimeout(() => this.play(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,7 +192,8 @@ class Flash extends Tech {
|
||||
* @method setCurrentTime
|
||||
*/
|
||||
setCurrentTime(time) {
|
||||
let seekable = this.seekable();
|
||||
const seekable = this.seekable();
|
||||
|
||||
if (seekable.length) {
|
||||
// clamp to the current seekable range
|
||||
time = time > seekable.start(0) ? time : seekable.start(0);
|
||||
@@ -224,9 +230,8 @@ class Flash extends Tech {
|
||||
currentSrc() {
|
||||
if (this.currentSource_) {
|
||||
return this.currentSource_.src;
|
||||
} else {
|
||||
return this.el_.vjs_getProperty('currentSrc');
|
||||
}
|
||||
return this.el_.vjs_getProperty('currentSrc');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -237,10 +242,10 @@ class Flash extends Tech {
|
||||
duration() {
|
||||
if (this.readyState() === 0) {
|
||||
return NaN;
|
||||
} else {
|
||||
let duration = this.el_.vjs_getProperty('duration');
|
||||
return duration >= 0 ? duration : Infinity;
|
||||
}
|
||||
const duration = this.el_.vjs_getProperty('duration');
|
||||
|
||||
return duration >= 0 ? duration : Infinity;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -276,6 +281,7 @@ class Flash extends Tech {
|
||||
*/
|
||||
seekable() {
|
||||
const duration = this.duration();
|
||||
|
||||
if (duration === 0) {
|
||||
return createTimeRange();
|
||||
}
|
||||
@@ -289,7 +295,8 @@ class Flash extends Tech {
|
||||
* @method buffered
|
||||
*/
|
||||
buffered() {
|
||||
let ranges = this.el_.vjs_getProperty('buffered');
|
||||
const ranges = this.el_.vjs_getProperty('buffered');
|
||||
|
||||
if (ranges.length === 0) {
|
||||
return createTimeRange();
|
||||
}
|
||||
@@ -305,7 +312,8 @@ class Flash extends Tech {
|
||||
* @method supportsFullScreen
|
||||
*/
|
||||
supportsFullScreen() {
|
||||
return false; // Flash does not allow fullscreen through javascript
|
||||
// Flash does not allow fullscreen through javascript
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -322,18 +330,23 @@ class Flash extends Tech {
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Create setters and getters for attributes
|
||||
const _api = Flash.prototype;
|
||||
const _readWrite = 'rtmpConnection,rtmpStream,preload,defaultPlaybackRate,playbackRate,autoplay,loop,mediaGroup,controller,controls,volume,muted,defaultMuted'.split(',');
|
||||
const _readOnly = 'networkState,readyState,initialTime,startOffsetTime,paused,ended,videoWidth,videoHeight'.split(',');
|
||||
|
||||
function _createSetter(attr){
|
||||
var attrUpper = attr.charAt(0).toUpperCase() + attr.slice(1);
|
||||
_api['set'+attrUpper] = function(val){ return this.el_.vjs_setProperty(attr, val); };
|
||||
function _createSetter(attr) {
|
||||
const attrUpper = attr.charAt(0).toUpperCase() + attr.slice(1);
|
||||
|
||||
_api['set' + attrUpper] = function(val) {
|
||||
return this.el_.vjs_setProperty(attr, val);
|
||||
};
|
||||
}
|
||||
|
||||
function _createGetter(attr) {
|
||||
_api[attr] = function(){ return this.el_.vjs_getProperty(attr); };
|
||||
_api[attr] = function() {
|
||||
return this.el_.vjs_getProperty(attr);
|
||||
};
|
||||
}
|
||||
|
||||
// Create getter and setters for all read/write attributes
|
||||
@@ -349,7 +362,7 @@ for (let i = 0; i < _readOnly.length; i++) {
|
||||
|
||||
/* Flash Support Testing -------------------------------------------------------- */
|
||||
|
||||
Flash.isSupported = function(){
|
||||
Flash.isSupported = function() {
|
||||
return Flash.version()[0] >= 10;
|
||||
// return swfobject.hasFlashPlayerVersion('10');
|
||||
};
|
||||
@@ -371,7 +384,7 @@ Flash.nativeSourceHandler = {};
|
||||
* @param {String} type The mimetype to check
|
||||
* @return {String} 'probably', 'maybe', or '' (empty string)
|
||||
*/
|
||||
Flash.nativeSourceHandler.canPlayType = function(type){
|
||||
Flash.nativeSourceHandler.canPlayType = function(type) {
|
||||
if (type in Flash.formats) {
|
||||
return 'maybe';
|
||||
}
|
||||
@@ -386,11 +399,12 @@ Flash.nativeSourceHandler.canPlayType = function(type){
|
||||
* @param {Object} options The options passed to the tech
|
||||
* @return {String} 'probably', 'maybe', or '' (empty string)
|
||||
*/
|
||||
Flash.nativeSourceHandler.canHandleSource = function(source, options){
|
||||
var type;
|
||||
Flash.nativeSourceHandler.canHandleSource = function(source, options) {
|
||||
let type;
|
||||
|
||||
function guessMimeType(src) {
|
||||
var ext = Url.getFileExtension(src);
|
||||
const ext = Url.getFileExtension(src);
|
||||
|
||||
if (ext) {
|
||||
return `video/${ext}`;
|
||||
}
|
||||
@@ -416,7 +430,7 @@ Flash.nativeSourceHandler.canHandleSource = function(source, options){
|
||||
* @param {Flash} tech The instance of the Flash tech
|
||||
* @param {Object} options The options to pass to the source
|
||||
*/
|
||||
Flash.nativeSourceHandler.handleSource = function(source, tech, options){
|
||||
Flash.nativeSourceHandler.handleSource = function(source, tech, options) {
|
||||
tech.setSrc(source.src);
|
||||
};
|
||||
|
||||
@@ -424,7 +438,7 @@ Flash.nativeSourceHandler.handleSource = function(source, tech, options){
|
||||
* Clean up the source handler when disposing the player or switching sources..
|
||||
* (no cleanup is needed when supporting the format natively)
|
||||
*/
|
||||
Flash.nativeSourceHandler.dispose = function(){};
|
||||
Flash.nativeSourceHandler.dispose = function() {};
|
||||
|
||||
// Register the native source handler
|
||||
Flash.registerSourceHandler(Flash.nativeSourceHandler);
|
||||
@@ -436,9 +450,9 @@ Flash.formats = {
|
||||
'video/m4v': 'MP4'
|
||||
};
|
||||
|
||||
Flash.onReady = function(currSwf){
|
||||
let el = Dom.getEl(currSwf);
|
||||
let tech = el && el.tech;
|
||||
Flash.onReady = function(currSwf) {
|
||||
const el = Dom.getEl(currSwf);
|
||||
const tech = el && el.tech;
|
||||
|
||||
// if there is no el then the tech has been disposed
|
||||
// and the tech element was removed from the player div
|
||||
@@ -450,7 +464,7 @@ Flash.onReady = function(currSwf){
|
||||
|
||||
// The SWF isn't always ready when it says it is. Sometimes the API functions still need to be added to the object.
|
||||
// If it's not ready, we set a timeout to check again shortly.
|
||||
Flash.checkReady = function(tech){
|
||||
Flash.checkReady = function(tech) {
|
||||
// stop worrying if the tech has been disposed
|
||||
if (!tech.el()) {
|
||||
return;
|
||||
@@ -462,20 +476,21 @@ Flash.checkReady = function(tech){
|
||||
tech.triggerReady();
|
||||
} else {
|
||||
// wait longer
|
||||
this.setTimeout(function(){
|
||||
Flash['checkReady'](tech);
|
||||
this.setTimeout(function() {
|
||||
Flash.checkReady(tech);
|
||||
}, 50);
|
||||
}
|
||||
};
|
||||
|
||||
// Trigger events from the swf on the player
|
||||
Flash.onEvent = function(swfID, eventName){
|
||||
let tech = Dom.getEl(swfID).tech;
|
||||
Flash.onEvent = function(swfID, eventName) {
|
||||
const tech = Dom.getEl(swfID).tech;
|
||||
|
||||
tech.trigger(eventName, Array.prototype.slice.call(arguments, 2));
|
||||
};
|
||||
|
||||
// Log errors from the swf
|
||||
Flash.onError = function(swfID, err){
|
||||
Flash.onError = function(swfID, err) {
|
||||
const tech = Dom.getEl(swfID).tech;
|
||||
|
||||
// trigger MEDIA_ERR_SRC_NOT_SUPPORTED
|
||||
@@ -488,7 +503,7 @@ Flash.onError = function(swfID, err){
|
||||
};
|
||||
|
||||
// Flash Version Check
|
||||
Flash.version = function(){
|
||||
Flash.version = function() {
|
||||
let version = '0,0,0';
|
||||
|
||||
// IE
|
||||
@@ -496,18 +511,20 @@ Flash.version = function(){
|
||||
version = new window.ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
|
||||
|
||||
// other browsers
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
try {
|
||||
if (navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin){
|
||||
if (navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin) {
|
||||
version = (navigator.plugins['Shockwave Flash 2.0'] || navigator.plugins['Shockwave Flash']).description.replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
|
||||
}
|
||||
} catch(err) {}
|
||||
} catch (err) {
|
||||
// satisfy linter
|
||||
}
|
||||
}
|
||||
return version.split(',');
|
||||
};
|
||||
|
||||
// Flash embedding method. Only used in non-iframe mode
|
||||
Flash.embed = function(swf, flashVars, params, attributes){
|
||||
Flash.embed = function(swf, flashVars, params, attributes) {
|
||||
const code = Flash.getEmbedCode(swf, flashVars, params, attributes);
|
||||
|
||||
// Get element by embedding code and retrieving created element
|
||||
@@ -516,7 +533,7 @@ Flash.embed = function(swf, flashVars, params, attributes){
|
||||
return obj;
|
||||
};
|
||||
|
||||
Flash.getEmbedCode = function(swf, flashVars, params, attributes){
|
||||
Flash.getEmbedCode = function(swf, flashVars, params, attributes) {
|
||||
const objTag = '<object type="application/x-shockwave-flash" ';
|
||||
let flashVarsString = '';
|
||||
let paramsString = '';
|
||||
@@ -524,36 +541,38 @@ Flash.getEmbedCode = function(swf, flashVars, params, attributes){
|
||||
|
||||
// Convert flash vars to string
|
||||
if (flashVars) {
|
||||
Object.getOwnPropertyNames(flashVars).forEach(function(key){
|
||||
Object.getOwnPropertyNames(flashVars).forEach(function(key) {
|
||||
flashVarsString += `${key}=${flashVars[key]}&`;
|
||||
});
|
||||
}
|
||||
|
||||
// Add swf, flashVars, and other default params
|
||||
params = assign({
|
||||
'movie': swf,
|
||||
'flashvars': flashVarsString,
|
||||
'allowScriptAccess': 'always', // Required to talk to swf
|
||||
'allowNetworking': 'all' // All should be default, but having security issues.
|
||||
movie: swf,
|
||||
flashvars: flashVarsString,
|
||||
// Required to talk to swf
|
||||
allowScriptAccess: 'always',
|
||||
// All should be default, but having security issues.
|
||||
allowNetworking: 'all'
|
||||
}, params);
|
||||
|
||||
// Create param tags string
|
||||
Object.getOwnPropertyNames(params).forEach(function(key){
|
||||
Object.getOwnPropertyNames(params).forEach(function(key) {
|
||||
paramsString += `<param name="${key}" value="${params[key]}" />`;
|
||||
});
|
||||
|
||||
attributes = assign({
|
||||
// Add swf to attributes (need both for IE and Others to work)
|
||||
'data': swf,
|
||||
data: swf,
|
||||
|
||||
// Default to 100% width/height
|
||||
'width': '100%',
|
||||
'height': '100%'
|
||||
width: '100%',
|
||||
height: '100%'
|
||||
|
||||
}, attributes);
|
||||
|
||||
// Create Attributes string
|
||||
Object.getOwnPropertyNames(attributes).forEach(function(key){
|
||||
Object.getOwnPropertyNames(attributes).forEach(function(key) {
|
||||
attrsString += `${key}="${attributes[key]}" `;
|
||||
});
|
||||
|
||||
|
||||
+229
-130
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+10
-10
@@ -3,7 +3,6 @@
|
||||
*/
|
||||
import Component from '../component.js';
|
||||
import Tech from './tech.js';
|
||||
import window from 'global/window';
|
||||
import toTitleCase from '../utils/to-title-case.js';
|
||||
|
||||
/**
|
||||
@@ -18,16 +17,17 @@ import toTitleCase from '../utils/to-title-case.js';
|
||||
*/
|
||||
class MediaLoader extends Component {
|
||||
|
||||
constructor(player, options, ready){
|
||||
constructor(player, options, ready) {
|
||||
super(player, options, ready);
|
||||
|
||||
// If there are no sources when the player is initialized,
|
||||
// load the first supported playback technology.
|
||||
|
||||
if (!options.playerOptions['sources'] || options.playerOptions['sources'].length === 0) {
|
||||
for (let i=0, j=options.playerOptions['techOrder']; i<j.length; i++) {
|
||||
let techName = toTitleCase(j[i]);
|
||||
if (!options.playerOptions.sources || options.playerOptions.sources.length === 0) {
|
||||
for (let i = 0, j = options.playerOptions.techOrder; i < j.length; i++) {
|
||||
const techName = toTitleCase(j[i]);
|
||||
let tech = Tech.getTech(techName);
|
||||
|
||||
// Support old behavior of techs being registered as components.
|
||||
// Remove once that deprecated behavior is removed.
|
||||
if (!techName) {
|
||||
@@ -41,11 +41,11 @@ class MediaLoader extends Component {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// // Loop through playback technologies (HTML5, Flash) and check for support.
|
||||
// // Then load the best source.
|
||||
// // A few assumptions here:
|
||||
// // All playback technologies respect preload false.
|
||||
player.src(options.playerOptions['sources']);
|
||||
// Loop through playback technologies (HTML5, Flash) and check for support.
|
||||
// Then load the best source.
|
||||
// A few assumptions here:
|
||||
// All playback technologies respect preload false.
|
||||
player.src(options.playerOptions.sources);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+110
-100
@@ -10,10 +10,8 @@ import HTMLTrackElementList from '../tracks/html-track-element-list';
|
||||
import mergeOptions from '../utils/merge-options.js';
|
||||
import TextTrack from '../tracks/text-track';
|
||||
import TextTrackList from '../tracks/text-track-list';
|
||||
import VideoTrack from '../tracks/video-track';
|
||||
import VideoTrackList from '../tracks/video-track-list';
|
||||
import AudioTrackList from '../tracks/audio-track-list';
|
||||
import AudioTrack from '../tracks/audio-track';
|
||||
import * as Fn from '../utils/fn.js';
|
||||
import log from '../utils/log.js';
|
||||
import { createTimeRange } from '../utils/time-ranges.js';
|
||||
@@ -22,6 +20,26 @@ import MediaError from '../media-error.js';
|
||||
import window from 'global/window';
|
||||
import document from 'global/document';
|
||||
|
||||
function createTrackHelper(self, kind, label, language, options = {}) {
|
||||
const tracks = self.textTracks();
|
||||
|
||||
options.kind = kind;
|
||||
|
||||
if (label) {
|
||||
options.label = label;
|
||||
}
|
||||
if (language) {
|
||||
options.language = language;
|
||||
}
|
||||
options.tech = self;
|
||||
|
||||
const track = new TextTrack(options);
|
||||
|
||||
tracks.addTrack_(track);
|
||||
|
||||
return track;
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class for media (HTML5 Video, Flash) controllers
|
||||
*
|
||||
@@ -32,7 +50,7 @@ import document from 'global/document';
|
||||
*/
|
||||
class Tech extends Component {
|
||||
|
||||
constructor(options={}, ready=function(){}){
|
||||
constructor(options = {}, ready = function() {}) {
|
||||
// we don't want the tech to report user activity automatically.
|
||||
// This is done manually in addControlsListeners
|
||||
options.reportTouchActivity = false;
|
||||
@@ -114,10 +132,10 @@ class Tech extends Component {
|
||||
*/
|
||||
trackProgress() {
|
||||
this.stopTrackingProgress();
|
||||
this.progressInterval = this.setInterval(Fn.bind(this, function(){
|
||||
this.progressInterval = this.setInterval(Fn.bind(this, function() {
|
||||
// Don't trigger unless buffered amount is greater than last time
|
||||
|
||||
let numBufferedPercent = this.bufferedPercent();
|
||||
const numBufferedPercent = this.bufferedPercent();
|
||||
|
||||
if (this.bufferedPercent_ !== numBufferedPercent) {
|
||||
this.trigger('progress');
|
||||
@@ -169,7 +187,6 @@ class Tech extends Component {
|
||||
this.clearInterval(this.progressInterval);
|
||||
}
|
||||
|
||||
/*! Time Tracking -------------------------------------------------------------- */
|
||||
/**
|
||||
* Set event listeners for on play and pause and tracking current time
|
||||
*
|
||||
@@ -200,10 +217,14 @@ class Tech extends Component {
|
||||
* @method trackCurrentTime
|
||||
*/
|
||||
trackCurrentTime() {
|
||||
if (this.currentTimeInterval) { this.stopTrackingCurrentTime(); }
|
||||
this.currentTimeInterval = this.setInterval(function(){
|
||||
if (this.currentTimeInterval) {
|
||||
this.stopTrackingCurrentTime();
|
||||
}
|
||||
this.currentTimeInterval = this.setInterval(function() {
|
||||
this.trigger({ type: 'timeupdate', target: this, manuallyTriggered: true });
|
||||
}, 250); // 42 = 24 fps // 250 is what Webkit uses // FF uses 15
|
||||
|
||||
// 42 = 24 fps // 250 is what Webkit uses // FF uses 15
|
||||
}, 250);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -230,9 +251,13 @@ class Tech extends Component {
|
||||
this.clearTracks(['audio', 'video', 'text']);
|
||||
|
||||
// Turn off any manual progress or timeupdate tracking
|
||||
if (this.manualProgress) { this.manualProgressOff(); }
|
||||
if (this.manualProgress) {
|
||||
this.manualProgressOff();
|
||||
}
|
||||
|
||||
if (this.manualTimeUpdates) { this.manualTimeUpdatesOff(); }
|
||||
if (this.manualTimeUpdates) {
|
||||
this.manualTimeUpdatesOff();
|
||||
}
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
@@ -252,10 +277,12 @@ class Tech extends Component {
|
||||
types = [].concat(types);
|
||||
// clear out all tracks because we can't reuse them between techs
|
||||
types.forEach((type) => {
|
||||
let list = this[`${type}Tracks`]() || [];
|
||||
const list = this[`${type}Tracks`]() || [];
|
||||
let i = list.length;
|
||||
|
||||
while (i--) {
|
||||
let track = list[i];
|
||||
const track = list[i];
|
||||
|
||||
if (type === 'text') {
|
||||
this.removeRemoteTextTrack(track);
|
||||
}
|
||||
@@ -282,11 +309,7 @@ class Tech extends Component {
|
||||
*/
|
||||
error(err) {
|
||||
if (err !== undefined) {
|
||||
if (err instanceof MediaError) {
|
||||
this.error_ = err;
|
||||
} else {
|
||||
this.error_ = new MediaError(err);
|
||||
}
|
||||
this.error_ = new MediaError(err);
|
||||
this.trigger('error');
|
||||
}
|
||||
return this.error_;
|
||||
@@ -315,7 +338,9 @@ class Tech extends Component {
|
||||
*/
|
||||
setCurrentTime() {
|
||||
// improve the accuracy of manual timeupdates
|
||||
if (this.manualTimeUpdates) { this.trigger({ type: 'timeupdate', target: this, manuallyTriggered: true }); }
|
||||
if (this.manualTimeUpdates) {
|
||||
this.trigger({ type: 'timeupdate', target: this, manuallyTriggered: true });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -324,13 +349,15 @@ class Tech extends Component {
|
||||
* @method initTextTrackListeners
|
||||
*/
|
||||
initTextTrackListeners() {
|
||||
let textTrackListChanges = Fn.bind(this, function() {
|
||||
const textTrackListChanges = Fn.bind(this, function() {
|
||||
this.trigger('texttrackchange');
|
||||
});
|
||||
|
||||
let tracks = this.textTracks();
|
||||
const tracks = this.textTracks();
|
||||
|
||||
if (!tracks) return;
|
||||
if (!tracks) {
|
||||
return;
|
||||
}
|
||||
|
||||
tracks.addEventListener('removetrack', textTrackListChanges);
|
||||
tracks.addEventListener('addtrack', textTrackListChanges);
|
||||
@@ -341,7 +368,6 @@ class Tech extends Component {
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize audio and video track listeners
|
||||
*
|
||||
@@ -351,11 +377,11 @@ class Tech extends Component {
|
||||
const trackTypes = ['video', 'audio'];
|
||||
|
||||
trackTypes.forEach((type) => {
|
||||
let trackListChanges = () => {
|
||||
const trackListChanges = () => {
|
||||
this.trigger(`${type}trackchange`);
|
||||
};
|
||||
|
||||
let tracks = this[`${type}Tracks`]();
|
||||
const tracks = this[`${type}Tracks`]();
|
||||
|
||||
tracks.addEventListener('removetrack', trackListChanges);
|
||||
tracks.addEventListener('addtrack', trackListChanges);
|
||||
@@ -373,13 +399,15 @@ class Tech extends Component {
|
||||
* @method emulateTextTracks
|
||||
*/
|
||||
emulateTextTracks() {
|
||||
let tracks = this.textTracks();
|
||||
const tracks = this.textTracks();
|
||||
|
||||
if (!tracks) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!window['WebVTT'] && this.el().parentNode != null) {
|
||||
let script = document.createElement('script');
|
||||
if (!window.WebVTT && this.el().parentNode !== null && this.el().parentNode !== undefined) {
|
||||
const script = document.createElement('script');
|
||||
|
||||
script.src = this.options_['vtt.js'] || '../node_modules/videojs-vtt.js/dist/vtt.js';
|
||||
script.onload = () => {
|
||||
this.trigger('vttjsloaded');
|
||||
@@ -393,16 +421,17 @@ class Tech extends Component {
|
||||
});
|
||||
// but have not loaded yet and we set it to true before the inject so that
|
||||
// we don't overwrite the injected window.WebVTT if it loads right away
|
||||
window['WebVTT'] = true;
|
||||
window.WebVTT = true;
|
||||
this.el().parentNode.appendChild(script);
|
||||
}
|
||||
|
||||
let updateDisplay = () => this.trigger('texttrackchange');
|
||||
let textTracksChanges = () => {
|
||||
const updateDisplay = () => this.trigger('texttrackchange');
|
||||
const textTracksChanges = () => {
|
||||
updateDisplay();
|
||||
|
||||
for (let i = 0; i < tracks.length; i++) {
|
||||
let track = tracks[i];
|
||||
const track = tracks[i];
|
||||
|
||||
track.removeEventListener('cuechange', updateDisplay);
|
||||
if (track.mode === 'showing') {
|
||||
track.addEventListener('cuechange', updateDisplay);
|
||||
@@ -506,11 +535,11 @@ class Tech extends Component {
|
||||
* @method addRemoteTextTrack
|
||||
*/
|
||||
addRemoteTextTrack(options) {
|
||||
let track = mergeOptions(options, {
|
||||
const track = mergeOptions(options, {
|
||||
tech: this
|
||||
});
|
||||
|
||||
let htmlTrackElement = new HTMLTrackElement(track);
|
||||
const htmlTrackElement = new HTMLTrackElement(track);
|
||||
|
||||
// store HTMLTrackElement and TextTrack to remote list
|
||||
this.remoteTextTrackEls().addTrackElement_(htmlTrackElement);
|
||||
@@ -531,7 +560,7 @@ class Tech extends Component {
|
||||
removeRemoteTextTrack(track) {
|
||||
this.textTracks().removeTrack_(track);
|
||||
|
||||
let trackElement = this.remoteTextTrackEls().getTrackElementByTrack_(track);
|
||||
const trackElement = this.remoteTextTrackEls().getTrackElementByTrack_(track);
|
||||
|
||||
// remove HTMLTrackElement and TextTrack from remote list
|
||||
this.remoteTextTrackEls().removeTrackElement_(trackElement);
|
||||
@@ -620,7 +649,7 @@ class Tech extends Component {
|
||||
* @type {TextTrackList}
|
||||
* @private
|
||||
*/
|
||||
Tech.prototype.textTracks_;
|
||||
Tech.prototype.textTracks_; // eslint-disable-line
|
||||
|
||||
/**
|
||||
* List of associated audio tracks
|
||||
@@ -628,7 +657,7 @@ Tech.prototype.textTracks_;
|
||||
* @type {AudioTrackList}
|
||||
* @private
|
||||
*/
|
||||
Tech.prototype.audioTracks_;
|
||||
Tech.prototype.audioTracks_; // eslint-disable-line
|
||||
|
||||
/**
|
||||
* List of associated video tracks
|
||||
@@ -636,27 +665,7 @@ Tech.prototype.audioTracks_;
|
||||
* @type {VideoTrackList}
|
||||
* @private
|
||||
*/
|
||||
Tech.prototype.videoTracks_;
|
||||
|
||||
|
||||
var createTrackHelper = function(self, kind, label, language, options={}) {
|
||||
let tracks = self.textTracks();
|
||||
|
||||
options.kind = kind;
|
||||
|
||||
if (label) {
|
||||
options.label = label;
|
||||
}
|
||||
if (language) {
|
||||
options.language = language;
|
||||
}
|
||||
options.tech = self;
|
||||
|
||||
let track = new TextTrack(options);
|
||||
tracks.addTrack_(track);
|
||||
|
||||
return track;
|
||||
};
|
||||
Tech.prototype.videoTracks_; // eslint-disable-line
|
||||
|
||||
Tech.prototype.featuresVolumeControl = true;
|
||||
|
||||
@@ -671,7 +680,7 @@ Tech.prototype.featuresTimeupdateEvents = false;
|
||||
|
||||
Tech.prototype.featuresNativeTextTracks = false;
|
||||
|
||||
/*
|
||||
/**
|
||||
* A functional mixin for techs that want to use the Source Handler pattern.
|
||||
*
|
||||
* ##### EXAMPLE:
|
||||
@@ -679,16 +688,17 @@ Tech.prototype.featuresNativeTextTracks = false;
|
||||
* Tech.withSourceHandlers.call(MyTech);
|
||||
*
|
||||
*/
|
||||
Tech.withSourceHandlers = function(_Tech){
|
||||
/*
|
||||
* Register a source handler
|
||||
* Source handlers are scripts for handling specific formats.
|
||||
* The source handler pattern is used for adaptive formats (HLS, DASH) that
|
||||
* manually load video data and feed it into a Source Buffer (Media Source Extensions)
|
||||
* @param {Function} handler The source handler
|
||||
* @param {Boolean} first Register it before any existing handlers
|
||||
*/
|
||||
_Tech.registerSourceHandler = function(handler, index){
|
||||
Tech.withSourceHandlers = function(_Tech) {
|
||||
|
||||
/**
|
||||
* Register a source handler
|
||||
* Source handlers are scripts for handling specific formats.
|
||||
* The source handler pattern is used for adaptive formats (HLS, DASH) that
|
||||
* manually load video data and feed it into a Source Buffer (Media Source Extensions)
|
||||
* @param {Function} handler The source handler
|
||||
* @param {Boolean} first Register it before any existing handlers
|
||||
*/
|
||||
_Tech.registerSourceHandler = function(handler, index) {
|
||||
let handlers = _Tech.sourceHandlers;
|
||||
|
||||
if (!handlers) {
|
||||
@@ -703,13 +713,13 @@ Tech.withSourceHandlers = function(_Tech){
|
||||
handlers.splice(index, 0, handler);
|
||||
};
|
||||
|
||||
/*
|
||||
/**
|
||||
* Check if the tech can support the given type
|
||||
* @param {String} type The mimetype to check
|
||||
* @return {String} 'probably', 'maybe', or '' (empty string)
|
||||
*/
|
||||
_Tech.canPlayType = function(type){
|
||||
let handlers = _Tech.sourceHandlers || [];
|
||||
_Tech.canPlayType = function(type) {
|
||||
const handlers = _Tech.sourceHandlers || [];
|
||||
let can;
|
||||
|
||||
for (let i = 0; i < handlers.length; i++) {
|
||||
@@ -723,16 +733,16 @@ Tech.withSourceHandlers = function(_Tech){
|
||||
return '';
|
||||
};
|
||||
|
||||
/*
|
||||
* Return the first source handler that supports the source
|
||||
* TODO: Answer question: should 'probably' be prioritized over 'maybe'
|
||||
* @param {Object} source The source object
|
||||
* @param {Object} options The options passed to the tech
|
||||
* @returns {Object} The first source handler that supports the source
|
||||
* @returns {null} Null if no source handler is found
|
||||
*/
|
||||
_Tech.selectSourceHandler = function(source, options){
|
||||
let handlers = _Tech.sourceHandlers || [];
|
||||
/**
|
||||
* Return the first source handler that supports the source
|
||||
* TODO: Answer question: should 'probably' be prioritized over 'maybe'
|
||||
* @param {Object} source The source object
|
||||
* @param {Object} options The options passed to the tech
|
||||
* @returns {Object} The first source handler that supports the source
|
||||
* @returns {null} Null if no source handler is found
|
||||
*/
|
||||
_Tech.selectSourceHandler = function(source, options) {
|
||||
const handlers = _Tech.sourceHandlers || [];
|
||||
let can;
|
||||
|
||||
for (let i = 0; i < handlers.length; i++) {
|
||||
@@ -746,14 +756,14 @@ Tech.withSourceHandlers = function(_Tech){
|
||||
return null;
|
||||
};
|
||||
|
||||
/*
|
||||
/**
|
||||
* Check if the tech can support the given source
|
||||
* @param {Object} srcObj The source object
|
||||
* @param {Object} options The options passed to the tech
|
||||
* @return {String} 'probably', 'maybe', or '' (empty string)
|
||||
*/
|
||||
_Tech.canPlaySource = function(srcObj, options){
|
||||
let sh = _Tech.selectSourceHandler(srcObj, options);
|
||||
_Tech.canPlaySource = function(srcObj, options) {
|
||||
const sh = _Tech.selectSourceHandler(srcObj, options);
|
||||
|
||||
if (sh) {
|
||||
return sh.canHandleSource(srcObj, options);
|
||||
@@ -762,17 +772,17 @@ Tech.withSourceHandlers = function(_Tech){
|
||||
return '';
|
||||
};
|
||||
|
||||
/*
|
||||
/**
|
||||
* When using a source handler, prefer its implementation of
|
||||
* any function normally provided by the tech.
|
||||
*/
|
||||
let deferrable = [
|
||||
'seekable',
|
||||
'duration'
|
||||
];
|
||||
const deferrable = [
|
||||
'seekable',
|
||||
'duration'
|
||||
];
|
||||
|
||||
deferrable.forEach(function (fnName) {
|
||||
let originalFn = this[fnName];
|
||||
deferrable.forEach(function(fnName) {
|
||||
const originalFn = this[fnName];
|
||||
|
||||
if (typeof originalFn !== 'function') {
|
||||
return;
|
||||
@@ -786,14 +796,14 @@ Tech.withSourceHandlers = function(_Tech){
|
||||
};
|
||||
}, _Tech.prototype);
|
||||
|
||||
/*
|
||||
* Create a function for setting the source using a source object
|
||||
* and source handlers.
|
||||
* Should never be called unless a source handler was found.
|
||||
* @param {Object} source A source object with src and type keys
|
||||
* @return {Tech} self
|
||||
*/
|
||||
_Tech.prototype.setSource = function(source){
|
||||
/**
|
||||
* Create a function for setting the source using a source object
|
||||
* and source handlers.
|
||||
* Should never be called unless a source handler was found.
|
||||
* @param {Object} source A source object with src and type keys
|
||||
* @return {Tech} self
|
||||
*/
|
||||
_Tech.prototype.setSource = function(source) {
|
||||
let sh = _Tech.selectSourceHandler(source, this.options_);
|
||||
|
||||
if (!sh) {
|
||||
|
||||
Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais
Referência em uma Nova Issue
Bloquear um usuário