Comparar commits

..

67 Commits

Autor SHA1 Mensagem Data
Gary Katsevman 4944f85888 v5.12.2 dist 2016-09-28 17:48:34 -04:00
Gary Katsevman 5f95e413e3 v5.12.2 2016-09-28 17:47:55 -04:00
Gary Katsevman 057588f6c7 Update CHANGELOG.md 2016-09-28 17:45:48 -04:00
Gary Katsevman 7cf2de30ac Merge branch 'stable' 2016-09-28 16:28:21 -04:00
Gary d520d29fd6 v5.11.7 2016-09-28 18:40:33 +00:00
Gary Katsevman 3a927523c3 @gkatsev set playerId on new el created for movingMediaElementInDOM. Fixes #3283. closes #3648 2016-09-28 13:59:21 -04:00
Pat O'Neill ecc95331a7 @misteroneill pinned grunt-contrib-uglify to ~0.11 to pin uglify to ~2.6. closes #3634 2016-09-28 13:54:41 -04:00
Gary Katsevman 282bda7e34 @gkatsev checked throwIfWhitespace first in hasElClass. closes #3640 2016-09-28 13:18:02 -04:00
Gary Katsevman 3a859f97d0 v5.12.1 2016-08-25 19:47:31 -04:00
Gary Katsevman 0d0ff90ca1 5.12.0 2016-08-25 19:47:02 -04:00
Gary Katsevman b4265a8468 v5.13.0 2016-08-25 19:34:46 -04:00
Gary Katsevman fac52046f3 Merge branch 'stable' 2016-08-25 19:34:07 -04:00
Jon-Carlos a17de688f3 v5.11.6 2016-08-25 23:17:28 +00:00
Jon-Carlos Rivera fdd8550307 @imbcmdth Added exception handling to event dispatcher. closes #3580
* Guard against exceptions in an event handler to stop them from breaking further processing of event handlers

* Added a test for try/catch behavior for exceptions originating in event handlers
2016-08-25 19:08:56 -04:00
Gary Katsevman 83b372c0d4 v5.12.0 2016-08-25 16:44:58 -04:00
Gary Katsevman daab267736 @gkatsev added webpack to test build. closes #3579 2016-08-25 16:24:31 -04:00
Gary Katsevman 8beab2791a @gkatsev updated the translation-needed doc. closes #3578 2016-08-25 16:01:10 -04:00
Lionel 2d9d6b9e46 @lionel-m updated french translations. closes #3576 2016-08-25 15:51:54 -04:00
mister-ben 94f22bb995 @mister-ben added task to maintain translations. closes #3572 2016-08-25 15:49:40 -04:00
Gary Katsevman 0b10b69775 @gkatsev added es2015 babel preset as a dependency. closes #3577 2016-08-25 14:46:38 -04:00
Gary Katsevman f37383784d Merge branch 'stable' 2016-08-25 12:19:03 -04:00
Justin eff1cf34db v5.11.5 2016-08-25 15:49:03 +00:00
Justin Barabander a2167a6b95 @jbarabander updated Audio to Audio Track and added to en.json. closes #3574 2016-08-25 11:01:13 -04:00
Richard L. Chung af6beb21c3 @rlchung fixed tests that weren't disposing players when they finished. closes 3524 2016-08-25 10:58:42 -04:00
brandonocasey ebf7718f1b @BrandonOCasey linted the sass files. closes #3559 2016-08-24 16:46:27 -04:00
Pat O'Neill 80851ea7ca @misteroneill added npm scripts for standard actions to match plugin generator. closes #3563 2016-08-24 16:44:58 -04:00
Gary Katsevman c154518df4 @gkatsev added tests for webpack and browserify bundling and node.js requiring. closes #3558 2016-08-24 16:32:05 -04:00
Pat O'Neill 1d2d08584e @misteroneill fixed IE8 media error test failure. closes #3568 2016-08-24 13:48:39 -04:00
Justin Barabander 46d713589b @jbarabander added title attribute to audio button. Fixes #3528. closes #3565 2016-08-24 11:30:37 -04:00
David Snyder 23d1fcd882 @snyderizer fixed switching between audio tracks. Fixes #3510. closes #3538 2016-08-24 11:24:55 -04:00
Pat O'Neill b56ed61523 @misteroneill fixed wrapping native and emulated MediaErrors. closes #3562 2016-08-24 11:00:21 -04:00
Greenkeeper b90f04fc3b Update karma-chrome-launcher to version 2.0.0 🚀 (#3553)
* chore(package): update karma-chrome-launcher to version 2.0.0

https://greenkeeper.io/

* update CHANGELOG
2016-08-22 17:56:10 -04:00
Gary Katsevman 141ecf221b @gkatsev made videojs requirable in node. closes #3540 2016-08-22 14:20:23 -04:00
Yanglin Zhao c859d8e104 @yanglinz enabled local coverage reporting with 'npm test --coverage'. closes #3539 2016-08-17 18:32:48 -04:00
Greenkeeper f787cbad18 Update grunt-concurrent to version 2.3.1 🚀 (#3532)
* chore(package): update grunt-concurrent to version 2.3.1

https://greenkeeper.io/

* update CHANGELOG
2016-08-17 18:08:24 -04:00
Greenkeeper 46058ddb0f Update uglify-js to version 2.7.3 🚀 (#3547)
* chore(package): update uglify-js to version 2.7.3

https://greenkeeper.io/

* update CHANGELOG
2016-08-17 17:53:46 -04:00
Gary Katsevman 955185379f @gkatsev updated build system to open es5 folder for bundles and dist folder other users. closes #3445 2016-08-17 17:16:41 -04:00
Gary Katsevman d58be409a6 Merge branch 'stable' 2016-08-16 14:28:25 -04:00
Gary Katsevman 13d16c1d76 v5.11.4 2016-08-16 14:27:22 -04:00
Gary Katsevman 773b5ab1c1 Merge branch 'stable' 2016-08-15 18:20:47 -04:00
Gary Katsevman 5178c122a5 v5.11.3 2016-08-15 18:11:54 -04:00
Gary Katsevman db0e821f38 Add DOMException to jshint to appease it 2016-08-15 18:02:41 -04:00
mister-ben fa1c6430f4 @mister-ben silenced chrome's play() request was interrupted by pause() error. closes #3518 2016-08-15 17:49:52 -04:00
Matthew Boles bf2eabf82d @mboles updated duration() method documentation. closes #3515 2016-08-15 17:46:59 -04:00
mister-ben 2f5a0ca48b @mister-ben fixed android treating swipe as a tap. closes #3514 2016-08-15 17:45:38 -04:00
Vineet 2c84f45ff3 @vdeshpande fixed control text for fullscreen button. closes #3485 2016-08-15 17:44:01 -04:00
Gary Katsevman 6385d1d429 @gkatsev reverted back to qunitjs 1.x to unbreak IE8. Added es5-shim to tests. closes #3533 2016-08-12 23:53:08 -04:00
Gary Katsevman 4ae370c1a2 @gkatsev added slack badge to README. closes #3527 2016-08-12 23:39:18 -04:00
Pat O'Neill 72c44daaf3 @misteroneill updated tests to qunit 2.0. closes #3509 2016-08-12 13:51:31 -04:00
Pat O'Neill b3e4e95f9c @misteroneill enabled and updated videojs-standard and fixed an issue with linting. closes #3508 2016-08-11 18:33:34 -04:00
Gary Katsevman ab82bf0008 @gkatsev removed unused dependencies. closes #3516 2016-08-11 18:13:37 -04:00
brandonocasey 1bb40b8d14 @BrandonOCasey updated language docs to link to IANA language registry. closes #3493 2016-08-11 18:09:48 -04:00
Greenkeeper f2a21d4aa2 Update karma to version 1.2.0 🚀 (#3523) - update karma plugins
* chore(package): update karma to version 1.2.0

https://greenkeeper.io/

* update all karma packages

* update CHANGELOG
2016-08-11 18:03:19 -04:00
Gary Katsevman c15d64adf5 Merge branch 'stable' 2016-08-09 11:24:23 -04:00
Gary Katsevman a0e9318862 Merge branch 'stable' 2016-08-08 18:23:27 -04:00
Gary Katsevman 56fc3356dc Merge branch 'stable' 2016-08-08 15:29:30 -04:00
Gary Katsevman f947ed7791 @gkatsev added null checks around navigator.userAgent. closes #3502 2016-08-05 14:38:42 -04:00
Gary Katsevman 1ff9f381a2 @gkatsev modified ie8.css build process 2016-08-05 14:23:15 -04:00
Erik Yuzwa d86d4b2222 @erikyuzwa reworked build to separate out IE8-specific CSS 2016-08-05 14:17:51 -04:00
brandonocasey 052c2ce1a9 @BrandonOCasey removed unused base-styles.js file. closes #3486 2016-08-05 11:52:10 -04:00
Gary Katsevman 4f6cb03add Update CHANGELOG for linter changes. Closes #3459 2016-08-05 11:41:53 -04:00
Pat O'Neill 485524882e @misteroneill added ghooks to run linter on git push 2016-08-05 11:39:21 -04:00
Priti Agarwal 945711855a @pagarwal123 updated some test code to pass linter 2016-08-05 11:38:08 -04:00
Pat O'Neill 272d5eed83 @misteroneill updated source code for linter v5 2016-08-05 11:37:22 -04:00
Brandon Casey 86068a5b45 @BrandonOCasey updates tests to pass linter 2016-08-05 11:37:12 -04:00
Pat O'Neill e85c1c0391 @misteroneill updated source code to pass linter 2016-08-05 11:35:54 -04:00
Brandon Casey c89b75699e first half of the test/unit/tracks directory (#3483) 2016-08-03 15:27:47 -04:00
183 arquivos alterados com 47728 adições e 45559 exclusões
+4
Ver Arquivo
@@ -0,0 +1,4 @@
{
"presets": ["es2015-loose"],
"plugins": ["transform-es3-property-literals", "transform-es3-member-expression-literals", "inline-json"]
}
+1
Ver Arquivo
@@ -28,5 +28,6 @@ test/coverage/*
.sass-cache
dist/*
es5/*
.idea/
-47
Ver Arquivo
@@ -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
Ver Arquivo
@@ -1,4 +1,5 @@
# Exclude everything but the contents of the dist directory.
**/*
!dist/**
!es5/**
!src/css/**
+1 -1
Ver Arquivo
@@ -1,6 +1,6 @@
language: node_js
node_js:
- 0.12
- 4.4
before_install:
- export CHROME_BIN=chromium-browser
- export DISPLAY=:99.0
+52
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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.
+2
Ver Arquivo
@@ -3,6 +3,8 @@
# [Video.js - HTML5 Video Player](http://videojs.com)
[![Build Status](https://travis-ci.org/videojs/video.js.svg?branch=master)](https://travis-ci.org/videojs/video.js)
[![Coverage Status](https://coveralls.io/repos/github/videojs/video.js/badge.svg?branch=master)](https://coveralls.io/github/videojs/video.js?branch=master)
[![Slack Status](http://slack.videojs.com/badge.svg)](http://slack.videojs.com)
[![NPM](https://nodei.co/npm/video.js.png?downloads=true&downloadRank=true)](https://nodei.co/npm/video.js/)
+73 -58
Ver Arquivo
@@ -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 -1
Ver Arquivo
@@ -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');
+35
Ver Arquivo
@@ -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);
});
};
-24
Ver Arquivo
@@ -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
Ver Arquivo
@@ -1,7 +1,7 @@
{
"name": "video.js",
"description": "An HTML5 and Flash video player with a common API and skin for both.",
"version": "5.11.2",
"version": "5.12.2",
"keywords": [
"videojs",
"html5",
-7
Ver Arquivo
@@ -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; }
+1 -1
Ver Arquivo
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
+20416 -19897
Ver Arquivo
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
+10 -11
Ver Arquivo
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
+7 -1
Ver Arquivo
@@ -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"
});
+2
Ver Arquivo
@@ -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",
+16 -3
Ver Arquivo
@@ -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é"
});
BIN
Ver Arquivo
Arquivo binário não exibido.
BIN
Ver Arquivo
Arquivo binário não exibido.
+31 -7
Ver Arquivo
@@ -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; } }
+1 -1
Ver Arquivo
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
BIN
Ver Arquivo
Arquivo binário não exibido.
+20415 -19896
Ver Arquivo
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
-319
Ver Arquivo
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
+11 -11
Ver Arquivo
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
-1
Ver Arquivo
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
+6 -154
Ver Arquivo
@@ -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>
+363
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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"
}
+2
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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"
}
}
}
+1 -1
Ver Arquivo
@@ -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
-16
Ver Arquivo
@@ -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;
-2
Ver Arquivo
@@ -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
-2
Ver Arquivo
@@ -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 {
+1 -1
Ver Arquivo
@@ -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
+2 -1
Ver Arquivo
@@ -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;
}
+30
Ver Arquivo
@@ -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; } }
-18
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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);
+18 -11
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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;
}
}
+20 -19
Ver Arquivo
@@ -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'
});
}
}
+17 -3
Ver Arquivo
@@ -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');
}
}
+1 -1
Ver Arquivo
@@ -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'
});
+11 -9
Ver Arquivo
@@ -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}`);
+5 -3
Ver Arquivo
@@ -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,
+25 -16
Ver Arquivo
@@ -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}`;
+4 -3
Ver Arquivo
@@ -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 -6
Ver Arquivo
@@ -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');
+10 -9
Ver Arquivo
@@ -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);
+2 -3
Ver Arquivo
@@ -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) : '';
}
}
+10 -7
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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];
}
+3 -3
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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;
+17 -14
Ver Arquivo
@@ -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();
}
}
+5 -5
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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();
+9 -11
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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 -7
Ver Arquivo
@@ -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) {
+7 -4
Ver Arquivo
@@ -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();
});
+4 -3
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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]}&amp;`;
});
}
// 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
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+10 -10
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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